Linux Audio

Check our new training course

Yocto / OpenEmbedded training

Feb 10-13, 2025
Register
Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 *  HID driver for ELECOM devices:
  4 *  - BM084 Bluetooth Mouse
  5 *  - EX-G Trackballs (M-XT3DRBK, M-XT3URBK, M-XT4DRBK)
  6 *  - DEFT Trackballs (M-DT1DRBK, M-DT1URBK, M-DT2DRBK, M-DT2URBK)
  7 *  - HUGE Trackballs (M-HT1DRBK, M-HT1URBK)
  8 *
  9 *  Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com>
 10 *  Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com>
 11 *  Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu>
 12 *  Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org>
 13 *  Copyright (c) 2017 Tomasz Kramkowski <tk@the-tk.com>
 14 *  Copyright (c) 2020 YOSHIOKA Takuma <lo48576@hard-wi.red>
 15 *  Copyright (c) 2022 Takahiro Fujii <fujii@xaxxi.net>
 16 */
 17
 18/*
 19 */
 20
 21#include <linux/device.h>
 22#include <linux/hid.h>
 23#include <linux/module.h>
 24
 25#include "hid-ids.h"
 26
 27/*
 28 * Certain ELECOM mice misreport their button count meaning that they only work
 29 * correctly with the ELECOM mouse assistant software which is unavailable for
 30 * Linux. A four extra INPUT reports and a FEATURE report are described by the
 31 * report descriptor but it does not appear that these enable software to
 32 * control what the extra buttons map to. The only simple and straightforward
 33 * solution seems to involve fixing up the report descriptor.
 
 
 
 
 34 */
 35#define MOUSE_BUTTONS_MAX 8
 36static void mouse_button_fixup(struct hid_device *hdev,
 37			       __u8 *rdesc, unsigned int rsize,
 38			       unsigned int button_bit_count,
 39			       unsigned int padding_bit,
 40			       unsigned int button_report_size,
 41			       unsigned int button_usage_maximum,
 42			       int nbuttons)
 43{
 44	if (rsize < 32 || rdesc[button_bit_count] != 0x95 ||
 45	    rdesc[button_report_size] != 0x75 ||
 46	    rdesc[button_report_size + 1] != 0x01 ||
 47	    rdesc[button_usage_maximum] != 0x29 || rdesc[padding_bit] != 0x75)
 48		return;
 49	hid_info(hdev, "Fixing up Elecom mouse button count\n");
 50	nbuttons = clamp(nbuttons, 0, MOUSE_BUTTONS_MAX);
 51	rdesc[button_bit_count + 1] = nbuttons;
 52	rdesc[button_usage_maximum + 1] = nbuttons;
 53	rdesc[padding_bit + 1] = MOUSE_BUTTONS_MAX - nbuttons;
 54}
 55
 56static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 57		unsigned int *rsize)
 58{
 59	switch (hdev->product) {
 60	case USB_DEVICE_ID_ELECOM_BM084:
 61		/* The BM084 Bluetooth mouse includes a non-existing horizontal
 62		 * wheel in the HID descriptor. */
 63		if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) {
 64			hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
 65			rdesc[47] = 0x00;
 66		}
 67		break;
 68	case USB_DEVICE_ID_ELECOM_M_XGL20DLBK:
 69		/*
 70		 * Report descriptor format:
 71		 * 20: button bit count
 72		 * 28: padding bit count
 73		 * 22: button report size
 74		 * 14: button usage maximum
 75		 */
 76		mouse_button_fixup(hdev, rdesc, *rsize, 20, 28, 22, 14, 8);
 77		break;
 78	case USB_DEVICE_ID_ELECOM_M_XT3URBK:
 79	case USB_DEVICE_ID_ELECOM_M_XT3DRBK:
 80	case USB_DEVICE_ID_ELECOM_M_XT4DRBK:
 81		/*
 82		 * Report descriptor format:
 83		 * 12: button bit count
 84		 * 30: padding bit count
 85		 * 14: button report size
 86		 * 20: button usage maximum
 87		 */
 88		mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 6);
 89		break;
 90	case USB_DEVICE_ID_ELECOM_M_DT1URBK:
 91	case USB_DEVICE_ID_ELECOM_M_DT1DRBK:
 92	case USB_DEVICE_ID_ELECOM_M_HT1URBK:
 93	case USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D:
 94		/*
 95		 * Report descriptor format:
 96		 * 12: button bit count
 97		 * 30: padding bit count
 98		 * 14: button report size
 99		 * 20: button usage maximum
100		 */
101		mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 8);
102		break;
103	case USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C:
104		/*
105		 * Report descriptor format:
106		 * 22: button bit count
107		 * 30: padding bit count
108		 * 24: button report size
109		 * 16: button usage maximum
110		 */
111		mouse_button_fixup(hdev, rdesc, *rsize, 22, 30, 24, 16, 8);
112		break;
113	}
114	return rdesc;
115}
116
117static const struct hid_device_id elecom_devices[] = {
118	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
119	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XGL20DLBK) },
120	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) },
121	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) },
122	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },
123	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) },
124	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) },
125	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) },
126	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D) },
127	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C) },
128	{ }
129};
130MODULE_DEVICE_TABLE(hid, elecom_devices);
131
132static struct hid_driver elecom_driver = {
133	.name = "elecom",
134	.id_table = elecom_devices,
135	.report_fixup = elecom_report_fixup
136};
137module_hid_driver(elecom_driver);
138
139MODULE_LICENSE("GPL");
v5.4
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 *  HID driver for ELECOM devices:
  4 *  - BM084 Bluetooth Mouse
  5 *  - EX-G Trackballs (M-XT3DRBK, M-XT3URBK, M-XT4DRBK)
  6 *  - DEFT Trackballs (M-DT1DRBK, M-DT1URBK, M-DT2DRBK, M-DT2URBK)
  7 *  - HUGE Trackballs (M-HT1DRBK, M-HT1URBK)
  8 *
  9 *  Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com>
 10 *  Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com>
 11 *  Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu>
 12 *  Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org>
 13 *  Copyright (c) 2017 Tomasz Kramkowski <tk@the-tk.com>
 
 
 14 */
 15
 16/*
 17 */
 18
 19#include <linux/device.h>
 20#include <linux/hid.h>
 21#include <linux/module.h>
 22
 23#include "hid-ids.h"
 24
 25/*
 26 * Certain ELECOM mice misreport their button count meaning that they only work
 27 * correctly with the ELECOM mouse assistant software which is unavailable for
 28 * Linux. A four extra INPUT reports and a FEATURE report are described by the
 29 * report descriptor but it does not appear that these enable software to
 30 * control what the extra buttons map to. The only simple and straightforward
 31 * solution seems to involve fixing up the report descriptor.
 32 *
 33 * Report descriptor format:
 34 * Positions 13, 15, 21 and 31 store the button bit count, button usage minimum,
 35 * button usage maximum and padding bit count respectively.
 36 */
 37#define MOUSE_BUTTONS_MAX 8
 38static void mouse_button_fixup(struct hid_device *hdev,
 39			       __u8 *rdesc, unsigned int rsize,
 
 
 
 
 40			       int nbuttons)
 41{
 42	if (rsize < 32 || rdesc[12] != 0x95 ||
 43	    rdesc[14] != 0x75 || rdesc[15] != 0x01 ||
 44	    rdesc[20] != 0x29 || rdesc[30] != 0x75)
 
 45		return;
 46	hid_info(hdev, "Fixing up Elecom mouse button count\n");
 47	nbuttons = clamp(nbuttons, 0, MOUSE_BUTTONS_MAX);
 48	rdesc[13] = nbuttons;
 49	rdesc[21] = nbuttons;
 50	rdesc[31] = MOUSE_BUTTONS_MAX - nbuttons;
 51}
 52
 53static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 54		unsigned int *rsize)
 55{
 56	switch (hdev->product) {
 57	case USB_DEVICE_ID_ELECOM_BM084:
 58		/* The BM084 Bluetooth mouse includes a non-existing horizontal
 59		 * wheel in the HID descriptor. */
 60		if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) {
 61			hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
 62			rdesc[47] = 0x00;
 63		}
 64		break;
 
 
 
 
 
 
 
 
 
 
 65	case USB_DEVICE_ID_ELECOM_M_XT3URBK:
 66	case USB_DEVICE_ID_ELECOM_M_XT3DRBK:
 67	case USB_DEVICE_ID_ELECOM_M_XT4DRBK:
 68		mouse_button_fixup(hdev, rdesc, *rsize, 6);
 
 
 
 
 
 
 
 69		break;
 70	case USB_DEVICE_ID_ELECOM_M_DT1URBK:
 71	case USB_DEVICE_ID_ELECOM_M_DT1DRBK:
 72	case USB_DEVICE_ID_ELECOM_M_HT1URBK:
 73	case USB_DEVICE_ID_ELECOM_M_HT1DRBK:
 74		mouse_button_fixup(hdev, rdesc, *rsize, 8);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 75		break;
 76	}
 77	return rdesc;
 78}
 79
 80static const struct hid_device_id elecom_devices[] = {
 81	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
 
 82	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) },
 83	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) },
 84	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },
 85	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) },
 86	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) },
 87	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) },
 88	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK) },
 
 89	{ }
 90};
 91MODULE_DEVICE_TABLE(hid, elecom_devices);
 92
 93static struct hid_driver elecom_driver = {
 94	.name = "elecom",
 95	.id_table = elecom_devices,
 96	.report_fixup = elecom_report_fixup
 97};
 98module_hid_driver(elecom_driver);
 99
100MODULE_LICENSE("GPL");