linux/drivers/hid/hid-elecom.c
<<
>>
Prefs
   1/*
   2 *  HID driver for ELECOM devices.
   3 *  Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com>
   4 *  Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com>
   5 *  Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu>
   6 */
   7
   8/*
   9 * This program is free software; you can redistribute it and/or modify it
  10 * under the terms of the GNU General Public License as published by the Free
  11 * Software Foundation; either version 2 of the License, or (at your option)
  12 * any later version.
  13 */
  14
  15#include <linux/device.h>
  16#include <linux/hid.h>
  17#include <linux/module.h>
  18
  19#include "hid-ids.h"
  20
  21static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
  22                unsigned int *rsize)
  23{
  24        switch (hdev->product) {
  25        case USB_DEVICE_ID_ELECOM_BM084:
  26                /* The BM084 Bluetooth mouse includes a non-existing horizontal
  27                 * wheel in the HID descriptor. */
  28                if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) {
  29                        hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
  30                        rdesc[47] = 0x00;
  31                }
  32                break;
  33        case USB_DEVICE_ID_ELECOM_DEFT_WIRED:
  34        case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS:
  35                /* The DEFT trackball has eight buttons, but its descriptor only
  36                 * reports five, disabling the three Fn buttons on the top of
  37                 * the mouse.
  38                 *
  39                 * Apply the following diff to the descriptor:
  40                 *
  41                 * Collection (Physical),              Collection (Physical),
  42                 *     Report ID (1),                      Report ID (1),
  43                 *     Report Count (5),           ->      Report Count (8),
  44                 *     Report Size (1),                    Report Size (1),
  45                 *     Usage Page (Button),                Usage Page (Button),
  46                 *     Usage Minimum (01h),                Usage Minimum (01h),
  47                 *     Usage Maximum (05h),        ->      Usage Maximum (08h),
  48                 *     Logical Minimum (0),                Logical Minimum (0),
  49                 *     Logical Maximum (1),                Logical Maximum (1),
  50                 *     Input (Variable),                   Input (Variable),
  51                 *     Report Count (1),           ->      Report Count (0),
  52                 *     Report Size (3),                    Report Size (3),
  53                 *     Input (Constant),                   Input (Constant),
  54                 *     Report Size (16),                   Report Size (16),
  55                 *     Report Count (2),                   Report Count (2),
  56                 *     Usage Page (Desktop),               Usage Page (Desktop),
  57                 *     Usage (X),                          Usage (X),
  58                 *     Usage (Y),                          Usage (Y),
  59                 *     Logical Minimum (-32768),           Logical Minimum (-32768),
  60                 *     Logical Maximum (32767),            Logical Maximum (32767),
  61                 *     Input (Variable, Relative),         Input (Variable, Relative),
  62                 * End Collection,                     End Collection,
  63                 */
  64                if (*rsize == 213 && rdesc[13] == 5 && rdesc[21] == 5) {
  65                        hid_info(hdev, "Fixing up Elecom DEFT Fn buttons\n");
  66                        rdesc[13] = 8; /* Button/Variable Report Count */
  67                        rdesc[21] = 8; /* Button/Variable Usage Maximum */
  68                        rdesc[29] = 0; /* Button/Constant Report Count */
  69                }
  70                break;
  71        }
  72        return rdesc;
  73}
  74
  75static const struct hid_device_id elecom_devices[] = {
  76        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
  77        { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
  78        { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
  79        { }
  80};
  81MODULE_DEVICE_TABLE(hid, elecom_devices);
  82
  83static struct hid_driver elecom_driver = {
  84        .name = "elecom",
  85        .id_table = elecom_devices,
  86        .report_fixup = elecom_report_fixup
  87};
  88module_hid_driver(elecom_driver);
  89
  90MODULE_LICENSE("GPL");
  91