linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Hid bus #2
@ 2008-04-04 20:35 Jiri Slaby
  2008-04-04 20:35 ` [RFC 1/8] HID: make a bus from hid code Jiri Slaby
                   ` (7 more replies)
  0 siblings, 8 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-04 20:35 UTC (permalink / raw)
  To: linux-input; +Cc: jkosina, marcel, dmitry.torokhov


Hi,

requesting for comments hid bus turn 2 based on a discussion some time ago.
All the changes try to be as close as possible to what you all mentioned
in that discussion, although it's possible that some misunderstaning from
my side of any facts you mentioned there occurs in this patch serie. Please
comment the patches, all ideas/improvements are welcome.

Thanks.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [RFC 1/8] HID: make a bus from hid code
  2008-04-04 20:35 Hid bus #2 Jiri Slaby
@ 2008-04-04 20:35 ` Jiri Slaby
  2008-04-04 20:35 ` [RFC 2/8] HID: hid, make parsing event driven Jiri Slaby
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-04 20:35 UTC (permalink / raw)
  To: linux-input; +Cc: jkosina, marcel, dmitry.torokhov, Jiri Slaby, Jiri Slaby

Make a bus from hid core. This is the first step for converting all the
quirks and separate almost-drivers into real drivers attached to this bus.

It's implemented to change behaviour in very tiny manner, so that no driver
needs to be changed this time.

Also add generic drivers for both usb and bt into usbhid or hidp
respectively which will bind all non-blacklisted device. Those blacklisted
will be either grabbed by special drivers or by nobody if they are broken at
the very rude base.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/hid/hid-core.c        |  452 ++++++++++++++++++++++++++++++++++-------
 drivers/hid/hid-input.c       |    2 +-
 drivers/hid/usbhid/hid-core.c |   39 +++-
 drivers/hid/usbhid/usbhid.h   |    2 +-
 include/linux/hid.h           |  104 +++++++++-
 net/bluetooth/hidp/core.c     |   59 +++++-
 6 files changed, 554 insertions(+), 104 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index e03c67d..aa0ff0d 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -534,9 +534,10 @@ static void hid_free_report(struct hid_report *report)
  * Free a device structure, all reports, and all fields.
  */
 
-void hid_free_device(struct hid_device *device)
+static void hid_device_release(struct device *dev)
 {
-	unsigned i,j;
+	struct hid_device *device = container_of(dev, struct hid_device, dev);
+	unsigned int i, j;
 
 	for (i = 0; i < HID_REPORT_TYPES; i++) {
 		struct hid_report_enum *report_enum = device->report_enum + i;
@@ -552,7 +553,6 @@ void hid_free_device(struct hid_device *device)
 	kfree(device->collection);
 	kfree(device);
 }
-EXPORT_SYMBOL_GPL(hid_free_device);
 
 /*
  * Fetch a report description item from the data stream. We support long
@@ -622,18 +622,24 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
 	return NULL;
 }
 
-/*
+/**
+ * hid_parse_report - parse device report
+ *
+ * @device: hid device
+ * @start: report start
+ * @size: report size
+ *
  * 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.
  */
-
-struct hid_device *hid_parse_report(__u8 *start, unsigned size)
+int hid_parse_report(struct hid_device *device, __u8 *start,
+		unsigned size)
 {
-	struct hid_device *device;
 	struct hid_parser *parser;
 	struct hid_item item;
 	__u8 *end;
-	unsigned i;
+	int ret;
 	static int (*dispatch_type[])(struct hid_parser *parser,
 				      struct hid_item *item) = {
 		hid_parser_main,
@@ -642,76 +648,54 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
 		hid_parser_reserved
 	};
 
-	if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL)))
-		return NULL;
-
-	if (!(device->collection = kzalloc(sizeof(struct hid_collection) *
-				   HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) {
-		kfree(device);
-		return NULL;
-	}
-	device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
-
-	for (i = 0; i < HID_REPORT_TYPES; i++)
-		INIT_LIST_HEAD(&device->report_enum[i].report_list);
-
-	if (!(device->rdesc = kmalloc(size, GFP_KERNEL))) {
-		kfree(device->collection);
-		kfree(device);
-		return NULL;
-	}
+	device->rdesc = kmalloc(size, GFP_KERNEL);
+	if (device->rdesc == NULL)
+		return -ENOMEM;
 	memcpy(device->rdesc, start, size);
 	device->rsize = size;
 
-	if (!(parser = vmalloc(sizeof(struct hid_parser)))) {
-		kfree(device->rdesc);
-		kfree(device->collection);
-		kfree(device);
-		return NULL;
+	parser = vmalloc(sizeof(struct hid_parser));
+	if (!parser) {
+		ret = -ENOMEM;
+		goto err;
 	}
+
 	memset(parser, 0, sizeof(struct hid_parser));
 	parser->device = device;
 
 	end = start + size;
+	ret = -EINVAL;
 	while ((start = fetch_item(start, end, &item)) != NULL) {
 
 		if (item.format != HID_ITEM_FORMAT_SHORT) {
 			dbg_hid("unexpected long global item\n");
-			hid_free_device(device);
-			vfree(parser);
-			return NULL;
+			goto err;
 		}
 
 		if (dispatch_type[item.type](parser, &item)) {
 			dbg_hid("item %u %u %u %u parsing failed\n",
 				item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
-			hid_free_device(device);
-			vfree(parser);
-			return NULL;
+			goto err;
 		}
 
 		if (start == end) {
 			if (parser->collection_stack_ptr) {
 				dbg_hid("unbalanced collection at end of report description\n");
-				hid_free_device(device);
-				vfree(parser);
-				return NULL;
+				goto err;
 			}
 			if (parser->local.delimiter_depth) {
 				dbg_hid("unbalanced delimiter at end of report description\n");
-				hid_free_device(device);
-				vfree(parser);
-				return NULL;
+				goto err;
 			}
 			vfree(parser);
-			return device;
+			return 0;
 		}
 	}
 
 	dbg_hid("item fetching failed at offset %d\n", (int)(end - start));
-	hid_free_device(device);
+err:
 	vfree(parser);
-	return NULL;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(hid_parse_report);
 
@@ -815,9 +799,69 @@ static __inline__ int search(__s32 *array, __s32 value, unsigned n)
 	return -1;
 }
 
-static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt)
+/**
+ * hid_match_report - check if driver's raw_event should be called
+ *
+ * @hid: hid device
+ * @report_type: type to match against
+ *
+ * compare hid->driver->report_table->report_type to report->type
+ */
+static int hid_match_report(struct hid_device *hid, struct hid_report *report)
+{
+	const struct hid_report_id *id = hid->driver->report_table;
+
+	if (!id) /* NULL means all */
+		return 1;
+
+	for (; id->report_type != HID_ANY_ID - 1; id++)
+		if (id->report_type == HID_ANY_ID ||
+				id->report_type == report->type)
+			return 1;
+	return 0;
+}
+
+/**
+ * hid_match_usage - check if driver's event should be called
+ *
+ * @hid: hid device
+ * @usage: usage to match against
+ *
+ * compare hid->driver->usage_table->usage_{type,code} to
+ * usage->usage_{type,code}
+ */
+static int hid_match_usage(struct hid_device *hid, struct hid_usage *usage)
+{
+	const struct hid_usage_id *id = hid->driver->usage_table;
+
+	if (!id) /* NULL means all */
+		return 1;
+
+	for (; id->usage_type != HID_ANY_ID - 1; id++)
+		if ((id->usage_type == HID_ANY_ID ||
+				id->usage_type == usage->type) &&
+				(id->usage_code == HID_ANY_ID ||
+				 id->usage_code == usage->code))
+			return 1;
+	return 0;
+}
+
+static void hid_process_event(struct hid_device *hid, struct hid_field *field,
+		struct hid_usage *usage, __s32 value, int interrupt)
 {
+	struct hid_driver *hdrv = hid->driver;
+	int ret;
+
 	hid_dump_input(usage, value);
+
+	if (hdrv && hdrv->event && hid_match_usage(hid, usage)) {
+		ret = hdrv->event(hid, field, usage, value);
+		if (ret != -ENODEV) {
+			dbg_hid("%s's event failed with %d\n", hdrv->name, ret);
+			return;
+		}
+	}
+
 	if (hid->claimed & HID_CLAIMED_INPUT)
 		hidinput_hid_event(hid, field, usage, value);
 	if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt && hid->hiddev_hid_event)
@@ -946,44 +990,47 @@ 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)
+static struct hid_report *hid_get_report(struct hid_report_enum *report_enum,
+		const u8 *data)
 {
-	struct hid_report_enum *report_enum = hid->report_enum + type;
 	struct hid_report *report;
-	int n, rsize, i;
+	unsigned int n = 0;	/* Normally report number is 0 */
 
-	if (!hid)
-		return -ENODEV;
+	/* Device uses numbered reports, data[0] is report number */
+	if (report_enum->numbered)
+		n = *data;
 
-	if (!size) {
-		dbg_hid("empty report\n");
-		return -1;
-	}
+	report = report_enum->report_id_hash[n];
+	if (report == NULL)
+		dbg_hid("undefined report_id %u received\n", n);
 
-	dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
+	return report;
+}
 
-	n = 0;                          /* Normally report number is 0 */
-	if (report_enum->numbered) {    /* Device uses numbered reports, data[0] is report number */
-		n = *data++;
-		size--;
-	}
+void hid_report_raw_event(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;
+	unsigned int a;
+	int rsize, csize = size;
+	u8 *cdata = data;
 
-	/* dump the report */
-	dbg_hid("report %d (size %u) = ", n, size);
-	for (i = 0; i < size; i++)
-		dbg_hid_line(" %02x", data[i]);
-	dbg_hid_line("\n");
+	report = hid_get_report(report_enum, data);
+	if (!report)
+		return;
 
-	if (!(report = report_enum->report_id_hash[n])) {
-		dbg_hid("undefined report_id %d received\n", n);
-		return -1;
+	if (report_enum->numbered) {
+		cdata++;
+		csize--;
 	}
 
 	rsize = ((report->size - 1) >> 3) + 1;
 
-	if (size < rsize) {
-		dbg_hid("report %d is too short, (%d < %d)\n", report->id, size, rsize);
-		memset(data + size, 0, rsize - size);
+	if (csize < rsize) {
+		dbg_hid("report %d is too short, (%d < %d)\n", report->id,
+				csize, rsize);
+		memset(cdata + csize, 0, rsize - csize);
 	}
 
 	if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
@@ -996,24 +1043,277 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
 			hidraw_report_event(hid, data, size);
 	}
 
-	for (n = 0; n < report->maxfield; n++)
-		hid_input_field(hid, report->field[n], data, interrupt);
+	for (a = 0; a < report->maxfield; a++)
+		hid_input_field(hid, report->field[a], cdata, interrupt);
 
 	if (hid->claimed & HID_CLAIMED_INPUT)
 		hidinput_report_event(hid, report);
+}
+EXPORT_SYMBOL_GPL(hid_report_raw_event);
+
+/**
+ * hid_input_report - report data from lower layer (usb, bt...)
+ *
+ * @hid: hid device
+ * @type: HID report type (HID_*_REPORT)
+ * @data: report contents
+ * @size: size of data parameter
+ * @interrupt: called from atomic?
+ *
+ * This is data entry for lower layers.
+ */
+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_driver *hdrv = hid->driver;
+	struct hid_report *report;
+	unsigned int i;
+	int ret;
+
+	if (!hid)
+		return -ENODEV;
+
+	if (!size) {
+		dbg_hid("empty report\n");
+		return -1;
+	}
+
+	dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
+
+	report = hid_get_report(report_enum, data);
+	if (!report)
+		return -1;
+
+	/* dump the report */
+	dbg_hid("report %d (size %u) = ", report->id, size);
+	for (i = 0; i < size; i++)
+		dbg_hid_line(" %02x", data[i]);
+	dbg_hid_line("\n");
+
+	if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
+		ret = hdrv->raw_event(hid, report, data, size);
+		if (ret != -ENODEV)
+			return ret;
+	}
+
+	hid_report_raw_event(hid, type, data, size, interrupt);
 
 	return 0;
 }
 EXPORT_SYMBOL_GPL(hid_input_report);
 
+static bool hid_match_one_id(unsigned int bus_type, struct hid_device *hdev,
+		const struct hid_device_id *id)
+{
+	return bus_type == hdev->bus &&
+		(id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) &&
+		(id->product == HID_ANY_ID || id->product == hdev->product);
+}
+
+static const struct hid_device_id *hid_match_id(unsigned int bus_type,
+		struct hid_device *hdev, const struct hid_device_id *id)
+{
+	for (; id->vendor || id->product; id++)
+		if (hid_match_one_id(bus_type, hdev, id))
+			return id;
+
+	return NULL;
+}
+
+static const struct hid_device_id hid_usb_blacklist[] = {
+	{ }
+};
+
+static const struct hid_device_id *hid_blacklist[] = {
+	[BUS_USB] = hid_usb_blacklist,
+	[BUS_BLUETOOTH] = NULL,
+};
+
+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 (hdrv->bus_type != hdev->bus)
+		return 0;
+
+	/* generic wants all non-blacklisted */
+	if (!strncmp(hdrv->name, "hid-generic-", 12))
+		return !hid_blacklist[hdrv->bus_type] ||
+			!hid_match_id(hdrv->bus_type, hdev,
+				hid_blacklist[hdrv->bus_type]);
+
+	return !!hid_match_id(hdrv->bus_type, hdev, hdrv->id_table);
+}
+
+static int hid_device_probe(struct device *dev)
+{
+	struct hid_driver *hdrv = container_of(dev->driver,
+			struct hid_driver, driver);
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	const struct hid_device_id *id;
+	int ret = 0;
+
+	if (!hdev->driver) {
+		if (hdrv->probe) {
+			ret = -ENODEV;
+
+			id = hid_match_id(hdrv->bus_type, hdev, hdrv->id_table);
+			if (id)
+				ret = hdrv->probe(hdev, id);
+		}
+		if (!ret)
+			hdev->driver = hdrv;
+	}
+	return ret;
+}
+
+static int hid_device_remove(struct device *dev)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct hid_driver *hdrv = hdev->driver;
+
+	if (hdrv) {
+		if (hdrv->remove)
+			hdrv->remove(hdev);
+		hdev->driver = NULL;
+	}
+
+	return 0;
+}
+
+static struct bus_type hid_bus_type = {
+	.name		= "hid",
+	.match		= hid_bus_match,
+	.probe		= hid_device_probe,
+	.remove		= hid_device_remove,
+};
+
+int hid_add_device(struct hid_device *hdev)
+{
+	static atomic_t id = ATOMIC_INIT(0);
+	int ret;
+
+	if (WARN_ON(hdev->is_added))
+		return -EBUSY;
+
+	/* XXX hack, any other cleaner solution < 20 bus_id bytes? */
+	sprintf(hdev->dev.bus_id, "%02X:%04X:%04X.%02X", hdev->bus,
+			hdev->vendor, hdev->product, atomic_inc_return(&id));
+
+	ret = device_add(&hdev->dev);
+	if (!ret)
+		hdev->is_added = 1;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(hid_add_device);
+
+/**
+ * hid_allocate_device - allocate new hid device descriptor
+ *
+ * Allocate and initialize hid device, so that hid_destroy_device might be
+ * used to free it.
+ *
+ * New hid_device pointer is returned on success, otherwise ERR_PTR encoded
+ * error value.
+ */
+struct hid_device *hid_allocate_device(void)
+{
+	struct hid_device *hdev;
+	unsigned int i;
+	int ret = -ENOMEM;
+
+	hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
+	if (hdev == NULL)
+		return ERR_PTR(ret);
+
+	device_initialize(&hdev->dev);
+	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);
+
+	return hdev;
+err:
+	put_device(&hdev->dev);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(hid_allocate_device);
+
+static void hid_remove_device(struct hid_device *hdev)
+{
+	if (hdev->is_added) {
+		device_del(&hdev->dev);
+		hdev->is_added = 0;
+	}
+}
+
+/**
+ * hid_destroy_device - free previously allocated device
+ *
+ * @hdev: hid device
+ *
+ * If you allocate hid_device through hid_allocate_device, you should ever
+ * free by this function.
+ */
+void hid_destroy_device(struct hid_device *hdev)
+{
+	hid_remove_device(hdev);
+	put_device(&hdev->dev);
+}
+EXPORT_SYMBOL_GPL(hid_destroy_device);
+
+int __hid_register_driver(struct hid_driver *hdrv, struct module *owner,
+		const char *mod_name)
+{
+	hdrv->driver.name = hdrv->name;
+	hdrv->driver.bus = &hid_bus_type;
+	hdrv->driver.owner = owner;
+	hdrv->driver.mod_name = mod_name;
+
+	return driver_register(&hdrv->driver);
+}
+EXPORT_SYMBOL_GPL(__hid_register_driver);
+
+void hid_unregister_driver(struct hid_driver *hdrv)
+{
+	driver_unregister(&hdrv->driver);
+}
+EXPORT_SYMBOL_GPL(hid_unregister_driver);
+
 static int __init hid_init(void)
 {
-	return hidraw_init();
+	int ret;
+
+	ret = bus_register(&hid_bus_type);
+	if (ret) {
+		printk(KERN_ERR "HID: can't register hid bus\n");
+		goto err;
+	}
+
+	ret = hidraw_init();
+	if (ret)
+		goto err_bus;
+
+	return 0;
+err_bus:
+	bus_unregister(&hid_bus_type);
+err:
+	return ret;
 }
 
 static void __exit hid_exit(void)
 {
 	hidraw_exit();
+	bus_unregister(&hid_bus_type);
 }
 
 module_init(hid_init);
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index c3eb3f1..f300c7b 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1030,7 +1030,7 @@ int hidinput_connect(struct hid_device *hid)
 				input_dev->id.vendor  = hid->vendor;
 				input_dev->id.product = hid->product;
 				input_dev->id.version = hid->version;
-				input_dev->dev.parent = hid->dev;
+				input_dev->dev.parent = hid->dev.parent;
 				hidinput->input = input_dev;
 				list_add_tail(&hidinput->list, &hid->inputs);
 			}
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index e0d805f..25f5541 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -770,8 +770,15 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 		dbg_hid_line(" %02x", (unsigned char) rdesc[n]);
 	dbg_hid_line("\n");
 
-	if (!(hid = hid_parse_report(rdesc, n))) {
+	hid = hid_allocate_device();
+	if (IS_ERR(hid)) {
+		kfree(rdesc);
+		return NULL;
+	}
+
+	if (hid_parse_report(hid, rdesc, n)) {
 		dbg_hid("parsing report descriptor failed\n");
+		hid_destroy_device(hid);
 		kfree(rdesc);
 		return NULL;
 	}
@@ -798,10 +805,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 	if (insize > HID_MAX_BUFFER_SIZE)
 		insize = HID_MAX_BUFFER_SIZE;
 
-	if (hid_alloc_buffers(dev, hid)) {
-		hid_free_buffers(dev, hid);
+	if (hid_alloc_buffers(dev, hid))
 		goto fail;
-	}
 
 	hid->name[0] = 0;
 
@@ -881,7 +886,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 
 	hid->version = le16_to_cpu(hdesc->bcdHID);
 	hid->country = hdesc->bCountryCode;
-	hid->dev = &intf->dev;
+	hid->dev.parent = &intf->dev;
 	usbhid->intf = intf;
 	usbhid->ifnum = interface->desc.bInterfaceNumber;
 
@@ -925,7 +930,7 @@ fail:
 	hid_free_buffers(dev, hid);
 	kfree(usbhid);
 fail_no_usbhid:
-	hid_free_device(hid);
+	hid_destroy_device(hid);
 
 	return NULL;
 }
@@ -964,14 +969,14 @@ static void hid_disconnect(struct usb_interface *intf)
 
 	hid_free_buffers(hid_to_usb_dev(hid), hid);
 	kfree(usbhid);
-	hid_free_device(hid);
+	hid_destroy_device(hid);
 }
 
 static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct hid_device *hid;
 	char path[64];
-	int i;
+	int i, ret;
 	char *c;
 
 	dbg_hid("HID probe called for ifnum %d\n",
@@ -1037,7 +1042,12 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
 	printk(": USB HID v%x.%02x %s [%s] on %s\n",
 		hid->version >> 8, hid->version & 0xff, c, hid->name, path);
 
-	return 0;
+	ret = hid_add_device(hid);
+	if (ret) {
+		dev_err(&intf->dev, "can't add hid device: %d\n", ret);
+		hid_disconnect(intf);
+	}
+	return ret;
 }
 
 static int hid_suspend(struct usb_interface *intf, pm_message_t message)
@@ -1107,9 +1117,17 @@ static struct usb_driver hid_driver = {
 	.supports_autosuspend = 1,
 };
 
+static struct hid_driver hid_generic_usb = {
+	.name = "hid-generic-usb",
+	.bus_type = BUS_USB,
+};
+
 static int __init hid_init(void)
 {
 	int retval;
+	retval = hid_register_driver(&hid_generic_usb);
+	if (retval)
+		goto hid_register_fail;
 	retval = usbhid_quirks_init(quirks_param);
 	if (retval)
 		goto usbhid_quirks_init_fail;
@@ -1127,6 +1145,8 @@ usb_register_fail:
 hiddev_init_fail:
 	usbhid_quirks_exit();
 usbhid_quirks_init_fail:
+	hid_unregister_driver(&hid_generic_usb);
+hid_register_fail:
 	return retval;
 }
 
@@ -1135,6 +1155,7 @@ static void __exit hid_exit(void)
 	usb_deregister(&hid_driver);
 	hiddev_exit();
 	usbhid_quirks_exit();
+	hid_unregister_driver(&hid_generic_usb);
 }
 
 module_init(hid_init);
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index 62d2d7c..b47f991 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -82,7 +82,7 @@ struct usbhid_device {
 };
 
 #define	hid_to_usb_dev(hid_dev) \
-	container_of(hid_dev->dev->parent, struct usb_device, dev)
+	container_of(hid_dev->dev.parent->parent, struct usb_device, dev)
 
 #endif
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index d951ec4..fa1f28c 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -70,6 +70,7 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/timer.h>
+#include <linux/types.h>
 #include <linux/workqueue.h>
 #include <linux/input.h>
 
@@ -432,22 +433,26 @@ struct hid_input {
 	struct input_dev *input;
 };
 
+struct hid_driver;
+
 struct hid_device {							/* device report descriptor */
-	 __u8 *rdesc;
+	__u8 *rdesc;
 	unsigned rsize;
 	struct hid_collection *collection;				/* List of HID collections */
 	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 int bus;						/* BUS ID */
+	__u32 vendor;							/* Vendor ID */
+	__u32 product;							/* Product ID */
+	__u32 version;							/* HID version */
 	unsigned country;						/* HID country */
 	struct hid_report_enum report_enum[HID_REPORT_TYPES];
 
-	struct device *dev;						/* device */
+	struct device dev;						/* device */
+	struct hid_driver *driver;
 
+	unsigned int is_added;						/* hid_add_device called? */
 	unsigned claimed;						/* Claimed by hidinput, hiddev? */
 	unsigned quirks;						/* Various quirks the device can pull on us */
 
@@ -483,6 +488,16 @@ struct hid_device {							/* device report descriptor */
 #endif
 };
 
+static inline void *hid_get_drvdata(struct hid_device *hdev)
+{
+	return dev_get_drvdata(&hdev->dev);
+}
+
+static inline void hid_set_drvdata(struct hid_device *hdev, void *data)
+{
+	dev_set_drvdata(&hdev->dev, data);
+}
+
 #define HID_GLOBAL_STACK_SIZE 4
 #define HID_COLLECTION_STACK_SIZE 4
 
@@ -511,6 +526,62 @@ struct hid_descriptor {
 	struct hid_class_descriptor desc[1];
 } __attribute__ ((packed));
 
+#define HID_ANY_ID	(~0)
+#define HID_DEVICE(ven, prod) \
+	.vendor = (ven), .product = (prod)
+
+struct hid_device_id {
+	__u32 vendor, product;
+	kernel_ulong_t driver_data;
+};
+
+#define HID_REPORT_ID(rep) \
+	.report_type = (rep)
+#define HID_USAGE_ID(utype, ucode) \
+	.usage_type = (utype), .usage_code = (ucode)
+/* we don't want to catch types and codes equal to 0 */
+#define HID_TERMINATOR \
+	(HID_ANY_ID - 1)
+
+struct hid_report_id {
+	__u32 report_type;
+};
+struct hid_usage_id {
+	__u32 usage_type;
+	__u32 usage_code;
+};
+
+/**
+ * struct hid_driver
+ * @name: driver name (e.g. "Footech_bar-wheel")
+ * @bus_type: BUS_* type
+ * @id_table: which devices is this driver for (must be non-NULL for probe
+ * 	      to be called)
+ * @probe: new device inserted
+ * @remove: device removed (NULL if not a hot-plug capable driver)
+ * @report_table: on which reports to call raw_event (NULL means all)
+ * @raw_event: if report in report_table, this hook is called (NULL means nop)
+ * @usage_table: on which events to call event (NULL means all)
+ * @event: if usage in usage_table, this hook is called (NULL means nop)
+ */
+struct hid_driver {
+	char *name;
+	unsigned int bus_type;
+	const struct hid_device_id *id_table;
+
+	int (*probe)(struct hid_device *dev, const struct hid_device_id *id);
+	void (*remove)(struct hid_device *dev);
+
+	const struct hid_report_id *report_table;
+	int (*raw_event)(struct hid_device *hdev, struct hid_report *report,
+			u8 *data, int size);
+	const struct hid_usage_id *usage_table;
+	int (*event)(struct hid_device *hdev, struct hid_field *field,
+			struct hid_usage *usage, __s32 value);
+/* private: */
+	struct device_driver driver;
+};
+
 /* 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))
@@ -521,6 +592,17 @@ struct hid_descriptor {
 extern int hid_debug;
 #endif
 
+extern int hid_add_device(struct hid_device *);
+extern void hid_destroy_device(struct hid_device *);
+
+extern int __must_check __hid_register_driver(struct hid_driver *,
+		struct module *, const char *mod_name);
+static inline int __must_check hid_register_driver(struct hid_driver *driver)
+{
+	return __hid_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
+}
+extern void hid_unregister_driver(struct hid_driver *);
+
 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 *);
@@ -533,8 +615,14 @@ int hidinput_mapping_quirks(struct hid_usage *, struct input_dev *, unsigned lon
 int hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
 int hidinput_apple_event(struct hid_device *, struct input_dev *, struct hid_usage *, __s32);
 void hid_output_report(struct hid_report *report, __u8 *data);
-void hid_free_device(struct hid_device *device);
-struct hid_device *hid_parse_report(__u8 *start, unsigned size);
+struct hid_device *hid_allocate_device(void);
+int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
+
+void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
+		int interrupt);
+
+extern int hid_generic_init(void);
+extern void hid_generic_exit(void);
 
 /* HID quirks API */
 u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct);
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 519cdb9..b3329bf 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -578,7 +578,7 @@ static int hidp_session(void *arg)
 	if (session->hid) {
 		if (session->hid->claimed & HID_CLAIMED_INPUT)
 			hidinput_disconnect(session->hid);
-		hid_free_device(session->hid);
+		hid_destroy_device(session->hid);
 	}
 
 	fput(session->intr_sock->file);
