HID: Add special driver for Jabra devices
authorNiels Skou Olsen <nolsen@jabra.com>
Wed, 4 Oct 2017 10:31:22 +0000 (12:31 +0200)
committerJiri Kosina <jkosina@suse.cz>
Tue, 21 Nov 2017 11:54:58 +0000 (12:54 +0100)
Add a hid-jabra driver to the list of special drivers in hid-core. The
driver prevents vendor defined HID usages (FF00-FFFF) in Jabra devices
from being mapped to input events, that become unintended mouse events
in the X11 server.

Signed-off-by: Niels Skou Olsen <nolsen@jabra.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-jabra.c [new file with mode: 0644]
drivers/hid/hid-quirks.c

index 779c5ae47f36b5857dfed6a67342472ce4ddc571..9058dbc4dd6ef131fb324ea1361d3ea3c494d926 100644 (file)
@@ -396,6 +396,17 @@ config HID_ITE
        ---help---
        Support for ITE devices not fully compliant with HID standard.
 
+config HID_JABRA
+       tristate "Jabra USB HID Driver"
+       depends on HID
+       ---help---
+       Support for Jabra USB HID devices.
+
+       Prevents mapping of vendor defined HID usages to input events. Without
+       this driver HID reports from Jabra devices may incorrectly be seen as
+       mouse button events.
+       Say M here if you may ever plug in a Jabra USB device.
+
 config HID_TWINHAN
        tristate "Twinhan IR remote control"
        depends on HID
index 2be460d44c69e4e179a731e40b19f095417a5702..eb13b9e92d8528d01f9e8581b6d92eaa76a5b5d5 100644 (file)
@@ -52,6 +52,7 @@ obj-$(CONFIG_HID_HOLTEK)      += hid-holtekff.o
 obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
 obj-$(CONFIG_HID_ICADE)                += hid-icade.o
 obj-$(CONFIG_HID_ITE)          += hid-ite.o
+obj-$(CONFIG_HID_JABRA)                += hid-jabra.o
 obj-$(CONFIG_HID_KENSINGTON)   += hid-kensington.o
 obj-$(CONFIG_HID_KEYTOUCH)     += hid-keytouch.o
 obj-$(CONFIG_HID_KYE)          += hid-kye.o
diff --git a/drivers/hid/hid-jabra.c b/drivers/hid/hid-jabra.c
new file mode 100644 (file)
index 0000000..1f52daf
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *  Jabra USB HID Driver
+ *
+ *  Copyright (c) 2017 Niels Skou Olsen <nolsen@jabra.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define HID_UP_VENDOR_DEFINED_MIN      0xff000000
+#define HID_UP_VENDOR_DEFINED_MAX      0xffff0000
+
+static int jabra_input_mapping(struct hid_device *hdev,
+                              struct hid_input *hi,
+                              struct hid_field *field,
+                              struct hid_usage *usage,
+                              unsigned long **bit, int *max)
+{
+       int is_vendor_defined =
+               ((usage->hid & HID_USAGE_PAGE) >= HID_UP_VENDOR_DEFINED_MIN &&
+                (usage->hid & HID_USAGE_PAGE) <= HID_UP_VENDOR_DEFINED_MAX);
+
+       dbg_hid("hid=0x%08x appl=0x%08x coll_idx=0x%02x usage_idx=0x%02x: %s\n",
+               usage->hid,
+               field->application,
+               usage->collection_index,
+               usage->usage_index,
+               is_vendor_defined ? "ignored" : "defaulted");
+
+       /* Ignore vendor defined usages, default map standard usages */
+       return is_vendor_defined ? -1 : 0;
+}
+
+static const struct hid_device_id jabra_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, HID_ANY_ID) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, jabra_devices);
+
+static struct hid_driver jabra_driver = {
+       .name = "jabra",
+       .id_table = jabra_devices,
+       .input_mapping = jabra_input_mapping,
+};
+module_hid_driver(jabra_driver);
+
+MODULE_AUTHOR("Niels Skou Olsen <nolsen@jabra.com>");
+MODULE_DESCRIPTION("Jabra USB HID Driver");
+MODULE_LICENSE("GPL");
index d57a22432957e2cb4762db412dd075715dec4fc5..015e0c10248b7ee3122b42ca085300fe0118943a 100644 (file)
@@ -384,6 +384,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
 #if IS_ENABLED(CONFIG_HID_ICADE)
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
 #endif
+#if IS_ENABLED(CONFIG_HID_JABRA)
+       { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, HID_ANY_ID) },
+#endif
 #if IS_ENABLED(CONFIG_HID_KENSINGTON)
        { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
 #endif