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
271static __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc,
272 unsigned int *rsize, int offset, const char *device_name) {
273
274
275
276
277
278 if (*rsize >= offset + 31 &&
279
280 rdesc[offset] == 0x05 && rdesc[offset + 1] == 0x0c &&
281
282 rdesc[offset + 2] == 0x09 && rdesc[offset + 3] == 0x01 &&
283
284 rdesc[offset + 10] == 0x2a && rdesc[offset + 12] > 0x2f) {
285 hid_info(hdev, "fixing up %s report descriptor\n", device_name);
286 rdesc[offset + 12] = 0x2f;
287 }
288 return rdesc;
289}
290
291static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
292 unsigned int *rsize)
293{
294 switch (hdev->product) {
295 case USB_DEVICE_ID_KYE_ERGO_525V:
296
297
298
299
300
301
302
303 if (*rsize >= 74 &&
304 rdesc[61] == 0x05 && rdesc[62] == 0x08 &&
305 rdesc[63] == 0x19 && rdesc[64] == 0x08 &&
306 rdesc[65] == 0x29 && rdesc[66] == 0x0f &&
307 rdesc[71] == 0x75 && rdesc[72] == 0x08 &&
308 rdesc[73] == 0x95 && rdesc[74] == 0x01) {
309 hid_info(hdev,
310 "fixing up Kye/Genius Ergo Mouse "
311 "report descriptor\n");
312 rdesc[62] = 0x09;
313 rdesc[64] = 0x04;
314 rdesc[66] = 0x07;
315 rdesc[72] = 0x01;
316 rdesc[74] = 0x08;
317 }
318 break;
319 case USB_DEVICE_ID_KYE_EASYPEN_I405X:
320 if (*rsize == EASYPEN_I405X_RDESC_ORIG_SIZE) {
321 rdesc = easypen_i405x_rdesc_fixed;
322 *rsize = sizeof(easypen_i405x_rdesc_fixed);
323 }
324 break;
325 case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
326 if (*rsize == MOUSEPEN_I608X_RDESC_ORIG_SIZE) {
327 rdesc = mousepen_i608x_rdesc_fixed;
328 *rsize = sizeof(mousepen_i608x_rdesc_fixed);
329 }
330 break;
331 case USB_DEVICE_ID_KYE_EASYPEN_M610X:
332 if (*rsize == EASYPEN_M610X_RDESC_ORIG_SIZE) {
333 rdesc = easypen_m610x_rdesc_fixed;
334 *rsize = sizeof(easypen_m610x_rdesc_fixed);
335 }
336 break;
337 case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE:
338 rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
339 "Genius Gila Gaming Mouse");
340 break;
341 case USB_DEVICE_ID_GENIUS_GX_IMPERATOR:
342 rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83,
343 "Genius Gx Imperator Keyboard");
344 break;
345 case USB_DEVICE_ID_GENIUS_MANTICORE:
346 rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
347 "Genius Manticore Keyboard");
348 break;
349 }
350 return rdesc;
351}
352
353
354
355
356
357
358
359
360
361static int kye_tablet_enable(struct hid_device *hdev)
362{
363 struct list_head *list;
364 struct list_head *head;
365 struct hid_report *report;
366 __s32 *value;
367
368 list = &hdev->report_enum[HID_FEATURE_REPORT].report_list;
369 list_for_each(head, list) {
370 report = list_entry(head, struct hid_report, list);
371 if (report->id == 5)
372 break;
373 }
374
375 if (head == list) {
376 hid_err(hdev, "tablet-enabling feature report not found\n");
377 return -ENODEV;
378 }
379
380 if (report->maxfield < 1 || report->field[0]->report_count < 7) {
381 hid_err(hdev, "invalid tablet-enabling feature report\n");
382 return -ENODEV;
383 }
384
385 value = report->field[0]->value;
386
387 value[0] = 0x12;
388 value[1] = 0x10;
389 value[2] = 0x11;
390 value[3] = 0x12;
391 value[4] = 0x00;
392 value[5] = 0x00;
393 value[6] = 0x00;
394 hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
395
396 return 0;
397}
398
399static int kye_probe(struct hid_device *hdev, const struct hid_device_id *id)
400{
401 int ret;
402
403 ret = hid_parse(hdev);
404 if (ret) {
405 hid_err(hdev, "parse failed\n");
406 goto err;
407 }
408
409 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
410 if (ret) {
411 hid_err(hdev, "hw start failed\n");
412 goto err;
413 }
414
415 switch (id->product) {
416 case USB_DEVICE_ID_KYE_EASYPEN_I405X:
417 case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
418 case USB_DEVICE_ID_KYE_EASYPEN_M610X:
419 ret = kye_tablet_enable(hdev);
420 if (ret) {
421 hid_err(hdev, "tablet enabling failed\n");
422 goto enabling_err;
423 }
424 break;
425 case USB_DEVICE_ID_GENIUS_MANTICORE:
426
427
428
429
430 if (hid_hw_open(hdev))
431 hid_hw_close(hdev);
432 break;
433 }
434
435 return 0;
436enabling_err:
437 hid_hw_stop(hdev);
438err:
439 return ret;
440}
441
442static const struct hid_device_id kye_devices[] = {
443 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
444 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
445 USB_DEVICE_ID_KYE_EASYPEN_I405X) },
446 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
447 USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
448 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
449 USB_DEVICE_ID_KYE_EASYPEN_M610X) },
450 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
451 USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
452 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
453 USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
454 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
455 USB_DEVICE_ID_GENIUS_MANTICORE) },
456 { }
457};
458MODULE_DEVICE_TABLE(hid, kye_devices);
459
460static struct hid_driver kye_driver = {
461 .name = "kye",
462 .id_table = kye_devices,
463 .probe = kye_probe,
464 .report_fixup = kye_report_fixup,
465};
466module_hid_driver(kye_driver);
467
468MODULE_LICENSE("GPL");
469