Linux Audio

Check our new training course

Yocto / OpenEmbedded training

Feb 10-13, 2025
Register
Loading...
v3.1
  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
345/*
346 * Original WP1062 report descriptor.
347 *
348 * Only report ID 9 is actually used.
349 *
350 *  Usage Page (Digitizer),         ; Digitizer (0Dh)
351 *  Usage (Pen),                    ; Pen (02h, application collection)
352 *  Collection (Application),
353 *    Report ID (7),
354 *    Usage (Stylus),               ; Stylus (20h, logical collection)
355 *    Collection (Physical),
356 *      Usage (Tip Switch),         ; Tip switch (42h, momentary control)
357 *      Usage (Barrel Switch),      ; Barrel switch (44h, momentary control)
358 *      Usage (Eraser),             ; Eraser (45h, momentary control)
359 *      Logical Minimum (0),
360 *      Logical Maximum (1),
361 *      Report Size (1),
362 *      Report Count (3),
363 *      Input (Variable),
364 *      Report Count (3),
365 *      Input (Constant, Variable),
366 *      Usage (In Range),           ; In range (32h, momentary control)
367 *      Report Count (1),
368 *      Input (Variable),
369 *      Report Count (1),
370 *      Input (Constant, Variable),
371 *      Usage Page (Desktop),       ; Generic desktop controls (01h)
372 *      Usage (X),                  ; X (30h, dynamic value)
373 *      Report Size (16),
374 *      Report Count (1),
375 *      Push,
376 *      Unit Exponent (13),
377 *      Unit (Inch),
378 *      Physical Minimum (0),
379 *      Physical Maximum (10000),
380 *      Logical Maximum (20000),
381 *      Input (Variable),
382 *      Usage (Y),                  ; Y (31h, dynamic value)
383 *      Physical Maximum (6583),
384 *      Logical Maximum (13166),
385 *      Input (Variable),
386 *      Pop,
387 *      Usage Page (Digitizer),     ; Digitizer (0Dh)
388 *      Usage (Tip Pressure),       ; Tip pressure (30h, dynamic value)
389 *      Logical Maximum (1023),
390 *      Input (Variable),
391 *      Report Size (16),
392 *    End Collection,
393 *  End Collection,
394 *  Usage Page (Desktop),           ; Generic desktop controls (01h)
395 *  Usage (Mouse),                  ; Mouse (02h, application collection)
396 *  Collection (Application),
397 *    Report ID (8),
398 *    Usage (Pointer),              ; Pointer (01h, physical collection)
399 *    Collection (Physical),
400 *      Usage Page (Button),        ; Button (09h)
401 *      Usage Minimum (01h),
402 *      Usage Maximum (03h),
403 *      Logical Minimum (0),
404 *      Logical Maximum (1),
405 *      Report Count (3),
406 *      Report Size (1),
407 *      Input (Variable),
408 *      Report Count (5),
409 *      Input (Constant),
410 *      Usage Page (Desktop),       ; Generic desktop controls (01h)
411 *      Usage (X),                  ; X (30h, dynamic value)
412 *      Usage (Y),                  ; Y (31h, dynamic value)
413 *      Usage (Wheel),              ; Wheel (38h, dynamic value)
414 *      Usage (00h),
415 *      Logical Minimum (-127),
416 *      Logical Maximum (127),
417 *      Report Size (8),
418 *      Report Count (4),
419 *      Input (Variable, Relative),
420 *    End Collection,
421 *  End Collection,
422 *  Usage Page (Desktop),           ; Generic desktop controls (01h)
423 *  Usage (Mouse),                  ; Mouse (02h, application collection)
424 *  Collection (Application),
425 *    Report ID (9),
426 *    Usage (Pointer),              ; Pointer (01h, physical collection)
427 *    Collection (Physical),
428 *      Usage Page (Button),        ; Button (09h)
429 *      Usage Minimum (01h),
430 *      Usage Maximum (03h),
431 *      Logical Minimum (0),
432 *      Logical Maximum (1),
433 *      Report Count (3),
434 *      Report Size (1),
435 *      Input (Variable),
436 *      Report Count (4),
437 *      Input (Constant),
438 *      Usage Page (Digitizer),     ; Digitizer (0Dh)
439 *      Usage (In Range),           ; In range (32h, momentary control)
440 *      Report Count (1),
441 *      Input (Variable),
442 *      Usage Page (Desktop),       ; Generic desktop controls (01h)
443 *      Usage (X),                  ; X (30h, dynamic value)
444 *      Report Size (16),
445 *      Report Count (1),
446 *      Push,
447 *      Unit Exponent (13),
448 *      Unit (Inch),
449 *      Physical Minimum (0),
450 *      Physical Maximum (10000),
451 *      Logical Maximum (20000),
452 *      Input (Variable),
453 *      Usage (Y),                  ; Y (31h, dynamic value)
454 *      Physical Maximum (6583),
455 *      Logical Maximum (13166),
456 *      Input (Variable),
457 *      Pop,
458 *      Usage Page (Digitizer),     ; Digitizer (0Dh)
459 *      Usage (Tip Pressure),       ; Tip pressure (30h, dynamic value)
460 *      Logical Maximum (1023),
461 *      Report Count (1),
462 *      Report Size (16),
463 *      Input (Variable),
464 *    End Collection,
465 *  End Collection,
466 *  Usage Page (Desktop),           ; Generic desktop controls (01h)
467 *  Usage (00h),
468 *  Collection (Application),
469 *    Report ID (4),
470 *    Logical Minimum (0),
471 *    Logical Maximum (255),
472 *    Usage (00h),
473 *    Report Size (8),
474 *    Report Count (3),
475 *    Feature (Variable),
476 *  End Collection
477 */
478
479/* Size of the original descriptor of WP1062 tablet */
480#define WP1062_RDESC_ORIG_SIZE	254
481
482/*
483 * Fixed WP1062 report descriptor.
484 *
485 * Removed unused reports, corrected second barrel button usage code, physical
486 * units.
487 */
488static __u8 wp1062_rdesc_fixed[] = {
489	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
490	0x09, 0x02,         /*  Usage (Pen),                        */
491	0xA1, 0x01,         /*  Collection (Application),           */
492	0x85, 0x09,         /*      Report ID (9),                  */
493	0x09, 0x20,         /*      Usage (Stylus),                 */
494	0xA0,               /*      Collection (Physical),          */
495	0x75, 0x01,         /*          Report Size (1),            */
496	0x09, 0x42,         /*          Usage (Tip Switch),         */
497	0x09, 0x44,         /*          Usage (Barrel Switch),      */
498	0x09, 0x46,         /*          Usage (Tablet Pick),        */
499	0x14,               /*          Logical Minimum (0),        */
500	0x25, 0x01,         /*          Logical Maximum (1),        */
501	0x95, 0x03,         /*          Report Count (3),           */
502	0x81, 0x02,         /*          Input (Variable),           */
503	0x95, 0x04,         /*          Report Count (4),           */
504	0x81, 0x01,         /*          Input (Constant),           */
505	0x09, 0x32,         /*          Usage (In Range),           */
506	0x95, 0x01,         /*          Report Count (1),           */
507	0x81, 0x02,         /*          Input (Variable),           */
508	0x75, 0x10,         /*          Report Size (16),           */
509	0x95, 0x01,         /*          Report Count (1),           */
510	0x14,               /*          Logical Minimum (0),        */
511	0xA4,               /*          Push,                       */
512	0x05, 0x01,         /*          Usage Page (Desktop),       */
513	0x55, 0xFD,         /*          Unit Exponent (-3),         */
514	0x65, 0x13,         /*          Unit (Inch),                */
515	0x34,               /*          Physical Minimum (0),       */
516	0x09, 0x30,         /*          Usage (X),                  */
517	0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
518	0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
519	0x81, 0x02,         /*          Input (Variable),           */
520	0x09, 0x31,         /*          Usage (Y),                  */
521	0x46, 0xB7, 0x19,   /*          Physical Maximum (6583),    */
522	0x26, 0x6E, 0x33,   /*          Logical Maximum (13166),    */
523	0x81, 0x02,         /*          Input (Variable),           */
524	0xB4,               /*          Pop,                        */
525	0x09, 0x30,         /*          Usage (Tip Pressure),       */
526	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
527	0x81, 0x02,         /*          Input (Variable),           */
528	0xC0,               /*      End Collection,                 */
529	0xC0                /*  End Collection                      */
530};
531
532/*
533 * Original PF1209 report descriptor.
534 *
535 * The descriptor is similar to WPXXXXU descriptors, with an addition of a
536 * feature report (ID 4) of unknown purpose.
537 *
538 * Although the advertised resolution is 4000 LPI the unused report ID
539 * (taken from WPXXXXU, it seems) states 2000 LPI, but it is probably
540 * incorrect and is a result of blind copying without understanding. Anyway
541 * the real logical extents are always scaled to 0..32767, which IMHO spoils
542 * the precision.
543 *
544 *  Usage Page (Digitizer),         ; Digitizer (0Dh)
545 *  Usage (Pen),                    ; Pen (02h, application collection)
546 *  Collection (Application),
547 *    Report ID (7),
548 *    Usage (Stylus),               ; Stylus (20h, logical collection)
549 *    Collection (Physical),
550 *      Usage (Tip Switch),         ; Tip switch (42h, momentary control)
551 *      Usage (Barrel Switch),      ; Barrel switch (44h, momentary control)
552 *      Usage (Eraser),             ; Eraser (45h, momentary control)
553 *      Logical Minimum (0),
554 *      Logical Maximum (1),
555 *      Report Size (1),
556 *      Report Count (3),
557 *      Input (Variable),
558 *      Report Count (3),
559 *      Input (Constant, Variable),
560 *      Usage (In Range),           ; In range (32h, momentary control)
561 *      Report Count (1),
562 *      Input (Variable),
563 *      Report Count (1),
564 *      Input (Constant, Variable),
565 *      Usage Page (Desktop),       ; Generic desktop controls (01h)
566 *      Usage (X),                  ; X (30h, dynamic value)
567 *      Report Size (16),
568 *      Report Count (1),
569 *      Push,
570 *      Unit Exponent (13),
571 *      Unit (Inch^3),
572 *      Physical Minimum (0),
573 *      Physical Maximum (12000),
574 *      Logical Maximum (24000),
575 *      Input (Variable),
576 *      Usage (Y),                  ; Y (31h, dynamic value)
577 *      Physical Maximum (9000),
578 *      Logical Maximum (18000),
579 *      Input (Variable),
580 *      Pop,
581 *      Usage Page (Digitizer),     ; Digitizer (0Dh)
582 *      Usage (Tip Pressure),       ; Tip pressure (30h, dynamic value)
583 *      Logical Maximum (1023),
584 *      Input (Variable),
585 *      Report Size (16),
586 *    End Collection,
587 *  End Collection,
588 *  Usage Page (Desktop),           ; Generic desktop controls (01h)
589 *  Usage (Mouse),                  ; Mouse (02h, application collection)
590 *  Collection (Application),
591 *    Report ID (8),
592 *    Usage (Pointer),              ; Pointer (01h, physical collection)
593 *    Collection (Physical),
594 *      Usage Page (Button),        ; Button (09h)
595 *      Usage Minimum (01h),
596 *      Usage Maximum (03h),
597 *      Logical Minimum (0),
598 *      Logical Maximum (1),
599 *      Report Count (3),
600 *      Report Size (1),
601 *      Input (Variable),
602 *      Report Count (5),
603 *      Input (Constant),
604 *      Usage Page (Desktop),       ; Generic desktop controls (01h)
605 *      Usage (X),                  ; X (30h, dynamic value)
606 *      Usage (Y),                  ; Y (31h, dynamic value)
607 *      Usage (Wheel),              ; Wheel (38h, dynamic value)
608 *      Usage (00h),
609 *      Logical Minimum (-127),
610 *      Logical Maximum (127),
611 *      Report Size (8),
612 *      Report Count (4),
613 *      Input (Variable, Relative),
614 *    End Collection,
615 *  End Collection,
616 *  Usage Page (Desktop),           ; Generic desktop controls (01h)
617 *  Usage (Mouse),                  ; Mouse (02h, application collection)
618 *  Collection (Application),
619 *    Report ID (9),
620 *    Usage (Pointer),              ; Pointer (01h, physical collection)
621 *    Collection (Physical),
622 *      Usage Page (Button),        ; Button (09h)
623 *      Usage Minimum (01h),
624 *      Usage Maximum (03h),
625 *      Logical Minimum (0),
626 *      Logical Maximum (1),
627 *      Report Count (3),
628 *      Report Size (1),
629 *      Input (Variable),
630 *      Report Count (5),
631 *      Input (Constant),
632 *      Usage Page (Desktop),       ; Generic desktop controls (01h)
633 *      Usage (X),                  ; X (30h, dynamic value)
634 *      Usage (Y),                  ; Y (31h, dynamic value)
635 *      Logical Minimum (0),
636 *      Logical Maximum (32767),
637 *      Physical Minimum (0),
638 *      Physical Maximum (32767),
639 *      Report Count (2),
640 *      Report Size (16),
641 *      Input (Variable),
642 *      Usage Page (Digitizer),     ; Digitizer (0Dh)
643 *      Usage (Tip Pressure),       ; Tip pressure (30h, dynamic value)
644 *      Logical Maximum (1023),
645 *      Report Count (1),
646 *      Report Size (16),
647 *      Input (Variable),
648 *    End Collection,
649 *  End Collection,
650 *  Usage Page (Desktop),           ; Generic desktop controls (01h)
651 *  Usage (00h),
652 *  Collection (Application),
653 *    Report ID (4),
654 *    Logical Minimum (0),
655 *    Logical Maximum (255),
656 *    Usage (00h),
657 *    Report Size (8),
658 *    Report Count (3),
659 *    Feature (Variable),
660 *  End Collection
661 */
662
663/* Size of the original descriptor of PF1209 tablet */
664#define PF1209_RDESC_ORIG_SIZE	234
665
666/*
667 * Fixed PF1209 report descriptor
668 *
669 * The descriptor is fixed similarly to WP5540U and WP8060U, plus the
670 * feature report is removed, because its purpose is unknown and it is of no
671 * use to the generic HID driver anyway for now.
672 */
673static __u8 pf1209_rdesc_fixed[] = {
674	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
675	0x09, 0x02,         /*  Usage (Pen),                        */
676	0xA1, 0x01,         /*  Collection (Application),           */
677	0x85, 0x09,         /*      Report ID (9),                  */
678	0x09, 0x20,         /*      Usage (Stylus),                 */
679	0xA0,               /*      Collection (Physical),          */
680	0x75, 0x01,         /*          Report Size (1),            */
681	0x09, 0x42,         /*          Usage (Tip Switch),         */
682	0x09, 0x44,         /*          Usage (Barrel Switch),      */
683	0x09, 0x46,         /*          Usage (Tablet Pick),        */
684	0x14,               /*          Logical Minimum (0),        */
685	0x25, 0x01,         /*          Logical Maximum (1),        */
686	0x95, 0x03,         /*          Report Count (3),           */
687	0x81, 0x02,         /*          Input (Variable),           */
688	0x95, 0x05,         /*          Report Count (5),           */
689	0x81, 0x01,         /*          Input (Constant),           */
690	0x75, 0x10,         /*          Report Size (16),           */
691	0x95, 0x01,         /*          Report Count (1),           */
692	0x14,               /*          Logical Minimum (0),        */
693	0xA4,               /*          Push,                       */
694	0x05, 0x01,         /*          Usage Page (Desktop),       */
695	0x55, 0xFD,         /*          Unit Exponent (-3),         */
696	0x65, 0x13,         /*          Unit (Inch),                */
697	0x34,               /*          Physical Minimum (0),       */
698	0x09, 0x30,         /*          Usage (X),                  */
699	0x46, 0xE0, 0x2E,   /*          Physical Maximum (12000),   */
700	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
701	0x81, 0x02,         /*          Input (Variable),           */
702	0x09, 0x31,         /*          Usage (Y),                  */
703	0x46, 0x28, 0x23,   /*          Physical Maximum (9000),    */
704	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
705	0x81, 0x02,         /*          Input (Variable),           */
706	0xB4,               /*          Pop,                        */
707	0x09, 0x30,         /*          Usage (Tip Pressure),       */
708	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
709	0x81, 0x02,         /*          Input (Variable),           */
710	0xC0,               /*      End Collection,                 */
711	0xC0,               /*  End Collection,                     */
712	0x05, 0x01,         /*  Usage Page (Desktop),               */
713	0x09, 0x02,         /*  Usage (Mouse),                      */
714	0xA1, 0x01,         /*  Collection (Application),           */
715	0x85, 0x08,         /*      Report ID (8),                  */
716	0x09, 0x01,         /*      Usage (Pointer),                */
717	0xA0,               /*      Collection (Physical),          */
718	0x75, 0x01,         /*          Report Size (1),            */
719	0x05, 0x09,         /*          Usage Page (Button),        */
720	0x19, 0x01,         /*          Usage Minimum (01h),        */
721	0x29, 0x03,         /*          Usage Maximum (03h),        */
722	0x14,               /*          Logical Minimum (0),        */
723	0x25, 0x01,         /*          Logical Maximum (1),        */
724	0x95, 0x03,         /*          Report Count (3),           */
725	0x81, 0x02,         /*          Input (Variable),           */
726	0x95, 0x05,         /*          Report Count (5),           */
727	0x81, 0x01,         /*          Input (Constant),           */
728	0x05, 0x01,         /*          Usage Page (Desktop),       */
729	0x75, 0x08,         /*          Report Size (8),            */
730	0x09, 0x30,         /*          Usage (X),                  */
731	0x09, 0x31,         /*          Usage (Y),                  */
732	0x15, 0x81,         /*          Logical Minimum (-127),     */
733	0x25, 0x7F,         /*          Logical Maximum (127),      */
734	0x95, 0x02,         /*          Report Count (2),           */
735	0x81, 0x06,         /*          Input (Variable, Relative), */
736	0x09, 0x38,         /*          Usage (Wheel),              */
737	0x15, 0xFF,         /*          Logical Minimum (-1),       */
738	0x25, 0x01,         /*          Logical Maximum (1),        */
739	0x95, 0x01,         /*          Report Count (1),           */
740	0x81, 0x06,         /*          Input (Variable, Relative), */
741	0x81, 0x01,         /*          Input (Constant),           */
742	0xC0,               /*      End Collection,                 */
743	0xC0                /*  End Collection                      */
744};
745
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
746static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
747					unsigned int *rsize)
748{
 
 
 
 
749	switch (hdev->product) {
750	case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209:
751		if (*rsize == PF1209_RDESC_ORIG_SIZE) {
752			rdesc = pf1209_rdesc_fixed;
753			*rsize = sizeof(pf1209_rdesc_fixed);
754		}
755		break;
756	case USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U:
757		if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
758			rdesc = wp4030u_rdesc_fixed;
759			*rsize = sizeof(wp4030u_rdesc_fixed);
760		}
761		break;
762	case USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U:
763		if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
764			rdesc = wp5540u_rdesc_fixed;
765			*rsize = sizeof(wp5540u_rdesc_fixed);
766		}
767		break;
768	case USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U:
769		if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
770			rdesc = wp8060u_rdesc_fixed;
771			*rsize = sizeof(wp8060u_rdesc_fixed);
772		}
773		break;
774	case USB_DEVICE_ID_UCLOGIC_TABLET_WP1062:
775		if (*rsize == WP1062_RDESC_ORIG_SIZE) {
776			rdesc = wp1062_rdesc_fixed;
777			*rsize = sizeof(wp1062_rdesc_fixed);
778		}
779		break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
780	}
781
782	return rdesc;
783}
784
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
785static const struct hid_device_id uclogic_devices[] = {
786	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
787				USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) },
788	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
789				USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
790	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
791				USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
792	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
793				USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
794	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
795				USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
 
 
 
 
 
 
796	{ }
797};
798MODULE_DEVICE_TABLE(hid, uclogic_devices);
799
800static struct hid_driver uclogic_driver = {
801	.name = "uclogic",
802	.id_table = uclogic_devices,
 
803	.report_fixup = uclogic_report_fixup,
 
 
 
804};
 
