usb: The HID Simple Driver Interface 0.3.1 (core)
PATCH 1/1 usb: The HID Simple Driver Interface 0.3.1 (core)
Chanelogs: (upto 20060814)
1. add force-feedback driver support.
2. add simple driver module refcnt support.
3. add two CONFIG_HID_SIMPLE and CONFIG_HID_SIMPLE_FF Kconfig entries.
4. refactoring.
5. replace two semaphones with mutex.
6. some bugfixes.
It also can apply on 2.6.17.6 and 2.6.17.8 at least.
PS: I have not Subscribe linux-usb-devel maillist, please CC me your reply, thanks.
drivers/usb/input/hid-core.c renamed from drivers/usb/input.orig/hid-core.c +227 -7
@@ -26,6 +26,7 @@#include <asm/byteorder.h> #include <linux/input.h> #include <linux/wait.h> +#include <linux/mutex.h> #undef DEBUG#undef DEBUG_DATA
@@ -33,6 +34,9 @@#include <linux/usb.h> #include "hid.h" +#ifdef CONFIG_HID_SIMPLE +#include "hid-simple.h" +#endif #include <linux/hiddev.h> /*
@@ -46,6 +50,17 @@static char *hid_types[] = {"Device" ,"Pointer" ,"Mouse" ,"Device" ,"Joystick" ,"Gamepad" ,"Keyboard" ,"Keypad" ,"Multi-Axis Controller" }; + +#ifdef CONFIG_HID_SIMPLE +/* +* The global data structure for simple device driver interface. +*/ +static DEFINE_MUTEX (matched_lock); +static DEFINE_MUTEX (simple_lock); +static struct list_head matched_devices_list; +static struct list_head simple_drivers_list; +#endif +/* * Module parameters. */
@@ -785,8 +800,22 @@ static __inline__ int search(__s32 *arrastatic void hid_process_event (struct hid_device *hid,struct hid_field *field,struct hid_usage *usage,__s32 value,int interrupt,struct pt_regs *regs) {hid_dump_input (usage, value); -if (hid->claimed &HID_CLAIMED_INPUT ) +if (hid->claimed &HID_CLAIMED_INPUT ) { +#ifdef CONFIG_HID_SIMPLE +/* event filter here */ +if (hid->simple) { +if (hid->simple->pre_event && + !hid->simple->pre_event (hid, field, usage, + value, regs)) +return ; + } +#endif hidinput_hid_event (hid, field, usage, value, regs); +#ifdef CONFIG_HID_SIMPLE +if (hid->simple && hid->simple->post_event) + hid->simple->post_event (hid, field, usage, value, regs); +#endif + }if (hid->claimed &HID_CLAIMED_HIDDEV && interrupt)hiddev_hid_event (hid, field, usage, value, regs); }
@@ -832,7 +861,6 @@ static void hid_input_field(struct hid_d && field->usage[field->value[n] - min].hid && search(value, field->value[n], count))hid_process_event (hid, field, &field->usage[field->value[n] - min],0 , interrupt, regs); -if (value[n] >= min && value[n] <= max && field->usage[value[n] - min].hid &&search (field->value, value[n], count))
@@ -1977,7 +2005,11 @@ fail:static void hid_disconnect (struct usb_interface *intf) {struct hid_device *hid =usb_get_intfdata (intf); - +#ifdef CONFIG_HID_SIMPLE +struct list_head *node; +struct matched_device *matched; +#endif +if (!hid)return ;
@@ -1991,8 +2023,32 @@ static void hid_disconnect(struct usb_indel_timer_sync (&hid->io_retry);flush_scheduled_work (); -if (hid->claimed &HID_CLAIMED_INPUT ) +if (hid->claimed &HID_CLAIMED_INPUT ) { +#ifdef CONFIG_HID_SIMPLE + matched =NULL ; +mutex_lock (&matched_lock); +list_for_each (node, &matched_devices_list) { + matched = list_entry(node, struct matched_device, node); +if (matched->intf == intf) { +list_del (&matched->node); +break ; + } + matched =NULL ; + } +mutex_unlock (&matched_lock); +/* disconnect simple device driver if need */ +if (matched && hid->simple) { +hidinput_simple_driver_disconnect (hid); +module_put (hid->simple->owner); +hidinput_simple_driver_pop (hid, matched); + } +if (matched) { + matched->intf =NULL ; +kfree (matched); + } +#endif hidinput_disconnect (hid); + }if (hid->claimed &HID_CLAIMED_HIDDEV )hiddev_disconnect (hid);
@@ -2005,12 +2061,150 @@ static void hid_disconnect(struct usb_inhid_free_device (hid); } +#ifdef CONFIG_HID_SIMPLE +static int hidinput_simple_driver_bind_one (struct hidinput_simple_driver *simple, +struct hid_device *hid, +struct matched_device *matched) +{ +int ret; + +if (!try_module_get (simple->owner)) +return -ENODEV ; + ret =hidinput_simple_driver_connect (simple, hid); +if (ret) + goto exit_err; + ret =hidinput_simple_driver_push (hid, simple, matched); +if (ret) + goto exit_err; +hidinput_simple_driver_setup_usage (hid); +printk (KERN_INFO "The simple HID driver \'%s\' attach on\'%s\'\n" , + simple->name, hid->name); + goto exit; +exit_err: +module_put (simple->owner); +exit: +return ret; +} + +static void hidinput_simple_driver_bind_foreach (void ) +{ +struct hidinput_simple_driver *simple; +struct matched_device *matched=NULL ; +struct list_head *matched_node =NULL ; +struct list_head *simple_node =NULL ; +struct hid_device *hid=NULL ; + +mutex_lock (&matched_lock); +list_for_each (matched_node, &matched_devices_list) { + matched = list_entry(matched_node, struct matched_device, node); + hid =usb_get_intfdata (matched->intf); +if (hid->simple) +continue ; +mutex_lock (&simple_lock); +list_for_each (simple_node, &simple_drivers_list) { + simple = list_entry(simple_node, struct hidinput_simple_driver, node); + +if (test_bit (HIDINPUT_SIMPLE_CONNECTED , &simple->flags)) +continue ; +if (!usb_match_id (matched->intf, simple->id_table)) +continue ; +hidinput_simple_driver_bind_one (simple, hid, matched); + } +mutex_unlock (&simple_lock); + } +mutex_unlock (&matched_lock); +} + +static void hidinput_simple_driver_bind_foreach_simple ( +struct matched_device *matched) +{ +struct hidinput_simple_driver *simple; +struct list_head *node; +struct hid_device *hid; + +if (!matched->intf) +return ; + hid =usb_get_intfdata (matched->intf); +if (!hid || hid->simple) +return ; + +mutex_lock (&simple_lock); +list_for_each (node, &simple_drivers_list) { + simple = list_entry(node, struct hidinput_simple_driver, node); +if (test_bit (HIDINPUT_SIMPLE_CONNECTED , &simple->flags)) +continue ; +if (usb_match_id (matched->intf, simple->id_table)) { +hidinput_simple_driver_bind_one (simple, hid, matched); +break ; + } + } +mutex_unlock (&simple_lock); +} + +static void hidinput_simple_driver_bind_foreach_matched ( +struct hidinput_simple_driver *simple) +{ +struct list_head *node=NULL ; +struct matched_device *matched; +struct hid_device *hid=NULL ; + +if (!simple ||test_bit (HIDINPUT_SIMPLE_CONNECTED , &simple->flags)) +return ; + +mutex_lock (&matched_lock); +list_for_each (node, &matched_devices_list) { + matched = list_entry(node, struct matched_device, node); + hid =usb_get_intfdata (matched->intf); +if (hid->simple) +continue ; +if (!usb_match_id (matched->intf, simple->id_table)) +continue ; +hidinput_simple_driver_bind_one (simple, hid, matched); + } +mutex_unlock (&matched_lock); +} + +int hidinput_register_simple_driver (struct hidinput_simple_driver *simple) +{ +if (!simple || !simple->name) +return -EINVAL ; + +printk (KERN_INFO "The simple HID driver \'%s\' register.\n" , + simple->name); +hidinput_simple_driver_init (simple); +hidinput_simple_driver_bind_foreach_matched (simple); + +mutex_lock (&simple_lock); +list_add (&simple->node, &simple_drivers_list); +mutex_unlock (&simple_lock); + +return 0 ; +} +EXPORT_SYMBOL_GPL (hidinput_register_simple_driver); + +void hidinput_unregister_simple_driver (struct hidinput_simple_driver *simple) +{ +printk (KERN_INFO "The simple HID driver \'%s\' unregister.\n" , + simple->name); +hidinput_simple_driver_clear (simple); +mutex_lock (&simple_lock); +list_del (&simple->node); +mutex_unlock (&simple_lock); +/* to active simple device driver that it is waiting */ +hidinput_simple_driver_bind_foreach (); +} +EXPORT_SYMBOL_GPL (hidinput_unregister_simple_driver); +#endif +static int hid_probe (struct usb_interface *intf,const struct usb_device_id *id) {struct hid_device *hid;char path[64 ];int i;char *c; +#ifdef CONFIG_HID_SIMPLE +struct matched_device *matched; +#endif dbg ("HID probe called for ifnum %d" , intf->altsetting->desc.bInterfaceNumber);
@@ -2021,13 +2215,24 @@ static int hid_probe(struct usb_interfachid_init_reports (hid);hid_dump_device (hid); -if (!hidinput_connect (hid)) +usb_set_intfdata (intf, hid); + +if (!hidinput_connect (hid)) { +#ifdef CONFIG_HID_SIMPLE + matched =kmalloc (sizeof (struct matched_device ),GFP_KERNEL ); +if (matched) { + matched->intf = intf; +mutex_lock (&matched_lock); +list_add (&matched->node, &matched_devices_list); +mutex_unlock (&matched_lock); +hidinput_simple_driver_bind_foreach_simple (matched); + } +#endif hid->claimed |=HID_CLAIMED_INPUT ; + }if (!hiddev_connect (hid)) hid->claimed |=HID_CLAIMED_HIDDEV ; -usb_set_intfdata (intf, hid); -if (!hid->claimed) {printk ("HID device not claimed by input or hiddev\n" );hid_disconnect (intf);
@@ -2108,6 +2313,10 @@ static int __init hid_init(void) retval =hiddev_init ();if (retval) goto hiddev_init_fail; +#ifdef CONFIG_HID_SIMPLE +INIT_LIST_HEAD (&matched_devices_list); +INIT_LIST_HEAD (&simple_drivers_list); +#endif retval =usb_register (&hid_driver);if (retval) goto usb_register_fail;
@@ -2122,7 +2331,18 @@ hiddev_init_fail: static void __exit hid_exit(void) { +#ifdef CONFIG_HID_SIMPLE +struct list_head *node, *tmp; +struct matched_device *matched; +#endif usb_deregister (&hid_driver); +#ifdef CONFIG_HID_SIMPLE +list_for_each_safe (node, tmp, &matched_devices_list) { + matched = list_entry(node, struct matched_device, node); +list_del (&matched->node); +kfree (matched); + } +#endif hiddev_exit (); }
drivers/usb/input/hid.h renamed from drivers/usb/input.orig/hid.h +9 -0
@@ -380,8 +380,13 @@ struct hid_input {struct list_head list;struct hid_report *report;struct input_dev *input; +void *private; }; +#ifdef CONFIG_HID_SIMPLE +struct hidinput_simple_driver ; +#endif +struct hid_device {/* device report descriptor */ __u8 *rdesc;unsigned rsize;
@@ -445,6 +450,10 @@ struct hid_device { /* device repoint (*ff_event)(struct hid_device *hid,struct input_dev *input,unsigned int type,unsigned int code,int value); +#ifdef CONFIG_HID_SIMPLE +struct hidinput_simple_driver *simple; +#endif +#ifdef CONFIG_USB_HIDINPUT_POWERBOOK unsigned long pb_pressed_fn[NBITS (KEY_MAX )];unsigned long pb_pressed_numlock[NBITS (KEY_MAX )];
drivers/usb/input/hid-input.c renamed from drivers/usb/input.orig/hid-input.c +354 -3
403 lines not on this page · raw message
drivers/usb/input/hid-simple.h renamed from drivers/usb/input.orig/hid-simple.h +162 -0
162 lines not on this page · raw message
drivers/usb/input/hid-core.c line 39
Quoted 9 lines · liyu
drivers/usb/input/hid-core.c renamed from drivers/usb/input.orig/hid-core.c +3
-0@@ -33,6 +34,9 @@#include <linux/usb.h> #include "hid.h" +#ifdef CONFIG_HID_SIMPLE +#include "hid-simple.h" +#endif
Headers on that level are supposed without ifdefs.
drivers/usb/input/hid-core.c line 59
Quoted 11 lines
drivers/usb/input/hid-core.c renamed from drivers/usb/input.orig/hid-core.c +7
-0@@ -46,6 +50,17 @@static char *hid_types[] = {"Device" ,"Pointer" ,"Mouse" ,"Device" ,"Joystick" ,"Gamepad" ,"Keyboard" ,"Keypad" ,"Multi-Axis Controller" }; + +#ifdef CONFIG_HID_SIMPLE +/* +* The global data structure for simple device driver interface. +*/ +static DEFINE_MUTEX (matched_lock); +static DEFINE_MUTEX (simple_lock);
Way too generic name[s].
Quoted 187 lines
drivers/usb/input/hid-core.c renamed from drivers/usb/input.orig/hid-core.c +146
-4+static struct list_head matched_devices_list; +static struct list_head simple_drivers_list; +#endif +/* * Module parameters. */ @@ -785,8 +800,22 @@ static __inline__ int search(__s32 *arrastatic void hid_process_event (struct hid_device *hid,struct hid_field *field,struct hid_usage *usage,__s32 value,int interrupt,struct pt_regs *regs) {hid_dump_input (usage, value); -if (hid->claimed &HID_CLAIMED_INPUT ) +if (hid->claimed &HID_CLAIMED_INPUT ) { +#ifdef CONFIG_HID_SIMPLE +/* event filter here */ +if (hid->simple) { +if (hid->simple->pre_event && + !hid->simple->pre_event (hid, field, usage, + value, regs)) +return ; + } +#endif hidinput_hid_event (hid, field, usage, value, regs); +#ifdef CONFIG_HID_SIMPLE +if (hid->simple && hid->simple->post_event) + hid->simple->post_event (hid, field, usage, value, regs); +#endif + }if (hid->claimed &HID_CLAIMED_HIDDEV && interrupt)hiddev_hid_event (hid, field, usage, value, regs); }@@ -832,7 +861,6 @@ static void hid_input_field(struct hid_d && field->usage[field->value[n] - min].hid && search(value, field->value[n], count))hid_process_event (hid, field, &field->usage[field->value[n] - min],0 , interrupt, regs); -if (value[n] >= min && value[n] <= max && field->usage[value[n] - min].hid &&search (field->value, value[n], count))@@ -1977,7 +2005,11 @@ fail:static void hid_disconnect (struct usb_interface *intf) {struct hid_device *hid =usb_get_intfdata (intf); - +#ifdef CONFIG_HID_SIMPLE +struct list_head *node; +struct matched_device *matched; +#endif +if (!hid)return ;@@ -1991,8 +2023,32 @@ static void hid_disconnect(struct usb_indel_timer_sync (&hid->io_retry);flush_scheduled_work (); -if (hid->claimed &HID_CLAIMED_INPUT ) +if (hid->claimed &HID_CLAIMED_INPUT ) { +#ifdef CONFIG_HID_SIMPLE + matched =NULL ; +mutex_lock (&matched_lock); +list_for_each (node, &matched_devices_list) { + matched = list_entry(node, struct matched_device, node); +if (matched->intf == intf) { +list_del (&matched->node); +break ; + } + matched =NULL ; + } +mutex_unlock (&matched_lock); +/* disconnect simple device driver if need */ +if (matched && hid->simple) { +hidinput_simple_driver_disconnect (hid); +module_put (hid->simple->owner); +hidinput_simple_driver_pop (hid, matched); + } +if (matched) { + matched->intf =NULL ; +kfree (matched); + } +#endif hidinput_disconnect (hid); + }if (hid->claimed &HID_CLAIMED_HIDDEV )hiddev_disconnect (hid);@@ -2005,12 +2061,150 @@ static void hid_disconnect(struct usb_inhid_free_device (hid); } +#ifdef CONFIG_HID_SIMPLE +static int hidinput_simple_driver_bind_one (struct hidinput_simple_driver *simple, +struct hid_device *hid, +struct matched_device *matched) +{ +int ret; + +if (!try_module_get (simple->owner)) +return -ENODEV ; + ret =hidinput_simple_driver_connect (simple, hid); +if (ret) + goto exit_err; + ret =hidinput_simple_driver_push (hid, simple, matched); +if (ret) + goto exit_err; +hidinput_simple_driver_setup_usage (hid); +printk (KERN_INFO "The simple HID driver \'%s\' attach on\'%s\'\n" , + simple->name, hid->name); + goto exit; +exit_err: +module_put (simple->owner); +exit: +return ret; +} + +static void hidinput_simple_driver_bind_foreach (void ) +{ +struct hidinput_simple_driver *simple; +struct matched_device *matched=NULL ; +struct list_head *matched_node =NULL ; +struct list_head *simple_node =NULL ; +struct hid_device *hid=NULL ; + +mutex_lock (&matched_lock); +list_for_each (matched_node, &matched_devices_list) { + matched = list_entry(matched_node, struct matched_device, node); + hid =usb_get_intfdata (matched->intf); +if (hid->simple) +continue ; +mutex_lock (&simple_lock); +list_for_each (simple_node, &simple_drivers_list) { + simple = list_entry(simple_node, struct hidinput_simple_driver, node); + +if (test_bit (HIDINPUT_SIMPLE_CONNECTED , &simple->flags)) +continue ; +if (!usb_match_id (matched->intf, simple->id_table)) +continue ; +hidinput_simple_driver_bind_one (simple, hid, matched); + } +mutex_unlock (&simple_lock); + } +mutex_unlock (&matched_lock); +} + +static void hidinput_simple_driver_bind_foreach_simple ( +struct matched_device *matched) +{ +struct hidinput_simple_driver *simple; +struct list_head *node; +struct hid_device *hid; + +if (!matched->intf) +return ; + hid =usb_get_intfdata (matched->intf); +if (!hid || hid->simple) +return ; + +mutex_lock (&simple_lock); +list_for_each (node, &simple_drivers_list) { + simple = list_entry(node, struct hidinput_simple_driver, node); +if (test_bit (HIDINPUT_SIMPLE_CONNECTED , &simple->flags)) +continue ; +if (usb_match_id (matched->intf, simple->id_table)) { +hidinput_simple_driver_bind_one (simple, hid, matched); +break ; + } + } +mutex_unlock (&simple_lock); +} + +static void hidinput_simple_driver_bind_foreach_matched ( +struct hidinput_simple_driver *simple) +{ +struct list_head *node=NULL ; +struct matched_device *matched; +struct hid_device *hid=NULL ; + +if (!simple ||test_bit (HIDINPUT_SIMPLE_CONNECTED , &simple->flags)) +return ; + +mutex_lock (&matched_lock); +list_for_each (node, &matched_devices_list) { + matched = list_entry(node, struct matched_device, node); + hid =usb_get_intfdata (matched->intf); +if (hid->simple) +continue ; +if (!usb_match_id (matched->intf, simple->id_table))
drivers/usb/input/hid-core.c static void hid_disconnect(struct usb_in · line 2170
Quoted 10 lines
drivers/usb/input/hid-core.c renamed from drivers/usb/input.orig/hid-core.c +10
-0+continue ; +hidinput_simple_driver_bind_one (simple, hid, matched); + } +mutex_unlock (&matched_lock); +} + +int hidinput_register_simple_driver (struct hidinput_simple_driver *simple) +{ +if (!simple || !simple->name) +return -EINVAL ;
If someone registers nil drivers, he deserves oops.
Quoted 27 lines
drivers/usb/input/hid-core.c renamed from drivers/usb/input.orig/hid-core.c +27
-0+ +printk (KERN_INFO "The simple HID driver \'%s\' register.\n" , + simple->name); +hidinput_simple_driver_init (simple); +hidinput_simple_driver_bind_foreach_matched (simple); + +mutex_lock (&simple_lock); +list_add (&simple->node, &simple_drivers_list); +mutex_unlock (&simple_lock); + + return 0; +} +EXPORT_SYMBOL_GPL (hidinput_register_simple_driver); + +void hidinput_unregister_simple_driver (struct hidinput_simple_driver *simple) +{ +printk (KERN_INFO "The simple HID driver \'%s\' unregister.\n" , + simple->name); +hidinput_simple_driver_clear (simple); +mutex_lock (&simple_lock); +list_del (&simple->node); +mutex_unlock (&simple_lock); +/* to active simple device driver that it is waiting */ +hidinput_simple_driver_bind_foreach (); +} +EXPORT_SYMBOL_GPL (hidinput_unregister_simple_driver); +#endif
drivers/usb/input/hid-core.c static void hid_disconnect(struct usb_in · line 2207
Quoted 10 lines
drivers/usb/input/hid-core.c renamed from drivers/usb/input.orig/hid-core.c +4
-0+static int hid_probe (struct usb_interface *intf,const struct usb_device_id *id) {struct hid_device *hid;char path[64 ];int i;char *c; +#ifdef CONFIG_HID_SIMPLE +struct matched_device *matched; +#endif
Save #ifdef by moving var -+
|
drivers/usb/input/hid-core.c s|atic int hid_probe(struct usb_interfac · line 2221
Quoted 11 lines
drivers/usb/input/hid-core.c renamed from drivers/usb/input.orig/hid-core.c +4
-1dbg ("HID probe call|d for ifnum %d" , int|->altsetting->desc.bInterfaceNumber);@@ -2021,13 +2215,24 @@ s|atic int hid_probe(struct usb_interfac hid_init_reports(hi|); hid_dump_device(hid|; | - if (!hidinput_conne|t(hid)) + usb_set_intfdata(in|f, hid); + | + if (!hidinput_conne|t(hid)) { +#ifdef CONFIG_HID_SIMPLE|
here <--+
Quoted 53 lines
drivers/usb/input/hid-core.c renamed from drivers/usb/input.orig/hid-core.c +25
-2+ matched =kmalloc (sizeof (struct matched_device ),GFP_KERNEL ); +if (matched) { + matched->intf = intf; +mutex_lock (&matched_lock); +list_add (&matched->node, &matched_devices_list); +mutex_unlock (&matched_lock); +hidinput_simple_driver_bind_foreach_simple (matched); + } +#endif hid->claimed |=HID_CLAIMED_INPUT ; + }if (!hiddev_connect (hid)) hid->claimed |=HID_CLAIMED_HIDDEV ; -usb_set_intfdata (intf, hid); -if (!hid->claimed) {printk ("HID device not claimed by input or hiddev\n" );hid_disconnect (intf);@@ -2108,6 +2313,10 @@ static int __init hid_init(void) retval =hiddev_init ();if (retval) goto hiddev_init_fail; +#ifdef CONFIG_HID_SIMPLE +INIT_LIST_HEAD (&matched_devices_list); +INIT_LIST_HEAD (&simple_drivers_list); +#endif retval =usb_register (&hid_driver);if (retval) goto usb_register_fail;@@ -2122,7 +2331,18 @@ hiddev_init_fail: static void __exit hid_exit(void) { +#ifdef CONFIG_HID_SIMPLE +struct list_head *node, *tmp; +struct matched_device *matched; +#endif usb_deregister (&hid_driver); +#ifdef CONFIG_HID_SIMPLE +list_for_each_safe (node, tmp, &matched_devices_list) { + matched = list_entry(node, struct matched_device, node); +list_del (&matched->node); +kfree (matched); + } +#endif hiddev_exit (); }diff -Naurp
linux-2.6.17.7/drivers/usb/input.orig/hid.hlinux-2.6.17.7/drivers/usb/input/hid.h
drivers/usb/input/hid.h struct hid_input { · line 388
Quoted 9 lines
drivers/usb/input/hid.h renamed from drivers/usb/input.orig/hid.h +4
-0@@ -380,8 +380,13 @@ struct hid_input {struct list_head list;struct hid_report *report;struct input_dev *input; +void *private; }; +#ifdef CONFIG_HID_SIMPLE +struct hidinput_simple_driver ; +#endif
Totally unneeded ifdef.
Quoted 582 lines
drivers/usb/input/hid.h renamed from drivers/usb/input.orig/hid.h +4
-0struct hid_device {/* device report descriptor */ __u8 *rdesc;unsigned rsize;@@ -445,6 +450,10 @@ struct hid_device { /* device repoint (*ff_event)(struct hid_device *hid,struct input_dev *input,unsigned int type,unsigned int code,int value); +#ifdef CONFIG_HID_SIMPLE +struct hidinput_simple_driver *simple; +#endif +#ifdef CONFIG_USB_HIDINPUT_POWERBOOK unsigned long pb_pressed_fn[NBITS (KEY_MAX )];unsigned long pb_pressed_numlock[NBITS (KEY_MAX )];diff -Naurp
linux-2.6.17.7/drivers/usb/input.orig/hid-input.clinux-2.6.17.7/drivers/usb/input/hid-input.cdrivers/usb/input/hid-input.c renamed from drivers/usb/input.orig/hid-input.c +354
-3@@ -36,7 +36,9 @@#undef DEBUG#include "hid.h" - +#ifdef CONFIG_HID_SIMPLE +#include "hid-simple.h" +#endif #define unk KEY_UNKNOWNstatic const unsigned char hid_keyboard[256 ] = {@@ -63,6 +65,8 @@ static const struct {__s32 y; } hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; +typedef void (*do_usage_t )(struct hid_field *,struct hid_usage *); +#define map_abs (c) do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; } while (0)#define map_rel (c) do { usage->code = c; usage->type = EV_REL; bit = input->relbit; max = REL_MAX; } while (0)#define map_key (c) do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; } while (0)@@ -736,8 +740,16 @@ static int hidinput_input_event(struct istruct hid_field *field;int offset; -if (type ==EV_FF ) +if (type ==EV_FF ) { +#ifdef CONFIG_HID_SIMPLE_FF +if (hid->simple && hid->simple->ff_event) { +if (!hid->simple->ff_event (dev, type, code, value)); +return 0 ; + } +#else return hid_ff_event (hid, dev, type, code, value); +#endif + }if (type !=EV_LED )return -1 ;@@ -756,15 +768,63 @@ static int hidinput_input_event(struct istatic int hidinput_open (struct input_dev *dev) {struct hid_device *hid = dev->private; +#ifdef CONFIG_HID_SIMPLE_FF +int ret =0 ; + +if (hid->simple && hid->simple->open) + ret = hid->simple->open (dev); +if (!ret) +return hid_open (hid); +else +return ret; +#else return hid_open (hid); +#endif }static void hidinput_close (struct input_dev *dev) {struct hid_device *hid = dev->private; + +#ifdef CONFIG_HID_SIMPLE_FF +if (hid->simple && hid->simple->close) + hid->simple->close (dev); +#endif hid_close (hid); } +#ifdef CONFIG_HID_SIMPLE_FF +static int hidinput_upload_effect (struct input_dev *dev,struct ff_effect *effect) +{ +struct hid_device *hid; + + hid = dev->private; +if (hid->simple && hid->simple->upload_effect) +return hid->simple->upload_effect (dev, effect); +return 0 ; +} + +static int hidinput_erase_effect (struct input_dev *dev,int effect_id) +{ +struct hid_device *hid; + + hid = dev->private; +if (hid->simple && hid->simple->erase_effect) +return hid->simple->erase_effect (dev, effect_id); +return 0 ; +} + +static int hidinput_flush (struct input_dev *dev,struct file *filep) +{ +struct hid_device *hid; + + hid = dev->private; +if (hid->simple && hid->simple->flush) +return hid->simple->flush (dev, filep); +return 0 ; +} +#endif +/* * Register the input device; print a message. * Configure the input layer interface @@ -810,7 +870,11 @@ int hidinput_connect(struct hid_device * input_dev->event = hidinput_input_event; input_dev->open = hidinput_open; input_dev->close = hidinput_close; - +#ifdef CONFIG_HID_SIMPLE_FF + input_dev->upload_effect = hidinput_upload_effect; + input_dev->erase_effect = hidinput_erase_effect; + input_dev->flush = hidinput_flush; +#endif input_dev->name = hid->name; input_dev->phys = hid->phys; input_dev->uniq = hid->uniq;@@ -849,6 +913,293 @@ int hidinput_connect(struct hid_device *return 0 ; } +#ifdef CONFIG_HID_SIMPLE +int hidinput_simple_driver_init (struct hidinput_simple_driver *drv) +{ +if (unlikely (!drv)) +return -EINVAL ; +INIT_LIST_HEAD (&drv->node); +INIT_LIST_HEAD (&drv->raw_devices); + drv->flags =0 ; +return 0 ; +} + +#define SET_BIT (1) +#define CLR_BIT (0) +static void inline hidinput_simple_configure_one_usage (int op, +struct input_dev *input, +struct hid_usage *usage, +struct usage_block *usage_block) +{ +unsigned long *bits; +int flag; +struct hid_device *hid; + + hid = input->private; +switch (usage_block->event) { +case EV_KEY : + flag =HIDINPUT_SIMPLE_KEYBIT ; + bits = input->keybit; +break ; +case EV_REL : + flag =HIDINPUT_SIMPLE_RELBIT ; + bits = input->relbit; +break ; +case EV_ABS : + flag =HIDINPUT_SIMPLE_ABSBIT ; + bits = input->relbit; +break ; +case EV_MSC : + flag =HIDINPUT_SIMPLE_MSCBIT ; + bits = input->absbit; +break ; +case EV_SW : + flag =HIDINPUT_SIMPLE_SWBIT ; + bits = input->swbit; +break ; +case EV_LED : + flag =HIDINPUT_SIMPLE_LEDBIT ; + bits = input->ledbit; +break ; +case EV_SND : + flag =HIDINPUT_SIMPLE_SNDBIT ; + bits = input->sndbit; +break ; +#ifdef CONFIG_HID_SIMPLE_FF +case EV_FF : + flag =HIDINPUT_SIMPLE_FFBIT ; + bits = input->ffbit; +break ; +case EV_FF_STATUS : + flag =HIDINPUT_SIMPLE_FFSTSBIT ; + bits =NULL ; +break ; +#endif +default : +return ; + } + +if (SET_BIT == op) { + usage->code = usage_block->code; + usage->type = usage_block->event; +if (bits) +set_bit (usage_block->code, bits); +if (!test_and_set_bit (usage_block->event, input->evbit)) +set_bit (flag, &hid->simple->flags); + } +else if (CLR_BIT == op) { + usage->code =0 ; + usage->type =0 ; +if (bits) +clear_bit (usage_block->code, bits); +if (test_and_clear_bit (flag, &hid->simple->flags)) +clear_bit (usage_block->event, input->evbit); + } +} + +static do_usage_t hidinput_simple_driver_configure_usage_prep ( +struct hid_device *hid, +int *op) +{ +do_usage_t do_usage; + +if (!hid->simple) +return NULL ; + +if (test_bit (HIDINPUT_SIMPLE_SETUP_USAGE , &hid->simple->flags)) { + do_usage = hid->simple->setup_usage; + *op =SET_BIT ; + } +else { + do_usage = hid->simple->clear_usage; + *op =CLR_BIT ; + } +return do_usage; +} + +static void __hidinput_simple_driver_configure_usage (int op, +struct hid_field *field, +struct hid_usage *hid_usage) +{ +struct input_dev *input = field->hidinput->input; +struct hid_device *hid = input->private; +struct usage_block *usage_block; +struct usage_page_block *page_block; +int page; +int usage; + + page = (hid_usage->hid &HID_USAGE_PAGE ); + usage = (hid_usage->hid &HID_USAGE ); + page_block = hid->simple->usage_page_table; +for (;page_block && page_block->usage_blockes;page_block++) { +if (page_block->page != page) +continue ; + usage_block = page_block->usage_blockes; +for (; usage_block && usage_block->usage; usage_block++) { +if (usage_block->usage != usage) +continue ; +hidinput_simple_configure_one_usage (op, input, + hid_usage, usage_block); + } + } +} + +/* +* To give one simple device a configure usage chance. +* The framework of this function come from hidinput_connect() +*/ +void hidinput_simple_driver_configure_usage (struct hid_device *hid) +{ +struct hid_report *report; +int i, j, k; +do_usage_t do_usage; +int op; + +if (!hid->simple) +return ; + + do_usage =hidinput_simple_driver_configure_usage_prep (hid, &op); + +for (i =0 ; i < hid->maxcollection; i++) +if (hid->collection[i].type ==HID_COLLECTION_APPLICATION || + hid->collection[i].type==HID_COLLECTION_PHYSICAL ) +if (IS_INPUT_APPLICATION (hid->collection[i].usage)) +break ; + +if (i == hid->maxcollection) +return ; + +for (k =HID_INPUT_REPORT ; k <=HID_OUTPUT_REPORT ; k++) +list_for_each_entry (report, &hid->report_enum[k].report_list, list) { +if (!report->maxfield) +continue ; + +for (i =0 ; i < report->maxfield; i++) +for (j =0 ; j < report->field[i]->maxusage; j++) { +__hidinput_simple_driver_configure_usage (op, report->field[i], report->field[i]->usage + j); +if (do_usage) +do_usage (report->field[i], + report->field[i]->usage + j); + } + } + +return ; +} +#undef SET_BIT +#undef CLR_BIT + +int hidinput_simple_driver_push (struct hid_device *hid, +struct hidinput_simple_driver *simple, +struct matched_device *matched) +{ +struct raw_simple_device *raw_simple; + + raw_simple =kmalloc (sizeof (struct raw_simple_device ),GFP_KERNEL ); +if (!raw_simple) +return -ENOMEM ; + raw_simple->intf = matched->intf; + hid =usb_get_intfdata (matched->intf); + hid->simple = simple; +list_add (&raw_simple->node, &simple->raw_devices); +return 0 ; +} + +void hidinput_simple_driver_pop (struct hid_device *hid, +struct matched_device *matched) +{ +struct list_head *node; +struct raw_simple_device *raw_simple=NULL ; + + list_for_each (node, &hid->simple->raw_devices) { + raw_simple = list_entry(node, struct raw_simple_device, node); +if (raw_simple && raw_simple->intf == matched->intf) { + hid->simple =NULL ; +list_del (&raw_simple->node); +kfree (raw_simple); +return ; + } + } +} + +void hidinput_simple_driver_clear (struct hidinput_simple_driver *simple) +{ +struct raw_simple_device *raw_simple; +struct hid_device *hid; + +while (!list_empty_careful (&simple->raw_devices)) { + raw_simple =list_entry (simple->raw_devices.next, + struct raw_simple_device, node); + hid =usb_get_intfdata (raw_simple->intf); +if (hid) { +if (hid->simple) { +BUG_ON (hid->simple != simple); + hid->simple =NULL ; + } +hidinput_simple_driver_clear_usage (hid); +hidinput_simple_driver_disconnect (hid); + } +list_del_init (simple->raw_devices.next); + } +} + +int hidinput_simple_driver_connect (struct hidinput_simple_driver *simple, +struct hid_device *hid) +{ +struct hid_input *hidinput, *next; +int ret = -ENODEV ; + +if (!simple) + goto exit; +if (!simple->connect) { + ret =0 ; + goto exit; + } + +list_for_each_entry_safe (hidinput, next, &hid->inputs, list) { +if (!simple->connect (hid, hidinput)) { + hid->simple = simple; + ret =0 ; + } + } +exit: +set_bit (HIDINPUT_SIMPLE_CONNECTED , &simple->flags); +return ret; +} + + +void hidinput_simple_driver_disconnect (struct hid_device *hid) +{ +struct hid_input *hidinput, *next; + +if (!hid || !hid->simple) +return ; + +if (!hid->simple->disconnect) + goto exit; +list_for_each_entry_safe (hidinput, next, &hid->inputs, list) { + hid->simple->disconnect (hid, hidinput); + } +exit: +clear_bit (HIDINPUT_SIMPLE_CONNECTED , &hid->simple->flags); +return ; +} + +struct hid_input *hidinput_simple_inputdev_to_hidinput (struct input_dev *dev) +{ +struct hid_device *hid = dev->private; +struct list_head *iter; +struct hid_input *hidinput; + +list_for_each (iter, &hid->inputs) { + hidinput = list_entry(iter, struct hid_input, list); +if (hidinput->input == dev) +return hidinput; + } +return NULL ; +} +EXPORT_SYMBOL_GPL (hidinput_simple_inputdev_to_hidinput); +#endif +void hidinput_disconnect (struct hid_device *hid) {struct hid_input *hidinput, *next;diff -Naurp
linux-2.6.17.7/drivers/usb/input.orig/hid-simple.hlinux-2.6.17.7/drivers/usb/input/hid-simple.hdrivers/usb/input/hid-simple.h renamed from drivers/usb/input.orig/hid-simple.h +152
-0@@ -0,0 +1,162 @@ +#ifdef CONFIG_HID_SIMPLE +/* + * NOTE: + * For use me , you must include hid.h in your source first. + */ +#ifndef __HID_SIMPLE_H +#define __HID_SIMPLE_H + +#ifdef __KERNEL__ + +#include <linux/usb.h> + +/***** The public interface for simple device driver *****/ +struct usage_block { + int usage; /* usage code */ + int value; /* not used, for F_EVENT_BY_VALUE in future */ + int event; /* input event type, e.g. EV_KEY. */ + int code; /* input subsystem code, e.g. KEY_F1. */ + int flags; /* not used */ +}; + +struct usage_page_block { + int page; /* usage page code */ + int flags; /* not used */ + struct usage_block *usage_blockes; +}; + +/* usage_block flags list */ +#define F_EVENT_BY_VALUE (0x1) /* submit input event by usage_block.value, + not implement yet */ + +#define USAGE_BLOCK(i_usage, i_value, i_event, i_code, i_flags) \ + {\ + .usage = (i_usage),\ + .value = (i_value),\ + .event = (i_event),\ + .code = (i_code),\ + .flags = (i_flags),\ + } + +#define USAGE_BLOCK_NULL {} + +#define USAGE_PAGE_BLOCK(i_page, i_usage_blockes) \ + {\ + .page = (i_page),\ + .usage_blockes = (i_usage_blockes),\ + } + +#define USAGE_PAGE_BLOCK_NULL {} + +#define __SIMPLE_DRIVER_INIT \ + .owner = THIS_MODULE, + +struct hidinput_simple_driver { +/* private */ + struct module *owner; + struct list_head node; /* link with simple_drivers_list */ + struct list_head raw_devices; + unsigned long flags; +/* public */ + char *name; + int (*connect)(struct hid_device *, struct hid_input *); + void (*disconnect)(struct hid_device *, struct hid_input *); + void (*setup_usage)(struct hid_field *, struct hid_usage *); + void (*clear_usage)(struct hid_field *, struct hid_usage *); + int (*pre_event)(const struct hid_device *, const struct hid_field *, + const struct hid_usage *, const __s32, + const struct pt_regs *regs); + int (*post_event)(const struct hid_device *, const struct hid_field *, + const struct hid_usage *, const __s32, + const struct pt_regs *regs); +#ifdef CONFIG_HID_SIMPLE_FF + int (*open)(struct input_dev *dev); + void (*close)(struct input_dev *dev); + int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect); + int (*erase_effect)(struct input_dev *dev, int effect_id); + int (*flush)(struct input_dev *dev, struct file *file); + int (*ff_event)(struct input_dev *dev, int type, int code, int value); +#endif + struct usb_device_id *id_table; + struct usage_page_block *usage_page_table; + void *private; +}; + + +int hidinput_register_simple_driver(struct hidinput_simple_driver *device); +void hidinput_unregister_simple_driver(struct hidinput_simple_driver *device); +struct hid_input* hidinput_simple_inputdev_to_hidinput(struct input_dev *dev); + +/********************* The public section end ***********/ + +/***** The private section for simple device driver implement only *****/ + +/* + * matched_device record one device which hid-subsystem handle, it may + * be one simple device can not handle. + * + * The element of matched_device list is inserted at hidinput_connect(), + * and is removed at hidinput_disconnect(). + */ +struct matched_device { + struct usb_interface *intf; + struct list_head node; +}; + +/* + * raw_simple_driver record one device which hid simple device handle. + * It used as one member of hid_simple_driver. + */ + +struct raw_simple_device { + struct usb_interface *intf; + struct list_head node; +}; + +void hidinput_simple_driver_configure_usage(struct hid_device *hid); +int hidinput_simple_driver_init(struct hidinput_simple_driver *simple); +int hidinput_simple_driver_push(struct hid_device *hid, + struct hidinput_simple_driver *simple, + struct matched_device *dev); +void hidinput_simple_driver_pop(struct hid_device *hid, + struct matched_device *dev); +void hidinput_simple_driver_clear(struct hidinput_simple_driver *simple); +int hidinput_simple_driver_connect(struct hidinput_simple_driver *simple, + struct hid_device *hid); +void hidinput_simple_driver_disconnect(struct hid_device *hid); + +/* simple driver internal flags */ +#define HIDINPUT_SIMPLE_SETUP_USAGE (0x0) +#define HIDINPUT_SIMPLE_KEYBIT (0x1) +#define HIDINPUT_SIMPLE_RELBIT (0x2) +#define HIDINPUT_SIMPLE_ABSBIT (0x3) +#define HIDINPUT_SIMPLE_MSCBIT (0x4) +#define HIDINPUT_SIMPLE_SWBIT (0x5) +#define HIDINPUT_SIMPLE_LEDBIT (0x6) +#define HIDINPUT_SIMPLE_SNDBIT (0x7) +#ifdef CONFIG_HID_SIMPLE_FF +#define HIDINPUT_SIMPLE_FFBIT (0x8) +#define HIDINPUT_SIMPLE_FFSTSBIT (0x9) +#endif +#define HIDINPUT_SIMPLE_CONNECTED (0x1f) + +static void inline hidinput_simple_driver_setup_usage(struct hid_device *hid) +{ + if (hid && hid->simple) { + set_bit(HIDINPUT_SIMPLE_SETUP_USAGE, &hid->simple->flags); + hidinput_simple_driver_configure_usage(hid); + } +} + +static void inline hidinput_simple_driver_clear_usage(struct hid_device *hid) +{
drivers/usb/input/hid-simple.h line 162
Quoted 10 lines
drivers/usb/input/hid-simple.h renamed from drivers/usb/input.orig/hid-simple.h +10
-0+if (hid && hid->simple) { +clear_bit (HIDINPUT_SIMPLE_SETUP_USAGE , &hid->simple->flags); +hidinput_simple_driver_configure_usage (hid); + } +} + +/***** The private section end. *****/ +#endif /* __KERNEL__ */ +#endif /* __HID_SIMPLE_H */ +#endif /* CONFIG_HID_SIMPLE */
I'll repeat that word again, this code looks uncleanly because of many ifdefs scattered around.
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 2 lines · liyu
Well, Where I can get some guide for how use #ifdef/#if ?
Documentation/CodingStyle.
Basically, don't use it in .c files, but only in .h files if necessary.
Quoted 9 lines
Also, I found I can not send mail to <[email protected]> now, the reject reply like this:
Connected to 209.132.176.167 but sender was rejected.
Remote host said: 553 5.7.1 Hello [210.76.114.181], for your MAIL FROM address <[email protected]> policy analysis reported: Your address is not liked source for emailIs it looked my mail as spam mail? Who should I send to for help me resolving this problem?
Go here:
http://vger.kernel.org/mxverify.html
to see how to fix this up.
good luck,
greg k-h
Quoted 5 lines · Greg KH
Go here:
http://vger.kernel.org/mxverify.html
to see how to fix this up.
That test site reply me "Apparently OK!", however, I still can not send/receive any mail from LKML.
Also, I will review CodingStyle. Sorry for uncleanly code.
Quoted 7 lines · On Wednesday 16 August 2006 05:14, [email protected] wrote:
Quoted 5 lines · Greg KH
Go here:
http://vger.kernel.org/mxverify.html
to see how to fix this up.
Quoted 5 lines
That test site reply me "Apparently OK!", however, I still can not send/receive any mail from LKML.
Also, I will review CodingStyle. Sorry for uncleanly code.
Hi,
Just an overall comment. I like the idea of simple plugins for HID but we somehow need to allow them be built as modules and loaded on demand so when I plug a device that needs special handling an appropriate piece will get loaded and attached to the HID driver before my device is bound to it. Built-ins are not very nice when you look from a distribution POV becuase they have to enable every option and there are qute a few of devices that need special handling.
Signature · 1 line
Dmitry