[PATCH] Generic HID layer - input and event reporting
Jiri Kosina [Fri, 8 Dec 2006 17:41:17 +0000 (18:41 +0100)]
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 <jkosina@suse.cz>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

drivers/hid/hid-core.c
drivers/usb/input/hid-core.c
drivers/usb/input/hiddev.c
include/linux/hid.h

index 1dd9e4f..18c2b3c 100644 (file)
@@ -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);
 
index 4fc8280..a20ff61 100644 (file)
@@ -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;
index 0c2647e..114d6c9 100644 (file)
@@ -214,6 +214,7 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report)
 
        hiddev_send_event(hid, &uref);
 }
+
 /*
  * fasync file op
  */
index 5a969a1..342b4e6 100644 (file)
@@ -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);