2 * HID driver for Waltop devices not fully compliant with HID standard
4 * Copyright (c) 2010 Nikolai Kondrashov
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
14 #include <linux/device.h>
15 #include <linux/hid.h>
16 #include <linux/module.h>
21 * There exists an official driver on the manufacturer's website, which
22 * wasn't submitted to the kernel, for some reason. The official driver
23 * doesn't seem to support extra features of some tablets, like wheels.
25 * It shows that the feature report ID 2 could be used to control any waltop
26 * tablet input mode, switching it between "default", "tablet" and "ink".
28 * This driver only uses "default" mode for all the supported tablets. This
29 * mode tries to be HID-compatible (not very successfully), but cripples the
30 * resolution of some tablets.
32 * The "tablet" mode uses some proprietary, yet decipherable protocol, which
33 * represents the correct resolution, but is possibly HID-incompatible (i.e.
34 * indescribable by a report descriptor).
36 * The purpose of the "ink" mode is unknown.
38 * The feature reports needed for switching to each mode are these:
46 * See Slim Tablet 5.8 inch description, device and HID report descriptors at
47 * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Slim_Tablet_5.8%22
50 /* Size of the original report descriptor of Slim Tablet 5.8 inch */
51 #define SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE 222
53 /* Fixed Slim Tablet 5.8 inch descriptor */
54 static __u8 slim_tablet_5_8_inch_rdesc_fixed
[] = {
55 0x05, 0x0D, /* Usage Page (Digitizer), */
56 0x09, 0x02, /* Usage (Pen), */
57 0xA1, 0x01, /* Collection (Application), */
58 0x85, 0x10, /* Report ID (16), */
59 0x09, 0x20, /* Usage (Stylus), */
60 0xA0, /* Collection (Physical), */
61 0x09, 0x42, /* Usage (Tip Switch), */
62 0x09, 0x44, /* Usage (Barrel Switch), */
63 0x09, 0x46, /* Usage (Tablet Pick), */
64 0x15, 0x01, /* Logical Minimum (1), */
65 0x25, 0x03, /* Logical Maximum (3), */
66 0x75, 0x04, /* Report Size (4), */
67 0x95, 0x01, /* Report Count (1), */
69 0x09, 0x32, /* Usage (In Range), */
70 0x14, /* Logical Minimum (0), */
71 0x25, 0x01, /* Logical Maximum (1), */
72 0x75, 0x01, /* Report Size (1), */
73 0x95, 0x01, /* Report Count (1), */
74 0x81, 0x02, /* Input (Variable), */
75 0x95, 0x03, /* Report Count (3), */
76 0x81, 0x03, /* Input (Constant, Variable), */
77 0x75, 0x10, /* Report Size (16), */
78 0x95, 0x01, /* Report Count (1), */
79 0x14, /* Logical Minimum (0), */
81 0x05, 0x01, /* Usage Page (Desktop), */
82 0x65, 0x13, /* Unit (Inch), */
83 0x55, 0xFD, /* Unit Exponent (-3), */
84 0x34, /* Physical Minimum (0), */
85 0x09, 0x30, /* Usage (X), */
86 0x46, 0x88, 0x13, /* Physical Maximum (5000), */
87 0x26, 0x10, 0x27, /* Logical Maximum (10000), */
88 0x81, 0x02, /* Input (Variable), */
89 0x09, 0x31, /* Usage (Y), */
90 0x46, 0xB8, 0x0B, /* Physical Maximum (3000), */
91 0x26, 0x70, 0x17, /* Logical Maximum (6000), */
92 0x81, 0x02, /* Input (Variable), */
94 0x09, 0x30, /* Usage (Tip Pressure), */
95 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
96 0x81, 0x02, /* Input (Variable), */
97 0xC0, /* End Collection, */
98 0xC0 /* End Collection */
102 * See Slim Tablet 12.1 inch description, device and HID report descriptors at
103 * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Slim_Tablet_12.1%22
106 /* Size of the original report descriptor of Slim Tablet 12.1 inch */
107 #define SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE 269
109 /* Fixed Slim Tablet 12.1 inch descriptor */
110 static __u8 slim_tablet_12_1_inch_rdesc_fixed
[] = {
111 0x05, 0x0D, /* Usage Page (Digitizer), */
112 0x09, 0x02, /* Usage (Pen), */
113 0xA1, 0x01, /* Collection (Application), */
114 0x85, 0x10, /* Report ID (16), */
115 0x09, 0x20, /* Usage (Stylus), */
116 0xA0, /* Collection (Physical), */
117 0x09, 0x42, /* Usage (Tip Switch), */
118 0x09, 0x44, /* Usage (Barrel Switch), */
119 0x09, 0x46, /* Usage (Tablet Pick), */
120 0x15, 0x01, /* Logical Minimum (1), */
121 0x25, 0x03, /* Logical Maximum (3), */
122 0x75, 0x04, /* Report Size (4), */
123 0x95, 0x01, /* Report Count (1), */
125 0x09, 0x32, /* Usage (In Range), */
126 0x14, /* Logical Minimum (0), */
127 0x25, 0x01, /* Logical Maximum (1), */
128 0x75, 0x01, /* Report Size (1), */
129 0x95, 0x01, /* Report Count (1), */
130 0x81, 0x02, /* Input (Variable), */
131 0x95, 0x03, /* Report Count (3), */
132 0x81, 0x03, /* Input (Constant, Variable), */
133 0x75, 0x10, /* Report Size (16), */
134 0x95, 0x01, /* Report Count (1), */
135 0x14, /* Logical Minimum (0), */
137 0x05, 0x01, /* Usage Page (Desktop), */
138 0x65, 0x13, /* Unit (Inch), */
139 0x55, 0xFD, /* Unit Exponent (-3), */
140 0x34, /* Physical Minimum (0), */
141 0x09, 0x30, /* Usage (X), */
142 0x46, 0x10, 0x27, /* Physical Maximum (10000), */
143 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */
144 0x81, 0x02, /* Input (Variable), */
145 0x09, 0x31, /* Usage (Y), */
146 0x46, 0x6A, 0x18, /* Physical Maximum (6250), */
147 0x26, 0xD4, 0x30, /* Logical Maximum (12500), */
148 0x81, 0x02, /* Input (Variable), */
150 0x09, 0x30, /* Usage (Tip Pressure), */
151 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
152 0x81, 0x02, /* Input (Variable), */
153 0xC0, /* End Collection, */
154 0xC0 /* End Collection */
158 * See Q Pad description, device and HID report descriptors at
159 * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Q_Pad
162 /* Size of the original report descriptor of Q Pad */
163 #define Q_PAD_RDESC_ORIG_SIZE 241
165 /* Fixed Q Pad descriptor */
166 static __u8 q_pad_rdesc_fixed
[] = {
167 0x05, 0x0D, /* Usage Page (Digitizer), */
168 0x09, 0x02, /* Usage (Pen), */
169 0xA1, 0x01, /* Collection (Application), */
170 0x85, 0x10, /* Report ID (16), */
171 0x09, 0x20, /* Usage (Stylus), */
172 0xA0, /* Collection (Physical), */
173 0x09, 0x42, /* Usage (Tip Switch), */
174 0x09, 0x44, /* Usage (Barrel Switch), */
175 0x09, 0x46, /* Usage (Tablet Pick), */
176 0x15, 0x01, /* Logical Minimum (1), */
177 0x25, 0x03, /* Logical Maximum (3), */
178 0x75, 0x04, /* Report Size (4), */
179 0x95, 0x01, /* Report Count (1), */
181 0x09, 0x32, /* Usage (In Range), */
182 0x14, /* Logical Minimum (0), */
183 0x25, 0x01, /* Logical Maximum (1), */
184 0x75, 0x01, /* Report Size (1), */
185 0x95, 0x01, /* Report Count (1), */
186 0x81, 0x02, /* Input (Variable), */
187 0x95, 0x03, /* Report Count (3), */
188 0x81, 0x03, /* Input (Constant, Variable), */
189 0x75, 0x10, /* Report Size (16), */
190 0x95, 0x01, /* Report Count (1), */
191 0x14, /* Logical Minimum (0), */
193 0x05, 0x01, /* Usage Page (Desktop), */
194 0x65, 0x13, /* Unit (Inch), */
195 0x55, 0xFD, /* Unit Exponent (-3), */
196 0x34, /* Physical Minimum (0), */
197 0x09, 0x30, /* Usage (X), */
198 0x46, 0x70, 0x17, /* Physical Maximum (6000), */
199 0x26, 0x00, 0x30, /* Logical Maximum (12288), */
200 0x81, 0x02, /* Input (Variable), */
201 0x09, 0x31, /* Usage (Y), */
202 0x46, 0x94, 0x11, /* Physical Maximum (4500), */
203 0x26, 0x00, 0x24, /* Logical Maximum (9216), */
204 0x81, 0x02, /* Input (Variable), */
206 0x09, 0x30, /* Usage (Tip Pressure), */
207 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
208 0x81, 0x02, /* Input (Variable), */
209 0xC0, /* End Collection, */
210 0xC0 /* End Collection */
214 * See description, device and HID report descriptors of tablet with PID 0038 at
215 * http://sf.net/apps/mediawiki/digimend/?title=Waltop_PID_0038
218 /* Size of the original report descriptor of tablet with PID 0038 */
219 #define PID_0038_RDESC_ORIG_SIZE 241
222 * Fixed report descriptor for tablet with PID 0038.
224 static __u8 pid_0038_rdesc_fixed
[] = {
225 0x05, 0x0D, /* Usage Page (Digitizer), */
226 0x09, 0x02, /* Usage (Pen), */
227 0xA1, 0x01, /* Collection (Application), */
228 0x85, 0x10, /* Report ID (16), */
229 0x09, 0x20, /* Usage (Stylus), */
230 0xA0, /* Collection (Physical), */
231 0x09, 0x42, /* Usage (Tip Switch), */
232 0x09, 0x44, /* Usage (Barrel Switch), */
233 0x09, 0x46, /* Usage (Tablet Pick), */
234 0x15, 0x01, /* Logical Minimum (1), */
235 0x25, 0x03, /* Logical Maximum (3), */
236 0x75, 0x04, /* Report Size (4), */
237 0x95, 0x01, /* Report Count (1), */
239 0x09, 0x32, /* Usage (In Range), */
240 0x14, /* Logical Minimum (0), */
241 0x25, 0x01, /* Logical Maximum (1), */
242 0x75, 0x01, /* Report Size (1), */
243 0x95, 0x01, /* Report Count (1), */
244 0x81, 0x02, /* Input (Variable), */
245 0x95, 0x03, /* Report Count (3), */
246 0x81, 0x03, /* Input (Constant, Variable), */
247 0x75, 0x10, /* Report Size (16), */
248 0x95, 0x01, /* Report Count (1), */
249 0x14, /* Logical Minimum (0), */
251 0x05, 0x01, /* Usage Page (Desktop), */
252 0x65, 0x13, /* Unit (Inch), */
253 0x55, 0xFD, /* Unit Exponent (-3), */
254 0x34, /* Physical Minimum (0), */
255 0x09, 0x30, /* Usage (X), */
256 0x46, 0x2E, 0x22, /* Physical Maximum (8750), */
257 0x26, 0x00, 0x46, /* Logical Maximum (17920), */
258 0x81, 0x02, /* Input (Variable), */
259 0x09, 0x31, /* Usage (Y), */
260 0x46, 0x82, 0x14, /* Physical Maximum (5250), */
261 0x26, 0x00, 0x2A, /* Logical Maximum (10752), */
262 0x81, 0x02, /* Input (Variable), */
264 0x09, 0x30, /* Usage (Tip Pressure), */
265 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
266 0x81, 0x02, /* Input (Variable), */
267 0xC0, /* End Collection, */
268 0xC0 /* End Collection */
272 * See Media Tablet 10.6 inch description, device and HID report descriptors at
273 * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Media_Tablet_10.6%22
276 /* Size of the original report descriptor of Media Tablet 10.6 inch */
277 #define MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE 300
279 /* Fixed Media Tablet 10.6 inch descriptor */
280 static __u8 media_tablet_10_6_inch_rdesc_fixed
[] = {
281 0x05, 0x0D, /* Usage Page (Digitizer), */
282 0x09, 0x02, /* Usage (Pen), */
283 0xA1, 0x01, /* Collection (Application), */
284 0x85, 0x10, /* Report ID (16), */
285 0x09, 0x20, /* Usage (Stylus), */
286 0xA0, /* Collection (Physical), */
287 0x09, 0x42, /* Usage (Tip Switch), */
288 0x09, 0x44, /* Usage (Barrel Switch), */
289 0x09, 0x46, /* Usage (Tablet Pick), */
290 0x15, 0x01, /* Logical Minimum (1), */
291 0x25, 0x03, /* Logical Maximum (3), */
292 0x75, 0x04, /* Report Size (4), */
293 0x95, 0x01, /* Report Count (1), */
295 0x75, 0x01, /* Report Size (1), */
296 0x09, 0x32, /* Usage (In Range), */
297 0x14, /* Logical Minimum (0), */
298 0x25, 0x01, /* Logical Maximum (1), */
299 0x95, 0x01, /* Report Count (1), */
300 0x81, 0x02, /* Input (Variable), */
301 0x95, 0x03, /* Report Count (3), */
302 0x81, 0x03, /* Input (Constant, Variable), */
303 0x75, 0x10, /* Report Size (16), */
304 0x95, 0x01, /* Report Count (1), */
305 0x14, /* Logical Minimum (0), */
307 0x05, 0x01, /* Usage Page (Desktop), */
308 0x65, 0x13, /* Unit (Inch), */
309 0x55, 0xFD, /* Unit Exponent (-3), */
310 0x34, /* Physical Minimum (0), */
311 0x09, 0x30, /* Usage (X), */
312 0x46, 0x28, 0x23, /* Physical Maximum (9000), */
313 0x26, 0x50, 0x46, /* Logical Maximum (18000), */
314 0x81, 0x02, /* Input (Variable), */
315 0x09, 0x31, /* Usage (Y), */
316 0x46, 0x7C, 0x15, /* Physical Maximum (5500), */
317 0x26, 0xF8, 0x2A, /* Logical Maximum (11000), */
318 0x81, 0x02, /* Input (Variable), */
320 0x09, 0x30, /* Usage (Tip Pressure), */
321 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
322 0x81, 0x02, /* Input (Variable), */
323 0xC0, /* End Collection, */
324 0xC0, /* End Collection, */
325 0x05, 0x01, /* Usage Page (Desktop), */
326 0x09, 0x02, /* Usage (Mouse), */
327 0xA1, 0x01, /* Collection (Application), */
328 0x85, 0x01, /* Report ID (1), */
329 0x09, 0x01, /* Usage (Pointer), */
330 0xA0, /* Collection (Physical), */
331 0x75, 0x08, /* Report Size (8), */
332 0x95, 0x03, /* Report Count (3), */
333 0x81, 0x03, /* Input (Constant, Variable), */
334 0x95, 0x02, /* Report Count (2), */
335 0x15, 0xFF, /* Logical Minimum (-1), */
336 0x25, 0x01, /* Logical Maximum (1), */
337 0x09, 0x38, /* Usage (Wheel), */
338 0x0B, 0x38, 0x02, /* Usage (Consumer AC Pan), */
340 0x81, 0x06, /* Input (Variable, Relative), */
341 0x95, 0x02, /* Report Count (2), */
342 0x81, 0x03, /* Input (Constant, Variable), */
343 0xC0, /* End Collection, */
344 0xC0, /* End Collection, */
345 0x05, 0x0C, /* Usage Page (Consumer), */
346 0x09, 0x01, /* Usage (Consumer Control), */
347 0xA1, 0x01, /* Collection (Application), */
348 0x85, 0x0D, /* Report ID (13), */
349 0x95, 0x01, /* Report Count (1), */
350 0x75, 0x10, /* Report Size (16), */
351 0x81, 0x03, /* Input (Constant, Variable), */
352 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */
353 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */
354 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */
355 0x09, 0xB6, /* Usage (Scan Previous Track), */
356 0x09, 0xB5, /* Usage (Scan Next Track), */
357 0x08, /* Usage (00h), */
358 0x08, /* Usage (00h), */
359 0x08, /* Usage (00h), */
360 0x08, /* Usage (00h), */
361 0x08, /* Usage (00h), */
362 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */
363 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */
364 0x15, 0x0C, /* Logical Minimum (12), */
365 0x25, 0x17, /* Logical Maximum (23), */
366 0x75, 0x05, /* Report Size (5), */
368 0x75, 0x03, /* Report Size (3), */
369 0x81, 0x03, /* Input (Constant, Variable), */
370 0x75, 0x20, /* Report Size (32), */
371 0x81, 0x03, /* Input (Constant, Variable), */
372 0xC0, /* End Collection, */
373 0x09, 0x01, /* Usage (Consumer Control), */
374 0xA1, 0x01, /* Collection (Application), */
375 0x85, 0x0C, /* Report ID (12), */
376 0x75, 0x01, /* Report Size (1), */
377 0x09, 0xE9, /* Usage (Volume Inc), */
378 0x09, 0xEA, /* Usage (Volume Dec), */
379 0x09, 0xE2, /* Usage (Mute), */
380 0x14, /* Logical Minimum (0), */
381 0x25, 0x01, /* Logical Maximum (1), */
382 0x95, 0x03, /* Report Count (3), */
383 0x81, 0x06, /* Input (Variable, Relative), */
384 0x95, 0x35, /* Report Count (53), */
385 0x81, 0x03, /* Input (Constant, Variable), */
386 0xC0 /* End Collection */
390 * See Media Tablet 14.1 inch description, device and HID report descriptors at
391 * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Media_Tablet_14.1%22
394 /* Size of the original report descriptor of Media Tablet 14.1 inch */
395 #define MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE 309
397 /* Fixed Media Tablet 14.1 inch descriptor */
398 static __u8 media_tablet_14_1_inch_rdesc_fixed
[] = {
399 0x05, 0x0D, /* Usage Page (Digitizer), */
400 0x09, 0x02, /* Usage (Pen), */
401 0xA1, 0x01, /* Collection (Application), */
402 0x85, 0x10, /* Report ID (16), */
403 0x09, 0x20, /* Usage (Stylus), */
404 0xA0, /* Collection (Physical), */
405 0x09, 0x42, /* Usage (Tip Switch), */
406 0x09, 0x44, /* Usage (Barrel Switch), */
407 0x09, 0x46, /* Usage (Tablet Pick), */
408 0x15, 0x01, /* Logical Minimum (1), */
409 0x25, 0x03, /* Logical Maximum (3), */
410 0x75, 0x04, /* Report Size (4), */
411 0x95, 0x01, /* Report Count (1), */
413 0x75, 0x01, /* Report Size (1), */
414 0x09, 0x32, /* Usage (In Range), */
415 0x14, /* Logical Minimum (0), */
416 0x25, 0x01, /* Logical Maximum (1), */
417 0x95, 0x01, /* Report Count (1), */
418 0x81, 0x02, /* Input (Variable), */
419 0x95, 0x03, /* Report Count (3), */
420 0x81, 0x03, /* Input (Constant, Variable), */
421 0x75, 0x10, /* Report Size (16), */
422 0x95, 0x01, /* Report Count (1), */
423 0x14, /* Logical Minimum (0), */
425 0x05, 0x01, /* Usage Page (Desktop), */
426 0x65, 0x13, /* Unit (Inch), */
427 0x55, 0xFD, /* Unit Exponent (-3), */
428 0x34, /* Physical Minimum (0), */
429 0x09, 0x30, /* Usage (X), */
430 0x46, 0xE0, 0x2E, /* Physical Maximum (12000), */
431 0x26, 0xFF, 0x3F, /* Logical Maximum (16383), */
432 0x81, 0x02, /* Input (Variable), */
433 0x09, 0x31, /* Usage (Y), */
434 0x46, 0x52, 0x1C, /* Physical Maximum (7250), */
435 0x26, 0xFF, 0x3F, /* Logical Maximum (16383), */
436 0x81, 0x02, /* Input (Variable), */
438 0x09, 0x30, /* Usage (Tip Pressure), */
439 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
440 0x81, 0x02, /* Input (Variable), */
441 0xC0, /* End Collection, */
442 0xC0, /* End Collection, */
443 0x05, 0x01, /* Usage Page (Desktop), */
444 0x09, 0x02, /* Usage (Mouse), */
445 0xA1, 0x01, /* Collection (Application), */
446 0x85, 0x01, /* Report ID (1), */
447 0x09, 0x01, /* Usage (Pointer), */
448 0xA0, /* Collection (Physical), */
449 0x75, 0x08, /* Report Size (8), */
450 0x95, 0x03, /* Report Count (3), */
451 0x81, 0x03, /* Input (Constant, Variable), */
452 0x95, 0x02, /* Report Count (2), */
453 0x15, 0xFF, /* Logical Minimum (-1), */
454 0x25, 0x01, /* Logical Maximum (1), */
455 0x09, 0x38, /* Usage (Wheel), */
456 0x0B, 0x38, 0x02, /* Usage (Consumer AC Pan), */
458 0x81, 0x06, /* Input (Variable, Relative), */
459 0xC0, /* End Collection, */
460 0xC0, /* End Collection, */
461 0x05, 0x0C, /* Usage Page (Consumer), */
462 0x09, 0x01, /* Usage (Consumer Control), */
463 0xA1, 0x01, /* Collection (Application), */
464 0x85, 0x0D, /* Report ID (13), */
465 0x95, 0x01, /* Report Count (1), */
466 0x75, 0x10, /* Report Size (16), */
467 0x81, 0x03, /* Input (Constant, Variable), */
468 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */
469 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */
470 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */
471 0x09, 0xB6, /* Usage (Scan Previous Track), */
472 0x09, 0xB5, /* Usage (Scan Next Track), */
473 0x08, /* Usage (00h), */
474 0x08, /* Usage (00h), */
475 0x08, /* Usage (00h), */
476 0x08, /* Usage (00h), */
477 0x08, /* Usage (00h), */
478 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */
479 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */
480 0x15, 0x0C, /* Logical Minimum (12), */
481 0x25, 0x17, /* Logical Maximum (23), */
482 0x75, 0x05, /* Report Size (5), */
484 0x75, 0x03, /* Report Size (3), */
485 0x81, 0x03, /* Input (Constant, Variable), */
486 0x75, 0x20, /* Report Size (32), */
487 0x81, 0x03, /* Input (Constant, Variable), */
488 0xC0, /* End Collection, */
489 0x09, 0x01, /* Usage (Consumer Control), */
490 0xA1, 0x01, /* Collection (Application), */
491 0x85, 0x0C, /* Report ID (12), */
492 0x75, 0x01, /* Report Size (1), */
493 0x09, 0xE9, /* Usage (Volume Inc), */
494 0x09, 0xEA, /* Usage (Volume Dec), */
495 0x09, 0xE2, /* Usage (Mute), */
496 0x14, /* Logical Minimum (0), */
497 0x25, 0x01, /* Logical Maximum (1), */
498 0x95, 0x03, /* Report Count (3), */
499 0x81, 0x06, /* Input (Variable, Relative), */
500 0x75, 0x05, /* Report Size (5), */
501 0x81, 0x03, /* Input (Constant, Variable), */
502 0xC0 /* End Collection */
506 * See Sirius Battery Free Tablet description, device and HID report descriptors
508 * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Sirius_Battery_Free_Tablet
511 /* Size of the original report descriptor of Sirius Battery Free Tablet */
512 #define SIRIUS_BATTERY_FREE_TABLET_RDESC_ORIG_SIZE 335
514 /* Fixed Sirius Battery Free Tablet descriptor */
515 static __u8 sirius_battery_free_tablet_rdesc_fixed
[] = {
516 0x05, 0x0D, /* Usage Page (Digitizer), */
517 0x09, 0x02, /* Usage (Pen), */
518 0xA1, 0x01, /* Collection (Application), */
519 0x85, 0x10, /* Report ID (16), */
520 0x09, 0x20, /* Usage (Stylus), */
521 0xA0, /* Collection (Physical), */
522 0x95, 0x01, /* Report Count (1), */
523 0x15, 0x01, /* Logical Minimum (1), */
524 0x25, 0x03, /* Logical Maximum (3), */
525 0x75, 0x02, /* Report Size (2), */
526 0x09, 0x42, /* Usage (Tip Switch), */
527 0x09, 0x44, /* Usage (Barrel Switch), */
528 0x09, 0x46, /* Usage (Tablet Pick), */
530 0x14, /* Logical Minimum (0), */
531 0x25, 0x01, /* Logical Maximum (1), */
532 0x75, 0x01, /* Report Size (1), */
533 0x09, 0x3C, /* Usage (Invert), */
534 0x81, 0x02, /* Input (Variable), */
535 0x81, 0x03, /* Input (Constant, Variable), */
536 0x09, 0x32, /* Usage (In Range), */
537 0x81, 0x02, /* Input (Variable), */
538 0x95, 0x03, /* Report Count (3), */
539 0x81, 0x03, /* Input (Constant, Variable), */
541 0x05, 0x01, /* Usage Page (Desktop), */
542 0x55, 0xFD, /* Unit Exponent (-3), */
543 0x65, 0x13, /* Unit (Inch), */
544 0x34, /* Physical Minimum (0), */
545 0x14, /* Logical Minimum (0), */
546 0x75, 0x10, /* Report Size (16), */
547 0x95, 0x01, /* Report Count (1), */
548 0x46, 0x10, 0x27, /* Physical Maximum (10000), */
549 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */
550 0x09, 0x30, /* Usage (X), */
551 0x81, 0x02, /* Input (Variable), */
552 0x46, 0x70, 0x17, /* Physical Maximum (6000), */
553 0x26, 0xE0, 0x2E, /* Logical Maximum (12000), */
554 0x09, 0x31, /* Usage (Y), */
555 0x81, 0x02, /* Input (Variable), */
557 0x75, 0x10, /* Report Size (16), */
558 0x95, 0x01, /* Report Count (1), */
559 0x14, /* Logical Minimum (0), */
560 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
561 0x09, 0x30, /* Usage (Tip Pressure), */
562 0x81, 0x02, /* Input (Variable), */
564 0x55, 0xFE, /* Unit Exponent (-2), */
565 0x65, 0x12, /* Unit (Radians), */
566 0x35, 0x97, /* Physical Minimum (-105), */
567 0x45, 0x69, /* Physical Maximum (105), */
568 0x15, 0x97, /* Logical Minimum (-105), */
569 0x25, 0x69, /* Logical Maximum (105), */
570 0x75, 0x08, /* Report Size (8), */
571 0x95, 0x02, /* Report Count (2), */
572 0x09, 0x3D, /* Usage (X Tilt), */
573 0x09, 0x3E, /* Usage (Y Tilt), */
574 0x81, 0x02, /* Input (Variable), */
576 0xC0, /* End Collection, */
577 0xC0, /* End Collection, */
578 0x05, 0x01, /* Usage Page (Desktop), */
579 0x09, 0x02, /* Usage (Mouse), */
580 0xA1, 0x01, /* Collection (Application), */
581 0x85, 0x01, /* Report ID (1), */
582 0x09, 0x01, /* Usage (Pointer), */
583 0xA0, /* Collection (Physical), */
584 0x75, 0x08, /* Report Size (8), */
585 0x95, 0x03, /* Report Count (3), */
586 0x81, 0x03, /* Input (Constant, Variable), */
587 0x09, 0x38, /* Usage (Wheel), */
588 0x15, 0xFF, /* Logical Minimum (-1), */
589 0x25, 0x01, /* Logical Maximum (1), */
590 0x75, 0x08, /* Report Size (8), */
591 0x95, 0x01, /* Report Count (1), */
592 0x81, 0x06, /* Input (Variable, Relative), */
593 0x75, 0x08, /* Report Size (8), */
594 0x95, 0x03, /* Report Count (3), */
595 0x81, 0x03, /* Input (Constant, Variable), */
596 0xC0, /* End Collection, */
597 0xC0, /* End Collection, */
598 0x05, 0x01, /* Usage Page (Desktop), */
599 0x09, 0x06, /* Usage (Keyboard), */
600 0xA1, 0x01, /* Collection (Application), */
601 0x85, 0x0D, /* Report ID (13), */
602 0x05, 0x07, /* Usage Page (Keyboard), */
603 0x19, 0xE0, /* Usage Minimum (KB Leftcontrol), */
604 0x29, 0xE7, /* Usage Maximum (KB Right GUI), */
605 0x14, /* Logical Minimum (0), */
606 0x25, 0x01, /* Logical Maximum (1), */
607 0x75, 0x01, /* Report Size (1), */
608 0x95, 0x08, /* Report Count (8), */
609 0x81, 0x02, /* Input (Variable), */
610 0x75, 0x08, /* Report Size (8), */
611 0x95, 0x01, /* Report Count (1), */
612 0x81, 0x01, /* Input (Constant), */
613 0x18, /* Usage Minimum (None), */
614 0x29, 0x65, /* Usage Maximum (KB Application), */
615 0x14, /* Logical Minimum (0), */
616 0x25, 0x65, /* Logical Maximum (101), */
617 0x75, 0x08, /* Report Size (8), */
618 0x95, 0x05, /* Report Count (5), */
620 0xC0, /* End Collection, */
621 0x05, 0x0C, /* Usage Page (Consumer), */
622 0x09, 0x01, /* Usage (Consumer Control), */
623 0xA1, 0x01, /* Collection (Application), */
624 0x85, 0x0C, /* Report ID (12), */
625 0x09, 0xE9, /* Usage (Volume Inc), */
626 0x09, 0xEA, /* Usage (Volume Dec), */
627 0x14, /* Logical Minimum (0), */
628 0x25, 0x01, /* Logical Maximum (1), */
629 0x75, 0x01, /* Report Size (1), */
630 0x95, 0x02, /* Report Count (2), */
631 0x81, 0x02, /* Input (Variable), */
632 0x75, 0x06, /* Report Size (6), */
633 0x95, 0x01, /* Report Count (1), */
634 0x81, 0x03, /* Input (Constant, Variable), */
635 0x75, 0x10, /* Report Size (16), */
636 0x95, 0x03, /* Report Count (3), */
637 0x81, 0x03, /* Input (Constant, Variable), */
638 0xC0 /* End Collection */
641 static __u8
*waltop_report_fixup(struct hid_device
*hdev
, __u8
*rdesc
,
644 switch (hdev
->product
) {
645 case USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH
:
646 if (*rsize
== SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE
) {
647 rdesc
= slim_tablet_5_8_inch_rdesc_fixed
;
648 *rsize
= sizeof(slim_tablet_5_8_inch_rdesc_fixed
);
651 case USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH
:
652 if (*rsize
== SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE
) {
653 rdesc
= slim_tablet_12_1_inch_rdesc_fixed
;
654 *rsize
= sizeof(slim_tablet_12_1_inch_rdesc_fixed
);
657 case USB_DEVICE_ID_WALTOP_Q_PAD
:
658 if (*rsize
== Q_PAD_RDESC_ORIG_SIZE
) {
659 rdesc
= q_pad_rdesc_fixed
;
660 *rsize
= sizeof(q_pad_rdesc_fixed
);
663 case USB_DEVICE_ID_WALTOP_PID_0038
:
664 if (*rsize
== PID_0038_RDESC_ORIG_SIZE
) {
665 rdesc
= pid_0038_rdesc_fixed
;
666 *rsize
= sizeof(pid_0038_rdesc_fixed
);
669 case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH
:
670 if (*rsize
== MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE
) {
671 rdesc
= media_tablet_10_6_inch_rdesc_fixed
;
672 *rsize
= sizeof(media_tablet_10_6_inch_rdesc_fixed
);
675 case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH
:
676 if (*rsize
== MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE
) {
677 rdesc
= media_tablet_14_1_inch_rdesc_fixed
;
678 *rsize
= sizeof(media_tablet_14_1_inch_rdesc_fixed
);
681 case USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET
:
682 if (*rsize
== SIRIUS_BATTERY_FREE_TABLET_RDESC_ORIG_SIZE
) {
683 rdesc
= sirius_battery_free_tablet_rdesc_fixed
;
684 *rsize
= sizeof(sirius_battery_free_tablet_rdesc_fixed
);
691 static int waltop_raw_event(struct hid_device
*hdev
, struct hid_report
*report
,
694 /* If this is a pen input report */
695 if (report
->type
== HID_INPUT_REPORT
&& report
->id
== 16 && size
>= 8) {
697 * Ignore reported pressure when a barrel button is pressed,
698 * because it is rarely correct.
701 /* If a barrel button is pressed */
702 if ((data
[1] & 0xF) > 1) {
703 /* Report zero pressure */
709 /* If this is a pen input report of Sirius Battery Free Tablet */
710 if (hdev
->product
== USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET
&&
711 report
->type
== HID_INPUT_REPORT
&&
715 * The tablet reports tilt as roughly sin(a)*21 (18 means 60
718 * This array stores angles as radians * 100, corresponding to
719 * reported values up to 60 degrees, as expected by userspace.
721 static const s8 tilt_to_radians
[] = {
722 0, 5, 10, 14, 19, 24, 29, 34, 40, 45,
723 50, 56, 62, 68, 74, 81, 88, 96, 105
726 s8 tilt_x
= (s8
)data
[8];
727 s8 tilt_y
= (s8
)data
[9];
728 s8 sign_x
= tilt_x
>= 0 ? 1 : -1;
729 s8 sign_y
= tilt_y
>= 0 ? 1 : -1;
735 * Reverse the Y Tilt direction to match the HID standard and
736 * userspace expectations. See HID Usage Tables v1.12 16.3.2
742 * This effectively clamps reported tilt to 60 degrees - the
743 * range expected by userspace
745 if (tilt_x
> ARRAY_SIZE(tilt_to_radians
) - 1)
746 tilt_x
= ARRAY_SIZE(tilt_to_radians
) - 1;
747 if (tilt_y
> ARRAY_SIZE(tilt_to_radians
) - 1)
748 tilt_y
= ARRAY_SIZE(tilt_to_radians
) - 1;
750 data
[8] = tilt_to_radians
[tilt_x
] * sign_x
;
751 data
[9] = tilt_to_radians
[tilt_y
] * sign_y
;
757 static const struct hid_device_id waltop_devices
[] = {
758 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP
,
759 USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH
) },
760 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP
,
761 USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH
) },
762 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP
,
763 USB_DEVICE_ID_WALTOP_Q_PAD
) },
764 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP
,
765 USB_DEVICE_ID_WALTOP_PID_0038
) },
766 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP
,
767 USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH
) },
768 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP
,
769 USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH
) },
770 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP
,
771 USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET
) },
774 MODULE_DEVICE_TABLE(hid
, waltop_devices
);
776 static struct hid_driver waltop_driver
= {
778 .id_table
= waltop_devices
,
779 .report_fixup
= waltop_report_fixup
,
780 .raw_event
= waltop_raw_event
,
782 module_hid_driver(waltop_driver
);
784 MODULE_LICENSE("GPL");