From jkosina@suse.cz Thu Dec 7 09:59:18 2006 Date: Thu, 7 Dec 2006 17:58:52 +0100 (CET) From: Jiri Kosina To: Greg KH , Marcel Holtmann Cc: Dmitry Torokhov Subject: [PATCH 3/8] Generic HID layer - API Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII [PATCH] Generic HID layer - API - 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 Signed-off-by: Marcel Holtmann Cc: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-core.c | 18 +++++++++++------- drivers/hid/hid-input.c | 19 +++++++++++++------ drivers/usb/input/hid-core.c | 9 ++++++++- drivers/usb/input/hid-ff.c | 2 ++ drivers/usb/input/hiddev.c | 2 +- include/linux/hid.h | 27 +++++++++++++++++++-------- 6 files changed, 54 insertions(+), 23 deletions(-) --- gregkh-2.6.orig/drivers/hid/hid-core.c +++ gregkh-2.6/drivers/hid/hid-core.c @@ -538,7 +538,7 @@ static void hid_free_report(struct hid_r * 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 +555,7 @@ static void hid_free_device(struct hid_d 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 +630,7 @@ static u8 *fetch_item(__u8 *start, __u8 * 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 +720,7 @@ static struct hid_device *hid_parse_repo kfree(parser); return NULL; } +EXPORT_SYMBOL_GPL(hid_parse_report); /* * Convert a signed n-bit integer to signed 32-bit integer. Common @@ -767,10 +769,10 @@ static __inline__ __u32 extract(__u8 *re 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 +831,7 @@ static void hid_process_event(struct hid * 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 +877,7 @@ static void hid_input_field(struct hid_d exit: kfree(value); } - +EXPORT_SYMBOL_GPL(hid_input_field); /* * Output the field into the report. @@ -900,7 +902,7 @@ static void hid_output_field(struct hid_ * 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 +912,7 @@ static void hid_output_report(struct hid 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 +940,5 @@ int hid_set_field(struct hid_field *fiel field->value[offset] = value; return 0; } +EXPORT_SYMBOL_GPL(hid_set_field); --- gregkh-2.6.orig/drivers/hid/hid-input.c +++ gregkh-2.6/drivers/hid/hid-input.c @@ -723,8 +723,9 @@ void hidinput_report_event(struct hid_de 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; @@ -739,6 +740,7 @@ static int hidinput_find_field(struct hi } return -1; } +EXPORT_SYMBOL_GPL(hidinput_find_field); /* * Register the input device; print a message. @@ -748,7 +750,6 @@ static int hidinput_find_field(struct hi 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; @@ -782,14 +783,17 @@ int hidinput_connect(struct hid_device * } 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; @@ -823,6 +827,7 @@ int hidinput_connect(struct hid_device * return 0; } +EXPORT_SYMBOL_GPL(hidinput_connect); void hidinput_disconnect(struct hid_device *hid) { @@ -834,3 +839,5 @@ void hidinput_disconnect(struct hid_devi kfree(hidinput); } } +EXPORT_SYMBOL_GPL(hidinput_disconnect); + --- gregkh-2.6.orig/drivers/usb/input/hid-core.c +++ gregkh-2.6/drivers/usb/input/hid-core.c @@ -497,7 +497,7 @@ void hid_submit_report(struct hid_device 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; @@ -1226,6 +1226,10 @@ static struct hid_device *usb_hid_config 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); @@ -1245,6 +1249,9 @@ static struct hid_device *usb_hid_config 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; --- gregkh-2.6.orig/drivers/usb/input/hid-ff.c +++ gregkh-2.6/drivers/usb/input/hid-ff.c @@ -79,3 +79,5 @@ int hid_ff_init(struct hid_device* hid) return init->init(hid); } +EXPORT_SYMBOL_GPL(hid_ff_init); + --- gregkh-2.6.orig/drivers/usb/input/hiddev.c +++ gregkh-2.6/drivers/usb/input/hiddev.c @@ -197,7 +197,7 @@ void hiddev_hid_event(struct hid_device hiddev_send_event(hid, &uref); } - +EXPORT_SYMBOL_GPL(hiddev_hid_event); void hiddev_report_event(struct hid_device *hid, struct hid_report *report) { --- gregkh-2.6.orig/include/linux/hid.h +++ gregkh-2.6/include/linux/hid.h @@ -402,11 +402,17 @@ struct hid_device { /* device repo 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 */ @@ -453,6 +459,13 @@ struct hid_device { /* device repo 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)]; @@ -501,17 +514,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);