@@ -692,12 +692,13 @@ static void hidp_setup_quirks(struct hid_device *hid)
 			hid->quirks = hidp_blacklist[n].quirks;
 }
 
-static void hidp_setup_hid(struct hidp_session *session,
+static int hidp_setup_hid(struct hidp_session *session,
 				struct hidp_connadd_req *req)
 {
 	struct hid_device *hid = session->hid;
 	struct hid_report *report;
 	bdaddr_t src, dst;
+	int ret;
 
 	baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
 	baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst);
@@ -715,7 +716,7 @@ static void hidp_setup_hid(struct hidp_session *session,
 	strncpy(hid->phys, batostr(&src), 64);
 	strncpy(hid->uniq, batostr(&dst), 64);
 
-	hid->dev = hidp_get_device(session);
+	hid->dev.parent = hidp_get_device(session);
 
 	hid->hid_open  = hidp_open;
 	hid->hid_close = hidp_close;
@@ -732,6 +733,15 @@ static void hidp_setup_hid(struct hidp_session *session,
 
 	if (hidinput_connect(hid) == 0)
 		hid->claimed |= HID_CLAIMED_INPUT;
+
+	ret = hid_add_device(hid);
+	if (ret) {
+		if (hid->claimed & HID_CLAIMED_INPUT)
+			hidinput_disconnect(hid);
+		skb_queue_purge(&session->intr_transmit);
+	}
+
+	return ret;
 }
 
 int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
@@ -765,11 +775,19 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
 			return -EFAULT;
 		}
 
-		session->hid = hid_parse_report(buf, req->rd_size);
+		session->hid = hid_allocate_device();
+		if (IS_ERR(session->hid)) {
+			kfree(buf);
+			kfree(session);
+			return PTR_ERR(session->hid);
+		}
+
+		err = hid_parse_report(session->hid, buf, req->rd_size);
 
 		kfree(buf);
 
-		if (!session->hid) {
+		if (err) {
+			hid_destroy_device(session->hid);
 			kfree(session);
 			return -EINVAL;
 		}
@@ -816,8 +834,11 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
 			goto failed;
 	}
 
-	if (session->hid)
-		hidp_setup_hid(session, req);
+	if (session->hid) {
+		err = hidp_setup_hid(session, req);
+		if (err)
+			goto failed;
+	}
 
 	__hidp_link_session(session);
 
@@ -853,7 +874,7 @@ failed:
 	up_write(&hidp_session_sem);
 
 	if (session->hid)
-		hid_free_device(session->hid);
+		hid_destroy_device(session->hid);
 
 	input_free_device(session->input);
 	kfree(session);
@@ -940,18 +961,38 @@ int hidp_get_conninfo(struct hidp_conninfo *ci)
 	return err;
 }
 
+static struct hid_driver hid_generic_bt = {
+	.name = "hid-generic-bt",
+	.bus_type = BUS_BLUETOOTH,
+};
+
 static int __init hidp_init(void)
 {
+	int ret;
+
 	l2cap_load();
 
 	BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
 
-	return hidp_init_sockets();
+	ret = hid_register_driver(&hid_generic_bt);
+	if (ret)
+		goto err;
+
+	ret = hidp_init_sockets();
+	if (ret)
+		goto err_drv;
+
+	return 0;
+err_drv:
+	hid_unregister_driver(&hid_generic_bt);
+err:
+	return ret;
 }
 
 static void __exit hidp_exit(void)
 {
 	hidp_cleanup_sockets();
+	hid_unregister_driver(&hid_generic_bt);
 }
 
 module_init(hidp_init);
