aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-uclogic.c
diff options
context:
space:
mode:
authorNikolai Kondrashov <spbnick@gmail.com>2010-08-09 12:44:17 -0400
committerJiri Kosina <jkosina@suse.cz>2010-08-09 13:52:43 -0400
commitf8a489cc5f7adafa9f1420279be793de0fba481c (patch)
treed131e5c50460bedaa2a464818892ebebcd106720 /drivers/hid/hid-uclogic.c
parent50b6369767f65c39de3d7ca17842ebc6c52888b8 (diff)
HID: Add support for UC-Logic WP????U tablets
Add support for UC-Logic WP4030U, WP5540U and WP8060U tablets. These tablets are usually sold by Genius, Trust and possibly others under different names and in different cases, but with the original USB vendor/product IDs. Currently, these tablets are supported by standalone X.org driver WizardPen. This patch aims to fix them in the kernel and make them supported by the generic evdev X.org driver. Still, some minor fixes in the X.org driver are to be made for the full stack support. Signed-off-by: Nikolai Kondrashov <spbnick@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-uclogic.c')
-rw-r--r--drivers/hid/hid-uclogic.c404
1 files changed, 404 insertions, 0 deletions
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c
new file mode 100644
index 000000000000..107aa9fb07f2
--- /dev/null
+++ b/drivers/hid/hid-uclogic.c
@@ -0,0 +1,404 @@
1/*
2 * HID driver for UC-Logic 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
20/*
21 * The original descriptors of WPXXXXU tablets have three report IDs, of
22 * which only two are used (8 and 9), and the remaining (7) seems to have
23 * the originally intended pen description which was abandoned for some
24 * reason. From this unused description it is possible to extract the
25 * actual physical extents and resolution. All the models use the same
26 * descriptor with different extents for the unused report ID.
27 *
28 * Here it is:
29 *
30 * Usage Page (Digitizer), ; Digitizer (0Dh)
31 * Usage (Pen), ; Pen (02h, application collection)
32 * Collection (Application),
33 * Report ID (7),
34 * Usage (Stylus), ; Stylus (20h, logical collection)
35 * Collection (Physical),
36 * Usage (Tip Switch), ; Tip switch (42h, momentary control)
37 * Usage (Barrel Switch), ; Barrel switch (44h, momentary control)
38 * Usage (Eraser), ; Eraser (45h, momentary control)
39 * Logical Minimum (0),
40 * Logical Maximum (1),
41 * Report Size (1),
42 * Report Count (3),
43 * Input (Variable),
44 * Report Count (3),
45 * Input (Constant, Variable),
46 * Usage (In Range), ; In range (32h, momentary control)
47 * Report Count (1),
48 * Input (Variable),
49 * Report Count (1),
50 * Input (Constant, Variable),
51 * Usage Page (Desktop), ; Generic desktop controls (01h)
52 * Usage (X), ; X (30h, dynamic value)
53 * Report Size (16),
54 * Report Count (1),
55 * Push,
56 * Unit Exponent (13),
57 * Unit (Inch^3),
58 * Physical Minimum (0),
59 * Physical Maximum (Xpm),
60 * Logical Maximum (Xlm),
61 * Input (Variable),
62 * Usage (Y), ; Y (31h, dynamic value)
63 * Physical Maximum (Ypm),
64 * Logical Maximum (Ylm),
65 * Input (Variable),
66 * Pop,
67 * Usage Page (Digitizer), ; Digitizer (0Dh)
68 * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value)
69 * Logical Maximum (1023),
70 * Input (Variable),
71 * Report Size (16),
72 * End Collection,
73 * End Collection,
74 * Usage Page (Desktop), ; Generic desktop controls (01h)
75 * Usage (Mouse), ; Mouse (02h, application collection)
76 * Collection (Application),
77 * Report ID (8),
78 * Usage (Pointer), ; Pointer (01h, physical collection)
79 * Collection (Physical),
80 * Usage Page (Button), ; Button (09h)
81 * Usage Minimum (01h),
82 * Usage Maximum (03h),
83 * Logical Minimum (0),
84 * Logical Maximum (1),
85 * Report Count (3),
86 * Report Size (1),
87 * Input (Variable),
88 * Report Count (5),
89 * Input (Constant),
90 * Usage Page (Desktop), ; Generic desktop controls (01h)
91 * Usage (X), ; X (30h, dynamic value)
92 * Usage (Y), ; Y (31h, dynamic value)
93 * Usage (Wheel), ; Wheel (38h, dynamic value)
94 * Usage (00h),
95 * Logical Minimum (-127),
96 * Logical Maximum (127),
97 * Report Size (8),
98 * Report Count (4),
99 * Input (Variable, Relative),
100 * End Collection,
101 * End Collection,
102 * Usage Page (Desktop), ; Generic desktop controls (01h)
103 * Usage (Mouse), ; Mouse (02h, application collection)
104 * Collection (Application),
105 * Report ID (9),
106 * Usage (Pointer), ; Pointer (01h, physical collection)
107 * Collection (Physical),
108 * Usage Page (Button), ; Button (09h)
109 * Usage Minimum (01h),
110 * Usage Maximum (03h),
111 * Logical Minimum (0),
112 * Logical Maximum (1),
113 * Report Count (3),
114 * Report Size (1),
115 * Input (Variable),
116 * Report Count (5),
117 * Input (Constant),
118 * Usage Page (Desktop), ; Generic desktop controls (01h)
119 * Usage (X), ; X (30h, dynamic value)
120 * Usage (Y), ; Y (31h, dynamic value)
121 * Logical Minimum (0),
122 * Logical Maximum (32767),
123 * Physical Minimum (0),
124 * Physical Maximum (32767),
125 * Report Count (2),
126 * Report Size (16),
127 * Input (Variable),
128 * Usage Page (Digitizer), ; Digitizer (0Dh)
129 * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value)
130 * Logical Maximum (1023),
131 * Report Count (1),
132 * Report Size (16),
133 * Input (Variable),
134 * End Collection,
135 * End Collection
136 *
137 * Here are the extents values for the WPXXXXU models:
138 *
139 * Xpm Xlm Ypm Ylm
140 * WP4030U 4000 8000 3000 6000
141 * WP5540U 5500 11000 4000 8000
142 * WP8060U 8000 16000 6000 12000
143 *
144 * This suggests that all of them have 2000 LPI resolution, as advertised.
145 */
146
147/* Size of the original descriptor of WPXXXXU tablets */
148#define WPXXXXU_RDESC_ORIG_SIZE 212
149
150/*
151 * Fixed WP4030U report descriptor.
152 * Although the hardware might actually support it, the mouse description
153 * has been removed, since there seems to be no devices having one and it
154 * wouldn't make much sense because of the working area size.
155 */
156static __u8 wp4030u_rdesc_fixed[] = {
157 0x05, 0x0D, /* Usage Page (Digitizer), */
158 0x09, 0x02, /* Usage (Pen), */
159 0xA1, 0x01, /* Collection (Application), */
160 0x85, 0x09, /* Report ID (9), */
161 0x09, 0x20, /* Usage (Stylus), */
162 0xA0, /* Collection (Physical), */
163 0x75, 0x01, /* Report Size (1), */
164 0x09, 0x42, /* Usage (Tip Switch), */
165 0x09, 0x44, /* Usage (Barrel Switch), */
166 0x09, 0x46, /* Usage (Tablet Pick), */
167 0x14, /* Logical Minimum (0), */
168 0x25, 0x01, /* Logical Maximum (1), */
169 0x95, 0x03, /* Report Count (3), */
170 0x81, 0x02, /* Input (Variable), */
171 0x95, 0x05, /* Report Count (5), */
172 0x81, 0x01, /* Input (Constant), */
173 0x75, 0x10, /* Report Size (16), */
174 0x95, 0x01, /* Report Count (1), */
175 0x14, /* Logical Minimum (0), */
176 0xA4, /* Push, */
177 0x05, 0x01, /* Usage Page (Desktop), */
178 0x55, 0xFD, /* Unit Exponent (-3), */
179 0x65, 0x13, /* Unit (Inch), */
180 0x34, /* Physical Minimum (0), */
181 0x09, 0x30, /* Usage (X), */
182 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */
183 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */
184 0x81, 0x02, /* Input (Variable), */
185 0x09, 0x31, /* Usage (Y), */
186 0x46, 0xB8, 0x0B, /* Physical Maximum (3000), */
187 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */
188 0x81, 0x02, /* Input (Variable), */
189 0xB4, /* Pop, */
190 0x09, 0x30, /* Usage (Tip Pressure), */
191 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
192 0x81, 0x02, /* Input (Variable), */
193 0xC0, /* End Collection, */
194 0xC0 /* End Collection */
195};
196
197/* Fixed WP5540U report descriptor */
198static __u8 wp5540u_rdesc_fixed[] = {
199 0x05, 0x0D, /* Usage Page (Digitizer), */
200 0x09, 0x02, /* Usage (Pen), */
201 0xA1, 0x01, /* Collection (Application), */
202 0x85, 0x09, /* Report ID (9), */
203 0x09, 0x20, /* Usage (Stylus), */
204 0xA0, /* Collection (Physical), */
205 0x75, 0x01, /* Report Size (1), */
206 0x09, 0x42, /* Usage (Tip Switch), */
207 0x09, 0x44, /* Usage (Barrel Switch), */
208 0x09, 0x46, /* Usage (Tablet Pick), */
209 0x14, /* Logical Minimum (0), */
210 0x25, 0x01, /* Logical Maximum (1), */
211 0x95, 0x03, /* Report Count (3), */
212 0x81, 0x02, /* Input (Variable), */
213 0x95, 0x05, /* Report Count (5), */
214 0x81, 0x01, /* Input (Constant), */
215 0x75, 0x10, /* Report Size (16), */
216 0x95, 0x01, /* Report Count (1), */
217 0x14, /* Logical Minimum (0), */
218 0xA4, /* Push, */
219 0x05, 0x01, /* Usage Page (Desktop), */
220 0x55, 0xFD, /* Unit Exponent (-3), */
221 0x65, 0x13, /* Unit (Inch), */
222 0x34, /* Physical Minimum (0), */
223 0x09, 0x30, /* Usage (X), */
224 0x46, 0x7C, 0x15, /* Physical Maximum (5500), */
225 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */
226 0x81, 0x02, /* Input (Variable), */
227 0x09, 0x31, /* Usage (Y), */
228 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */
229 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */
230 0x81, 0x02, /* Input (Variable), */
231 0xB4, /* Pop, */
232 0x09, 0x30, /* Usage (Tip Pressure), */
233 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
234 0x81, 0x02, /* Input (Variable), */
235 0xC0, /* End Collection, */
236 0xC0, /* End Collection, */
237 0x05, 0x01, /* Usage Page (Desktop), */
238 0x09, 0x02, /* Usage (Mouse), */
239 0xA1, 0x01, /* Collection (Application), */
240 0x85, 0x08, /* Report ID (8), */
241 0x09, 0x01, /* Usage (Pointer), */
242 0xA0, /* Collection (Physical), */
243 0x75, 0x01, /* Report Size (1), */
244 0x05, 0x09, /* Usage Page (Button), */
245 0x19, 0x01, /* Usage Minimum (01h), */
246 0x29, 0x03, /* Usage Maximum (03h), */
247 0x14, /* Logical Minimum (0), */
248 0x25, 0x01, /* Logical Maximum (1), */
249 0x95, 0x03, /* Report Count (3), */
250 0x81, 0x02, /* Input (Variable), */
251 0x95, 0x05, /* Report Count (5), */
252 0x81, 0x01, /* Input (Constant), */
253 0x05, 0x01, /* Usage Page (Desktop), */
254 0x75, 0x08, /* Report Size (8), */
255 0x09, 0x30, /* Usage (X), */
256 0x09, 0x31, /* Usage (Y), */
257 0x15, 0x81, /* Logical Minimum (-127), */
258 0x25, 0x7F, /* Logical Maximum (127), */
259 0x95, 0x02, /* Report Count (2), */
260 0x81, 0x06, /* Input (Variable, Relative), */
261 0x09, 0x38, /* Usage (Wheel), */
262 0x15, 0xFF, /* Logical Minimum (-1), */
263 0x25, 0x01, /* Logical Maximum (1), */
264 0x95, 0x01, /* Report Count (1), */
265 0x81, 0x06, /* Input (Variable, Relative), */
266 0x81, 0x01, /* Input (Constant), */
267 0xC0, /* End Collection, */
268 0xC0 /* End Collection */
269};
270
271/* Fixed WP8060U report descriptor */
272static __u8 wp8060u_rdesc_fixed[] = {
273 0x05, 0x0D, /* Usage Page (Digitizer), */
274 0x09, 0x02, /* Usage (Pen), */
275 0xA1, 0x01, /* Collection (Application), */
276 0x85, 0x09, /* Report ID (9), */
277 0x09, 0x20, /* Usage (Stylus), */
278 0xA0, /* Collection (Physical), */
279 0x75, 0x01, /* Report Size (1), */
280 0x09, 0x42, /* Usage (Tip Switch), */
281 0x09, 0x44, /* Usage (Barrel Switch), */
282 0x09, 0x46, /* Usage (Tablet Pick), */
283 0x14, /* Logical Minimum (0), */
284 0x25, 0x01, /* Logical Maximum (1), */
285 0x95, 0x03, /* Report Count (3), */
286 0x81, 0x02, /* Input (Variable), */
287 0x95, 0x05, /* Report Count (5), */
288 0x81, 0x01, /* Input (Constant), */
289 0x75, 0x10, /* Report Size (16), */
290 0x95, 0x01, /* Report Count (1), */
291 0x14, /* Logical Minimum (0), */
292 0xA4, /* Push, */
293 0x05, 0x01, /* Usage Page (Desktop), */
294 0x55, 0xFD, /* Unit Exponent (-3), */
295 0x65, 0x13, /* Unit (Inch), */
296 0x34, /* Physical Minimum (0), */
297 0x09, 0x30, /* Usage (X), */
298 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */
299 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */
300 0x81, 0x02, /* Input (Variable), */
301 0x09, 0x31, /* Usage (Y), */
302 0x46, 0x70, 0x17, /* Physical Maximum (6000), */
303 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */
304 0x81, 0x02, /* Input (Variable), */
305 0xB4, /* Pop, */
306 0x09, 0x30, /* Usage (Tip Pressure), */
307 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
308 0x81, 0x02, /* Input (Variable), */
309 0xC0, /* End Collection, */
310 0xC0, /* End Collection, */
311 0x05, 0x01, /* Usage Page (Desktop), */
312 0x09, 0x02, /* Usage (Mouse), */
313 0xA1, 0x01, /* Collection (Application), */
314 0x85, 0x08, /* Report ID (8), */
315 0x09, 0x01, /* Usage (Pointer), */
316 0xA0, /* Collection (Physical), */
317 0x75, 0x01, /* Report Size (1), */
318 0x05, 0x09, /* Usage Page (Button), */
319 0x19, 0x01, /* Usage Minimum (01h), */
320 0x29, 0x03, /* Usage Maximum (03h), */
321 0x14, /* Logical Minimum (0), */
322 0x25, 0x01, /* Logical Maximum (1), */
323 0x95, 0x03, /* Report Count (3), */
324 0x81, 0x02, /* Input (Variable), */
325 0x95, 0x05, /* Report Count (5), */
326 0x81, 0x01, /* Input (Constant), */
327 0x05, 0x01, /* Usage Page (Desktop), */
328 0x75, 0x08, /* Report Size (8), */
329 0x09, 0x30, /* Usage (X), */
330 0x09, 0x31, /* Usage (Y), */
331 0x15, 0x81, /* Logical Minimum (-127), */
332 0x25, 0x7F, /* Logical Maximum (127), */
333 0x95, 0x02, /* Report Count (2), */
334 0x81, 0x06, /* Input (Variable, Relative), */
335 0x09, 0x38, /* Usage (Wheel), */
336 0x15, 0xFF, /* Logical Minimum (-1), */
337 0x25, 0x01, /* Logical Maximum (1), */
338 0x95, 0x01, /* Report Count (1), */
339 0x81, 0x06, /* Input (Variable, Relative), */
340 0x81, 0x01, /* Input (Constant), */
341 0xC0, /* End Collection, */
342 0xC0 /* End Collection */
343};
344
345static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
346 unsigned int *rsize)
347{
348 switch (hdev->product) {
349 case USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U:
350 if (*rsize == WPXXXXU_RDESC_ORIG_SIZE)
351 {
352 rdesc = wp4030u_rdesc_fixed;
353 *rsize = sizeof(wp4030u_rdesc_fixed);
354 }
355 break;
356 case USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U:
357 if (*rsize == WPXXXXU_RDESC_ORIG_SIZE)
358 {
359 rdesc = wp5540u_rdesc_fixed;
360 *rsize = sizeof(wp5540u_rdesc_fixed);
361 }
362 break;
363 case USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U:
364 if (*rsize == WPXXXXU_RDESC_ORIG_SIZE)
365 {
366 rdesc = wp8060u_rdesc_fixed;
367 *rsize = sizeof(wp8060u_rdesc_fixed);
368 }
369 break;
370 }
371
372 return rdesc;
373}
374
375static const struct hid_device_id uclogic_devices[] = {
376 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
377 USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
378 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
379 USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
380 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
381 USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
382 { }
383};
384MODULE_DEVICE_TABLE(hid, uclogic_devices);
385
386static struct hid_driver uclogic_driver = {
387 .name = "uclogic",
388 .id_table = uclogic_devices,
389 .report_fixup = uclogic_report_fixup,
390};
391
392static int __init uclogic_init(void)
393{
394 return hid_register_driver(&uclogic_driver);
395}
396
397static void __exit uclogic_exit(void)
398{
399 hid_unregister_driver(&uclogic_driver);
400}
401
402module_init(uclogic_init);
403module_exit(uclogic_exit);
404MODULE_LICENSE("GPL");