[PATCH] Generic HID layer - API
Jiri Kosina [Fri, 8 Dec 2006 17:40:53 +0000 (18:40 +0100)]
- fixed generic API (added neccessary EXPORT_SYMBOL, fixed hid.h to provide correct
  prototypes)
- extended hid_device with open/close/event function pointers to driver-specific
  functions
- added driver specific driver_data to hid_device

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/hid/hid-input.c
drivers/usb/input/hid-core.c
drivers/usb/input/hid-ff.c
drivers/usb/input/hiddev.c
include/linux/hid.h

index 689ae16..8474a79 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  USB HID support for Linux
+ *  HID support for Linux
  *
  *  Copyright (c) 1999 Andreas Gal
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
@@ -31,8 +31,6 @@
 #undef DEBUG
 #undef DEBUG_DATA
 
-#include <linux/usb.h>
-
 #include <linux/hid.h>
 #include <linux/hiddev.h>
 
@@ -538,7 +536,7 @@ static void hid_free_report(struct hid_report *report)
  * Free a device structure, all reports, and all fields.
  */
 
-static void hid_free_device(struct hid_device *device)
+void hid_free_device(struct hid_device *device)
 {
        unsigned i,j;
 
@@ -555,6 +553,7 @@ static void hid_free_device(struct hid_device *device)
        kfree(device->rdesc);
        kfree(device);
 }
+EXPORT_SYMBOL_GPL(hid_free_device);
 
 /*
  * Fetch a report description item from the data stream. We support long
@@ -629,7 +628,7 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
  * enumerated, fields are attached to these reports.
  */
 
-static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
+struct hid_device *hid_parse_report(__u8 *start, unsigned size)
 {
        struct hid_device *device;
        struct hid_parser *parser;
@@ -719,6 +718,7 @@ static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
        kfree(parser);
        return NULL;
 }
+EXPORT_SYMBOL_GPL(hid_parse_report);
 
 /*
  * Convert a signed n-bit integer to signed 32-bit integer. Common
@@ -767,10 +767,10 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
        WARN_ON(n > 32);
 
        report += offset >> 3;  /* adjust byte index */
-       offset &= 7;            /* now only need bit offset into one byte */
+       offset &= 7;            /* now only need bit offset into one byte */
        x = get_unaligned((u64 *) report);
        x = le64_to_cpu(x);
-       x = (x >> offset) & ((1ULL << n) - 1);  /* extract bit field */
+       x = (x >> offset) & ((1ULL << n) - 1);  /* extract bit field */
        return (u32) x;
 }
 
@@ -829,7 +829,7 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, s
  * reporting to the layer).
  */
 
-static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt)
+void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt)
 {
        unsigned n;
        unsigned count = field->report_count;
@@ -875,7 +875,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u
 exit:
        kfree(value);
 }
-
+EXPORT_SYMBOL_GPL(hid_input_field);
 
 /*
  * Output the field into the report.
@@ -900,7 +900,7 @@ static void hid_output_field(struct hid_field *field, __u8 *data)
  * Create a report.
  */
 
-static void hid_output_report(struct hid_report *report, __u8 *data)
+void hid_output_report(struct hid_report *report, __u8 *data)
 {
        unsigned n;
 
@@ -910,6 +910,7 @@ static void hid_output_report(struct hid_report *report, __u8 *data)
        for (n = 0; n < report->maxfield; n++)
                hid_output_field(report->field[n], data);
 }
