Commit | Line | Data |
---|---|---|
72a46344 NK |
1 | /* |
2 | * HID driver for Waltop devices not fully compliant with HID standard | |
3 | * | |
4 | * Copyright (c) 2010 Nikolai Kondrashov | |
5 | */ | |
6 | ||
7 | /* | |
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) | |
11 | * any later version. | |
12 | */ | |
13 | ||
14 | #include <linux/device.h> | |
15 | #include <linux/hid.h> | |
16 | #include <linux/module.h> | |
17 | ||
18 | #include "hid-ids.h" | |
19 | ||
cdd49a85 NK |
20 | /* |
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. | |
24 | * | |
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". | |
27 | * | |
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. | |
31 | * | |
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). | |
35 | * | |
36 | * The purpose of the "ink" mode is unknown. | |
37 | * | |
38 | * The feature reports needed for switching to each mode are these: | |
39 | * | |
40 | * 02 16 00 default | |
41 | * 02 16 01 tablet | |
42 | * 02 16 02 ink | |
43 | */ | |
44 | ||
72a46344 | 45 | /* |
56d27dd6 NK |
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 | |
72a46344 NK |
48 | */ |
49 | ||
50 | /* Size of the original report descriptor of Slim Tablet 5.8 inch */ | |
51 | #define SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE 222 | |
52 | ||
56d27dd6 | 53 | /* Fixed Slim Tablet 5.8 inch descriptor */ |
72a46344 NK |
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), */ | |
68 | 0x80, /* Input, */ | |
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), */ | |
80 | 0xA4, /* Push, */ | |
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), */ | |
93 | 0xB4, /* Pop, */ | |
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 */ | |
99 | }; | |
100 | ||
00e7f964 | 101 | /* |
56d27dd6 NK |
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 | |
00e7f964 NK |
104 | */ |
105 | ||
106 | /* Size of the original report descriptor of Slim Tablet 12.1 inch */ | |
107 | #define SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE 269 | |
108 | ||
56d27dd6 | 109 | /* Fixed Slim Tablet 12.1 inch descriptor */ |
00e7f964 NK |
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), */ | |
124 | 0x80, /* Input, */ | |
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), */ | |
136 | 0xA4, /* Push, */ | |
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), */ | |
149 | 0xB4, /* Pop, */ | |
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 */ | |
155 | }; | |
156 | ||
4fdc18d1 | 157 | /* |
56d27dd6 NK |
158 | * See Q Pad description, device and HID report descriptors at |
159 | * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Q_Pad | |
4fdc18d1 NK |
160 | */ |
161 | ||
162 | /* Size of the original report descriptor of Q Pad */ | |
163 | #define Q_PAD_RDESC_ORIG_SIZE 241 | |
164 | ||
56d27dd6 | 165 | /* Fixed Q Pad descriptor */ |
4fdc18d1 NK |
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), */ | |
180 | 0x80, /* Input, */ | |
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), */ | |
192 | 0xA4, /* Push, */ | |
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), */ | |
205 | 0xB4, /* Pop, */ | |
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 */ | |
211 | }; | |
212 | ||
a786e83c NK |
213 | /* |
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 | |
216 | */ | |
217 | ||
218 | /* Size of the original report descriptor of tablet with PID 0038 */ | |
219 | #define PID_0038_RDESC_ORIG_SIZE 241 | |
220 | ||
221 | /* | |
222 | * Fixed report descriptor for tablet with PID 0038. | |
223 | */ | |
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), */ | |
238 | 0x80, /* Input, */ | |
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), */ | |
250 | 0xA4, /* Push, */ | |
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), */ | |
263 | 0xB4, /* Pop, */ | |
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 */ | |
269 | }; | |
270 | ||
72a46344 | 271 | /* |
56d27dd6 NK |
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 | |
72a46344 NK |
274 | */ |
275 | ||
276 | /* Size of the original report descriptor of Media Tablet 10.6 inch */ | |
277 | #define MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE 300 | |
278 | ||
56d27dd6 | 279 | /* Fixed Media Tablet 10.6 inch descriptor */ |
72a46344 NK |
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), */ | |
294 | 0x80, /* Input, */ | |
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), */ | |
306 | 0xA4, /* Push, */ | |
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), */ | |
319 | 0xB4, /* Pop, */ | |
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), */ | |
4b5b4575 NK |
331 | 0x75, 0x08, /* Report Size (8), */ |
332 | 0x95, 0x03, /* Report Count (3), */ | |
72a46344 | 333 | 0x81, 0x03, /* Input (Constant, Variable), */ |
4b5b4575 | 334 | 0x95, 0x02, /* Report Count (2), */ |
72a46344 NK |
335 | 0x15, 0xFF, /* Logical Minimum (-1), */ |
336 | 0x25, 0x01, /* Logical Maximum (1), */ | |
4b5b4575 NK |
337 | 0x09, 0x38, /* Usage (Wheel), */ |
338 | 0x0B, 0x38, 0x02, /* Usage (Consumer AC Pan), */ | |
339 | 0x0C, 0x00, | |
72a46344 | 340 | 0x81, 0x06, /* Input (Variable, Relative), */ |
4b5b4575 | 341 | 0x95, 0x02, /* Report Count (2), */ |
72a46344 NK |
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), */ | |
30311549 NK |
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), */ | |
72a46344 | 367 | 0x80, /* Input, */ |
30311549 NK |
368 | 0x75, 0x03, /* Report Size (3), */ |
369 | 0x81, 0x03, /* Input (Constant, Variable), */ | |
72a46344 NK |
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 */ | |
387 | }; | |
388 | ||
8f1acc32 | 389 | /* |
56d27dd6 NK |
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 | |
8f1acc32 NK |
392 | */ |
393 | ||
394 | /* Size of the original report descriptor of Media Tablet 14.1 inch */ | |
395 | #define MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE 309 | |
396 | ||
56d27dd6 | 397 | /* Fixed Media Tablet 14.1 inch descriptor */ |
8f1acc32 NK |
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), */ | |
412 | 0x80, /* Input, */ | |
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), */ | |
424 | 0xA4, /* Push, */ | |
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), */ | |
437 | 0xB4, /* Pop, */ | |
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), */ | |
457 | 0x0C, 0x00, | |
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), */ | |
483 | 0x80, /* Input, */ | |
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 */ | |
503 | }; | |
504 | ||
a786e83c NK |
505 | struct waltop_state { |
506 | u8 pressure0; | |
507 | u8 pressure1; | |
508 | }; | |
509 | ||
510 | static int waltop_probe(struct hid_device *hdev, | |
511 | const struct hid_device_id *id) | |
512 | { | |
513 | int ret; | |
514 | struct waltop_state *s; | |
515 | ||
516 | s = kzalloc(sizeof(*s), GFP_KERNEL); | |
517 | if (s == NULL) { | |
518 | hid_err(hdev, "can't allocate device state\n"); | |
519 | ret = -ENOMEM; | |
520 | goto err; | |
521 | } | |
522 | ||
523 | s->pressure0 = 0; | |
524 | s->pressure1 = 0; | |
525 | ||
526 | hid_set_drvdata(hdev, s); | |
527 | ||
528 | ret = hid_parse(hdev); | |
529 | if (ret) { | |
530 | hid_err(hdev, "parse failed\n"); | |
531 | goto err; | |
532 | } | |
533 | ||
534 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | |
535 | if (ret) { | |
536 | hid_err(hdev, "hw start failed\n"); | |
537 | goto err; | |
538 | } | |
539 | ||
540 | return 0; | |
541 | err: | |
542 | kfree(s); | |
543 | return ret; | |
544 | } | |
545 | ||
72a46344 NK |
546 | static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
547 | unsigned int *rsize) | |
548 | { | |
549 | switch (hdev->product) { | |
550 | case USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH: | |
551 | if (*rsize == SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE) { | |
552 | rdesc = slim_tablet_5_8_inch_rdesc_fixed; | |
553 | *rsize = sizeof(slim_tablet_5_8_inch_rdesc_fixed); | |
554 | } | |
555 | break; | |
00e7f964 NK |
556 | case USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH: |
557 | if (*rsize == SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE) { | |
558 | rdesc = slim_tablet_12_1_inch_rdesc_fixed; | |
559 | *rsize = sizeof(slim_tablet_12_1_inch_rdesc_fixed); | |
560 | } | |
561 | break; | |
4fdc18d1 NK |
562 | case USB_DEVICE_ID_WALTOP_Q_PAD: |
563 | if (*rsize == Q_PAD_RDESC_ORIG_SIZE) { | |
564 | rdesc = q_pad_rdesc_fixed; | |
565 | *rsize = sizeof(q_pad_rdesc_fixed); | |
566 | } | |
567 | break; | |
a786e83c NK |
568 | case USB_DEVICE_ID_WALTOP_PID_0038: |
569 | if (*rsize == PID_0038_RDESC_ORIG_SIZE) { | |
570 | rdesc = pid_0038_rdesc_fixed; | |
571 | *rsize = sizeof(pid_0038_rdesc_fixed); | |
572 | } | |
573 | break; | |
72a46344 NK |
574 | case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH: |
575 | if (*rsize == MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE) { | |
576 | rdesc = media_tablet_10_6_inch_rdesc_fixed; | |
577 | *rsize = sizeof(media_tablet_10_6_inch_rdesc_fixed); | |
578 | } | |
579 | break; | |
8f1acc32 NK |
580 | case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH: |
581 | if (*rsize == MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE) { | |
582 | rdesc = media_tablet_14_1_inch_rdesc_fixed; | |
583 | *rsize = sizeof(media_tablet_14_1_inch_rdesc_fixed); | |
584 | } | |
585 | break; | |
72a46344 NK |
586 | } |
587 | return rdesc; | |
588 | } | |
589 | ||
a786e83c NK |
590 | static int waltop_raw_event(struct hid_device *hdev, struct hid_report *report, |
591 | u8 *data, int size) | |
592 | { | |
593 | /* If this is a pen input report of a tablet with PID 0038 */ | |
594 | if (hdev->product == USB_DEVICE_ID_WALTOP_PID_0038 && | |
595 | report->type == HID_INPUT_REPORT && | |
596 | report->id == 16 && | |
597 | size == 8) { | |
598 | struct waltop_state *s = hid_get_drvdata(hdev); | |
599 | ||
600 | /* | |
601 | * Ignore maximum pressure reported when a barrel button is | |
602 | * pressed. | |
603 | */ | |
604 | ||
605 | /* If a barrel button is pressed */ | |
606 | if ((data[1] & 0xF) > 1) { | |
607 | /* Use the last known pressure */ | |
608 | data[6] = s->pressure0; | |
609 | data[7] = s->pressure1; | |
610 | } else { | |
611 | /* Remember reported pressure */ | |
612 | s->pressure0 = data[6]; | |
613 | s->pressure1 = data[7]; | |
614 | } | |
615 | } | |
616 | ||
617 | return 0; | |
618 | } | |
619 | ||
620 | static void waltop_remove(struct hid_device *hdev) | |
621 | { | |
622 | struct waltop_state *s = hid_get_drvdata(hdev); | |
623 | ||
624 | hid_hw_stop(hdev); | |
625 | kfree(s); | |
626 | } | |
627 | ||
72a46344 NK |
628 | static const struct hid_device_id waltop_devices[] = { |
629 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, | |
630 | USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, | |
00e7f964 NK |
631 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, |
632 | USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, | |
4fdc18d1 NK |
633 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, |
634 | USB_DEVICE_ID_WALTOP_Q_PAD) }, | |
a786e83c NK |
635 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, |
636 | USB_DEVICE_ID_WALTOP_PID_0038) }, | |
72a46344 NK |
637 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, |
638 | USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, | |
8f1acc32 NK |
639 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, |
640 | USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, | |
72a46344 NK |
641 | { } |
642 | }; | |
643 | MODULE_DEVICE_TABLE(hid, waltop_devices); | |
644 | ||
645 | static struct hid_driver waltop_driver = { | |
646 | .name = "waltop", | |
647 | .id_table = waltop_devices, | |
a786e83c | 648 | .probe = waltop_probe, |
72a46344 | 649 | .report_fixup = waltop_report_fixup, |
a786e83c NK |
650 | .raw_event = waltop_raw_event, |
651 | .remove = waltop_remove, | |
72a46344 NK |
652 | }; |
653 | ||
654 | static int __init waltop_init(void) | |
655 | { | |
656 | return hid_register_driver(&waltop_driver); | |
657 | } | |
658 | ||
659 | static void __exit waltop_exit(void) | |
660 | { | |
661 | hid_unregister_driver(&waltop_driver); | |
662 | } | |
663 | ||
664 | module_init(waltop_init); | |
665 | module_exit(waltop_exit); | |
666 | MODULE_LICENSE("GPL"); |