Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  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#include <linux/usb.h>
 18
 19#include "hid-ids.h"
 20
 21/*
 22 * See WPXXXXU model descriptions, device and HID report descriptors at
 23 * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP4030U
 24 * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP5540U
 25 * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP8060U
 26 */
 27
 28/* Size of the original descriptor of WPXXXXU tablets */
 29#define WPXXXXU_RDESC_ORIG_SIZE	212
 30
 31/* Fixed WP4030U report descriptor */
 32static __u8 wp4030u_rdesc_fixed[] = {
 33	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
 34	0x09, 0x02,         /*  Usage (Pen),                        */
 35	0xA1, 0x01,         /*  Collection (Application),           */
 36	0x85, 0x09,         /*      Report ID (9),                  */
 37	0x09, 0x20,         /*      Usage (Stylus),                 */
 38	0xA0,               /*      Collection (Physical),          */
 39	0x75, 0x01,         /*          Report Size (1),            */
 40	0x09, 0x42,         /*          Usage (Tip Switch),         */
 41	0x09, 0x44,         /*          Usage (Barrel Switch),      */
 42	0x09, 0x46,         /*          Usage (Tablet Pick),        */
 43	0x14,               /*          Logical Minimum (0),        */
 44	0x25, 0x01,         /*          Logical Maximum (1),        */
 45	0x95, 0x03,         /*          Report Count (3),           */
 46	0x81, 0x02,         /*          Input (Variable),           */
 47	0x95, 0x05,         /*          Report Count (5),           */
 48	0x81, 0x01,         /*          Input (Constant),           */
 49	0x75, 0x10,         /*          Report Size (16),           */
 50	0x95, 0x01,         /*          Report Count (1),           */
 51	0x14,               /*          Logical Minimum (0),        */
 52	0xA4,               /*          Push,                       */
 53	0x05, 0x01,         /*          Usage Page (Desktop),       */
 54	0x55, 0xFD,         /*          Unit Exponent (-3),         */
 55	0x65, 0x13,         /*          Unit (Inch),                */
 56	0x34,               /*          Physical Minimum (0),       */
 57	0x09, 0x30,         /*          Usage (X),                  */
 58	0x46, 0xA0, 0x0F,   /*          Physical Maximum (4000),    */
 59	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
 60	0x81, 0x02,         /*          Input (Variable),           */
 61	0x09, 0x31,         /*          Usage (Y),                  */
 62	0x46, 0xB8, 0x0B,   /*          Physical Maximum (3000),    */
 63	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
 64	0x81, 0x02,         /*          Input (Variable),           */
 65	0xB4,               /*          Pop,                        */
 66	0x09, 0x30,         /*          Usage (Tip Pressure),       */
 67	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
 68	0x81, 0x02,         /*          Input (Variable),           */
 69	0xC0,               /*      End Collection,                 */
 70	0xC0                /*  End Collection                      */
 71};
 72
 73/* Fixed WP5540U report descriptor */
 74static __u8 wp5540u_rdesc_fixed[] = {
 75	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
 76	0x09, 0x02,         /*  Usage (Pen),                        */
 77	0xA1, 0x01,         /*  Collection (Application),           */
 78	0x85, 0x09,         /*      Report ID (9),                  */
 79	0x09, 0x20,         /*      Usage (Stylus),                 */
 80	0xA0,               /*      Collection (Physical),          */
 81	0x75, 0x01,         /*          Report Size (1),            */
 82	0x09, 0x42,         /*          Usage (Tip Switch),         */
 83	0x09, 0x44,         /*          Usage (Barrel Switch),      */
 84	0x09, 0x46,         /*          Usage (Tablet Pick),        */
 85	0x14,               /*          Logical Minimum (0),        */
 86	0x25, 0x01,         /*          Logical Maximum (1),        */
 87	0x95, 0x03,         /*          Report Count (3),           */
 88	0x81, 0x02,         /*          Input (Variable),           */
 89	0x95, 0x05,         /*          Report Count (5),           */
 90	0x81, 0x01,         /*          Input (Constant),           */
 91	0x75, 0x10,         /*          Report Size (16),           */
 92	0x95, 0x01,         /*          Report Count (1),           */
 93	0x14,               /*          Logical Minimum (0),        */
 94	0xA4,               /*          Push,                       */
 95	0x05, 0x01,         /*          Usage Page (Desktop),       */
 96	0x55, 0xFD,         /*          Unit Exponent (-3),         */
 97	0x65, 0x13,         /*          Unit (Inch),                */
 98	0x34,               /*          Physical Minimum (0),       */
 99	0x09, 0x30,         /*          Usage (X),                  */
100	0x46, 0x7C, 0x15,   /*          Physical Maximum (5500),    */
101	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
102	0x81, 0x02,         /*          Input (Variable),           */
103	0x09, 0x31,         /*          Usage (Y),                  */
104	0x46, 0xA0, 0x0F,   /*          Physical Maximum (4000),    */
105	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
106	0x81, 0x02,         /*          Input (Variable),           */
107	0xB4,               /*          Pop,                        */
108	0x09, 0x30,         /*          Usage (Tip Pressure),       */
109	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
110	0x81, 0x02,         /*          Input (Variable),           */
111	0xC0,               /*      End Collection,                 */
112	0xC0,               /*  End Collection,                     */
113	0x05, 0x01,         /*  Usage Page (Desktop),               */
114	0x09, 0x02,         /*  Usage (Mouse),                      */
115	0xA1, 0x01,         /*  Collection (Application),           */
116	0x85, 0x08,         /*      Report ID (8),                  */
117	0x09, 0x01,         /*      Usage (Pointer),                */
118	0xA0,               /*      Collection (Physical),          */
119	0x75, 0x01,         /*          Report Size (1),            */
120	0x05, 0x09,         /*          Usage Page (Button),        */
121	0x19, 0x01,         /*          Usage Minimum (01h),        */
122	0x29, 0x03,         /*          Usage Maximum (03h),        */
123	0x14,               /*          Logical Minimum (0),        */
124	0x25, 0x01,         /*          Logical Maximum (1),        */
125	0x95, 0x03,         /*          Report Count (3),           */
126	0x81, 0x02,         /*          Input (Variable),           */
127	0x95, 0x05,         /*          Report Count (5),           */
128	0x81, 0x01,         /*          Input (Constant),           */
129	0x05, 0x01,         /*          Usage Page (Desktop),       */
130	0x75, 0x08,         /*          Report Size (8),            */
131	0x09, 0x30,         /*          Usage (X),                  */
132	0x09, 0x31,         /*          Usage (Y),                  */
133	0x15, 0x81,         /*          Logical Minimum (-127),     */
134	0x25, 0x7F,         /*          Logical Maximum (127),      */
135	0x95, 0x02,         /*          Report Count (2),           */
136	0x81, 0x06,         /*          Input (Variable, Relative), */
137	0x09, 0x38,         /*          Usage (Wheel),              */
138	0x15, 0xFF,         /*          Logical Minimum (-1),       */
139	0x25, 0x01,         /*          Logical Maximum (1),        */
140	0x95, 0x01,         /*          Report Count (1),           */
141	0x81, 0x06,         /*          Input (Variable, Relative), */
142	0x81, 0x01,         /*          Input (Constant),           */
143	0xC0,               /*      End Collection,                 */
144	0xC0                /*  End Collection                      */
145};
146
147/* Fixed WP8060U report descriptor */
148static __u8 wp8060u_rdesc_fixed[] = {
149	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
150	0x09, 0x02,         /*  Usage (Pen),                        */
151	0xA1, 0x01,         /*  Collection (Application),           */
152	0x85, 0x09,         /*      Report ID (9),                  */
153	0x09, 0x20,         /*      Usage (Stylus),                 */
154	0xA0,               /*      Collection (Physical),          */
155	0x75, 0x01,         /*          Report Size (1),            */
156	0x09, 0x42,         /*          Usage (Tip Switch),         */
157	0x09, 0x44,         /*          Usage (Barrel Switch),      */
158	0x09, 0x46,         /*          Usage (Tablet Pick),        */
159	0x14,               /*          Logical Minimum (0),        */
160	0x25, 0x01,         /*          Logical Maximum (1),        */
161	0x95, 0x03,         /*          Report Count (3),           */
162	0x81, 0x02,         /*          Input (Variable),           */
163	0x95, 0x05,         /*          Report Count (5),           */
164	0x81, 0x01,         /*          Input (Constant),           */
165	0x75, 0x10,         /*          Report Size (16),           */
166	0x95, 0x01,         /*          Report Count (1),           */
167	0x14,               /*          Logical Minimum (0),        */
168	0xA4,               /*          Push,                       */
169	0x05, 0x01,         /*          Usage Page (Desktop),       */
170	0x55, 0xFD,         /*          Unit Exponent (-3),         */
171	0x65, 0x13,         /*          Unit (Inch),                */
172	0x34,               /*          Physical Minimum (0),       */
173	0x09, 0x30,         /*          Usage (X),                  */
174	0x46, 0x40, 0x1F,   /*          Physical Maximum (8000),    */
175	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
176	0x81, 0x02,         /*          Input (Variable),           */
177	0x09, 0x31,         /*          Usage (Y),                  */
178	0x46, 0x70, 0x17,   /*          Physical Maximum (6000),    */
179	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
180	0x81, 0x02,         /*          Input (Variable),           */
181	0xB4,               /*          Pop,                        */
182	0x09, 0x30,         /*          Usage (Tip Pressure),       */
183	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
184	0x81, 0x02,         /*          Input (Variable),           */
185	0xC0,               /*      End Collection,                 */
186	0xC0,               /*  End Collection,                     */
187	0x05, 0x01,         /*  Usage Page (Desktop),               */
188	0x09, 0x02,         /*  Usage (Mouse),                      */
189	0xA1, 0x01,         /*  Collection (Application),           */
190	0x85, 0x08,         /*      Report ID (8),                  */
191	0x09, 0x01,         /*      Usage (Pointer),                */
192	0xA0,               /*      Collection (Physical),          */
193	0x75, 0x01,         /*          Report Size (1),            */
194	0x05, 0x09,         /*          Usage Page (Button),        */
195	0x19, 0x01,         /*          Usage Minimum (01h),        */
196	0x29, 0x03,         /*          Usage Maximum (03h),        */
197	0x14,               /*          Logical Minimum (0),        */
198	0x25, 0x01,         /*          Logical Maximum (1),        */
199	0x95, 0x03,         /*          Report Count (3),           */
200	0x81, 0x02,         /*          Input (Variable),           */
201	0x95, 0x05,         /*          Report Count (5),           */
202	0x81, 0x01,         /*          Input (Constant),           */
203	0x05, 0x01,         /*          Usage Page (Desktop),       */
204	0x75, 0x08,         /*          Report Size (8),            */
205	0x09, 0x30,         /*          Usage (X),                  */
206	0x09, 0x31,         /*          Usage (Y),                  */
207	0x15, 0x81,         /*          Logical Minimum (-127),     */
208	0x25, 0x7F,         /*          Logical Maximum (127),      */
209	0x95, 0x02,         /*          Report Count (2),           */
210	0x81, 0x06,         /*          Input (Variable, Relative), */
211	0x09, 0x38,         /*          Usage (Wheel),              */
212	0x15, 0xFF,         /*          Logical Minimum (-1),       */
213	0x25, 0x01,         /*          Logical Maximum (1),        */
214	0x95, 0x01,         /*          Report Count (1),           */
215	0x81, 0x06,         /*          Input (Variable, Relative), */
216	0x81, 0x01,         /*          Input (Constant),           */
217	0xC0,               /*      End Collection,                 */
218	0xC0                /*  End Collection                      */
219};
220
221/*
222 * See WP1062 description, device and HID report descriptors at
223 * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP1062
224 */
225
226/* Size of the original descriptor of WP1062 tablet */
227#define WP1062_RDESC_ORIG_SIZE	254
228
229/* Fixed WP1062 report descriptor */
230static __u8 wp1062_rdesc_fixed[] = {
231	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
232	0x09, 0x02,         /*  Usage (Pen),                        */
233	0xA1, 0x01,         /*  Collection (Application),           */
234	0x85, 0x09,         /*      Report ID (9),                  */
235	0x09, 0x20,         /*      Usage (Stylus),                 */
236	0xA0,               /*      Collection (Physical),          */
237	0x75, 0x01,         /*          Report Size (1),            */
238	0x09, 0x42,         /*          Usage (Tip Switch),         */
239	0x09, 0x44,         /*          Usage (Barrel Switch),      */
240	0x09, 0x46,         /*          Usage (Tablet Pick),        */
241	0x14,               /*          Logical Minimum (0),        */
242	0x25, 0x01,         /*          Logical Maximum (1),        */
243	0x95, 0x03,         /*          Report Count (3),           */
244	0x81, 0x02,         /*          Input (Variable),           */
245	0x95, 0x04,         /*          Report Count (4),           */
246	0x81, 0x01,         /*          Input (Constant),           */
247	0x09, 0x32,         /*          Usage (In Range),           */
248	0x95, 0x01,         /*          Report Count (1),           */
249	0x81, 0x02,         /*          Input (Variable),           */
250	0x75, 0x10,         /*          Report Size (16),           */
251	0x95, 0x01,         /*          Report Count (1),           */
252	0x14,               /*          Logical Minimum (0),        */
253	0xA4,               /*          Push,                       */
254	0x05, 0x01,         /*          Usage Page (Desktop),       */
255	0x55, 0xFD,         /*          Unit Exponent (-3),         */
256	0x65, 0x13,         /*          Unit (Inch),                */
257	0x34,               /*          Physical Minimum (0),       */
258	0x09, 0x30,         /*          Usage (X),                  */
259	0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
260	0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
261	0x81, 0x02,         /*          Input (Variable),           */
262	0x09, 0x31,         /*          Usage (Y),                  */
263	0x46, 0xB7, 0x19,   /*          Physical Maximum (6583),    */
264	0x26, 0x6E, 0x33,   /*          Logical Maximum (13166),    */
265	0x81, 0x02,         /*          Input (Variable),           */
266	0xB4,               /*          Pop,                        */
267	0x09, 0x30,         /*          Usage (Tip Pressure),       */
268	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
269	0x81, 0x02,         /*          Input (Variable),           */
270	0xC0,               /*      End Collection,                 */
271	0xC0                /*  End Collection                      */
272};
273
274/*
275 * See PF1209 description, device and HID report descriptors at
276 * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_PF1209
277 */
278
279/* Size of the original descriptor of PF1209 tablet */
280#define PF1209_RDESC_ORIG_SIZE	234
281
282/* Fixed PF1209 report descriptor */
283static __u8 pf1209_rdesc_fixed[] = {
284	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
285	0x09, 0x02,         /*  Usage (Pen),                        */
286	0xA1, 0x01,         /*  Collection (Application),           */
287	0x85, 0x09,         /*      Report ID (9),                  */
288	0x09, 0x20,         /*      Usage (Stylus),                 */
289	0xA0,               /*      Collection (Physical),          */
290	0x75, 0x01,         /*          Report Size (1),            */
291	0x09, 0x42,         /*          Usage (Tip Switch),         */
292	0x09, 0x44,         /*          Usage (Barrel Switch),      */
293	0x09, 0x46,         /*          Usage (Tablet Pick),        */
294	0x14,               /*          Logical Minimum (0),        */
295	0x25, 0x01,         /*          Logical Maximum (1),        */
296	0x95, 0x03,         /*          Report Count (3),           */
297	0x81, 0x02,         /*          Input (Variable),           */
298	0x95, 0x05,         /*          Report Count (5),           */
299	0x81, 0x01,         /*          Input (Constant),           */
300	0x75, 0x10,         /*          Report Size (16),           */
301	0x95, 0x01,         /*          Report Count (1),           */
302	0x14,               /*          Logical Minimum (0),        */
303	0xA4,               /*          Push,                       */
304	0x05, 0x01,         /*          Usage Page (Desktop),       */
305	0x55, 0xFD,         /*          Unit Exponent (-3),         */
306	0x65, 0x13,         /*          Unit (Inch),                */
307	0x34,               /*          Physical Minimum (0),       */
308	0x09, 0x30,         /*          Usage (X),                  */
309	0x46, 0xE0, 0x2E,   /*          Physical Maximum (12000),   */
310	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
311	0x81, 0x02,         /*          Input (Variable),           */
312	0x09, 0x31,         /*          Usage (Y),                  */
313	0x46, 0x28, 0x23,   /*          Physical Maximum (9000),    */
314	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
315	0x81, 0x02,         /*          Input (Variable),           */
316	0xB4,               /*          Pop,                        */
317	0x09, 0x30,         /*          Usage (Tip Pressure),       */
318	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
319	0x81, 0x02,         /*          Input (Variable),           */
320	0xC0,               /*      End Collection,                 */
321	0xC0,               /*  End Collection,                     */
322	0x05, 0x01,         /*  Usage Page (Desktop),               */
323	0x09, 0x02,         /*  Usage (Mouse),                      */
324	0xA1, 0x01,         /*  Collection (Application),           */
325	0x85, 0x08,         /*      Report ID (8),                  */
326	0x09, 0x01,         /*      Usage (Pointer),                */
327	0xA0,               /*      Collection (Physical),          */
328	0x75, 0x01,         /*          Report Size (1),            */
329	0x05, 0x09,         /*          Usage Page (Button),        */
330	0x19, 0x01,         /*          Usage Minimum (01h),        */
331	0x29, 0x03,         /*          Usage Maximum (03h),        */
332	0x14,               /*          Logical Minimum (0),        */
333	0x25, 0x01,         /*          Logical Maximum (1),        */
334	0x95, 0x03,         /*          Report Count (3),           */
335	0x81, 0x02,         /*          Input (Variable),           */
336	0x95, 0x05,         /*          Report Count (5),           */
337	0x81, 0x01,         /*          Input (Constant),           */
338	0x05, 0x01,         /*          Usage Page (Desktop),       */
339	0x75, 0x08,         /*          Report Size (8),            */
340	0x09, 0x30,         /*          Usage (X),                  */
341	0x09, 0x31,         /*          Usage (Y),                  */
342	0x15, 0x81,         /*          Logical Minimum (-127),     */
343	0x25, 0x7F,         /*          Logical Maximum (127),      */
344	0x95, 0x02,         /*          Report Count (2),           */
345	0x81, 0x06,         /*          Input (Variable, Relative), */
346	0x09, 0x38,         /*          Usage (Wheel),              */
347	0x15, 0xFF,         /*          Logical Minimum (-1),       */
348	0x25, 0x01,         /*          Logical Maximum (1),        */
349	0x95, 0x01,         /*          Report Count (1),           */
350	0x81, 0x06,         /*          Input (Variable, Relative), */
351	0x81, 0x01,         /*          Input (Constant),           */
352	0xC0,               /*      End Collection,                 */
353	0xC0                /*  End Collection                      */
354};
355
356/*
357 * See TWHL850 description, device and HID report descriptors at
358 * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Wireless_Tablet_TWHL850
359 */
360
361/* Size of the original descriptors of TWHL850 tablet */
362#define TWHL850_RDESC_ORIG_SIZE0	182
363#define TWHL850_RDESC_ORIG_SIZE1	161
364#define TWHL850_RDESC_ORIG_SIZE2	92
365
366/* Fixed PID 0522 tablet report descriptor, interface 0 (stylus) */
367static __u8 twhl850_rdesc_fixed0[] = {
368	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
369	0x09, 0x02,         /*  Usage (Pen),                        */
370	0xA1, 0x01,         /*  Collection (Application),           */
371	0x85, 0x09,         /*      Report ID (9),                  */
372	0x09, 0x20,         /*      Usage (Stylus),                 */
373	0xA0,               /*      Collection (Physical),          */
374	0x14,               /*          Logical Minimum (0),        */
375	0x25, 0x01,         /*          Logical Maximum (1),        */
376	0x75, 0x01,         /*          Report Size (1),            */
377	0x95, 0x03,         /*          Report Count (3),           */
378	0x09, 0x42,         /*          Usage (Tip Switch),         */
379	0x09, 0x44,         /*          Usage (Barrel Switch),      */
380	0x09, 0x46,         /*          Usage (Tablet Pick),        */
381	0x81, 0x02,         /*          Input (Variable),           */
382	0x81, 0x03,         /*          Input (Constant, Variable), */
383	0x95, 0x01,         /*          Report Count (1),           */
384	0x09, 0x32,         /*          Usage (In Range),           */
385	0x81, 0x02,         /*          Input (Variable),           */
386	0x81, 0x03,         /*          Input (Constant, Variable), */
387	0x75, 0x10,         /*          Report Size (16),           */
388	0xA4,               /*          Push,                       */
389	0x05, 0x01,         /*          Usage Page (Desktop),       */
390	0x65, 0x13,         /*          Unit (Inch),                */
391	0x55, 0xFD,         /*          Unit Exponent (-3),         */
392	0x34,               /*          Physical Minimum (0),       */
393	0x09, 0x30,         /*          Usage (X),                  */
394	0x46, 0x40, 0x1F,   /*          Physical Maximum (8000),    */
395	0x26, 0x00, 0x7D,   /*          Logical Maximum (32000),    */
396	0x81, 0x02,         /*          Input (Variable),           */
397	0x09, 0x31,         /*          Usage (Y),                  */
398	0x46, 0x88, 0x13,   /*          Physical Maximum (5000),    */
399	0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
400	0x81, 0x02,         /*          Input (Variable),           */
401	0xB4,               /*          Pop,                        */
402	0x09, 0x30,         /*          Usage (Tip Pressure),       */
403	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
404	0x81, 0x02,         /*          Input (Variable),           */
405	0xC0,               /*      End Collection,                 */
406	0xC0                /*  End Collection                      */
407};
408
409/* Fixed PID 0522 tablet report descriptor, interface 1 (mouse) */
410static __u8 twhl850_rdesc_fixed1[] = {
411	0x05, 0x01,         /*  Usage Page (Desktop),               */
412	0x09, 0x02,         /*  Usage (Mouse),                      */
413	0xA1, 0x01,         /*  Collection (Application),           */
414	0x85, 0x01,         /*      Report ID (1),                  */
415	0x09, 0x01,         /*      Usage (Pointer),                */
416	0xA0,               /*      Collection (Physical),          */
417	0x05, 0x09,         /*          Usage Page (Button),        */
418	0x75, 0x01,         /*          Report Size (1),            */
419	0x95, 0x03,         /*          Report Count (3),           */
420	0x19, 0x01,         /*          Usage Minimum (01h),        */
421	0x29, 0x03,         /*          Usage Maximum (03h),        */
422	0x14,               /*          Logical Minimum (0),        */
423	0x25, 0x01,         /*          Logical Maximum (1),        */
424	0x81, 0x02,         /*          Input (Variable),           */
425	0x95, 0x05,         /*          Report Count (5),           */
426	0x81, 0x03,         /*          Input (Constant, Variable), */
427	0x05, 0x01,         /*          Usage Page (Desktop),       */
428	0x09, 0x30,         /*          Usage (X),                  */
429	0x09, 0x31,         /*          Usage (Y),                  */
430	0x16, 0x00, 0x80,   /*          Logical Minimum (-32768),   */
431	0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
432	0x75, 0x10,         /*          Report Size (16),           */
433	0x95, 0x02,         /*          Report Count (2),           */
434	0x81, 0x06,         /*          Input (Variable, Relative), */
435	0x09, 0x38,         /*          Usage (Wheel),              */
436	0x15, 0xFF,         /*          Logical Minimum (-1),       */
437	0x25, 0x01,         /*          Logical Maximum (1),        */
438	0x95, 0x01,         /*          Report Count (1),           */
439	0x75, 0x08,         /*          Report Size (8),            */
440	0x81, 0x06,         /*          Input (Variable, Relative), */
441	0x81, 0x03,         /*          Input (Constant, Variable), */
442	0xC0,               /*      End Collection,                 */
443	0xC0                /*  End Collection                      */
444};
445
446/* Fixed PID 0522 tablet report descriptor, interface 2 (frame buttons) */
447static __u8 twhl850_rdesc_fixed2[] = {
448	0x05, 0x01,         /*  Usage Page (Desktop),               */
449	0x09, 0x06,         /*  Usage (Keyboard),                   */
450	0xA1, 0x01,         /*  Collection (Application),           */
451	0x85, 0x03,         /*      Report ID (3),                  */
452	0x05, 0x07,         /*      Usage Page (Keyboard),          */
453	0x14,               /*      Logical Minimum (0),            */
454	0x19, 0xE0,         /*      Usage Minimum (KB Leftcontrol), */
455	0x29, 0xE7,         /*      Usage Maximum (KB Right GUI),   */
456	0x25, 0x01,         /*      Logical Maximum (1),            */
457	0x75, 0x01,         /*      Report Size (1),                */
458	0x95, 0x08,         /*      Report Count (8),               */
459	0x81, 0x02,         /*      Input (Variable),               */
460	0x18,               /*      Usage Minimum (None),           */
461	0x29, 0xFF,         /*      Usage Maximum (FFh),            */
462	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
463	0x75, 0x08,         /*      Report Size (8),                */
464	0x95, 0x06,         /*      Report Count (6),               */
465	0x80,               /*      Input,                          */
466	0xC0                /*  End Collection                      */
467};
468
469/*
470 * See TWHA60 description, device and HID report descriptors at
471 * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_TWHA60
472 */
473
474/* Size of the original descriptors of TWHA60 tablet */
475#define TWHA60_RDESC_ORIG_SIZE0 254
476#define TWHA60_RDESC_ORIG_SIZE1 139
477
478/* Fixed TWHA60 report descriptor, interface 0 (stylus) */
479static __u8 twha60_rdesc_fixed0[] = {
480	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
481	0x09, 0x02,         /*  Usage (Pen),                        */
482	0xA1, 0x01,         /*  Collection (Application),           */
483	0x85, 0x09,         /*      Report ID (9),                  */
484	0x09, 0x20,         /*      Usage (Stylus),                 */
485	0xA0,               /*      Collection (Physical),          */
486	0x75, 0x01,         /*          Report Size (1),            */
487	0x09, 0x42,         /*          Usage (Tip Switch),         */
488	0x09, 0x44,         /*          Usage (Barrel Switch),      */
489	0x09, 0x46,         /*          Usage (Tablet Pick),        */
490	0x14,               /*          Logical Minimum (0),        */
491	0x25, 0x01,         /*          Logical Maximum (1),        */
492	0x95, 0x03,         /*          Report Count (3),           */
493	0x81, 0x02,         /*          Input (Variable),           */
494	0x95, 0x04,         /*          Report Count (4),           */
495	0x81, 0x01,         /*          Input (Constant),           */
496	0x09, 0x32,         /*          Usage (In Range),           */
497	0x95, 0x01,         /*          Report Count (1),           */
498	0x81, 0x02,         /*          Input (Variable),           */
499	0x75, 0x10,         /*          Report Size (16),           */
500	0x95, 0x01,         /*          Report Count (1),           */
501	0x14,               /*          Logical Minimum (0),        */
502	0xA4,               /*          Push,                       */
503	0x05, 0x01,         /*          Usage Page (Desktop),       */
504	0x55, 0xFD,         /*          Unit Exponent (-3),         */
505	0x65, 0x13,         /*          Unit (Inch),                */
506	0x34,               /*          Physical Minimum (0),       */
507	0x09, 0x30,         /*          Usage (X),                  */
508	0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
509	0x27, 0x3F, 0x9C,
510		0x00, 0x00, /*          Logical Maximum (39999),    */
511	0x81, 0x02,         /*          Input (Variable),           */
512	0x09, 0x31,         /*          Usage (Y),                  */
513	0x46, 0x6A, 0x18,   /*          Physical Maximum (6250),    */
514	0x26, 0xA7, 0x61,   /*          Logical Maximum (24999),    */
515	0x81, 0x02,         /*          Input (Variable),           */
516	0xB4,               /*          Pop,                        */
517	0x09, 0x30,         /*          Usage (Tip Pressure),       */
518	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
519	0x81, 0x02,         /*          Input (Variable),           */
520	0xC0,               /*      End Collection,                 */
521	0xC0                /*  End Collection                      */
522};
523
524/* Fixed TWHA60 report descriptor, interface 1 (frame buttons) */
525static __u8 twha60_rdesc_fixed1[] = {
526	0x05, 0x01, /*  Usage Page (Desktop),       */
527	0x09, 0x06, /*  Usage (Keyboard),           */
528	0xA1, 0x01, /*  Collection (Application),   */
529	0x85, 0x05, /*      Report ID (5),          */
530	0x05, 0x07, /*      Usage Page (Keyboard),  */
531	0x14,       /*      Logical Minimum (0),    */
532	0x25, 0x01, /*      Logical Maximum (1),    */
533	0x75, 0x01, /*      Report Size (1),        */
534	0x95, 0x08, /*      Report Count (8),       */
535	0x81, 0x01, /*      Input (Constant),       */
536	0x95, 0x0C, /*      Report Count (12),      */
537	0x19, 0x3A, /*      Usage Minimum (KB F1),  */
538	0x29, 0x45, /*      Usage Maximum (KB F12), */
539	0x81, 0x02, /*      Input (Variable),       */
540	0x95, 0x0C, /*      Report Count (12),      */
541	0x19, 0x68, /*      Usage Minimum (KB F13), */
542	0x29, 0x73, /*      Usage Maximum (KB F24), */
543	0x81, 0x02, /*      Input (Variable),       */
544	0x95, 0x08, /*      Report Count (8),       */
545	0x81, 0x01, /*      Input (Constant),       */
546	0xC0        /*  End Collection              */
547};
548
549static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
550					unsigned int *rsize)
551{
552	struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
553	__u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
554
555	switch (hdev->product) {
556	case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209:
557		if (*rsize == PF1209_RDESC_ORIG_SIZE) {
558			rdesc = pf1209_rdesc_fixed;
559			*rsize = sizeof(pf1209_rdesc_fixed);
560		}
561		break;
562	case USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U:
563		if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
564			rdesc = wp4030u_rdesc_fixed;
565			*rsize = sizeof(wp4030u_rdesc_fixed);
566		}
567		break;
568	case USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U:
569		if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
570			rdesc = wp5540u_rdesc_fixed;
571			*rsize = sizeof(wp5540u_rdesc_fixed);
572		}
573		break;
574	case USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U:
575		if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
576			rdesc = wp8060u_rdesc_fixed;
577			*rsize = sizeof(wp8060u_rdesc_fixed);
578		}
579		break;
580	case USB_DEVICE_ID_UCLOGIC_TABLET_WP1062:
581		if (*rsize == WP1062_RDESC_ORIG_SIZE) {
582			rdesc = wp1062_rdesc_fixed;
583			*rsize = sizeof(wp1062_rdesc_fixed);
584		}
585		break;
586	case USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850:
587		switch (iface_num) {
588		case 0:
589			if (*rsize == TWHL850_RDESC_ORIG_SIZE0) {
590				rdesc = twhl850_rdesc_fixed0;
591				*rsize = sizeof(twhl850_rdesc_fixed0);
592			}
593			break;
594		case 1:
595			if (*rsize == TWHL850_RDESC_ORIG_SIZE1) {
596				rdesc = twhl850_rdesc_fixed1;
597				*rsize = sizeof(twhl850_rdesc_fixed1);
598			}
599			break;
600		case 2:
601			if (*rsize == TWHL850_RDESC_ORIG_SIZE2) {
602				rdesc = twhl850_rdesc_fixed2;
603				*rsize = sizeof(twhl850_rdesc_fixed2);
604			}
605			break;
606		}
607		break;
608	case USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60:
609		switch (iface_num) {
610		case 0:
611			if (*rsize == TWHA60_RDESC_ORIG_SIZE0) {
612				rdesc = twha60_rdesc_fixed0;
613				*rsize = sizeof(twha60_rdesc_fixed0);
614			}
615			break;
616		case 1:
617			if (*rsize == TWHA60_RDESC_ORIG_SIZE1) {
618				rdesc = twha60_rdesc_fixed1;
619				*rsize = sizeof(twha60_rdesc_fixed1);
620			}
621			break;
622		}
623		break;
624	}
625
626	return rdesc;
627}
628
629static const struct hid_device_id uclogic_devices[] = {
630	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
631				USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) },
632	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
633				USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
634	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
635				USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
636	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
637				USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
638	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
639				USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
640	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
641				USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
642	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
643				USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) },
644	{ }
645};
646MODULE_DEVICE_TABLE(hid, uclogic_devices);
647
648static struct hid_driver uclogic_driver = {
649	.name = "uclogic",
650	.id_table = uclogic_devices,
651	.report_fixup = uclogic_report_fixup,
652};
653module_hid_driver(uclogic_driver);
654
655MODULE_LICENSE("GPL");