From b6787242f32700377d3da3b8d788ab3928bab849 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Fri, 27 Apr 2012 00:56:08 +0200 Subject: HID: hidraw: add proper error handling to raw event reporting If kmemdup() in hidraw_report_event() fails, we are not propagating this fact properly. Let hidraw_report_event() and hid_report_raw_event() return an error value to the caller. Reported-by: Oliver Neukum Signed-off-by: Jiri Kosina --- include/linux/hid.h | 2 +- include/linux/hidraw.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/hid.h b/include/linux/hid.h index 3a95da60fd3e..58b3857dc51c 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -896,7 +896,7 @@ static inline int hid_hw_power(struct hid_device *hdev, int level) return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0; } -void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, +int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, int interrupt); extern int hid_generic_init(void); diff --git a/include/linux/hidraw.h b/include/linux/hidraw.h index 4b88e697c4e9..9cdc9b67ff49 100644 --- a/include/linux/hidraw.h +++ b/include/linux/hidraw.h @@ -76,13 +76,13 @@ struct hidraw_list { #ifdef CONFIG_HIDRAW int hidraw_init(void); void hidraw_exit(void); -void hidraw_report_event(struct hid_device *, u8 *, int); +int hidraw_report_event(struct hid_device *, u8 *, int); int hidraw_connect(struct hid_device *); void hidraw_disconnect(struct hid_device *); #else static inline int hidraw_init(void) { return 0; } static inline void hidraw_exit(void) { } -static inline void hidraw_report_event(struct hid_device *hid, u8 *data, int len) { } +static inline int hidraw_report_event(struct hid_device *hid, u8 *data, int len) { } static inline int hidraw_connect(struct hid_device *hid) { return -1; } static inline void hidraw_disconnect(struct hid_device *hid) { } #endif -- cgit v1.2.3 From d6d7c873529abd622897cad5e36f1fd7d82f5110 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Mon, 30 Apr 2012 10:39:17 +0200 Subject: HID: fix return value of hidraw_report_event() when !CONFIG_HIDRAW Commit b6787242f327 ("HID: hidraw: add proper error handling to raw event reporting") forgot to update the static inline version of hidraw_report_event() for the case when CONFIG_HIDRAW is unset. Fix that up. Reported-by: Stephen Rothwell Signed-off-by: Jiri Kosina --- include/linux/hidraw.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/hidraw.h b/include/linux/hidraw.h index 9cdc9b67ff49..45e9fcb8d877 100644 --- a/include/linux/hidraw.h +++ b/include/linux/hidraw.h @@ -82,7 +82,7 @@ void hidraw_disconnect(struct hid_device *); #else static inline int hidraw_init(void) { return 0; } static inline void hidraw_exit(void) { } -static inline int hidraw_report_event(struct hid_device *hid, u8 *data, int len) { } +static inline int hidraw_report_event(struct hid_device *hid, u8 *data, int len) { return 0; } static inline int hidraw_connect(struct hid_device *hid) { return -1; } static inline void hidraw_disconnect(struct hid_device *hid) { } #endif -- cgit v1.2.3 From a7197c2e4120ce40e7e3f5580336b9a1dc791220 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sun, 22 Apr 2012 14:21:40 +0200 Subject: HID: Handle driver-specific device descriptor in core The low-level driver can read the report descriptor, but it cannot determine driver-specific changes to it. The hid core can fixup and parse the report descriptor during driver attach, but does not have direct access to the descriptor when doing so. To be able to handle attach/detach of hid drivers properly, a semantic change to hid_parse_report() is needed. This function has been used in two ways, both as descriptor reader in the ll drivers and as a parsor in the probe of the drivers. This patch splits the usage by introducing hid_open_report(), and modifies the hid_parse() macro to call hid_open_report() instead. The only usage of hid_parse_report() is then to read and store the device descriptor. As a consequence, we can handle the report fixups automatically inside the hid core. Signed-off-by: Henrik Rydberg Tested-by: Nikolai Kondrashov Tested-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 112 +++++++++++++++++++++++++++++++++++++++---------- include/linux/hid.h | 14 ++----- 2 files changed, 94 insertions(+), 32 deletions(-) (limited to 'include/linux') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 4da66b4b977c..9ed4ff37dc2b 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -546,12 +546,11 @@ static void hid_free_report(struct hid_report *report) } /* - * Free a device structure, all reports, and all fields. + * Close report. This function returns the device + * state to the point prior to hid_open_report(). */ - -static void hid_device_release(struct device *dev) +static void hid_close_report(struct hid_device *device) { - struct hid_device *device = container_of(dev, struct hid_device, dev); unsigned i, j; for (i = 0; i < HID_REPORT_TYPES; i++) { @@ -562,11 +561,34 @@ static void hid_device_release(struct device *dev) if (report) hid_free_report(report); } + memset(report_enum, 0, sizeof(*report_enum)); + INIT_LIST_HEAD(&report_enum->report_list); } kfree(device->rdesc); + device->rdesc = NULL; + device->rsize = 0; + kfree(device->collection); - kfree(device); + device->collection = NULL; + device->collection_size = 0; + device->maxcollection = 0; + device->maxapplication = 0; + + device->status &= ~HID_STAT_PARSED; +} + +/* + * Free a device structure, all reports, and all fields. + */ + +static void hid_device_release(struct device *dev) +{ + struct hid_device *hid = container_of(dev, struct hid_device, dev); + + hid_close_report(hid); + kfree(hid->dev_rdesc); + kfree(hid); } /* @@ -643,15 +665,37 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) * @start: report start * @size: report size * + * Allocate the device report as read by the bus driver. This function should + * only be called from parse() in ll drivers. + */ +int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size) +{ + hid->dev_rdesc = kmemdup(start, size, GFP_KERNEL); + if (!hid->dev_rdesc) + return -ENOMEM; + hid->dev_rsize = size; + return 0; +} +EXPORT_SYMBOL_GPL(hid_parse_report); + +/** + * hid_open_report - open a driver-specific device report + * + * @device: hid device + * * Parse a report description into a hid_device structure. Reports are * enumerated, fields are attached to these reports. * 0 returned on success, otherwise nonzero error value. + * + * This function (or the equivalent hid_parse() macro) should only be + * called from probe() in drivers, before starting the device. */ -int hid_parse_report(struct hid_device *device, __u8 *start, - unsigned size) +int hid_open_report(struct hid_device *device) { struct hid_parser *parser; struct hid_item item; + unsigned int size; + __u8 *start; __u8 *end; int ret; static int (*dispatch_type[])(struct hid_parser *parser, @@ -662,6 +706,14 @@ int hid_parse_report(struct hid_device *device, __u8 *start, hid_parser_reserved }; + if (WARN_ON(device->status & HID_STAT_PARSED)) + return -EBUSY; + + start = device->dev_rdesc; + if (WARN_ON(!start)) + return -ENODEV; + size = device->dev_rsize; + if (device->driver->report_fixup) start = device->driver->report_fixup(device, start, &size); @@ -679,6 +731,15 @@ int hid_parse_report(struct hid_device *device, __u8 *start, parser->device = device; end = start + size; + + device->collection = kcalloc(HID_DEFAULT_NUM_COLLECTIONS, + sizeof(struct hid_collection), GFP_KERNEL); + if (!device->collection) { + ret = -ENOMEM; + goto err; + } + device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; + ret = -EINVAL; while ((start = fetch_item(start, end, &item)) != NULL) { @@ -704,6 +765,7 @@ int hid_parse_report(struct hid_device *device, __u8 *start, goto err; } vfree(parser); + device->status |= HID_STAT_PARSED; return 0; } } @@ -711,9 +773,10 @@ int hid_parse_report(struct hid_device *device, __u8 *start, hid_err(device, "item fetching failed at offset %d\n", (int)(end - start)); err: vfree(parser); + hid_close_report(device); return ret; } -EXPORT_SYMBOL_GPL(hid_parse_report); +EXPORT_SYMBOL_GPL(hid_open_report); /* * Convert a signed n-bit integer to signed 32-bit integer. Common @@ -1718,12 +1781,14 @@ static int hid_device_probe(struct device *dev) if (hdrv->probe) { ret = hdrv->probe(hdev, id); } else { /* default probe */ - ret = hid_parse(hdev); + ret = hid_open_report(hdev); if (!ret) ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); } - if (ret) + if (ret) { + hid_close_report(hdev); hdev->driver = NULL; + } } unlock: up(&hdev->driver_lock); @@ -1744,6 +1809,7 @@ static int hid_device_remove(struct device *dev) hdrv->remove(hdev); else /* default remove */ hid_hw_stop(hdev); + hid_close_report(hdev); hdev->driver = NULL; } @@ -2075,6 +2141,16 @@ int hid_add_device(struct hid_device *hdev) && (hid_ignore(hdev) || (hdev->quirks & HID_QUIRK_IGNORE))) return -ENODEV; + /* + * Read the device report descriptor once and use as template + * for the driver-specific modifications. + */ + ret = hdev->ll_driver->parse(hdev); + if (ret) + return ret; + if (!hdev->dev_rdesc) + return -ENODEV; + /* XXX hack, any other cleaner solution after the driver core * is converted to allow more than 20 bytes as the device name? */ dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, @@ -2103,7 +2179,6 @@ EXPORT_SYMBOL_GPL(hid_add_device); struct hid_device *hid_allocate_device(void) { struct hid_device *hdev; - unsigned int i; int ret = -ENOMEM; hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); @@ -2114,23 +2189,13 @@ struct hid_device *hid_allocate_device(void) hdev->dev.release = hid_device_release; hdev->dev.bus = &hid_bus_type; - hdev->collection = kcalloc(HID_DEFAULT_NUM_COLLECTIONS, - sizeof(struct hid_collection), GFP_KERNEL); - if (hdev->collection == NULL) - goto err; - hdev->collection_size = HID_DEFAULT_NUM_COLLECTIONS; - - for (i = 0; i < HID_REPORT_TYPES; i++) - INIT_LIST_HEAD(&hdev->report_enum[i].report_list); + hid_close_report(hdev); init_waitqueue_head(&hdev->debug_wait); INIT_LIST_HEAD(&hdev->debug_list); sema_init(&hdev->driver_lock, 1); return hdev; -err: - put_device(&hdev->dev); - return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(hid_allocate_device); @@ -2141,6 +2206,9 @@ static void hid_remove_device(struct hid_device *hdev) hid_debug_unregister(hdev); hdev->status &= ~HID_STAT_ADDED; } + kfree(hdev->dev_rdesc); + hdev->dev_rdesc = NULL; + hdev->dev_rsize = 0; } /** diff --git a/include/linux/hid.h b/include/linux/hid.h index 3a95da60fd3e..d8e7cc7f894f 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -467,6 +467,8 @@ struct hid_driver; struct hid_ll_driver; struct hid_device { /* device report descriptor */ + __u8 *dev_rdesc; + unsigned dev_rsize; __u8 *rdesc; unsigned rsize; struct hid_collection *collection; /* List of HID collections */ @@ -735,6 +737,7 @@ void hid_output_report(struct hid_report *report, __u8 *data); struct hid_device *hid_allocate_device(void); struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); +int hid_open_report(struct hid_device *device); int hid_check_keys_pressed(struct hid_device *hid); int hid_connect(struct hid_device *hid, unsigned int connect_mask); void hid_disconnect(struct hid_device *hid); @@ -805,16 +808,7 @@ static inline void hid_map_usage_clear(struct hid_input *hidinput, */ static inline int __must_check hid_parse(struct hid_device *hdev) { - int ret; - - if (hdev->status & HID_STAT_PARSED) - return 0; - - ret = hdev->ll_driver->parse(hdev); - if (!ret) - hdev->status |= HID_STAT_PARSED; - - return ret; + return hid_open_report(hdev); } /** -- cgit v1.2.3 From 4d53b8012f1f01ddb3f24db2031b042bb4cbd0d0 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Mon, 23 Apr 2012 12:07:02 +0200 Subject: HID: Add device group to modalias HID devices are only partially presented to userland. Hotplugged devices emit events containing a modalias based on the basic bus, vendor and product entities. However, in practise a hid device can depend on details such as a single usb interface or a particular item in a report descriptor. This patch adds a device group to the hid device id, and broadcasts it using uevent and the device modalias. The module alias generation is modified to match. As a consequence, a device with a non-zero group will be processed by the corresponding group driver instead of by the generic hid driver. Signed-off-by: Henrik Rydberg Acked-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 24 ++++++++++++++++++++++-- include/linux/hid.h | 1 + include/linux/mod_devicetable.h | 3 ++- scripts/mod/file2alias.c | 2 ++ 4 files changed, 27 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 9ed4ff37dc2b..cfcb69eb17d6 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1222,6 +1222,7 @@ static bool hid_match_one_id(struct hid_device *hdev, const struct hid_device_id *id) { return id->bus == hdev->bus && + (id->group == HID_GROUP_ANY || id->group == hdev->group) && (id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) && (id->product == HID_ANY_ID || id->product == hdev->product); } @@ -1694,6 +1695,7 @@ static ssize_t store_new_id(struct device_driver *drv, const char *buf, return -ENOMEM; dynid->id.bus = bus; + dynid->id.group = HID_GROUP_ANY; dynid->id.vendor = vendor; dynid->id.product = product; dynid->id.driver_data = driver_data; @@ -1817,6 +1819,23 @@ static int hid_device_remove(struct device *dev) return 0; } +static ssize_t modalias_show(struct device *dev, struct device_attribute *a, + char *buf) +{ + struct hid_device *hdev = container_of(dev, struct hid_device, dev); + int len; + + len = snprintf(buf, PAGE_SIZE, "hid:b%04Xg%04Xv%08Xp%08X\n", + hdev->bus, hdev->group, hdev->vendor, hdev->product); + + return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; +} + +static struct device_attribute hid_dev_attrs[] = { + __ATTR_RO(modalias), + __ATTR_NULL, +}; + static int hid_uevent(struct device *dev, struct kobj_uevent_env *env) { struct hid_device *hdev = container_of(dev, struct hid_device, dev); @@ -1834,8 +1853,8 @@ static int hid_uevent(struct device *dev, struct kobj_uevent_env *env) if (add_uevent_var(env, "HID_UNIQ=%s", hdev->uniq)) return -ENOMEM; - if (add_uevent_var(env, "MODALIAS=hid:b%04Xv%08Xp%08X", - hdev->bus, hdev->vendor, hdev->product)) + if (add_uevent_var(env, "MODALIAS=hid:b%04Xg%04Xv%08Xp%08X", + hdev->bus, hdev->group, hdev->vendor, hdev->product)) return -ENOMEM; return 0; @@ -1843,6 +1862,7 @@ static int hid_uevent(struct device *dev, struct kobj_uevent_env *env) static struct bus_type hid_bus_type = { .name = "hid", + .dev_attrs = hid_dev_attrs, .match = hid_bus_match, .probe = hid_device_probe, .remove = hid_device_remove, diff --git a/include/linux/hid.h b/include/linux/hid.h index d8e7cc7f894f..a0e27ddb887d 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -476,6 +476,7 @@ struct hid_device { /* device report descriptor */ unsigned maxcollection; /* Number of parsed collections */ unsigned maxapplication; /* Number of applications */ __u16 bus; /* BUS ID */ + __u16 group; /* Report group */ __u32 vendor; /* Vendor ID */ __u32 product; /* Product ID */ __u32 version; /* HID version */ diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 501da4cb8a6d..55ed0b0dc610 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -132,10 +132,11 @@ struct usb_device_id { #define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 #define HID_ANY_ID (~0) +#define HID_GROUP_ANY 0x0000 struct hid_device_id { __u16 bus; - __u16 pad1; + __u16 group; __u32 vendor; __u32 product; kernel_ulong_t driver_data diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 8e730ccc3f2b..fe967cee7371 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -336,10 +336,12 @@ static int do_hid_entry(const char *filename, struct hid_device_id *id, char *alias) { id->bus = TO_NATIVE(id->bus); + id->group = TO_NATIVE(id->group); id->vendor = TO_NATIVE(id->vendor); id->product = TO_NATIVE(id->product); sprintf(alias, "hid:b%04X", id->bus); + ADD(alias, "g", id->group != HID_GROUP_ANY, id->group); ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor); ADD(alias, "p", id->product != HID_ANY_ID, id->product); -- cgit v1.2.3 From 734c660931095ae165c0db6ff60558fc4173bfd0 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Mon, 23 Apr 2012 12:07:03 +0200 Subject: HID: Scan the device for group info before adding it In order to allow the report descriptor to influence the hid device properties, one needs to parse the descriptor early, without reference to any driver. Scan the descriptor for group information during device add, before the device has been broadcast to userland. The device modalias will contain group information which can be used to differentiate between modules. For starters, just handle the generic group. Signed-off-by: Henrik Rydberg Acked-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/hid.h | 5 ++++ 2 files changed, 67 insertions(+) (limited to 'include/linux') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index cfcb69eb17d6..f932cd533d49 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -658,6 +658,58 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) return NULL; } +static void hid_scan_usage(struct hid_device *hid, u32 usage) +{ +} + +/* + * Scan a report descriptor before the device is added to the bus. + * Sets device groups and other properties that determine what driver + * to load. + */ +static int hid_scan_report(struct hid_device *hid) +{ + unsigned int page = 0, delim = 0; + __u8 *start = hid->dev_rdesc; + __u8 *end = start + hid->dev_rsize; + unsigned int u, u_min = 0, u_max = 0; + struct hid_item item; + + hid->group = HID_GROUP_GENERIC; + while ((start = fetch_item(start, end, &item)) != NULL) { + if (item.format != HID_ITEM_FORMAT_SHORT) + return -EINVAL; + if (item.type == HID_ITEM_TYPE_GLOBAL) { + if (item.tag == HID_GLOBAL_ITEM_TAG_USAGE_PAGE) + page = item_udata(&item) << 16; + } else if (item.type == HID_ITEM_TYPE_LOCAL) { + if (delim > 1) + break; + u = item_udata(&item); + if (item.size <= 2) + u += page; + switch (item.tag) { + case HID_LOCAL_ITEM_TAG_DELIMITER: + delim += !!u; + break; + case HID_LOCAL_ITEM_TAG_USAGE: + hid_scan_usage(hid, u); + break; + case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: + u_min = u; + break; + case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM: + u_max = u; + for (u = u_min; u <= u_max; u++) + hid_scan_usage(hid, u); + break; + } + } + } + + return 0; +} + /** * hid_parse_report - parse device report * @@ -2171,6 +2223,16 @@ int hid_add_device(struct hid_device *hdev) if (!hdev->dev_rdesc) return -ENODEV; + /* + * Scan generic devices for group information + */ + if (hid_ignore_special_drivers || + !hid_match_id(hdev, hid_have_special_driver)) { + ret = hid_scan_report(hdev); + if (ret) + hid_warn(hdev, "bad device descriptor (%d)\n", ret); + } + /* XXX hack, any other cleaner solution after the driver core * is converted to allow more than 20 bytes as the device name? */ dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, diff --git a/include/linux/hid.h b/include/linux/hid.h index a0e27ddb887d..f45d33d0c121 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -324,6 +324,11 @@ struct hid_item { #define HID_QUIRK_NO_IGNORE 0x40000000 #define HID_QUIRK_NO_INPUT_SYNC 0x80000000 +/* + * HID device groups + */ +#define HID_GROUP_GENERIC 0x0001 + /* * This is the global environment of the parser. This information is * persistent for main-items. The global environment can be saved and -- cgit v1.2.3 From 7431fb767d896b7f0048039f2e17707ea057d35a Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Mon, 23 Apr 2012 12:07:04 +0200 Subject: HID: Allow bus wildcard matching Most HID drivers do not need to know what bus driver is in use. A generic group driver can drive any hid device, and the device list should not need to be duplicated for each new bus. This patch adds wildcard matching to the HID bus, simplifying device list handling for group drivers. Signed-off-by: Henrik Rydberg Acked-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 2 +- include/linux/mod_devicetable.h | 1 + scripts/mod/file2alias.c | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index f932cd533d49..20daee56d325 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1273,7 +1273,7 @@ EXPORT_SYMBOL_GPL(hid_input_report); static bool hid_match_one_id(struct hid_device *hdev, const struct hid_device_id *id) { - return id->bus == hdev->bus && + return (id->bus == HID_BUS_ANY || id->bus == hdev->bus) && (id->group == HID_GROUP_ANY || id->group == hdev->group) && (id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) && (id->product == HID_ANY_ID || id->product == hdev->product); diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 55ed0b0dc610..5db93821f9c7 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -132,6 +132,7 @@ struct usb_device_id { #define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 #define HID_ANY_ID (~0) +#define HID_BUS_ANY 0xffff #define HID_GROUP_ANY 0x0000 struct hid_device_id { diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index fe967cee7371..056de3104e75 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -340,7 +340,8 @@ static int do_hid_entry(const char *filename, id->vendor = TO_NATIVE(id->vendor); id->product = TO_NATIVE(id->product); - sprintf(alias, "hid:b%04X", id->bus); + sprintf(alias, "hid:"); + ADD(alias, "b", id->bus != HID_BUS_ANY, id->bus); ADD(alias, "g", id->group != HID_GROUP_ANY, id->group); ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor); ADD(alias, "p", id->product != HID_ANY_ID, id->product); -- cgit v1.2.3 From 070748ed0b52399858a5967026a452bbb903a64c Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Mon, 23 Apr 2012 12:07:05 +0200 Subject: HID: Create a generic device group Devices that do not have a special driver are handled by the generic driver. This patch does the same thing using device groups; Instead of forcing a particular driver, the appropriate driver is picked up by udev. As a consequence, one can now move a device from generic to specific handling by a simple rebind. By adding a new device id to the generic driver, the same thing can be done in reverse. Signed-off-by: Henrik Rydberg Acked-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 9 +-------- drivers/hid/usbhid/hid-core.c | 2 +- include/linux/hid.h | 12 ++++++------ net/bluetooth/hidp/core.c | 2 +- 4 files changed, 9 insertions(+), 16 deletions(-) (limited to 'include/linux') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 20daee56d325..cb5a10337541 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1800,14 +1800,7 @@ static int hid_bus_match(struct device *dev, struct device_driver *drv) !strncmp(hdrv->name, "hid-multitouch", 14)) return 1; - if (!hid_match_device(hdev, hdrv)) - return 0; - - /* generic wants all that don't have specialized driver */ - if (!strncmp(hdrv->name, "generic-", 8) && !hid_ignore_special_drivers) - return !hid_match_id(hdev, hid_have_special_driver); - - return 1; + return hid_match_device(hdev, hdrv) != NULL; } static int hid_device_probe(struct device *dev) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 5bf91dbad59d..9abf718318ca 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1505,7 +1505,7 @@ static struct usb_driver hid_driver = { }; static const struct hid_device_id hid_usb_table[] = { - { HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) }, + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, HID_ANY_ID, HID_ANY_ID) }, { } }; diff --git a/include/linux/hid.h b/include/linux/hid.h index f45d33d0c121..dd694fb0c284 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -586,12 +586,12 @@ struct hid_descriptor { struct hid_class_descriptor desc[1]; } __attribute__ ((packed)); -#define HID_DEVICE(b, ven, prod) \ - .bus = (b), \ - .vendor = (ven), .product = (prod) - -#define HID_USB_DEVICE(ven, prod) HID_DEVICE(BUS_USB, ven, prod) -#define HID_BLUETOOTH_DEVICE(ven, prod) HID_DEVICE(BUS_BLUETOOTH, ven, prod) +#define HID_DEVICE(b, g, ven, prod) \ + .bus = (b), .group = (g), .vendor = (ven), .product = (prod) +#define HID_USB_DEVICE(ven, prod) \ + .bus = BUS_USB, .vendor = (ven), .product = (prod) +#define HID_BLUETOOTH_DEVICE(ven, prod) \ + .bus = BUS_BLUETOOTH, .vendor = (ven), .product = (prod) #define HID_REPORT_ID(rep) \ .report_type = (rep) diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index d478be11d562..b6fa982e4031 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -1196,7 +1196,7 @@ int hidp_get_conninfo(struct hidp_conninfo *ci) } static const struct hid_device_id hidp_table[] = { - { HID_BLUETOOTH_DEVICE(HID_ANY_ID, HID_ANY_ID) }, + { HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_GENERIC, HID_ANY_ID, HID_ANY_ID) }, { } }; -- cgit v1.2.3 From 4fa3a5837b8427faab9b064b1948795eb77b9f8d Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Tue, 1 May 2012 08:40:01 +0200 Subject: HID: hid-multitouch: Switch to device groups Switch the driver over to device group handling. By adding the HID_GROUP_MULTITOUCH group to hid-core, hid-generic will no longer match multitouch devices. By adding the HID_GROUP_MULTITOUCH entry to the device list, hid-multitouch will match all unknown multitouch devices, and udev will automatically load the module. Since HID_QUIRK_MULTITOUCH never gets set, the special quirks handling can be removed. Since all HID MT devices have HID_DG_CONTACTID, they can be removed from the hid_have_special_driver list. With this patch, the unknown device ids are no longer NULL, so the code is modified to check for the generic entry instead. Signed-off-by: Henrik Rydberg Acked-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 75 +++----------------------------------------- drivers/hid/hid-input.c | 11 ------- drivers/hid/hid-multitouch.c | 28 +++++++++++------ include/linux/hid.h | 2 +- 4 files changed, 24 insertions(+), 92 deletions(-) (limited to 'include/linux') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index cb5a10337541..0a107fe7e528 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -660,6 +660,8 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) static void hid_scan_usage(struct hid_device *hid, u32 usage) { + if (usage == HID_DG_CONTACTID) + hid->group = HID_GROUP_MULTITOUCH; } /* @@ -1350,10 +1352,6 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev, connect_mask & HID_CONNECT_HIDINPUT_FORCE)) hdev->claimed |= HID_CLAIMED_INPUT; - if (hdev->quirks & HID_QUIRK_MULTITOUCH) { - /* this device should be handled by hid-multitouch, skip it */ - return -ENODEV; - } if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect && !hdev->hiddev_connect(hdev, @@ -1430,13 +1428,10 @@ EXPORT_SYMBOL_GPL(hid_disconnect); /* a list of devices for which there is a specialized driver on HID bus */ static const struct hid_device_id hid_have_special_driver[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) }, - { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) }, { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, USB_DEVICE_ID_ACTIONSTAR_1011) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, @@ -1501,60 +1496,32 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) }, { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_FRUCTEL, USB_DEVICE_ID_GAMETEL_MT_MODE) }, { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, USB_DEVICE_ID_GOODTOUCH_000f) }, { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, - { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT, USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6650) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, @@ -1563,7 +1530,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) }, { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MULTITOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, @@ -1596,8 +1562,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH_DUAL) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) }, @@ -1629,15 +1593,8 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) }, { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PANASONIC, USB_DEVICE_ID_PANABOARD_UBT780) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PANASONIC, USB_DEVICE_ID_PANABOARD_UBT880) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) }, { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, @@ -1654,9 +1611,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM) }, - { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX) }, { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) }, @@ -1670,16 +1624,12 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) }, { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL, USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) }, @@ -1694,16 +1644,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_PID_0038) }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XAT, USB_DEVICE_ID_XAT_CSR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR2) }, { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, @@ -1796,10 +1736,6 @@ static int hid_bus_match(struct device *dev, struct device_driver *drv) struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); struct hid_device *hdev = container_of(dev, struct hid_device, dev); - if ((hdev->quirks & HID_QUIRK_MULTITOUCH) && - !strncmp(hdrv->name, "hid-multitouch", 14)) - return 1; - return hid_match_device(hdev, hdrv) != NULL; } @@ -1817,11 +1753,8 @@ static int hid_device_probe(struct device *dev) if (!hdev->driver) { id = hid_match_device(hdev, hdrv); if (id == NULL) { - if (!((hdev->quirks & HID_QUIRK_MULTITOUCH) && - !strncmp(hdrv->name, "hid-multitouch", 14))) { - ret = -ENODEV; - goto unlock; - } + ret = -ENODEV; + goto unlock; } hdev->driver = hdrv; diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 002781c5a616..7b43186b022c 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -638,10 +638,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel map_key_clear(BTN_STYLUS2); break; - case 0x51: /* ContactID */ - device->quirks |= HID_QUIRK_MULTITOUCH; - goto unknown; - default: goto unknown; } break; @@ -1208,13 +1204,6 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) } } - if (hid->quirks & HID_QUIRK_MULTITOUCH) { - /* generic hid does not know how to handle multitouch devices */ - if (hidinput) - goto out_cleanup; - goto out_unwind; - } - if (hidinput && input_register_device(hidinput->input)) goto out_cleanup; diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 1d5b94167b52..ea465f1ceae9 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -635,6 +635,21 @@ static void mt_set_maxcontacts(struct hid_device *hdev) } } +static void mt_post_parse_default_settings(struct mt_device *td) +{ + __s32 quirks = td->mtclass.quirks; + + /* unknown serial device needs special quirks */ + if (td->touches_by_report == 1) { + quirks |= MT_QUIRK_ALWAYS_VALID; + quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP; + quirks &= ~MT_QUIRK_VALID_IS_INRANGE; + quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE; + } + + td->mtclass.quirks = quirks; +} + static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret, i; @@ -654,7 +669,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) * that emit events over several HID messages. */ hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; - hdev->quirks &= ~HID_QUIRK_MULTITOUCH; td = kzalloc(sizeof(struct mt_device), GFP_KERNEL); if (!td) { @@ -674,14 +688,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) if (ret) goto fail; - if (!id && td->touches_by_report == 1) { - /* the device has been sent by hid-generic */ - mtclass = &td->mtclass; - mtclass->quirks |= MT_QUIRK_ALWAYS_VALID; - mtclass->quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP; - mtclass->quirks &= ~MT_QUIRK_VALID_IS_INRANGE; - mtclass->quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE; - } + if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID) + mt_post_parse_default_settings(td); td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot), GFP_KERNEL); @@ -999,6 +1007,8 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR2) }, + /* Generic MT device */ + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) }, { } }; MODULE_DEVICE_TABLE(hid, mt_devices); diff --git a/include/linux/hid.h b/include/linux/hid.h index dd694fb0c284..2c7a19515c3a 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -317,7 +317,6 @@ struct hid_item { #define HID_QUIRK_BADPAD 0x00000020 #define HID_QUIRK_MULTI_INPUT 0x00000040 #define HID_QUIRK_HIDINPUT_FORCE 0x00000080 -#define HID_QUIRK_MULTITOUCH 0x00000100 #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 #define HID_QUIRK_NO_INIT_REPORTS 0x20000000 @@ -328,6 +327,7 @@ struct hid_item { * HID device groups */ #define HID_GROUP_GENERIC 0x0001 +#define HID_GROUP_MULTITOUCH 0x0002 /* * This is the global environment of the parser. This information is -- cgit v1.2.3