aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/Kconfig1
-rw-r--r--drivers/hid/hid-elecom.c78
-rw-r--r--drivers/hid/hid-ids.h2
-rw-r--r--drivers/hid/hid-quirks.c2
4 files changed, 47 insertions, 36 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 9058dbc4dd6e..19c499f5623d 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -280,6 +280,7 @@ config HID_ELECOM
280 ---help--- 280 ---help---
281 Support for ELECOM devices: 281 Support for ELECOM devices:
282 - BM084 Bluetooth Mouse 282 - BM084 Bluetooth Mouse
283 - EX-G Trackball (Wired and wireless)
283 - DEFT Trackball (Wired and wireless) 284 - DEFT Trackball (Wired and wireless)
284 - HUGE Trackball (Wired and wireless) 285 - HUGE Trackball (Wired and wireless)
285 286
diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c
index 54aeea57d209..1a1ecc491c02 100644
--- a/drivers/hid/hid-elecom.c
+++ b/drivers/hid/hid-elecom.c
@@ -1,9 +1,15 @@
1/* 1/*
2 * HID driver for ELECOM devices. 2 * HID driver for ELECOM devices:
3 * - BM084 Bluetooth Mouse
4 * - EX-G Trackball (Wired and wireless)
5 * - DEFT Trackball (Wired and wireless)
6 * - HUGE Trackball (Wired and wireless)
7 *
3 * Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com> 8 * Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com>
4 * Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com> 9 * Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com>
5 * Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu> 10 * Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu>
6 * Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org> 11 * Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org>
12 * Copyright (c) 2017 Tomasz Kramkowski <tk@the-tk.com>
7 */ 13 */
8 14
9/* 15/*
@@ -19,6 +25,34 @@
19 25
20#include "hid-ids.h" 26#include "hid-ids.h"
21 27
28/*
29 * Certain ELECOM mice misreport their button count meaning that they only work
30 * correctly with the ELECOM mouse assistant software which is unavailable for
31 * Linux. A four extra INPUT reports and a FEATURE report are described by the
32 * report descriptor but it does not appear that these enable software to
33 * control what the extra buttons map to. The only simple and straightforward
34 * solution seems to involve fixing up the report descriptor.
35 *
36 * Report descriptor format:
37 * Positions 13, 15, 21 and 31 store the button bit count, button usage minimum,
38 * button usage maximum and padding bit count respectively.
39 */
40#define MOUSE_BUTTONS_MAX 8
41static void mouse_button_fixup(struct hid_device *hdev,
42 __u8 *rdesc, unsigned int rsize,
43 int nbuttons)
44{
45 if (rsize < 32 || rdesc[12] != 0x95 ||
46 rdesc[14] != 0x75 || rdesc[15] != 0x01 ||
47 rdesc[20] != 0x29 || rdesc[30] != 0x75)
48 return;
49 hid_info(hdev, "Fixing up Elecom mouse button count\n");
50 nbuttons = clamp(nbuttons, 0, MOUSE_BUTTONS_MAX);
51 rdesc[13] = nbuttons;
52 rdesc[21] = nbuttons;
53 rdesc[31] = MOUSE_BUTTONS_MAX - nbuttons;
54}
55
22static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, 56static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
23 unsigned int *rsize) 57 unsigned int *rsize)
24{ 58{
@@ -31,45 +65,15 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
31 rdesc[47] = 0x00; 65 rdesc[47] = 0x00;
32 } 66 }
33 break; 67 break;
68 case USB_DEVICE_ID_ELECOM_EX_G_WIRED:
69 case USB_DEVICE_ID_ELECOM_EX_G_WIRELESS:
70 mouse_button_fixup(hdev, rdesc, *rsize, 6);
71 break;
34 case USB_DEVICE_ID_ELECOM_DEFT_WIRED: 72 case USB_DEVICE_ID_ELECOM_DEFT_WIRED:
35 case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS: 73 case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS:
36 case USB_DEVICE_ID_ELECOM_HUGE_WIRED: 74 case USB_DEVICE_ID_ELECOM_HUGE_WIRED:
37 case USB_DEVICE_ID_ELECOM_HUGE_WIRELESS: 75 case USB_DEVICE_ID_ELECOM_HUGE_WIRELESS:
38 /* The DEFT/HUGE trackball has eight buttons, but its descriptor 76 mouse_button_fixup(hdev, rdesc, *rsize, 8);
39 * only reports five, disabling the three Fn buttons on the top
40 * of the mouse.
41 *
42 * Apply the following diff to the descriptor:
43 *
44 * Collection (Physical), Collection (Physical),
45 * Report ID (1), Report ID (1),
46 * Report Count (5), -> Report Count (8),
47 * Report Size (1), Report Size (1),
48 * Usage Page (Button), Usage Page (Button),
49 * Usage Minimum (01h), Usage Minimum (01h),
50 * Usage Maximum (05h), -> Usage Maximum (08h),
51 * Logical Minimum (0), Logical Minimum (0),
52 * Logical Maximum (1), Logical Maximum (1),
53 * Input (Variable), Input (Variable),
54 * Report Count (1), -> Report Count (0),
55 * Report Size (3), Report Size (3),
56 * Input (Constant), Input (Constant),
57 * Report Size (16), Report Size (16),
58 * Report Count (2), Report Count (2),
59 * Usage Page (Desktop), Usage Page (Desktop),
60 * Usage (X), Usage (X),
61 * Usage (Y), Usage (Y),
62 * Logical Minimum (-32768), Logical Minimum (-32768),
63 * Logical Maximum (32767), Logical Maximum (32767),
64 * Input (Variable, Relative), Input (Variable, Relative),
65 * End Collection, End Collection,
66 */
67 if (*rsize == 213 && rdesc[13] == 5 && rdesc[21] == 5) {
68 hid_info(hdev, "Fixing up Elecom DEFT/HUGE Fn buttons\n");
69 rdesc[13] = 8; /* Button/Variable Report Count */
70 rdesc[21] = 8; /* Button/Variable Usage Maximum */
71 rdesc[29] = 0; /* Button/Constant Report Count */
72 }
73 break; 77 break;
74 } 78 }
75 return rdesc; 79 return rdesc;
@@ -77,6 +81,8 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
77 81
78static const struct hid_device_id elecom_devices[] = { 82static const struct hid_device_id elecom_devices[] = {
79 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, 83 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
84 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRED) },
85 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRELESS) },
80 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) }, 86 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
81 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) }, 87 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
82 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) }, 88 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 5da3d6256d25..d5daf2e638f7 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -370,6 +370,8 @@
370 370
371#define USB_VENDOR_ID_ELECOM 0x056e 371#define USB_VENDOR_ID_ELECOM 0x056e
372#define USB_DEVICE_ID_ELECOM_BM084 0x0061 372#define USB_DEVICE_ID_ELECOM_BM084 0x0061
373#define USB_DEVICE_ID_ELECOM_EX_G_WIRED 0x00fb
374#define USB_DEVICE_ID_ELECOM_EX_G_WIRELESS 0x00fc
373#define USB_DEVICE_ID_ELECOM_DEFT_WIRED 0x00fe 375#define USB_DEVICE_ID_ELECOM_DEFT_WIRED 0x00fe
374#define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS 0x00ff 376#define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS 0x00ff
375#define USB_DEVICE_ID_ELECOM_HUGE_WIRED 0x010c 377#define USB_DEVICE_ID_ELECOM_HUGE_WIRED 0x010c
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 20e68a7ac79f..2b43437401e6 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -335,6 +335,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
335#endif 335#endif
336#if IS_ENABLED(CONFIG_HID_ELECOM) 336#if IS_ENABLED(CONFIG_HID_ELECOM)
337 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, 337 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
338 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRED) },
339 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRELESS) },
338 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) }, 340 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
339 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) }, 341 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
340 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) }, 342 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) },