1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <linux/device.h>
17#include <linux/hid.h>
18#include <linux/module.h>
19#include <linux/usb.h>
20#include "usbhid/usbhid.h"
21
22#include "hid-ids.h"
23
24
25
26
27
28
29
30#define EASYPEN_I405X_RDESC_ORIG_SIZE 476
31
32
33static __u8 easypen_i405x_rdesc_fixed[] = {
34 0x06, 0x00, 0xFF,
35 0x09, 0x01,
36 0xA1, 0x01,
37 0x85, 0x05,
38 0x09, 0x01,
39 0x15, 0x80,
40 0x25, 0x7F,
41 0x75, 0x08,
42 0x95, 0x07,
43 0xB1, 0x02,
44 0xC0,
45 0x05, 0x0D,
46 0x09, 0x02,
47 0xA1, 0x01,
48 0x85, 0x10,
49 0x09, 0x20,
50 0xA0,
51 0x14,
52 0x25, 0x01,
53 0x75, 0x01,
54 0x09, 0x42,
55 0x09, 0x44,
56 0x09, 0x46,
57 0x95, 0x03,
58 0x81, 0x02,
59 0x95, 0x04,
60 0x81, 0x03,
61 0x09, 0x32,
62 0x95, 0x01,
63 0x81, 0x02,
64 0x75, 0x10,
65 0x95, 0x01,
66 0xA4,
67 0x05, 0x01,
68 0x55, 0xFD,
69 0x65, 0x13,
70 0x34,
71 0x09, 0x30,
72 0x46, 0x7C, 0x15,
73 0x26, 0x00, 0x37,
74 0x81, 0x02,
75 0x09, 0x31,
76 0x46, 0xA0, 0x0F,
77 0x26, 0x00, 0x28,
78 0x81, 0x02,
79 0xB4,
80 0x09, 0x30,
81 0x26, 0xFF, 0x03,
82 0x81, 0x02,
83 0xC0,
84 0xC0
85};
86
87
88
89
90
91
92
93#define MOUSEPEN_I608X_RDESC_ORIG_SIZE 476
94
95
96static __u8 mousepen_i608x_rdesc_fixed[] = {
97 0x06, 0x00, 0xFF,
98 0x09, 0x01,
99 0xA1, 0x01,
100 0x85, 0x05,
101 0x09, 0x01,
102 0x15, 0x80,
103 0x25, 0x7F,
104 0x75, 0x08,
105 0x95, 0x07,
106 0xB1, 0x02,
107 0xC0,
108 0x05, 0x0D,
109 0x09, 0x02,
110 0xA1, 0x01,
111 0x85, 0x10,
112 0x09, 0x20,
113 0xA0,
114 0x14,
115 0x25, 0x01,
116 0x75, 0x01,
117 0x09, 0x42,
118 0x09, 0x44,
119 0x09, 0x46,
120 0x95, 0x03,
121 0x81, 0x02,
122 0x95, 0x04,
123 0x81, 0x03,
124 0x09, 0x32,
125 0x95, 0x01,
126 0x81, 0x02,
127 0x75, 0x10,
128 0x95, 0x01,
129 0xA4,
130 0x05, 0x01,
131 0x55, 0xFD,
132 0x65, 0x13,
133 0x34,
134 0x09, 0x30,
135 0x46, 0x40, 0x1F,
136 0x26, 0x00, 0x50,
137 0x81, 0x02,
138 0x09, 0x31,
139 0x46, 0x70, 0x17,
140 0x26, 0x00, 0x3C,
141 0x81, 0x02,
142 0xB4,
143 0x09, 0x30,
144 0x26, 0xFF, 0x03,
145 0x81, 0x02,
146 0xC0,
147 0xC0,
148 0x05, 0x01,
149 0x09, 0x02,
150 0xA1, 0x01,
151 0x85, 0x11,
152 0x09, 0x01,
153 0xA0,
154 0x14,
155 0xA4,
156 0x05, 0x09,
157 0x75, 0x01,
158 0x19, 0x01,
159 0x29, 0x03,
160 0x25, 0x01,
161 0x95, 0x03,
162 0x81, 0x02,
163 0x95, 0x05,
164 0x81, 0x01,
165 0xB4,
166 0x95, 0x01,
167 0xA4,
168 0x55, 0xFD,
169 0x65, 0x13,
170 0x34,
171 0x75, 0x10,
172 0x09, 0x30,
173 0x46, 0x40, 0x1F,
174 0x26, 0x00, 0x50,
175 0x81, 0x02,
176 0x09, 0x31,
177 0x46, 0x70, 0x17,
178 0x26, 0x00, 0x3C,
179 0x81, 0x02,
180 0xB4,
181 0x75, 0x08,
182 0x09, 0x38,
183 0x15, 0xFF,
184 0x25, 0x01,
185 0x81, 0x06,
186 0x81, 0x01,
187 0xC0,
188 0xC0
189};
190
191
192
193
194
195
196
197#define EASYPEN_M610X_RDESC_ORIG_SIZE 476
198
199
200static __u8 easypen_m610x_rdesc_fixed[] = {
201 0x06, 0x00, 0xFF,
202 0x09, 0x01,
203 0xA1, 0x01,
204 0x85, 0x05,
205 0x09, 0x01,
206 0x15, 0x80,
207 0x25, 0x7F,
208 0x75, 0x08,
209 0x95, 0x07,
210 0xB1, 0x02,
211 0xC0,
212 0x05, 0x0D,
213 0x09, 0x02,
214 0xA1, 0x01,
215 0x85, 0x10,
216 0x09, 0x20,
217 0xA0,
218 0x14,
219 0x25, 0x01,
220 0x75, 0x01,
221 0x09, 0x42,
222 0x09, 0x44,
223 0x09, 0x46,
224 0x95, 0x03,
225 0x81, 0x02,
226 0x95, 0x04,
227 0x81, 0x03,
228 0x09, 0x32,
229 0x95, 0x01,
230 0x81, 0x02,
231 0x75, 0x10,
232 0x95, 0x01,
233 0xA4,
234 0x05, 0x01,
235 0x55, 0xFD,
236 0x65, 0x13,
237 0x34,
238 0x09, 0x30,
239 0x46, 0x10, 0x27,
240 0x27, 0x00, 0xA0, 0x00, 0x00,
241 0x81, 0x02,
242 0x09, 0x31,
243 0x46, 0x6A, 0x18,
244 0x26, 0x00, 0x64,
245 0x81, 0x02,
246 0xB4,
247 0x09, 0x30,
248 0x26, 0xFF, 0x03,
249 0x81, 0x02,
250 0xC0,
251 0xC0,
252 0x05, 0x0C,
253 0x09, 0x01,
254 0xA1, 0x01,
255 0x85, 0x12,
256 0x14,
257 0x25, 0x01,
258 0x75, 0x01,
259 0x95, 0x04,
260 0x0A, 0x1A, 0x02,
261 0x0A, 0x79, 0x02,
262 0x0A, 0x2D, 0x02,
263 0x0A, 0x2E, 0x02,
264 0x81, 0x02,
265 0x95, 0x01,
266 0x75, 0x14,
267 0x81, 0x03,
268 0x75, 0x20,
269 0x81, 0x03,
270 0xC0
271};
272
273static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
274 unsigned int *rsize)
275{
276 switch (hdev->product) {
277 case USB_DEVICE_ID_KYE_ERGO_525V:
278
279
280
281
282
283
284
285 if (*rsize >= 74 &&
286 rdesc[61] == 0x05 && rdesc[62] == 0x08 &&
287 rdesc[63] == 0x19 && rdesc[64] == 0x08 &&
288 rdesc[65] == 0x29 && rdesc[66] == 0x0f &&
289 rdesc[71] == 0x75 && rdesc[72] == 0x08 &&
290 rdesc[73] == 0x95 && rdesc[74] == 0x01) {
291 hid_info(hdev,
292 "fixing up Kye/Genius Ergo Mouse "
293 "report descriptor\n");
294 rdesc[62] = 0x09;
295 rdesc[64] = 0x04;
296 rdesc[66] = 0x07;
297 rdesc[72] = 0x01;
298 rdesc[74] = 0x08;
299 }
300 break;
301 case USB_DEVICE_ID_KYE_EASYPEN_I405X:
302 if (*rsize == EASYPEN_I405X_RDESC_ORIG_SIZE) {
303 rdesc = easypen_i405x_rdesc_fixed;
304 *rsize = sizeof(easypen_i405x_rdesc_fixed);
305 }
306 break;
307 case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
308 if (*rsize == MOUSEPEN_I608X_RDESC_ORIG_SIZE) {
309 rdesc = mousepen_i608x_rdesc_fixed;
310 *rsize = sizeof(mousepen_i608x_rdesc_fixed);
311 }
312 break;
313 case USB_DEVICE_ID_KYE_EASYPEN_M610X:
314 if (*rsize == EASYPEN_M610X_RDESC_ORIG_SIZE) {
315 rdesc = easypen_m610x_rdesc_fixed;
316 *rsize = sizeof(easypen_m610x_rdesc_fixed);
317 }
318 break;
319 }
320 return rdesc;
321}
322
323
324
325
326
327
328
329
330
331static int kye_tablet_enable(struct hid_device *hdev)
332{
333 struct list_head *list;
334 struct list_head *head;
335 struct hid_report *report;
336 __s32 *value;
337
338 list = &hdev->report_enum[HID_FEATURE_REPORT].report_list;
339 list_for_each(head, list) {
340 report = list_entry(head, struct hid_report, list);
341 if (report->id == 5)
342 break;
343 }
344
345 if (head == list) {
346 hid_err(hdev, "tablet-enabling feature report not found\n");
347 return -ENODEV;
348 }
349
350 if (report->maxfield < 1 || report->field[0]->report_count < 7) {
351 hid_err(hdev, "invalid tablet-enabling feature report\n");
352 return -ENODEV;
353 }
354
355 value = report->field[0]->value;
356
357 value[0] = 0x12;
358 value[1] = 0x10;
359 value[2] = 0x11;
360 value[3] = 0x12;
361 value[4] = 0x00;
362 value[5] = 0x00;
363 value[6] = 0x00;
364 usbhid_submit_report(hdev, report, USB_DIR_OUT);
365
366 return 0;
367}
368
369static int kye_probe(struct hid_device *hdev, const struct hid_device_id *id)
370{
371 int ret;
372
373 ret = hid_parse(hdev);
374 if (ret) {
375 hid_err(hdev, "parse failed\n");
376 goto err;
377 }
378
379 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
380 if (ret) {
381 hid_err(hdev, "hw start failed\n");
382 goto err;
383 }
384
385 switch (id->product) {
386 case USB_DEVICE_ID_KYE_EASYPEN_I405X:
387 case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
388 case USB_DEVICE_ID_KYE_EASYPEN_M610X:
389 ret = kye_tablet_enable(hdev);
390 if (ret) {
391 hid_err(hdev, "tablet enabling failed\n");
392 goto enabling_err;
393 }
394 break;
395 }
396
397 return 0;
398enabling_err:
399 hid_hw_stop(hdev);
400err:
401 return ret;
402}
403
404static const struct hid_device_id kye_devices[] = {
405 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
406 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
407 USB_DEVICE_ID_KYE_EASYPEN_I405X) },
408 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
409 USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
410 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
411 USB_DEVICE_ID_KYE_EASYPEN_M610X) },
412 { }
413};
414MODULE_DEVICE_TABLE(hid, kye_devices);
415
416static struct hid_driver kye_driver = {
417 .name = "kye",
418 .id_table = kye_devices,
419 .probe = kye_probe,
420 .report_fixup = kye_report_fixup,
421};
422module_hid_driver(kye_driver);
423
424MODULE_LICENSE("GPL");
425