Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * HID driver for some ITE "special" devices
0004  * Copyright (c) 2017 Hans de Goede <hdegoede@redhat.com>
0005  */
0006 
0007 #include <linux/device.h>
0008 #include <linux/input.h>
0009 #include <linux/hid.h>
0010 #include <linux/module.h>
0011 
0012 #include "hid-ids.h"
0013 
0014 #define QUIRK_TOUCHPAD_ON_OFF_REPORT        BIT(0)
0015 
0016 static __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize)
0017 {
0018     unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
0019 
0020     if (quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) {
0021         /* For Acer Aspire Switch 10 SW5-012 keyboard-dock */
0022         if (*rsize == 188 && rdesc[162] == 0x81 && rdesc[163] == 0x02) {
0023             hid_info(hdev, "Fixing up Acer Sw5-012 ITE keyboard report descriptor\n");
0024             rdesc[163] = HID_MAIN_ITEM_RELATIVE;
0025         }
0026         /* For Acer One S1002/S1003 keyboard-dock */
0027         if (*rsize == 188 && rdesc[185] == 0x81 && rdesc[186] == 0x02) {
0028             hid_info(hdev, "Fixing up Acer S1002/S1003 ITE keyboard report descriptor\n");
0029             rdesc[186] = HID_MAIN_ITEM_RELATIVE;
0030         }
0031         /* For Acer Aspire Switch 10E (SW3-016) keyboard-dock */
0032         if (*rsize == 210 && rdesc[184] == 0x81 && rdesc[185] == 0x02) {
0033             hid_info(hdev, "Fixing up Acer Aspire Switch 10E (SW3-016) ITE keyboard report descriptor\n");
0034             rdesc[185] = HID_MAIN_ITEM_RELATIVE;
0035         }
0036     }
0037 
0038     return rdesc;
0039 }
0040 
0041 static int ite_input_mapping(struct hid_device *hdev,
0042         struct hid_input *hi, struct hid_field *field,
0043         struct hid_usage *usage, unsigned long **bit,
0044         int *max)
0045 {
0046 
0047     unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
0048 
0049     if ((quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) &&
0050         (usage->hid & HID_USAGE_PAGE) == 0x00880000) {
0051         if (usage->hid == 0x00880078) {
0052             /* Touchpad on, userspace expects F22 for this */
0053             hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F22);
0054             return 1;
0055         }
0056         if (usage->hid == 0x00880079) {
0057             /* Touchpad off, userspace expects F23 for this */
0058             hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F23);
0059             return 1;
0060         }
0061         return -1;
0062     }
0063 
0064     return 0;
0065 }
0066 
0067 static int ite_event(struct hid_device *hdev, struct hid_field *field,
0068              struct hid_usage *usage, __s32 value)
0069 {
0070     struct input_dev *input;
0071 
0072     if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput)
0073         return 0;
0074 
0075     input = field->hidinput->input;
0076 
0077     /*
0078      * The ITE8595 always reports 0 as value for the rfkill button. Luckily
0079      * it is the only button in its report, and it sends a report on
0080      * release only, so receiving a report means the button was pressed.
0081      */
0082     if (usage->hid == HID_GD_RFKILL_BTN) {
0083         input_event(input, EV_KEY, KEY_RFKILL, 1);
0084         input_sync(input);
0085         input_event(input, EV_KEY, KEY_RFKILL, 0);
0086         input_sync(input);
0087         return 1;
0088     }
0089 
0090     return 0;
0091 }
0092 
0093 static int ite_probe(struct hid_device *hdev, const struct hid_device_id *id)
0094 {
0095     int ret;
0096 
0097     hid_set_drvdata(hdev, (void *)id->driver_data);
0098 
0099     ret = hid_open_report(hdev);
0100     if (ret)
0101         return ret;
0102 
0103     return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
0104 }
0105 
0106 static const struct hid_device_id ite_devices[] = {
0107     { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
0108     { HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
0109     /* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
0110     { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
0111              USB_VENDOR_ID_SYNAPTICS,
0112              USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012),
0113       .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
0114     /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
0115     { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
0116              USB_VENDOR_ID_SYNAPTICS,
0117              USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1002),
0118       .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
0119     /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
0120     { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
0121              USB_VENDOR_ID_SYNAPTICS,
0122              USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003),
0123       .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
0124     { }
0125 };
0126 MODULE_DEVICE_TABLE(hid, ite_devices);
0127 
0128 static struct hid_driver ite_driver = {
0129     .name = "itetech",
0130     .id_table = ite_devices,
0131     .probe = ite_probe,
0132     .report_fixup = ite_report_fixup,
0133     .input_mapping = ite_input_mapping,
0134     .event = ite_event,
0135 };
0136 module_hid_driver(ite_driver);
0137 
0138 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
0139 MODULE_LICENSE("GPL");