Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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
469static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
470					unsigned int *rsize)
471{
472	struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
473	__u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
474
475	switch (hdev->product) {
476	case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209:
477		if (*rsize == PF1209_RDESC_ORIG_SIZE) {
478			rdesc = pf1209_rdesc_fixed;
479			*rsize = sizeof(pf1209_rdesc_fixed);
480		}
481		break;
482	case USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U:
483		if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
484			rdesc = wp4030u_rdesc_fixed;
485			*rsize = sizeof(wp4030u_rdesc_fixed);
486		}
487		break;
488	case USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U:
489		if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
490			rdesc = wp5540u_rdesc_fixed;
491			*rsize = sizeof(wp5540u_rdesc_fixed);
492		}
493		break;
494	case USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U:
495		if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
496			rdesc = wp8060u_rdesc_fixed;
497			*rsize = sizeof(wp8060u_rdesc_fixed);
498		}
499		break;
500	case USB_DEVICE_ID_UCLOGIC_TABLET_WP1062:
501		if (*rsize == WP1062_RDESC_ORIG_SIZE) {
502			rdesc = wp1062_rdesc_fixed;
503			*rsize = sizeof(wp1062_rdesc_fixed);
504		}
505		break;
506	case USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850:
507		switch (iface_num) {
508		case 0:
509			if (*rsize == TWHL850_RDESC_ORIG_SIZE0) {
510				rdesc = twhl850_rdesc_fixed0;
511				*rsize = sizeof(twhl850_rdesc_fixed0);
512			}
513			break;
514		case 1:
515			if (*rsize == TWHL850_RDESC_ORIG_SIZE1) {
516				rdesc = twhl850_rdesc_fixed1;
517				*rsize = sizeof(twhl850_rdesc_fixed1);
518			}
519			break;
520		case 2:
521			if (*rsize == TWHL850_RDESC_ORIG_SIZE2) {
522				rdesc = twhl850_rdesc_fixed2;
523				*rsize = sizeof(twhl850_rdesc_fixed2);
524			}
525			break;
526		}
527		break;
528	}
529
530	return rdesc;
531}
532
533static const struct hid_device_id uclogic_devices[] = {
534	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
535				USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) },
536	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
537				USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
538	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
539				USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
540	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
541				USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
542	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
543				USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
544	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
545				USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
546	{ }
547};
548MODULE_DEVICE_TABLE(hid, uclogic_devices);
549
550static struct hid_driver uclogic_driver = {
551	.name = "uclogic",
552	.id_table = uclogic_devices,
553	.report_fixup = uclogic_report_fixup,
554};
555
556static int __init uclogic_init(void)
557{
558	return hid_register_driver(&uclogic_driver);
559}
560
561static void __exit uclogic_exit(void)
562{
563	hid_unregister_driver(&uclogic_driver);
564}
565
566module_init(uclogic_init);
567module_exit(uclogic_exit);
568MODULE_LICENSE("GPL");