805
806static int __init uclogic_init(void)
807{
808	return hid_register_driver(&uclogic_driver);
809}
810
811static void __exit uclogic_exit(void)
812{
813	hid_unregister_driver(&uclogic_driver);
814}
815
816module_init(uclogic_init);
817module_exit(uclogic_exit);
818MODULE_LICENSE("GPL");
v4.6
  1/*
  2 *  HID driver for UC-Logic devices not fully compliant with HID standard
  3 *
  4 *  Copyright (c) 2010-2014 Nikolai Kondrashov
  5 *  Copyright (c) 2013 Martin Rusko
  6 */
  7
  8/*
  9 * This program is free software; you can redistribute it and/or modify it
 10 * under the terms of the GNU General Public License as published by the Free
 11 * Software Foundation; either version 2 of the License, or (at your option)
 12 * any later version.
 13 */
 14
 15#include <linux/device.h>
 16#include <linux/hid.h>
 17#include <linux/module.h>
 18#include <linux/usb.h>
 19#include <asm/unaligned.h>
 20#include "usbhid/usbhid.h"
 21
 22#include "hid-ids.h"
 23
 24/*
 25 * See WPXXXXU model descriptions, device and HID report descriptors at
 26 * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP4030U
 27 * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP5540U
 28 * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP8060U
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 29 */
 30
 31/* Size of the original descriptor of WPXXXXU tablets */
 32#define WPXXXXU_RDESC_ORIG_SIZE	212
 33
 34/* Fixed WP4030U report descriptor */
 
 
 
 
 
 35static __u8 wp4030u_rdesc_fixed[] = {
 36	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
 37	0x09, 0x02,         /*  Usage (Pen),                        */
 38	0xA1, 0x01,         /*  Collection (Application),           */
 39	0x85, 0x09,         /*      Report ID (9),                  */
 40	0x09, 0x20,         /*      Usage (Stylus),                 */
 41	0xA0,               /*      Collection (Physical),          */
 42	0x75, 0x01,         /*          Report Size (1),            */
 43	0x09, 0x42,         /*          Usage (Tip Switch),         */
 44	0x09, 0x44,         /*          Usage (Barrel Switch),      */
 45	0x09, 0x46,         /*          Usage (Tablet Pick),        */
 46	0x14,               /*          Logical Minimum (0),        */
 47	0x25, 0x01,         /*          Logical Maximum (1),        */
 48	0x95, 0x03,         /*          Report Count (3),           */
 49	0x81, 0x02,         /*          Input (Variable),           */
 50	0x95, 0x05,         /*          Report Count (5),           */
 51	0x81, 0x01,         /*          Input (Constant),           */
 52	0x75, 0x10,         /*          Report Size (16),           */
 53	0x95, 0x01,         /*          Report Count (1),           */
 54	0x14,               /*          Logical Minimum (0),        */
 55	0xA4,               /*          Push,                       */
 56	0x05, 0x01,         /*          Usage Page (Desktop),       */
 57	0x55, 0xFD,         /*          Unit Exponent (-3),         */
 58	0x65, 0x13,         /*          Unit (Inch),                */
 59	0x34,               /*          Physical Minimum (0),       */
 60	0x09, 0x30,         /*          Usage (X),                  */
 61	0x46, 0xA0, 0x0F,   /*          Physical Maximum (4000),    */
 62	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
 63	0x81, 0x02,         /*          Input (Variable),           */
 64	0x09, 0x31,         /*          Usage (Y),                  */
 65	0x46, 0xB8, 0x0B,   /*          Physical Maximum (3000),    */
 66	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
 67	0x81, 0x02,         /*          Input (Variable),           */
 68	0xB4,               /*          Pop,                        */
 69	0x09, 0x30,         /*          Usage (Tip Pressure),       */
 70	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
 71	0x81, 0x02,         /*          Input (Variable),           */
 72	0xC0,               /*      End Collection,                 */
 73	0xC0                /*  End Collection                      */
 74};
 75
 76/* Fixed WP5540U report descriptor */
 77static __u8 wp5540u_rdesc_fixed[] = {
 78	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
 79	0x09, 0x02,         /*  Usage (Pen),                        */
 80	0xA1, 0x01,         /*  Collection (Application),           */
 81	0x85, 0x09,         /*      Report ID (9),                  */
 82	0x09, 0x20,         /*      Usage (Stylus),                 */
 83	0xA0,               /*      Collection (Physical),          */
 84	0x75, 0x01,         /*          Report Size (1),            */
 85	0x09, 0x42,         /*          Usage (Tip Switch),         */
 86	0x09, 0x44,         /*          Usage (Barrel Switch),      */
 87	0x09, 0x46,         /*          Usage (Tablet Pick),        */
 88	0x14,               /*          Logical Minimum (0),        */
 89	0x25, 0x01,         /*          Logical Maximum (1),        */
 90	0x95, 0x03,         /*          Report Count (3),           */
 91	0x81, 0x02,         /*          Input (Variable),           */
 92	0x95, 0x05,         /*          Report Count (5),           */
 93	0x81, 0x01,         /*          Input (Constant),           */
 94	0x75, 0x10,         /*          Report Size (16),           */
 95	0x95, 0x01,         /*          Report Count (1),           */
 96	0x14,               /*          Logical Minimum (0),        */
 97	0xA4,               /*          Push,                       */
 98	0x05, 0x01,         /*          Usage Page (Desktop),       */
 99	0x55, 0xFD,         /*          Unit Exponent (-3),         */
100	0x65, 0x13,         /*          Unit (Inch),                */
101	0x34,               /*          Physical Minimum (0),       */
102	0x09, 0x30,         /*          Usage (X),                  */
103	0x46, 0x7C, 0x15,   /*          Physical Maximum (5500),    */
104	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
105	0x81, 0x02,         /*          Input (Variable),           */
106	0x09, 0x31,         /*          Usage (Y),                  */
107	0x46, 0xA0, 0x0F,   /*          Physical Maximum (4000),    */
108	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
109	0x81, 0x02,         /*          Input (Variable),           */
110	0xB4,               /*          Pop,                        */
111	0x09, 0x30,         /*          Usage (Tip Pressure),       */
112	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
113	0x81, 0x02,         /*          Input (Variable),           */
114	0xC0,               /*      End Collection,                 */
115	0xC0,               /*  End Collection,                     */
116	0x05, 0x01,         /*  Usage Page (Desktop),               */
117	0x09, 0x02,         /*  Usage (Mouse),                      */
118	0xA1, 0x01,         /*  Collection (Application),           */
119	0x85, 0x08,         /*      Report ID (8),                  */
120	0x09, 0x01,         /*      Usage (Pointer),                */
121	0xA0,               /*      Collection (Physical),          */
122	0x75, 0x01,         /*          Report Size (1),            */
123	0x05, 0x09,         /*          Usage Page (Button),        */
124	0x19, 0x01,         /*          Usage Minimum (01h),        */
125	0x29, 0x03,         /*          Usage Maximum (03h),        */
126	0x14,               /*          Logical Minimum (0),        */
127	0x25, 0x01,         /*          Logical Maximum (1),        */
128	0x95, 0x03,         /*          Report Count (3),           */
129	0x81, 0x02,         /*          Input (Variable),           */
130	0x95, 0x05,         /*          Report Count (5),           */
131	0x81, 0x01,         /*          Input (Constant),           */
132	0x05, 0x01,         /*          Usage Page (Desktop),       */
133	0x75, 0x08,         /*          Report Size (8),            */
134	0x09, 0x30,         /*          Usage (X),                  */
135	0x09, 0x31,         /*          Usage (Y),                  */
136	0x15, 0x81,         /*          Logical Minimum (-127),     */
137	0x25, 0x7F,         /*          Logical Maximum (127),      */
138	0x95, 0x02,         /*          Report Count (2),           */
139	0x81, 0x06,         /*          Input (Variable, Relative), */
140	0x09, 0x38,         /*          Usage (Wheel),              */
141	0x15, 0xFF,         /*          Logical Minimum (-1),       */
142	0x25, 0x01,         /*          Logical Maximum (1),        */
143	0x95, 0x01,         /*          Report Count (1),           */
144	0x81, 0x06,         /*          Input (Variable, Relative), */
145	0x81, 0x01,         /*          Input (Constant),           */
146	0xC0,               /*      End Collection,                 */
147	0xC0                /*  End Collection                      */
148};
149
150/* Fixed WP8060U report descriptor */
151static __u8 wp8060u_rdesc_fixed[] = {
152	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
153	0x09, 0x02,         /*  Usage (Pen),                        */
154	0xA1, 0x01,         /*  Collection (Application),           */
155	0x85, 0x09,         /*      Report ID (9),                  */
156	0x09, 0x20,         /*      Usage (Stylus),                 */
157	0xA0,               /*      Collection (Physical),          */
158	0x75, 0x01,         /*          Report Size (1),            */
159	0x09, 0x42,         /*          Usage (Tip Switch),         */
160	0x09, 0x44,         /*          Usage (Barrel Switch),      */
161	0x09, 0x46,         /*          Usage (Tablet Pick),        */
162	0x14,               /*          Logical Minimum (0),        */
163	0x25, 0x01,         /*          Logical Maximum (1),        */
164	0x95, 0x03,         /*          Report Count (3),           */
165	0x81, 0x02,         /*          Input (Variable),           */
166	0x95, 0x05,         /*          Report Count (5),           */
167	0x81, 0x01,         /*          Input (Constant),           */
168	0x75, 0x10,         /*          Report Size (16),           */
169	0x95, 0x01,         /*          Report Count (1),           */
170	0x14,               /*          Logical Minimum (0),        */
171	0xA4,               /*          Push,                       */
172	0x05, 0x01,         /*          Usage Page (Desktop),       */
173	0x55, 0xFD,         /*          Unit Exponent (-3),         */
174	0x65, 0x13,         /*          Unit (Inch),                */
175	0x34,               /*          Physical Minimum (0),       */
176	0x09, 0x30,         /*          Usage (X),                  */
177	0x46, 0x40, 0x1F,   /*          Physical Maximum (8000),    */
178	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
179	0x81, 0x02,         /*          Input (Variable),           */
180	0x09, 0x31,         /*          Usage (Y),                  */
181	0x46, 0x70, 0x17,   /*          Physical Maximum (6000),    */
182	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
183	0x81, 0x02,         /*          Input (Variable),           */
184	0xB4,               /*          Pop,                        */
185	0x09, 0x30,         /*          Usage (Tip Pressure),       */
186	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
187	0x81, 0x02,         /*          Input (Variable),           */
188	0xC0,               /*      End Collection,                 */
189	0xC0,               /*  End Collection,                     */
190	0x05, 0x01,         /*  Usage Page (Desktop),               */
191	0x09, 0x02,         /*  Usage (Mouse),                      */
192	0xA1, 0x01,         /*  Collection (Application),           */
193	0x85, 0x08,         /*      Report ID (8),                  */
194	0x09, 0x01,         /*      Usage (Pointer),                */
195	0xA0,               /*      Collection (Physical),          */
196	0x75, 0x01,         /*          Report Size (1),            */
197	0x05, 0x09,         /*          Usage Page (Button),        */
198	0x19, 0x01,         /*          Usage Minimum (01h),        */
199	0x29, 0x03,         /*          Usage Maximum (03h),        */
200	0x14,               /*          Logical Minimum (0),        */
201	0x25, 0x01,         /*          Logical Maximum (1),        */
202	0x95, 0x03,         /*          Report Count (3),           */
203	0x81, 0x02,         /*          Input (Variable),           */
204	0x95, 0x05,         /*          Report Count (5),           */
205	0x81, 0x01,         /*          Input (Constant),           */
206	0x05, 0x01,         /*          Usage Page (Desktop),       */
207	0x75, 0x08,         /*          Report Size (8),            */
208	0x09, 0x30,         /*          Usage (X),                  */
209	0x09, 0x31,         /*          Usage (Y),                  */
210	0x15, 0x81,         /*          Logical Minimum (-127),     */
211	0x25, 0x7F,         /*          Logical Maximum (127),      */
212	0x95, 0x02,         /*          Report Count (2),           */
213	0x81, 0x06,         /*          Input (Variable, Relative), */
214	0x09, 0x38,         /*          Usage (Wheel),              */
215	0x15, 0xFF,         /*          Logical Minimum (-1),       */
216	0x25, 0x01,         /*          Logical Maximum (1),        */
217	0x95, 0x01,         /*          Report Count (1),           */
218	0x81, 0x06,         /*          Input (Variable, Relative), */
219	0x81, 0x01,         /*          Input (Constant),           */
220	0xC0,               /*      End Collection,                 */
221	0xC0                /*  End Collection                      */
222};
223
224/*
225 * See WP1062 description, device and HID report descriptors at
226 * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP1062
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227 */
228
229/* Size of the original descriptor of WP1062 tablet */
230#define WP1062_RDESC_ORIG_SIZE	254
231
232/* Fixed WP1062 report descriptor */
 
 
 
 
 
