0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/device.h>
0017 #include <linux/input.h>
0018 #include <linux/hid.h>
0019 #include <linux/module.h>
0020 #include <linux/usb.h>
0021
0022 #include "hid-ids.h"
0023
0024 #define CH_WIRELESS_CTL_REPORT_ID 0x11
0025
0026 static int ch_report_wireless(struct hid_report *report, u8 *data, int size)
0027 {
0028 struct hid_device *hdev = report->device;
0029 struct input_dev *input;
0030
0031 if (report->id != CH_WIRELESS_CTL_REPORT_ID || report->maxfield != 1)
0032 return 0;
0033
0034 input = report->field[0]->hidinput->input;
0035 if (!input) {
0036 hid_warn(hdev, "can't find wireless radio control's input");
0037 return 0;
0038 }
0039
0040 input_report_key(input, KEY_RFKILL, 1);
0041 input_sync(input);
0042 input_report_key(input, KEY_RFKILL, 0);
0043 input_sync(input);
0044
0045 return 1;
0046 }
0047
0048 static int ch_raw_event(struct hid_device *hdev,
0049 struct hid_report *report, u8 *data, int size)
0050 {
0051 if (report->application == HID_GD_WIRELESS_RADIO_CTLS)
0052 return ch_report_wireless(report, data, size);
0053
0054 return 0;
0055 }
0056
0057 #define ch_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
0058 EV_KEY, (c))
0059 static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
0060 struct hid_field *field, struct hid_usage *usage,
0061 unsigned long **bit, int *max)
0062 {
0063 if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
0064 return 0;
0065
0066 set_bit(EV_REP, hi->input->evbit);
0067 switch (usage->hid & HID_USAGE) {
0068 case 0xff01: ch_map_key_clear(BTN_1); break;
0069 case 0xff02: ch_map_key_clear(BTN_2); break;
0070 case 0xff03: ch_map_key_clear(BTN_3); break;
0071 case 0xff04: ch_map_key_clear(BTN_4); break;
0072 case 0xff05: ch_map_key_clear(BTN_5); break;
0073 case 0xff06: ch_map_key_clear(BTN_6); break;
0074 case 0xff07: ch_map_key_clear(BTN_7); break;
0075 case 0xff08: ch_map_key_clear(BTN_8); break;
0076 case 0xff09: ch_map_key_clear(BTN_9); break;
0077 case 0xff0a: ch_map_key_clear(BTN_A); break;
0078 case 0xff0b: ch_map_key_clear(BTN_B); break;
0079 case 0x00f1: ch_map_key_clear(KEY_WLAN); break;
0080 case 0x00f2: ch_map_key_clear(KEY_BRIGHTNESSDOWN); break;
0081 case 0x00f3: ch_map_key_clear(KEY_BRIGHTNESSUP); break;
0082 case 0x00f4: ch_map_key_clear(KEY_DISPLAY_OFF); break;
0083 case 0x00f7: ch_map_key_clear(KEY_CAMERA); break;
0084 case 0x00f8: ch_map_key_clear(KEY_PROG1); break;
0085 default:
0086 return 0;
0087 }
0088 return 1;
0089 }
0090
0091 static __u8 *ch_switch12_report_fixup(struct hid_device *hdev, __u8 *rdesc,
0092 unsigned int *rsize)
0093 {
0094 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
0095
0096 if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
0097
0098
0099 switch (hdev->product) {
0100 case USB_DEVICE_ID_CHICONY_ACER_SWITCH12:
0101 if (*rsize >= 128 && rdesc[64] == 0xff && rdesc[65] == 0x7f
0102 && rdesc[69] == 0xff && rdesc[70] == 0x7f) {
0103 hid_info(hdev, "Fixing up report descriptor\n");
0104 rdesc[65] = rdesc[70] = 0x2f;
0105 }
0106 break;
0107 }
0108
0109 }
0110 return rdesc;
0111 }
0112
0113 static int ch_probe(struct hid_device *hdev, const struct hid_device_id *id)
0114 {
0115 int ret;
0116
0117 if (!hid_is_usb(hdev))
0118 return -EINVAL;
0119
0120 hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
0121 ret = hid_parse(hdev);
0122 if (ret) {
0123 hid_err(hdev, "Chicony hid parse failed: %d\n", ret);
0124 return ret;
0125 }
0126
0127 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
0128 if (ret) {
0129 hid_err(hdev, "Chicony hw start failed: %d\n", ret);
0130 return ret;
0131 }
0132
0133 return 0;
0134 }
0135
0136 static const struct hid_device_id ch_devices[] = {
0137 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
0138 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
0139 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS3) },
0140 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
0141 { }
0142 };
0143 MODULE_DEVICE_TABLE(hid, ch_devices);
0144
0145 static struct hid_driver ch_driver = {
0146 .name = "chicony",
0147 .id_table = ch_devices,
0148 .report_fixup = ch_switch12_report_fixup,
0149 .input_mapping = ch_input_mapping,
0150 .probe = ch_probe,
0151 .raw_event = ch_raw_event,
0152 };
0153 module_hid_driver(ch_driver);
0154
0155 MODULE_LICENSE("GPL");