Commit 229695e5 authored by Jiri Kosina's avatar Jiri Kosina Committed by Greg Kroah-Hartman

[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: default avatarJiri Kosina <jkosina@suse.cz>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent dde5845a
/* /*
* USB HID support for Linux * HID support for Linux
* *
* Copyright (c) 1999 Andreas Gal * Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
...@@ -31,8 +31,6 @@ ...@@ -31,8 +31,6 @@
#undef DEBUG #undef DEBUG
#undef DEBUG_DATA #undef DEBUG_DATA
#include <linux/usb.h>
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/hiddev.h> #include <linux/hiddev.h>
...@@ -538,7 +536,7 @@ static void hid_free_report(struct hid_report *report) ...@@ -538,7 +536,7 @@ static void hid_free_report(struct hid_report *report)
* Free a device structure, all reports, and all fields. * 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; unsigned i,j;
...@@ -555,6 +553,7 @@ static void hid_free_device(struct hid_device *device) ...@@ -555,6 +553,7 @@ static void hid_free_device(struct hid_device *device)
kfree(device->rdesc); kfree(device->rdesc);
kfree(device); kfree(device);
} }
EXPORT_SYMBOL_GPL(hid_free_device);
/* /*
* Fetch a report description item from the data stream. We support long * 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) ...@@ -629,7 +628,7 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
* enumerated, fields are attached to these reports. * 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_device *device;
struct hid_parser *parser; struct hid_parser *parser;
...@@ -719,6 +718,7 @@ static struct hid_device *hid_parse_report(__u8 *start, unsigned size) ...@@ -719,6 +718,7 @@ static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
kfree(parser); kfree(parser);
return NULL; return NULL;
} }
EXPORT_SYMBOL_GPL(hid_parse_report);
/* /*
* Convert a signed n-bit integer to signed 32-bit integer. Common * 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) ...@@ -767,10 +767,10 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
WARN_ON(n > 32); WARN_ON(n > 32);
report += offset >> 3; /* adjust byte index */ 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 = get_unaligned((u64 *) report);
x = le64_to_cpu(x); 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; return (u32) x;
} }
...@@ -829,7 +829,7 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, s ...@@ -829,7 +829,7 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, s
* reporting to the layer). * 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 n;
unsigned count = field->report_count; unsigned count = field->report_count;
...@@ -875,7 +875,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u ...@@ -875,7 +875,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u
exit: exit:
kfree(value); kfree(value);
} }
EXPORT_SYMBOL_GPL(hid_input_field);
/* /*
* Output the field into the report. * Output the field into the report.
...@@ -900,7 +900,7 @@ static void hid_output_field(struct hid_field *field, __u8 *data) ...@@ -900,7 +900,7 @@ static void hid_output_field(struct hid_field *field, __u8 *data)
* Create a report. * 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; unsigned n;
...@@ -910,6 +910,7 @@ static void hid_output_report(struct hid_report *report, __u8 *data) ...@@ -910,6 +910,7 @@ static void hid_output_report(struct hid_report *report, __u8 *data)
for (n = 0; n < report->maxfield; n++) for (n = 0; n < report->maxfield; n++)
hid_output_field(report->field[n], data); 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 * 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) ...@@ -937,4 +938,5 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
field->value[offset] = value; field->value[offset] = value;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(hid_set_field);
...@@ -727,8 +727,9 @@ void hidinput_report_event(struct hid_device *hid, struct hid_report *report) ...@@ -727,8 +727,9 @@ void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
list_for_each_entry(hidinput, &hid->inputs, list) list_for_each_entry(hidinput, &hid->inputs, list)
input_sync(hidinput->input); 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; struct hid_report *report;
int i, j; int i, j;
...@@ -743,6 +744,7 @@ static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsign ...@@ -743,6 +744,7 @@ static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsign
} }
return -1; return -1;
} }
EXPORT_SYMBOL_GPL(hidinput_find_field);
/* /*
* Register the input device; print a message. * Register the input device; print a message.
...@@ -752,7 +754,6 @@ static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsign ...@@ -752,7 +754,6 @@ static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsign
int hidinput_connect(struct hid_device *hid) int hidinput_connect(struct hid_device *hid)
{ {
struct usb_device *dev = hid->dev;
struct hid_report *report; struct hid_report *report;
struct hid_input *hidinput = NULL; struct hid_input *hidinput = NULL;
struct input_dev *input_dev; struct input_dev *input_dev;
...@@ -786,14 +787,17 @@ int hidinput_connect(struct hid_device *hid) ...@@ -786,14 +787,17 @@ int hidinput_connect(struct hid_device *hid)
} }
input_dev->private = hid; input_dev->private = hid;
input_dev->event = hidinput_input_event; input_dev->event = hid->hidinput_input_event;
input_dev->open = hidinput_open; input_dev->open = hid->hidinput_open;
input_dev->close = hidinput_close; input_dev->close = hid->hidinput_close;
input_dev->name = hid->name; input_dev->name = hid->name;
input_dev->phys = hid->phys; input_dev->phys = hid->phys;
input_dev->uniq = hid->uniq; 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; input_dev->cdev.dev = &hid->intf->dev;
hidinput->input = input_dev; hidinput->input = input_dev;
...@@ -827,6 +831,7 @@ int hidinput_connect(struct hid_device *hid) ...@@ -827,6 +831,7 @@ int hidinput_connect(struct hid_device *hid)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(hidinput_connect);
void hidinput_disconnect(struct hid_device *hid) void hidinput_disconnect(struct hid_device *hid)
{ {
...@@ -838,3 +843,5 @@ void hidinput_disconnect(struct hid_device *hid) ...@@ -838,3 +843,5 @@ void hidinput_disconnect(struct hid_device *hid)
kfree(hidinput); kfree(hidinput);
} }
} }
EXPORT_SYMBOL_GPL(hidinput_disconnect);
...@@ -497,7 +497,7 @@ void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsign ...@@ -497,7 +497,7 @@ void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsign
spin_unlock_irqrestore(&hid->ctrllock, flags); 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_device *hid = dev->private;
struct hid_field *field; struct hid_field *field;
...@@ -1231,6 +1231,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) ...@@ -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.idVendor),
le16_to_cpu(dev->descriptor.idProduct)); 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)); usb_make_path(dev, hid->phys, sizeof(hid->phys));
strlcat(hid->phys, "/input", sizeof(hid->phys)); strlcat(hid->phys, "/input", sizeof(hid->phys));
len = strlen(hid->phys); len = strlen(hid->phys);
...@@ -1250,6 +1254,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) ...@@ -1250,6 +1254,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
hid->urbctrl->setup_dma = hid->cr_dma; hid->urbctrl->setup_dma = hid->cr_dma;
hid->urbctrl->transfer_dma = hid->ctrlbuf_dma; hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); 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; return hid;
......
...@@ -79,3 +79,5 @@ int hid_ff_init(struct hid_device* hid) ...@@ -79,3 +79,5 @@ int hid_ff_init(struct hid_device* hid)
return init->init(hid); return init->init(hid);
} }
EXPORT_SYMBOL_GPL(hid_ff_init);
...@@ -197,7 +197,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, ...@@ -197,7 +197,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
hiddev_send_event(hid, &uref); hiddev_send_event(hid, &uref);
} }
EXPORT_SYMBOL_GPL(hiddev_hid_event);
void hiddev_report_event(struct hid_device *hid, struct hid_report *report) void hiddev_report_event(struct hid_device *hid, struct hid_report *report)
{ {
......
...@@ -403,11 +403,17 @@ struct hid_device { /* device report descriptor */ ...@@ -403,11 +403,17 @@ struct hid_device { /* device report descriptor */
unsigned collection_size; /* Number of allocated hid_collections */ unsigned collection_size; /* Number of allocated hid_collections */
unsigned maxcollection; /* Number of parsed collections */ unsigned maxcollection; /* Number of parsed collections */
unsigned maxapplication; /* Number of applications */ 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 version; /* HID version */
unsigned country; /* HID country */ unsigned country; /* HID country */
struct hid_report_enum report_enum[HID_REPORT_TYPES]; 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 */ struct usb_interface *intf; /* USB interface */
int ifnum; /* USB interface number */ int ifnum; /* USB interface number */
...@@ -454,6 +460,13 @@ struct hid_device { /* device report descriptor */ ...@@ -454,6 +460,13 @@ struct hid_device { /* device report descriptor */
char phys[64]; /* Device physical location */ char phys[64]; /* Device physical location */
char uniq[64]; /* Device unique identifier (serial #) */ 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 #ifdef CONFIG_USB_HIDINPUT_POWERBOOK
unsigned long pb_pressed_fn[NBITS(KEY_MAX)]; unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
unsigned long pb_pressed_numlock[NBITS(KEY_MAX)]; unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
...@@ -502,17 +515,15 @@ struct hid_descriptor { ...@@ -502,17 +515,15 @@ struct hid_descriptor {
/* Applications from HID Usage Tables 4/8/99 Version 1.1 */ /* Applications from HID Usage Tables 4/8/99 Version 1.1 */
/* We ignore a few input applications that are not widely used */ /* We ignore a few input applications that are not widely used */
#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001)) #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_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 void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
extern int hidinput_connect(struct hid_device *); extern int hidinput_connect(struct hid_device *);
extern void hidinput_disconnect(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 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); 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; } ...@@ -536,5 +547,14 @@ static inline int hid_pidff_init(struct hid_device *hid) { return -ENODEV; }
#else #else
static inline int hid_ff_init(struct hid_device *hid) { return -1; } static inline int hid_ff_init(struct hid_device *hid) { return -1; }
#endif #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 #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment