CINXE.COM
LKML: Dmitry Torokhov: [patch 27/28] Input: convert input handlers to class interfaces
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>LKML: Dmitry Torokhov: [patch 27/28] Input: convert input handlers to class interfaces</title><link href="/css/message.css" rel="stylesheet" type="text/css" /><link href="/css/wrap.css" rel="alternate stylesheet" type="text/css" title="wrap" /><link href="/css/nowrap.css" rel="stylesheet" type="text/css" title="nowrap" /><link href="/favicon.ico" rel="shortcut icon" /><script src="/js/simple-calendar.js" type="text/javascript"></script><script src="/js/styleswitcher.js" type="text/javascript"></script><link rel="alternate" type="application/rss+xml" title="lkml.org : last 100 messages" href="/rss.php" /><link rel="alternate" type="application/rss+xml" title="lkml.org : last messages by Dmitry Torokhov" href="/groupie.php?aid=10658" /><!--Matomo--><script> var _paq = window._paq = window._paq || []; /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ _paq.push(["setDoNotTrack", true]); _paq.push(["disableCookies"]); _paq.push(['trackPageView']); _paq.push(['enableLinkTracking']); (function() { var u="//m.lkml.org/"; _paq.push(['setTrackerUrl', u+'matomo.php']); _paq.push(['setSiteId', '1']); var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); })(); </script><!--End Matomo Code--></head><body onload="es.jasper.simpleCalendar.init();" itemscope="itemscope" itemtype="http://schema.org/BlogPosting"><table border="0" cellpadding="0" cellspacing="0"><tr><td width="180" align="center"><a href="/"><img style="border:0;width:135px;height:32px" src="/images/toprowlk.gif" alt="lkml.org" /></a></td><td width="32">聽</td><td class="nb"><div><a class="nb" href="/lkml"> [lkml]</a> 聽 <a class="nb" href="/lkml/2005"> [2005]</a> 聽 <a class="nb" href="/lkml/2005/9"> [Sep]</a> 聽 <a class="nb" href="/lkml/2005/9/15"> [15]</a> 聽 <a class="nb" href="/lkml/last100"> [last100]</a> 聽 <a href="/rss.php"><img src="/images/rss-or.gif" border="0" alt="RSS Feed" /></a></div><div>Views: <a href="#" class="nowrap" onclick="setActiveStyleSheet('wrap');return false;">[wrap]</a><a href="#" class="wrap" onclick="setActiveStyleSheet('nowrap');return false;">[no wrap]</a> 聽 <a class="nb" href="/lkml/mheaders/2005/9/15/55" onclick="this.href='/lkml/headers'+'/2005/9/15/55';">[headers]</a>聽 <a href="/lkml/bounce/2005/9/15/55">[forward]</a>聽 </div></td><td width="32">聽</td></tr><tr><td valign="top"><div class="es-jasper-simpleCalendar" baseurl="/lkml/"></div><div class="threadlist">Messages in this thread</div><ul class="threadlist"><li class="root"><a href="/lkml/2005/9/15/58">First message in thread</a></li><li><a href="/lkml/2005/9/15/58">Dmitry Torokhov</a><ul><li><a href="/lkml/2005/9/15/54">Dmitry Torokhov</a></li><li class="origin"><a href="">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/56">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/57">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/59">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/60">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/61">Dmitry Torokhov</a><ul><li><a href="/lkml/2005/9/27/26">Greg KH</a><ul><li><a href="/lkml/2005/9/27/45">Markus Lidel</a></li></ul></li></ul></li><li><a href="/lkml/2005/9/15/63">Dmitry Torokhov</a><ul><li><a href="/lkml/2005/9/15/101">Marcel Holtmann</a><ul><li><a href="/lkml/2005/9/15/200">Dmitry Torokhov</a><ul><li><a href="/lkml/2005/9/15/206">Marcel Holtmann</a></li></ul></li></ul></li></ul></li><li><a href="/lkml/2005/9/15/64">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/65">Dmitry Torokhov</a><ul><li><a href="/lkml/2005/9/27/29">Greg KH</a></li></ul></li><li><a href="/lkml/2005/9/15/66">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/67">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/68">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/70">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/71">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/72">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/89">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/90">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/91">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/92">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/93">Dmitry Torokhov</a><ul><li><a href="/lkml/2005/10/5/315">Greg KH</a><ul><li><a href="/lkml/2005/10/5/317">Dmitry Torokhov</a><ul><li><a href="/lkml/2005/10/5/330">Greg KH</a></li></ul></li></ul></li></ul></li><li><a href="/lkml/2005/9/15/94">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/95">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/96">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/104">Marcel Holtmann</a><ul><li><a href="/lkml/2005/9/15/201">Dmitry Torokhov</a></li></ul></li><li><a href="/lkml/2005/9/15/106">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/107">Dmitry Torokhov</a></li><li><a href="/lkml/2005/9/15/388">Andrew Morton</a><ul><li><a href="/lkml/2005/9/15/389">Dmitry Torokhov</a><ul><li><a href="/lkml/2005/9/16/2">Andrew Morton</a><ul><li><a href="/lkml/2005/9/16/3">Dmitry Torokhov</a></li></ul></li></ul></li></ul></li></ul></li></ul><div class="threadlist">Patch in this message</div><ul class="threadlist"><li><a href="/lkml/diff/2005/9/15/55/1">Get diff 1</a></li></ul></td><td width="32" rowspan="2" class="c" valign="top"><img src="/images/icornerl.gif" width="32" height="32" alt="/" /></td><td class="c" rowspan="2" valign="top" style="padding-top: 1em"><table><tr><td><table><tr><td class="lp">Date</td><td class="rp" itemprop="datePublished">Thu, 15 Sep 2005 02:01:58 -0500</td></tr><tr><td class="lp">From</td><td class="rp" itemprop="author">Dmitry Torokhov <></td></tr><tr><td class="lp">Subject</td><td class="rp" itemprop="name">[patch 27/28] Input: convert input handlers to class interfaces</td></tr></table></td><td></td></tr></table><pre itemprop="articleBody">Input: convert input handlers to class interfaces<br /><br />Thit is exactly why class interfaces were created - to provide<br />several different 'views' for the same hardware.<br /><br />Signed-off-by: Dmitry Torokhov <dtor@mail.ru><br />---<br /><br /> drivers/input/input.c | 455 +++++++++++++++++++++++++-------------------------<br /> include/linux/input.h | 8 <br /> 2 files changed, 232 insertions(+), 231 deletions(-)<br /><br />Index: work/drivers/input/input.c<br />===================================================================<br />--- work.orig/drivers/input/input.c<br />+++ work/drivers/input/input.c<br />@@ -49,9 +49,6 @@ static struct class input_class = {<br /> .name = "input",<br /> };<br /> <br />-static LIST_HEAD(input_dev_list);<br />-static LIST_HEAD(input_handler_list);<br />-<br /> static struct input_handler *input_table[8];<br /> <br /> void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)<br />@@ -271,12 +268,6 @@ void input_close_device(struct input_han<br /> up(&dev->sem);<br /> }<br /> <br />-static void input_link_handle(struct input_handle *handle)<br />-{<br />- list_add_tail(&handle->d_node, &handle->dev->h_list);<br />- list_add_tail(&handle->h_node, &handle->handler->h_list);<br />-}<br />-<br /> #define MATCH_BIT(bit, max) \<br /> for (i = 0; i < NBITS(max); i++) \<br /> if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \<br />@@ -337,182 +328,6 @@ static int input_print_bitmap(char *buf,<br /> return len;<br /> }<br /> <br />-#ifdef CONFIG_PROC_FS<br />-<br />-static struct proc_dir_entry *proc_bus_input_dir;<br />-static DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);<br />-static int input_devices_state;<br />-<br />-static inline void input_wakeup_procfs_readers(void)<br />-{<br />- input_devices_state++;<br />- wake_up(&input_devices_poll_wait);<br />-}<br />-<br />-static unsigned int input_devices_poll(struct file *file, poll_table *wait)<br />-{<br />- int state = input_devices_state;<br />- poll_wait(file, &input_devices_poll_wait, wait);<br />- if (state != input_devices_state)<br />- return POLLIN | POLLRDNORM;<br />- return 0;<br />-}<br />-<br />-#define SPRINTF_BIT(ev, bm) \<br />- do { \<br />- len += sprintf(buf + len, "B: %s=", #ev); \<br />- len += input_print_bitmap(buf + len, INT_MAX, \<br />- dev->bm##bit, ev##_MAX); \<br />- len += sprintf(buf + len, "\n"); \<br />- } while (0)<br />-<br />-#define TEST_AND_SPRINTF_BIT(ev, bm) \<br />- do { \<br />- if (test_bit(EV_##ev, dev->evbit)) \<br />- SPRINTF_BIT(ev, bm); \<br />- } while (0)<br />-<br />-static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)<br />-{<br />- struct input_dev *dev;<br />- struct input_handle *handle;<br />- const char *path;<br />-<br />- off_t at = 0;<br />- int len, cnt = 0;<br />-<br />- list_for_each_entry(dev, &input_dev_list, node) {<br />-<br />- path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);<br />-<br />- len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",<br />- dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);<br />-<br />- len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");<br />- len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");<br />- len += sprintf(buf + len, "S: Sysfs=%s\n", path ? path : "");<br />- len += sprintf(buf + len, "H: Handlers=");<br />-<br />- list_for_each_entry(handle, &dev->h_list, d_node)<br />- len += sprintf(buf + len, "%s ", handle->name);<br />-<br />- len += sprintf(buf + len, "\n");<br />-<br />- SPRINTF_BIT(EV, ev);<br />- TEST_AND_SPRINTF_BIT(KEY, key);<br />- TEST_AND_SPRINTF_BIT(REL, rel);<br />- TEST_AND_SPRINTF_BIT(ABS, abs);<br />- TEST_AND_SPRINTF_BIT(MSC, msc);<br />- TEST_AND_SPRINTF_BIT(LED, led);<br />- TEST_AND_SPRINTF_BIT(SND, snd);<br />- TEST_AND_SPRINTF_BIT(FF, ff);<br />- TEST_AND_SPRINTF_BIT(SW, sw);<br />-<br />- len += sprintf(buf + len, "\n");<br />-<br />- at += len;<br />-<br />- if (at >= pos) {<br />- if (!*start) {<br />- *start = buf + (pos - (at - len));<br />- cnt = at - pos;<br />- } else cnt += len;<br />- buf += len;<br />- if (cnt >= count)<br />- break;<br />- }<br />-<br />- kfree(path);<br />- }<br />-<br />- if (&dev->node == &input_dev_list)<br />- *eof = 1;<br />-<br />- return (count > cnt) ? cnt : count;<br />-}<br />-<br />-static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)<br />-{<br />- struct input_handler *handler;<br />-<br />- off_t at = 0;<br />- int len = 0, cnt = 0;<br />- int i = 0;<br />-<br />- list_for_each_entry(handler, &input_handler_list, node) {<br />-<br />- if (handler->fops)<br />- len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n",<br />- i++, handler->name, handler->minor);<br />- else<br />- len = sprintf(buf, "N: Number=%d Name=%s\n",<br />- i++, handler->name);<br />-<br />- at += len;<br />-<br />- if (at >= pos) {<br />- if (!*start) {<br />- *start = buf + (pos - (at - len));<br />- cnt = at - pos;<br />- } else cnt += len;<br />- buf += len;<br />- if (cnt >= count)<br />- break;<br />- }<br />- }<br />- if (&handler->node == &input_handler_list)<br />- *eof = 1;<br />-<br />- return (count > cnt) ? cnt : count;<br />-}<br />-<br />-static struct file_operations input_fileops;<br />-<br />-static int __init input_proc_init(void)<br />-{<br />- struct proc_dir_entry *entry;<br />-<br />- proc_bus_input_dir = proc_mkdir("input", proc_bus);<br />- if (!proc_bus_input_dir)<br />- return -ENOMEM;<br />-<br />- proc_bus_input_dir->owner = THIS_MODULE;<br />-<br />- entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL);<br />- if (!entry)<br />- goto fail1;<br />-<br />- entry->owner = THIS_MODULE;<br />- input_fileops = *entry->proc_fops;<br />- entry->proc_fops = &input_fileops;<br />- entry->proc_fops->poll = input_devices_poll;<br />-<br />- entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);<br />- if (!entry)<br />- goto fail2;<br />-<br />- entry->owner = THIS_MODULE;<br />-<br />- return 0;<br />-<br />- fail2: remove_proc_entry("devices", proc_bus_input_dir);<br />- fail1: remove_proc_entry("input", proc_bus);<br />- return -ENOMEM;<br />-}<br />-<br />-static void input_proc_exit(void)<br />-{<br />- remove_proc_entry("devices", proc_bus_input_dir);<br />- remove_proc_entry("handlers", proc_bus_input_dir);<br />- remove_proc_entry("input", proc_bus);<br />-}<br />-<br />-#else /* !CONFIG_PROC_FS */<br />-static inline void input_wakeup_procfs_readers(void) { }<br />-static inline int input_proc_init(void) { return 0; }<br />-static inline void input_proc_exit(void) { }<br />-#endif<br />-<br /> #define INPUT_DEV_STRING_ATTR_SHOW(name) \<br /> static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \<br /> { \<br />@@ -710,6 +525,188 @@ static struct class input_dev_class = {<br /> .class_dev_attrs = input_dev_attrs,<br /> };<br /> <br />+#ifdef CONFIG_PROC_FS<br />+<br />+static struct proc_dir_entry *proc_bus_input_dir;<br />+static DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);<br />+static int input_devices_state;<br />+<br />+static inline void input_wakeup_procfs_readers(void)<br />+{<br />+ input_devices_state++;<br />+ wake_up(&input_devices_poll_wait);<br />+}<br />+<br />+static unsigned int input_devices_poll(struct file *file, poll_table *wait)<br />+{<br />+ int state = input_devices_state;<br />+ poll_wait(file, &input_devices_poll_wait, wait);<br />+ if (state != input_devices_state)<br />+ return POLLIN | POLLRDNORM;<br />+ return 0;<br />+}<br />+<br />+#define SPRINTF_BIT(ev, bm) \<br />+ do { \<br />+ len += sprintf(buf + len, "B: %s=", #ev); \<br />+ len += input_print_bitmap(buf + len, INT_MAX, \<br />+ dev->bm##bit, ev##_MAX); \<br />+ len += sprintf(buf + len, "\n"); \<br />+ } while (0)<br />+<br />+#define TEST_AND_SPRINTF_BIT(ev, bm) \<br />+ do { \<br />+ if (test_bit(EV_##ev, dev->evbit)) \<br />+ SPRINTF_BIT(ev, bm); \<br />+ } while (0)<br />+<br />+static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)<br />+{<br />+ struct list_head *node;<br />+ struct input_dev *dev;<br />+ struct input_handle *handle;<br />+ const char *path;<br />+<br />+ off_t at = 0;<br />+ int len, cnt = 0;<br />+<br />+ list_for_each(node, &input_dev_class.children) {<br />+<br />+ dev = to_input_dev(container_of(node, struct class_device, node));<br />+ path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);<br />+<br />+ len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",<br />+ dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);<br />+<br />+ len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");<br />+ len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");<br />+ len += sprintf(buf + len, "S: Sysfs=%s\n", path ? path : "");<br />+ len += sprintf(buf + len, "H: Handlers=");<br />+<br />+ list_for_each_entry(handle, &dev->h_list, d_node)<br />+ len += sprintf(buf + len, "%s ", handle->name);<br />+<br />+ len += sprintf(buf + len, "\n");<br />+<br />+ SPRINTF_BIT(EV, ev);<br />+ TEST_AND_SPRINTF_BIT(KEY, key);<br />+ TEST_AND_SPRINTF_BIT(REL, rel);<br />+ TEST_AND_SPRINTF_BIT(ABS, abs);<br />+ TEST_AND_SPRINTF_BIT(MSC, msc);<br />+ TEST_AND_SPRINTF_BIT(LED, led);<br />+ TEST_AND_SPRINTF_BIT(SND, snd);<br />+ TEST_AND_SPRINTF_BIT(FF, ff);<br />+ TEST_AND_SPRINTF_BIT(SW, sw);<br />+<br />+ len += sprintf(buf + len, "\n");<br />+<br />+ at += len;<br />+<br />+ if (at >= pos) {<br />+ if (!*start) {<br />+ *start = buf + (pos - (at - len));<br />+ cnt = at - pos;<br />+ } else cnt += len;<br />+ buf += len;<br />+ if (cnt >= count)<br />+ break;<br />+ }<br />+<br />+ kfree(path);<br />+ }<br />+<br />+ if (node == &input_dev_class.children)<br />+ *eof = 1;<br />+<br />+ return (count > cnt) ? cnt : count;<br />+}<br />+<br />+static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)<br />+{<br />+ struct list_head *node;<br />+ struct input_handler *handler;<br />+<br />+ off_t at = 0;<br />+ int len = 0, cnt = 0;<br />+ int i = 0;<br />+<br />+ list_for_each(node, &input_dev_class.interfaces) {<br />+<br />+ handler = to_input_handler(container_of(node, struct class_interface, node));<br />+<br />+ if (handler->fops)<br />+ len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n",<br />+ i++, handler->name, handler->minor);<br />+ else<br />+ len = sprintf(buf, "N: Number=%d Name=%s\n",<br />+ i++, handler->name);<br />+<br />+ at += len;<br />+<br />+ if (at >= pos) {<br />+ if (!*start) {<br />+ *start = buf + (pos - (at - len));<br />+ cnt = at - pos;<br />+ } else cnt += len;<br />+ buf += len;<br />+ if (cnt >= count)<br />+ break;<br />+ }<br />+ }<br />+<br />+ if (node == &input_dev_class.interfaces)<br />+ *eof = 1;<br />+<br />+ return (count > cnt) ? cnt : count;<br />+}<br />+<br />+static struct file_operations input_fileops;<br />+<br />+static int __init input_proc_init(void)<br />+{<br />+ struct proc_dir_entry *entry;<br />+<br />+ proc_bus_input_dir = proc_mkdir("input", proc_bus);<br />+ if (!proc_bus_input_dir)<br />+ return -ENOMEM;<br />+<br />+ proc_bus_input_dir->owner = THIS_MODULE;<br />+<br />+ entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL);<br />+ if (!entry)<br />+ goto fail1;<br />+<br />+ entry->owner = THIS_MODULE;<br />+ input_fileops = *entry->proc_fops;<br />+ entry->proc_fops = &input_fileops;<br />+ entry->proc_fops->poll = input_devices_poll;<br />+<br />+ entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);<br />+ if (!entry)<br />+ goto fail2;<br />+<br />+ entry->owner = THIS_MODULE;<br />+<br />+ return 0;<br />+<br />+ fail2: remove_proc_entry("devices", proc_bus_input_dir);<br />+ fail1: remove_proc_entry("input", proc_bus);<br />+ return -ENOMEM;<br />+}<br />+<br />+static void input_proc_exit(void)<br />+{<br />+ remove_proc_entry("devices", proc_bus_input_dir);<br />+ remove_proc_entry("handlers", proc_bus_input_dir);<br />+ remove_proc_entry("input", proc_bus);<br />+}<br />+<br />+#else /* !CONFIG_PROC_FS */<br />+static inline void input_wakeup_procfs_readers(void) { }<br />+static inline int input_proc_init(void) { return 0; }<br />+static inline void input_proc_exit(void) { }<br />+#endif<br />+<br /> struct input_dev *input_allocate_device(void)<br /> {<br /> struct input_dev *dev;<br />@@ -718,7 +715,6 @@ struct input_dev *input_allocate_device(<br /> if (dev) {<br /> dev->dynalloc = 1;<br /> INIT_LIST_HEAD(&dev->h_list);<br />- INIT_LIST_HEAD(&dev->node);<br /> }<br /> <br /> return dev;<br />@@ -727,9 +723,6 @@ struct input_dev *input_allocate_device(<br /> int input_register_device(struct input_dev *dev)<br /> {<br /> static atomic_t input_no = ATOMIC_INIT(0);<br />- struct input_handle *handle;<br />- struct input_handler *handler;<br />- struct input_device_id *id;<br /> const char *path;<br /> int error;<br /> <br />@@ -757,13 +750,6 @@ int input_register_device(struct input_d<br /> }<br /> <br /> INIT_LIST_HEAD(&dev->h_list);<br />- list_add_tail(&dev->node, &input_dev_list);<br />-<br />- list_for_each_entry(handler, &input_handler_list, node)<br />- if (!handler->blacklist || !input_match_device(handler->blacklist, dev))<br />- if ((id = input_match_device(handler->id_table, dev)))<br />- if ((handle = handler->connect(handler, dev, id)))<br />- input_link_handle(handle);<br /> <br /> dev->cdev.class = &input_dev_class;<br /> snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),<br />@@ -799,19 +785,8 @@ int input_register_device(struct input_d<br /> <br /> void input_unregister_device(struct input_dev *dev)<br /> {<br />- struct list_head * node, * next;<br />-<br /> del_timer_sync(&dev->timer);<br /> <br />- list_for_each_safe(node, next, &dev->h_list) {<br />- struct input_handle * handle = to_handle(node);<br />- list_del_init(&handle->d_node);<br />- list_del_init(&handle->h_node);<br />- handle->handler->disconnect(handle);<br />- }<br />-<br />- list_del_init(&dev->node);<br />-<br /> sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group);<br /> sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);<br /> class_device_unregister(&dev->cdev);<br />@@ -819,46 +794,72 @@ void input_unregister_device(struct inpu<br /> input_wakeup_procfs_readers();<br /> }<br /> <br />-void input_register_handler(struct input_handler *handler)<br />+static int input_handler_add_device(struct class_device *cdev, struct class_interface *intf)<br /> {<br />- struct input_dev *dev;<br />+ struct input_dev *dev = to_input_dev(cdev);<br />+ struct input_handler *handler = to_input_handler(intf);<br /> struct input_handle *handle;<br /> struct input_device_id *id;<br /> <br />- if (!handler) return;<br />+ if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) {<br />+ id = input_match_device(handler->id_table, dev);<br />+ if (id) {<br />+ handle = handler->connect(handler, dev, id);<br />+ if (handle) {<br />+ list_add_tail(&handle->d_node, &dev->h_list);<br />+ list_add_tail(&handle->h_node, &handler->h_list);<br />+ return 0;<br />+ }<br />+ }<br />+ }<br />+<br />+ return -ENODEV;<br />+}<br />+<br />+static void input_handler_remove_device(struct class_device *cdev, struct class_interface *intf)<br />+{<br />+ struct input_dev *dev = to_input_dev(cdev);<br />+ struct input_handler *handler = to_input_handler(intf);<br />+ struct input_handle *handle, *next;<br />+<br />+ list_for_each_entry_safe(handle, next, &dev->h_list, d_node) {<br />+ if (handle->handler == handler) {<br />+ list_del_init(&handle->h_node);<br />+ list_del_init(&handle->d_node);<br />+ handler->disconnect(handle);<br />+ }<br />+ }<br />+}<br />+<br />+int input_register_handler(struct input_handler *handler)<br />+{<br />+ int error;<br /> <br /> INIT_LIST_HEAD(&handler->h_list);<br /> <br /> if (handler->fops != NULL)<br /> input_table[handler->minor >> 5] = handler;<br /> <br />- list_add_tail(&handler->node, &input_handler_list);<br />+ handler->intf.class = &input_dev_class;<br />+ handler->intf.add = input_handler_add_device;<br />+ handler->intf.remove = input_handler_remove_device;<br /> <br />- list_for_each_entry(dev, &input_dev_list, node)<br />- if (!handler->blacklist || !input_match_device(handler->blacklist, dev))<br />- if ((id = input_match_device(handler->id_table, dev)))<br />- if ((handle = handler->connect(handler, dev, id)))<br />- input_link_handle(handle);<br />+ error = class_interface_register(&handler->intf);<br />+ if (error)<br />+ return error;<br /> <br /> input_wakeup_procfs_readers();<br />+<br />+ return 0;<br /> }<br /> <br /> void input_unregister_handler(struct input_handler *handler)<br /> {<br />- struct list_head * node, * next;<br />-<br />- list_for_each_safe(node, next, &handler->h_list) {<br />- struct input_handle * handle = to_handle_h(node);<br />- list_del_init(&handle->h_node);<br />- list_del_init(&handle->d_node);<br />- handler->disconnect(handle);<br />- }<br />-<br />- list_del_init(&handler->node);<br />-<br /> if (handler->fops != NULL)<br /> input_table[handler->minor >> 5] = NULL;<br /> <br />+ class_interface_unregister(&handler->intf);<br />+<br /> input_wakeup_procfs_readers();<br /> }<br /> <br />Index: work/include/linux/input.h<br />===================================================================<br />--- work.orig/include/linux/input.h<br />+++ work/include/linux/input.h<br />@@ -895,7 +895,6 @@ struct input_dev {<br /> int dynalloc; /* temporarily */<br /> <br /> struct list_head h_list;<br />- struct list_head node;<br /> };<br /> #define to_input_dev(d) container_of(d, struct input_dev, cdev)<br /> <br />@@ -960,8 +959,10 @@ struct input_handler {<br /> struct input_device_id *blacklist;<br /> <br /> struct list_head h_list;<br />- struct list_head node;<br />+<br />+ struct class_interface intf;<br /> };<br />+#define to_input_handler(h) container_of(h, struct input_handler, intf)<br /> <br /> struct input_handle {<br /> <br />@@ -986,7 +987,6 @@ struct input_handle {<br /> static inline void init_input_dev(struct input_dev *dev)<br /> {<br /> INIT_LIST_HEAD(&dev->h_list);<br />- INIT_LIST_HEAD(&dev->node);<br /> }<br /> <br /> struct input_dev *input_allocate_device(void);<br />@@ -1009,7 +1009,7 @@ static inline void input_put_device(stru<br /> int input_register_device(struct input_dev *);<br /> void input_unregister_device(struct input_dev *);<br /> <br />-void input_register_handler(struct input_handler *);<br />+int input_register_handler(struct input_handler *);<br /> void input_unregister_handler(struct input_handler *);<br /> <br /> int input_create_interface_device(struct input_handle *, dev_t);<br />-<br />To unsubscribe from this list: send the line "unsubscribe linux-kernel" in<br />the body of a message to majordomo@vger.kernel.org<br />More majordomo info at <a href="http://vger.kernel.org/majordomo-info.html">http://vger.kernel.org/majordomo-info.html</a><br />Please read the FAQ at <a href="http://www.tux.org/lkml/">http://www.tux.org/lkml/</a><br /><br /></pre></td><td width="32" rowspan="2" class="c" valign="top"><img src="/images/icornerr.gif" width="32" height="32" alt="\" /></td></tr><tr><td align="right" valign="bottom"> 聽 </td></tr><tr><td align="right" valign="bottom">聽</td><td class="c" valign="bottom" style="padding-bottom: 0px"><img src="/images/bcornerl.gif" width="32" height="32" alt="\" /></td><td class="c">聽</td><td class="c" valign="bottom" style="padding-bottom: 0px"><img src="/images/bcornerr.gif" width="32" height="32" alt="/" /></td></tr><tr><td align="right" valign="top" colspan="2"> 聽 </td><td class="lm">Last update: 2005-09-15 09:07 聽聽 [from the cache]<br />漏2003-2020 <a href="http://blog.jasper.es/"><span itemprop="editor">Jasper Spaans</span></a>|hosted at <a href="https://www.digitalocean.com/?refcode=9a8e99d24cf9">Digital Ocean</a> and my Meterkast|<a href="http://blog.jasper.es/categories.html#lkml-ref">Read the blog</a></td><td>聽</td></tr></table><script language="javascript" src="/js/styleswitcher.js" type="text/javascript"></script></body></html>