From aa8de2f038baec993f07ef66fb3e94481d1ec22b Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Fri, 8 Dec 2006 18:41:17 +0100 Subject: [PATCH] [PATCH] Generic HID layer - input and event reporting hid_input_report() was needlessly USB-specific in USB HID. This patch makes the function independent of HID implementation and fixes all the current users. Bluetooth patches comply with this prototype. Signed-off-by: Jiri Kosina Signed-off-by: Marcel Holtmann Cc: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-core.c | 59 +++++++++++++++++++++++++++++++ drivers/usb/input/hid-core.c | 67 ++++-------------------------------- drivers/usb/input/hiddev.c | 1 + include/linux/hid.h | 3 +- 4 files changed, 68 insertions(+), 62 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 1dd9e4f0df1e..18c2b3cf6bcc 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -940,5 +940,64 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) } EXPORT_SYMBOL_GPL(hid_set_field); +int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt) +{ + struct hid_report_enum *report_enum = hid->report_enum + type; + struct hid_report *report; + int n, rsize; + + if (!hid) + return -ENODEV; + + if (!size) { + dbg("empty report"); + return -1; + } + +#ifdef DEBUG_DATA + printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un"); +#endif + + n = 0; /* Normally report number is 0 */ + if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */ + n = *data++; + size--; + } + +#ifdef DEBUG_DATA + { + int i; + printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size); + for (i = 0; i < size; i++) + printk(" %02x", data[i]); + printk("\n"); + } +#endif + + if (!(report = report_enum->report_id_hash[n])) { + dbg("undefined report_id %d received", n); + return -1; + } + + rsize = ((report->size - 1) >> 3) + 1; + + if (size < rsize) { + dbg("report %d is too short, (%d < %d)", report->id, size, rsize); + return -1; + } + + if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) + hid->hiddev_report_event(hid, report); + + for (n = 0; n < report->maxfield; n++) + hid_input_field(hid, report->field[n], data, interrupt); + + if (hid->claimed & HID_CLAIMED_INPUT) + hidinput_report_event(hid, report); + + return 0; +} +EXPORT_SYMBOL_GPL(hid_input_report); + MODULE_LICENSE(DRIVER_LICENSE); diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 4fc828041d0f..a20ff61624b1 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -169,65 +169,6 @@ done: spin_unlock_irqrestore(&usbhid->inlock, flags); } - -static int hid_input_report(int type, struct urb *urb, int interrupt) -{ - struct hid_device *hid = urb->context; - struct hid_report_enum *report_enum = hid->report_enum + type; - u8 *data = urb->transfer_buffer; - int len = urb->actual_length; - struct hid_report *report; - int n, size; - - if (!len) { - dbg("empty report"); - return -1; - } - -#ifdef DEBUG_DATA - printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un"); -#endif - - n = 0; /* Normally report number is 0 */ - if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */ - n = *data++; - len--; - } - -#ifdef DEBUG_DATA - { - int i; - printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, len); - for (i = 0; i < len; i++) - printk(" %02x", data[i]); - printk("\n"); - } -#endif - - if (!(report = report_enum->report_id_hash[n])) { - dbg("undefined report_id %d received", n); - return -1; - } - - size = ((report->size - 1) >> 3) + 1; - - if (len < size) { - dbg("report %d is too short, (%d < %d)", report->id, len, size); - memset(data + len, 0, size - len); - } - - if (hid->claimed & HID_CLAIMED_HIDDEV) - hiddev_report_event(hid, report); - - for (n = 0; n < report->maxfield; n++) - hid_input_field(hid, report->field[n], data, interrupt); - - if (hid->claimed & HID_CLAIMED_INPUT) - hidinput_report_event(hid, report); - - return 0; -} - /* * Input interrupt completion handler. */ @@ -241,7 +182,9 @@ static void hid_irq_in(struct urb *urb) switch (urb->status) { case 0: /* success */ usbhid->retry_delay = 0; - hid_input_report(HID_INPUT_REPORT, urb, 1); + hid_input_report(urb->context, HID_INPUT_REPORT, + urb->transfer_buffer, + urb->actual_length, 1); break; case -EPIPE: /* stall */ clear_bit(HID_IN_RUNNING, &usbhid->iofl); @@ -426,7 +369,8 @@ static void hid_ctrl(struct urb *urb) switch (urb->status) { case 0: /* success */ if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN) - hid_input_report(usbhid->ctrl[usbhid->ctrltail].report->type, urb, 0); + hid_input_report(urb->context, usbhid->ctrl[usbhid->ctrltail].report->type, + urb->transfer_buffer, urb->actual_length, 0); break; case -ESHUTDOWN: /* unplug */ unplug = 1; @@ -1286,6 +1230,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) hid->hidinput_close = hidinput_close; #ifdef CONFIG_USB_HIDDEV hid->hiddev_hid_event = hiddev_hid_event; + hid->hiddev_report_event = hiddev_report_event; #endif return hid; diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index 0c2647eb9eec..114d6c9f64b1 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c @@ -214,6 +214,7 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report) hiddev_send_event(hid, &uref); } + /* * fasync file op */ diff --git a/include/linux/hid.h b/include/linux/hid.h index 5a969a137b85..342b4e639acb 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -436,7 +436,7 @@ struct hid_device { /* device report descriptor */ /* hiddev event handler */ void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field, struct hid_usage *, __s32); - + void (*hiddev_report_event) (struct hid_device *, struct hid_report *); #ifdef CONFIG_USB_HIDINPUT_POWERBOOK unsigned long pb_pressed_fn[NBITS(KEY_MAX)]; unsigned long pb_pressed_numlock[NBITS(KEY_MAX)]; @@ -492,6 +492,7 @@ extern int hidinput_connect(struct hid_device *); extern void hidinput_disconnect(struct hid_device *); int hid_set_field(struct hid_field *, unsigned, __s32); +int hid_input_report(struct hid_device *, int type, u8 *, int, int); int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field); void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt); void hid_output_report(struct hid_report *report, __u8 *data); -- 2.20.1