diff options
| -rw-r--r-- | drivers/hid/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/hid/hid-elecom.c | 78 | ||||
| -rw-r--r-- | drivers/hid/hid-ids.h | 2 | ||||
| -rw-r--r-- | drivers/hid/hid-quirks.c | 2 |
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 | ||
| 41 | static 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 | |||
| 22 | static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 56 | static __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 | ||
| 78 | static const struct hid_device_id elecom_devices[] = { | 82 | static 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) }, |
