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
20#include "hid-ids.h"
21
22
23
24
25
26
27
28#define EASYPEN_I405X_RDESC_ORIG_SIZE 476
29
30
31static __u8 easypen_i405x_rdesc_fixed[] = {
32 0x06, 0x00, 0xFF,
33 0x09, 0x01,
34 0xA1, 0x01,
35 0x85, 0x05,
36 0x09, 0x01,
37 0x15, 0x80,
38 0x25, 0x7F,
39 0x75, 0x08,
40 0x95, 0x07,
41 0xB1, 0x02,
42 0xC0,
43 0x05, 0x0D,
44 0x09, 0x02,
45 0xA1, 0x01,
46 0x85, 0x10,
47 0x09, 0x20,
48 0xA0,
49 0x14,
50 0x25, 0x01,
51 0x75, 0x01,
52 0x09, 0x42,
53 0x09, 0x44,
54 0x09, 0x46,
55 0x95, 0x03,
56 0x81, 0x02,
57 0x95, 0x04,
58 0x81, 0x03,
59 0x09, 0x32,
60 0x95, 0x01,
61 0x81, 0x02,
62 0x75, 0x10,
63 0x95, 0x01,
64 0xA4,
65 0x05, 0x01,
66 0x55, 0xFD,
67 0x65, 0x13,
68 0x34,
69 0x09, 0x30,
70 0x46, 0x7C, 0x15,
71 0x26, 0x00, 0x37,
72 0x81, 0x02,
73 0x09, 0x31,
74 0x46, 0xA0, 0x0F,
75 0x26, 0x00, 0x28,
76 0x81, 0x02,
77 0xB4,
78 0x09, 0x30,
79 0x26, 0xFF, 0x03,
80 0x81, 0x02,
81 0xC0,
82 0xC0
83};
84
85
86
87
88
89
90
91#define MOUSEPEN_I608X_RDESC_ORIG_SIZE 476
92
93
94static __u8 mousepen_i608x_rdesc_fixed[] = {
95 0x06, 0x00, 0xFF,
96 0x09, 0x01,
97 0xA1, 0x01,
98 0x85, 0x05,
99 0x09, 0x01,
100 0x15, 0x80,
101 0x25, 0x7F,
102 0x75, 0x08,
103 0x95, 0x07,
104 0xB1, 0x02,
105 0xC0,
106 0x05, 0x0D,
107 0x09, 0x02,
108 0xA1, 0x01,
109 0x85, 0x10,
110 0x09, 0x20,
111 0xA0,
112 0x14,
113 0x25, 0x01,
114 0x75, 0x01,
115 0x09, 0x42,
116 0x09, 0x44,
117 0x09, 0x46,
118 0x95, 0x03,
119 0x81, 0x02,
120 0x95, 0x04,
121 0x81, 0x03,
122 0x09, 0x32,
123 0x95, 0x01,
124 0x81, 0x02,
125 0x75, 0x10,
126 0x95, 0x01,
127 0xA4,
128 0x05, 0x01,
129 0x55, 0xFD,
130 0x65, 0x13,
131 0x34,
132 0x09, 0x30,
133 0x46, 0x40, 0x1F,
134 0x26, 0x00, 0x50,
135 0x81, 0x02,
136 0x09, 0x31,
137 0x46, 0x70, 0x17,
138 0x26, 0x00, 0x3C,
139 0x81, 0x02,
140 0xB4,
141 0x09, 0x30,
142 0x26, 0xFF, 0x03,
143 0x81, 0x02,
144 0xC0,
145 0xC0,
146 0x05, 0x01,
147 0x09, 0x02,
148 0xA1, 0x01,
149 0x85, 0x11,
150 0x09, 0x01,
151 0xA0,
152 0x14,
153 0xA4,
154 0x05, 0x09,
155 0x75, 0x01,
156 0x19, 0x01,
157 0x29, 0x03,
158 0x25, 0x01,
159 0x95, 0x03,
160 0x81, 0x02,
161 0x95, 0x05,
162 0x81, 0x01,
163 0xB4,
164 0x95, 0x01,
165 0xA4,
166 0x55, 0xFD,
167 0x65, 0x13,
168 0x34,
169 0x75, 0x10,
170 0x09, 0x30,
171 0x46, 0x40, 0x1F,
172 0x26, 0x00, 0x50,
173 0x81, 0x02,
174 0x09, 0x31,
175 0x46, 0x70, 0x17,
176 0x26, 0x00, 0x3C,
177 0x81, 0x02,
178 0xB4,
179 0x75, 0x08,
180 0x09, 0x38,
181 0x15, 0xFF,
182 0x25, 0x01,
183 0x81, 0x06,
184 0x81, 0x01,
185 0xC0,
186 0xC0
187};
188
189
190
191
192
193
194
195#define EASYPEN_M610X_RDESC_ORIG_SIZE 476
196
197
198static __u8 easypen_m610x_rdesc_fixed[] = {
199 0x06, 0x00, 0xFF,
200 0x09, 0x01,
201 0xA1, 0x01,
202 0x85, 0x05,
203 0x09, 0x01,
204 0x15, 0x80,
205 0x25, 0x7F,
206 0x75, 0x08,
207 0x95, 0x07,
208 0xB1, 0x02,
209 0xC0,
210 0x05, 0x0D,
211 0x09, 0x02,
212 0xA1, 0x01,
213 0x85, 0x10,
214 0x09, 0x20,
215 0xA0,
216 0x14,
217 0x25, 0x01,
218 0x75, 0x01,
219 0x09, 0x42,
220 0x09, 0x44,
221 0x09, 0x46,
222 0x95, 0x03,
223 0x81, 0x02,
224 0x95, 0x04,
225 0x81, 0x03,
226 0x09, 0x32,
227 0x95, 0x01,
228 0x81, 0x02,
229 0x75, 0x10,
230 0x95, 0x01,
231 0xA4,
232 0x05, 0x01,
233 0x55, 0xFD,
234 0x65, 0x13,
235 0x34,
236 0x09, 0x30,
237 0x46, 0x10, 0x27,
238 0x27, 0x00, 0xA0, 0x00, 0x00,
239 0x81, 0x02,
240 0x09, 0x31,
241 0x46, 0x6A, 0x18,
242 0x26, 0x00, 0x64,
243 0x81, 0x02,
244 0xB4,
245 0x09, 0x30,
246 0x26, 0xFF, 0x03,
247 0x81, 0x02,
248 0xC0,
249 0xC0,
250 0x05, 0x0C,
251 0x09, 0x01,
252 0xA1, 0x01,
253 0x85, 0x12,
254 0x14,
255 0x25, 0x01,
256 0x75, 0x01,
257 0x95, 0x04,
258 0x0A, 0x1A, 0x02,
259 0x0A, 0x79, 0x02,
260 0x0A, 0x2D, 0x02,
261 0x0A, 0x2E, 0x02,
262 0x81, 0x02,
263 0x95, 0x01,
264 0x75, 0x14,
265 0x81, 0x03,
266 0x75, 0x20,
267 0x81, 0x03,
268 0xC0
269};
270
271
272
273#define PENSKETCH_M912_RDESC_ORIG_SIZE 482
274
275
276static __u8 pensketch_m912_rdesc_fixed[] = {
277 0x05, 0x01,
278 0x08,
279 0xA1, 0x01,
280 0x85, 0x05,
281 0x06, 0x00, 0xFF,
282 0x09, 0x01,
283 0x15, 0x81,
284 0x25, 0x7F,
285 0x75, 0x08,
286 0x95, 0x07,
287 0xB1, 0x02,
288 0xC0,
289 0x05, 0x0D,
290 0x09, 0x02,
291 0xA1, 0x01,
292 0x85, 0x10,
293 0x09, 0x20,
294 0xA0,
295 0x09, 0x42,
296 0x09, 0x44,
297 0x09, 0x46,
298 0x14,
299 0x25, 0x01,
300 0x75, 0x01,
301 0x95, 0x03,
302 0x81, 0x02,
303 0x95, 0x04,
304 0x81, 0x03,
305 0x09, 0x32,
306 0x95, 0x01,
307 0x81, 0x02,
308 0x75, 0x10,
309 0x95, 0x01,
310 0xA4,
311 0x05, 0x01,
312 0x55, 0xFD,
313 0x65, 0x13,
314 0x14,
315 0x34,
316 0x09, 0x30,
317 0x27, 0x00, 0xF0, 0x00, 0x00,
318 0x46, 0xE0, 0x2E,
319 0x81, 0x02,
320 0x09, 0x31,
321 0x27, 0x00, 0xB4, 0x00, 0x00,
322 0x46, 0x28, 0x23,
323 0x81, 0x02,
324 0xB4,
325 0x09, 0x30,
326 0x14,
327 0x26, 0xFF, 0x07,
328 0x81, 0x02,
329 0xC0,
330 0xC0,
331 0x05, 0x0D,
332 0x09, 0x21,
333 0xA1, 0x01,
334 0x85, 0x11,
335 0x09, 0x21,
336 0xA0,
337 0x05, 0x09,
338 0x75, 0x01,
339 0x19, 0x01,
340 0x29, 0x03,
341 0x14,
342 0x25, 0x01,
343 0x95, 0x03,
344 0x81, 0x02,
345 0x95, 0x04,
346 0x81, 0x01,
347 0x95, 0x01,
348 0x0B, 0x32, 0x00, 0x0D, 0x00,
349 0x14,
350 0x25, 0x01,
351 0x81, 0x02,
352 0xA4,
353 0x05, 0x01,
354 0x75, 0x10,
355 0x95, 0x01,
356 0x55, 0xFD,
357 0x65, 0x13,
358 0x14,
359 0x34,
360 0x09, 0x30,
361 0x27, 0x00, 0xF0, 0x00, 0x00,
362 0x46, 0xE0, 0x2E,
363 0x81, 0x02,
364 0x09, 0x31,
365 0x27, 0x00, 0xB4, 0x00, 0x00,
366 0x46, 0x28, 0x23,
367 0x81, 0x02,
368 0x09, 0x38,
369 0x75, 0x08,
370 0x95, 0x01,
371 0x15, 0xFF,
372 0x25, 0x01,
373 0x34,
374 0x44,
375 0x81, 0x06,
376 0xB4,
377 0xC0,
378 0xC0,
379 0x05, 0x0C,
380 0x09, 0x01,
381 0xA1, 0x01,
382 0x85, 0x12,
383 0x14,
384 0x25, 0x01,
385 0x75, 0x01,
386 0x95, 0x08,
387 0x05, 0x0C,
388 0x0A, 0x6A, 0x02,
389 0x0A, 0x1A, 0x02,
390 0x0A, 0x01, 0x02,
391 0x0A, 0x2F, 0x02,
392 0x0A, 0x25, 0x02,
393 0x0A, 0x24, 0x02,
394 0x0A, 0x2D, 0x02,
395 0x0A, 0x2E, 0x02,
396 0x81, 0x02,
397 0x95, 0x30,
398 0x81, 0x03,
399 0xC0
400};
401
402static __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc,
403 unsigned int *rsize, int offset, const char *device_name) {
404
405
406
407
408
409 if (*rsize >= offset + 31 &&
410
411 rdesc[offset] == 0x05 && rdesc[offset + 1] == 0x0c &&
412
413 rdesc[offset + 2] == 0x09 && rdesc[offset + 3] == 0x01 &&
414
415 rdesc[offset + 10] == 0x2a && rdesc[offset + 12] > 0x2f) {
416 hid_info(hdev, "fixing up %s report descriptor\n", device_name);
417 rdesc[offset + 12] = 0x2f;
418 }
419 return rdesc;
420}
421
422static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
423 unsigned int *rsize)
424{
425 switch (hdev->product) {
426 case USB_DEVICE_ID_KYE_ERGO_525V:
427
428
429
430
431
432
433
434 if (*rsize >= 75 &&
435 rdesc[61] == 0x05 && rdesc[62] == 0x08 &&
436 rdesc[63] == 0x19 && rdesc[64] == 0x08 &&
437 rdesc[65] == 0x29 && rdesc[66] == 0x0f &&
438 rdesc[71] == 0x75 && rdesc[72] == 0x08 &&
439 rdesc[73] == 0x95 && rdesc[74] == 0x01) {
440 hid_info(hdev,
441 "fixing up Kye/Genius Ergo Mouse "
442 "report descriptor\n");
443 rdesc[62] = 0x09;
444 rdesc[64] = 0x04;
445 rdesc[66] = 0x07;
446 rdesc[72] = 0x01;
447 rdesc[74] = 0x08;
448 }
449 break;
450 case USB_DEVICE_ID_KYE_EASYPEN_I405X:
451 if (*rsize == EASYPEN_I405X_RDESC_ORIG_SIZE) {
452 rdesc = easypen_i405x_rdesc_fixed;
453 *rsize = sizeof(easypen_i405x_rdesc_fixed);
454 }
455 break;
456 case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
457 case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2:
458 if (*rsize == MOUSEPEN_I608X_RDESC_ORIG_SIZE) {
459 rdesc = mousepen_i608x_rdesc_fixed;
460 *rsize = sizeof(mousepen_i608x_rdesc_fixed);
461 }
462 break;
463 case USB_DEVICE_ID_KYE_EASYPEN_M610X:
464 if (*rsize == EASYPEN_M610X_RDESC_ORIG_SIZE) {
465 rdesc = easypen_m610x_rdesc_fixed;
466 *rsize = sizeof(easypen_m610x_rdesc_fixed);
467 }
468 break;
469 case USB_DEVICE_ID_KYE_PENSKETCH_M912:
470 if (*rsize == PENSKETCH_M912_RDESC_ORIG_SIZE) {
471 rdesc = pensketch_m912_rdesc_fixed;
472 *rsize = sizeof(pensketch_m912_rdesc_fixed);
473 }
474 break;
475 case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE:
476 rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
477 "Genius Gila Gaming Mouse");
478 break;
479 case USB_DEVICE_ID_GENIUS_GX_IMPERATOR:
480 rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83,
481 "Genius Gx Imperator Keyboard");
482 break;
483 case USB_DEVICE_ID_GENIUS_MANTICORE:
484 rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
485 "Genius Manticore Keyboard");
486 break;
487 }
488 return rdesc;
489}
490
491
492
493
494
495
496
497
498
499static int kye_tablet_enable(struct hid_device *hdev)
500{
501 struct list_head *list;
502 struct list_head *head;
503 struct hid_report *report;
504 __s32 *value;
505
506 list = &hdev->report_enum[HID_FEATURE_REPORT].report_list;
507 list_for_each(head, list) {
508 report = list_entry(head, struct hid_report, list);
509 if (report->id == 5)
510 break;
511 }
512
513 if (head == list) {
514 hid_err(hdev, "tablet-enabling feature report not found\n");
515 return -ENODEV;
516 }
517
518 if (report->maxfield < 1 || report->field[0]->report_count < 7) {
519 hid_err(hdev, "invalid tablet-enabling feature report\n");
520 return -ENODEV;
521 }
522
523 value = report->field[0]->value;
524
525 value[0] = 0x12;
526 value[1] = 0x10;
527 value[2] = 0x11;
528 value[3] = 0x12;
529 value[4] = 0x00;
530 value[5] = 0x00;
531 value[6] = 0x00;
532 hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
533
534 return 0;
535}
536
537static int kye_probe(struct hid_device *hdev, const struct hid_device_id *id)
538{
539 int ret;
540
541 ret = hid_parse(hdev);
542 if (ret) {
543 hid_err(hdev, "parse failed\n");
544 goto err;
545 }
546
547 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
548 if (ret) {
549 hid_err(hdev, "hw start failed\n");
550 goto err;
551 }
552
553 switch (id->product) {
554 case USB_DEVICE_ID_KYE_EASYPEN_I405X:
555 case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
556 case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2:
557 case USB_DEVICE_ID_KYE_EASYPEN_M610X:
558 case USB_DEVICE_ID_KYE_PENSKETCH_M912:
559 ret = kye_tablet_enable(hdev);
560 if (ret) {
561 hid_err(hdev, "tablet enabling failed\n");
562 goto enabling_err;
563 }
564 break;
565 case USB_DEVICE_ID_GENIUS_MANTICORE:
566
567
568
569
570 if (hid_hw_open(hdev))
571 hid_hw_close(hdev);
572 break;
573 }
574
575 return 0;
576enabling_err:
577 hid_hw_stop(hdev);
578err:
579 return ret;
580}
581
582static const struct hid_device_id kye_devices[] = {
583 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
584 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
585 USB_DEVICE_ID_KYE_EASYPEN_I405X) },
586 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
587 USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
588 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
589 USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2) },
590 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
591 USB_DEVICE_ID_KYE_EASYPEN_M610X) },
592 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
593 USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
594 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
595 USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
596 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
597 USB_DEVICE_ID_GENIUS_MANTICORE) },
598 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
599 USB_DEVICE_ID_KYE_PENSKETCH_M912) },
600 { }
601};
602MODULE_DEVICE_TABLE(hid, kye_devices);
603
604static struct hid_driver kye_driver = {
605 .name = "kye",
606 .id_table = kye_devices,
607 .probe = kye_probe,
608 .report_fixup = kye_report_fixup,
609};
610module_hid_driver(kye_driver);
611
612MODULE_LICENSE("GPL");
613