Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HID: fixup fullspeed interval on highspeed Afatech DVB-T IR kbd

Many vendors highspeed devices give erroneously fullspeed interval value in
endpoint descriptor for interrupt endpoints. This quirk fixes up that by
recalculating the right value for highspeed device.

At the time of hid configuration this quirk calculates which highspeed interval
value gives same interval delay as, or next smaller then, what it would be if
the original value would be interpreted as fullspeed value. In subsequent urbs
that new value is used instead.

Forming the 'hid->name' in usb_hid_config() was moved up to accommodate more
descriptive printk reporting the fixup.

In this patch the quirk is set for one such device: Afatech DVB-T 2 infrared
HID-keyboard. It reports value 16 which means 4,069s in highspeed while
obviously 16ms was intended. In this case quirk calculates new value to be 8
which gives when interpreted as highspeed value 16ms as wanted. The behavior of
the device was verified to be what expected both before and after the patch.

Signed-off-by: Pekka Sarnila <sarnila@adit.fi>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

authored by

Pekka Sarnila and committed by
Jiri Kosina
f345c37c cf2a299e

+30 -16
+24 -16
drivers/hid/usbhid/hid-core.c
··· 800 800 goto fail; 801 801 } 802 802 803 + hid->name[0] = 0; 804 + 805 + if (dev->manufacturer) 806 + strlcpy(hid->name, dev->manufacturer, sizeof(hid->name)); 807 + 808 + if (dev->product) { 809 + if (dev->manufacturer) 810 + strlcat(hid->name, " ", sizeof(hid->name)); 811 + strlcat(hid->name, dev->product, sizeof(hid->name)); 812 + } 813 + 814 + if (!strlen(hid->name)) 815 + snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x", 816 + le16_to_cpu(dev->descriptor.idVendor), 817 + le16_to_cpu(dev->descriptor.idProduct)); 818 + 803 819 for (n = 0; n < interface->desc.bNumEndpoints; n++) { 804 820 805 821 struct usb_endpoint_descriptor *endpoint; ··· 827 811 continue; 828 812 829 813 interval = endpoint->bInterval; 814 + 815 + /* Some vendors give fullspeed interval on highspeed devides */ 816 + if (quirks & HID_QUIRK_FULLSPEED_INTERVAL && 817 + dev->speed == USB_SPEED_HIGH) { 818 + interval = fls(endpoint->bInterval*8); 819 + printk(KERN_INFO "%s: Fixing fullspeed to highspeed interval: %d -> %d\n", 820 + hid->name, endpoint->bInterval, interval); 821 + } 830 822 831 823 /* Change the polling interval of mice. */ 832 824 if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) ··· 882 858 hid->dev = &intf->dev; 883 859 usbhid->intf = intf; 884 860 usbhid->ifnum = interface->desc.bInterfaceNumber; 885 - 886 - hid->name[0] = 0; 887 - 888 - if (dev->manufacturer) 889 - strlcpy(hid->name, dev->manufacturer, sizeof(hid->name)); 890 - 891 - if (dev->product) { 892 - if (dev->manufacturer) 893 - strlcat(hid->name, " ", sizeof(hid->name)); 894 - strlcat(hid->name, dev->product, sizeof(hid->name)); 895 - } 896 - 897 - if (!strlen(hid->name)) 898 - snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x", 899 - le16_to_cpu(dev->descriptor.idVendor), 900 - le16_to_cpu(dev->descriptor.idProduct)); 901 861 902 862 hid->bus = BUS_USB; 903 863 hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
+5
drivers/hid/usbhid/hid-quirks.c
··· 32 32 #define USB_VENDOR_ID_ADS_TECH 0x06e1 33 33 #define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155 34 34 35 + #define USB_VENDOR_ID_AFATECH 0x15a4 36 + #define USB_DEVICE_ID_AFATECH_AF9016 0x9016 37 + 35 38 #define USB_VENDOR_ID_AIPTEK 0x08ca 36 39 #define USB_DEVICE_ID_AIPTEK_01 0x0001 37 40 #define USB_DEVICE_ID_AIPTEK_10 0x0010 ··· 438 435 { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, 439 436 440 437 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES }, 438 + 439 + { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL }, 441 440 442 441 { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV }, 443 442 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT },
+1
include/linux/hid.h
··· 284 284 #define HID_QUIRK_2WHEEL_MOUSE_HACK_B8 0x02000000 285 285 #define HID_QUIRK_HWHEEL_WHEEL_INVERT 0x04000000 286 286 #define HID_QUIRK_MICROSOFT_KEYS 0x08000000 287 + #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 287 288 288 289 /* 289 290 * Separate quirks for runtime report descriptor fixup