Before this patch it was possible to specify quirks using run-time parameters only for the usbhid module. This patch introduces a quirks parameter for hid-core allowing to specify quirks as hid.quirks=BUS:vendorID:productID:quirks Signed-off-by: Marco Morandini <marco.morandini@xxxxxxxxx> --- I don't know if this is a good idea or not. If it was for me, I'd get rid of the usbhid parameters and of the duplicated hid_quirks_init, forcing everyone to specify the bus, but I fear this could be a regression for user space. drivers/hid/hid-core.c | 13 +++++++++++++ drivers/hid/hid-quirks.c | 33 +++++++++++++++++++++++++++++++++ include/linux/hid.h | 1 + 3 files changed, 47 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 22623eb4f72f..e1bdba978dbc 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -45,6 +45,13 @@ static int hid_ignore_special_drivers = 0; module_param_named(ignore_special_drivers, hid_ignore_special_drivers, int, 0600); MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special drivers and handle all devices by generic driver"); +/* Quirks specified at module load time */ +static char *quirks_param[MAX_USBHID_BOOT_QUIRKS]; +module_param_array_named(quirks, quirks_param, charp, NULL, 0444); +MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying " + " quirks=BUS:vendorID:productID:quirks" + " where BUS, vendorID, productID, and quirks are all in" + " 0x-prefixed hex"); /* * Register a new report for a device. */ @@ -2951,6 +2958,10 @@ static int __init hid_init(void) { int ret; + ret = hid_quirks_bus_init(quirks_param, MAX_USBHID_BOOT_QUIRKS); + if (ret) + goto usbhid_quirks_init_fail; + ret = bus_register(&hid_bus_type); if (ret) { pr_err("can't register hid bus\n"); @@ -2972,6 +2983,8 @@ static int __init hid_init(void) bus_unregister(&hid_bus_type); err: return ret; +usbhid_quirks_init_fail: + return ret; } static void __exit hid_exit(void) diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index 3983b4f282f8..40d3ba78ff73 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -1182,6 +1182,39 @@ static void hid_remove_all_dquirks(__u16 bus) } + +/** + * hid_quirks_bus_init - apply HID quirks specified at module load time + * @quirks_param: array of quirks strings (bus:vendor:product:quirks) + * @count: number of quirks to check + */ +int hid_quirks_bus_init(char **quirks_param, int count) +{ + struct hid_device_id id = { 0 }; + int n = 0, m; + unsigned short int bus, vendor, product; + u32 quirks; + + for (; n < count && quirks_param[n]; n++) { + + m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%hx:0x%x", + &bus, &vendor, &product, &quirks); + + id.bus = (__u16)bus; + id.vendor = (__u16)vendor; + id.product = (__u16)product; + + if (m != 4 || + hid_modify_dquirk(&id, quirks) != 0) { + pr_warn("Could not parse HID quirk module param %s\n", + quirks_param[n]); + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(hid_quirks_bus_init); + /** * hid_quirks_init - apply HID quirks specified at module load time * @quirks_param: array of quirks strings (vendor:product:quirks) diff --git a/include/linux/hid.h b/include/linux/hid.h index 4e4c4fe36911..7f2e8ba7d783 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -1178,6 +1178,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 * /* HID quirks API */ unsigned long hid_lookup_quirk(const struct hid_device *hdev); +int hid_quirks_bus_init(char **quirks_param, int count); int hid_quirks_init(char **quirks_param, __u16 bus, int count); void hid_quirks_exit(__u16 bus); -- 2.41.0