233static __u8 wp1062_rdesc_fixed[] = {
234	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
235	0x09, 0x02,         /*  Usage (Pen),                        */
236	0xA1, 0x01,         /*  Collection (Application),           */
237	0x85, 0x09,         /*      Report ID (9),                  */
238	0x09, 0x20,         /*      Usage (Stylus),                 */
239	0xA0,               /*      Collection (Physical),          */
240	0x75, 0x01,         /*          Report Size (1),            */
241	0x09, 0x42,         /*          Usage (Tip Switch),         */
242	0x09, 0x44,         /*          Usage (Barrel Switch),      */
243	0x09, 0x46,         /*          Usage (Tablet Pick),        */
244	0x14,               /*          Logical Minimum (0),        */
245	0x25, 0x01,         /*          Logical Maximum (1),        */
246	0x95, 0x03,         /*          Report Count (3),           */
247	0x81, 0x02,         /*          Input (Variable),           */
248	0x95, 0x04,         /*          Report Count (4),           */
249	0x81, 0x01,         /*          Input (Constant),           */
250	0x09, 0x32,         /*          Usage (In Range),           */
251	0x95, 0x01,         /*          Report Count (1),           */
252	0x81, 0x02,         /*          Input (Variable),           */
253	0x75, 0x10,         /*          Report Size (16),           */
254	0x95, 0x01,         /*          Report Count (1),           */
255	0x14,               /*          Logical Minimum (0),        */
256	0xA4,               /*          Push,                       */
257	0x05, 0x01,         /*          Usage Page (Desktop),       */
258	0x55, 0xFD,         /*          Unit Exponent (-3),         */
259	0x65, 0x13,         /*          Unit (Inch),                */
260	0x34,               /*          Physical Minimum (0),       */
261	0x09, 0x30,         /*          Usage (X),                  */
262	0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
263	0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
264	0x81, 0x02,         /*          Input (Variable),           */
265	0x09, 0x31,         /*          Usage (Y),                  */
266	0x46, 0xB7, 0x19,   /*          Physical Maximum (6583),    */
267	0x26, 0x6E, 0x33,   /*          Logical Maximum (13166),    */
268	0x81, 0x02,         /*          Input (Variable),           */
269	0xB4,               /*          Pop,                        */
270	0x09, 0x30,         /*          Usage (Tip Pressure),       */
271	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
272	0x81, 0x02,         /*          Input (Variable),           */
273	0xC0,               /*      End Collection,                 */
274	0xC0                /*  End Collection                      */
275};
276
277/*
278 * See PF1209 description, device and HID report descriptors at
279 * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_PF1209
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280 */
281
282/* Size of the original descriptor of PF1209 tablet */
283#define PF1209_RDESC_ORIG_SIZE	234
284
285/* Fixed PF1209 report descriptor */
 
 
 
 
 
 
286static __u8 pf1209_rdesc_fixed[] = {
287	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
288	0x09, 0x02,         /*  Usage (Pen),                        */
289	0xA1, 0x01,         /*  Collection (Application),           */
290	0x85, 0x09,         /*      Report ID (9),                  */
291	0x09, 0x20,         /*      Usage (Stylus),                 */
292	0xA0,               /*      Collection (Physical),          */
293	0x75, 0x01,         /*          Report Size (1),            */
294	0x09, 0x42,         /*          Usage (Tip Switch),         */
295	0x09, 0x44,         /*          Usage (Barrel Switch),      */
296	0x09, 0x46,         /*          Usage (Tablet Pick),        */
297	0x14,               /*          Logical Minimum (0),        */
298	0x25, 0x01,         /*          Logical Maximum (1),        */
299	0x95, 0x03,         /*          Report Count (3),           */
300	0x81, 0x02,         /*          Input (Variable),           */
301	0x95, 0x05,         /*          Report Count (5),           */
302	0x81, 0x01,         /*          Input (Constant),           */
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	0x55, 0xFD,         /*          Unit Exponent (-3),         */
309	0x65, 0x13,         /*          Unit (Inch),                */
310	0x34,               /*          Physical Minimum (0),       */
311	0x09, 0x30,         /*          Usage (X),                  */
312	0x46, 0xE0, 0x2E,   /*          Physical Maximum (12000),   */
313	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
314	0x81, 0x02,         /*          Input (Variable),           */
315	0x09, 0x31,         /*          Usage (Y),                  */
316	0x46, 0x28, 0x23,   /*          Physical Maximum (9000),    */
317	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
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, 0x08,         /*      Report ID (8),                  */
329	0x09, 0x01,         /*      Usage (Pointer),                */
330	0xA0,               /*      Collection (Physical),          */
331	0x75, 0x01,         /*          Report Size (1),            */
332	0x05, 0x09,         /*          Usage Page (Button),        */
333	0x19, 0x01,         /*          Usage Minimum (01h),        */
334	0x29, 0x03,         /*          Usage Maximum (03h),        */
335	0x14,               /*          Logical Minimum (0),        */
336	0x25, 0x01,         /*          Logical Maximum (1),        */
337	0x95, 0x03,         /*          Report Count (3),           */
338	0x81, 0x02,         /*          Input (Variable),           */
339	0x95, 0x05,         /*          Report Count (5),           */
340	0x81, 0x01,         /*          Input (Constant),           */
341	0x05, 0x01,         /*          Usage Page (Desktop),       */
342	0x75, 0x08,         /*          Report Size (8),            */
343	0x09, 0x30,         /*          Usage (X),                  */
344	0x09, 0x31,         /*          Usage (Y),                  */
345	0x15, 0x81,         /*          Logical Minimum (-127),     */
346	0x25, 0x7F,         /*          Logical Maximum (127),      */
347	0x95, 0x02,         /*          Report Count (2),           */
348	0x81, 0x06,         /*          Input (Variable, Relative), */
349	0x09, 0x38,         /*          Usage (Wheel),              */
350	0x15, 0xFF,         /*          Logical Minimum (-1),       */
351	0x25, 0x01,         /*          Logical Maximum (1),        */
352	0x95, 0x01,         /*          Report Count (1),           */
353	0x81, 0x06,         /*          Input (Variable, Relative), */
354	0x81, 0x01,         /*          Input (Constant),           */
355	0xC0,               /*      End Collection,                 */
356	0xC0                /*  End Collection                      */
357};
358
359/*
360 * See TWHL850 description, device and HID report descriptors at
361 * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Wireless_Tablet_TWHL850
362 */
363
364/* Size of the original descriptors of TWHL850 tablet */
365#define TWHL850_RDESC_ORIG_SIZE0	182
366#define TWHL850_RDESC_ORIG_SIZE1	161
367#define TWHL850_RDESC_ORIG_SIZE2	92
368
369/* Fixed PID 0522 tablet report descriptor, interface 0 (stylus) */
370static __u8 twhl850_rdesc_fixed0[] = {
371	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
372	0x09, 0x02,         /*  Usage (Pen),                        */
373	0xA1, 0x01,         /*  Collection (Application),           */
374	0x85, 0x09,         /*      Report ID (9),                  */
375	0x09, 0x20,         /*      Usage (Stylus),                 */
376	0xA0,               /*      Collection (Physical),          */
377	0x14,               /*          Logical Minimum (0),        */
378	0x25, 0x01,         /*          Logical Maximum (1),        */
379	0x75, 0x01,         /*          Report Size (1),            */
380	0x95, 0x03,         /*          Report Count (3),           */
381	0x09, 0x42,         /*          Usage (Tip Switch),         */
382	0x09, 0x44,         /*          Usage (Barrel Switch),      */
383	0x09, 0x46,         /*          Usage (Tablet Pick),        */
384	0x81, 0x02,         /*          Input (Variable),           */
385	0x81, 0x03,         /*          Input (Constant, Variable), */
386	0x95, 0x01,         /*          Report Count (1),           */
387	0x09, 0x32,         /*          Usage (In Range),           */
388	0x81, 0x02,         /*          Input (Variable),           */
389	0x81, 0x03,         /*          Input (Constant, Variable), */
390	0x75, 0x10,         /*          Report Size (16),           */
391	0xA4,               /*          Push,                       */
392	0x05, 0x01,         /*          Usage Page (Desktop),       */
393	0x65, 0x13,         /*          Unit (Inch),                */
394	0x55, 0xFD,         /*          Unit Exponent (-3),         */
395	0x34,               /*          Physical Minimum (0),       */
396	0x09, 0x30,         /*          Usage (X),                  */
397	0x46, 0x40, 0x1F,   /*          Physical Maximum (8000),    */
398	0x26, 0x00, 0x7D,   /*          Logical Maximum (32000),    */
399	0x81, 0x02,         /*          Input (Variable),           */
400	0x09, 0x31,         /*          Usage (Y),                  */
401	0x46, 0x88, 0x13,   /*          Physical Maximum (5000),    */
402	0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
403	0x81, 0x02,         /*          Input (Variable),           */
404	0xB4,               /*          Pop,                        */
405	0x09, 0x30,         /*          Usage (Tip Pressure),       */
406	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
407	0x81, 0x02,         /*          Input (Variable),           */
408	0xC0,               /*      End Collection,                 */
409	0xC0                /*  End Collection                      */
410};
411
412/* Fixed PID 0522 tablet report descriptor, interface 1 (mouse) */
413static __u8 twhl850_rdesc_fixed1[] = {
414	0x05, 0x01,         /*  Usage Page (Desktop),               */
415	0x09, 0x02,         /*  Usage (Mouse),                      */
416	0xA1, 0x01,         /*  Collection (Application),           */
417	0x85, 0x01,         /*      Report ID (1),                  */
418	0x09, 0x01,         /*      Usage (Pointer),                */
419	0xA0,               /*      Collection (Physical),          */
420	0x05, 0x09,         /*          Usage Page (Button),        */
421	0x75, 0x01,         /*          Report Size (1),            */
422	0x95, 0x03,         /*          Report Count (3),           */
423	0x19, 0x01,         /*          Usage Minimum (01h),        */
424	0x29, 0x03,         /*          Usage Maximum (03h),        */
425	0x14,               /*          Logical Minimum (0),        */
426	0x25, 0x01,         /*          Logical Maximum (1),        */
427	0x81, 0x02,         /*          Input (Variable),           */
428	0x95, 0x05,         /*          Report Count (5),           */
429	0x81, 0x03,         /*          Input (Constant, Variable), */
430	0x05, 0x01,         /*          Usage Page (Desktop),       */
431	0x09, 0x30,         /*          Usage (X),                  */
432	0x09, 0x31,         /*          Usage (Y),                  */
433	0x16, 0x00, 0x80,   /*          Logical Minimum (-32768),   */
434	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
435	0x75, 0x10,         /*          Report Size (16),           */
436	0x95, 0x02,         /*          Report Count (2),           */
437	0x81, 0x06,         /*          Input (Variable, Relative), */
438	0x09, 0x38,         /*          Usage (Wheel),              */
439	0x15, 0xFF,         /*          Logical Minimum (-1),       */
440	0x25, 0x01,         /*          Logical Maximum (1),        */
441	0x95, 0x01,         /*          Report Count (1),           */
442	0x75, 0x08,         /*          Report Size (8),            */
443	0x81, 0x06,         /*          Input (Variable, Relative), */
444	0x81, 0x03,         /*          Input (Constant, Variable), */
445	0xC0,               /*      End Collection,                 */
446	0xC0                /*  End Collection                      */
447};
448
449/* Fixed PID 0522 tablet report descriptor, interface 2 (frame buttons) */
450static __u8 twhl850_rdesc_fixed2[] = {
451	0x05, 0x01,         /*  Usage Page (Desktop),               */
452	0x09, 0x06,         /*  Usage (Keyboard),                   */
453	0xA1, 0x01,         /*  Collection (Application),           */
454	0x85, 0x03,         /*      Report ID (3),                  */
455	0x05, 0x07,         /*      Usage Page (Keyboard),          */
456	0x14,               /*      Logical Minimum (0),            */
457	0x19, 0xE0,         /*      Usage Minimum (KB Leftcontrol), */
458	0x29, 0xE7,         /*      Usage Maximum (KB Right GUI),   */
459	0x25, 0x01,         /*      Logical Maximum (1),            */
460	0x75, 0x01,         /*      Report Size (1),                */
461	0x95, 0x08,         /*      Report Count (8),               */
462	0x81, 0x02,         /*      Input (Variable),               */
463	0x18,               /*      Usage Minimum (None),           */
464	0x29, 0xFF,         /*      Usage Maximum (FFh),            */
465	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
466	0x75, 0x08,         /*      Report Size (8),                */
467	0x95, 0x06,         /*      Report Count (6),               */
468	0x80,               /*      Input,                          */
469	0xC0                /*  End Collection                      */
470};
471
472/*
473 * See TWHA60 description, device and HID report descriptors at
474 * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_TWHA60
475 */
476
477/* Size of the original descriptors of TWHA60 tablet */
478#define TWHA60_RDESC_ORIG_SIZE0 254
479#define TWHA60_RDESC_ORIG_SIZE1 139
480
481/* Fixed TWHA60 report descriptor, interface 0 (stylus) */
482static __u8 twha60_rdesc_fixed0[] = {
483	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
484	0x09, 0x02,         /*  Usage (Pen),                        */
485	0xA1, 0x01,         /*  Collection (Application),           */
486	0x85, 0x09,         /*      Report ID (9),                  */
487	0x09, 0x20,         /*      Usage (Stylus),                 */
488	0xA0,               /*      Collection (Physical),          */
489	0x75, 0x01,         /*          Report Size (1),            */
490	0x09, 0x42,         /*          Usage (Tip Switch),         */
491	0x09, 0x44,         /*          Usage (Barrel Switch),      */
492	0x09, 0x46,         /*          Usage (Tablet Pick),        */
493	0x14,               /*          Logical Minimum (0),        */
494	0x25, 0x01,         /*          Logical Maximum (1),        */
495	0x95, 0x03,         /*          Report Count (3),           */
496	0x81, 0x02,         /*          Input (Variable),           */
497	0x95, 0x04,         /*          Report Count (4),           */
498	0x81, 0x01,         /*          Input (Constant),           */
499	0x09, 0x32,         /*          Usage (In Range),           */
500	0x95, 0x01,         /*          Report Count (1),           */
501	0x81, 0x02,         /*          Input (Variable),           */
502	0x75, 0x10,         /*          Report Size (16),           */
503	0x95, 0x01,         /*          Report Count (1),           */
504	0x14,               /*          Logical Minimum (0),        */
505	0xA4,               /*          Push,                       */
506	0x05, 0x01,         /*          Usage Page (Desktop),       */
507	0x55, 0xFD,         /*          Unit Exponent (-3),         */
508	0x65, 0x13,         /*          Unit (Inch),                */
509	0x34,               /*          Physical Minimum (0),       */
510	0x09, 0x30,         /*          Usage (X),                  */
511	0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
512	0x27, 0x3F, 0x9C,
513		0x00, 0x00, /*          Logical Maximum (39999),    */
514	0x81, 0x02,         /*          Input (Variable),           */
515	0x09, 0x31,         /*          Usage (Y),                  */
516	0x46, 0x6A, 0x18,   /*          Physical Maximum (6250),    */
517	0x26, 0xA7, 0x61,   /*          Logical Maximum (24999),    */
518	0x81, 0x02,         /*          Input (Variable),           */
519	0xB4,               /*          Pop,                        */
520	0x09, 0x30,         /*          Usage (Tip Pressure),       */
521	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
522	0x81, 0x02,         /*          Input (Variable),           */
523	0xC0,               /*      End Collection,                 */
524	0xC0                /*  End Collection                      */
525};
526
527/* Fixed TWHA60 report descriptor, interface 1 (frame buttons) */
528static __u8 twha60_rdesc_fixed1[] = {
529	0x05, 0x01, /*  Usage Page (Desktop),       */
530	0x09, 0x06, /*  Usage (Keyboard),           */
531	0xA1, 0x01, /*  Collection (Application),   */
532	0x85, 0x05, /*      Report ID (5),          */
533	0x05, 0x07, /*      Usage Page (Keyboard),  */
534	0x14,       /*      Logical Minimum (0),    */
535	0x25, 0x01, /*      Logical Maximum (1),    */
536	0x75, 0x01, /*      Report Size (1),        */
537	0x95, 0x08, /*      Report Count (8),       */
538	0x81, 0x01, /*      Input (Constant),       */
539	0x95, 0x0C, /*      Report Count (12),      */
540	0x19, 0x3A, /*      Usage Minimum (KB F1),  */
541	0x29, 0x45, /*      Usage Maximum (KB F12), */
542	0x81, 0x02, /*      Input (Variable),       */
543	0x95, 0x0C, /*      Report Count (12),      */
544	0x19, 0x68, /*      Usage Minimum (KB F13), */
545	0x29, 0x73, /*      Usage Maximum (KB F24), */
546	0x81, 0x02, /*      Input (Variable),       */
547	0x95, 0x08, /*      Report Count (8),       */
548	0x81, 0x01, /*      Input (Constant),       */
549	0xC0        /*  End Collection              */
550};
551
552/* Report descriptor template placeholder head */
553#define UCLOGIC_PH_HEAD	0xFE, 0xED, 0x1D
554
555/* Report descriptor template placeholder IDs */
556enum uclogic_ph_id {
557	UCLOGIC_PH_ID_X_LM,
558	UCLOGIC_PH_ID_X_PM,
559	UCLOGIC_PH_ID_Y_LM,
560	UCLOGIC_PH_ID_Y_PM,
561	UCLOGIC_PH_ID_PRESSURE_LM,
562	UCLOGIC_PH_ID_NUM
563};
564
565/* Report descriptor template placeholder */
566#define UCLOGIC_PH(_ID) UCLOGIC_PH_HEAD, UCLOGIC_PH_ID_##_ID
567#define UCLOGIC_PEN_REPORT_ID	0x07
568
569/* Fixed report descriptor template */
570static const __u8 uclogic_tablet_rdesc_template[] = {
571	0x05, 0x0D,             /*  Usage Page (Digitizer),                 */
572	0x09, 0x02,             /*  Usage (Pen),                            */
573	0xA1, 0x01,             /*  Collection (Application),               */
574	0x85, 0x07,             /*      Report ID (7),                      */
575	0x09, 0x20,             /*      Usage (Stylus),                     */
576	0xA0,                   /*      Collection (Physical),              */
577	0x14,                   /*          Logical Minimum (0),            */
578	0x25, 0x01,             /*          Logical Maximum (1),            */
579	0x75, 0x01,             /*          Report Size (1),                */
580	0x09, 0x42,             /*          Usage (Tip Switch),             */
581	0x09, 0x44,             /*          Usage (Barrel Switch),          */
582	0x09, 0x46,             /*          Usage (Tablet Pick),            */
583	0x95, 0x03,             /*          Report Count (3),               */
584	0x81, 0x02,             /*          Input (Variable),               */
585	0x95, 0x03,             /*          Report Count (3),               */
586	0x81, 0x03,             /*          Input (Constant, Variable),     */
587	0x09, 0x32,             /*          Usage (In Range),               */
588	0x95, 0x01,             /*          Report Count (1),               */
589	0x81, 0x02,             /*          Input (Variable),               */
590	0x95, 0x01,             /*          Report Count (1),               */
591	0x81, 0x03,             /*          Input (Constant, Variable),     */
592	0x75, 0x10,             /*          Report Size (16),               */
593	0x95, 0x01,             /*          Report Count (1),               */
594	0xA4,                   /*          Push,                           */
595	0x05, 0x01,             /*          Usage Page (Desktop),           */
596	0x65, 0x13,             /*          Unit (Inch),                    */
597	0x55, 0xFD,             /*          Unit Exponent (-3),             */
598	0x34,                   /*          Physical Minimum (0),           */
599	0x09, 0x30,             /*          Usage (X),                      */
600	0x27, UCLOGIC_PH(X_LM), /*          Logical Maximum (PLACEHOLDER),  */
601	0x47, UCLOGIC_PH(X_PM), /*          Physical Maximum (PLACEHOLDER), */
602	0x81, 0x02,             /*          Input (Variable),               */
603	0x09, 0x31,             /*          Usage (Y),                      */
604	0x27, UCLOGIC_PH(Y_LM), /*          Logical Maximum (PLACEHOLDER),  */
605	0x47, UCLOGIC_PH(Y_PM), /*          Physical Maximum (PLACEHOLDER), */
606	0x81, 0x02,             /*          Input (Variable),               */
607	0xB4,                   /*          Pop,                            */
608	0x09, 0x30,             /*          Usage (Tip Pressure),           */
609	0x27,
610	UCLOGIC_PH(PRESSURE_LM),/*          Logical Maximum (PLACEHOLDER),  */
611	0x81, 0x02,             /*          Input (Variable),               */
612	0xC0,                   /*      End Collection,                     */
613	0xC0                    /*  End Collection                          */
614};
615
616/* Parameter indices */
617enum uclogic_prm {
618	UCLOGIC_PRM_X_LM	= 1,
619	UCLOGIC_PRM_Y_LM	= 2,
620	UCLOGIC_PRM_PRESSURE_LM	= 4,
621	UCLOGIC_PRM_RESOLUTION	= 5,
622	UCLOGIC_PRM_NUM
623};
624
625/* Driver data */
626struct uclogic_drvdata {
627	__u8 *rdesc;
628	unsigned int rsize;
629	bool invert_pen_inrange;
630	bool ignore_pen_usage;
631};
632
633static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
634					unsigned int *rsize)
635{
636	struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
637	__u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
638	struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
639
640	switch (hdev->product) {
641	case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209:
642		if (*rsize == PF1209_RDESC_ORIG_SIZE) {
643			rdesc = pf1209_rdesc_fixed;
644			*rsize = sizeof(pf1209_rdesc_fixed);
645		}
646		break;
647	case USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U:
648		if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
649			rdesc = wp4030u_rdesc_fixed;
650			*rsize = sizeof(wp4030u_rdesc_fixed);
651		}
652		break;
653	case USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U:
654		if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
655			rdesc = wp5540u_rdesc_fixed;
656			*rsize = sizeof(wp5540u_rdesc_fixed);
657		}
658		break;
659	case USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U:
660		if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
661			rdesc = wp8060u_rdesc_fixed;
662			*rsize = sizeof(wp8060u_rdesc_fixed);
663		}
664		break;
665	case USB_DEVICE_ID_UCLOGIC_TABLET_WP1062:
666		if (*rsize == WP1062_RDESC_ORIG_SIZE) {
667			rdesc = wp1062_rdesc_fixed;
668			*rsize = sizeof(wp1062_rdesc_fixed);
669		}
670		break;
671	case USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850:
672		switch (iface_num) {
673		case 0:
674			if (*rsize == TWHL850_RDESC_ORIG_SIZE0) {
675				rdesc = twhl850_rdesc_fixed0;
676				*rsize = sizeof(twhl850_rdesc_fixed0);
677			}
678			break;
679		case 1:
680			if (*rsize == TWHL850_RDESC_ORIG_SIZE1) {
681				rdesc = twhl850_rdesc_fixed1;
682				*rsize = sizeof(twhl850_rdesc_fixed1);
683			}
684			break;
685		case 2:
686			if (*rsize == TWHL850_RDESC_ORIG_SIZE2) {
687				rdesc = twhl850_rdesc_fixed2;
688				*rsize = sizeof(twhl850_rdesc_fixed2);
689			}
690			break;
691		}
692		break;
693	case USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60:
694		switch (iface_num) {
695		case 0:
696			if (*rsize == TWHA60_RDESC_ORIG_SIZE0) {
697				rdesc = twha60_rdesc_fixed0;
698				*rsize = sizeof(twha60_rdesc_fixed0);
699			}
700			break;
701		case 1:
702			if (*rsize == TWHA60_RDESC_ORIG_SIZE1) {
703				rdesc = twha60_rdesc_fixed1;
704				*rsize = sizeof(twha60_rdesc_fixed1);
705			}
706			break;
707		}
708		break;
709	default:
710		if (drvdata->rdesc != NULL) {
711			rdesc = drvdata->rdesc;
712			*rsize = drvdata->rsize;
713		}
714	}
715
716	return rdesc;
717}
718
719static int uclogic_input_mapping(struct hid_device *hdev, struct hid_input *hi,
720		struct hid_field *field, struct hid_usage *usage,
721		unsigned long **bit, int *max)
722{
723	struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
724
725	/* discard the unused pen interface */
726	if ((drvdata->ignore_pen_usage) &&
727	    (field->application == HID_DG_PEN))
728		return -1;
729
730	/* let hid-core decide what to do */
731	return 0;
732}
733
734static int uclogic_input_configured(struct hid_device *hdev,
735		struct hid_input *hi)
736{
737	char *name;
738	const char *suffix = NULL;
739	struct hid_field *field;
740	size_t len;
741
742	/* no report associated (HID_QUIRK_MULTI_INPUT not set) */
743	if (!hi->report)
744		return 0;
745
746	field = hi->report->field[0];
747
748	switch (field->application) {
749	case HID_GD_KEYBOARD:
750		suffix = "Keyboard";
751		break;
752	case HID_GD_MOUSE:
753		suffix = "Mouse";
754		break;
755	case HID_GD_KEYPAD:
756		suffix = "Pad";
757		break;
758	case HID_DG_PEN:
759		suffix = "Pen";
760		break;
761	case HID_CP_CONSUMER_CONTROL:
762		suffix = "Consumer Control";
763		break;
764	case HID_GD_SYSTEM_CONTROL:
765		suffix = "System Control";
766		break;
767	}
768
769	if (suffix) {
770		len = strlen(hdev->name) + 2 + strlen(suffix);
771		name = devm_kzalloc(&hi->input->dev, len, GFP_KERNEL);
772		if (name) {
773			snprintf(name, len, "%s %s", hdev->name, suffix);
774			hi->input->name = name;
775		}
776	}
777
778	return 0;
779}
780
781/**
782 * Enable fully-functional tablet mode and determine device parameters.
783 *
784 * @hdev:	HID device
785 */
786static int uclogic_tablet_enable(struct hid_device *hdev)
787{
788	int rc;
789	struct usb_device *usb_dev = hid_to_usb_dev(hdev);
790	struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
791	__le16 *buf = NULL;
792	size_t len;
793	s32 params[UCLOGIC_PH_ID_NUM];
794	s32 resolution;
795	__u8 *p;
796	s32 v;
797
798	/*
799	 * Read string descriptor containing tablet parameters. The specific
800	 * string descriptor and data were discovered by sniffing the Windows
801	 * driver traffic.
802	 * NOTE: This enables fully-functional tablet mode.
803	 */
804	len = UCLOGIC_PRM_NUM * sizeof(*buf);
805	buf = kmalloc(len, GFP_KERNEL);
806	if (buf == NULL) {
807		hid_err(hdev, "failed to allocate parameter buffer\n");
808		rc = -ENOMEM;
809		goto cleanup;
810	}
811	rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
812				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
813				(USB_DT_STRING << 8) + 0x64,
814				0x0409, buf, len,
815				USB_CTRL_GET_TIMEOUT);
816	if (rc == -EPIPE) {
817		hid_err(hdev, "device parameters not found\n");
818		rc = -ENODEV;
819		goto cleanup;
820	} else if (rc < 0) {
821		hid_err(hdev, "failed to get device parameters: %d\n", rc);
822		rc = -ENODEV;
823		goto cleanup;
824	} else if (rc != len) {
825		hid_err(hdev, "invalid device parameters\n");
826		rc = -ENODEV;
827		goto cleanup;
828	}
829
830	/* Extract device parameters */
831	params[UCLOGIC_PH_ID_X_LM] = le16_to_cpu(buf[UCLOGIC_PRM_X_LM]);
832	params[UCLOGIC_PH_ID_Y_LM] = le16_to_cpu(buf[UCLOGIC_PRM_Y_LM]);
833	params[UCLOGIC_PH_ID_PRESSURE_LM] =
834		le16_to_cpu(buf[UCLOGIC_PRM_PRESSURE_LM]);
835	resolution = le16_to_cpu(buf[UCLOGIC_PRM_RESOLUTION]);
836	if (resolution == 0) {
837		params[UCLOGIC_PH_ID_X_PM] = 0;
838		params[UCLOGIC_PH_ID_Y_PM] = 0;
839	} else {
840		params[UCLOGIC_PH_ID_X_PM] = params[UCLOGIC_PH_ID_X_LM] *
841						1000 / resolution;
842		params[UCLOGIC_PH_ID_Y_PM] = params[UCLOGIC_PH_ID_Y_LM] *
843						1000 / resolution;
844	}
845
846	/* Allocate fixed report descriptor */
847	drvdata->rdesc = devm_kzalloc(&hdev->dev,
848				sizeof(uclogic_tablet_rdesc_template),
849				GFP_KERNEL);
850	if (drvdata->rdesc == NULL) {
851		hid_err(hdev, "failed to allocate fixed rdesc\n");
852		rc = -ENOMEM;
853		goto cleanup;
854	}
855	drvdata->rsize = sizeof(uclogic_tablet_rdesc_template);
856
857	/* Format fixed report descriptor */
858	memcpy(drvdata->rdesc, uclogic_tablet_rdesc_template,
859		drvdata->rsize);
860	for (p = drvdata->rdesc;
861	     p <= drvdata->rdesc + drvdata->rsize - 4;) {
862		if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
863		    p[3] < ARRAY_SIZE(params)) {
864			v = params[p[3]];
865			put_unaligned(cpu_to_le32(v), (s32 *)p);
866			p += 4;
867		} else {
868			p++;
869		}
870	}
871
872	rc = 0;
873
874cleanup:
875	kfree(buf);
876	return rc;
877}
878
879static int uclogic_probe(struct hid_device *hdev,
880		const struct hid_device_id *id)
881{
882	int rc;
883	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
884	struct uclogic_drvdata *drvdata;
885
886	/*
887	 * libinput requires the pad interface to be on a different node
888	 * than the pen, so use QUIRK_MULTI_INPUT for all tablets.
889	 */
890	hdev->quirks |= HID_QUIRK_MULTI_INPUT;
891	hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
892
893	/* Allocate and assign driver data */
894	drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
895	if (drvdata == NULL)
896		return -ENOMEM;
897
898	hid_set_drvdata(hdev, drvdata);
899
900	switch (id->product) {
901	case USB_DEVICE_ID_HUION_TABLET:
902		/* If this is the pen interface */
903		if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
904			rc = uclogic_tablet_enable(hdev);
905			if (rc) {
906				hid_err(hdev, "tablet enabling failed\n");
907				return rc;
908			}
909			drvdata->invert_pen_inrange = true;
910		} else {
911			drvdata->ignore_pen_usage = true;
912		}
913		break;
914	}
915
916	rc = hid_parse(hdev);
917	if (rc) {
918		hid_err(hdev, "parse failed\n");
919		return rc;
920	}
921
922	rc = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
923	if (rc) {
924		hid_err(hdev, "hw start failed\n");
925		return rc;
926	}
927
928	return 0;
929}
930
931static int uclogic_raw_event(struct hid_device *hdev, struct hid_report *report,
932			u8 *data, int size)
933{
934	struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
935
936	if ((drvdata->invert_pen_inrange) &&
937	    (report->type == HID_INPUT_REPORT) &&
938	    (report->id == UCLOGIC_PEN_REPORT_ID) &&
939	    (size >= 2))
940		/* Invert the in-range bit */
941		data[1] ^= 0x40;
942
943	return 0;
944}
945
946static const struct hid_device_id uclogic_devices[] = {
947	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
948				USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) },
949	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
950				USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
951	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
952				USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
953	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
954				USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
955	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
956				USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
957	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
958				USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
959	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
960				USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) },
961	{ HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
962	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET) },
963	{ }
964};
965MODULE_DEVICE_TABLE(hid, uclogic_devices);
966
967static struct hid_driver uclogic_driver = {
968	.name = "uclogic",
969	.id_table = uclogic_devices,
970	.probe = uclogic_probe,
971	.report_fixup = uclogic_report_fixup,
972	.raw_event = uclogic_raw_event,
973	.input_mapping = uclogic_input_mapping,
974	.input_configured = uclogic_input_configured,
975};
976module_hid_driver(uclogic_driver);
977
978MODULE_AUTHOR("Martin Rusko");
979MODULE_AUTHOR("Nikolai Kondrashov");
 
 
 
 
 
 
 
 
 
 
980MODULE_LICENSE("GPL");