+EXPORT_SYMBOL_GPL(hid_output_report);
 
 /*
  * Set a field value. The report this field belongs to has to be
@@ -937,4 +938,5 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
        field->value[offset] = value;
        return 0;
 }
+EXPORT_SYMBOL_GPL(hid_set_field);
 
index d459005..6d3d80b 100644 (file)
@@ -727,8 +727,9 @@ void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
        list_for_each_entry(hidinput, &hid->inputs, list)
                input_sync(hidinput->input);
 }
+EXPORT_SYMBOL_GPL(hidinput_report_event);
 
-static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
+int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
 {
        struct hid_report *report;
        int i, j;
@@ -743,6 +744,7 @@ static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsign
        }
        return -1;
 }
+EXPORT_SYMBOL_GPL(hidinput_find_field);
 
 /*
  * Register the input device; print a message.
@@ -752,7 +754,6 @@ static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsign
 
 int hidinput_connect(struct hid_device *hid)
 {
-       struct usb_device *dev = hid->dev;
        struct hid_report *report;
        struct hid_input *hidinput = NULL;
        struct input_dev *input_dev;
@@ -786,14 +787,17 @@ int hidinput_connect(struct hid_device *hid)
                                }
 
                                input_dev->private = hid;
-                               input_dev->event = hidinput_input_event;
-                               input_dev->open = hidinput_open;
-                               input_dev->close = hidinput_close;
+                               input_dev->event = hid->hidinput_input_event;
+                               input_dev->open = hid->hidinput_open;
+                               input_dev->close = hid->hidinput_close;
 
                                input_dev->name = hid->name;
                                input_dev->phys = hid->phys;
                                input_dev->uniq = hid->uniq;
-                               usb_to_input_id(dev, &input_dev->id);
+                               input_dev->id.bustype = hid->bus;
+                               input_dev->id.vendor  = hid->vendor;
+                               input_dev->id.product = hid->product;
+                               input_dev->id.version = hid->version;
                                input_dev->cdev.dev = &hid->intf->dev;
 
                                hidinput->input = input_dev;
@@ -827,6 +831,7 @@ int hidinput_connect(struct hid_device *hid)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(hidinput_connect);
 
 void hidinput_disconnect(struct hid_device *hid)
 {
@@ -838,3 +843,5 @@ void hidinput_disconnect(struct hid_device *hid)
                kfree(hidinput);
        }
 }
+EXPORT_SYMBOL_GPL(hidinput_disconnect);
+
index 06e169b..462947f 100644 (file)
@@ -497,7 +497,7 @@ void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsign
        spin_unlock_irqrestore(&hid->ctrllock, flags);
 }
 
-static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
        struct hid_device *hid = dev->private;
        struct hid_field *field;
@@ -1231,6 +1231,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                         le16_to_cpu(dev->descriptor.idVendor),
                         le16_to_cpu(dev->descriptor.idProduct));
 
+       hid->bus = BUS_USB;
+       hid->vendor = dev->descriptor.idVendor;
+       hid->product = dev->descriptor.idProduct;
+
        usb_make_path(dev, hid->phys, sizeof(hid->phys));
        strlcat(hid->phys, "/input", sizeof(hid->phys));
        len = strlen(hid->phys);
@@ -1250,6 +1254,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        hid->urbctrl->setup_dma = hid->cr_dma;
        hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
        hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
+       hid->hidinput_input_event = usb_hidinput_input_event;
+       hid->hidinput_open = hidinput_open;
+       hid->hidinput_close = hidinput_close;
 
        return hid;
 
index 4187f4e..7ecdafa 100644 (file)
@@ -79,3 +79,5 @@ int hid_ff_init(struct hid_device* hid)
 
        return init->init(hid);
 }
+EXPORT_SYMBOL_GPL(hid_ff_init);
+
index cbd3b60..07d7996 100644 (file)
@@ -197,7 +197,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
 
        hiddev_send_event(hid, &uref);
 }
-
+EXPORT_SYMBOL_GPL(hiddev_hid_event);
 
 void hiddev_report_event(struct hid_device *hid, struct hid_report *report)
 {
index ee567ae..0473b45 100644 (file)
@@ -403,11 +403,17 @@ struct hid_device {                                                       /* device report descriptor */
        unsigned collection_size;                                       /* Number of allocated hid_collections */
        unsigned maxcollection;                                         /* Number of parsed collections */
        unsigned maxapplication;                                        /* Number of applications */
+       unsigned short bus;                                             /* BUS ID */
+       unsigned short vendor;                                          /* Vendor ID */
+       unsigned short product;                                         /* Product ID */
        unsigned version;                                               /* HID version */
        unsigned country;                                               /* HID country */
        struct hid_report_enum report_enum[HID_REPORT_TYPES];
 
-       struct usb_device *dev;                                         /* USB device */
+       struct usb_device *dev;                                         /* device */
+
+       /* USB specific fields */
+
        struct usb_interface *intf;                                     /* USB interface */
        int ifnum;                                                      /* USB interface number */
 
@@ -454,6 +460,13 @@ struct hid_device {                                                        /* device report descriptor */
        char phys[64];                                                  /* Device physical location */
        char uniq[64];                                                  /* Device unique identifier (serial #) */
 
+       void *driver_data;
+
+       /* device-specific function pointers */
+       int (*hidinput_input_event) (struct input_dev *, unsigned int, unsigned int, int);
+       int (*hidinput_open) (struct input_dev *);
+       void (*hidinput_close) (struct input_dev *);
+
 #ifdef CONFIG_USB_HIDINPUT_POWERBOOK
        unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
        unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
@@ -502,17 +515,15 @@ struct hid_descriptor {
 /* Applications from HID Usage Tables 4/8/99 Version 1.1 */
 /* We ignore a few input applications that are not widely used */
 #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001))
+#else
+#define IS_INPUT_APPLICATION(a) (0)
+#endif
+
+/* HID core API */
 extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
 extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
 extern int hidinput_connect(struct hid_device *);
 extern void hidinput_disconnect(struct hid_device *);
-#else
-#define IS_INPUT_APPLICATION(a) (0)
-static inline void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { }
-static inline void hidinput_report_event(struct hid_device *hid, struct hid_report *report) { }
-static inline int hidinput_connect(struct hid_device *hid) { return -ENODEV; }
-static inline void hidinput_disconnect(struct hid_device *hid) { }
-#endif
 
 int hid_set_field(struct hid_field *, unsigned, __s32);
 int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field);
@@ -536,5 +547,14 @@ static inline int hid_pidff_init(struct hid_device *hid) { return -ENODEV; }
 #else
 static inline int hid_ff_init(struct hid_device *hid) { return -1; }
 #endif
+#ifdef DEBUG
+#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
+               __FILE__ , ## arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+
+#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
+               __FILE__ , ## arg)
 #endif