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

HID: Sunplus Wireless Desktop needs report descriptor fixup

This device has reports lower logical maximum compared to the real
usages for Zoom+ and Zoom- it emits.

This patch bumps the values in the report descriptor up, and also
adjusts HID_MAX_USAGE accordingly.

Reported-by: Khelben Blackstaff <eye.of.the.8eholder@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

+42 -2
+21 -1
drivers/hid/hid-input-quirks.c
··· 276 276 return 1; 277 277 } 278 278 279 + static int quirk_sunplus_wdesktop(struct hid_usage *usage, struct input_dev *input, 280 + unsigned long **bit, int *max) 281 + { 282 + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) 283 + return 0; 284 + 285 + switch (usage->hid & HID_USAGE) { 286 + case 0x2003: map_key_clear(KEY_ZOOMIN); break; 287 + case 0x2103: map_key_clear(KEY_ZOOMOUT); break; 288 + default: 289 + return 0; 290 + } 291 + return 1; 292 + } 293 + 279 294 #define VENDOR_ID_BELKIN 0x1020 280 295 #define DEVICE_ID_BELKIN_WIRELESS_KEYBOARD 0x0006 281 296 ··· 321 306 #define VENDOR_ID_PETALYNX 0x18b1 322 307 #define DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037 323 308 309 + #define VENDOR_ID_SUNPLUS 0x04fc 310 + #define DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8 311 + 324 312 static const struct hid_input_blacklist { 325 313 __u16 idVendor; 326 314 __u16 idProduct; ··· 350 332 { VENDOR_ID_MONTEREY, DEVICE_ID_GENIUS_KB29E, quirk_cherry_genius_29e }, 351 333 352 334 { VENDOR_ID_PETALYNX, DEVICE_ID_PETALYNX_MAXTER_REMOTE, quirk_petalynx_remote }, 353 - 335 + 336 + { VENDOR_ID_SUNPLUS, DEVICE_ID_SUNPLUS_WDESKTOP, quirk_sunplus_wdesktop }, 337 + 354 338 { 0, 0, 0 } 355 339 }; 356 340
+19
drivers/hid/usbhid/hid-quirks.c
··· 381 381 #define USB_VENDOR_ID_SUN 0x0430 382 382 #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab 383 383 384 + #define USB_VENDOR_ID_SUNPLUS 0x04fc 385 + #define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8 386 + 384 387 #define USB_VENDOR_ID_TOPMAX 0x0663 385 388 #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 386 389 ··· 738 735 739 736 { USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_RDESC_SAMSUNG_REMOTE }, 740 737 738 + { USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP, HID_QUIRK_RDESC_SUNPLUS_WDESKTOP }, 739 + 741 740 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX }, 742 741 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX }, 743 742 ··· 1014 1009 } 1015 1010 } 1016 1011 1012 + static void usbhid_fixup_sunplus_wdesktop(unsigned char *rdesc, int rsize) 1013 + { 1014 + if (rsize >= 107 && rdesc[104] == 0x26 1015 + && rdesc[105] == 0x80 1016 + && rdesc[106] == 0x03) { 1017 + printk(KERN_INFO "Fixing up Sunplus Wireless Desktop report descriptor\n"); 1018 + rdesc[105] = rdesc[110] = 0x03; 1019 + rdesc[106] = rdesc[111] = 0x21; 1020 + } 1021 + } 1022 + 1017 1023 /* 1018 1024 * Samsung IrDA remote controller (reports as Cypress USB Mouse). 1019 1025 * ··· 1197 1181 else if (paramVendor == idVendor && paramProduct == idProduct) 1198 1182 __usbhid_fixup_report_descriptor(quirks, rdesc, rsize); 1199 1183 } 1184 + 1185 + if (quirks & HID_QUIRK_RDESC_SUNPLUS_WDESKTOP) 1186 + usbhid_fixup_sunplus_wdesktop(rdesc, rsize); 1200 1187 1201 1188 }
+2 -1
include/linux/hid.h
··· 298 298 #define HID_QUIRK_RDESC_BUTTON_CONSUMER 0x00000020 299 299 #define HID_QUIRK_RDESC_SAMSUNG_REMOTE 0x00000040 300 300 #define HID_QUIRK_RDESC_MICROSOFT_RECV_1028 0x00000080 301 + #define HID_QUIRK_RDESC_SUNPLUS_WDESKTOP 0x00000100 301 302 302 303 /* 303 304 * This is the global environment of the parser. This information is ··· 323 322 * This is the local environment. It is persistent up the next main-item. 324 323 */ 325 324 326 - #define HID_MAX_USAGES 8192 325 + #define HID_MAX_USAGES 12288 327 326 #define HID_DEFAULT_NUM_COLLECTIONS 16 328 327 329 328 struct hid_local {