[PATCH 1/1] HID: add have_special_driver hid module parameter

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add "have_special_driver" hid module parameter - a list of additional HID
devices which have specialized driver on HID bus. Needed to support out-of-tree
HID drivers.

Signed-off-by: Nikolai Kondrashov <spbnick@xxxxxxxxx>
---

I plan to use this with a DKMS package of my tablet drivers, which haven't yet
appeared in the end-user distributions. I'll be submitting them to the kernel
once they are tested, as usual.

 drivers/hid/hid-core.c |   80 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 79 insertions(+), 1 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index af08ce7..829d9a1 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -50,6 +50,21 @@ module_param_named(debug, hid_debug, int, 0600);
 MODULE_PARM_DESC(debug, "toggle HID debugging messages");
 EXPORT_SYMBOL_GPL(hid_debug);
 
+#define MAX_HAVE_SPECIAL_DRIVER_EXTRA 4
+
+static char *hid_have_special_driver_param[MAX_HAVE_SPECIAL_DRIVER_EXTRA] = {
+		NULL,
+};
+module_param_array_named(have_special_driver, hid_have_special_driver_param,
+			 charp, NULL, 0444);
+MODULE_PARM_DESC(have_special_driver,
+		 "A comma-separated list of additional HID devices which have "
+		 "specialized driver; each device is described as BUS:VID:PID, "
+		 "where BUS is either \"usb\" or \"bluetooth\" and both VID "
+		 "and PID are 0x-prefixed hex numbers, e.g. "
+		 "have_special_driver=bluetooth:0x1234:0x1234,"
+		 "usb:0x4321:0x4321");
+
 /*
  * Register a new report for a device.
  */
@@ -1578,6 +1593,13 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ }
 };
 
+/*
+ * An additional, load-time supplied list of devices which have specialized
+ * driver on HID bus.
+ */
+static struct hid_device_id hid_have_special_driver_extra[
+				MAX_HAVE_SPECIAL_DRIVER_EXTRA + 1] = { { } };
+
 struct hid_dynid {
 	struct list_head list;
 	struct hid_device_id id;
@@ -1668,7 +1690,8 @@ static int hid_bus_match(struct device *dev, struct device_driver *drv)
 
 	/* generic wants all that don't have specialized driver */
 	if (!strncmp(hdrv->name, "generic-", 8))
-		return !hid_match_id(hdev, hid_have_special_driver);
+		return !hid_match_id(hdev, hid_have_special_driver) &&
+		       !hid_match_id(hdev, hid_have_special_driver_extra);
 
 	return 1;
 }
@@ -2167,6 +2190,55 @@ int hid_check_keys_pressed(struct hid_device *hid)
 
 EXPORT_SYMBOL_GPL(hid_check_keys_pressed);
 
+static int __init hid_parse_device_id_list(struct hid_device_id *id_list,
+					   char **str_list,
+					   size_t max)
+{
+	static const char *usb_str = "usb";
+	static const char *bluetooth_str = "bluetooth";
+
+	size_t i;
+	const char *p;
+	const char *t;
+	int n;
+	u16 bus;
+	u32 vid, pid;
+
+	for (i = 0; i < max && str_list[i] != NULL; i++) {
+		p = str_list[i];
+
+		t = strchr(p, ':');
+		if (t == NULL)
+			goto err;
+
+		if ((t - p) == strlen(usb_str) &&
+		    memcmp(p, usb_str, t - p) == 0)
+			bus = BUS_USB;
+		else if ((t - p) == strlen(bluetooth_str) &&
+			 memcmp(p, bluetooth_str, t - p) == 0)
+			bus = BUS_BLUETOOTH;
+		else
+			goto err;
+
+		p = t + 1;
+
+		if (sscanf(p, "0x%x:0x%x%n", &vid, &pid, &n) != 2)
+			goto err;
+
+		p += n;
+		if (*p != '\0')
+			goto err;
+
+		id_list[i] = (struct hid_device_id){HID_DEVICE(bus, vid, pid)};
+	}
+
+	id_list[i].bus = 0;
+	return 0;
+err:
+	id_list[0].bus = 0;
+	return 1;
+}
+
 static int __init hid_init(void)
 {
 	int ret;
@@ -2175,6 +2247,12 @@ static int __init hid_init(void)
 		pr_warn("hid_debug is now used solely for parser and driver debugging.\n"
 			"debugfs is now used for inspecting the device (report descriptor, reports)\n");
 
+	ret = hid_parse_device_id_list(hid_have_special_driver_extra,
+				       hid_have_special_driver_param,
+				       MAX_HAVE_SPECIAL_DRIVER_EXTRA);
+	if (ret)
+		pr_warn("invalid have_special_driver module parameter\n");
+
 	ret = bus_register(&hid_bus_type);
 	if (ret) {
 		pr_err("can't register hid bus\n");
-- 
1.7.9

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux