From ed596a4a88bd161f868ccba078557ee7ede8a6ef Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 31 May 2016 14:48:15 +0200 Subject: HID: elo: kill not flush the work Flushing a work that reschedules itself is not a sensible operation. It needs to be killed. Failure to do so leads to a kernel panic in the timer code. CC: stable@vger.kernel.org Signed-off-by: Oliver Neukum Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-elo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c index aad8c162a825..0cd4f7216239 100644 --- a/drivers/hid/hid-elo.c +++ b/drivers/hid/hid-elo.c @@ -261,7 +261,7 @@ static void elo_remove(struct hid_device *hdev) struct elo_priv *priv = hid_get_drvdata(hdev); hid_hw_stop(hdev); - flush_workqueue(wq); + cancel_delayed_work_sync(&priv->work); kfree(priv); } -- cgit v1.2.3 From a80e803a2ae4efa5efbcfa97dcbbc48d15226cf9 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 31 May 2016 17:31:15 +0200 Subject: HID: multitouch: Add MT_QUIRK_NOT_SEEN_MEANS_UP to Surface Pro 3 The firmware found in the touch screen of an SP3 is buggy and may miss to send lift off reports for contacts. Try to work around that issue by using MT_QUIRK_NOT_SEEN_MEANS_UP. based on a patch from: Daniel Martin Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index c741f5e50a66..95b7d61d9910 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1401,6 +1401,11 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_PCT) }, + /* Ntrig Panel */ + { .driver_data = MT_CLS_NSMU, + HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, + USB_VENDOR_ID_NTRIG, 0x1b05) }, + /* PixArt optical touch screen */ { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER, MT_USB_DEVICE(USB_VENDOR_ID_PIXART, -- cgit v1.2.3 From 67f8ecc550b5bda03335f845dc869b8501d25fd0 Mon Sep 17 00:00:00 2001 From: Roderick Colenbrander Date: Wed, 18 May 2016 13:11:09 -0700 Subject: HID: uhid: fix timeout when probe races with IO Many devices use userspace bluetooth stacks like BlueZ or Bluedroid in combination with uhid. If any of these stacks is used with a HID device for which the driver performs a HID request as part .probe (or technically another HID operation), this results in a deadlock situation. The deadlock results in a 5 second timeout for I/O operations in HID drivers, so isn't fatal, but none of the I/O operations have a chance of succeeding. The root cause for the problem is that uhid only allows for one request to be processed at a time per uhid instance and locks out other operations. This means that if a user space is creating a new HID device through 'UHID_CREATE', which ultimately triggers '.probe' through the HID layer. Then any HID request e.g. a read for calibration data would trigger a HID operation on uhid again, but it won't go out to userspace, because it is still stuck in UHID_CREATE. In addition bluetooth stacks are typically single threaded, so they wouldn't be able to handle any requests while waiting on uhid. Lucikly the UHID spec is somewhat flexible and allows for fixing the issue, without breaking user space. The idea which the patch implements as discussed with David Herrmann is to decouple adding of a hid device (which triggers .probe) from UHID_CREATE. The work will kick off roughly once UHID_CREATE completed (or else will wait a tiny bit of time in .probe for a lock). A HID driver has to call HID to call 'hid_hw_start()' as part of .probe once it is ready for I/O, which triggers UHID_START to user space. Any HID operations should function now within .probe and won't deadlock because userspace is stuck on UHID_CREATE. We verified this patch on Bluedroid with Android 6.0 and on desktop Linux with BlueZ stacks. Prior to the patch they had the deadlock issue. [jkosina@suse.cz: reword subject] Signed-off-by: Roderick Colenbrander Cc: stable@vger.kernel.org Signed-off-by: Jiri Kosina --- drivers/hid/uhid.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index 16b6f11a0700..99ec3ff7563b 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c @@ -51,10 +51,26 @@ struct uhid_device { u32 report_id; u32 report_type; struct uhid_event report_buf; + struct work_struct worker; }; static struct miscdevice uhid_misc; +static void uhid_device_add_worker(struct work_struct *work) +{ + struct uhid_device *uhid = container_of(work, struct uhid_device, worker); + int ret; + + ret = hid_add_device(uhid->hid); + if (ret) { + hid_err(uhid->hid, "Cannot register HID device: error %d\n", ret); + + hid_destroy_device(uhid->hid); + uhid->hid = NULL; + uhid->running = false; + } +} + static void uhid_queue(struct uhid_device *uhid, struct uhid_event *ev) { __u8 newhead; @@ -498,18 +514,14 @@ static int uhid_dev_create2(struct uhid_device *uhid, uhid->hid = hid; uhid->running = true; - ret = hid_add_device(hid); - if (ret) { - hid_err(hid, "Cannot register HID device\n"); - goto err_hid; - } + /* Adding of a HID device is done through a worker, to allow HID drivers + * which use feature requests during .probe to work, without they would + * be blocked on devlock, which is held by uhid_char_write. + */ + schedule_work(&uhid->worker); return 0; -err_hid: - hid_destroy_device(hid); - uhid->hid = NULL; - uhid->running = false; err_free: kfree(uhid->rd_data); uhid->rd_data = NULL; @@ -550,6 +562,8 @@ static int uhid_dev_destroy(struct uhid_device *uhid) uhid->running = false; wake_up_interruptible(&uhid->report_wait); + cancel_work_sync(&uhid->worker); + hid_destroy_device(uhid->hid); kfree(uhid->rd_data); @@ -612,6 +626,7 @@ static int uhid_char_open(struct inode *inode, struct file *file) init_waitqueue_head(&uhid->waitq); init_waitqueue_head(&uhid->report_wait); uhid->running = false; + INIT_WORK(&uhid->worker, uhid_device_add_worker); file->private_data = uhid; nonseekable_open(inode, file); -- cgit v1.2.3 From 982e42d655ad9a579147e0feaf9a050b57d3d71e Mon Sep 17 00:00:00 2001 From: "Fu, Zhonghui" Date: Thu, 19 May 2016 10:46:24 +0800 Subject: HID: i2c_hid: enable i2c-hid devices to suspend/resume asynchronously i2c-hid devices' suspend/resume are usually time-consuming process. For example, the touch controller(i2c-ATML1000:00) on ASUS T100 tablet takes about 160ms for suspending and 120ms for resuming. This patch enables i2c-hid devices to suspend/resume asynchronously. This will take advantage of multicore and speed up system suspend/resume process. Signed-off-by: Zhonghui Fu Acked-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/hid') diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 2e021ba8ff05..cc41e1ef8255 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -1020,6 +1020,7 @@ static int i2c_hid_probe(struct i2c_client *client, pm_runtime_get_noresume(&client->dev); pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); + device_enable_async_suspend(&client->dev); ret = i2c_hid_fetch_hid_descriptor(ihid); if (ret < 0) -- cgit v1.2.3 From ddfe8483e9a938ed82b411e1f47c3249f0567658 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 19 Jun 2016 15:46:02 +0200 Subject: HID: thingm: simplify debug output code Kernel printf format %*ph allows to print small buffers up to 64 bytes. Make use of it to simplify the debug output code. Signed-off-by: Heiner Kallweit Signed-off-by: Jiri Kosina --- drivers/hid/hid-thingm.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c index 9ad9c6ec5bba..9b4fec4ed149 100644 --- a/drivers/hid/hid-thingm.c +++ b/drivers/hid/hid-thingm.c @@ -73,9 +73,7 @@ static int thingm_send(struct thingm_device *tdev, u8 buf[REPORT_SIZE]) { int ret; - hid_dbg(tdev->hdev, "-> %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n", - buf[0], buf[1], buf[2], buf[3], buf[4], - buf[5], buf[6], buf[7], buf[8]); + hid_dbg(tdev->hdev, "-> %d %c %7ph\n", buf[0], buf[1], &buf[2]); mutex_lock(&tdev->lock); @@ -110,9 +108,7 @@ static int thingm_recv(struct thingm_device *tdev, u8 buf[REPORT_SIZE]) ret = 0; - hid_dbg(tdev->hdev, "<- %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n", - buf[0], buf[1], buf[2], buf[3], buf[4], - buf[5], buf[6], buf[7], buf[8]); + hid_dbg(tdev->hdev, "<- %d %c %7ph\n", buf[0], buf[1], &buf[2]); err: mutex_unlock(&tdev->lock); return ret; -- cgit v1.2.3 From d9f448e3d71f3a703977196fa73be533b4b85adc Mon Sep 17 00:00:00 2001 From: Guohua Zhong Date: Tue, 21 Jun 2016 18:27:45 +0800 Subject: HID: i2c-hid: set power sleep before shutdown Add i2c_hid_shutdown for i2c-hid driver to send suspend cmd & free irq before device shutdown. Some HW design (i.e. Umaro, a chromebook model) is that the power to i2c hid device won't down after device shutdown. Also the i2c-hid driver do not send suspend cmd to the hid i2c device and free its irq before shutdown.So if We touch the touchscreen or some other i2c hid device, the power consumtion will be go up even when the device is in shutdown state. Though the root cause maybe a HW issue. But it seems that it is a good pratice to set power sleep for i2c-hid device before shutdown. Signed-off-by: Guohua Zhong Acked-By: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index cc41e1ef8255..b3ec4f2de875 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -1107,6 +1107,14 @@ static int i2c_hid_remove(struct i2c_client *client) return 0; } +static void i2c_hid_shutdown(struct i2c_client *client) +{ + struct i2c_hid *ihid = i2c_get_clientdata(client); + + i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); + free_irq(client->irq, ihid); +} + #ifdef CONFIG_PM_SLEEP static int i2c_hid_suspend(struct device *dev) { @@ -1231,7 +1239,7 @@ static struct i2c_driver i2c_hid_driver = { .probe = i2c_hid_probe, .remove = i2c_hid_remove, - + .shutdown = i2c_hid_shutdown, .id_table = i2c_hid_id_table, }; -- cgit v1.2.3 From 93a2001bdfd5376c3dc2158653034c20392d15c5 Mon Sep 17 00:00:00 2001 From: Scott Bauer Date: Thu, 23 Jun 2016 08:59:47 -0600 Subject: HID: hiddev: validate num_values for HIDIOCGUSAGES, HIDIOCSUSAGES commands This patch validates the num_values parameter from userland during the HIDIOCGUSAGES and HIDIOCSUSAGES commands. Previously, if the report id was set to HID_REPORT_ID_UNKNOWN, we would fail to validate the num_values parameter leading to a heap overflow. Cc: stable@vger.kernel.org Signed-off-by: Scott Bauer Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 2f1ddca6f2e0..700145b15088 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -516,13 +516,13 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, goto inval; } else if (uref->usage_index >= field->report_count) goto inval; - - else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && - (uref_multi->num_values > HID_MAX_MULTI_USAGES || - uref->usage_index + uref_multi->num_values > field->report_count)) - goto inval; } + if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && + (uref_multi->num_values > HID_MAX_MULTI_USAGES || + uref->usage_index + uref_multi->num_values > field->report_count)) + goto inval; + switch (cmd) { case HIDIOCGUSAGE: uref->value = field->value[uref->usage_index]; -- cgit v1.2.3 From 62630ea768869beeb1e514b0bf5607a0c9b93d12 Mon Sep 17 00:00:00 2001 From: Allen Hung Date: Thu, 23 Jun 2016 16:31:29 +0800 Subject: Revert "HID: multitouch: enable palm rejection if device implements confidence usage" This reverts commit 25a84db15b3f ("HID: multitouch: enable palm rejection if device implements confidence usage") The commit enables palm rejection for Win8 Precision Touchpad devices but the quirk MT_QUIRK_VALID_IS_CONFIDENCE it is using is not working very properly. This quirk is originally designed for some WIn7 touchscreens. Use of this for a Win8 Precision Touchpad will cause unexpected pointer jumping problem. Cc: stable@vger.kernel.org # v4.5+ Reviewed-by: Benjamin Tissoires Tested-by: Andy Lutomirski # XPS 13 9350, BIOS 1.4.3 Signed-off-by: Allen Hung Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 95b7d61d9910..4ef700688657 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -502,11 +502,6 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, mt_store_field(usage, td, hi); return 1; case HID_DG_CONFIDENCE: - if (cls->name == MT_CLS_WIN_8 && - field->application == HID_DG_TOUCHPAD) { - cls->quirks &= ~MT_QUIRK_ALWAYS_VALID; - cls->quirks |= MT_QUIRK_VALID_IS_CONFIDENCE; - } mt_store_field(usage, td, hi); return 1; case HID_DG_TIPSWITCH: -- cgit v1.2.3 From 6dd2e27a103d716921cc4a1a96a9adc0a8e3ab57 Mon Sep 17 00:00:00 2001 From: Allen Hung Date: Thu, 23 Jun 2016 16:31:30 +0800 Subject: HID: multitouch: enable palm rejection for Windows Precision Touchpad The usage Confidence is mandary to Windows Precision Touchpad devices. If it is examined in input_mapping on a WIndows Precision Touchpad, a new add quirk MT_QUIRK_CONFIDENCE desgned for such devices will be applied to the device. A touch with the confidence bit is not set is determined as invalid. Tested on Dell XPS13 9343 Cc: stable@vger.kernel.org # v4.5+ Reviewed-by: Benjamin Tissoires Tested-by: Andy Lutomirski # XPS 13 9350, BIOS 1.4.3 Signed-off-by: Allen Hung Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 4ef700688657..fb6f1f447279 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -61,6 +61,7 @@ MODULE_LICENSE("GPL"); #define MT_QUIRK_ALWAYS_VALID (1 << 4) #define MT_QUIRK_VALID_IS_INRANGE (1 << 5) #define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6) +#define MT_QUIRK_CONFIDENCE (1 << 7) #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8) #define MT_QUIRK_NO_AREA (1 << 9) #define MT_QUIRK_IGNORE_DUPLICATES (1 << 10) @@ -78,6 +79,7 @@ struct mt_slot { __s32 contactid; /* the device ContactID assigned to this slot */ bool touch_state; /* is the touch valid? */ bool inrange_state; /* is the finger in proximity of the sensor? */ + bool confidence_state; /* is the touch made by a finger? */ }; struct mt_class { @@ -502,6 +504,9 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, mt_store_field(usage, td, hi); return 1; case HID_DG_CONFIDENCE: + if (cls->name == MT_CLS_WIN_8 && + field->application == HID_DG_TOUCHPAD) + cls->quirks |= MT_QUIRK_CONFIDENCE; mt_store_field(usage, td, hi); return 1; case HID_DG_TIPSWITCH: @@ -614,6 +619,7 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input) return; if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) { + int active; int slotnum = mt_compute_slot(td, input); struct mt_slot *s = &td->curdata; struct input_mt *mt = input->mt; @@ -628,10 +634,14 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input) return; } + if (!(td->mtclass.quirks & MT_QUIRK_CONFIDENCE)) + s->confidence_state = 1; + active = (s->touch_state || s->inrange_state) && + s->confidence_state; + input_mt_slot(input, slotnum); - input_mt_report_slot_state(input, MT_TOOL_FINGER, - s->touch_state || s->inrange_state); - if (s->touch_state || s->inrange_state) { + input_mt_report_slot_state(input, MT_TOOL_FINGER, active); + if (active) { /* this finger is in proximity of the sensor */ int wide = (s->w > s->h); /* divided by two to match visual scale of touch */ @@ -696,6 +706,8 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, td->curdata.touch_state = value; break; case HID_DG_CONFIDENCE: + if (quirks & MT_QUIRK_CONFIDENCE) + td->curdata.confidence_state = value; if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE) td->curvalid = value; break; -- cgit v1.2.3 From b5d9427549be859dd42c5a6c635bc09d1d07b00b Mon Sep 17 00:00:00 2001 From: Jean-Gabriel Gill-Couture Date: Mon, 11 Jul 2016 17:41:26 +0200 Subject: HID: add usb device id for Apple Magic Keyboard USB device Vendor 05ac (Apple) Device 0267 (Magic Keyboard) This keyboard supports both Bluetooth and USB connections, this patch only covers USB. Thanks to Maxime Poulin Signed-off-by: Jean-Gabriel Gill-Couture Signed-off-by: Jiri Kosina --- drivers/hid/hid-apple.c | 2 ++ drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + 3 files changed, 4 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 884d82f9190e..2e046082210f 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -474,6 +474,8 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI), + .driver_data = APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), .driver_data = APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 8ea3a26360e9..21eadd9abca3 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1851,6 +1851,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 3eec09a134cb..b5e5415fdf79 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -142,6 +142,7 @@ #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI 0x0255 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS 0x0257 +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI 0x0267 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0290 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0291 #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0292 -- cgit v1.2.3