-- 
1.5.4.4


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC 2/8] HID: hid, make parsing event driven
  2008-04-04 20:35 Hid bus #2 Jiri Slaby
  2008-04-04 20:35 ` [RFC 1/8] HID: make a bus from hid code Jiri Slaby
@ 2008-04-04 20:35 ` Jiri Slaby
  2008-04-04 20:35 ` [RFC 3/8] HID: move ids into separate file Jiri Slaby
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-04 20:35 UTC (permalink / raw)
  To: linux-input; +Cc: jkosina, marcel, dmitry.torokhov, Jiri Slaby, Jiri Slaby

Next step for complete hid bus, this patch includes:
- call parser either from probe or from hid-core if there is no probe.
- add ll_driver structure and centralize some stuff there (open, close...)
- split and merge usb_hid_configure and hid_probe into several functions
  to allow hooks/fixes between them

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/hid/hid-core.c        |   24 ++-
 drivers/hid/hid-input.c       |   16 ++-
 drivers/hid/hidraw.c          |    6 +-
 drivers/hid/usbhid/hid-core.c |  330 ++++++++++++++++++++++++-----------------
 include/linux/hid.h           |   98 ++++++++++++-
 net/bluetooth/hidp/core.c     |  191 ++++++++++++++----------
 net/bluetooth/hidp/hidp.h     |    2 +
 7 files changed, 427 insertions(+), 240 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index aa0ff0d..40de7e7 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -648,6 +648,9 @@ int hid_parse_report(struct hid_device *device, __u8 *start,
 		hid_parser_reserved
 	};
 
+	if (device->driver->report_fixup)
+		device->driver->report_fixup(device, start, size);
+
 	device->rdesc = kmalloc(size, GFP_KERNEL);
 	if (device->rdesc == NULL)
 		return -ENOMEM;
@@ -1070,7 +1073,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
 	unsigned int i;
 	int ret;
 
-	if (!hid)
+	if (!hid || !hid->driver)
 		return -ENODEV;
 
 	if (!size) {
@@ -1155,15 +1158,20 @@ static int hid_device_probe(struct device *dev)
 	int ret = 0;
 
 	if (!hdev->driver) {
+		hdev->driver = hdrv;
 		if (hdrv->probe) {
 			ret = -ENODEV;
 
 			id = hid_match_id(hdrv->bus_type, hdev, hdrv->id_table);
 			if (id)
 				ret = hdrv->probe(hdev, id);
+		} else { /* default probe */
+			ret = hid_parse(hdev);
+			if (!ret)
+				ret = hid_hw_start(hdev);
 		}
-		if (!ret)
-			hdev->driver = hdrv;
+		if (ret)
+			hdev->driver = NULL;
 	}
 	return ret;
 }
@@ -1176,6 +1184,8 @@ static int hid_device_remove(struct device *dev)
 	if (hdrv) {
 		if (hdrv->remove)
 			hdrv->remove(hdev);
+		else /* default remove */
+			hid_hw_stop(hdev);
 		hdev->driver = NULL;
 	}
 
@@ -1194,7 +1204,7 @@ int hid_add_device(struct hid_device *hdev)
 	static atomic_t id = ATOMIC_INIT(0);
 	int ret;
 
-	if (WARN_ON(hdev->is_added))
+	if (WARN_ON(hdev->status & HID_STAT_ADDED))
 		return -EBUSY;
 
 	/* XXX hack, any other cleaner solution < 20 bus_id bytes? */
@@ -1203,7 +1213,7 @@ int hid_add_device(struct hid_device *hdev)
 
 	ret = device_add(&hdev->dev);
 	if (!ret)
-		hdev->is_added = 1;
+		hdev->status |= HID_STAT_ADDED;
 
 	return ret;
 }
@@ -1250,9 +1260,9 @@ EXPORT_SYMBOL_GPL(hid_allocate_device);
 
 static void hid_remove_device(struct hid_device *hdev)
 {
-	if (hdev->is_added) {
+	if (hdev->status & HID_STAT_ADDED) {
 		device_del(&hdev->dev);
-		hdev->is_added = 0;
+		hdev->status &= ~HID_STAT_ADDED;
 	}
 }
 
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index f300c7b..5f1a91a 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -389,6 +389,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 	if (ret)
 		goto mapped;
 
+	if (device->driver->input_mapping &&
+			device->driver->input_mapping(device, hidinput, usage,
+				&bit, &max))
+		goto mapped;
+
 	switch (usage->hid & HID_USAGE_PAGE) {
 
 		case HID_UP_UNDEFINED:
@@ -753,6 +758,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 	}
 
 mapped:
+	if (device->driver->input_mapped)
+		device->driver->input_mapped(device, hidinput, usage,
+				&bit, &max);
+
 	if (device->quirks & HID_QUIRK_MIGHTYMOUSE) {
 		if (usage->hid == HID_GD_Z)
 			map_rel(REL_HWHEEL);
@@ -959,14 +968,14 @@ static int hidinput_open(struct input_dev *dev)
 {
 	struct hid_device *hid = input_get_drvdata(dev);
 
-	return hid->hid_open(hid);
+	return hid->ll_driver->open(hid);
 }
 
 static void hidinput_close(struct input_dev *dev)
 {
 	struct hid_device *hid = input_get_drvdata(dev);
 
-	hid->hid_close(hid);
+	hid->ll_driver->close(hid);
 }
 
 /*
@@ -1017,7 +1026,8 @@ int hidinput_connect(struct hid_device *hid)
 				}
 
 				input_set_drvdata(input_dev, hid);
-				input_dev->event = hid->hidinput_input_event;
+				input_dev->event =
+					hid->ll_driver->hidinput_input_event;
 				input_dev->open = hidinput_open;
 				input_dev->close = hidinput_close;
 				input_dev->setkeycode = hidinput_setkeycode;
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 1ca6f46..19081d0 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -178,7 +178,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
 
 	dev = hidraw_table[minor];
 	if (!dev->open++)
-		dev->hid->hid_open(dev->hid);
+		dev->hid->ll_driver->open(dev->hid);
 
 out_unlock:
 	spin_unlock(&minors_lock);
@@ -203,7 +203,7 @@ static int hidraw_release(struct inode * inode, struct file * file)
 	dev = hidraw_table[minor];
 	if (!dev->open--) {
 		if (list->hidraw->exist)
-			dev->hid->hid_close(dev->hid);
+			dev->hid->ll_driver->close(dev->hid);
 		else
 			kfree(list->hidraw);
 	}
@@ -359,7 +359,7 @@ void hidraw_disconnect(struct hid_device *hid)
 	device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
 
 	if (hidraw->open) {
-		hid->hid_close(hid);
+		hid->ll_driver->close(hid);
 		wake_up_interruptible(&hidraw->wait);
 	} else {
 		kfree(hidraw);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 25f5541..d655dfc 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -701,17 +701,84 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
 	kfree(buf);
 }
 
-static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+static int usbhid_start_finish(struct hid_device *hid)
 {
+	struct usb_interface *intf = to_usb_interface(hid->dev.parent);
+	char path[64], *type;
+	unsigned int i;
+
+	usbhid_init_reports(hid);
+	hid_dump_device(hid);
+	if (hid->quirks & HID_QUIRK_RESET_LEDS)
+		usbhid_set_leds(hid);
+
+	if (!hidinput_connect(hid))
+		hid->claimed |= HID_CLAIMED_INPUT;
+	if (!hiddev_connect(hid))
+		hid->claimed |= HID_CLAIMED_HIDDEV;
+	if (!hidraw_connect(hid))
+		hid->claimed |= HID_CLAIMED_HIDRAW;
+
+	if (!hid->claimed) {
+		printk(KERN_ERR "HID device claimed by neither input, hiddev "
+				"nor hidraw\n");
+		return -ENODEV;
+	}
+
+	if ((hid->claimed & HID_CLAIMED_INPUT))
+		hid_ff_init(hid);
+
+	if (hid->quirks & HID_QUIRK_SONY_PS3_CONTROLLER)
+		hid_fixup_sony_ps3_controller(interface_to_usbdev(intf),
+			intf->cur_altsetting->desc.bInterfaceNumber);
+
+	printk(KERN_INFO);
+
+	if (hid->claimed & HID_CLAIMED_INPUT)
+		printk("input");
+	if ((hid->claimed & HID_CLAIMED_INPUT) &&
+			((hid->claimed & HID_CLAIMED_HIDDEV) ||
+				hid->claimed & HID_CLAIMED_HIDRAW))
+		printk(",");
+	if (hid->claimed & HID_CLAIMED_HIDDEV)
+		printk("hiddev%d", hid->minor);
+	if ((hid->claimed & HID_CLAIMED_INPUT) &&
+			(hid->claimed & HID_CLAIMED_HIDDEV) &&
+			(hid->claimed & HID_CLAIMED_HIDRAW))
+		printk(",");
+	if (hid->claimed & HID_CLAIMED_HIDRAW)
+		printk("hidraw%d", ((struct hidraw *)hid->hidraw)->minor);
+
+	type = "Device";
+	for (i = 0; i < hid->maxcollection; i++) {
+		if (hid->collection[i].type == HID_COLLECTION_APPLICATION &&
+		    (hid->collection[i].usage & HID_USAGE_PAGE) ==
+						HID_UP_GENDESK &&
+		    (hid->collection[i].usage & 0xffff) <
+						ARRAY_SIZE(hid_types)) {
+			type = hid_types[hid->collection[i].usage & 0xffff];
+			break;
+		}
+	}
+
+	usb_make_path(interface_to_usbdev(intf), path, 63);
+
+	printk(": USB HID v%x.%02x %s [%s] on %s\n",
+		hid->version >> 8, hid->version & 0xff, type, hid->name, path);
+
+	return 0;
+}
+
+static int usbhid_parse(struct hid_device *hid)
+{
+	struct usb_interface *intf = to_usb_interface(hid->dev.parent);
 	struct usb_host_interface *interface = intf->cur_altsetting;
 	struct usb_device *dev = interface_to_usbdev (intf);
 	struct hid_descriptor *hdesc;
-	struct hid_device *hid;
 	u32 quirks = 0;
-	unsigned int insize = 0, rsize = 0;
+	unsigned int rsize = 0;
 	char *rdesc;
-	int n, len;
-	struct usbhid_device *usbhid;
+	int ret, n;
 
 	quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
 			le16_to_cpu(dev->descriptor.idProduct));
@@ -725,40 +792,44 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 	}
 
 	if (quirks & HID_QUIRK_IGNORE)
-		return NULL;
+		return -ENODEV;
 
 	if ((quirks & HID_QUIRK_IGNORE_MOUSE) &&
 		(interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE))
-			return NULL;
-
+			return -ENODEV;
 
 	if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
 	    (!interface->desc.bNumEndpoints ||
 	     usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
 		dbg_hid("class descriptor not present\n");
-		return NULL;
+		return -ENODEV;
 	}
 
+	hid->version = le16_to_cpu(hdesc->bcdHID);
+	hid->country = hdesc->bCountryCode;
+
 	for (n = 0; n < hdesc->bNumDescriptors; n++)
 		if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
 			rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
 
 	if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
 		dbg_hid("weird size of report descriptor (%u)\n", rsize);
-		return NULL;
+		return -EINVAL;
 	}
 
 	if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) {
 		dbg_hid("couldn't allocate rdesc memory\n");
-		return NULL;
+		return -ENOMEM;
 	}
 
 	hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);
 
-	if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
+	ret = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber,
+			HID_DT_REPORT, rdesc, rsize);
+	if (ret < 0) {
 		dbg_hid("reading report descriptor failed\n");
 		kfree(rdesc);
-		return NULL;
+		goto err;
 	}
 
 	usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor),
@@ -770,24 +841,36 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 		dbg_hid_line(" %02x", (unsigned char) rdesc[n]);
 	dbg_hid_line("\n");
 
-	hid = hid_allocate_device();
-	if (IS_ERR(hid)) {
-		kfree(rdesc);
-		return NULL;
-	}
-
-	if (hid_parse_report(hid, rdesc, n)) {
+	ret = hid_parse_report(hid, rdesc, rsize);
+	kfree(rdesc);
+	if (ret) {
 		dbg_hid("parsing report descriptor failed\n");
-		hid_destroy_device(hid);
-		kfree(rdesc);
-		return NULL;
+		goto err;
 	}
 
-	kfree(rdesc);
 	hid->quirks = quirks;
 
-	if (!(usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL)))
-		goto fail_no_usbhid;
+	return 0;
+err:
+	return ret;
+}
+
+static int usbhid_start(struct hid_device *hid)
+{
+	struct usb_interface *intf = to_usb_interface(hid->dev.parent);
+	struct usb_host_interface *interface = intf->cur_altsetting;
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usbhid_device *usbhid;
+	unsigned int n, insize = 0;
+	int ret;
+
+	WARN_ON(hid->driver_data);
+
+	usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL);
+	if (usbhid == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
 
 	hid->driver_data = usbhid;
 	usbhid->hid = hid;
@@ -805,27 +888,12 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 	if (insize > HID_MAX_BUFFER_SIZE)
 		insize = HID_MAX_BUFFER_SIZE;
 
-	if (hid_alloc_buffers(dev, hid))
+	if (hid_alloc_buffers(dev, hid)) {
+		ret = -ENOMEM;
 		goto fail;
-
-	hid->name[0] = 0;
-
-	if (dev->manufacturer)
-		strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
-
-	if (dev->product) {
-		if (dev->manufacturer)
-			strlcat(hid->name, " ", sizeof(hid->name));
-		strlcat(hid->name, dev->product, sizeof(hid->name));
 	}
 
-	if (!strlen(hid->name))
-		snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
-			 le16_to_cpu(dev->descriptor.idVendor),
-			 le16_to_cpu(dev->descriptor.idProduct));
-
 	for (n = 0; n < interface->desc.bNumEndpoints; n++) {
-
 		struct usb_endpoint_descriptor *endpoint;
 		int pipe;
 		int interval;
@@ -837,7 +905,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 		interval = endpoint->bInterval;
 
 		/* Some vendors give fullspeed interval on highspeed devides */
-		if (quirks & HID_QUIRK_FULLSPEED_INTERVAL  &&
+		if (hid->quirks & HID_QUIRK_FULLSPEED_INTERVAL &&
 		    dev->speed == USB_SPEED_HIGH) {
 			interval = fls(endpoint->bInterval*8);
 			printk(KERN_INFO "%s: Fixing fullspeed to highspeed interval: %d -> %d\n",
@@ -848,6 +916,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 		if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
 			interval = hid_mousepoll_interval;
 
+		ret = -ENOMEM;
 		if (usb_endpoint_dir_in(endpoint)) {
 			if (usbhid->urbin)
 				continue;
@@ -873,6 +942,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 
 	if (!usbhid->urbin) {
 		err_hid("couldn't find an input interrupt endpoint");
+		ret = -ENODEV;
 		goto fail;
 	}
 
@@ -884,44 +954,26 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 	spin_lock_init(&usbhid->outlock);
 	spin_lock_init(&usbhid->ctrllock);
 
-	hid->version = le16_to_cpu(hdesc->bcdHID);
-	hid->country = hdesc->bCountryCode;
-	hid->dev.parent = &intf->dev;
 	usbhid->intf = intf;
 	usbhid->ifnum = interface->desc.bInterfaceNumber;
 
-	hid->bus = BUS_USB;
-	hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
-	hid->product = le16_to_cpu(dev->descriptor.idProduct);
-
-	usb_make_path(dev, hid->phys, sizeof(hid->phys));
-	strlcat(hid->phys, "/input", sizeof(hid->phys));
-	len = strlen(hid->phys);
-	if (len < sizeof(hid->phys) - 1)
-		snprintf(hid->phys + len, sizeof(hid->phys) - len,
-			 "%d", intf->altsetting[0].desc.bInterfaceNumber);
-
-	if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
-		hid->uniq[0] = 0;
-
 	usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
-	if (!usbhid->urbctrl)
+	if (!usbhid->urbctrl) {
+		ret = -ENOMEM;
 		goto fail;
+	}
 
 	usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr,
 			     usbhid->ctrlbuf, 1, hid_ctrl, hid);
 	usbhid->urbctrl->setup_dma = usbhid->cr_dma;
 	usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
 	usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
-	hid->hidinput_input_event = usb_hidinput_input_event;
-	hid->hid_open = usbhid_open;
-	hid->hid_close = usbhid_close;
-#ifdef CONFIG_USB_HIDDEV
-	hid->hiddev_hid_event = hiddev_hid_event;
-	hid->hiddev_report_event = hiddev_report_event;
-#endif
-	hid->hid_output_raw_report = usbhid_output_raw_report;
-	return hid;
+
+	ret = usbhid_start_finish(hid);
+	if (ret)
+		goto fail;
+
+	return 0;
 
 fail:
 	usb_free_urb(usbhid->urbin);
@@ -929,24 +981,18 @@ fail:
 	usb_free_urb(usbhid->urbctrl);
 	hid_free_buffers(dev, hid);
 	kfree(usbhid);
-fail_no_usbhid:
-	hid_destroy_device(hid);
-
-	return NULL;
+err:
+	return ret;
 }
 
-static void hid_disconnect(struct usb_interface *intf)
+static void usbhid_stop(struct hid_device *hid)
 {
-	struct hid_device *hid = usb_get_intfdata (intf);
-	struct usbhid_device *usbhid;
+	struct usbhid_device *usbhid = hid->driver_data;
 
-	if (!hid)
+	if (WARN_ON(!usbhid))
 		return;
 
-	usbhid = hid->driver_data;
-
 	spin_lock_irq(&usbhid->inlock);	/* Sync with error handler */
-	usb_set_intfdata(intf, NULL);
 	set_bit(HID_DISCONNECTED, &usbhid->iofl);
 	spin_unlock_irq(&usbhid->inlock);
 	usb_kill_urb(usbhid->urbin);
@@ -963,93 +1009,99 @@ static void hid_disconnect(struct usb_interface *intf)
 	if (hid->claimed & HID_CLAIMED_HIDRAW)
 		hidraw_disconnect(hid);
 
+	hid->claimed = 0;
+
 	usb_free_urb(usbhid->urbin);
 	usb_free_urb(usbhid->urbctrl);
 	usb_free_urb(usbhid->urbout);
 
 	hid_free_buffers(hid_to_usb_dev(hid), hid);
 	kfree(usbhid);
-	hid_destroy_device(hid);
+	hid->driver_data = NULL;
 }
 
+static struct hid_ll_driver usb_hid_driver = {
+	.parse = usbhid_parse,
+	.start = usbhid_start,
+	.stop = usbhid_stop,
+	.open = usbhid_open,
+	.close = usbhid_close,
+	.hidinput_input_event = usb_hidinput_input_event,
+};
+
 static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
+	struct usb_device *dev = interface_to_usbdev(intf);
 	struct hid_device *hid;
-	char path[64];
-	int i, ret;
-	char *c;
+	size_t len;
+	int ret;
 
 	dbg_hid("HID probe called for ifnum %d\n",
 			intf->altsetting->desc.bInterfaceNumber);
 
-	if (!(hid = usb_hid_configure(intf)))
-		return -ENODEV;
-
-	usbhid_init_reports(hid);
-	hid_dump_device(hid);
-	if (hid->quirks & HID_QUIRK_RESET_LEDS)
-		usbhid_set_leds(hid);
-
-	if (!hidinput_connect(hid))
-		hid->claimed |= HID_CLAIMED_INPUT;
-	if (!hiddev_connect(hid))
-		hid->claimed |= HID_CLAIMED_HIDDEV;
-	if (!hidraw_connect(hid))
-		hid->claimed |= HID_CLAIMED_HIDRAW;
+	hid = hid_allocate_device();
+	if (IS_ERR(hid))
+		return PTR_ERR(hid);
 
 	usb_set_intfdata(intf, hid);
+	hid->ll_driver = &usb_hid_driver;
+	hid->hid_output_raw_report = usbhid_output_raw_report;
+#ifdef CONFIG_USB_HIDDEV
+	hid->hiddev_hid_event = hiddev_hid_event;
+	hid->hiddev_report_event = hiddev_report_event;
+#endif
+	hid->dev.parent = &intf->dev;
+	hid->bus = BUS_USB;
+	hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
+	hid->product = le16_to_cpu(dev->descriptor.idProduct);
+	hid->name[0] = 0;
 
-	if (!hid->claimed) {
-		printk ("HID device claimed by neither input, hiddev nor hidraw\n");
-		hid_disconnect(intf);
-		return -ENODEV;
-	}
-
-	if ((hid->claimed & HID_CLAIMED_INPUT))
-		hid_ff_init(hid);
-
-	if (hid->quirks & HID_QUIRK_SONY_PS3_CONTROLLER)
-		hid_fixup_sony_ps3_controller(interface_to_usbdev(intf),
-			intf->cur_altsetting->desc.bInterfaceNumber);
-
-	printk(KERN_INFO);
-
-	if (hid->claimed & HID_CLAIMED_INPUT)
-		printk("input");
-	if ((hid->claimed & HID_CLAIMED_INPUT) && ((hid->claimed & HID_CLAIMED_HIDDEV) ||
-				hid->claimed & HID_CLAIMED_HIDRAW))
-		printk(",");
-	if (hid->claimed & HID_CLAIMED_HIDDEV)
-		printk("hiddev%d", hid->minor);
-	if ((hid->claimed & HID_CLAIMED_INPUT) && (hid->claimed & HID_CLAIMED_HIDDEV) &&
-			(hid->claimed & HID_CLAIMED_HIDRAW))
-		printk(",");
-	if (hid->claimed & HID_CLAIMED_HIDRAW)
-		printk("hidraw%d", ((struct hidraw*)hid->hidraw)->minor);
+	if (dev->manufacturer)
+		strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
 
-	c = "Device";
-	for (i = 0; i < hid->maxcollection; i++) {
-		if (hid->collection[i].type == HID_COLLECTION_APPLICATION &&
-		    (hid->collection[i].usage & HID_USAGE_PAGE) == HID_UP_GENDESK &&
-		    (hid->collection[i].usage & 0xffff) < ARRAY_SIZE(hid_types)) {
-			c = hid_types[hid->collection[i].usage & 0xffff];
-			break;
-		}
+	if (dev->product) {
+		if (dev->manufacturer)
+			strlcat(hid->name, " ", sizeof(hid->name));
+		strlcat(hid->name, dev->product, sizeof(hid->name));
 	}
 
-	usb_make_path(interface_to_usbdev(intf), path, 63);
+	if (!strlen(hid->name))
+		snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
+			 le16_to_cpu(dev->descriptor.idVendor),
+			 le16_to_cpu(dev->descriptor.idProduct));
 
-	printk(": USB HID v%x.%02x %s [%s] on %s\n",
-		hid->version >> 8, hid->version & 0xff, c, hid->name, path);
+	usb_make_path(dev, hid->phys, sizeof(hid->phys));
+	strlcat(hid->phys, "/input", sizeof(hid->phys));
+	len = strlen(hid->phys);
+	if (len < sizeof(hid->phys) - 1)
+		snprintf(hid->phys + len, sizeof(hid->phys) - len,
+			 "%d", intf->altsetting[0].desc.bInterfaceNumber);
+
+	if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
+		hid->uniq[0] = 0;
 
 	ret = hid_add_device(hid);
 	if (ret) {
 		dev_err(&intf->dev, "can't add hid device: %d\n", ret);
-		hid_disconnect(intf);
+		goto err;
 	}
+
+	return 0;
+err:
+	hid_destroy_device(hid);
 	return ret;
 }
 
+static void hid_disconnect(struct usb_interface *intf)
+{
+	struct hid_device *hid = usb_get_intfdata(intf);
+
+	if (WARN_ON(!hid))
+		return;
+
+	hid_destroy_device(hid);
+}
+
 static int hid_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct hid_device *hid = usb_get_intfdata (intf);
diff --git a/include/linux/hid.h b/include/linux/hid.h
index fa1f28c..ff6df20 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -419,6 +419,9 @@ struct hid_control_fifo {
 #define HID_CLAIMED_HIDDEV	2
 #define HID_CLAIMED_HIDRAW	4
 
+#define HID_STAT_ADDED		1
+#define HID_STAT_PARSED		2
+
 #define HID_CTRL_RUNNING	1
 #define HID_OUT_RUNNING		2
 #define HID_IN_RUNNING		3
@@ -434,6 +437,7 @@ struct hid_input {
 };
 
 struct hid_driver;
+struct hid_ll_driver;
 
 struct hid_device {							/* device report descriptor */
 	__u8 *rdesc;
@@ -451,8 +455,9 @@ struct hid_device {							/* device report descriptor */
 
 	struct device dev;						/* device */
 	struct hid_driver *driver;
+	struct hid_ll_driver *ll_driver;
 
-	unsigned int is_added;						/* hid_add_device called? */
+	unsigned int status;						/* see STAT flags above */
 	unsigned claimed;						/* Claimed by hidinput, hiddev? */
 	unsigned quirks;						/* Various quirks the device can pull on us */
 
@@ -470,11 +475,6 @@ struct hid_device {							/* device report descriptor */
 
 	__s32 delayed_value;						/* For A4 Tech mice hwheel quirk */
 
-	/* device-specific function pointers */
-	int (*hidinput_input_event) (struct input_dev *, unsigned int, unsigned int, int);
-	int (*hid_open) (struct hid_device *);
-	void (*hid_close) (struct hid_device *);
-
 	/* hiddev event handler */
 	void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field,
 				  struct hid_usage *, __s32);
@@ -563,6 +563,9 @@ struct hid_usage_id {
  * @raw_event: if report in report_table, this hook is called (NULL means nop)
  * @usage_table: on which events to call event (NULL means all)
  * @event: if usage in usage_table, this hook is called (NULL means nop)
+ * @report_fixup: called before report descriptor parsing (NULL means nop)
+ * @input_mapping: invoked on input registering before mapping an usage
+ * @input_mapped: invoked on input registering after mapping an usage
  */
 struct hid_driver {
 	char *name;
@@ -578,10 +581,43 @@ struct hid_driver {
 	const struct hid_usage_id *usage_table;
 	int (*event)(struct hid_device *hdev, struct hid_field *field,
 			struct hid_usage *usage, __s32 value);
+
+	void (*report_fixup)(struct hid_device *hdev, __u8 *buf,
+			unsigned int size);
+
+	int (*input_mapping)(struct hid_device *hdev,
+			struct hid_input *hidinput, struct hid_usage *usage,
+			unsigned long **bit, int *max);
+	void (*input_mapped)(struct hid_device *hdev,
+			struct hid_input *hidinput, struct hid_usage *usage,
+			unsigned long **bit, int *max);
 /* private: */
 	struct device_driver driver;
 };
 
+/**
+ * hid_ll_driver - low level driver callbacks
+ * @start: called on probe to start the device
+ * @stop: called on remove
+ * @open: called by input layer on open
+ * @close: called by input layer on close
+ * @hidinput_input_event: event input event (e.g. ff or leds)
+ * @parse: this method is called only once to parse the device data,
+ *	   shouldn't allocate anything to not leak memory
+ */
+struct hid_ll_driver {
+	int (*start)(struct hid_device *hdev);
+	void (*stop)(struct hid_device *hdev);
+
+	int (*open)(struct hid_device *hdev);
+	void (*close)(struct hid_device *hdev);
+
+	int (*hidinput_input_event) (struct input_dev *idev, unsigned int type,
+			unsigned int code, int value);
+
+	int (*parse)(struct hid_device *hdev);
+};
+
 /* 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))
@@ -618,6 +654,56 @@ void hid_output_report(struct hid_report *report, __u8 *data);
 struct hid_device *hid_allocate_device(void);
 int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
 
+/**
+ * hid_parse - parse HW reports
+ *
+ * @hdev: hid device
+ *
+ * Call this from probe after you set up the device (if needed). Your
+ * report_fixup will be called (if non-NULL) after reading raw report from
+ * device before passing it to hid layer for real parsing.
+ */
+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;
+}
+
+/**
+ * hid_hw_start - start underlaying HW
+ *
+ * @hdev: hid device
+ *
+ * Call this in probe function *after* hid_parse. This will setup HW buffers
+ * and start the device (if not deffered to device open). hid_hw_stop must be
+ * called if this was successfull.
+ */
+static inline int __must_check hid_hw_start(struct hid_device *hdev)
+{
+	return hdev->ll_driver->start(hdev);
+}
+
+/**
+ * hid_hw_stop - stop underlaying HW
+ *
+ * @hdev: hid device
+ *
+ * This is usually called from remove function or from probe when something
+ * failed and hid_hw_start was called already.
+ */
+static inline void hid_hw_stop(struct hid_device *hdev)
+{
+	hdev->ll_driver->stop(hdev);
+}
+
 void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
 		int interrupt);
 
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index b3329bf..8261d4c 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -617,9 +617,15 @@ static struct device *hidp_get_device(struct hidp_session *session)
 static int hidp_setup_input(struct hidp_session *session,
 				struct hidp_connadd_req *req)
 {
-	struct input_dev *input = session->input;
+	struct input_dev *input;
 	int i;
 
+	input = input_allocate_device();
+	if (!input)
+		return -ENOMEM;
+
+	session->input = input;
+
 	input_set_drvdata(input, session);
 
 	input->name = "Bluetooth HID Boot Protocol Device";
@@ -692,55 +698,117 @@ static void hidp_setup_quirks(struct hid_device *hid)
 			hid->quirks = hidp_blacklist[n].quirks;
 }
 
+static int hidp_parse(struct hid_device *hid)
+{
+	struct hidp_session *session = hid->driver_data;
+	struct hidp_connadd_req *req = session->req;
+	unsigned char *buf;
+	int ret;
+
+	buf = kmalloc(req->rd_size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (copy_from_user(buf, req->rd_data, req->rd_size)) {
+		kfree(buf);
+		return -EFAULT;
+	}
+
+	ret = hid_parse_report(session->hid, buf, req->rd_size);
+
+	kfree(buf);
+
+	if (ret)
+		return ret;
+
+	session->req = NULL;
+
+	hidp_setup_quirks(hid);
+	return 0;
+}
+
+static int hidp_start(struct hid_device *hid)
+{
+	struct hidp_session *session = hid->driver_data;
+	struct hid_report *report;
+
+	list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].
+			report_list, list)
+		hidp_send_report(session, report);
+
+	list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].
+			report_list, list)
+		hidp_send_report(session, report);
+
+	if (hidinput_connect(hid) == 0)
+		hid->claimed |= HID_CLAIMED_INPUT;
+
+	return 0;
+}
+
+static void hidp_stop(struct hid_device *hid)
+{
+	struct hidp_session *session = hid->driver_data;
+
+	skb_queue_purge(&session->ctrl_transmit);
+	skb_queue_purge(&session->intr_transmit);
+
+	if (hid->claimed & HID_CLAIMED_INPUT)
+		hidinput_disconnect(hid);
+	hid->claimed = 0;
+}
+
+static struct hid_ll_driver hidp_driver = {
+	.parse = hidp_parse,
+	.start = hidp_start,
+	.stop = hidp_stop,
+	.open  = hidp_open,
+	.close = hidp_close,
+	.hidinput_input_event = hidp_hidinput_event,
+};
+
 static int hidp_setup_hid(struct hidp_session *session,
 				struct hidp_connadd_req *req)
 {
-	struct hid_device *hid = session->hid;
-	struct hid_report *report;
+	struct hid_device *hid;
 	bdaddr_t src, dst;
 	int ret;
 
-	baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
-	baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst);
+	hid = hid_allocate_device();
+	if (IS_ERR(hid)) {
+		ret = PTR_ERR(session->hid);
+		goto err;
+	}
 
+	session->hid = hid;
+	session->req = req;
 	hid->driver_data = session;
 
-	hid->country = req->country;
+	baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
+	baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst);
 
 	hid->bus     = BUS_BLUETOOTH;
 	hid->vendor  = req->vendor;
 	hid->product = req->product;
 	hid->version = req->version;
+	hid->country = req->country;
 
 	strncpy(hid->name, req->name, 128);
 	strncpy(hid->phys, batostr(&src), 64);
 	strncpy(hid->uniq, batostr(&dst), 64);
 
 	hid->dev.parent = hidp_get_device(session);
-
-	hid->hid_open  = hidp_open;
-	hid->hid_close = hidp_close;
-
-	hid->hidinput_input_event = hidp_hidinput_event;
-
-	hidp_setup_quirks(hid);
-
-	list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
-		hidp_send_report(session, report);
-
-	list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
-		hidp_send_report(session, report);
-
-	if (hidinput_connect(hid) == 0)
-		hid->claimed |= HID_CLAIMED_INPUT;
+	hid->ll_driver = &hidp_driver;
 
 	ret = hid_add_device(hid);
-	if (ret) {
-		if (hid->claimed & HID_CLAIMED_INPUT)
-			hidinput_disconnect(hid);
-		skb_queue_purge(&session->intr_transmit);
-	}
+	if (ret)
+		goto err_hid;
 
+	return 0;
+err_hid:
+	hid_destroy_device(hid);
+	session->hid = NULL;
+err:
 	return ret;
 }
 
@@ -761,46 +829,6 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
 
 	BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
 
-	if (req->rd_size > 0) {
-		unsigned char *buf = kmalloc(req->rd_size, GFP_KERNEL);
-
-		if (!buf) {
-			kfree(session);
-			return -ENOMEM;
-		}
-
-		if (copy_from_user(buf, req->rd_data, req->rd_size)) {
-			kfree(buf);
-			kfree(session);
-			return -EFAULT;
-		}
-
-		session->hid = hid_allocate_device();
-		if (IS_ERR(session->hid)) {
-			kfree(buf);
-			kfree(session);
-			return PTR_ERR(session->hid);
-		}
-
-		err = hid_parse_report(session->hid, buf, req->rd_size);
-
-		kfree(buf);
-
-		if (err) {
-			hid_destroy_device(session->hid);
-			kfree(session);
-			return -EINVAL;
-		}
-	}
-
-	if (!session->hid) {
-		session->input = input_allocate_device();
-		if (!session->input) {
-			kfree(session);
-			return -ENOMEM;
-		}
-	}
-
 	down_write(&hidp_session_sem);
 
 	s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
@@ -828,16 +856,16 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
 	session->flags   = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
 	session->idle_to = req->idle_to;
 
-	if (session->input) {
-		err = hidp_setup_input(session, req);
-		if (err < 0)
-			goto failed;
-	}
-
-	if (session->hid) {
+	if (req->rd_size > 0) {
 		err = hidp_setup_hid(session, req);
 		if (err)
-			goto failed;
+			goto err_skb;
+	}
+
+	if (!session->hid) {
+		err = hidp_setup_input(session, req);
+		if (err < 0)
+			goto err_skb;
 	}
 
 	__hidp_link_session(session);
@@ -865,16 +893,15 @@ unlink:
 
 	__hidp_unlink_session(session);
 
-	if (session->input) {
+	if (session->input)
 		input_unregister_device(session->input);
-		session->input = NULL; /* don't try to free it here */
-	}
-
-failed:
-	up_write(&hidp_session_sem);
-
 	if (session->hid)
 		hid_destroy_device(session->hid);
+err_skb:
+	skb_queue_purge(&session->ctrl_transmit);
+	skb_queue_purge(&session->intr_transmit);
+failed:
+	up_write(&hidp_session_sem);
 
 	input_free_device(session->input);
 	kfree(session);
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index 343fb05..e503c89 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -151,6 +151,8 @@ struct hidp_session {
 
 	struct sk_buff_head ctrl_transmit;
 	struct sk_buff_head intr_transmit;
+
+	struct hidp_connadd_req *req;
 };
 
 static inline void hidp_schedule(struct hidp_session *session)
-- 
1.5.4.4


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC 3/8] HID: move ids into separate file
  2008-04-04 20:35 Hid bus #2 Jiri Slaby
  2008-04-04 20:35 ` [RFC 1/8] HID: make a bus from hid code Jiri Slaby
  2008-04-04 20:35 ` [RFC 2/8] HID: hid, make parsing event driven Jiri Slaby
@ 2008-04-04 20:35 ` Jiri Slaby
  2008-04-04 20:35 ` [RFC 4/8] HID: move usage input mapping to hid.h Jiri Slaby
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-04 20:35 UTC (permalink / raw)
  To: linux-input; +Cc: jkosina, marcel, dmitry.torokhov, Jiri Slaby, Jiri Slaby

Move ids from hid-quirks.c into separate file, since it will be needed in
more than one place.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/hid/hid-ids.h           |  423 +++++++++++++++++++++++++++++++++++++++
 drivers/hid/usbhid/hid-quirks.c |  402 +-------------------------------------
 2 files changed, 424 insertions(+), 401 deletions(-)
 create mode 100644 drivers/hid/hid-ids.h

diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
new file mode 100644
index 0000000..05bcb22
--- /dev/null
+++ b/drivers/hid/hid-ids.h
@@ -0,0 +1,423 @@
+/*
+ *  USB HID quirks support for Linux
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#ifndef HID_IDS_H_FILE
+#define HID_IDS_H_FILE
+
+#define USB_VENDOR_ID_A4TECH		0x09da
+#define USB_DEVICE_ID_A4TECH_WCP32PU	0x0006
+#define USB_DEVICE_ID_A4TECH_X5_005D	0x000a
+
+#define USB_VENDOR_ID_AASHIMA		0x06d6
+#define USB_DEVICE_ID_AASHIMA_GAMEPAD	0x0025
+#define USB_DEVICE_ID_AASHIMA_PREDATOR	0x0026
+
+#define USB_VENDOR_ID_ACECAD		0x0460
+#define USB_DEVICE_ID_ACECAD_FLAIR	0x0004
+#define USB_DEVICE_ID_ACECAD_302	0x0008
+
+#define USB_VENDOR_ID_ADS_TECH 		0x06e1
+#define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X	0xa155
+
+#define USB_VENDOR_ID_AFATECH		0x15a4
+#define USB_DEVICE_ID_AFATECH_AF9016	0x9016
+
+#define USB_VENDOR_ID_AIPTEK		0x08ca
+#define USB_DEVICE_ID_AIPTEK_01		0x0001
+#define USB_DEVICE_ID_AIPTEK_10		0x0010
+#define USB_DEVICE_ID_AIPTEK_20		0x0020
+#define USB_DEVICE_ID_AIPTEK_21		0x0021
+#define USB_DEVICE_ID_AIPTEK_22		0x0022
+#define USB_DEVICE_ID_AIPTEK_23		0x0023
+#define USB_DEVICE_ID_AIPTEK_24		0x0024
+
+#define USB_VENDOR_ID_AIRCABLE		0x16CA
+#define USB_DEVICE_ID_AIRCABLE1		0x1502
+
+#define USB_VENDOR_ID_ALCOR		0x058f
+#define USB_DEVICE_ID_ALCOR_USBRS232	0x9720
+
+#define USB_VENDOR_ID_ALPS		0x0433
+#define USB_DEVICE_ID_IBM_GAMEPAD	0x1101
+
+#define USB_VENDOR_ID_APPLE		0x05ac
+#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE	0x0304
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI	0x020e
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO	0x020f
+#define USB_DEVICE_ID_APPLE_GEYSER_ANSI	0x0214
+#define USB_DEVICE_ID_APPLE_GEYSER_ISO	0x0215
+#define USB_DEVICE_ID_APPLE_GEYSER_JIS	0x0216
+#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI	0x0217
+#define USB_DEVICE_ID_APPLE_GEYSER3_ISO	0x0218
+#define USB_DEVICE_ID_APPLE_GEYSER3_JIS	0x0219
+#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI	0x021a
+#define USB_DEVICE_ID_APPLE_GEYSER4_ISO	0x021b
+#define USB_DEVICE_ID_APPLE_GEYSER4_JIS	0x021c
+#define USB_DEVICE_ID_APPLE_ALU_ANSI	0x0220
+#define USB_DEVICE_ID_APPLE_ALU_ISO	0x0221
+#define USB_DEVICE_ID_APPLE_ALU_JIS	0x0222
+#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI    0x0229
+#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO     0x022a
+#define USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS     0x022b
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI  0x022c
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO   0x022d
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS   0x022e
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY	0x030a
+#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY	0x030b
+#define USB_DEVICE_ID_APPLE_IRCONTROL4	0x8242
+
+#define USB_VENDOR_ID_ASUS		0x0b05
+#define USB_DEVICE_ID_ASUS_LCM		0x1726
+
+#define USB_VENDOR_ID_ATEN		0x0557
+#define USB_DEVICE_ID_ATEN_UC100KM	0x2004
+#define USB_DEVICE_ID_ATEN_CS124U	0x2202
+#define USB_DEVICE_ID_ATEN_2PORTKVM	0x2204
+#define USB_DEVICE_ID_ATEN_4PORTKVM	0x2205
+#define USB_DEVICE_ID_ATEN_4PORTKVMC	0x2208
+
+#define USB_VENDOR_ID_BELKIN           0x050d
+#define USB_DEVICE_ID_FLIP_KVM         0x3201
+
+#define USB_VENDOR_ID_BERKSHIRE		0x0c98
+#define USB_DEVICE_ID_BERKSHIRE_PCWD	0x1140
+
+#define USB_VENDOR_ID_CHERRY		0x046a
+#define USB_DEVICE_ID_CHERRY_CYMOTION	0x0023
+
+#define USB_VENDOR_ID_CHIC		0x05fe
+#define USB_DEVICE_ID_CHIC_GAMEPAD	0x0014
+
+#define USB_VENDOR_ID_CIDC		0x1677
+
+#define USB_VENDOR_ID_CMEDIA		0x0d8c
+#define USB_DEVICE_ID_CM109		0x000e
+
+#define USB_VENDOR_ID_CODEMERCS		0x07c0
+#define USB_DEVICE_ID_CODEMERCS_IOW_FIRST	0x1500
+#define USB_DEVICE_ID_CODEMERCS_IOW_LAST	0x15ff
+
+#define USB_VENDOR_ID_CYGNAL		0x10c4
+#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X	0x818a
+
+#define USB_VENDOR_ID_CYPRESS		0x04b4
+#define USB_DEVICE_ID_CYPRESS_MOUSE	0x0001
+#define USB_DEVICE_ID_CYPRESS_HIDCOM	0x5500
+#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE	0x7417
+#define USB_DEVICE_ID_CYPRESS_BARCODE_1	0xde61
+#define USB_DEVICE_ID_CYPRESS_BARCODE_2	0xde64
+
+#define USB_VENDOR_ID_DELL		0x413c
+#define USB_DEVICE_ID_DELL_W7658	0x2005
+
+#define USB_VENDOR_ID_DELORME		0x1163
+#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
+#define USB_DEVICE_ID_DELORME_EM_LT20	0x0200
+
+#define USB_VENDOR_ID_DMI		0x0c0b
+#define USB_DEVICE_ID_DMI_ENC		0x5fab
+
+#define USB_VENDOR_ID_ELO		0x04E7
+#define USB_DEVICE_ID_ELO_TS2700	0x0020
+
+#define USB_VENDOR_ID_ESSENTIAL_REALITY	0x0d7f
+#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
+
+#define USB_VENDOR_ID_EZKEY 		0x0518
+#define USB_DEVICE_ID_BTC_8193		0x0002
+
+#define USB_VENDOR_ID_GAMERON		0x0810
+#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR	0x0001
+
+#define USB_VENDOR_ID_GENERAL_TOUCH	0x0dfc
+
+#define USB_VENDOR_ID_GLAB		0x06c2
+#define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038
+#define USB_DEVICE_ID_1_PHIDGETSERVO_30	0x0039
+#define USB_DEVICE_ID_0_0_4_IF_KIT	0x0040
+#define USB_DEVICE_ID_0_16_16_IF_KIT	0x0044
+#define USB_DEVICE_ID_8_8_8_IF_KIT	0x0045
+#define USB_DEVICE_ID_0_8_7_IF_KIT	0x0051
+#define USB_DEVICE_ID_0_8_8_IF_KIT	0x0053
+#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL	0x0058
+
+#define USB_VENDOR_ID_GOTOP		0x08f2
+#define USB_DEVICE_ID_SUPER_Q2		0x007f
+#define USB_DEVICE_ID_GOGOPEN		0x00ce
+#define USB_DEVICE_ID_PENPOWER		0x00f4
+
+#define USB_VENDOR_ID_GRETAGMACBETH	0x0971
+#define USB_DEVICE_ID_GRETAGMACBETH_HUEY	0x2005
+
+#define USB_VENDOR_ID_GRIFFIN		0x077d
+#define USB_DEVICE_ID_POWERMATE		0x0410
+#define USB_DEVICE_ID_SOUNDKNOB		0x04AA
+
+#define USB_VENDOR_ID_GTCO		0x078c
+#define USB_DEVICE_ID_GTCO_90		0x0090
+#define USB_DEVICE_ID_GTCO_100		0x0100
+#define USB_DEVICE_ID_GTCO_101		0x0101
+#define USB_DEVICE_ID_GTCO_103		0x0103
+#define USB_DEVICE_ID_GTCO_104		0x0104
+#define USB_DEVICE_ID_GTCO_105		0x0105
+#define USB_DEVICE_ID_GTCO_106		0x0106
+#define USB_DEVICE_ID_GTCO_107		0x0107
+#define USB_DEVICE_ID_GTCO_108		0x0108
+#define USB_DEVICE_ID_GTCO_200		0x0200
+#define USB_DEVICE_ID_GTCO_201		0x0201
+#define USB_DEVICE_ID_GTCO_202		0x0202
+#define USB_DEVICE_ID_GTCO_203		0x0203
+#define USB_DEVICE_ID_GTCO_204		0x0204
+#define USB_DEVICE_ID_GTCO_205		0x0205
+#define USB_DEVICE_ID_GTCO_206		0x0206
+#define USB_DEVICE_ID_GTCO_207		0x0207
+#define USB_DEVICE_ID_GTCO_300		0x0300
+#define USB_DEVICE_ID_GTCO_301		0x0301
+#define USB_DEVICE_ID_GTCO_302		0x0302
+#define USB_DEVICE_ID_GTCO_303		0x0303
+#define USB_DEVICE_ID_GTCO_304		0x0304
+#define USB_DEVICE_ID_GTCO_305		0x0305
+#define USB_DEVICE_ID_GTCO_306		0x0306
+#define USB_DEVICE_ID_GTCO_307		0x0307
+#define USB_DEVICE_ID_GTCO_308		0x0308
+#define USB_DEVICE_ID_GTCO_309		0x0309
+#define USB_DEVICE_ID_GTCO_400		0x0400
+#define USB_DEVICE_ID_GTCO_401		0x0401
+#define USB_DEVICE_ID_GTCO_402		0x0402
+#define USB_DEVICE_ID_GTCO_403		0x0403
+#define USB_DEVICE_ID_GTCO_404		0x0404
+#define USB_DEVICE_ID_GTCO_405		0x0405
+#define USB_DEVICE_ID_GTCO_500		0x0500
+#define USB_DEVICE_ID_GTCO_501		0x0501
+#define USB_DEVICE_ID_GTCO_502		0x0502
+#define USB_DEVICE_ID_GTCO_503		0x0503
+#define USB_DEVICE_ID_GTCO_504		0x0504
+#define USB_DEVICE_ID_GTCO_600		0x0600
+#define USB_DEVICE_ID_GTCO_601		0x0601
+#define USB_DEVICE_ID_GTCO_602		0x0602
+#define USB_DEVICE_ID_GTCO_603		0x0603
+#define USB_DEVICE_ID_GTCO_604		0x0604
+#define USB_DEVICE_ID_GTCO_605		0x0605
+#define USB_DEVICE_ID_GTCO_606		0x0606
+#define USB_DEVICE_ID_GTCO_607		0x0607
+#define USB_DEVICE_ID_GTCO_608		0x0608
+#define USB_DEVICE_ID_GTCO_609		0x0609
+#define USB_DEVICE_ID_GTCO_609		0x0609
+#define USB_DEVICE_ID_GTCO_1000		0x1000
+#define USB_DEVICE_ID_GTCO_1001		0x1001
+#define USB_DEVICE_ID_GTCO_1002		0x1002
+#define USB_DEVICE_ID_GTCO_1003		0x1003
+#define USB_DEVICE_ID_GTCO_1004		0x1004
+#define USB_DEVICE_ID_GTCO_1005		0x1005
+#define USB_DEVICE_ID_GTCO_1006		0x1006
+#define USB_DEVICE_ID_GTCO_1007		0x1007
+#define USB_VENDOR_ID_HAPP		0x078b
+#define USB_DEVICE_ID_UGCI_DRIVING	0x0010
+#define USB_DEVICE_ID_UGCI_FLYING	0x0020
+#define USB_DEVICE_ID_UGCI_FIGHTING	0x0030
+
+#define USB_VENDOR_ID_IMATION		0x0718
+#define USB_DEVICE_ID_DISC_STAKKA	0xd000
+
+#define USB_VENDOR_ID_KBGEAR		0x084e
+#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO	0x1001
+
+#define USB_VENDOR_ID_LD		0x0f11
+#define USB_DEVICE_ID_LD_CASSY		0x1000
+#define USB_DEVICE_ID_LD_POCKETCASSY	0x1010
+#define USB_DEVICE_ID_LD_MOBILECASSY	0x1020
+#define USB_DEVICE_ID_LD_JWM		0x1080
+#define USB_DEVICE_ID_LD_DMMP		0x1081
+#define USB_DEVICE_ID_LD_UMIP		0x1090
+#define USB_DEVICE_ID_LD_XRAY1		0x1100
+#define USB_DEVICE_ID_LD_XRAY2		0x1101
+#define USB_DEVICE_ID_LD_VIDEOCOM	0x1200
+#define USB_DEVICE_ID_LD_COM3LAB	0x2000
+#define USB_DEVICE_ID_LD_TELEPORT	0x2010
+#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020
+#define USB_DEVICE_ID_LD_POWERCONTROL	0x2030
+#define USB_DEVICE_ID_LD_MACHINETEST	0x2040
+
+#define USB_VENDOR_ID_LOGITECH		0x046d
+#define USB_DEVICE_ID_LOGITECH_RECEIVER	0xc101
+#define USB_DEVICE_ID_LOGITECH_HARMONY  0xc110
+#define USB_DEVICE_ID_LOGITECH_HARMONY_2 0xc111
+#define USB_DEVICE_ID_LOGITECH_HARMONY_3 0xc112
+#define USB_DEVICE_ID_LOGITECH_HARMONY_4 0xc113
+#define USB_DEVICE_ID_LOGITECH_HARMONY_5 0xc114
+#define USB_DEVICE_ID_LOGITECH_HARMONY_6 0xc115
+#define USB_DEVICE_ID_LOGITECH_HARMONY_7 0xc116
+#define USB_DEVICE_ID_LOGITECH_HARMONY_8 0xc117
+#define USB_DEVICE_ID_LOGITECH_HARMONY_9 0xc118
+#define USB_DEVICE_ID_LOGITECH_HARMONY_10 0xc119
+#define USB_DEVICE_ID_LOGITECH_HARMONY_11 0xc11a
+#define USB_DEVICE_ID_LOGITECH_HARMONY_12 0xc11b
+#define USB_DEVICE_ID_LOGITECH_HARMONY_13 0xc11c
+#define USB_DEVICE_ID_LOGITECH_HARMONY_14 0xc11d
+#define USB_DEVICE_ID_LOGITECH_HARMONY_15 0xc11e
+#define USB_DEVICE_ID_LOGITECH_HARMONY_16 0xc11f
+#define USB_DEVICE_ID_LOGITECH_HARMONY_17 0xc120
+#define USB_DEVICE_ID_LOGITECH_HARMONY_18 0xc121
+#define USB_DEVICE_ID_LOGITECH_HARMONY_19 0xc122
+#define USB_DEVICE_ID_LOGITECH_HARMONY_20 0xc123
+#define USB_DEVICE_ID_LOGITECH_HARMONY_21 0xc124
+#define USB_DEVICE_ID_LOGITECH_HARMONY_22 0xc125
+#define USB_DEVICE_ID_LOGITECH_HARMONY_23 0xc126
+#define USB_DEVICE_ID_LOGITECH_HARMONY_24 0xc127
+#define USB_DEVICE_ID_LOGITECH_HARMONY_25 0xc128
+#define USB_DEVICE_ID_LOGITECH_HARMONY_26 0xc129
+#define USB_DEVICE_ID_LOGITECH_HARMONY_27 0xc12a
+#define USB_DEVICE_ID_LOGITECH_HARMONY_28 0xc12b
+#define USB_DEVICE_ID_LOGITECH_HARMONY_29 0xc12c
+#define USB_DEVICE_ID_LOGITECH_HARMONY_30 0xc12d
+#define USB_DEVICE_ID_LOGITECH_HARMONY_31 0xc12e
+#define USB_DEVICE_ID_LOGITECH_HARMONY_32 0xc12f
+#define USB_DEVICE_ID_LOGITECH_HARMONY_33 0xc130
+#define USB_DEVICE_ID_LOGITECH_HARMONY_34 0xc131
+#define USB_DEVICE_ID_LOGITECH_HARMONY_35 0xc132
+#define USB_DEVICE_ID_LOGITECH_HARMONY_36 0xc133
+#define USB_DEVICE_ID_LOGITECH_HARMONY_37 0xc134
+#define USB_DEVICE_ID_LOGITECH_HARMONY_38 0xc135
+#define USB_DEVICE_ID_LOGITECH_HARMONY_39 0xc136
+#define USB_DEVICE_ID_LOGITECH_HARMONY_40 0xc137
+#define USB_DEVICE_ID_LOGITECH_HARMONY_41 0xc138
+#define USB_DEVICE_ID_LOGITECH_HARMONY_42 0xc139
+#define USB_DEVICE_ID_LOGITECH_HARMONY_43 0xc13a
+#define USB_DEVICE_ID_LOGITECH_HARMONY_44 0xc13b
+#define USB_DEVICE_ID_LOGITECH_HARMONY_45 0xc13c
+#define USB_DEVICE_ID_LOGITECH_HARMONY_46 0xc13d
+#define USB_DEVICE_ID_LOGITECH_HARMONY_47 0xc13e
+#define USB_DEVICE_ID_LOGITECH_HARMONY_48 0xc13f
+#define USB_DEVICE_ID_LOGITECH_HARMONY_49 0xc140
+#define USB_DEVICE_ID_LOGITECH_HARMONY_50 0xc141
+#define USB_DEVICE_ID_LOGITECH_HARMONY_51 0xc142
+#define USB_DEVICE_ID_LOGITECH_HARMONY_52 0xc143
+#define USB_DEVICE_ID_LOGITECH_HARMONY_53 0xc144
+#define USB_DEVICE_ID_LOGITECH_HARMONY_54 0xc145
+#define USB_DEVICE_ID_LOGITECH_HARMONY_55 0xc146
+#define USB_DEVICE_ID_LOGITECH_HARMONY_56 0xc147
+#define USB_DEVICE_ID_LOGITECH_HARMONY_57 0xc148
+#define USB_DEVICE_ID_LOGITECH_HARMONY_58 0xc149
+#define USB_DEVICE_ID_LOGITECH_HARMONY_59 0xc14a
+#define USB_DEVICE_ID_LOGITECH_HARMONY_60 0xc14b
+#define USB_DEVICE_ID_LOGITECH_HARMONY_61 0xc14c
+#define USB_DEVICE_ID_LOGITECH_HARMONY_62 0xc14d
+#define USB_DEVICE_ID_LOGITECH_HARMONY_63 0xc14e
+#define USB_DEVICE_ID_LOGITECH_HARMONY_64 0xc14f
+#define USB_DEVICE_ID_LOGITECH_EXTREME_3D	0xc215
+#define USB_DEVICE_ID_LOGITECH_WHEEL	0xc294
+#define USB_DEVICE_ID_LOGITECH_ELITE_KBD	0xc30a
+#define USB_DEVICE_ID_LOGITECH_KBD	0xc311
+#define USB_DEVICE_ID_S510_RECEIVER	0xc50c
+#define USB_DEVICE_ID_S510_RECEIVER_2	0xc517
+#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500	0xc512
+#define USB_DEVICE_ID_MX3000_RECEIVER	0xc513
+#define USB_DEVICE_ID_DINOVO_EDGE	0xc714
+#define USB_DEVICE_ID_DINOVO_MINI	0xc71f
+
+#define USB_VENDOR_ID_MCC		0x09db
+#define USB_DEVICE_ID_MCC_PMD1024LS	0x0076
+#define USB_DEVICE_ID_MCC_PMD1208LS	0x007a
+
+#define USB_VENDOR_ID_MGE		0x0463
+#define USB_DEVICE_ID_MGE_UPS		0xffff
+#define USB_DEVICE_ID_MGE_UPS1		0x0001
+
+#define USB_VENDOR_ID_MICROSOFT		0x045e
+#define USB_DEVICE_ID_SIDEWINDER_GV	0x003b
+#define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
+#define USB_DEVICE_ID_DESKTOP_RECV_1028 0x00f9
+#define USB_DEVICE_ID_MS_NE4K		0x00db
+#define USB_DEVICE_ID_MS_LK6K		0x00f9
+
+#define USB_VENDOR_ID_MONTEREY		0x0566
+#define USB_DEVICE_ID_GENIUS_KB29E	0x3004
+
+#define USB_VENDOR_ID_NCR		0x0404
+#define USB_DEVICE_ID_NCR_FIRST		0x0300
+#define USB_DEVICE_ID_NCR_LAST		0x03ff
+
+#define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
+#define USB_DEVICE_ID_N_S_HARMONY       0xc359
+
+#define USB_VENDOR_ID_NATSU             0x08b7
+#define USB_DEVICE_ID_NATSU_GAMEPAD     0x0001
+
+#define USB_VENDOR_ID_NEC		0x073e
+#define USB_DEVICE_ID_NEC_USB_GAME_PAD	0x0301
+
+#define USB_VENDOR_ID_ONTRAK		0x0a07
+#define USB_DEVICE_ID_ONTRAK_ADU100	0x0064
+
+#define USB_VENDOR_ID_PANJIT		0x134c
+
+#define USB_VENDOR_ID_PANTHERLORD	0x0810
+#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK	0x0001
+
+#define USB_VENDOR_ID_PETALYNX		0x18b1
+#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE	0x0037
+
+#define USB_VENDOR_ID_PLAYDOTCOM	0x0b43
+#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII	0x0003
+
+#define USB_VENDOR_ID_SAITEK		0x06a3
+#define USB_DEVICE_ID_SAITEK_RUMBLEPAD	0xff17
+
+#define USB_VENDOR_ID_SAMSUNG		0x0419
+#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE	0x0001
+
+#define USB_VENDOR_ID_SONY			0x054c
+#define USB_DEVICE_ID_SONY_PS3_CONTROLLER	0x0268
+
+#define USB_VENDOR_ID_SUN		0x0430
+#define USB_DEVICE_ID_RARITAN_KVM_DONGLE	0xcdab
+
+#define USB_VENDOR_ID_SUNPLUS		0x04fc
+#define USB_DEVICE_ID_SUNPLUS_WDESKTOP	0x05d8
+
+#define USB_VENDOR_ID_TOPMAX		0x0663
+#define USB_DEVICE_ID_TOPMAX_COBRAPAD	0x0103
+
+#define USB_VENDOR_ID_TURBOX		0x062a
+#define USB_DEVICE_ID_TURBOX_KEYBOARD	0x0201
+
+#define USB_VENDOR_ID_VERNIER		0x08f7
+#define USB_DEVICE_ID_VERNIER_LABPRO	0x0001
+#define USB_DEVICE_ID_VERNIER_GOTEMP	0x0002
+#define USB_DEVICE_ID_VERNIER_SKIP	0x0003
+#define USB_DEVICE_ID_VERNIER_CYCLOPS	0x0004
+#define USB_DEVICE_ID_VERNIER_LCSPEC	0x0006
+
+#define USB_VENDOR_ID_WACOM		0x056a
+
+#define USB_VENDOR_ID_WISEGROUP		0x0925
+#define USB_DEVICE_ID_1_PHIDGETSERVO_20	0x8101
+#define USB_DEVICE_ID_4_PHIDGETSERVO_20	0x8104
+#define USB_DEVICE_ID_8_8_4_IF_KIT	0x8201
+#define USB_DEVICE_ID_QUAD_USB_JOYPAD	0x8800
+#define USB_DEVICE_ID_DUAL_USB_JOYPAD	0x8866
+
+#define USB_VENDOR_ID_WISEGROUP_LTD	0x6677
+#define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
+
+#define USB_VENDOR_ID_YEALINK		0x6993
+#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K	0xb001
+
+#define USB_VENDOR_ID_KYE		0x0458
+#define USB_DEVICE_ID_KYE_GPEN_560	0x5003
+
+#endif
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 6530fc4..9e32a2f 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -17,407 +17,7 @@
 
 #include <linux/hid.h>
 
-#define USB_VENDOR_ID_A4TECH		0x09da
-#define USB_DEVICE_ID_A4TECH_WCP32PU	0x0006
-#define USB_DEVICE_ID_A4TECH_X5_005D	0x000a
-
-#define USB_VENDOR_ID_AASHIMA		0x06d6
-#define USB_DEVICE_ID_AASHIMA_GAMEPAD	0x0025
-#define USB_DEVICE_ID_AASHIMA_PREDATOR	0x0026
-
-#define USB_VENDOR_ID_ACECAD		0x0460
-#define USB_DEVICE_ID_ACECAD_FLAIR	0x0004
-#define USB_DEVICE_ID_ACECAD_302	0x0008
-
-#define USB_VENDOR_ID_ADS_TECH 		0x06e1
-#define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X	0xa155
-
-#define USB_VENDOR_ID_AFATECH		0x15a4
-#define USB_DEVICE_ID_AFATECH_AF9016	0x9016
-
-#define USB_VENDOR_ID_AIPTEK		0x08ca
-#define USB_DEVICE_ID_AIPTEK_01		0x0001
-#define USB_DEVICE_ID_AIPTEK_10		0x0010
-#define USB_DEVICE_ID_AIPTEK_20		0x0020
-#define USB_DEVICE_ID_AIPTEK_21		0x0021
-#define USB_DEVICE_ID_AIPTEK_22		0x0022
-#define USB_DEVICE_ID_AIPTEK_23		0x0023
-#define USB_DEVICE_ID_AIPTEK_24		0x0024
-
-#define USB_VENDOR_ID_AIRCABLE		0x16CA
-#define USB_DEVICE_ID_AIRCABLE1		0x1502
-
-#define USB_VENDOR_ID_ALCOR		0x058f
-#define USB_DEVICE_ID_ALCOR_USBRS232	0x9720
-
-#define USB_VENDOR_ID_ALPS		0x0433
-#define USB_DEVICE_ID_IBM_GAMEPAD	0x1101
-
-#define USB_VENDOR_ID_APPLE		0x05ac
-#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE	0x0304
-#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI	0x020e
-#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO	0x020f
-#define USB_DEVICE_ID_APPLE_GEYSER_ANSI	0x0214
-#define USB_DEVICE_ID_APPLE_GEYSER_ISO	0x0215
-#define USB_DEVICE_ID_APPLE_GEYSER_JIS	0x0216
-#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI	0x0217
-#define USB_DEVICE_ID_APPLE_GEYSER3_ISO	0x0218
-#define USB_DEVICE_ID_APPLE_GEYSER3_JIS	0x0219
-#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI	0x021a
-#define USB_DEVICE_ID_APPLE_GEYSER4_ISO	0x021b
-#define USB_DEVICE_ID_APPLE_GEYSER4_JIS	0x021c
-#define USB_DEVICE_ID_APPLE_ALU_ANSI	0x0220
-#define USB_DEVICE_ID_APPLE_ALU_ISO	0x0221
-#define USB_DEVICE_ID_APPLE_ALU_JIS	0x0222
-#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI    0x0229
-#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO     0x022a
-#define USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS     0x022b
-#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI  0x022c
-#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO   0x022d
-#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS   0x022e
-#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY	0x030a
-#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY	0x030b
-#define USB_DEVICE_ID_APPLE_IRCONTROL4	0x8242
-
-#define USB_VENDOR_ID_ASUS		0x0b05
-#define USB_DEVICE_ID_ASUS_LCM		0x1726
-
-#define USB_VENDOR_ID_ATEN		0x0557
-#define USB_DEVICE_ID_ATEN_UC100KM	0x2004
-#define USB_DEVICE_ID_ATEN_CS124U	0x2202
-#define USB_DEVICE_ID_ATEN_2PORTKVM	0x2204
-#define USB_DEVICE_ID_ATEN_4PORTKVM	0x2205
-#define USB_DEVICE_ID_ATEN_4PORTKVMC	0x2208
-
-#define USB_VENDOR_ID_BELKIN           0x050d
-#define USB_DEVICE_ID_FLIP_KVM         0x3201
-
-#define USB_VENDOR_ID_BERKSHIRE		0x0c98
-#define USB_DEVICE_ID_BERKSHIRE_PCWD	0x1140
-
-#define USB_VENDOR_ID_CHERRY		0x046a
-#define USB_DEVICE_ID_CHERRY_CYMOTION	0x0023
-
-#define USB_VENDOR_ID_CHIC		0x05fe
-#define USB_DEVICE_ID_CHIC_GAMEPAD	0x0014
-
-#define USB_VENDOR_ID_CIDC		0x1677
-
-#define USB_VENDOR_ID_CMEDIA		0x0d8c
-#define USB_DEVICE_ID_CM109		0x000e
-
-#define USB_VENDOR_ID_CODEMERCS		0x07c0
-#define USB_DEVICE_ID_CODEMERCS_IOW_FIRST	0x1500
-#define USB_DEVICE_ID_CODEMERCS_IOW_LAST	0x15ff
-
-#define USB_VENDOR_ID_CYGNAL		0x10c4
-#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X	0x818a
-
-#define USB_VENDOR_ID_CYPRESS		0x04b4
-#define USB_DEVICE_ID_CYPRESS_MOUSE	0x0001
-#define USB_DEVICE_ID_CYPRESS_HIDCOM	0x5500
-#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE	0x7417
-#define USB_DEVICE_ID_CYPRESS_BARCODE_1	0xde61
-#define USB_DEVICE_ID_CYPRESS_BARCODE_2	0xde64
-
-#define USB_VENDOR_ID_DELL		0x413c
-#define USB_DEVICE_ID_DELL_W7658	0x2005
-
-#define USB_VENDOR_ID_DELORME		0x1163
-#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
-#define USB_DEVICE_ID_DELORME_EM_LT20	0x0200
-
-#define USB_VENDOR_ID_DMI		0x0c0b
-#define USB_DEVICE_ID_DMI_ENC		0x5fab
-
-#define USB_VENDOR_ID_ELO		0x04E7
-#define USB_DEVICE_ID_ELO_TS2700	0x0020
-
-#define USB_VENDOR_ID_ESSENTIAL_REALITY	0x0d7f
-#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
-
-#define USB_VENDOR_ID_EZKEY 		0x0518
-#define USB_DEVICE_ID_BTC_8193		0x0002
-
-#define USB_VENDOR_ID_GAMERON		0x0810
-#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR	0x0001
-
-#define USB_VENDOR_ID_GENERAL_TOUCH	0x0dfc
-
-#define USB_VENDOR_ID_GLAB		0x06c2
-#define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038
-#define USB_DEVICE_ID_1_PHIDGETSERVO_30	0x0039
-#define USB_DEVICE_ID_0_0_4_IF_KIT	0x0040
-#define USB_DEVICE_ID_0_16_16_IF_KIT	0x0044
-#define USB_DEVICE_ID_8_8_8_IF_KIT	0x0045
-#define USB_DEVICE_ID_0_8_7_IF_KIT	0x0051
-#define USB_DEVICE_ID_0_8_8_IF_KIT	0x0053
-#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL	0x0058
-
-#define USB_VENDOR_ID_GOTOP		0x08f2
-#define USB_DEVICE_ID_SUPER_Q2		0x007f
-#define USB_DEVICE_ID_GOGOPEN		0x00ce
-#define USB_DEVICE_ID_PENPOWER		0x00f4
-
-#define USB_VENDOR_ID_GRETAGMACBETH	0x0971
-#define USB_DEVICE_ID_GRETAGMACBETH_HUEY	0x2005
-
-#define USB_VENDOR_ID_GRIFFIN		0x077d
-#define USB_DEVICE_ID_POWERMATE		0x0410
-#define USB_DEVICE_ID_SOUNDKNOB		0x04AA
-
-#define USB_VENDOR_ID_GTCO		0x078c
-#define USB_DEVICE_ID_GTCO_90		0x0090
-#define USB_DEVICE_ID_GTCO_100		0x0100
-#define USB_DEVICE_ID_GTCO_101		0x0101
-#define USB_DEVICE_ID_GTCO_103		0x0103
-#define USB_DEVICE_ID_GTCO_104		0x0104
-#define USB_DEVICE_ID_GTCO_105		0x0105
-#define USB_DEVICE_ID_GTCO_106		0x0106
-#define USB_DEVICE_ID_GTCO_107		0x0107
-#define USB_DEVICE_ID_GTCO_108		0x0108
-#define USB_DEVICE_ID_GTCO_200		0x0200
-#define USB_DEVICE_ID_GTCO_201		0x0201
-#define USB_DEVICE_ID_GTCO_202		0x0202
-#define USB_DEVICE_ID_GTCO_203		0x0203
-#define USB_DEVICE_ID_GTCO_204		0x0204
-#define USB_DEVICE_ID_GTCO_205		0x0205
-#define USB_DEVICE_ID_GTCO_206		0x0206
-#define USB_DEVICE_ID_GTCO_207		0x0207
-#define USB_DEVICE_ID_GTCO_300		0x0300
-#define USB_DEVICE_ID_GTCO_301		0x0301
-#define USB_DEVICE_ID_GTCO_302		0x0302
-#define USB_DEVICE_ID_GTCO_303		0x0303
-#define USB_DEVICE_ID_GTCO_304		0x0304
-#define USB_DEVICE_ID_GTCO_305		0x0305
-#define USB_DEVICE_ID_GTCO_306		0x0306
-#define USB_DEVICE_ID_GTCO_307		0x0307
-#define USB_DEVICE_ID_GTCO_308		0x0308
-#define USB_DEVICE_ID_GTCO_309		0x0309
-#define USB_DEVICE_ID_GTCO_400		0x0400
-#define USB_DEVICE_ID_GTCO_401		0x0401
-#define USB_DEVICE_ID_GTCO_402		0x0402
-#define USB_DEVICE_ID_GTCO_403		0x0403
-#define USB_DEVICE_ID_GTCO_404		0x0404
-#define USB_DEVICE_ID_GTCO_405		0x0405
-#define USB_DEVICE_ID_GTCO_500		0x0500
-#define USB_DEVICE_ID_GTCO_501		0x0501
-#define USB_DEVICE_ID_GTCO_502		0x0502
-#define USB_DEVICE_ID_GTCO_503		0x0503
-#define USB_DEVICE_ID_GTCO_504		0x0504
-#define USB_DEVICE_ID_GTCO_600		0x0600
-#define USB_DEVICE_ID_GTCO_601		0x0601
-#define USB_DEVICE_ID_GTCO_602		0x0602
-#define USB_DEVICE_ID_GTCO_603		0x0603
-#define USB_DEVICE_ID_GTCO_604		0x0604
-#define USB_DEVICE_ID_GTCO_605		0x0605
-#define USB_DEVICE_ID_GTCO_606		0x0606
-#define USB_DEVICE_ID_GTCO_607		0x0607
-#define USB_DEVICE_ID_GTCO_608		0x0608
-#define USB_DEVICE_ID_GTCO_609		0x0609
-#define USB_DEVICE_ID_GTCO_609		0x0609
-#define USB_DEVICE_ID_GTCO_1000		0x1000
-#define USB_DEVICE_ID_GTCO_1001		0x1001
-#define USB_DEVICE_ID_GTCO_1002		0x1002
-#define USB_DEVICE_ID_GTCO_1003		0x1003
-#define USB_DEVICE_ID_GTCO_1004		0x1004
-#define USB_DEVICE_ID_GTCO_1005		0x1005
-#define USB_DEVICE_ID_GTCO_1006		0x1006
-#define USB_DEVICE_ID_GTCO_1007		0x1007
-#define USB_VENDOR_ID_HAPP		0x078b
-#define USB_DEVICE_ID_UGCI_DRIVING	0x0010
-#define USB_DEVICE_ID_UGCI_FLYING	0x0020
-#define USB_DEVICE_ID_UGCI_FIGHTING	0x0030
-
-#define USB_VENDOR_ID_IMATION		0x0718
-#define USB_DEVICE_ID_DISC_STAKKA	0xd000
-
-#define USB_VENDOR_ID_KBGEAR		0x084e
-#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO	0x1001
-
-#define USB_VENDOR_ID_LD		0x0f11
-#define USB_DEVICE_ID_LD_CASSY		0x1000
-#define USB_DEVICE_ID_LD_POCKETCASSY	0x1010
-#define USB_DEVICE_ID_LD_MOBILECASSY	0x1020
-#define USB_DEVICE_ID_LD_JWM		0x1080
-#define USB_DEVICE_ID_LD_DMMP		0x1081
-#define USB_DEVICE_ID_LD_UMIP		0x1090
-#define USB_DEVICE_ID_LD_XRAY1		0x1100
-#define USB_DEVICE_ID_LD_XRAY2		0x1101
-#define USB_DEVICE_ID_LD_VIDEOCOM	0x1200
-#define USB_DEVICE_ID_LD_COM3LAB	0x2000
-#define USB_DEVICE_ID_LD_TELEPORT	0x2010
-#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020
-#define USB_DEVICE_ID_LD_POWERCONTROL	0x2030
-#define USB_DEVICE_ID_LD_MACHINETEST	0x2040
-
-#define USB_VENDOR_ID_LOGITECH		0x046d
-#define USB_DEVICE_ID_LOGITECH_RECEIVER	0xc101
-#define USB_DEVICE_ID_LOGITECH_HARMONY  0xc110
-#define USB_DEVICE_ID_LOGITECH_HARMONY_2 0xc111
-#define USB_DEVICE_ID_LOGITECH_HARMONY_3 0xc112
-#define USB_DEVICE_ID_LOGITECH_HARMONY_4 0xc113
-#define USB_DEVICE_ID_LOGITECH_HARMONY_5 0xc114
-#define USB_DEVICE_ID_LOGITECH_HARMONY_6 0xc115
-#define USB_DEVICE_ID_LOGITECH_HARMONY_7 0xc116
-#define USB_DEVICE_ID_LOGITECH_HARMONY_8 0xc117
-#define USB_DEVICE_ID_LOGITECH_HARMONY_9 0xc118
-#define USB_DEVICE_ID_LOGITECH_HARMONY_10 0xc119
-#define USB_DEVICE_ID_LOGITECH_HARMONY_11 0xc11a
-#define USB_DEVICE_ID_LOGITECH_HARMONY_12 0xc11b
-#define USB_DEVICE_ID_LOGITECH_HARMONY_13 0xc11c
-#define USB_DEVICE_ID_LOGITECH_HARMONY_14 0xc11d
-#define USB_DEVICE_ID_LOGITECH_HARMONY_15 0xc11e
-#define USB_DEVICE_ID_LOGITECH_HARMONY_16 0xc11f
-#define USB_DEVICE_ID_LOGITECH_HARMONY_17 0xc120
-#define USB_DEVICE_ID_LOGITECH_HARMONY_18 0xc121
-#define USB_DEVICE_ID_LOGITECH_HARMONY_19 0xc122
-#define USB_DEVICE_ID_LOGITECH_HARMONY_20 0xc123
-#define USB_DEVICE_ID_LOGITECH_HARMONY_21 0xc124
-#define USB_DEVICE_ID_LOGITECH_HARMONY_22 0xc125
-#define USB_DEVICE_ID_LOGITECH_HARMONY_23 0xc126
-#define USB_DEVICE_ID_LOGITECH_HARMONY_24 0xc127
-#define USB_DEVICE_ID_LOGITECH_HARMONY_25 0xc128
-#define USB_DEVICE_ID_LOGITECH_HARMONY_26 0xc129
-#define USB_DEVICE_ID_LOGITECH_HARMONY_27 0xc12a
-#define USB_DEVICE_ID_LOGITECH_HARMONY_28 0xc12b
-#define USB_DEVICE_ID_LOGITECH_HARMONY_29 0xc12c
-#define USB_DEVICE_ID_LOGITECH_HARMONY_30 0xc12d
-#define USB_DEVICE_ID_LOGITECH_HARMONY_31 0xc12e
-#define USB_DEVICE_ID_LOGITECH_HARMONY_32 0xc12f
-#define USB_DEVICE_ID_LOGITECH_HARMONY_33 0xc130
-#define USB_DEVICE_ID_LOGITECH_HARMONY_34 0xc131
-#define USB_DEVICE_ID_LOGITECH_HARMONY_35 0xc132
-#define USB_DEVICE_ID_LOGITECH_HARMONY_36 0xc133
-#define USB_DEVICE_ID_LOGITECH_HARMONY_37 0xc134
-#define USB_DEVICE_ID_LOGITECH_HARMONY_38 0xc135
-#define USB_DEVICE_ID_LOGITECH_HARMONY_39 0xc136
-#define USB_DEVICE_ID_LOGITECH_HARMONY_40 0xc137
-#define USB_DEVICE_ID_LOGITECH_HARMONY_41 0xc138
-#define USB_DEVICE_ID_LOGITECH_HARMONY_42 0xc139
-#define USB_DEVICE_ID_LOGITECH_HARMONY_43 0xc13a
-#define USB_DEVICE_ID_LOGITECH_HARMONY_44 0xc13b
-#define USB_DEVICE_ID_LOGITECH_HARMONY_45 0xc13c
-#define USB_DEVICE_ID_LOGITECH_HARMONY_46 0xc13d
-#define USB_DEVICE_ID_LOGITECH_HARMONY_47 0xc13e
-#define USB_DEVICE_ID_LOGITECH_HARMONY_48 0xc13f
-#define USB_DEVICE_ID_LOGITECH_HARMONY_49 0xc140
-#define USB_DEVICE_ID_LOGITECH_HARMONY_50 0xc141
-#define USB_DEVICE_ID_LOGITECH_HARMONY_51 0xc142
-#define USB_DEVICE_ID_LOGITECH_HARMONY_52 0xc143
-#define USB_DEVICE_ID_LOGITECH_HARMONY_53 0xc144
-#define USB_DEVICE_ID_LOGITECH_HARMONY_54 0xc145
-#define USB_DEVICE_ID_LOGITECH_HARMONY_55 0xc146
-#define USB_DEVICE_ID_LOGITECH_HARMONY_56 0xc147
-#define USB_DEVICE_ID_LOGITECH_HARMONY_57 0xc148
-#define USB_DEVICE_ID_LOGITECH_HARMONY_58 0xc149
-#define USB_DEVICE_ID_LOGITECH_HARMONY_59 0xc14a
-#define USB_DEVICE_ID_LOGITECH_HARMONY_60 0xc14b
-#define USB_DEVICE_ID_LOGITECH_HARMONY_61 0xc14c
-#define USB_DEVICE_ID_LOGITECH_HARMONY_62 0xc14d
-#define USB_DEVICE_ID_LOGITECH_HARMONY_63 0xc14e
-#define USB_DEVICE_ID_LOGITECH_HARMONY_64 0xc14f
-#define USB_DEVICE_ID_LOGITECH_EXTREME_3D	0xc215
-#define USB_DEVICE_ID_LOGITECH_WHEEL	0xc294
-#define USB_DEVICE_ID_LOGITECH_ELITE_KBD	0xc30a
-#define USB_DEVICE_ID_LOGITECH_KBD	0xc311
-#define USB_DEVICE_ID_S510_RECEIVER	0xc50c
-#define USB_DEVICE_ID_S510_RECEIVER_2	0xc517
-#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500	0xc512
-#define USB_DEVICE_ID_MX3000_RECEIVER	0xc513
-#define USB_DEVICE_ID_DINOVO_EDGE	0xc714
-#define USB_DEVICE_ID_DINOVO_MINI	0xc71f
-
-#define USB_VENDOR_ID_MCC		0x09db
-#define USB_DEVICE_ID_MCC_PMD1024LS	0x0076
-#define USB_DEVICE_ID_MCC_PMD1208LS	0x007a
-
-#define USB_VENDOR_ID_MGE		0x0463
-#define USB_DEVICE_ID_MGE_UPS		0xffff
-#define USB_DEVICE_ID_MGE_UPS1		0x0001
-
-#define USB_VENDOR_ID_MICROSOFT		0x045e
-#define USB_DEVICE_ID_SIDEWINDER_GV	0x003b
-#define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
-#define USB_DEVICE_ID_DESKTOP_RECV_1028 0x00f9
-#define USB_DEVICE_ID_MS_NE4K		0x00db
-#define USB_DEVICE_ID_MS_LK6K		0x00f9
-
-#define USB_VENDOR_ID_MONTEREY		0x0566
-#define USB_DEVICE_ID_GENIUS_KB29E	0x3004
-
-#define USB_VENDOR_ID_NCR		0x0404
-#define USB_DEVICE_ID_NCR_FIRST		0x0300
-#define USB_DEVICE_ID_NCR_LAST		0x03ff
-
-#define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
-#define USB_DEVICE_ID_N_S_HARMONY       0xc359
-
-#define USB_VENDOR_ID_NATSU             0x08b7
-#define USB_DEVICE_ID_NATSU_GAMEPAD     0x0001
-
-#define USB_VENDOR_ID_NEC		0x073e
-#define USB_DEVICE_ID_NEC_USB_GAME_PAD	0x0301
-
-#define USB_VENDOR_ID_ONTRAK		0x0a07
-#define USB_DEVICE_ID_ONTRAK_ADU100	0x0064
-
-#define USB_VENDOR_ID_PANJIT		0x134c
-
-#define USB_VENDOR_ID_PANTHERLORD	0x0810
-#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK	0x0001
-
-#define USB_VENDOR_ID_PETALYNX		0x18b1
-#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE	0x0037
-
-#define USB_VENDOR_ID_PLAYDOTCOM	0x0b43
-#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII	0x0003
-
-#define USB_VENDOR_ID_SAITEK		0x06a3
-#define USB_DEVICE_ID_SAITEK_RUMBLEPAD	0xff17
-
-#define USB_VENDOR_ID_SAMSUNG		0x0419
-#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE	0x0001
-
-#define USB_VENDOR_ID_SONY			0x054c
-#define USB_DEVICE_ID_SONY_PS3_CONTROLLER	0x0268
-
-#define USB_VENDOR_ID_SUN		0x0430
-#define USB_DEVICE_ID_RARITAN_KVM_DONGLE	0xcdab
-
-#define USB_VENDOR_ID_SUNPLUS		0x04fc
-#define USB_DEVICE_ID_SUNPLUS_WDESKTOP	0x05d8
-
-#define USB_VENDOR_ID_TOPMAX		0x0663
-#define USB_DEVICE_ID_TOPMAX_COBRAPAD	0x0103
-
-#define USB_VENDOR_ID_TURBOX		0x062a
-#define USB_DEVICE_ID_TURBOX_KEYBOARD	0x0201
-
-#define USB_VENDOR_ID_VERNIER		0x08f7
-#define USB_DEVICE_ID_VERNIER_LABPRO	0x0001
-#define USB_DEVICE_ID_VERNIER_GOTEMP	0x0002
-#define USB_DEVICE_ID_VERNIER_SKIP	0x0003
-#define USB_DEVICE_ID_VERNIER_CYCLOPS	0x0004
-#define USB_DEVICE_ID_VERNIER_LCSPEC	0x0006
-
-#define USB_VENDOR_ID_WACOM		0x056a
-
-#define USB_VENDOR_ID_WISEGROUP		0x0925
-#define USB_DEVICE_ID_1_PHIDGETSERVO_20	0x8101
-#define USB_DEVICE_ID_4_PHIDGETSERVO_20	0x8104
-#define USB_DEVICE_ID_8_8_4_IF_KIT	0x8201
-#define USB_DEVICE_ID_QUAD_USB_JOYPAD	0x8800
-#define USB_DEVICE_ID_DUAL_USB_JOYPAD	0x8866
-
-#define USB_VENDOR_ID_WISEGROUP_LTD	0x6677
-#define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
-
-#define USB_VENDOR_ID_YEALINK		0x6993
-#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K	0xb001
-
-#define USB_VENDOR_ID_KYE		0x0458
-#define USB_DEVICE_ID_KYE_GPEN_560	0x5003
+#include "../hid-ids.h"
 
 /*
  * Alphabetically sorted blacklist by quirk type.
-- 
1.5.4.4


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC 4/8] HID: move usage input mapping to hid.h
  2008-04-04 20:35 Hid bus #2 Jiri Slaby
                   ` (2 preceding siblings ...)
  2008-04-04 20:35 ` [RFC 3/8] HID: move ids into separate file Jiri Slaby
@ 2008-04-04 20:35 ` Jiri Slaby
  2008-04-04 20:35 ` [RFC 5/8] HID: move logitech report quirks Jiri Slaby
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-04 20:35 UTC (permalink / raw)
  To: linux-input; +Cc: jkosina, marcel, dmitry.torokhov, Jiri Slaby, Jiri Slaby

This mapping are currently used on 2 placces and will be needed by more
quirk drivers, so move them to hid.h to allow them to use it.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/hid/hid-input-quirks.c |   71 ++++++++++++++++++++-------------------
 drivers/hid/hid-input.c        |   16 +++++----
 include/linux/hid.h            |   55 ++++++++++++++++++++++++++++++-
 3 files changed, 99 insertions(+), 43 deletions(-)

diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c
index 4c2052c..51ae184 100644
--- a/drivers/hid/hid-input-quirks.c
+++ b/drivers/hid/hid-input-quirks.c
@@ -16,16 +16,14 @@
 #include <linux/input.h>
 #include <linux/hid.h>
 
-#define map_abs(c)      do { usage->code = c; usage->type = EV_ABS; *bit = input->absbit; *max = ABS_MAX; } while (0)
-#define map_rel(c)      do { usage->code = c; usage->type = EV_REL; *bit = input->relbit; *max = REL_MAX; } while (0)
-#define map_key(c)      do { usage->code = c; usage->type = EV_KEY; *bit = input->keybit; *max = KEY_MAX; } while (0)
-#define map_led(c)      do { usage->code = c; usage->type = EV_LED; *bit = input->ledbit; *max = LED_MAX; } while (0)
+#define map_rel(c)	hid_map_usage(hidinput, usage, bit, max, EV_REL, (c))
+#define map_key(c)	hid_map_usage(hidinput, usage, bit, max, EV_KEY, (c))
 
-#define map_abs_clear(c)        do { map_abs(c); clear_bit(c, *bit); } while (0)
-#define map_key_clear(c)        do { map_key(c); clear_bit(c, *bit); } while (0)
+#define map_key_clear(c)	hid_map_usage_clear(hidinput, usage, bit, \
+		max, EV_KEY, (c))
 
-static int quirk_belkin_wkbd(struct hid_usage *usage, struct input_dev *input,
-			      unsigned long **bit, int *max)
+static int quirk_belkin_wkbd(struct hid_usage *usage,
+		struct hid_input *hidinput, unsigned long **bit, int *max)
 {
 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
 		return 0;
@@ -40,8 +38,8 @@ static int quirk_belkin_wkbd(struct hid_usage *usage, struct input_dev *input,
 	return 1;
 }
 
-static int quirk_cherry_cymotion(struct hid_usage *usage, struct input_dev *input,
-			      unsigned long **bit, int *max)
+static int quirk_cherry_cymotion(struct hid_usage *usage,
+		struct hid_input *hidinput, unsigned long **bit, int *max)
 {
 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
 		return 0;
@@ -56,13 +54,13 @@ static int quirk_cherry_cymotion(struct hid_usage *usage, struct input_dev *inpu
 	return 1;
 }
 
-static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_dev *input,
-			      unsigned long **bit, int *max)
+static int quirk_logitech_ultrax_remote(struct hid_usage *usage,
+		struct hid_input *hidinput, unsigned long **bit, int *max)
 {
 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
 		return 0;
 
-	set_bit(EV_REP, input->evbit);
+	set_bit(EV_REP, hidinput->input->evbit);
 	switch(usage->hid & HID_USAGE) {
 		/* Reported on Logitech Ultra X Media Remote */
 		case 0x004: map_key_clear(KEY_AGAIN);		break;
@@ -89,13 +87,13 @@ static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_de
 	return 1;
 }
 
-static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev *input,
-			      unsigned long **bit, int *max)
+static int quirk_chicony_tactical_pad(struct hid_usage *usage,
+		struct hid_input *hidinput, unsigned long **bit, int *max)
 {
 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
 		return 0;
 
-	set_bit(EV_REP, input->evbit);
+	set_bit(EV_REP, hidinput->input->evbit);
 	switch (usage->hid & HID_USAGE) {
 		case 0xff01: map_key_clear(BTN_1);		break;
 		case 0xff02: map_key_clear(BTN_2);		break;
@@ -114,9 +112,11 @@ static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev
 	return 1;
 }
 
-static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, struct input_dev *input,
-			      unsigned long **bit, int *max)
+static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage,
+		struct hid_input *hidinput, unsigned long **bit, int *max)
 {
+	struct input_dev *input = hidinput->input;
+
 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
 		return 0;
 
@@ -137,13 +137,13 @@ static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, struct input_dev
 	return 1;
 }
 
-static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_dev *input,
-			      unsigned long **bit, int *max)
+static int quirk_microsoft_presenter_8k(struct hid_usage *usage,
+		struct hid_input *hidinput, unsigned long **bit, int *max)
 {
 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
 		return 0;
 
-	set_bit(EV_REP, input->evbit);
+	set_bit(EV_REP, hidinput->input->evbit);
 	switch(usage->hid & HID_USAGE) {
 		case 0xfd08: map_key_clear(KEY_FORWARD);	break;
 		case 0xfd09: map_key_clear(KEY_BACK);		break;
@@ -156,8 +156,8 @@ static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_de
 	return 1;
 }
 
-static int quirk_petalynx_remote(struct hid_usage *usage, struct input_dev *input,
-			      unsigned long **bit, int *max)
+static int quirk_petalynx_remote(struct hid_usage *usage,
+		struct hid_input *hidinput, unsigned long **bit, int *max)
 {
 	if (((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) &&
 			((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER))
@@ -184,8 +184,8 @@ static int quirk_petalynx_remote(struct hid_usage *usage, struct input_dev *inpu
 	return 1;
 }
 
-static int quirk_logitech_wireless(struct hid_usage *usage, struct input_dev *input,
-			      unsigned long **bit, int *max)
+static int quirk_logitech_wireless(struct hid_usage *usage,
+		struct hid_input *hidinput, unsigned long **bit, int *max)
 {
 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
 		return 0;
@@ -236,8 +236,8 @@ static int quirk_logitech_wireless(struct hid_usage *usage, struct input_dev *in
 	return 1;
 }
 
-static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *input,
-			      unsigned long **bit, int *max)
+static int quirk_cherry_genius_29e(struct hid_usage *usage,
+		struct hid_input *hidinput, unsigned long **bit, int *max)
 {
 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
 		return 0;
@@ -254,7 +254,7 @@ static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *in
 	return 1;
 }
 
-static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input,
+static int quirk_btc_8193(struct hid_usage *usage, struct hid_input *hidinput,
 			      unsigned long **bit, int *max)
 {
 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
@@ -276,8 +276,8 @@ static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input,
 	return 1;
 }
 
-static int quirk_sunplus_wdesktop(struct hid_usage *usage, struct input_dev *input,
-			      unsigned long **bit, int *max)
+static int quirk_sunplus_wdesktop(struct hid_usage *usage,
+		struct hid_input *hidinput, unsigned long **bit, int *max)
 {
 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
 		return 0;
@@ -327,7 +327,8 @@ static int quirk_sunplus_wdesktop(struct hid_usage *usage, struct input_dev *inp
 static const struct hid_input_blacklist {
 	__u16 idVendor;
 	__u16 idProduct;
-	int (*quirk)(struct hid_usage *, struct input_dev *, unsigned long **, int *);
+	int (*quirk)(struct hid_usage *, struct hid_input *, unsigned long **,
+			int *);
 } hid_input_blacklist[] = {
 	{ VENDOR_ID_BELKIN, DEVICE_ID_BELKIN_WIRELESS_KEYBOARD, quirk_belkin_wkbd },
 
@@ -357,16 +358,16 @@ static const struct hid_input_blacklist {
 };
 
 int hidinput_mapping_quirks(struct hid_usage *usage, 
-				   struct input_dev *input, 
-				   unsigned long **bit, int *max)
+		struct hid_input *hi, unsigned long **bit, int *max)
 {
-	struct hid_device *device = input_get_drvdata(input);
+	struct hid_device *device = input_get_drvdata(hi->input);
 	int i = 0;
 	
 	while (hid_input_blacklist[i].quirk) {
 		if (hid_input_blacklist[i].idVendor == device->vendor &&
 				hid_input_blacklist[i].idProduct == device->product)
-			return hid_input_blacklist[i].quirk(usage, input, bit, max);
+			return hid_input_blacklist[i].quirk(usage, hi, bit,
+					max);
 		i++;
 	}
 	return 0;
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 5f1a91a..5439e76 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -78,13 +78,15 @@ static const struct {
 	__s32 y;
 }  hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
 
-#define map_abs(c)	do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; } while (0)
-#define map_rel(c)	do { usage->code = c; usage->type = EV_REL; bit = input->relbit; max = REL_MAX; } while (0)
-#define map_key(c)	do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; } while (0)
-#define map_led(c)	do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0)
+#define map_abs(c)	hid_map_usage(hidinput, usage, &bit, &max, EV_ABS, (c))
+#define map_rel(c)	hid_map_usage(hidinput, usage, &bit, &max, EV_REL, (c))
+#define map_key(c)	hid_map_usage(hidinput, usage, &bit, &max, EV_KEY, (c))
+#define map_led(c)	hid_map_usage(hidinput, usage, &bit, &max, EV_LED, (c))
 
-#define map_abs_clear(c)	do { map_abs(c); clear_bit(c, bit); } while (0)
-#define map_key_clear(c)	do { map_key(c); clear_bit(c, bit); } while (0)
+#define map_abs_clear(c)	hid_map_usage_clear(hidinput, usage, &bit, \
+		&max, EV_ABS, (c))
+#define map_key_clear(c)	hid_map_usage_clear(hidinput, usage, &bit, \
+		&max, EV_KEY, (c))
 
 #ifdef CONFIG_USB_HIDINPUT_POWERBOOK
 
@@ -385,7 +387,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 	}
 
 	/* handle input mappings for quirky devices */
-	ret = hidinput_mapping_quirks(usage, input, &bit, &max);
+	ret = hidinput_mapping_quirks(usage, hidinput, &bit, &max);
 	if (ret)
 		goto mapped;
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index ff6df20..3b594b4 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -647,7 +647,7 @@ 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);
-int hidinput_mapping_quirks(struct hid_usage *, struct input_dev *, unsigned long **, int *);
+int hidinput_mapping_quirks(struct hid_usage *, struct hid_input *, unsigned long **, int *);
 int hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
 int hidinput_apple_event(struct hid_device *, struct input_dev *, struct hid_usage *, __s32);
 void hid_output_report(struct hid_report *report, __u8 *data);
@@ -655,6 +655,59 @@ struct hid_device *hid_allocate_device(void);
 int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
 
 /**
+ * hid_map_usage - map usage input bits
+ *
+ * @hidinput: hidinput which we are interested in
+ * @usage: usage to fill in
+ * @bit: pointer to input->{}bit (out parameter)
+ * @max: maximal valid usage->code to consider later (out parameter)
+ * @type: input event type (EV_KEY, EV_REL, ...)
+ * @c: code which corresponds to this usage and type
+ */
+static inline void hid_map_usage(struct hid_input *hidinput,
+		struct hid_usage *usage, unsigned long **bit, int *max,
+		__u8 type, __u16 c)
+{
+	struct input_dev *input = hidinput->input;
+
+	usage->type = type;
+	usage->code = c;
+
+	switch (type) {
+	case EV_ABS:
+		*bit = input->absbit;
+		*max = ABS_MAX;
+		break;
+	case EV_REL:
+		*bit = input->relbit;
+		*max = REL_MAX;
+		break;
+	case EV_KEY:
+		*bit = input->keybit;
+		*max = KEY_MAX;
+		break;
+	case EV_LED:
+		*bit = input->ledbit;
+		*max = LED_MAX;
+		break;
+	}
+}
+
+/**
+ * hid_map_usage_clear - map usage input bits and clear the input bit
+ *
+ * The same as hid_map_usage, except the @c bit is also cleared in supported
+ * bits (@bit).
+ */
+static inline void hid_map_usage_clear(struct hid_input *hidinput,
+		struct hid_usage *usage, unsigned long **bit, int *max,
+		__u8 type, __u16 c)
+{
+	hid_map_usage(hidinput, usage, bit, max, type, c);
+	clear_bit(c, *bit);
+}
+
+/**
  * hid_parse - parse HW reports
  *
  * @hdev: hid device
-- 
1.5.4.4


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC 5/8] HID: move logitech report quirks
  2008-04-04 20:35 Hid bus #2 Jiri Slaby
                   ` (3 preceding siblings ...)
  2008-04-04 20:35 ` [RFC 4/8] HID: move usage input mapping to hid.h Jiri Slaby
@ 2008-04-04 20:35 ` Jiri Slaby
  2008-04-04 20:35 ` [RFC 6/8] HID: move ignore quirks Jiri Slaby
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-04 20:35 UTC (permalink / raw)
  To: linux-input; +Cc: jkosina, marcel, dmitry.torokhov, Jiri Slaby, Jiri Slaby

Move them from core code to separate drivers.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/hid/Kconfig             |   12 ++++++
 drivers/hid/Makefile            |    2 +
 drivers/hid/hid-core.c          |    5 +++
 drivers/hid/hid-logitech.c      |   74 +++++++++++++++++++++++++++++++++++++++
 drivers/hid/usbhid/hid-quirks.c |   23 ------------
 include/linux/hid.h             |    1 -
 6 files changed, 93 insertions(+), 24 deletions(-)
 create mode 100644 drivers/hid/hid-logitech.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index cacf89e..2c252d6 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -67,4 +67,16 @@ config HIDRAW
 
 source "drivers/hid/usbhid/Kconfig"
 
+menu "Special HID drivers"
+	depends on HID
+
+config HID_LOGITECH
+	tristate "Logitech"
+	depends on USB_HID
+	---help---
+	Support for some Logitech devices which breaks less or more
+	HID specification.
+
+endmenu
+
 endif # HID_SUPPORT
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 275dc52..cae036b 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -8,6 +8,8 @@ obj-$(CONFIG_HID)		+= hid.o
 hid-$(CONFIG_HID_DEBUG)		+= hid-debug.o
 hid-$(CONFIG_HIDRAW)		+= hidraw.o
 
+obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
+
 obj-$(CONFIG_USB_HID)		+= usbhid/
 obj-$(CONFIG_USB_MOUSE)		+= usbhid/
 obj-$(CONFIG_USB_KBD)		+= usbhid/
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 40de7e7..2440ad6 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -33,6 +33,8 @@
 #include <linux/hid-debug.h>
 #include <linux/hidraw.h>
 
+#include "hid-ids.h"
+
 /*
  * Version Information
  */
@@ -1124,6 +1126,9 @@ static const struct hid_device_id *hid_match_id(unsigned int bus_type,
 }
 
 static const struct hid_device_id hid_usb_blacklist[] = {
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
 	{ }
 };
 
diff --git a/drivers/hid/hid-logitech.c b/drivers/hid/hid-logitech.c
new file mode 100644
index 0000000..261e8a5
--- /dev/null
+++ b/drivers/hid/hid-logitech.c
@@ -0,0 +1,74 @@
+/*
+ *  HID driver for some logitech "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define LOGITECH_RDESC	0x1
+
+/*
+ * Certain Logitech keyboards send in report #3 keys which are far
+ * above the logical maximum described in descriptor. This extends
+ * the original value of 0x28c of logical maximum to 0x104d
+ */
+static void lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+		unsigned int rsize)
+{
+	if (rsize >= 90 && rdesc[83] == 0x26
+			&& rdesc[84] == 0x8c
+			&& rdesc[85] == 0x02) {
+		dev_info(&hdev->dev, "fixing up Logitech keyboard report "
+				"descriptor\n");
+		rdesc[84] = rdesc[89] = 0x4d;
+		rdesc[85] = rdesc[90] = 0x10;
+	}
+}
+
+static const struct hid_device_id lg_devices[] = {
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
+		.driver_data = LOGITECH_RDESC },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER),
+		.driver_data = LOGITECH_RDESC },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2),
+		.driver_data = LOGITECH_RDESC },
+	{ }
+};
+
+static struct hid_driver lg_driver = {
+	.name = "logitech-usb",
+	.bus_type = BUS_USB,
+	.id_table = lg_devices,
+	.report_fixup = lg_report_fixup,
+};
+
+static int lg_init(void)
+{
+	return hid_register_driver(&lg_driver);
+}
+
+static void lg_exit(void)
+{
+	hid_unregister_driver(&lg_driver);
+}
+
+module_init(lg_init);
+module_exit(lg_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 9e32a2f..8ebef18 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -335,9 +335,6 @@ static const struct hid_rdesc_blacklist {
 
 	{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_RDESC_CYMOTION },
 
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_DESKTOP_RECV_1028, HID_QUIRK_RDESC_MICROSOFT_RECV_1028 },
 
 	{ USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E, HID_QUIRK_RDESC_BUTTON_CONSUMER },
@@ -607,23 +604,6 @@ static void usbhid_fixup_cymotion_descriptor(char *rdesc, int rsize)
 	}
 }
 
-
-/*
- * Certain Logitech keyboards send in report #3 keys which are far
- * above the logical maximum described in descriptor. This extends
- * the original value of 0x28c of logical maximum to 0x104d
- */
-static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
-{
-	if (rsize >= 90 && rdesc[83] == 0x26
-			&& rdesc[84] == 0x8c
-			&& rdesc[85] == 0x02) {
-		printk(KERN_INFO "Fixing up Logitech keyboard report descriptor\n");
-		rdesc[84] = rdesc[89] = 0x4d;
-		rdesc[85] = rdesc[90] = 0x10;
-	}
-}
-
 static void usbhid_fixup_sunplus_wdesktop(unsigned char *rdesc, int rsize)
 {
 	if (rsize >= 107 && rdesc[104] == 0x26
@@ -749,9 +729,6 @@ static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned
 	if ((quirks & HID_QUIRK_RDESC_CYMOTION))
 		usbhid_fixup_cymotion_descriptor(rdesc, rsize);
 
-	if (quirks & HID_QUIRK_RDESC_LOGITECH)
-		usbhid_fixup_logitech_descriptor(rdesc, rsize);
-
 	if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX)
 		usbhid_fixup_cypress_descriptor(rdesc, rsize);
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 3b594b4..0cbc747 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -292,7 +292,6 @@ struct hid_item {
  */
 
 #define HID_QUIRK_RDESC_CYMOTION		0x00000001
-#define HID_QUIRK_RDESC_LOGITECH		0x00000002
 #define HID_QUIRK_RDESC_SWAPPED_MIN_MAX		0x00000004
 #define HID_QUIRK_RDESC_PETALYNX		0x00000008
 #define HID_QUIRK_RDESC_MACBOOK_JIS		0x00000010
-- 
1.5.4.4


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC 6/8] HID: move ignore quirks
  2008-04-04 20:35 Hid bus #2 Jiri Slaby
                   ` (4 preceding siblings ...)
  2008-04-04 20:35 ` [RFC 5/8] HID: move logitech report quirks Jiri Slaby
@ 2008-04-04 20:35 ` Jiri Slaby
  2008-04-04 20:35 ` [RFC 7/8] HID: move apple quirks Jiri Slaby
  2008-04-04 20:35 ` [RFC 8/8] test Jiri Slaby
  7 siblings, 0 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-04 20:35 UTC (permalink / raw)
  To: linux-input; +Cc: jkosina, marcel, dmitry.torokhov, Jiri Slaby

