0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <linux/device.h>
0021 #include <linux/hid.h>
0022 #include <linux/module.h>
0023
0024 #include "hid-ids.h"
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #define MOUSE_BUTTONS_MAX 8
0035 static void mouse_button_fixup(struct hid_device *hdev,
0036 __u8 *rdesc, unsigned int rsize,
0037 unsigned int button_bit_count,
0038 unsigned int padding_bit,
0039 unsigned int button_report_size,
0040 unsigned int button_usage_maximum,
0041 int nbuttons)
0042 {
0043 if (rsize < 32 || rdesc[button_bit_count] != 0x95 ||
0044 rdesc[button_report_size] != 0x75 ||
0045 rdesc[button_report_size + 1] != 0x01 ||
0046 rdesc[button_usage_maximum] != 0x29 || rdesc[padding_bit] != 0x75)
0047 return;
0048 hid_info(hdev, "Fixing up Elecom mouse button count\n");
0049 nbuttons = clamp(nbuttons, 0, MOUSE_BUTTONS_MAX);
0050 rdesc[button_bit_count + 1] = nbuttons;
0051 rdesc[button_usage_maximum + 1] = nbuttons;
0052 rdesc[padding_bit + 1] = MOUSE_BUTTONS_MAX - nbuttons;
0053 }
0054
0055 static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
0056 unsigned int *rsize)
0057 {
0058 switch (hdev->product) {
0059 case USB_DEVICE_ID_ELECOM_BM084:
0060
0061
0062 if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) {
0063 hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
0064 rdesc[47] = 0x00;
0065 }
0066 break;
0067 case USB_DEVICE_ID_ELECOM_M_XGL20DLBK:
0068
0069
0070
0071
0072
0073
0074
0075 mouse_button_fixup(hdev, rdesc, *rsize, 20, 28, 22, 14, 8);
0076 break;
0077 case USB_DEVICE_ID_ELECOM_M_XT3URBK:
0078 case USB_DEVICE_ID_ELECOM_M_XT3DRBK:
0079 case USB_DEVICE_ID_ELECOM_M_XT4DRBK:
0080
0081
0082
0083
0084
0085
0086
0087 mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 6);
0088 break;
0089 case USB_DEVICE_ID_ELECOM_M_DT1URBK:
0090 case USB_DEVICE_ID_ELECOM_M_DT1DRBK:
0091 case USB_DEVICE_ID_ELECOM_M_HT1URBK:
0092 case USB_DEVICE_ID_ELECOM_M_HT1DRBK:
0093
0094
0095
0096
0097
0098
0099
0100 mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 8);
0101 break;
0102 }
0103 return rdesc;
0104 }
0105
0106 static const struct hid_device_id elecom_devices[] = {
0107 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
0108 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XGL20DLBK) },
0109 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) },
0110 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) },
0111 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },
0112 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) },
0113 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) },
0114 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) },
0115 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK) },
0116 { }
0117 };
0118 MODULE_DEVICE_TABLE(hid, elecom_devices);
0119
0120 static struct hid_driver elecom_driver = {
0121 .name = "elecom",
0122 .id_table = elecom_devices,
0123 .report_fixup = elecom_report_fixup
0124 };
0125 module_hid_driver(elecom_driver);
0126
0127 MODULE_LICENSE("GPL");