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