1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/device.h>
14#include <linux/hid.h>
15#include <linux/module.h>
16#include <linux/usb.h>
17
18#include "hid-ids.h"
19#include "usbhid/usbhid.h"
20
21
22
23
24
25
26
27
28
29
30
31
32
33static __u8 holtek_kbd_rdesc_fixed[] = {
34
35 0x05, 0x01,
36 0x09, 0x80,
37 0xA1, 0x01,
38 0x85, 0x01,
39 0x19, 0x81,
40 0x29, 0x83,
41 0x15, 0x00,
42 0x25, 0x01,
43 0x95, 0x03,
44 0x75, 0x01,
45 0x81, 0x02,
46 0x95, 0x01,
47 0x75, 0x05,
48 0x81, 0x01,
49 0xC0,
50 0x05, 0x0C,
51 0x09, 0x01,
52 0xA1, 0x01,
53 0x85, 0x02,
54 0x19, 0x00,
55 0x2A, 0xFF, 0x2F,
56 0x15, 0x00,
57 0x26, 0xFF, 0x2F,
58 0x95, 0x01,
59 0x75, 0x10,
60 0x81, 0x00,
61 0xC0,
62 0x05, 0x01,
63 0x09, 0x06,
64 0xA1, 0x01,
65 0x85, 0x03,
66 0x95, 0x38,
67 0x75, 0x01,
68 0x15, 0x00,
69 0x25, 0x01,
70 0x05, 0x07,
71 0x19, 0xE0,
72 0x29, 0xE7,
73 0x19, 0x00,
74 0x29, 0x2F,
75 0x81, 0x02,
76 0xC0,
77 0x05, 0x01,
78 0x09, 0x06,
79 0xA1, 0x01,
80 0x85, 0x04,
81 0x95, 0x38,
82 0x75, 0x01,
83 0x15, 0x00,
84 0x25, 0x01,
85 0x05, 0x07,
86 0x19, 0x30,
87 0x29, 0x67,
88 0x81, 0x02,
89 0xC0,
90
91
92 0x05, 0x01,
93 0x09, 0x06,
94 0xA1, 0x01,
95 0x05, 0x08,
96 0x19, 0x01,
97 0x29, 0x03,
98 0x15, 0x00,
99 0x25, 0x01,
100 0x75, 0x01,
101 0x95, 0x03,
102 0x91, 0x02,
103 0x95, 0x05,
104 0x91, 0x01,
105 0xC0,
106};
107
108static __u8 *holtek_kbd_report_fixup(struct hid_device *hdev, __u8 *rdesc,
109 unsigned int *rsize)
110{
111 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
112
113 if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
114 rdesc = holtek_kbd_rdesc_fixed;
115 *rsize = sizeof(holtek_kbd_rdesc_fixed);
116 }
117 return rdesc;
118}
119
120static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type,
121 unsigned int code,
122 int value)
123{
124 struct hid_device *hid = input_get_drvdata(dev);
125 struct usb_device *usb_dev = hid_to_usb_dev(hid);
126
127
128 struct usb_interface *boot_interface = usb_ifnum_to_if(usb_dev, 0);
129
130 struct hid_device *boot_hid = usb_get_intfdata(boot_interface);
131 struct hid_input *boot_hid_input = list_first_entry(&boot_hid->inputs,
132 struct hid_input, list);
133
134 return boot_hid_input->input->event(boot_hid_input->input, type, code,
135 value);
136}
137
138static int holtek_kbd_probe(struct hid_device *hdev,
139 const struct hid_device_id *id)
140{
141 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
142 int ret = hid_parse(hdev);
143
144 if (!ret)
145 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
146
147 if (!ret && intf->cur_altsetting->desc.bInterfaceNumber == 1) {
148 struct hid_input *hidinput;
149 list_for_each_entry(hidinput, &hdev->inputs, list) {
150 hidinput->input->event = holtek_kbd_input_event;
151 }
152 }
153
154 return ret;
155}
156
157static const struct hid_device_id holtek_kbd_devices[] = {
158 { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
159 USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
160 { }
161};
162MODULE_DEVICE_TABLE(hid, holtek_kbd_devices);
163
164static struct hid_driver holtek_kbd_driver = {
165 .name = "holtek_kbd",
166 .id_table = holtek_kbd_devices,
167 .report_fixup = holtek_kbd_report_fixup,
168 .probe = holtek_kbd_probe
169};
170
171static int __init holtek_kbd_init(void)
172{
173 return hid_register_driver(&holtek_kbd_driver);
174}
175
176static void __exit holtek_kbd_exit(void)
177{
178 hid_unregister_driver(&holtek_kbd_driver);
179}
180
181module_exit(holtek_kbd_exit);
182module_init(holtek_kbd_init);
183MODULE_LICENSE("GPL");
184