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