linux/drivers/hid/hid-ite.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * HID driver for some ITE "special" devices
   4 * Copyright (c) 2017 Hans de Goede <hdegoede@redhat.com>
   5 */
   6
   7#include <linux/device.h>
   8#include <linux/input.h>
   9#include <linux/hid.h>
  10#include <linux/module.h>
  11
  12#include "hid-ids.h"
  13
  14#define QUIRK_TOUCHPAD_ON_OFF_REPORT            BIT(0)
  15
  16static __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize)
  17{
  18        unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
  19
  20        if (quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) {
  21                /* For Acer Aspire Switch 10 SW5-012 keyboard-dock */
  22                if (*rsize == 188 && rdesc[162] == 0x81 && rdesc[163] == 0x02) {
  23                        hid_info(hdev, "Fixing up Acer Sw5-012 ITE keyboard report descriptor\n");
  24                        rdesc[163] = HID_MAIN_ITEM_RELATIVE;
  25                }
  26                /* For Acer One S1002/S1003 keyboard-dock */
  27                if (*rsize == 188 && rdesc[185] == 0x81 && rdesc[186] == 0x02) {
  28                        hid_info(hdev, "Fixing up Acer S1002/S1003 ITE keyboard report descriptor\n");
  29                        rdesc[186] = HID_MAIN_ITEM_RELATIVE;
  30                }
  31                /* For Acer Aspire Switch 10E (SW3-016) keyboard-dock */
  32                if (*rsize == 210 && rdesc[184] == 0x81 && rdesc[185] == 0x02) {
  33                        hid_info(hdev, "Fixing up Acer Aspire Switch 10E (SW3-016) ITE keyboard report descriptor\n");
  34                        rdesc[185] = HID_MAIN_ITEM_RELATIVE;
  35                }
  36        }
  37
  38        return rdesc;
  39}
  40
  41static int ite_input_mapping(struct hid_device *hdev,
  42                struct hid_input *hi, struct hid_field *field,
  43                struct hid_usage *usage, unsigned long **bit,
  44                int *max)
  45{
  46
  47        unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
  48
  49        if ((quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) &&
  50            (usage->hid & HID_USAGE_PAGE) == 0x00880000) {
  51                if (usage->hid == 0x00880078) {
  52                        /* Touchpad on, userspace expects F22 for this */
  53                        hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F22);
  54                        return 1;
  55                }
  56                if (usage->hid == 0x00880079) {
  57                        /* Touchpad off, userspace expects F23 for this */
  58                        hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F23);
  59                        return 1;
  60                }
  61                return -1;
  62        }
  63
  64        return 0;
  65}
  66
  67static int ite_event(struct hid_device *hdev, struct hid_field *field,
  68                     struct hid_usage *usage, __s32 value)
  69{
  70        struct input_dev *input;
  71
  72        if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput)
  73                return 0;
  74
  75        input = field->hidinput->input;
  76
  77        /*
  78         * The ITE8595 always reports 0 as value for the rfkill button. Luckily
  79         * it is the only button in its report, and it sends a report on
  80         * release only, so receiving a report means the button was pressed.
  81         */
  82        if (usage->hid == HID_GD_RFKILL_BTN) {
  83                input_event(input, EV_KEY, KEY_RFKILL, 1);
  84                input_sync(input);
  85                input_event(input, EV_KEY, KEY_RFKILL, 0);
  86                input_sync(input);
  87                return 1;
  88        }
  89
  90        return 0;
  91}
  92
  93static int ite_probe(struct hid_device *hdev, const struct hid_device_id *id)
  94{
  95        int ret;
  96
  97        hid_set_drvdata(hdev, (void *)id->driver_data);
  98
  99        ret = hid_open_report(hdev);
 100        if (ret)
 101                return ret;
 102
 103        return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 104}
 105
 106static const struct hid_device_id ite_devices[] = {
 107        { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
 108        { HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
 109        /* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
 110        { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
 111                     USB_VENDOR_ID_SYNAPTICS,
 112                     USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012),
 113          .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
 114        /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
 115        { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
 116                     USB_VENDOR_ID_SYNAPTICS,
 117                     USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1002),
 118          .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
 119        /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
 120        { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
 121                     USB_VENDOR_ID_SYNAPTICS,
 122                     USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003),
 123          .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
 124        { }
 125};
 126MODULE_DEVICE_TABLE(hid, ite_devices);
 127
 128static struct hid_driver ite_driver = {
 129        .name = "itetech",
 130        .id_table = ite_devices,
 131        .probe = ite_probe,
 132        .report_fixup = ite_report_fixup,
 133        .input_mapping = ite_input_mapping,
 134        .event = ite_event,
 135};
 136module_hid_driver(ite_driver);
 137
 138MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 139MODULE_LICENSE("GPL");
 140