cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hid-elecom.c (4406B)


      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 */
     16
     17/*
     18 */
     19
     20#include <linux/device.h>
     21#include <linux/hid.h>
     22#include <linux/module.h>
     23
     24#include "hid-ids.h"
     25
     26/*
     27 * Certain ELECOM mice misreport their button count meaning that they only work
     28 * correctly with the ELECOM mouse assistant software which is unavailable for
     29 * Linux. A four extra INPUT reports and a FEATURE report are described by the
     30 * report descriptor but it does not appear that these enable software to
     31 * control what the extra buttons map to. The only simple and straightforward
     32 * solution seems to involve fixing up the report descriptor.
     33 */
     34#define MOUSE_BUTTONS_MAX 8
     35static void mouse_button_fixup(struct hid_device *hdev,
     36			       __u8 *rdesc, unsigned int rsize,
     37			       unsigned int button_bit_count,
     38			       unsigned int padding_bit,
     39			       unsigned int button_report_size,
     40			       unsigned int button_usage_maximum,
     41			       int nbuttons)
     42{
     43	if (rsize < 32 || rdesc[button_bit_count] != 0x95 ||
     44	    rdesc[button_report_size] != 0x75 ||
     45	    rdesc[button_report_size + 1] != 0x01 ||
     46	    rdesc[button_usage_maximum] != 0x29 || rdesc[padding_bit] != 0x75)
     47		return;
     48	hid_info(hdev, "Fixing up Elecom mouse button count\n");
     49	nbuttons = clamp(nbuttons, 0, MOUSE_BUTTONS_MAX);
     50	rdesc[button_bit_count + 1] = nbuttons;
     51	rdesc[button_usage_maximum + 1] = nbuttons;
     52	rdesc[padding_bit + 1] = MOUSE_BUTTONS_MAX - nbuttons;
     53}
     54
     55static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
     56		unsigned int *rsize)
     57{
     58	switch (hdev->product) {
     59	case USB_DEVICE_ID_ELECOM_BM084:
     60		/* The BM084 Bluetooth mouse includes a non-existing horizontal
     61		 * wheel in the HID descriptor. */
     62		if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) {
     63			hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
     64			rdesc[47] = 0x00;
     65		}
     66		break;
     67	case USB_DEVICE_ID_ELECOM_M_XGL20DLBK:
     68		/*
     69		 * Report descriptor format:
     70		 * 20: button bit count
     71		 * 28: padding bit count
     72		 * 22: button report size
     73		 * 14: button usage maximum
     74		 */
     75		mouse_button_fixup(hdev, rdesc, *rsize, 20, 28, 22, 14, 8);
     76		break;
     77	case USB_DEVICE_ID_ELECOM_M_XT3URBK:
     78	case USB_DEVICE_ID_ELECOM_M_XT3DRBK:
     79	case USB_DEVICE_ID_ELECOM_M_XT4DRBK:
     80		/*
     81		 * Report descriptor format:
     82		 * 12: button bit count
     83		 * 30: padding bit count
     84		 * 14: button report size
     85		 * 20: button usage maximum
     86		 */
     87		mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 6);
     88		break;
     89	case USB_DEVICE_ID_ELECOM_M_DT1URBK:
     90	case USB_DEVICE_ID_ELECOM_M_DT1DRBK:
     91	case USB_DEVICE_ID_ELECOM_M_HT1URBK:
     92	case USB_DEVICE_ID_ELECOM_M_HT1DRBK:
     93		/*
     94		 * Report descriptor format:
     95		 * 12: button bit count
     96		 * 30: padding bit count
     97		 * 14: button report size
     98		 * 20: button usage maximum
     99		 */
    100		mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 8);
    101		break;
    102	}
    103	return rdesc;
    104}
    105
    106static const struct hid_device_id elecom_devices[] = {
    107	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
    108	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XGL20DLBK) },
    109	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) },
    110	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) },
    111	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },
    112	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) },
    113	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) },
    114	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) },
    115	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK) },
    116	{ }
    117};
    118MODULE_DEVICE_TABLE(hid, elecom_devices);
    119
    120static struct hid_driver elecom_driver = {
    121	.name = "elecom",
    122	.id_table = elecom_devices,
    123	.report_fixup = elecom_report_fixup
    124};
    125module_hid_driver(elecom_driver);
    126
    127MODULE_LICENSE("GPL");