diff options
| -rw-r--r-- | drivers/hid/usbhid/hid-core.c | 13 | ||||
| -rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 38 | ||||
| -rw-r--r-- | include/linux/hid.h | 8 |
3 files changed, 59 insertions, 0 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index bf118c05a621..91d610358d57 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
| @@ -53,6 +53,13 @@ static unsigned int hid_mousepoll_interval; | |||
| 53 | module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); | 53 | module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); |
| 54 | MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); | 54 | MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); |
| 55 | 55 | ||
| 56 | /* Quirks specified at module load time */ | ||
| 57 | static char *quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL }; | ||
| 58 | module_param_array_named(quirks, quirks_param, charp, NULL, 0444); | ||
| 59 | MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying " | ||
| 60 | " quirks=vendorID:productID:quirks" | ||
| 61 | " where vendorID, productID, and quirks are all in" | ||
| 62 | " 0x-prefixed hex"); | ||
| 56 | /* | 63 | /* |
| 57 | * Input submission and I/O error handler. | 64 | * Input submission and I/O error handler. |
| 58 | */ | 65 | */ |
| @@ -1072,6 +1079,9 @@ static struct usb_driver hid_driver = { | |||
| 1072 | static int __init hid_init(void) | 1079 | static int __init hid_init(void) |
| 1073 | { | 1080 | { |
| 1074 | int retval; | 1081 | int retval; |
| 1082 | retval = usbhid_quirks_init(quirks_param); | ||
| 1083 | if (retval) | ||
| 1084 | goto usbhid_quirks_init_fail; | ||
| 1075 | retval = hiddev_init(); | 1085 | retval = hiddev_init(); |
| 1076 | if (retval) | 1086 | if (retval) |
| 1077 | goto hiddev_init_fail; | 1087 | goto hiddev_init_fail; |
| @@ -1084,6 +1094,8 @@ static int __init hid_init(void) | |||
| 1084 | usb_register_fail: | 1094 | usb_register_fail: |
| 1085 | hiddev_exit(); | 1095 | hiddev_exit(); |
| 1086 | hiddev_init_fail: | 1096 | hiddev_init_fail: |
| 1097 | usbhid_quirks_exit(); | ||
| 1098 | usbhid_quirks_init_fail: | ||
| 1087 | return retval; | 1099 | return retval; |
| 1088 | } | 1100 | } |
| 1089 | 1101 | ||
| @@ -1091,6 +1103,7 @@ static void __exit hid_exit(void) | |||
| 1091 | { | 1103 | { |
| 1092 | usb_deregister(&hid_driver); | 1104 | usb_deregister(&hid_driver); |
| 1093 | hiddev_exit(); | 1105 | hiddev_exit(); |
| 1106 | usbhid_quirks_exit(); | ||
| 1094 | } | 1107 | } |
| 1095 | 1108 | ||
| 1096 | module_init(hid_init); | 1109 | module_init(hid_init); |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index a5fc8b5144ef..27188bd1e851 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
| @@ -576,6 +576,44 @@ static void usbhid_remove_all_dquirks(void) | |||
| 576 | 576 | ||
| 577 | } | 577 | } |
| 578 | 578 | ||
| 579 | /** | ||
| 580 | * usbhid_quirks_init: apply USB HID quirks specified at module load time | ||
| 581 | */ | ||
| 582 | int usbhid_quirks_init(char **quirks_param) | ||
| 583 | { | ||
| 584 | u16 idVendor, idProduct; | ||
| 585 | u32 quirks; | ||
| 586 | int n = 0, m; | ||
| 587 | |||
| 588 | for (; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) { | ||
| 589 | |||
| 590 | m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x", | ||
| 591 | &idVendor, &idProduct, &quirks); | ||
| 592 | |||
| 593 | if (m != 3 || | ||
| 594 | usbhid_modify_dquirk(idVendor, idProduct, quirks) != 0) { | ||
| 595 | printk(KERN_WARNING | ||
| 596 | "Could not parse HID quirk module param %s\n", | ||
| 597 | quirks_param[n]); | ||
| 598 | } | ||
| 599 | } | ||
| 600 | |||
| 601 | return 0; | ||
| 602 | } | ||
| 603 | |||
| 604 | /** | ||
| 605 | * usbhid_quirks_exit: release memory associated with dynamic_quirks | ||
| 606 | * | ||
| 607 | * Description: | ||
| 608 | * Release all memory associated with dynamic quirks. Called upon | ||
| 609 | * module unload. | ||
| 610 | * | ||
| 611 | * Returns: nothing | ||
| 612 | */ | ||
| 613 | void usbhid_quirks_exit(void) | ||
| 614 | { | ||
| 615 | usbhid_remove_all_dquirks(); | ||
| 616 | } | ||
| 579 | 617 | ||
| 580 | /** | 618 | /** |
| 581 | * usbhid_exists_squirk: return any static quirks for a USB HID device | 619 | * usbhid_exists_squirk: return any static quirks for a USB HID device |
diff --git a/include/linux/hid.h b/include/linux/hid.h index 4ba456d71f6b..37076b116ed0 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -247,6 +247,11 @@ struct hid_item { | |||
| 247 | * HID device quirks. | 247 | * HID device quirks. |
| 248 | */ | 248 | */ |
| 249 | 249 | ||
| 250 | /* | ||
| 251 | * Increase this if you need to configure more HID quirks at module load time | ||
| 252 | */ | ||
| 253 | #define MAX_USBHID_BOOT_QUIRKS 4 | ||
| 254 | |||
| 250 | #define HID_QUIRK_INVERT 0x00000001 | 255 | #define HID_QUIRK_INVERT 0x00000001 |
| 251 | #define HID_QUIRK_NOTOUCH 0x00000002 | 256 | #define HID_QUIRK_NOTOUCH 0x00000002 |
| 252 | #define HID_QUIRK_IGNORE 0x00000004 | 257 | #define HID_QUIRK_IGNORE 0x00000004 |
| @@ -495,8 +500,11 @@ void hid_output_report(struct hid_report *report, __u8 *data); | |||
| 495 | void hid_free_device(struct hid_device *device); | 500 | void hid_free_device(struct hid_device *device); |
| 496 | struct hid_device *hid_parse_report(__u8 *start, unsigned size); | 501 | struct hid_device *hid_parse_report(__u8 *start, unsigned size); |
| 497 | 502 | ||
| 503 | /* HID quirks API */ | ||
| 498 | u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct); | 504 | u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct); |
| 499 | int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, const u32 quirks); | 505 | int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, const u32 quirks); |
| 506 | int usbhid_quirks_init(char **quirks_param); | ||
| 507 | void usbhid_quirks_exit(void); | ||
| 500 | 508 | ||
| 501 | #ifdef CONFIG_HID_FF | 509 | #ifdef CONFIG_HID_FF |
| 502 | int hid_ff_init(struct hid_device *hid); | 510 | int hid_ff_init(struct hid_device *hid); |