Move ignore quirks from usbhid-quirks into hid-core code. Also don't output
warning when ENODEV is error code in usbhid and try ordinal input in hidp
when that error is returned.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 drivers/hid/hid-core.c          |  222 +++++++++++++++++++++++++++++++++++++++
 drivers/hid/usbhid/hid-core.c   |    3 +-
 drivers/hid/usbhid/hid-quirks.c |  207 ------------------------------------
 net/bluetooth/hidp/core.c       |    2 +-
 4 files changed, 225 insertions(+), 209 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 2440ad6..739adc5 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1204,6 +1204,222 @@ static struct bus_type hid_bus_type = {
 	.remove		= hid_device_remove,
 };
 
+static const struct hid_device_id hid_usb_ignore[] = {
+	{ HID_DEVICE(USB_VENDOR_ID_ADS_TECH, USB_DEVICE_ID_ADS_TECH_RADIO_SI470X) },
+	{ HID_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01) },
+	{ HID_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10) },
+	{ HID_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20) },
+	{ HID_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21) },
+	{ HID_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22) },
+	{ HID_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23) },
+	{ HID_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) },
+	{ HID_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) },
+	{ HID_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) },
+	{ HID_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)},
+	{ HID_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) },
+	{ HID_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) },
+	{ HID_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) },
+	{ HID_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) },
+	{ HID_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) },
+	{ HID_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) },
+	{ HID_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
+	{ HID_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
+	{ HID_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
+	{ HID_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) },
+	{ HID_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) },
+	{ HID_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) },
+	{ HID_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) },
+	{ HID_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30) },
+	{ HID_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30) },
+	{ HID_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT) },
+	{ HID_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT) },
+	{ HID_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT) },
+	{ HID_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT) },
+	{ HID_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT) },
+	{ HID_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL) },
+	{ HID_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2) },
+	{ HID_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN) },
+	{ HID_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER) },
+	{ HID_DEVICE(USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY) },
+	{ HID_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE) },
+	{ HID_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_600) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_601) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_602) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_603) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_604) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_605) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_606) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_607) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_608) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_609) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) },
+	{ HID_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) },
+	{ HID_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
+	{ HID_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
+	{ HID_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) },
+	{ HID_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) },
+	{ HID_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) },
+	{ HID_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) },
+	{ HID_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) },
+	{ HID_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) },
+	{ HID_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1) },
+	{ HID_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2) },
+	{ HID_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM) },
+	{ HID_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB) },
+	{ HID_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT) },
+	{ HID_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) },
+	{ HID_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) },
+	{ HID_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) },
+	{ HID_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) },
+	{ HID_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) },
+	{ HID_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS) },
+	{ HID_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1) },
+	{ HID_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100) },
+	{ HID_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20) },
+	{ HID_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30) },
+	{ HID_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100) },
+	{ HID_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108) },
+	{ HID_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118) },
+	{ HID_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200) },
+	{ HID_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300) },
+	{ HID_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400) },
+	{ HID_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500) },
+	{ HID_DEVICE(USB_VENDOR_ID_PANJIT, 0x0001) },
+	{ HID_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
+	{ HID_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
+	{ HID_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
+	{ HID_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
+	{ HID_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
+	{ HID_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
+	{ HID_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) },
+	{ HID_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) },
+	{ HID_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20) },
+	{ HID_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20) },
+	{ HID_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT) },
+	{ HID_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) },
+
+	{ HID_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR) },
+	{ HID_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302) },
+
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_2) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_3) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_4) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_5) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_6) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_7) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_8) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_9) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_10) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_11) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_12) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_13) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_14) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_15) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_16) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_17) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_18) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_19) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_20) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_21) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_22) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_23) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_24) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_25) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_26) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_27) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_28) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_29) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_30) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_31) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_32) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_33) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_34) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_35) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_36) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_37) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_38) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_39) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_40) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_41) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_42) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_43) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_44) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_45) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_46) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_47) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_48) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_49) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_50) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_51) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_52) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_53) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_54) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_55) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_56) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_57) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_58) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_59) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_60) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_61) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_62) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_63) },
+	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_64) },
+	{ HID_DEVICE(USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY) },
+	{ HID_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
+	{ }
+};
+
+static const struct hid_device_id *hid_ignore[] = {
+	[BUS_USB] = hid_usb_ignore,
+	[BUS_BLUETOOTH] = NULL,
+};
+
 int hid_add_device(struct hid_device *hdev)
 {
 	static atomic_t id = ATOMIC_INIT(0);
@@ -1212,6 +1428,12 @@ int hid_add_device(struct hid_device *hdev)
 	if (WARN_ON(hdev->status & HID_STAT_ADDED))
 		return -EBUSY;
 
+	/* we need to kill them here, otherwise they will stay allocated to
+	 * wait for coming driver */
+	if (hid_ignore[hdev->bus] && hid_match_id(hdev->bus, hdev,
+				hid_ignore[hdev->bus]))
+		return -ENODEV;
+
 	/* XXX hack, any other cleaner solution < 20 bus_id bytes? */
 	sprintf(hdev->dev.bus_id, "%02X:%04X:%04X.%02X", hdev->bus,
 			hdev->vendor, hdev->product, atomic_inc_return(&id));
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index d655dfc..0ab4674 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -1082,7 +1082,8 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
 
 	ret = hid_add_device(hid);
 	if (ret) {
-		dev_err(&intf->dev, "can't add hid device: %d\n", ret);
+		if (ret != -ENODEV)
+			dev_err(&intf->dev, "can't add hid device: %d\n", ret);
 		goto err;
 	}
 
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 8ebef18..13f0365 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -59,147 +59,6 @@ static const struct hid_blacklist {
 
 	{ USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193, HID_QUIRK_HWHEEL_WHEEL_INVERT },
 
-	{ USB_VENDOR_ID_ADS_TECH, USB_DEVICE_ID_ADS_TECH_RADIO_SI470X, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM, HID_QUIRK_IGNORE},
-	{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GENERAL_TOUCH, 0x0001, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GENERAL_TOUCH, 0x0002, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GENERAL_TOUCH, 0x0003, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GENERAL_TOUCH, 0x0004, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_600, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_601, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_602, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_603, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_604, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_605, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_606, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_607, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_608, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_609, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE },
-
-	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
-
 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
 
@@ -256,72 +115,6 @@ static const struct hid_blacklist {
 
 	{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_2, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_3, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_4, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_5, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_6, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_7, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_8, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_9, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_10, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_11, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_12, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_13, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_14, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_15, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_16, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_17, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_18, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_19, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_20, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_21, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_22, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_23, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_24, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_25, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_26, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_27, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_28, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_29, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_30, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_31, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_32, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_33, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_34, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_35, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_36, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_37, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_38, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_39, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_40, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_41, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_42, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_43, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_44, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_45, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_46, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_47, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_48, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_49, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_50, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_51, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_52, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_53, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_54, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_55, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_56, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_57, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_58, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_59, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_60, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_61, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_62, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_63, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_64, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560, HID_QUIRK_IGNORE },
 
 	{ 0, 0 }
 };
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 8261d4c..b24a4d2 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -858,7 +858,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
 
 	if (req->rd_size > 0) {
 		err = hidp_setup_hid(session, req);
-		if (err)
+		if (err != -ENODEV)
 			goto err_skb;
 	}
 
-- 
1.5.4.4


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC 7/8] HID: move apple quirks
  2008-04-04 20:35 Hid bus #2 Jiri Slaby
                   ` (5 preceding siblings ...)
  2008-04-04 20:35 ` [RFC 6/8] HID: move ignore quirks Jiri Slaby
@ 2008-04-04 20:35 ` Jiri Slaby
  2008-04-16 13:31   ` HID bus Jiri Kosina
  2008-04-16 13:45   ` [RFC 7/8] HID: move apple quirks Jiri Kosina
  2008-04-04 20:35 ` [RFC 8/8] test Jiri Slaby
  7 siblings, 2 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-04 20:35 UTC (permalink / raw)
  To: linux-input; +Cc: jkosina, marcel, dmitry.torokhov, Jiri Slaby, Jiri Slaby

Move them from core code to separate driver.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/hid/Kconfig             |    7 +
 drivers/hid/Makefile            |    1 +
 drivers/hid/hid-apple.c         |  496 +++++++++++++++++++++++++++++++++++++++
 drivers/hid/hid-core.c          |   33 +++-
 drivers/hid/hid-input-quirks.c  |    8 -
 drivers/hid/hid-input.c         |  218 +-----------------
 drivers/hid/usbhid/hid-quirks.c |   43 ----
 include/linux/hid.h             |   11 -
 net/bluetooth/hidp/core.c       |   22 --
 9 files changed, 537 insertions(+), 302 deletions(-)
 create mode 100644 drivers/hid/hid-apple.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 2c252d6..c0d4d43 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -77,6 +77,13 @@ config HID_LOGITECH
 	Support for some Logitech devices which breaks less or more
 	HID specification.
 
+config HID_APPLE
+	tristate "Apple"
+	depends on (USB_HID || BT_HIDP)
+	---help---
+	Support for some Apple devices which less or more break
+	HID specification.
+
 endmenu
 
 endif # HID_SUPPORT
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index cae036b..8a5cbbe 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -9,6 +9,7 @@ hid-$(CONFIG_HID_DEBUG)		+= hid-debug.o
 hid-$(CONFIG_HIDRAW)		+= hidraw.o
 
 obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
+obj-$(CONFIG_HID_APPLE)		+= hid-apple.o
 
 obj-$(CONFIG_USB_HID)		+= usbhid/
 obj-$(CONFIG_USB_MOUSE)		+= usbhid/
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
new file mode 100644
index 0000000..afb910f
--- /dev/null
+++ b/drivers/hid/hid-apple.c
@@ -0,0 +1,496 @@
+/*
+ *  USB HID quirks support for Linux
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby <jslaby@suse.cz>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/autoconf.h>
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+/* to simplify the tests throughout the code */
+#ifdef CONFIG_BT_HIDP_MODULE
+#define CONFIG_BT_HIDP 1
+#endif
+#ifdef CONFIG_USB_HID_MODULE
+#define CONFIG_USB_HID 1
+#endif
+
+#define APPLE_RDESC_JIS		0x0001
+#define APPLE_IGNORE_MOUSE	0x0002
+#define APPLE_HAS_FN		0x0004
+#define APPLE_FN_ON		0x0008	/* is fn pressed? */
+#define APPLE_HIDDEV		0x0010
+#define APPLE_ISO_KEYBOARD	0x0020
+#define APPLE_MIGHTYMOUSE	0x0040
+#define APPLE_INVERT_HWHEEL	0x0080
+#define APPLE_IGNORE_HIDINPUT	0x0100
+
+#define APPLE_FLAG_FKEY		0x01
+
+static unsigned int fnmode = 1;
+module_param(fnmode, uint, 0644);
+MODULE_PARM_DESC(fnmode, "Mode of fn key on Apple keyboards (0 = disabled, "
+		"[1] = fkeyslast, 2 = fkeysfirst)");
+
+struct apple_sc {
+	unsigned long quirks;
+	DECLARE_BITMAP(pressed_fn, KEY_CNT);
+	DECLARE_BITMAP(pressed_numlock, KEY_CNT);
+};
+
+struct apple_key_translation {
+	u16 from;
+	u16 to;
+	u8 flags;
+};
+
+static struct apple_key_translation apple_fn_keys[] = {
+	{ KEY_BACKSPACE, KEY_DELETE },
+	{ KEY_F1,	KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
+	{ KEY_F2,	KEY_BRIGHTNESSUP,   APPLE_FLAG_FKEY },
+	{ KEY_F3,	KEY_FN_F5,          APPLE_FLAG_FKEY }, /* Exposé */
+	{ KEY_F4,	KEY_FN_F4,          APPLE_FLAG_FKEY }, /* Dashboard */
+	{ KEY_F7,	KEY_PREVIOUSSONG,   APPLE_FLAG_FKEY },
+	{ KEY_F8,	KEY_PLAYPAUSE,      APPLE_FLAG_FKEY },
+	{ KEY_F9,	KEY_NEXTSONG,       APPLE_FLAG_FKEY },
+	{ KEY_F10,	KEY_MUTE,           APPLE_FLAG_FKEY },
+	{ KEY_F11,	KEY_VOLUMEDOWN,     APPLE_FLAG_FKEY },
+	{ KEY_F12,	KEY_VOLUMEUP,       APPLE_FLAG_FKEY },
+	{ KEY_UP,	KEY_PAGEUP },
+	{ KEY_DOWN,	KEY_PAGEDOWN },
+	{ KEY_LEFT,	KEY_HOME },
+	{ KEY_RIGHT,	KEY_END },
+	{ }
+};
+
+static struct apple_key_translation powerbook_fn_keys[] = {
+	{ KEY_BACKSPACE, KEY_DELETE },
+	{ KEY_F1,	KEY_BRIGHTNESSDOWN,     APPLE_FLAG_FKEY },
+	{ KEY_F2,	KEY_BRIGHTNESSUP,       APPLE_FLAG_FKEY },
+	{ KEY_F3,	KEY_MUTE,               APPLE_FLAG_FKEY },
+	{ KEY_F4,	KEY_VOLUMEDOWN,         APPLE_FLAG_FKEY },
+	{ KEY_F5,	KEY_VOLUMEUP,           APPLE_FLAG_FKEY },
+	{ KEY_F6,	KEY_NUMLOCK,            APPLE_FLAG_FKEY },
+	{ KEY_F7,	KEY_SWITCHVIDEOMODE,    APPLE_FLAG_FKEY },
+	{ KEY_F8,	KEY_KBDILLUMTOGGLE,     APPLE_FLAG_FKEY },
+	{ KEY_F9,	KEY_KBDILLUMDOWN,       APPLE_FLAG_FKEY },
+	{ KEY_F10,	KEY_KBDILLUMUP,         APPLE_FLAG_FKEY },
+	{ KEY_UP,	KEY_PAGEUP },
+	{ KEY_DOWN,	KEY_PAGEDOWN },
+	{ KEY_LEFT,	KEY_HOME },
+	{ KEY_RIGHT,	KEY_END },
+	{ }
+};
+
+static struct apple_key_translation powerbook_numlock_keys[] = {
+	{ KEY_J,	KEY_KP1 },
+	{ KEY_K,	KEY_KP2 },
+	{ KEY_L,	KEY_KP3 },
+	{ KEY_U,	KEY_KP4 },
+	{ KEY_I,	KEY_KP5 },
+	{ KEY_O,	KEY_KP6 },
+	{ KEY_7,	KEY_KP7 },
+	{ KEY_8,	KEY_KP8 },
+	{ KEY_9,	KEY_KP9 },
+	{ KEY_M,	KEY_KP0 },
+	{ KEY_DOT,	KEY_KPDOT },
+	{ KEY_SLASH,	KEY_KPPLUS },
+	{ KEY_SEMICOLON, KEY_KPMINUS },
+	{ KEY_P,	KEY_KPASTERISK },
+	{ KEY_MINUS,	KEY_KPEQUAL },
+	{ KEY_0,	KEY_KPSLASH },
+	{ KEY_F6,	KEY_NUMLOCK },
+	{ KEY_KPENTER,	KEY_KPENTER },
+	{ KEY_BACKSPACE, KEY_BACKSPACE },
+	{ }
+};
+
+static struct apple_key_translation apple_iso_keyboard[] = {
+	{ KEY_GRAVE,	KEY_102ND },
+	{ KEY_102ND,	KEY_GRAVE },
+	{ }
+};
+
+static struct apple_key_translation *apple_find_translation(
+		struct apple_key_translation *table, u16 from)
+{
+	struct apple_key_translation *trans;
+
+	/* Look for the translation */
+	for (trans = table; trans->from; trans++)
+		if (trans->from == from)
+			return trans;
+
+	return NULL;
+}
+
+static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
+		struct hid_usage *usage, __s32 value)
+{
+	struct apple_sc *asc = hid_get_drvdata(hid);
+	struct apple_key_translation *trans;
+
+	if (usage->code == KEY_FN) {
+		if (value)
+			asc->quirks |= APPLE_FN_ON;
+		else
+			asc->quirks &= ~APPLE_FN_ON;
+
+		input_event(input, usage->type, usage->code, value);
+
+		return 1;
+	}
+
+	if (fnmode) {
+		int do_translate;
+
+		trans = apple_find_translation((hid->product < 0x220 ||
+					hid->product >= 0x300) ?
+					powerbook_fn_keys : apple_fn_keys,
+					usage->code);
+		if (trans) {
+			if (test_bit(usage->code, asc->pressed_fn))
+				do_translate = 1;
+			else if (trans->flags & APPLE_FLAG_FKEY)
+				do_translate =
+					(fnmode == 2 && (asc->quirks & APPLE_FN_ON)) ||
+					(fnmode == 1 && !(asc->quirks & APPLE_FN_ON));
+			else
+				do_translate = (asc->quirks & APPLE_FN_ON);
+
+			if (do_translate) {
+				if (value)
+					set_bit(usage->code, asc->pressed_fn);
+				else
+					clear_bit(usage->code, asc->pressed_fn);
+
+				input_event(input, usage->type, trans->to,
+						value);
+
+				return 1;
+			}
+		}
+
+		if (test_bit(usage->code, asc->pressed_numlock) ||
+				test_bit(LED_NUML, input->led)) {
+			trans = apple_find_translation(powerbook_numlock_keys,
+					usage->code);
+
+			if (trans) {
+				if (value)
+					set_bit(usage->code,
+							asc->pressed_numlock);
+				else
+					clear_bit(usage->code,
+							asc->pressed_numlock);
+
+				input_event(input, usage->type, trans->to,
+						value);
+			}
+
+			return 1;
+		}
+	}
+
+	if (asc->quirks & APPLE_ISO_KEYBOARD) {
+		trans = apple_find_translation(apple_iso_keyboard, usage->code);
+		if (trans) {
+			input_event(input, usage->type, trans->to, value);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int apple_event(struct hid_device *hdev, struct hid_field *field,
+		struct hid_usage *usage, __s32 value)
+{
+	struct apple_sc *asc = hid_get_drvdata(hdev);
+
+	if (!field->hidinput)
+		return -ENODEV;
+
+	if ((asc->quirks & APPLE_INVERT_HWHEEL) &&
+			usage->code == REL_HWHEEL) {
+		input_event(field->hidinput->input, usage->type, usage->code,
+				-value);
+		return 0;
+	}
+
+	if ((asc->quirks & APPLE_HAS_FN) &&
+			hidinput_apple_event(hdev, field->hidinput->input,
+				usage, value))
+		return 0;
+
+
+	return -ENODEV;
+}
+
+static void apple_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_usage *usage, unsigned long **bit, int *max)
+{
+	struct apple_sc *asc = hid_get_drvdata(hdev);
+
+	if (asc->quirks & APPLE_MIGHTYMOUSE) {
+		if (usage->hid == HID_GD_Z)
+			hid_map_usage(hi, usage, bit, max, EV_REL, REL_HWHEEL);
+		else if (usage->code == BTN_1)
+			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_2);
+		else if (usage->code == BTN_2)
+			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_1);
+	}
+}
+
+static int apple_probe(struct hid_device *hdev,
+		const struct hid_device_id *id)
+{
+	unsigned long quirks = id->driver_data;
+	struct apple_sc *asc;
+	int ret;
+
+	asc = kzalloc(sizeof(*asc), GFP_KERNEL);
+	if (asc == NULL) {
+		dev_err(&hdev->dev, "can't alloc apple descriptor\n");
+		return -ENOMEM;
+	}
+
+	hid_set_drvdata(hdev, asc);
+
+	if (quirks & APPLE_HIDDEV)
+		hdev->quirks |= HID_QUIRK_HIDDEV;
+	if (quirks & APPLE_IGNORE_HIDINPUT)
+		hdev->quirks |= HID_QUIRK_IGNORE_HIDINPUT;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		dev_err(&hdev->dev, "parse failed\n");
+		goto err_free;
+	}
+
+	ret = hid_hw_start(hdev);
+	if (ret) {
+		dev_err(&hdev->dev, "hw start failed\n");
+		goto err_free;
+	}
+
+	return 0;
+err_free:
+	kfree(asc);
+	return ret;
+}
+
+static void apple_remove(struct hid_device *hdev)
+{
+	hid_hw_stop(hdev);
+	kfree(hid_get_drvdata(hdev));
+}
+
+#ifdef CONFIG_USB_HID
+static const struct hid_device_id apple_usb_devices[] = {
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4),
+		.driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE),
+		.driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
+
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE |
+			APPLE_ISO_KEYBOARD},
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE |
+			APPLE_ISO_KEYBOARD},
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE |
+			APPLE_ISO_KEYBOARD},
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
+		.driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS),
+		.driver_data = APPLE_RDESC_JIS },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, apple_usb_devices);
+
+/*
+ * MacBook JIS keyboard has wrong logical maximum
+ */
+static void apple_usb_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+		unsigned int rsize)
+{
+	struct apple_sc *asc = hid_get_drvdata(hdev);
+
+	if ((asc->quirks & APPLE_RDESC_JIS) && rsize >= 60 &&
+			rdesc[53] == 0x65 && rdesc[59] == 0x65) {
+		dev_info(&hdev->dev, "fixing up MacBook JIS keyboard report "
+				"descriptor\n");
+		rdesc[53] = rdesc[59] = 0xe7;
+	}
+}
+
+static void apple_setup_input(struct input_dev *input)
+{
+	struct apple_key_translation *trans;
+
+	set_bit(KEY_NUMLOCK, input->keybit);
+
+	/* Enable all needed keys */
+	for (trans = apple_fn_keys; trans->from; trans++)
+		set_bit(trans->to, input->keybit);
+
+	for (trans = powerbook_fn_keys; trans->from; trans++)
+		set_bit(trans->to, input->keybit);
+
+	for (trans = powerbook_numlock_keys; trans->from; trans++)
+		set_bit(trans->to, input->keybit);
+
+	for (trans = apple_iso_keyboard; trans->from; trans++)
+		set_bit(trans->to, input->keybit);
+}
+
+static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_usage *usage, unsigned long **bit, int *max)
+{
+	if (usage->hid == (HID_UP_CUSTOM | 0x0003)) {
+		/* The fn key on Apple USB keyboards */
+		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);
+		apple_setup_input(hi->input);
+	}
+
+	/* we want the hid layer to go through standard path (set and ignore) */
+	return 0;
+}
+
+static int apple_usb_probe(struct hid_device *hdev,
+		const struct hid_device_id *id)
+{
+	/* return something else or move to hid layer? device will reside
+	   allocated */
+	if ((id->driver_data & APPLE_IGNORE_MOUSE) &&
+			to_usb_interface(hdev->dev.parent)->cur_altsetting->
+			desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
+		return -ENODEV;
+
+	return apple_probe(hdev, id);
+}
+
+static struct hid_driver apple_usb_driver = {
+	.name = "apple-usb",
+	.bus_type = BUS_USB,
+	.id_table = apple_usb_devices,
+	.report_fixup = apple_usb_report_fixup,
+	.probe = apple_usb_probe,
+	.remove = apple_remove,
+	.event = apple_event,
+	.input_mapping = apple_input_mapping,
+	.input_mapped = apple_input_mapped,
+};
+#endif /* USB_HID */
+
+#if CONFIG_BT_HIDP
+static const struct hid_device_id apple_bt_devices[] = {
+	/* Apple wireless Mighty Mouse */
+	{ HID_DEVICE(0x05ac, 0x030c),
+		.driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, apple_bt_devices);
+
+static struct hid_driver apple_bt_driver = {
+	.name = "apple-bt",
+	.bus_type = BUS_BLUETOOTH,
+	.id_table = apple_bt_devices,
+	.probe = apple_probe,
+	.remove = apple_remove,
+	.event = apple_event,
+	.input_mapped = apple_input_mapped,
+};
+#endif /* BT_HIDP */
+
+static int apple_init(void)
+{
+	int ret = -ENODEV;
+#ifdef CONFIG_USB_HID
+	ret = hid_register_driver(&apple_usb_driver);
+	if (ret) {
+		printk(KERN_ERR "can't register apple-usb driver\n");
+		return ret;
+	}
+#endif
+#ifdef CONFIG_BT_HIDP
+	ret = hid_register_driver(&apple_bt_driver);
+	if (ret) {
+#ifdef CONFIG_USB_HID
+		hid_unregister_driver(&apple_usb_driver);
+#endif
+		printk(KERN_ERR "can't register apple-bt driver\n");
+	}
+#endif
+	return ret;
+}
+
+static void apple_exit(void)
+{
+#ifdef CONFIG_BT_HIDP
+	hid_unregister_driver(&apple_bt_driver);
+#endif
+#ifdef CONFIG_USB_HID
+	hid_unregister_driver(&apple_usb_driver);
+#endif
+}
+
+module_init(apple_init);
+module_exit(apple_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 739adc5..e1b17e7 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1129,12 +1129,43 @@ static const struct hid_device_id hid_usb_blacklist[] = {
 	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
 	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
 	{ HID_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
+	/* APPLE */
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
+	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) },
+	{ }
+};
+
+static const struct hid_device_id hid_bt_blacklist[] = {
+	{ HID_DEVICE(0x05ac, 0x030c) },
 	{ }
 };
 
 static const struct hid_device_id *hid_blacklist[] = {
 	[BUS_USB] = hid_usb_blacklist,
-	[BUS_BLUETOOTH] = NULL,
+	[BUS_BLUETOOTH] = hid_bt_blacklist,
 };
 
 static int hid_bus_match(struct device *dev, struct device_driver *drv)
diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c
index 51ae184..ff9bbdd 100644
--- a/drivers/hid/hid-input-quirks.c
+++ b/drivers/hid/hid-input-quirks.c
@@ -399,19 +399,11 @@ int hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struc
 		return 1;
 	}
 
-	if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) {
-		input_event(input, usage->type, usage->code, -value);
-		return 1;
-	}
-
 	if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) {
 		input_event(input, usage->type, REL_HWHEEL, value);
 		return 1;
 	}
 
