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); |