-	if ((hid->quirks & HID_QUIRK_APPLE_HAS_FN) && hidinput_apple_event(hid, input, usage, value))
-		return 1;
-
 	/* Handling MS keyboards special buttons */
 	if (hid->quirks & HID_QUIRK_MICROSOFT_KEYS && 
 			usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 5439e76..0b13dca 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -34,11 +34,6 @@
 #include <linux/hid.h>
 #include <linux/hid-debug.h>
 
-static int hid_apple_fnmode = 1;
-module_param_named(pb_fnmode, hid_apple_fnmode, int, 0644);
-MODULE_PARM_DESC(pb_fnmode,
-		"Mode of fn key on Apple keyboards (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
-
 #define unk	KEY_UNKNOWN
 
 static const unsigned char hid_keyboard[256] = {
@@ -88,199 +83,6 @@ static const struct {
 #define map_key_clear(c)	hid_map_usage_clear(hidinput, usage, &bit, \
 		&max, EV_KEY, (c))
 
-#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
-
-struct hidinput_key_translation {
-	u16 from;
-	u16 to;
-	u8 flags;
-};
-
-#define APPLE_FLAG_FKEY 0x01
-
-static struct hidinput_key_translation apple_fn_keys[] = {
-	{ KEY_BACKSPACE, KEY_DELETE },
-	{ KEY_F1,       KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
-	{ KEY_F2,       KEY_BRIGHTNESSUP,   APPLE_FLAG_FKEY },
-	{ KEY_F3,       KEY_FN_F5,          APPLE_FLAG_FKEY }, /* Exposé */
-	{ KEY_F4,       KEY_FN_F4,          APPLE_FLAG_FKEY }, /* Dashboard */
-	{ KEY_F7,       KEY_PREVIOUSSONG,   APPLE_FLAG_FKEY },
-	{ KEY_F8,       KEY_PLAYPAUSE,      APPLE_FLAG_FKEY },
-	{ KEY_F9,       KEY_NEXTSONG,       APPLE_FLAG_FKEY },
-	{ KEY_F10,      KEY_MUTE,           APPLE_FLAG_FKEY },
-	{ KEY_F11,      KEY_VOLUMEDOWN,     APPLE_FLAG_FKEY },
-	{ KEY_F12,      KEY_VOLUMEUP,       APPLE_FLAG_FKEY },
-	{ KEY_UP,       KEY_PAGEUP },
-	{ KEY_DOWN,     KEY_PAGEDOWN },
-	{ KEY_LEFT,     KEY_HOME },
-	{ KEY_RIGHT,    KEY_END },
-	{ }
-};
-
-static struct hidinput_key_translation powerbook_fn_keys[] = {
-	{ KEY_BACKSPACE, KEY_DELETE },
-	{ KEY_F1,       KEY_BRIGHTNESSDOWN,     APPLE_FLAG_FKEY },
-	{ KEY_F2,       KEY_BRIGHTNESSUP,       APPLE_FLAG_FKEY },
-	{ KEY_F3,       KEY_MUTE,               APPLE_FLAG_FKEY },
-	{ KEY_F4,       KEY_VOLUMEDOWN,         APPLE_FLAG_FKEY },
-	{ KEY_F5,       KEY_VOLUMEUP,           APPLE_FLAG_FKEY },
-	{ KEY_F6,       KEY_NUMLOCK,            APPLE_FLAG_FKEY },
-	{ KEY_F7,       KEY_SWITCHVIDEOMODE,    APPLE_FLAG_FKEY },
-	{ KEY_F8,       KEY_KBDILLUMTOGGLE,     APPLE_FLAG_FKEY },
-	{ KEY_F9,       KEY_KBDILLUMDOWN,       APPLE_FLAG_FKEY },
-	{ KEY_F10,      KEY_KBDILLUMUP,         APPLE_FLAG_FKEY },
-	{ KEY_UP,       KEY_PAGEUP },
-	{ KEY_DOWN,     KEY_PAGEDOWN },
-	{ KEY_LEFT,     KEY_HOME },
-	{ KEY_RIGHT,    KEY_END },
-	{ }
-};
-
-static struct hidinput_key_translation powerbook_numlock_keys[] = {
-	{ KEY_J,        KEY_KP1 },
-	{ KEY_K,        KEY_KP2 },
-	{ KEY_L,        KEY_KP3 },
-	{ KEY_U,        KEY_KP4 },
-	{ KEY_I,        KEY_KP5 },
-	{ KEY_O,        KEY_KP6 },
-	{ KEY_7,        KEY_KP7 },
-	{ KEY_8,        KEY_KP8 },
-	{ KEY_9,        KEY_KP9 },
-	{ KEY_M,        KEY_KP0 },
-	{ KEY_DOT,      KEY_KPDOT },
-	{ KEY_SLASH,    KEY_KPPLUS },
-	{ KEY_SEMICOLON, KEY_KPMINUS },
-	{ KEY_P,        KEY_KPASTERISK },
-	{ KEY_MINUS,    KEY_KPEQUAL },
-	{ KEY_0,        KEY_KPSLASH },
-	{ KEY_F6,       KEY_NUMLOCK },
-	{ KEY_KPENTER,  KEY_KPENTER },
-	{ KEY_BACKSPACE, KEY_BACKSPACE },
-	{ }
-};
-
-static struct hidinput_key_translation apple_iso_keyboard[] = {
-	{ KEY_GRAVE,    KEY_102ND },
-	{ KEY_102ND,    KEY_GRAVE },
-	{ }
-};
-
-static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from)
-{
-	struct hidinput_key_translation *trans;
-
-	/* Look for the translation */
-	for (trans = table; trans->from; trans++)
-		if (trans->from == from)
-			return trans;
-
-	return NULL;
-}
-
-int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
-		struct hid_usage *usage, __s32 value)
-{
-	struct hidinput_key_translation *trans;
-
-	if (usage->code == KEY_FN) {
-		if (value) hid->quirks |=  HID_QUIRK_APPLE_FN_ON;
-		else       hid->quirks &= ~HID_QUIRK_APPLE_FN_ON;
-
-		input_event(input, usage->type, usage->code, value);
-
-		return 1;
-	}
-
-	if (hid_apple_fnmode) {
-		int do_translate;
-
-		trans = find_translation((hid->product < 0x220 ||
-					  hid->product >= 0x300) ?
-					 powerbook_fn_keys : apple_fn_keys,
-					 usage->code);
-		if (trans) {
-			if (test_bit(usage->code, hid->apple_pressed_fn))
-				do_translate = 1;
-			else if (trans->flags & APPLE_FLAG_FKEY)
-				do_translate =
-					(hid_apple_fnmode == 2 &&  (hid->quirks & HID_QUIRK_APPLE_FN_ON)) ||
-					(hid_apple_fnmode == 1 && !(hid->quirks & HID_QUIRK_APPLE_FN_ON));
-			else
-				do_translate = (hid->quirks & HID_QUIRK_APPLE_FN_ON);
-
-			if (do_translate) {
-				if (value)
-					set_bit(usage->code, hid->apple_pressed_fn);
-				else
-					clear_bit(usage->code, hid->apple_pressed_fn);
-
-				input_event(input, usage->type, trans->to, value);
-
-				return 1;
-			}
-		}
-
-		if (test_bit(usage->code, hid->pb_pressed_numlock) ||
-				test_bit(LED_NUML, input->led)) {
-			trans = find_translation(powerbook_numlock_keys, usage->code);
-
-			if (trans) {
-				if (value)
-					set_bit(usage->code, hid->pb_pressed_numlock);
-				else
-					clear_bit(usage->code, hid->pb_pressed_numlock);
-
-				input_event(input, usage->type, trans->to, value);
-			}
-
-			return 1;
-		}
-	}
-
-	if (hid->quirks & HID_QUIRK_APPLE_ISO_KEYBOARD) {
-		trans = find_translation(apple_iso_keyboard, usage->code);
-		if (trans) {
-			input_event(input, usage->type, trans->to, value);
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static void hidinput_apple_setup(struct input_dev *input)
-{
-	struct hidinput_key_translation *trans;
-
-	set_bit(KEY_NUMLOCK, input->keybit);
-
-	/* Enable all needed keys */
-	for (trans = apple_fn_keys; trans->from; trans++)
-		set_bit(trans->to, input->keybit);
-
-	for (trans = powerbook_fn_keys; trans->from; trans++)
-		set_bit(trans->to, input->keybit);
-
-	for (trans = powerbook_numlock_keys; trans->from; trans++)
-		set_bit(trans->to, input->keybit);
-
-	for (trans = apple_iso_keyboard; trans->from; trans++)
-		set_bit(trans->to, input->keybit);
-
-}
-#else
-inline int hidinput_apple_event(struct hid_device *hid,
-				       struct input_dev *input,
-				       struct hid_usage *usage, __s32 value)
-{
-	return 0;
-}
-
-static inline void hidinput_apple_setup(struct input_dev *input)
-{
-}
-#endif
-
 static inline int match_scancode(int code, int scancode)
 {
 	if (scancode == 0)
@@ -718,16 +520,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 		case HID_UP_CUSTOM: /* Reported on Logitech and Apple USB keyboards */
 
 			set_bit(EV_REP, input->evbit);
-			switch(usage->hid & HID_USAGE) {
-				case 0x003:
-					/* The fn key on Apple USB keyboards */
-					map_key_clear(KEY_FN);
-					hidinput_apple_setup(input);
-					break;
-
-				default:    goto ignore;
-			}
-			break;
+			goto ignore;
 
 		case HID_UP_LOGIVENDOR:
 
@@ -764,15 +557,6 @@ mapped:
 		device->driver->input_mapped(device, hidinput, usage,
 				&bit, &max);
 
-	if (device->quirks & HID_QUIRK_MIGHTYMOUSE) {
-		if (usage->hid == HID_GD_Z)
-			map_rel(REL_HWHEEL);
-		else if (usage->code == BTN_1)
-			map_key(BTN_2);
-		else if (usage->code == BTN_2)
-			map_key(BTN_1);
-	}
-
 	if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5 |
 			HID_QUIRK_2WHEEL_MOUSE_HACK_B8)) && (usage->type == EV_REL) &&
 			(usage->code == REL_WHEEL))
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 13f0365..a797f2c 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -54,7 +54,6 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL },
 
 	{ USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT },
 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
 
 	{ USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193, HID_QUIRK_HWHEEL_WHEEL_INVERT },
@@ -65,8 +64,6 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K, HID_QUIRK_MICROSOFT_KEYS },
 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K, HID_QUIRK_MICROSOFT_KEYS },
 
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
-
 	{ USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
 	{ USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT },
 
@@ -90,29 +87,6 @@ static const struct hid_blacklist {
 
 	{ USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI, HID_QUIRK_APPLE_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS, HID_QUIRK_APPLE_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, HID_QUIRK_APPLE_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS, HID_QUIRK_APPLE_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-
 	{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
 
@@ -132,8 +106,6 @@ static const struct hid_rdesc_blacklist {
 
 	{ USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E, HID_QUIRK_RDESC_BUTTON_CONSUMER },
 
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_RDESC_MACBOOK_JIS },
-
 	{ USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
 
 	{ USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_RDESC_SAMSUNG_REMOTE },
@@ -474,18 +446,6 @@ static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
 		printk(KERN_INFO "Fixing up Cypress report descriptor\n");
 }
 
-/*
- * MacBook JIS keyboard has wrong logical maximum
- */
-static void usbhid_fixup_macbook_descriptor(unsigned char *rdesc, int rsize)
-{
-	if (rsize >= 60 && rdesc[53] == 0x65
-			&& rdesc[59] == 0x65) {
-		printk(KERN_INFO "Fixing up MacBook JIS keyboard report descriptor\n");
-		rdesc[53] = rdesc[59] = 0xe7;
-	}
-}
-
 static void usbhid_fixup_button_consumer_descriptor(unsigned char *rdesc, int rsize)
 {
 	if (rsize >= 30 && rdesc[29] == 0x05
@@ -528,9 +488,6 @@ static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned
 	if (quirks & HID_QUIRK_RDESC_PETALYNX)
 		usbhid_fixup_petalynx_descriptor(rdesc, rsize);
 
-	if (quirks & HID_QUIRK_RDESC_MACBOOK_JIS)
-		usbhid_fixup_macbook_descriptor(rdesc, rsize);
-
 	if (quirks & HID_QUIRK_RDESC_BUTTON_CONSUMER)
 		usbhid_fixup_button_consumer_descriptor(rdesc, rsize);
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 0cbc747..550c9a3 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -267,11 +267,6 @@ struct hid_item {
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_7		0x00000080
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_5		0x00000100
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON		0x00000200
-#define HID_QUIRK_MIGHTYMOUSE			0x00000400
-#define HID_QUIRK_APPLE_HAS_FN			0x00000800
-#define HID_QUIRK_APPLE_FN_ON			0x00001000
-#define HID_QUIRK_INVERT_HWHEEL			0x00002000
-#define HID_QUIRK_APPLE_ISO_KEYBOARD		0x00004000
 #define HID_QUIRK_BAD_RELATIVE_KEYS		0x00008000
 #define HID_QUIRK_SKIP_OUTPUT_REPORTS		0x00010000
 #define HID_QUIRK_IGNORE_MOUSE			0x00020000
@@ -294,7 +289,6 @@ struct hid_item {
 #define HID_QUIRK_RDESC_CYMOTION		0x00000001
 #define HID_QUIRK_RDESC_SWAPPED_MIN_MAX		0x00000004
 #define HID_QUIRK_RDESC_PETALYNX		0x00000008
-#define HID_QUIRK_RDESC_MACBOOK_JIS		0x00000010
 #define HID_QUIRK_RDESC_BUTTON_CONSUMER		0x00000020
 #define HID_QUIRK_RDESC_SAMSUNG_REMOTE		0x00000040
 #define HID_QUIRK_RDESC_MICROSOFT_RECV_1028	0x00000080
@@ -481,10 +475,6 @@ struct hid_device {							/* device report descriptor */
 
 	/* handler for raw output data, used by hidraw */
 	int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t);
-#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
-	unsigned long apple_pressed_fn[BITS_TO_LONGS(KEY_CNT)];
-	unsigned long pb_pressed_numlock[BITS_TO_LONGS(KEY_CNT)];
-#endif
 };
 
 static inline void *hid_get_drvdata(struct hid_device *hdev)
@@ -648,7 +638,6 @@ 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);
 int hidinput_mapping_quirks(struct hid_usage *, struct hid_input *, unsigned long **, int *);
 int hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
-int hidinput_apple_event(struct hid_device *, struct input_dev *, struct hid_usage *, __s32);
 void hid_output_report(struct hid_report *report, __u8 *data);
 struct hid_device *hid_allocate_device(void);
 int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index b24a4d2..be3e17b 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -677,27 +677,6 @@ static void hidp_close(struct hid_device *hid)
 {
 }
 
-static const struct {
-	__u16 idVendor;
-	__u16 idProduct;
-	unsigned quirks;
-} hidp_blacklist[] = {
-	/* Apple wireless Mighty Mouse */
-	{ 0x05ac, 0x030c, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
-
-	{ }	/* Terminating entry */
-};
-
-static void hidp_setup_quirks(struct hid_device *hid)
-{
-	unsigned int n;
-
-	for (n = 0; hidp_blacklist[n].idVendor; n++)
-		if (hidp_blacklist[n].idVendor == le16_to_cpu(hid->vendor) &&
-				hidp_blacklist[n].idProduct == le16_to_cpu(hid->product))
-			hid->quirks = hidp_blacklist[n].quirks;
-}
-
 static int hidp_parse(struct hid_device *hid)
 {
 	struct hidp_session *session = hid->driver_data;
@@ -723,7 +702,6 @@ static int hidp_parse(struct hid_device *hid)
 
 	session->req = NULL;
 
-	hidp_setup_quirks(hid);
 	return 0;
 }
 
-- 
1.5.4.4

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC 8/8] test
  2008-04-04 20:35 Hid bus #2 Jiri Slaby
                   ` (6 preceding siblings ...)
  2008-04-04 20:35 ` [RFC 7/8] HID: move apple quirks Jiri Slaby
@ 2008-04-04 20:35 ` Jiri Slaby
  7 siblings, 0 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-04 20:35 UTC (permalink / raw)
  To: linux-input; +Cc: jkosina, marcel, dmitry.torokhov, Jiri Slaby

Just demonstrative example.

---
 drivers/hid/Makefile   |    2 +-
 drivers/hid/hid-core.c |    1 +
 drivers/hid/test.c     |   62 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 64 insertions(+), 1 deletions(-)
 create mode 100644 drivers/hid/test.c

diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 8a5cbbe..e607b7b 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -3,7 +3,7 @@
 #
 hid-objs			:= hid-core.o hid-input.o hid-input-quirks.o
 
-obj-$(CONFIG_HID)		+= hid.o
+obj-$(CONFIG_HID)		+= hid.o test.o
 
 hid-$(CONFIG_HID_DEBUG)		+= hid-debug.o
 hid-$(CONFIG_HIDRAW)		+= hidraw.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index e1b17e7..aff61c6 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1155,6 +1155,7 @@ static const struct hid_device_id hid_usb_blacklist[] = {
 	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
 	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
 	{ HID_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) },
+	{ HID_DEVICE(0x045e, 0x00f0) },
 	{ }
 };
 
diff --git a/drivers/hid/test.c b/drivers/hid/test.c
new file mode 100644
index 0000000..3633199
--- /dev/null
+++ b/drivers/hid/test.c
@@ -0,0 +1,62 @@
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+static const struct hid_report_id t_report_table[] = {
+	{ HID_REPORT_ID(0) },
+	{ HID_TERMINATOR }
+};
+
+static int t_raw_event(struct hid_device *hdev, struct hid_report *report,
+		u8 *data, int size)
+{
+/*	printk(KERN_DEBUG "report: %u, %u, %d, %.8x\n",
+			report->id, report->type,
+			size, __swab32(*((u32 *)data)));*/
+
+	return -ENODEV;
+}
+
+static const struct hid_usage_id t_usage_table[] = {
+	{ HID_USAGE_ID(HID_ANY_ID, 8) },
+	{ HID_TERMINATOR }
+};
+
+static int t_event(struct hid_device *hdev, struct hid_field *field,
+		struct hid_usage *usage, __s32 value)
+{
+/*	printk(KERN_DEBUG "usage: %u %u %u %d\n",
+			usage->hid, usage->code, usage->type, value);*/
+
+	return -ENODEV;
+}
+
+static const struct hid_device_id t_devices[] = {
+	{ HID_DEVICE(0x045e, 0x00f0) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, t_devices);
+
+static struct hid_driver t_driver = {
+	.name = "test-usb",
+	.bus_type = BUS_USB,
+	.id_table = t_devices,
+	.usage_table = t_usage_table,
+	.event = t_event,
+	.report_table = t_report_table,
+	.raw_event = t_raw_event,
+};
+
+static int t_init(void)
+{
+	return hid_register_driver(&t_driver);
+}
+
+static void t_exit(void)
+{
+	hid_unregister_driver(&t_driver);
+}
+
+module_init(t_init);
+module_exit(t_exit);
+MODULE_LICENSE("GPL");
-- 
1.5.4.4


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-04 20:35 ` [RFC 7/8] HID: move apple quirks Jiri Slaby
@ 2008-04-16 13:31   ` Jiri Kosina
  2008-04-16 14:43     ` Jiri Slaby
  2008-04-16 20:30     ` Jiri Slaby
  2008-04-16 13:45   ` [RFC 7/8] HID: move apple quirks Jiri Kosina
  1 sibling, 2 replies; 30+ messages in thread
From: Jiri Kosina @ 2008-04-16 13:31 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: linux-input, marcel, dmitry.torokhov, Jiri Slaby

On Fri, 4 Apr 2008, Jiri Slaby wrote:

> +menu "Special HID drivers"
> +	depends on HID
> +
> +config HID_LOGITECH
> +	tristate "Logitech"
> +	depends on USB_HID
> +	---help---
> +	Support for some Logitech devices which breaks less or more
> +	HID specification.

Hi Jiri,

I think that we want to make this default to y if USB_HID is selected, 
right?

>  
> +config HID_APPLE
> +	tristate "Apple"
> +	depends on (USB_HID || BT_HIDP)
> +	---help---
> +	Support for some Apple devices which less or more break
> +	HID specification.
> +

and the same here.

Otherwise default kernel configuration might make the hardware that worked 
properly in previous versions not to work with new kernel.

Thanks,

-- 
Jiri Kosina

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [RFC 7/8] HID: move apple quirks
  2008-04-04 20:35 ` [RFC 7/8] HID: move apple quirks Jiri Slaby
  2008-04-16 13:31   ` HID bus Jiri Kosina
@ 2008-04-16 13:45   ` Jiri Kosina
  2008-04-16 14:42     ` Jiri Slaby
  1 sibling, 1 reply; 30+ messages in thread
From: Jiri Kosina @ 2008-04-16 13:45 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: linux-input, marcel, dmitry.torokhov, Jiri Slaby

On Fri, 4 Apr 2008, Jiri Slaby wrote:

> Move them from core code to separate driver.
> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
> ---
>  drivers/hid/Kconfig             |    7 +
>  drivers/hid/Makefile            |    1 +
>  drivers/hid/hid-apple.c         |  496 +++++++++++++++++++++++++++++++++++++++
>  drivers/hid/hid-core.c          |   33 +++-
>  drivers/hid/hid-input-quirks.c  |    8 -
>  drivers/hid/hid-input.c         |  218 +-----------------
>  drivers/hid/usbhid/hid-quirks.c |   43 ----
>  include/linux/hid.h             |   11 -
>  net/bluetooth/hidp/core.c       |   22 --

Hi Jiri,

how is the bluetooth quirk code removal related to the rest of the patch 
(apple quirks movement) please?

Thanks,

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [RFC 7/8] HID: move apple quirks
  2008-04-16 13:45   ` [RFC 7/8] HID: move apple quirks Jiri Kosina
@ 2008-04-16 14:42     ` Jiri Slaby
  2008-04-18 11:33       ` Jiri Kosina
  0 siblings, 1 reply; 30+ messages in thread
From: Jiri Slaby @ 2008-04-16 14:42 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: linux-input, marcel, dmitry.torokhov, Jiri Slaby

On 04/16/2008 03:45 PM, Jiri Kosina wrote:
> On Fri, 4 Apr 2008, Jiri Slaby wrote:
> 
>> Move them from core code to separate driver.
>> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
>> ---
>>  drivers/hid/Kconfig             |    7 +
>>  drivers/hid/Makefile            |    1 +
>>  drivers/hid/hid-apple.c         |  496 +++++++++++++++++++++++++++++++++++++++
>>  drivers/hid/hid-core.c          |   33 +++-
>>  drivers/hid/hid-input-quirks.c  |    8 -
>>  drivers/hid/hid-input.c         |  218 +-----------------
>>  drivers/hid/usbhid/hid-quirks.c |   43 ----
>>  include/linux/hid.h             |   11 -
>>  net/bluetooth/hidp/core.c       |   22 --
> 
> Hi Jiri,
> 
> how is the bluetooth quirk code removal related to the rest of the patch 
> (apple quirks movement) please?

Since the apple mightymouse is only quirked bluetooth device. Do you want me to 
split it to 2 patches -- an usb part and a BT part? (Or note this in changelog?)

Thanks.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-16 13:31   ` HID bus Jiri Kosina
@ 2008-04-16 14:43     ` Jiri Slaby
  2008-04-16 20:30     ` Jiri Slaby
  1 sibling, 0 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-16 14:43 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: linux-input, marcel, dmitry.torokhov, Jiri Slaby

On 04/16/2008 03:31 PM, Jiri Kosina wrote:
> On Fri, 4 Apr 2008, Jiri Slaby wrote:
> 
>> +menu "Special HID drivers"
>> +	depends on HID
>> +
>> +config HID_LOGITECH
>> +	tristate "Logitech"
>> +	depends on USB_HID
>> +	---help---
>> +	Support for some Logitech devices which breaks less or more
>> +	HID specification.
> 
> Hi Jiri,
> 
> I think that we want to make this default to y if USB_HID is selected, 
> right?

I think you're right here. Thanks.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-16 13:31   ` HID bus Jiri Kosina
  2008-04-16 14:43     ` Jiri Slaby
@ 2008-04-16 20:30     ` Jiri Slaby
  2008-04-16 20:45       ` Dmitry Torokhov
  1 sibling, 1 reply; 30+ messages in thread
From: Jiri Slaby @ 2008-04-16 20:30 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: linux-input, marcel, dmitry.torokhov, Jiri Slaby

On 04/16/2008 03:31 PM, Jiri Kosina wrote:
> Otherwise default kernel configuration might make the hardware that worked 
> properly in previous versions not to work with new kernel.

Actually I have one problem here. Autoloading. I don't have any idea how to 
solve it. To solve it backward compatible with older userspace (if I would 
change module-init-tools). I'm thinking only about a default-y option which 
inhibits these drivers as a module for some time until the change gfets 
propagated (and user decides he no longer needs it).

Modules are supposed to have MODULE_DEVICE_TABLE(hid, table) (which has another 
minor issue with different buses). This won't load any module, since depmod et 
al. don't know this device table so far.

Any ideas, please?


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-16 20:30     ` Jiri Slaby
@ 2008-04-16 20:45       ` Dmitry Torokhov
  2008-04-16 20:54         ` Jiri Slaby
  0 siblings, 1 reply; 30+ messages in thread
From: Dmitry Torokhov @ 2008-04-16 20:45 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: Jiri Kosina, linux-input, marcel, Jiri Slaby

On Wed, Apr 16, 2008 at 10:30:54PM +0200, Jiri Slaby wrote:
> On 04/16/2008 03:31 PM, Jiri Kosina wrote:
>> Otherwise default kernel configuration might make the hardware that worked 
>> properly in previous versions not to work with new kernel.
>
> Actually I have one problem here. Autoloading. I don't have any idea how to 
> solve it. To solve it backward compatible with older userspace (if I would 
> change module-init-tools). I'm thinking only about a default-y option which 
> inhibits these drivers as a module for some time until the change gfets 
> propagated (and user decides he no longer needs it).
>
> Modules are supposed to have MODULE_DEVICE_TABLE(hid, table) (which has 
> another minor issue with different buses). This won't load any module, 
> since depmod et al. don't know this device table so far.
>
> Any ideas, please?
>

When I added serio bus I had to send patches to Rusty for
module-init-tools... No way around it as far as I understand.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-16 20:45       ` Dmitry Torokhov
@ 2008-04-16 20:54         ` Jiri Slaby
  2008-04-16 21:05           ` Dmitry Torokhov
  2008-04-18 11:36           ` Jiri Kosina
  0 siblings, 2 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-16 20:54 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Jiri Slaby, Jiri Kosina, linux-input, marcel

On 04/16/2008 10:45 PM, Dmitry Torokhov wrote:
> When I added serio bus I had to send patches to Rusty for
> module-init-tools... No way around it as far as I understand.

I have no fear of augmenting the tools, but the regressions. If one compile
those as modules, it won't work with older init tools installed, since it won't
get loaded. In that way I have been thinking of the option CONFIG_I_HAVE_OLD_MIT
which would integrate the drivers into hidbus module or something scary like that.

When you added that serio bus, you just added a new code, or converted something
into a bus?

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-16 20:54         ` Jiri Slaby
@ 2008-04-16 21:05           ` Dmitry Torokhov
  2008-04-18 11:36           ` Jiri Kosina
  1 sibling, 0 replies; 30+ messages in thread
From: Dmitry Torokhov @ 2008-04-16 21:05 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: Jiri Slaby, Jiri Kosina, linux-input, marcel

On Wed, Apr 16, 2008 at 10:54:03PM +0200, Jiri Slaby wrote:
> On 04/16/2008 10:45 PM, Dmitry Torokhov wrote:
>> When I added serio bus I had to send patches to Rusty for
>> module-init-tools... No way around it as far as I understand.
>
> I have no fear of augmenting the tools, but the regressions. If one compile
> those as modules, it won't work with older init tools installed, since it won't
> get loaded. In that way I have been thinking of the option CONFIG_I_HAVE_OLD_MIT
> which would integrate the drivers into hidbus module or something scary like that.
>
> When you added that serio bus, you just added a new code, or converted something
> into a bus?

The drivers already were there (atkbd, psmouse, etc) but I dont think
they were auto-loading before.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [RFC 7/8] HID: move apple quirks
  2008-04-16 14:42     ` Jiri Slaby
@ 2008-04-18 11:33       ` Jiri Kosina
  2008-04-18 11:35         ` David Miller
  0 siblings, 1 reply; 30+ messages in thread
From: Jiri Kosina @ 2008-04-18 11:33 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: linux-input, marcel, dmitry.torokhov, Jiri Slaby

On Wed, 16 Apr 2008, Jiri Slaby wrote:

> Since the apple mightymouse is only quirked bluetooth device. Do you 
> want me to split it to 2 patches -- an usb part and a BT part? (Or note 
> this in changelog?)

I think this is up to Marcel -- if he is OK with me taking this through my 
tree eventually, just Acked-by is OK. If he wants to take it through 
his/Davem's tree, a separate patch will be probably needed.

Thanks,

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [RFC 7/8] HID: move apple quirks
  2008-04-18 11:33       ` Jiri Kosina
@ 2008-04-18 11:35         ` David Miller
  0 siblings, 0 replies; 30+ messages in thread
From: David Miller @ 2008-04-18 11:35 UTC (permalink / raw)
  To: jkosina; +Cc: jirislaby, linux-input, marcel, dmitry.torokhov, jslaby

From: Jiri Kosina <jkosina@suse.cz>
Date: Fri, 18 Apr 2008 13:33:06 +0200 (CEST)

> On Wed, 16 Apr 2008, Jiri Slaby wrote:
> 
> > Since the apple mightymouse is only quirked bluetooth device. Do you 
> > want me to split it to 2 patches -- an usb part and a BT part? (Or note 
> > this in changelog?)
> 
> I think this is up to Marcel -- if he is OK with me taking this through my 
> tree eventually, just Acked-by is OK. If he wants to take it through 
> his/Davem's tree, a separate patch will be probably needed.

I'm ambivalent, you guys do whatever is most convenient for you.
It doesn't have to go through my tree at all and I doubt it will
generate any merge hassles for net-2.6.26.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-16 20:54         ` Jiri Slaby
  2008-04-16 21:05           ` Dmitry Torokhov
@ 2008-04-18 11:36           ` Jiri Kosina
  2008-04-19 22:38             ` Jiri Slaby
  1 sibling, 1 reply; 30+ messages in thread
From: Jiri Kosina @ 2008-04-18 11:36 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: Dmitry Torokhov, Jiri Slaby, linux-input, marcel

On Wed, 16 Apr 2008, Jiri Slaby wrote:

> > When I added serio bus I had to send patches to Rusty for 
> > module-init-tools... No way around it as far as I understand.
> I have no fear of augmenting the tools, but the regressions. If one 
> compile those as modules, it won't work with older init tools installed, 
> since it won't get loaded. In that way I have been thinking of the 
> option CONFIG_I_HAVE_OLD_MIT which would integrate the drivers into 
> hidbus module or something scary like that.

I don't seem to be smart enough to come up with any clever solution to 
this either.

So please also consider submitting the patch to module-init-tools, thanks.

Maybe introducing CONFIG_HID_COMPAT (which will link everything together 
again) and leaving it there for a few releases might help to leave the 
complaints from users on reasonable level.

Thanks!

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-18 11:36           ` Jiri Kosina
@ 2008-04-19 22:38             ` Jiri Slaby
  2008-04-20 11:57               ` Jiri Slaby
  2008-04-20 16:15               ` Anssi Hannula
  0 siblings, 2 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-19 22:38 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Dmitry Torokhov, linux-input, marcel, mit-devel, linux-kernel,
	Jiri Slaby

Hmm, I must admit, I didn't know how exactly autoloading works. On suse,
at least, module aliases are used. So autoloading works for me after this
patch and slight modifications of the previous patches. The pro of this
is that it's in-kernel modification of modpost phase.

Now, I wonder for exactly what purpose are module.*map files in
/lib/modules/`uname -r`/ dir, i.e. what would break, if the devices won't
be listed there on systems with unpatched module-init-tools.

--

Generate aliases for usb hid device modules to support autoloading.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 include/linux/hid.h             |    7 +++++++
 include/linux/mod_devicetable.h |    8 ++++++++
 scripts/mod/file2alias.c        |   21 +++++++++++++++++++++
 3 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/include/linux/hid.h b/include/linux/hid.h
index d951ec4..44c1b8b 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -29,11 +29,18 @@
  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
+#ifdef __KERNEL__
+#include <linux/mod_devicetable.h>
+#endif
+
 /*
  * USB HID (Human Interface Device) interface class code
  */
 
+/* this one is for userspace, we define this in linux/mod_devicetable.h */
+#ifndef USB_INTERFACE_CLASS_HID
 #define USB_INTERFACE_CLASS_HID		3
+#endif
 
 /*
  * USB HID interface subclass and protocol codes
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 139d49d..2227c43 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -131,6 +131,14 @@ struct usb_device_id {
 #define USB_DEVICE_ID_MATCH_INT_SUBCLASS	0x0100
 #define USB_DEVICE_ID_MATCH_INT_PROTOCOL	0x0200
 
+#define USB_INTERFACE_CLASS_HID			3
+#define HID_ANY_ID				(~0)
+
+struct hid_device_id {
+	__u32 vendor, product;
+	kernel_ulong_t driver_data;
+};
+
 /* s390 CCW devices */
 struct ccw_device_id {
 	__u16	match_flags;	/* which fields to match against */
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 769b69d..d92445e 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -199,6 +199,23 @@ static void do_usb_table(void *symval, unsigned long size,
 		do_usb_entry_multi(symval + i, mod);
 }
 
+/* Looks like: usb */
+static int do_hid_usb_entry(const char *filename,
+			     struct hid_device_id *id, char *alias)
+{
+	__u16 v = TO_NATIVE((__u16)id->vendor);
+	__u16 p = TO_NATIVE((__u16)id->product);
+
+	strcpy(alias, "usb:");
+	ADD(alias, "v", id->vendor != HID_ANY_ID, v);
+	ADD(alias, "p", id->product != HID_ANY_ID, p);
+
+	sprintf(alias + strlen(alias), "d*dc*dsc*dp*ic%02Xisc*ip*",
+			USB_INTERFACE_CLASS_HID);
+
+	return 1;
+}
+
 /* Looks like: ieee1394:venNmoNspNverN */
 static int do_ieee1394_entry(const char *filename,
 			     struct ieee1394_device_id *id, char *alias)
@@ -642,6 +659,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
 	else if (sym_is(symname, "__mod_usb_device_table"))
 		/* special case to handle bcdDevice ranges */
 		do_usb_table(symval, sym->st_size, mod);
+	else if (sym_is(symname, "__mod_hid_usb_device_table"))
+		do_table(symval, sym->st_size,
+			 sizeof(struct hid_device_id), "hid_usb",
+			 do_hid_usb_entry, mod);
 	else if (sym_is(symname, "__mod_ieee1394_device_table"))
 		do_table(symval, sym->st_size,
 			 sizeof(struct ieee1394_device_id), "ieee1394",
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-19 22:38             ` Jiri Slaby
@ 2008-04-20 11:57               ` Jiri Slaby
  2008-04-22  0:00                 ` Jiri Kosina
  2008-04-20 16:15               ` Anssi Hannula
  1 sibling, 1 reply; 30+ messages in thread
From: Jiri Slaby @ 2008-04-20 11:57 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: Dmitry Torokhov, linux-input, marcel, mit-devel, linux-kernel

On 04/20/2008 12:38 AM, Jiri Slaby wrote:
> Now, I wonder for exactly what purpose are module.*map files in
> /lib/modules/`uname -r`/ dir, i.e. what would break, if the devices won't
> be listed there on systems with unpatched module-init-tools.

Well, used by /sbin/hotplug. I.e. on systems which uses that hotplugging system 
and not new enough udev. It means older RHEL, SLE* et al., and older 
distributions too...

So I suppose we still need the option to let users compile all the chosen 
drivers into hid.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-19 22:38             ` Jiri Slaby
  2008-04-20 11:57               ` Jiri Slaby
@ 2008-04-20 16:15               ` Anssi Hannula
  2008-04-20 18:07                 ` Jiri Slaby
  2008-04-21  9:25                 ` Jiri Kosina
  1 sibling, 2 replies; 30+ messages in thread
From: Anssi Hannula @ 2008-04-20 16:15 UTC (permalink / raw)
  To: Jiri Slaby
  Cc: Jiri Kosina, Dmitry Torokhov, linux-input, marcel, mit-devel,
	linux-kernel

Jiri Slaby wrote:
> Hmm, I must admit, I didn't know how exactly autoloading works. On suse,
> at least, module aliases are used. So autoloading works for me after this
> patch and slight modifications of the previous patches. The pro of this
> is that it's in-kernel modification of modpost phase.

Indeed in current systems udev uses module aliases for autoloading.

> --
> 
> Generate aliases for usb hid device modules to support autoloading.
> 
> Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
[...]
> +/* Looks like: usb */

Looks like: "usb:vNpNd*dc*dsc*dp*ic3isc*ip*"

> +static int do_hid_usb_entry(const char *filename,
> +			     struct hid_device_id *id, char *alias)
> +{
> +	__u16 v = TO_NATIVE((__u16)id->vendor);
> +	__u16 p = TO_NATIVE((__u16)id->product);
> +
> +	strcpy(alias, "usb:");
> +	ADD(alias, "v", id->vendor != HID_ANY_ID, v);
> +	ADD(alias, "p", id->product != HID_ANY_ID, p);
> +
> +	sprintf(alias + strlen(alias), "d*dc*dsc*dp*ic%02Xisc*ip*",
> +			USB_INTERFACE_CLASS_HID);
> +
> +	return 1;
> +}

Oh, so we create a normal usb modalias entry anyway, not a custom
'usbhid:' one.

Why not just do something like

#define HID_DEVICE(vend, dev) \
	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
		       USB_DEVICE_ID_MATCH_INT_CLASS, \
	.idVendor = (vend), \
	.idProduct = (prod), \
	.bInterfaceClass = USB_INTERFACE_CLASS_HID
(see linux/usb.h)

and use USB hotplugging?

Or do we plan to match against something else as well, such as hid
reports or something?

-- 
Anssi Hannula

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-20 16:15               ` Anssi Hannula
@ 2008-04-20 18:07                 ` Jiri Slaby
  2008-04-21  9:25                 ` Jiri Kosina
  1 sibling, 0 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-20 18:07 UTC (permalink / raw)
  To: Anssi Hannula
  Cc: Jiri Kosina, Dmitry Torokhov, linux-input, marcel, linux-kernel

On 04/20/2008 06:15 PM, Anssi Hannula wrote:
> Oh, so we create a normal usb modalias entry anyway, not a custom
> 'usbhid:' one.

Arrr, thank you, this provoked me an idea. I'll repost the patch tomorrow or so.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-20 16:15               ` Anssi Hannula
  2008-04-20 18:07                 ` Jiri Slaby
@ 2008-04-21  9:25                 ` Jiri Kosina
  2008-04-21 13:36                   ` Dmitry Torokhov
  1 sibling, 1 reply; 30+ messages in thread
From: Jiri Kosina @ 2008-04-21  9:25 UTC (permalink / raw)
  To: Anssi Hannula
  Cc: Jiri Slaby, Dmitry Torokhov, linux-input, Marcel Holtmann,
	mit-devel, linux-kernel

On Sun, 20 Apr 2008, Anssi Hannula wrote:

> Why not just do something like
> 
> #define HID_DEVICE(vend, dev) \
> 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
> 		       USB_DEVICE_ID_MATCH_INT_CLASS, \
> 	.idVendor = (vend), \
> 	.idProduct = (prod), \
> 	.bInterfaceClass = USB_INTERFACE_CLASS_HID
> (see linux/usb.h)
> 
> and use USB hotplugging?
> Or do we plan to match against something else as well, such as hid
> reports or something?

No, we plan to do matching based solely on VID/PID. The report-specific 
stuff is then handled between the specific driver and HID generic code.

Thanks,

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-21  9:25                 ` Jiri Kosina
@ 2008-04-21 13:36                   ` Dmitry Torokhov
  2008-04-21 23:05                     ` Jiri Slaby
  0 siblings, 1 reply; 30+ messages in thread
From: Dmitry Torokhov @ 2008-04-21 13:36 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Anssi Hannula, Jiri Slaby, linux-input, Marcel Holtmann,
	mit-devel, linux-kernel

On Mon, Apr 21, 2008 at 11:25:43AM +0200, Jiri Kosina wrote:
> On Sun, 20 Apr 2008, Anssi Hannula wrote:
> 
> > Why not just do something like
> > 
> > #define HID_DEVICE(vend, dev) \
> > 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
> > 		       USB_DEVICE_ID_MATCH_INT_CLASS, \
> > 	.idVendor = (vend), \
> > 	.idProduct = (prod), \
> > 	.bInterfaceClass = USB_INTERFACE_CLASS_HID
> > (see linux/usb.h)
> > 
> > and use USB hotplugging?
> > Or do we plan to match against something else as well, such as hid
> > reports or something?
> 
> No, we plan to do matching based solely on VID/PID. The report-specific 
> stuff is then handled between the specific driver and HID generic code.
> 

Hmm, [ab]using USB modalias makes me a bit uneasy. What about bluetooth
HID devices?

-- 
Dmitry

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-21 13:36                   ` Dmitry Torokhov
@ 2008-04-21 23:05                     ` Jiri Slaby
  0 siblings, 0 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-21 23:05 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jiri Kosina, Anssi Hannula, linux-input, Marcel Holtmann,
	mit-devel, linux-kernel

On 04/21/2008 03:36 PM, Dmitry Torokhov wrote:
> On Mon, Apr 21, 2008 at 11:25:43AM +0200, Jiri Kosina wrote:
>> On Sun, 20 Apr 2008, Anssi Hannula wrote:
>>
>>> Why not just do something like
>>>
>>> #define HID_DEVICE(vend, dev) \
>>> 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
>>> 		       USB_DEVICE_ID_MATCH_INT_CLASS, \
>>> 	.idVendor = (vend), \
>>> 	.idProduct = (prod), \
>>> 	.bInterfaceClass = USB_INTERFACE_CLASS_HID
>>> (see linux/usb.h)
>>>
>>> and use USB hotplugging?
>>> Or do we plan to match against something else as well, such as hid
>>> reports or something?
>> No, we plan to do matching based solely on VID/PID. The report-specific 
>> stuff is then handled between the specific driver and HID generic code.
>>
> 
> Hmm, [ab]using USB modalias makes me a bit uneasy. What about bluetooth
> HID devices?

I do agree, it won't be nice and abstract enough. Working on it, give me some 
time, please.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-20 11:57               ` Jiri Slaby
@ 2008-04-22  0:00                 ` Jiri Kosina
  2008-04-27 11:22                   ` Jiri Slaby
  2008-05-09 21:24                   ` Jiri Slaby
  0 siblings, 2 replies; 30+ messages in thread
From: Jiri Kosina @ 2008-04-22  0:00 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: Dmitry Torokhov, linux-input, marcel, mit-devel, linux-kernel

On Sun, 20 Apr 2008, Jiri Slaby wrote:

> So I suppose we still need the option to let users compile all the 
> chosen drivers into hid.

Another possible workaround is to introduce dummy "hid" module, that will 
just depend on all other drivers with a reference to certail symbol (and 
this could of course be optional as CONFIG_HID_COMPAT, or whatever).

Thanks,

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-22  0:00                 ` Jiri Kosina
@ 2008-04-27 11:22                   ` Jiri Slaby
  2008-05-09 21:24                   ` Jiri Slaby
  1 sibling, 0 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-04-27 11:22 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: Dmitry Torokhov, linux-input, marcel, mit-devel, linux-kernel

On 04/22/2008 02:00 AM, Jiri Kosina wrote:
> On Sun, 20 Apr 2008, Jiri Slaby wrote:
> 
>> So I suppose we still need the option to let users compile all the 
>> chosen drivers into hid.
> 
> Another possible workaround is to introduce dummy "hid" module, that will 
> just depend on all other drivers with a reference to certail symbol (and 
> this could of course be optional as CONFIG_HID_COMPAT, or whatever).

If I understand correctly, it would create circular dependency:
hid->dummy_hid->hid_apple->hid

Is is correct?

Thanks.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: HID bus
  2008-04-22  0:00                 ` Jiri Kosina
  2008-04-27 11:22                   ` Jiri Slaby
@ 2008-05-09 21:24                   ` Jiri Slaby
  1 sibling, 0 replies; 30+ messages in thread
From: Jiri Slaby @ 2008-05-09 21:24 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: Dmitry Torokhov, linux-input, marcel, mit-devel, linux-kernel

On 04/22/2008 02:00 AM, Jiri Kosina wrote:
> On Sun, 20 Apr 2008, Jiri Slaby wrote:
> 
>> So I suppose we still need the option to let users compile all the 
>> chosen drivers into hid.

This won't work either. It wouldn't link due to multiple definitions of 
module_init, module_exit and some module tables.

> Another possible workaround is to introduce dummy "hid" module, that will 
> just depend on all other drivers with a reference to certail symbol (and 
> this could of course be optional as CONFIG_HID_COMPAT, or whatever).

Actually this may work if we load hid_dummy by request_module from hid. I have 
no other better idea.

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2008-05-09 21:25 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-04-04 20:35 Hid bus #2 Jiri Slaby
2008-04-04 20:35 ` [RFC 1/8] HID: make a bus from hid code Jiri Slaby
2008-04-04 20:35 ` [RFC 2/8] HID: hid, make parsing event driven Jiri Slaby
2008-04-04 20:35 ` [RFC 3/8] HID: move ids into separate file Jiri Slaby
2008-04-04 20:35 ` [RFC 4/8] HID: move usage input mapping to hid.h Jiri Slaby
2008-04-04 20:35 ` [RFC 5/8] HID: move logitech report quirks Jiri Slaby
2008-04-04 20:35 ` [RFC 6/8] HID: move ignore quirks Jiri Slaby
2008-04-04 20:35 ` [RFC 7/8] HID: move apple quirks Jiri Slaby
2008-04-16 13:31   ` HID bus Jiri Kosina
2008-04-16 14:43     ` Jiri Slaby
2008-04-16 20:30     ` Jiri Slaby
2008-04-16 20:45       ` Dmitry Torokhov
2008-04-16 20:54         ` Jiri Slaby
2008-04-16 21:05           ` Dmitry Torokhov
2008-04-18 11:36           ` Jiri Kosina
2008-04-19 22:38             ` Jiri Slaby
2008-04-20 11:57               ` Jiri Slaby
2008-04-22  0:00                 ` Jiri Kosina
2008-04-27 11:22                   ` Jiri Slaby
2008-05-09 21:24                   ` Jiri Slaby
2008-04-20 16:15               ` Anssi Hannula
2008-04-20 18:07                 ` Jiri Slaby
2008-04-21  9:25                 ` Jiri Kosina
2008-04-21 13:36                   ` Dmitry Torokhov
2008-04-21 23:05                     ` Jiri Slaby
2008-04-16 13:45   ` [RFC 7/8] HID: move apple quirks Jiri Kosina
2008-04-16 14:42     ` Jiri Slaby
2008-04-18 11:33       ` Jiri Kosina
2008-04-18 11:35         ` David Miller
2008-04-04 20:35 ` [RFC 8/8] test Jiri Slaby

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).