Merge tag 'rust-6.4' of https://github.com/Rust-for-Linux/linux
[linux-block.git] / drivers / hid / hid-uclogic-rdesc.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *  HID driver for UC-Logic devices not fully compliant with HID standard
4  *  - original and fixed report descriptors
5  *
6  *  Copyright (c) 2010-2017 Nikolai Kondrashov
7  *  Copyright (c) 2013 Martin Rusko
8  */
9
10 /*
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License as published by the Free
13  * Software Foundation; either version 2 of the License, or (at your option)
14  * any later version.
15  */
16
17 #include "hid-uclogic-rdesc.h"
18 #include <linux/slab.h>
19 #include <asm/unaligned.h>
20
21 /* Fixed WP4030U report descriptor */
22 __u8 uclogic_rdesc_wp4030u_fixed_arr[] = {
23         0x05, 0x0D,         /*  Usage Page (Digitizer),             */
24         0x09, 0x01,         /*  Usage (Digitizer),                  */
25         0xA1, 0x01,         /*  Collection (Application),           */
26         0x85, 0x09,         /*      Report ID (9),                  */
27         0x09, 0x20,         /*      Usage (Stylus),                 */
28         0xA0,               /*      Collection (Physical),          */
29         0x75, 0x01,         /*          Report Size (1),            */
30         0x09, 0x42,         /*          Usage (Tip Switch),         */
31         0x09, 0x44,         /*          Usage (Barrel Switch),      */
32         0x09, 0x46,         /*          Usage (Tablet Pick),        */
33         0x14,               /*          Logical Minimum (0),        */
34         0x25, 0x01,         /*          Logical Maximum (1),        */
35         0x95, 0x03,         /*          Report Count (3),           */
36         0x81, 0x02,         /*          Input (Variable),           */
37         0x95, 0x05,         /*          Report Count (5),           */
38         0x81, 0x01,         /*          Input (Constant),           */
39         0x75, 0x10,         /*          Report Size (16),           */
40         0x95, 0x01,         /*          Report Count (1),           */
41         0x14,               /*          Logical Minimum (0),        */
42         0xA4,               /*          Push,                       */
43         0x05, 0x01,         /*          Usage Page (Desktop),       */
44         0x55, 0xFD,         /*          Unit Exponent (-3),         */
45         0x65, 0x13,         /*          Unit (Inch),                */
46         0x34,               /*          Physical Minimum (0),       */
47         0x09, 0x30,         /*          Usage (X),                  */
48         0x46, 0xA0, 0x0F,   /*          Physical Maximum (4000),    */
49         0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
50         0x81, 0x02,         /*          Input (Variable),           */
51         0x09, 0x31,         /*          Usage (Y),                  */
52         0x46, 0xB8, 0x0B,   /*          Physical Maximum (3000),    */
53         0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
54         0x81, 0x02,         /*          Input (Variable),           */
55         0xB4,               /*          Pop,                        */
56         0x09, 0x30,         /*          Usage (Tip Pressure),       */
57         0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
58         0x81, 0x02,         /*          Input (Variable),           */
59         0xC0,               /*      End Collection,                 */
60         0xC0                /*  End Collection                      */
61 };
62
63 const size_t uclogic_rdesc_wp4030u_fixed_size =
64                         sizeof(uclogic_rdesc_wp4030u_fixed_arr);
65
66 /* Fixed WP5540U report descriptor */
67 __u8 uclogic_rdesc_wp5540u_fixed_arr[] = {
68         0x05, 0x0D,         /*  Usage Page (Digitizer),             */
69         0x09, 0x01,         /*  Usage (Digitizer),                  */
70         0xA1, 0x01,         /*  Collection (Application),           */
71         0x85, 0x09,         /*      Report ID (9),                  */
72         0x09, 0x20,         /*      Usage (Stylus),                 */
73         0xA0,               /*      Collection (Physical),          */
74         0x75, 0x01,         /*          Report Size (1),            */
75         0x09, 0x42,         /*          Usage (Tip Switch),         */
76         0x09, 0x44,         /*          Usage (Barrel Switch),      */
77         0x09, 0x46,         /*          Usage (Tablet Pick),        */
78         0x14,               /*          Logical Minimum (0),        */
79         0x25, 0x01,         /*          Logical Maximum (1),        */
80         0x95, 0x03,         /*          Report Count (3),           */
81         0x81, 0x02,         /*          Input (Variable),           */
82         0x95, 0x05,         /*          Report Count (5),           */
83         0x81, 0x01,         /*          Input (Constant),           */
84         0x75, 0x10,         /*          Report Size (16),           */
85         0x95, 0x01,         /*          Report Count (1),           */
86         0x14,               /*          Logical Minimum (0),        */
87         0xA4,               /*          Push,                       */
88         0x05, 0x01,         /*          Usage Page (Desktop),       */
89         0x55, 0xFD,         /*          Unit Exponent (-3),         */
90         0x65, 0x13,         /*          Unit (Inch),                */
91         0x34,               /*          Physical Minimum (0),       */
92         0x09, 0x30,         /*          Usage (X),                  */
93         0x46, 0x7C, 0x15,   /*          Physical Maximum (5500),    */
94         0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
95         0x81, 0x02,         /*          Input (Variable),           */
96         0x09, 0x31,         /*          Usage (Y),                  */
97         0x46, 0xA0, 0x0F,   /*          Physical Maximum (4000),    */
98         0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
99         0x81, 0x02,         /*          Input (Variable),           */
100         0xB4,               /*          Pop,                        */
101         0x09, 0x30,         /*          Usage (Tip Pressure),       */
102         0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
103         0x81, 0x02,         /*          Input (Variable),           */
104         0xC0,               /*      End Collection,                 */
105         0xC0,               /*  End Collection,                     */
106         0x05, 0x01,         /*  Usage Page (Desktop),               */
107         0x09, 0x02,         /*  Usage (Mouse),                      */
108         0xA1, 0x01,         /*  Collection (Application),           */
109         0x85, 0x08,         /*      Report ID (8),                  */
110         0x09, 0x01,         /*      Usage (Pointer),                */
111         0xA0,               /*      Collection (Physical),          */
112         0x75, 0x01,         /*          Report Size (1),            */
113         0x05, 0x09,         /*          Usage Page (Button),        */
114         0x19, 0x01,         /*          Usage Minimum (01h),        */
115         0x29, 0x03,         /*          Usage Maximum (03h),        */
116         0x14,               /*          Logical Minimum (0),        */
117         0x25, 0x01,         /*          Logical Maximum (1),        */
118         0x95, 0x03,         /*          Report Count (3),           */
119         0x81, 0x02,         /*          Input (Variable),           */
120         0x95, 0x05,         /*          Report Count (5),           */
121         0x81, 0x01,         /*          Input (Constant),           */
122         0x05, 0x01,         /*          Usage Page (Desktop),       */
123         0x75, 0x08,         /*          Report Size (8),            */
124         0x09, 0x30,         /*          Usage (X),                  */
125         0x09, 0x31,         /*          Usage (Y),                  */
126         0x15, 0x81,         /*          Logical Minimum (-127),     */
127         0x25, 0x7F,         /*          Logical Maximum (127),      */
128         0x95, 0x02,         /*          Report Count (2),           */
129         0x81, 0x06,         /*          Input (Variable, Relative), */
130         0x09, 0x38,         /*          Usage (Wheel),              */
131         0x15, 0xFF,         /*          Logical Minimum (-1),       */
132         0x25, 0x01,         /*          Logical Maximum (1),        */
133         0x95, 0x01,         /*          Report Count (1),           */
134         0x81, 0x06,         /*          Input (Variable, Relative), */
135         0x81, 0x01,         /*          Input (Constant),           */
136         0xC0,               /*      End Collection,                 */
137         0xC0                /*  End Collection                      */
138 };
139
140 const size_t uclogic_rdesc_wp5540u_fixed_size =
141                         sizeof(uclogic_rdesc_wp5540u_fixed_arr);
142
143 /* Fixed WP8060U report descriptor */
144 __u8 uclogic_rdesc_wp8060u_fixed_arr[] = {
145         0x05, 0x0D,         /*  Usage Page (Digitizer),             */
146         0x09, 0x01,         /*  Usage (Digitizer),                  */
147         0xA1, 0x01,         /*  Collection (Application),           */
148         0x85, 0x09,         /*      Report ID (9),                  */
149         0x09, 0x20,         /*      Usage (Stylus),                 */
150         0xA0,               /*      Collection (Physical),          */
151         0x75, 0x01,         /*          Report Size (1),            */
152         0x09, 0x42,         /*          Usage (Tip Switch),         */
153         0x09, 0x44,         /*          Usage (Barrel Switch),      */
154         0x09, 0x46,         /*          Usage (Tablet Pick),        */
155         0x14,               /*          Logical Minimum (0),        */
156         0x25, 0x01,         /*          Logical Maximum (1),        */
157         0x95, 0x03,         /*          Report Count (3),           */
158         0x81, 0x02,         /*          Input (Variable),           */
159         0x95, 0x05,         /*          Report Count (5),           */
160         0x81, 0x01,         /*          Input (Constant),           */
161         0x75, 0x10,         /*          Report Size (16),           */
162         0x95, 0x01,         /*          Report Count (1),           */
163         0x14,               /*          Logical Minimum (0),        */
164         0xA4,               /*          Push,                       */
165         0x05, 0x01,         /*          Usage Page (Desktop),       */
166         0x55, 0xFD,         /*          Unit Exponent (-3),         */
167         0x65, 0x13,         /*          Unit (Inch),                */
168         0x34,               /*          Physical Minimum (0),       */
169         0x09, 0x30,         /*          Usage (X),                  */
170         0x46, 0x40, 0x1F,   /*          Physical Maximum (8000),    */
171         0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
172         0x81, 0x02,         /*          Input (Variable),           */
173         0x09, 0x31,         /*          Usage (Y),                  */
174         0x46, 0x70, 0x17,   /*          Physical Maximum (6000),    */
175         0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
176         0x81, 0x02,         /*          Input (Variable),           */
177         0xB4,               /*          Pop,                        */
178         0x09, 0x30,         /*          Usage (Tip Pressure),       */
179         0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
180         0x81, 0x02,         /*          Input (Variable),           */
181         0xC0,               /*      End Collection,                 */
182         0xC0,               /*  End Collection,                     */
183         0x05, 0x01,         /*  Usage Page (Desktop),               */
184         0x09, 0x02,         /*  Usage (Mouse),                      */
185         0xA1, 0x01,         /*  Collection (Application),           */
186         0x85, 0x08,         /*      Report ID (8),                  */
187         0x09, 0x01,         /*      Usage (Pointer),                */
188         0xA0,               /*      Collection (Physical),          */
189         0x75, 0x01,         /*          Report Size (1),            */
190         0x05, 0x09,         /*          Usage Page (Button),        */
191         0x19, 0x01,         /*          Usage Minimum (01h),        */
192         0x29, 0x03,         /*          Usage Maximum (03h),        */
193         0x14,               /*          Logical Minimum (0),        */
194         0x25, 0x01,         /*          Logical Maximum (1),        */
195         0x95, 0x03,         /*          Report Count (3),           */
196         0x81, 0x02,         /*          Input (Variable),           */
197         0x95, 0x05,         /*          Report Count (5),           */
198         0x81, 0x01,         /*          Input (Constant),           */
199         0x05, 0x01,         /*          Usage Page (Desktop),       */
200         0x75, 0x08,         /*          Report Size (8),            */
201         0x09, 0x30,         /*          Usage (X),                  */
202         0x09, 0x31,         /*          Usage (Y),                  */
203         0x15, 0x81,         /*          Logical Minimum (-127),     */
204         0x25, 0x7F,         /*          Logical Maximum (127),      */
205         0x95, 0x02,         /*          Report Count (2),           */
206         0x81, 0x06,         /*          Input (Variable, Relative), */
207         0x09, 0x38,         /*          Usage (Wheel),              */
208         0x15, 0xFF,         /*          Logical Minimum (-1),       */
209         0x25, 0x01,         /*          Logical Maximum (1),        */
210         0x95, 0x01,         /*          Report Count (1),           */
211         0x81, 0x06,         /*          Input (Variable, Relative), */
212         0x81, 0x01,         /*          Input (Constant),           */
213         0xC0,               /*      End Collection,                 */
214         0xC0                /*  End Collection                      */
215 };
216
217 const size_t uclogic_rdesc_wp8060u_fixed_size =
218                         sizeof(uclogic_rdesc_wp8060u_fixed_arr);
219
220 /* Fixed WP1062 report descriptor */
221 __u8 uclogic_rdesc_wp1062_fixed_arr[] = {
222         0x05, 0x0D,         /*  Usage Page (Digitizer),             */
223         0x09, 0x01,         /*  Usage (Digitizer),                  */
224         0xA1, 0x01,         /*  Collection (Application),           */
225         0x85, 0x09,         /*      Report ID (9),                  */
226         0x09, 0x20,         /*      Usage (Stylus),                 */
227         0xA0,               /*      Collection (Physical),          */
228         0x75, 0x01,         /*          Report Size (1),            */
229         0x09, 0x42,         /*          Usage (Tip Switch),         */
230         0x09, 0x44,         /*          Usage (Barrel Switch),      */
231         0x09, 0x46,         /*          Usage (Tablet Pick),        */
232         0x14,               /*          Logical Minimum (0),        */
233         0x25, 0x01,         /*          Logical Maximum (1),        */
234         0x95, 0x03,         /*          Report Count (3),           */
235         0x81, 0x02,         /*          Input (Variable),           */
236         0x95, 0x04,         /*          Report Count (4),           */
237         0x81, 0x01,         /*          Input (Constant),           */
238         0x09, 0x32,         /*          Usage (In Range),           */
239         0x95, 0x01,         /*          Report Count (1),           */
240         0x81, 0x02,         /*          Input (Variable),           */
241         0x75, 0x10,         /*          Report Size (16),           */
242         0x95, 0x01,         /*          Report Count (1),           */
243         0x14,               /*          Logical Minimum (0),        */
244         0xA4,               /*          Push,                       */
245         0x05, 0x01,         /*          Usage Page (Desktop),       */
246         0x55, 0xFD,         /*          Unit Exponent (-3),         */
247         0x65, 0x13,         /*          Unit (Inch),                */
248         0x34,               /*          Physical Minimum (0),       */
249         0x09, 0x30,         /*          Usage (X),                  */
250         0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
251         0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
252         0x81, 0x02,         /*          Input (Variable),           */
253         0x09, 0x31,         /*          Usage (Y),                  */
254         0x46, 0xB7, 0x19,   /*          Physical Maximum (6583),    */
255         0x26, 0x6E, 0x33,   /*          Logical Maximum (13166),    */
256         0x81, 0x02,         /*          Input (Variable),           */
257         0xB4,               /*          Pop,                        */
258         0x09, 0x30,         /*          Usage (Tip Pressure),       */
259         0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
260         0x81, 0x02,         /*          Input (Variable),           */
261         0xC0,               /*      End Collection,                 */
262         0xC0                /*  End Collection                      */
263 };
264
265 const size_t uclogic_rdesc_wp1062_fixed_size =
266                         sizeof(uclogic_rdesc_wp1062_fixed_arr);
267
268 /* Fixed PF1209 report descriptor */
269 __u8 uclogic_rdesc_pf1209_fixed_arr[] = {
270         0x05, 0x0D,         /*  Usage Page (Digitizer),             */
271         0x09, 0x01,         /*  Usage (Digitizer),                  */
272         0xA1, 0x01,         /*  Collection (Application),           */
273         0x85, 0x09,         /*      Report ID (9),                  */
274         0x09, 0x20,         /*      Usage (Stylus),                 */
275         0xA0,               /*      Collection (Physical),          */
276         0x75, 0x01,         /*          Report Size (1),            */
277         0x09, 0x42,         /*          Usage (Tip Switch),         */
278         0x09, 0x44,         /*          Usage (Barrel Switch),      */
279         0x09, 0x46,         /*          Usage (Tablet Pick),        */
280         0x14,               /*          Logical Minimum (0),        */
281         0x25, 0x01,         /*          Logical Maximum (1),        */
282         0x95, 0x03,         /*          Report Count (3),           */
283         0x81, 0x02,         /*          Input (Variable),           */
284         0x95, 0x05,         /*          Report Count (5),           */
285         0x81, 0x01,         /*          Input (Constant),           */
286         0x75, 0x10,         /*          Report Size (16),           */
287         0x95, 0x01,         /*          Report Count (1),           */
288         0x14,               /*          Logical Minimum (0),        */
289         0xA4,               /*          Push,                       */
290         0x05, 0x01,         /*          Usage Page (Desktop),       */
291         0x55, 0xFD,         /*          Unit Exponent (-3),         */
292         0x65, 0x13,         /*          Unit (Inch),                */
293         0x34,               /*          Physical Minimum (0),       */
294         0x09, 0x30,         /*          Usage (X),                  */
295         0x46, 0xE0, 0x2E,   /*          Physical Maximum (12000),   */
296         0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
297         0x81, 0x02,         /*          Input (Variable),           */
298         0x09, 0x31,         /*          Usage (Y),                  */
299         0x46, 0x28, 0x23,   /*          Physical Maximum (9000),    */
300         0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
301         0x81, 0x02,         /*          Input (Variable),           */
302         0xB4,               /*          Pop,                        */
303         0x09, 0x30,         /*          Usage (Tip Pressure),       */
304         0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
305         0x81, 0x02,         /*          Input (Variable),           */
306         0xC0,               /*      End Collection,                 */
307         0xC0,               /*  End Collection,                     */
308         0x05, 0x01,         /*  Usage Page (Desktop),               */
309         0x09, 0x02,         /*  Usage (Mouse),                      */
310         0xA1, 0x01,         /*  Collection (Application),           */
311         0x85, 0x08,         /*      Report ID (8),                  */
312         0x09, 0x01,         /*      Usage (Pointer),                */
313         0xA0,               /*      Collection (Physical),          */
314         0x75, 0x01,         /*          Report Size (1),            */
315         0x05, 0x09,         /*          Usage Page (Button),        */
316         0x19, 0x01,         /*          Usage Minimum (01h),        */
317         0x29, 0x03,         /*          Usage Maximum (03h),        */
318         0x14,               /*          Logical Minimum (0),        */
319         0x25, 0x01,         /*          Logical Maximum (1),        */
320         0x95, 0x03,         /*          Report Count (3),           */
321         0x81, 0x02,         /*          Input (Variable),           */
322         0x95, 0x05,         /*          Report Count (5),           */
323         0x81, 0x01,         /*          Input (Constant),           */
324         0x05, 0x01,         /*          Usage Page (Desktop),       */
325         0x75, 0x08,         /*          Report Size (8),            */
326         0x09, 0x30,         /*          Usage (X),                  */
327         0x09, 0x31,         /*          Usage (Y),                  */
328         0x15, 0x81,         /*          Logical Minimum (-127),     */
329         0x25, 0x7F,         /*          Logical Maximum (127),      */
330         0x95, 0x02,         /*          Report Count (2),           */
331         0x81, 0x06,         /*          Input (Variable, Relative), */
332         0x09, 0x38,         /*          Usage (Wheel),              */
333         0x15, 0xFF,         /*          Logical Minimum (-1),       */
334         0x25, 0x01,         /*          Logical Maximum (1),        */
335         0x95, 0x01,         /*          Report Count (1),           */
336         0x81, 0x06,         /*          Input (Variable, Relative), */
337         0x81, 0x01,         /*          Input (Constant),           */
338         0xC0,               /*      End Collection,                 */
339         0xC0                /*  End Collection                      */
340 };
341
342 const size_t uclogic_rdesc_pf1209_fixed_size =
343                         sizeof(uclogic_rdesc_pf1209_fixed_arr);
344
345 /* Fixed PID 0522 tablet report descriptor, interface 0 (stylus) */
346 __u8 uclogic_rdesc_twhl850_fixed0_arr[] = {
347         0x05, 0x0D,         /*  Usage Page (Digitizer),             */
348         0x09, 0x01,         /*  Usage (Digitizer),                  */
349         0xA1, 0x01,         /*  Collection (Application),           */
350         0x85, 0x09,         /*      Report ID (9),                  */
351         0x09, 0x20,         /*      Usage (Stylus),                 */
352         0xA0,               /*      Collection (Physical),          */
353         0x14,               /*          Logical Minimum (0),        */
354         0x25, 0x01,         /*          Logical Maximum (1),        */
355         0x75, 0x01,         /*          Report Size (1),            */
356         0x95, 0x03,         /*          Report Count (3),           */
357         0x09, 0x42,         /*          Usage (Tip Switch),         */
358         0x09, 0x44,         /*          Usage (Barrel Switch),      */
359         0x09, 0x46,         /*          Usage (Tablet Pick),        */
360         0x81, 0x02,         /*          Input (Variable),           */
361         0x81, 0x03,         /*          Input (Constant, Variable), */
362         0x95, 0x01,         /*          Report Count (1),           */
363         0x09, 0x32,         /*          Usage (In Range),           */
364         0x81, 0x02,         /*          Input (Variable),           */
365         0x81, 0x03,         /*          Input (Constant, Variable), */
366         0x75, 0x10,         /*          Report Size (16),           */
367         0xA4,               /*          Push,                       */
368         0x05, 0x01,         /*          Usage Page (Desktop),       */
369         0x65, 0x13,         /*          Unit (Inch),                */
370         0x55, 0xFD,         /*          Unit Exponent (-3),         */
371         0x34,               /*          Physical Minimum (0),       */
372         0x09, 0x30,         /*          Usage (X),                  */
373         0x46, 0x40, 0x1F,   /*          Physical Maximum (8000),    */
374         0x26, 0x00, 0x7D,   /*          Logical Maximum (32000),    */
375         0x81, 0x02,         /*          Input (Variable),           */
376         0x09, 0x31,         /*          Usage (Y),                  */
377         0x46, 0x88, 0x13,   /*          Physical Maximum (5000),    */
378         0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
379         0x81, 0x02,         /*          Input (Variable),           */
380         0xB4,               /*          Pop,                        */
381         0x09, 0x30,         /*          Usage (Tip Pressure),       */
382         0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
383         0x81, 0x02,         /*          Input (Variable),           */
384         0xC0,               /*      End Collection,                 */
385         0xC0                /*  End Collection                      */
386 };
387
388 const size_t uclogic_rdesc_twhl850_fixed0_size =
389                         sizeof(uclogic_rdesc_twhl850_fixed0_arr);
390
391 /* Fixed PID 0522 tablet report descriptor, interface 1 (mouse) */
392 __u8 uclogic_rdesc_twhl850_fixed1_arr[] = {
393         0x05, 0x01,         /*  Usage Page (Desktop),               */
394         0x09, 0x02,         /*  Usage (Mouse),                      */
395         0xA1, 0x01,         /*  Collection (Application),           */
396         0x85, 0x01,         /*      Report ID (1),                  */
397         0x09, 0x01,         /*      Usage (Pointer),                */
398         0xA0,               /*      Collection (Physical),          */
399         0x05, 0x09,         /*          Usage Page (Button),        */
400         0x75, 0x01,         /*          Report Size (1),            */
401         0x95, 0x03,         /*          Report Count (3),           */
402         0x19, 0x01,         /*          Usage Minimum (01h),        */
403         0x29, 0x03,         /*          Usage Maximum (03h),        */
404         0x14,               /*          Logical Minimum (0),        */
405         0x25, 0x01,         /*          Logical Maximum (1),        */
406         0x81, 0x02,         /*          Input (Variable),           */
407         0x95, 0x05,         /*          Report Count (5),           */
408         0x81, 0x03,         /*          Input (Constant, Variable), */
409         0x05, 0x01,         /*          Usage Page (Desktop),       */
410         0x09, 0x30,         /*          Usage (X),                  */
411         0x09, 0x31,         /*          Usage (Y),                  */
412         0x16, 0x00, 0x80,   /*          Logical Minimum (-32768),   */
413         0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
414         0x75, 0x10,         /*          Report Size (16),           */
415         0x95, 0x02,         /*          Report Count (2),           */
416         0x81, 0x06,         /*          Input (Variable, Relative), */
417         0x09, 0x38,         /*          Usage (Wheel),              */
418         0x15, 0xFF,         /*          Logical Minimum (-1),       */
419         0x25, 0x01,         /*          Logical Maximum (1),        */
420         0x95, 0x01,         /*          Report Count (1),           */
421         0x75, 0x08,         /*          Report Size (8),            */
422         0x81, 0x06,         /*          Input (Variable, Relative), */
423         0x81, 0x03,         /*          Input (Constant, Variable), */
424         0xC0,               /*      End Collection,                 */
425         0xC0                /*  End Collection                      */
426 };
427
428 const size_t uclogic_rdesc_twhl850_fixed1_size =
429                         sizeof(uclogic_rdesc_twhl850_fixed1_arr);
430
431 /* Fixed PID 0522 tablet report descriptor, interface 2 (frame buttons) */
432 __u8 uclogic_rdesc_twhl850_fixed2_arr[] = {
433         0x05, 0x01,         /*  Usage Page (Desktop),               */
434         0x09, 0x06,         /*  Usage (Keyboard),                   */
435         0xA1, 0x01,         /*  Collection (Application),           */
436         0x85, 0x03,         /*      Report ID (3),                  */
437         0x05, 0x07,         /*      Usage Page (Keyboard),          */
438         0x14,               /*      Logical Minimum (0),            */
439         0x19, 0xE0,         /*      Usage Minimum (KB Leftcontrol), */
440         0x29, 0xE7,         /*      Usage Maximum (KB Right GUI),   */
441         0x25, 0x01,         /*      Logical Maximum (1),            */
442         0x75, 0x01,         /*      Report Size (1),                */
443         0x95, 0x08,         /*      Report Count (8),               */
444         0x81, 0x02,         /*      Input (Variable),               */
445         0x18,               /*      Usage Minimum (None),           */
446         0x29, 0xFF,         /*      Usage Maximum (FFh),            */
447         0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
448         0x75, 0x08,         /*      Report Size (8),                */
449         0x95, 0x06,         /*      Report Count (6),               */
450         0x80,               /*      Input,                          */
451         0xC0                /*  End Collection                      */
452 };
453
454 const size_t uclogic_rdesc_twhl850_fixed2_size =
455                         sizeof(uclogic_rdesc_twhl850_fixed2_arr);
456
457 /* Fixed TWHA60 report descriptor, interface 0 (stylus) */
458 __u8 uclogic_rdesc_twha60_fixed0_arr[] = {
459         0x05, 0x0D,         /*  Usage Page (Digitizer),             */
460         0x09, 0x01,         /*  Usage (Digitizer),                  */
461         0xA1, 0x01,         /*  Collection (Application),           */
462         0x85, 0x09,         /*      Report ID (9),                  */
463         0x09, 0x20,         /*      Usage (Stylus),                 */
464         0xA0,               /*      Collection (Physical),          */
465         0x75, 0x01,         /*          Report Size (1),            */
466         0x09, 0x42,         /*          Usage (Tip Switch),         */
467         0x09, 0x44,         /*          Usage (Barrel Switch),      */
468         0x09, 0x46,         /*          Usage (Tablet Pick),        */
469         0x14,               /*          Logical Minimum (0),        */
470         0x25, 0x01,         /*          Logical Maximum (1),        */
471         0x95, 0x03,         /*          Report Count (3),           */
472         0x81, 0x02,         /*          Input (Variable),           */
473         0x95, 0x04,         /*          Report Count (4),           */
474         0x81, 0x01,         /*          Input (Constant),           */
475         0x09, 0x32,         /*          Usage (In Range),           */
476         0x95, 0x01,         /*          Report Count (1),           */
477         0x81, 0x02,         /*          Input (Variable),           */
478         0x75, 0x10,         /*          Report Size (16),           */
479         0x95, 0x01,         /*          Report Count (1),           */
480         0x14,               /*          Logical Minimum (0),        */
481         0xA4,               /*          Push,                       */
482         0x05, 0x01,         /*          Usage Page (Desktop),       */
483         0x55, 0xFD,         /*          Unit Exponent (-3),         */
484         0x65, 0x13,         /*          Unit (Inch),                */
485         0x34,               /*          Physical Minimum (0),       */
486         0x09, 0x30,         /*          Usage (X),                  */
487         0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
488         0x27, 0x3F, 0x9C,
489                 0x00, 0x00, /*          Logical Maximum (39999),    */
490         0x81, 0x02,         /*          Input (Variable),           */
491         0x09, 0x31,         /*          Usage (Y),                  */
492         0x46, 0x6A, 0x18,   /*          Physical Maximum (6250),    */
493         0x26, 0xA7, 0x61,   /*          Logical Maximum (24999),    */
494         0x81, 0x02,         /*          Input (Variable),           */
495         0xB4,               /*          Pop,                        */
496         0x09, 0x30,         /*          Usage (Tip Pressure),       */
497         0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
498         0x81, 0x02,         /*          Input (Variable),           */
499         0xC0,               /*      End Collection,                 */
500         0xC0                /*  End Collection                      */
501 };
502
503 const size_t uclogic_rdesc_twha60_fixed0_size =
504                         sizeof(uclogic_rdesc_twha60_fixed0_arr);
505
506 /* Fixed TWHA60 report descriptor, interface 1 (frame buttons) */
507 __u8 uclogic_rdesc_twha60_fixed1_arr[] = {
508         0x05, 0x01, /*  Usage Page (Desktop),       */
509         0x09, 0x06, /*  Usage (Keyboard),           */
510         0xA1, 0x01, /*  Collection (Application),   */
511         0x85, 0x05, /*      Report ID (5),          */
512         0x05, 0x07, /*      Usage Page (Keyboard),  */
513         0x14,       /*      Logical Minimum (0),    */
514         0x25, 0x01, /*      Logical Maximum (1),    */
515         0x75, 0x01, /*      Report Size (1),        */
516         0x95, 0x08, /*      Report Count (8),       */
517         0x81, 0x01, /*      Input (Constant),       */
518         0x95, 0x0C, /*      Report Count (12),      */
519         0x19, 0x3A, /*      Usage Minimum (KB F1),  */
520         0x29, 0x45, /*      Usage Maximum (KB F12), */
521         0x81, 0x02, /*      Input (Variable),       */
522         0x95, 0x0C, /*      Report Count (12),      */
523         0x19, 0x68, /*      Usage Minimum (KB F13), */
524         0x29, 0x73, /*      Usage Maximum (KB F24), */
525         0x81, 0x02, /*      Input (Variable),       */
526         0x95, 0x08, /*      Report Count (8),       */
527         0x81, 0x01, /*      Input (Constant),       */
528         0xC0        /*  End Collection              */
529 };
530
531 const size_t uclogic_rdesc_twha60_fixed1_size =
532                         sizeof(uclogic_rdesc_twha60_fixed1_arr);
533
534 /* Fixed report descriptor template for (tweaked) v1 pen reports */
535 const __u8 uclogic_rdesc_v1_pen_template_arr[] = {
536         0x05, 0x0D,             /*  Usage Page (Digitizer),                 */
537         0x09, 0x01,             /*  Usage (Digitizer),                      */
538         0xA1, 0x01,             /*  Collection (Application),               */
539         0x85, 0x07,             /*      Report ID (7),                      */
540         0x09, 0x20,             /*      Usage (Stylus),                     */
541         0xA0,                   /*      Collection (Physical),              */
542         0x14,                   /*          Logical Minimum (0),            */
543         0x25, 0x01,             /*          Logical Maximum (1),            */
544         0x75, 0x01,             /*          Report Size (1),                */
545         0x09, 0x42,             /*          Usage (Tip Switch),             */
546         0x09, 0x44,             /*          Usage (Barrel Switch),          */
547         0x09, 0x46,             /*          Usage (Tablet Pick),            */
548         0x95, 0x03,             /*          Report Count (3),               */
549         0x81, 0x02,             /*          Input (Variable),               */
550         0x95, 0x03,             /*          Report Count (3),               */
551         0x81, 0x03,             /*          Input (Constant, Variable),     */
552         0x09, 0x32,             /*          Usage (In Range),               */
553         0x95, 0x01,             /*          Report Count (1),               */
554         0x81, 0x02,             /*          Input (Variable),               */
555         0x95, 0x01,             /*          Report Count (1),               */
556         0x81, 0x03,             /*          Input (Constant, Variable),     */
557         0x75, 0x10,             /*          Report Size (16),               */
558         0x95, 0x01,             /*          Report Count (1),               */
559         0xA4,                   /*          Push,                           */
560         0x05, 0x01,             /*          Usage Page (Desktop),           */
561         0x65, 0x13,             /*          Unit (Inch),                    */
562         0x55, 0xFD,             /*          Unit Exponent (-3),             */
563         0x34,                   /*          Physical Minimum (0),           */
564         0x09, 0x30,             /*          Usage (X),                      */
565         0x27, UCLOGIC_RDESC_PEN_PH(X_LM),
566                                 /*          Logical Maximum (PLACEHOLDER),  */
567         0x47, UCLOGIC_RDESC_PEN_PH(X_PM),
568                                 /*          Physical Maximum (PLACEHOLDER), */
569         0x81, 0x02,             /*          Input (Variable),               */
570         0x09, 0x31,             /*          Usage (Y),                      */
571         0x27, UCLOGIC_RDESC_PEN_PH(Y_LM),
572                                 /*          Logical Maximum (PLACEHOLDER),  */
573         0x47, UCLOGIC_RDESC_PEN_PH(Y_PM),
574                                 /*          Physical Maximum (PLACEHOLDER), */
575         0x81, 0x02,             /*          Input (Variable),               */
576         0xB4,                   /*          Pop,                            */
577         0x09, 0x30,             /*          Usage (Tip Pressure),           */
578         0x27, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM),
579                                 /*          Logical Maximum (PLACEHOLDER),  */
580         0x81, 0x02,             /*          Input (Variable),               */
581         0xC0,                   /*      End Collection,                     */
582         0xC0                    /*  End Collection                          */
583 };
584
585 const size_t uclogic_rdesc_v1_pen_template_size =
586                         sizeof(uclogic_rdesc_v1_pen_template_arr);
587
588 /* Fixed report descriptor template for (tweaked) v2 pen reports */
589 const __u8 uclogic_rdesc_v2_pen_template_arr[] = {
590         0x05, 0x0D,             /*  Usage Page (Digitizer),                 */
591         0x09, 0x01,             /*  Usage (Digitizer),                      */
592         0xA1, 0x01,             /*  Collection (Application),               */
593         0x85, 0x08,             /*      Report ID (8),                      */
594         0x09, 0x20,             /*      Usage (Stylus),                     */
595         0xA0,                   /*      Collection (Physical),              */
596         0x14,                   /*          Logical Minimum (0),            */
597         0x25, 0x01,             /*          Logical Maximum (1),            */
598         0x75, 0x01,             /*          Report Size (1),                */
599         0x09, 0x42,             /*          Usage (Tip Switch),             */
600         0x09, 0x44,             /*          Usage (Barrel Switch),          */
601         0x09, 0x46,             /*          Usage (Tablet Pick),            */
602         0x95, 0x03,             /*          Report Count (3),               */
603         0x81, 0x02,             /*          Input (Variable),               */
604         0x95, 0x03,             /*          Report Count (3),               */
605         0x81, 0x03,             /*          Input (Constant, Variable),     */
606         0x09, 0x32,             /*          Usage (In Range),               */
607         0x95, 0x01,             /*          Report Count (1),               */
608         0x81, 0x02,             /*          Input (Variable),               */
609         0x95, 0x01,             /*          Report Count (1),               */
610         0x81, 0x03,             /*          Input (Constant, Variable),     */
611         0x95, 0x01,             /*          Report Count (1),               */
612         0xA4,                   /*          Push,                           */
613         0x05, 0x01,             /*          Usage Page (Desktop),           */
614         0x65, 0x13,             /*          Unit (Inch),                    */
615         0x55, 0xFD,             /*          Unit Exponent (-3),             */
616         0x75, 0x18,             /*          Report Size (24),               */
617         0x34,                   /*          Physical Minimum (0),           */
618         0x09, 0x30,             /*          Usage (X),                      */
619         0x27, UCLOGIC_RDESC_PEN_PH(X_LM),
620                                 /*          Logical Maximum (PLACEHOLDER),  */
621         0x47, UCLOGIC_RDESC_PEN_PH(X_PM),
622                                 /*          Physical Maximum (PLACEHOLDER), */
623         0x81, 0x02,             /*          Input (Variable),               */
624         0x09, 0x31,             /*          Usage (Y),                      */
625         0x27, UCLOGIC_RDESC_PEN_PH(Y_LM),
626                                 /*          Logical Maximum (PLACEHOLDER),  */
627         0x47, UCLOGIC_RDESC_PEN_PH(Y_PM),
628                                 /*          Physical Maximum (PLACEHOLDER), */
629         0x81, 0x02,             /*          Input (Variable),               */
630         0xB4,                   /*          Pop,                            */
631         0x09, 0x30,             /*          Usage (Tip Pressure),           */
632         0x75, 0x10,             /*          Report Size (16),               */
633         0x27, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM),
634                                 /*          Logical Maximum (PLACEHOLDER),  */
635         0x81, 0x02,             /*          Input (Variable),               */
636         0x54,                   /*          Unit Exponent (0),              */
637         0x65, 0x14,             /*          Unit (Degrees),                 */
638         0x35, 0xC4,             /*          Physical Minimum (-60),         */
639         0x45, 0x3C,             /*          Physical Maximum (60),          */
640         0x15, 0xC4,             /*          Logical Minimum (-60),          */
641         0x25, 0x3C,             /*          Logical Maximum (60),           */
642         0x75, 0x08,             /*          Report Size (8),                */
643         0x95, 0x02,             /*          Report Count (2),               */
644         0x09, 0x3D,             /*          Usage (X Tilt),                 */
645         0x09, 0x3E,             /*          Usage (Y Tilt),                 */
646         0x81, 0x02,             /*          Input (Variable),               */
647         0xC0,                   /*      End Collection,                     */
648         0xC0                    /*  End Collection                          */
649 };
650
651 const size_t uclogic_rdesc_v2_pen_template_size =
652                         sizeof(uclogic_rdesc_v2_pen_template_arr);
653
654 /*
655  * Expand to the contents of a generic frame buttons report descriptor.
656  *
657  * @_id:        The report ID to use.
658  * @_size:      Size of the report to pad to, including report ID, bytes.
659  */
660 #define UCLOGIC_RDESC_FRAME_BUTTONS_BYTES(_id, _size) \
661         0x05, 0x01,     /*  Usage Page (Desktop),               */ \
662         0x09, 0x07,     /*  Usage (Keypad),                     */ \
663         0xA1, 0x01,     /*  Collection (Application),           */ \
664         0x85, (_id),    /*      Report ID (_id),                */ \
665         0x14,           /*      Logical Minimum (0),            */ \
666         0x25, 0x01,     /*      Logical Maximum (1),            */ \
667         0x75, 0x01,     /*      Report Size (1),                */ \
668         0x05, 0x0D,     /*      Usage Page (Digitizer),         */ \
669         0x09, 0x39,     /*      Usage (Tablet Function Keys),   */ \
670         0xA0,           /*      Collection (Physical),          */ \
671         0x09, 0x44,     /*          Usage (Barrel Switch),      */ \
672         0x95, 0x01,     /*          Report Count (1),           */ \
673         0x81, 0x02,     /*          Input (Variable),           */ \
674         0x05, 0x01,     /*          Usage Page (Desktop),       */ \
675         0x09, 0x30,     /*          Usage (X),                  */ \
676         0x09, 0x31,     /*          Usage (Y),                  */ \
677         0x95, 0x02,     /*          Report Count (2),           */ \
678         0x81, 0x02,     /*          Input (Variable),           */ \
679         0x95, 0x15,     /*          Report Count (21),          */ \
680         0x81, 0x01,     /*          Input (Constant),           */ \
681         0x05, 0x09,     /*          Usage Page (Button),        */ \
682         0x19, 0x01,     /*          Usage Minimum (01h),        */ \
683         0x29, 0x0A,     /*          Usage Maximum (0Ah),        */ \
684         0x95, 0x0A,     /*          Report Count (10),          */ \
685         0x81, 0x02,     /*          Input (Variable),           */ \
686         0xC0,           /*      End Collection,                 */ \
687         0x05, 0x01,     /*      Usage Page (Desktop),           */ \
688         0x09, 0x05,     /*      Usage (Gamepad),                */ \
689         0xA0,           /*      Collection (Physical),          */ \
690         0x05, 0x09,     /*          Usage Page (Button),        */ \
691         0x19, 0x01,     /*          Usage Minimum (01h),        */ \
692         0x29, 0x03,     /*          Usage Maximum (03h),        */ \
693         0x95, 0x03,     /*          Report Count (3),           */ \
694         0x81, 0x02,     /*          Input (Variable),           */ \
695         0x95, ((_size) * 8 - 45),                                  \
696                         /*          Report Count (padding),     */ \
697         0x81, 0x01,     /*          Input (Constant),           */ \
698         0xC0,           /*      End Collection,                 */ \
699         0xC0            /*  End Collection                      */
700
701 /* Fixed report descriptor for (tweaked) v1 frame reports */
702 const __u8 uclogic_rdesc_v1_frame_arr[] = {
703         UCLOGIC_RDESC_FRAME_BUTTONS_BYTES(UCLOGIC_RDESC_V1_FRAME_ID, 8)
704 };
705 const size_t uclogic_rdesc_v1_frame_size =
706                         sizeof(uclogic_rdesc_v1_frame_arr);
707
708 /* Fixed report descriptor for (tweaked) v2 frame button reports */
709 const __u8 uclogic_rdesc_v2_frame_buttons_arr[] = {
710         UCLOGIC_RDESC_FRAME_BUTTONS_BYTES(UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID,
711                                           12)
712 };
713 const size_t uclogic_rdesc_v2_frame_buttons_size =
714                         sizeof(uclogic_rdesc_v2_frame_buttons_arr);
715
716 /* Fixed report descriptor for (tweaked) v2 frame touch ring reports */
717 const __u8 uclogic_rdesc_v2_frame_touch_ring_arr[] = {
718         0x05, 0x01,         /*  Usage Page (Desktop),               */
719         0x09, 0x07,         /*  Usage (Keypad),                     */
720         0xA1, 0x01,         /*  Collection (Application),           */
721         0x85, UCLOGIC_RDESC_V2_FRAME_TOUCH_ID,
722                             /*      Report ID (TOUCH_ID),           */
723         0x14,               /*      Logical Minimum (0),            */
724         0x05, 0x0D,         /*      Usage Page (Digitizer),         */
725         0x09, 0x39,         /*      Usage (Tablet Function Keys),   */
726         0xA0,               /*      Collection (Physical),          */
727         0x25, 0x01,         /*          Logical Maximum (1),        */
728         0x75, 0x01,         /*          Report Size (1),            */
729         0x05, 0x09,         /*          Usage Page (Button),        */
730         0x09, 0x01,         /*          Usage (01h),                */
731         0x95, 0x01,         /*          Report Count (1),           */
732         0x81, 0x02,         /*          Input (Variable),           */
733         0x95, 0x07,         /*          Report Count (7),           */
734         0x81, 0x01,         /*          Input (Constant),           */
735         0x75, 0x08,         /*          Report Size (8),            */
736         0x95, 0x02,         /*          Report Count (2),           */
737         0x81, 0x01,         /*          Input (Constant),           */
738         0x05, 0x0D,         /*          Usage Page (Digitizer),     */
739         0x0A, 0xFF, 0xFF,   /*          Usage (FFFFh),              */
740         0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
741         0x95, 0x01,         /*          Report Count (1),           */
742         0x81, 0x02,         /*          Input (Variable),           */
743         0x05, 0x01,         /*          Usage Page (Desktop),       */
744         0x09, 0x38,         /*          Usage (Wheel),              */
745         0x95, 0x01,         /*          Report Count (1),           */
746         0x15, 0x00,         /*          Logical Minimum (0),        */
747         0x25, 0x0B,         /*          Logical Maximum (11),       */
748         0x81, 0x02,         /*          Input (Variable),           */
749         0x09, 0x30,         /*          Usage (X),                  */
750         0x09, 0x31,         /*          Usage (Y),                  */
751         0x14,               /*          Logical Minimum (0),        */
752         0x25, 0x01,         /*          Logical Maximum (1),        */
753         0x75, 0x01,         /*          Report Size (1),            */
754         0x95, 0x02,         /*          Report Count (2),           */
755         0x81, 0x02,         /*          Input (Variable),           */
756         0x95, 0x2E,         /*          Report Count (46),          */
757         0x81, 0x01,         /*          Input (Constant),           */
758         0xC0,               /*      End Collection,                 */
759         0xC0                /*  End Collection                      */
760 };
761 const size_t uclogic_rdesc_v2_frame_touch_ring_size =
762                         sizeof(uclogic_rdesc_v2_frame_touch_ring_arr);
763
764 /* Fixed report descriptor for (tweaked) v2 frame touch strip reports */
765 const __u8 uclogic_rdesc_v2_frame_touch_strip_arr[] = {
766         0x05, 0x01,         /*  Usage Page (Desktop),               */
767         0x09, 0x07,         /*  Usage (Keypad),                     */
768         0xA1, 0x01,         /*  Collection (Application),           */
769         0x85, UCLOGIC_RDESC_V2_FRAME_TOUCH_ID,
770                             /*      Report ID (TOUCH_ID),           */
771         0x14,               /*      Logical Minimum (0),            */
772         0x05, 0x0D,         /*      Usage Page (Digitizer),         */
773         0x09, 0x39,         /*      Usage (Tablet Function Keys),   */
774         0xA0,               /*      Collection (Physical),          */
775         0x25, 0x01,         /*          Logical Maximum (1),        */
776         0x75, 0x01,         /*          Report Size (1),            */
777         0x05, 0x09,         /*          Usage Page (Button),        */
778         0x09, 0x01,         /*          Usage (01h),                */
779         0x95, 0x01,         /*          Report Count (1),           */
780         0x81, 0x02,         /*          Input (Variable),           */
781         0x95, 0x07,         /*          Report Count (7),           */
782         0x81, 0x01,         /*          Input (Constant),           */
783         0x75, 0x08,         /*          Report Size (8),            */
784         0x95, 0x02,         /*          Report Count (2),           */
785         0x81, 0x01,         /*          Input (Constant),           */
786         0x05, 0x0D,         /*          Usage Page (Digitizer),     */
787         0x0A, 0xFF, 0xFF,   /*          Usage (FFFFh),              */
788         0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
789         0x95, 0x01,         /*          Report Count (1),           */
790         0x81, 0x02,         /*          Input (Variable),           */
791         0x05, 0x01,         /*          Usage Page (Desktop),       */
792         0x09, 0x38,         /*          Usage (Wheel),              */
793         0x95, 0x01,         /*          Report Count (1),           */
794         0x15, 0x00,         /*          Logical Minimum (0),        */
795         0x25, 0x07,         /*          Logical Maximum (7),        */
796         0x81, 0x02,         /*          Input (Variable),           */
797         0x09, 0x30,         /*          Usage (X),                  */
798         0x09, 0x31,         /*          Usage (Y),                  */
799         0x14,               /*          Logical Minimum (0),        */
800         0x25, 0x01,         /*          Logical Maximum (1),        */
801         0x75, 0x01,         /*          Report Size (1),            */
802         0x95, 0x02,         /*          Report Count (2),           */
803         0x81, 0x02,         /*          Input (Variable),           */
804         0x95, 0x2E,         /*          Report Count (46),          */
805         0x81, 0x01,         /*          Input (Constant),           */
806         0xC0,               /*      End Collection,                 */
807         0xC0                /*  End Collection                      */
808 };
809 const size_t uclogic_rdesc_v2_frame_touch_strip_size =
810                         sizeof(uclogic_rdesc_v2_frame_touch_strip_arr);
811
812 /* Fixed report descriptor for (tweaked) v2 frame dial reports */
813 const __u8 uclogic_rdesc_v2_frame_dial_arr[] = {
814         0x05, 0x01,         /*  Usage Page (Desktop),               */
815         0x09, 0x07,         /*  Usage (Keypad),                     */
816         0xA1, 0x01,         /*  Collection (Application),           */
817         0x85, UCLOGIC_RDESC_V2_FRAME_DIAL_ID,
818                             /*      Report ID (DIAL_ID),            */
819         0x14,               /*      Logical Minimum (0),            */
820         0x05, 0x0D,         /*      Usage Page (Digitizer),         */
821         0x09, 0x39,         /*      Usage (Tablet Function Keys),   */
822         0xA0,               /*      Collection (Physical),          */
823         0x25, 0x01,         /*          Logical Maximum (1),        */
824         0x75, 0x01,         /*          Report Size (1),            */
825         0x95, 0x01,         /*          Report Count (1),           */
826         0x81, 0x01,         /*          Input (Constant),           */
827         0x05, 0x09,         /*          Usage Page (Button),        */
828         0x09, 0x01,         /*          Usage (01h),                */
829         0x95, 0x01,         /*          Report Count (1),           */
830         0x81, 0x02,         /*          Input (Variable),           */
831         0x95, 0x06,         /*          Report Count (6),           */
832         0x81, 0x01,         /*          Input (Constant),           */
833         0x75, 0x08,         /*          Report Size (8),            */
834         0x95, 0x02,         /*          Report Count (2),           */
835         0x81, 0x01,         /*          Input (Constant),           */
836         0x05, 0x0D,         /*          Usage Page (Digitizer),     */
837         0x0A, 0xFF, 0xFF,   /*          Usage (FFFFh),              */
838         0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
839         0x95, 0x01,         /*          Report Count (1),           */
840         0x81, 0x02,         /*          Input (Variable),           */
841         0x05, 0x01,         /*          Usage Page (Desktop),       */
842         0x09, 0x38,         /*          Usage (Wheel),              */
843         0x95, 0x01,         /*          Report Count (1),           */
844         0x15, 0xFF,         /*          Logical Minimum (-1),       */
845         0x25, 0x01,         /*          Logical Maximum (1),        */
846         0x81, 0x06,         /*          Input (Variable, Relative), */
847         0x09, 0x30,         /*          Usage (X),                  */
848         0x09, 0x31,         /*          Usage (Y),                  */
849         0x14,               /*          Logical Minimum (0),        */
850         0x25, 0x01,         /*          Logical Maximum (1),        */
851         0x75, 0x01,         /*          Report Size (1),            */
852         0x95, 0x02,         /*          Report Count (2),           */
853         0x81, 0x02,         /*          Input (Variable),           */
854         0x95, 0x2E,         /*          Report Count (46),          */
855         0x81, 0x01,         /*          Input (Constant),           */
856         0xC0,               /*      End Collection,                 */
857         0xC0                /*  End Collection                      */
858 };
859 const size_t uclogic_rdesc_v2_frame_dial_size =
860                         sizeof(uclogic_rdesc_v2_frame_dial_arr);
861
862 const __u8 uclogic_ugee_v2_probe_arr[] = {
863         0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
864 };
865 const size_t uclogic_ugee_v2_probe_size = sizeof(uclogic_ugee_v2_probe_arr);
866 const int uclogic_ugee_v2_probe_endpoint = 0x03;
867
868 /* Fixed report descriptor template for UGEE v2 pen reports */
869 const __u8 uclogic_rdesc_ugee_v2_pen_template_arr[] = {
870         0x05, 0x0d,         /*  Usage Page (Digitizers),                */
871         0x09, 0x01,         /*  Usage (Digitizer),                      */
872         0xa1, 0x01,         /*  Collection (Application),               */
873         0x85, 0x02,         /*      Report ID (2),                      */
874         0x09, 0x20,         /*      Usage (Stylus),                     */
875         0xa1, 0x00,         /*      Collection (Physical),              */
876         0x09, 0x42,         /*          Usage (Tip Switch),             */
877         0x09, 0x44,         /*          Usage (Barrel Switch),          */
878         0x09, 0x46,         /*          Usage (Tablet Pick),            */
879         0x75, 0x01,         /*          Report Size (1),                */
880         0x95, 0x03,         /*          Report Count (3),               */
881         0x14,               /*          Logical Minimum (0),            */
882         0x25, 0x01,         /*          Logical Maximum (1),            */
883         0x81, 0x02,         /*          Input (Variable),               */
884         0x95, 0x02,         /*          Report Count (2),               */
885         0x81, 0x03,         /*          Input (Constant, Variable),     */
886         0x09, 0x32,         /*          Usage (In Range),               */
887         0x95, 0x01,         /*          Report Count (1),               */
888         0x81, 0x02,         /*          Input (Variable),               */
889         0x95, 0x02,         /*          Report Count (2),               */
890         0x81, 0x03,         /*          Input (Constant, Variable),     */
891         0x75, 0x10,         /*          Report Size (16),               */
892         0x95, 0x01,         /*          Report Count (1),               */
893         0x35, 0x00,         /*          Physical Minimum (0),           */
894         0xa4,               /*          Push,                           */
895         0x05, 0x01,         /*          Usage Page (Desktop),           */
896         0x09, 0x30,         /*          Usage (X),                      */
897         0x65, 0x13,         /*          Unit (Inch),                    */
898         0x55, 0x0d,         /*          Unit Exponent (-3),             */
899         0x27, UCLOGIC_RDESC_PEN_PH(X_LM),
900                             /*          Logical Maximum (PLACEHOLDER),  */
901         0x47, UCLOGIC_RDESC_PEN_PH(X_PM),
902                             /*          Physical Maximum (PLACEHOLDER), */
903         0x81, 0x02,         /*          Input (Variable),               */
904         0x09, 0x31,         /*          Usage (Y),                      */
905         0x27, UCLOGIC_RDESC_PEN_PH(Y_LM),
906                             /*          Logical Maximum (PLACEHOLDER),  */
907         0x47, UCLOGIC_RDESC_PEN_PH(Y_PM),
908                             /*          Physical Maximum (PLACEHOLDER), */
909         0x81, 0x02,         /*          Input (Variable),               */
910         0xb4,               /*          Pop,                            */
911         0x09, 0x30,         /*          Usage (Tip Pressure),           */
912         0x45, 0x00,         /*          Physical Maximum (0),           */
913         0x27, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM),
914                             /*          Logical Maximum (PLACEHOLDER),  */
915         0x75, 0x0D,         /*          Report Size (13),               */
916         0x95, 0x01,         /*          Report Count (1),               */
917         0x81, 0x02,         /*          Input (Variable),               */
918         0x75, 0x01,         /*          Report Size (1),                */
919         0x95, 0x03,         /*          Report Count (3),               */
920         0x81, 0x01,         /*          Input (Constant),               */
921         0x09, 0x3d,         /*          Usage (X Tilt),                 */
922         0x35, 0xC3,         /*          Physical Minimum (-61),         */
923         0x45, 0x3C,         /*          Physical Maximum (60),          */
924         0x15, 0xC3,         /*          Logical Minimum (-61),          */
925         0x25, 0x3C,         /*          Logical Maximum (60),           */
926         0x75, 0x08,         /*          Report Size (8),                */
927         0x95, 0x01,         /*          Report Count (1),               */
928         0x81, 0x02,         /*          Input (Variable),               */
929         0x09, 0x3e,         /*          Usage (Y Tilt),                 */
930         0x35, 0xC3,         /*          Physical Minimum (-61),         */
931         0x45, 0x3C,         /*          Physical Maximum (60),          */
932         0x15, 0xC3,         /*          Logical Minimum (-61),          */
933         0x25, 0x3C,         /*          Logical Maximum (60),           */
934         0x81, 0x02,         /*          Input (Variable),               */
935         0xc0,               /*      End Collection,                     */
936         0xc0,               /*  End Collection                          */
937 };
938 const size_t uclogic_rdesc_ugee_v2_pen_template_size =
939                         sizeof(uclogic_rdesc_ugee_v2_pen_template_arr);
940
941 /* Fixed report descriptor template for UGEE v2 frame reports (buttons only) */
942 const __u8 uclogic_rdesc_ugee_v2_frame_btn_template_arr[] = {
943         0x05, 0x01,         /*  Usage Page (Desktop),                   */
944         0x09, 0x07,         /*  Usage (Keypad),                         */
945         0xA1, 0x01,         /*  Collection (Application),               */
946         0x85, UCLOGIC_RDESC_V1_FRAME_ID,
947                             /*      Report ID,                          */
948         0x05, 0x0D,         /*      Usage Page (Digitizer),             */
949         0x09, 0x39,         /*      Usage (Tablet Function Keys),       */
950         0xA0,               /*      Collection (Physical),              */
951         0x75, 0x01,         /*          Report Size (1),                */
952         0x95, 0x08,         /*          Report Count (8),               */
953         0x81, 0x01,         /*          Input (Constant),               */
954         0x05, 0x09,         /*          Usage Page (Button),            */
955         0x19, 0x01,         /*          Usage Minimum (01h),            */
956         UCLOGIC_RDESC_FRAME_PH_BTN,
957                             /*          Usage Maximum (PLACEHOLDER),    */
958         0x95, 0x0A,         /*          Report Count (10),              */
959         0x14,               /*          Logical Minimum (0),            */
960         0x25, 0x01,         /*          Logical Maximum (1),            */
961         0x81, 0x02,         /*          Input (Variable),               */
962         0x95, 0x46,         /*          Report Count (70),              */
963         0x81, 0x01,         /*          Input (Constant),               */
964         0xC0,               /*      End Collection,                     */
965         0xC0                /*  End Collection                          */
966 };
967 const size_t uclogic_rdesc_ugee_v2_frame_btn_template_size =
968                         sizeof(uclogic_rdesc_ugee_v2_frame_btn_template_arr);
969
970 /* Fixed report descriptor template for UGEE v2 frame reports (dial) */
971 const __u8 uclogic_rdesc_ugee_v2_frame_dial_template_arr[] = {
972         0x05, 0x01,         /*  Usage Page (Desktop),                   */
973         0x09, 0x07,         /*  Usage (Keypad),                         */
974         0xA1, 0x01,         /*  Collection (Application),               */
975         0x85, UCLOGIC_RDESC_V1_FRAME_ID,
976                             /*      Report ID,                          */
977         0x05, 0x0D,         /*      Usage Page (Digitizer),             */
978         0x09, 0x39,         /*      Usage (Tablet Function Keys),       */
979         0xA0,               /*      Collection (Physical),              */
980         0x75, 0x01,         /*          Report Size (1),                */
981         0x95, 0x08,         /*          Report Count (8),               */
982         0x81, 0x01,         /*          Input (Constant),               */
983         0x05, 0x09,         /*          Usage Page (Button),            */
984         0x19, 0x01,         /*          Usage Minimum (01h),            */
985         UCLOGIC_RDESC_FRAME_PH_BTN,
986                             /*          Usage Maximum (PLACEHOLDER),    */
987         0x95, 0x0A,         /*          Report Count (10),              */
988         0x14,               /*          Logical Minimum (0),            */
989         0x25, 0x01,         /*          Logical Maximum (1),            */
990         0x81, 0x02,         /*          Input (Variable),               */
991         0x95, 0x06,         /*          Report Count (6),               */
992         0x81, 0x01,         /*          Input (Constant),               */
993         0x75, 0x08,         /*          Report Size (8),                */
994         0x95, 0x03,         /*          Report Count (3),               */
995         0x81, 0x01,         /*          Input (Constant),               */
996         0x05, 0x01,         /*          Usage Page (Desktop),           */
997         0x09, 0x38,         /*          Usage (Wheel),                  */
998         0x95, 0x01,         /*          Report Count (1),               */
999         0x15, 0xFF,         /*          Logical Minimum (-1),           */
1000         0x25, 0x01,         /*          Logical Maximum (1),            */
1001         0x81, 0x06,         /*          Input (Variable, Relative),     */
1002         0x95, 0x02,         /*          Report Count (2),               */
1003         0x81, 0x01,         /*          Input (Constant),               */
1004         0xC0,               /*      End Collection,                     */
1005         0xC0                /*  End Collection                          */
1006 };
1007 const size_t uclogic_rdesc_ugee_v2_frame_dial_template_size =
1008                         sizeof(uclogic_rdesc_ugee_v2_frame_dial_template_arr);
1009
1010 /* Fixed report descriptor template for UGEE v2 frame reports (mouse) */
1011 const __u8 uclogic_rdesc_ugee_v2_frame_mouse_template_arr[] = {
1012         0x05, 0x01,         /*  Usage Page (Desktop),                   */
1013         0x09, 0x02,         /*  Usage (Mouse),                          */
1014         0xA1, 0x01,         /*  Collection (Application),               */
1015         0x85, 0x01,         /*      Report ID (1),                      */
1016         0x05, 0x01,         /*      Usage Page (Pointer),               */
1017         0xA0,               /*      Collection (Physical),              */
1018         0x75, 0x01,         /*          Report Size (1),                */
1019         0x95, 0x02,         /*          Report Count (2),               */
1020         0x05, 0x09,         /*          Usage Page (Button),            */
1021         0x19, 0x01,         /*          Usage Minimum (01h),            */
1022         0x29, 0x02,         /*          Usage Maximum (02h),            */
1023         0x14,               /*          Logical Minimum (0),            */
1024         0x25, 0x01,         /*          Logical Maximum (1),            */
1025         0x81, 0x02,         /*          Input (Variable),               */
1026         0x95, 0x06,         /*          Report Count (6),               */
1027         0x81, 0x01,         /*          Input (Constant),               */
1028         0x05, 0x01,         /*          Usage Page (Generic Desktop),   */
1029         0x09, 0x30,         /*          Usage (X),                      */
1030         0x09, 0x31,         /*          Usage (Y),                      */
1031         0x75, 0x10,         /*          Report Size (16),               */
1032         0x95, 0x02,         /*          Report Count (2),               */
1033         0x16, 0x00, 0x80,   /*          Logical Minimum (-32768),       */
1034         0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),        */
1035         0x81, 0x06,         /*          Input (Variable, Relative),     */
1036         0x95, 0x01,         /*          Report Count (1),               */
1037         0x81, 0x01,         /*          Input (Constant),               */
1038         0xC0,               /*      End Collection,                     */
1039         0xC0                /*  End Collection                          */
1040 };
1041 const size_t uclogic_rdesc_ugee_v2_frame_mouse_template_size =
1042                         sizeof(uclogic_rdesc_ugee_v2_frame_mouse_template_arr);
1043
1044 /* Fixed report descriptor template for UGEE v2 battery reports */
1045 const __u8 uclogic_rdesc_ugee_v2_battery_template_arr[] = {
1046         0x05, 0x01,         /*  Usage Page (Desktop),                   */
1047         0x09, 0x07,         /*  Usage (Keypad),                         */
1048         0xA1, 0x01,         /*  Collection (Application),               */
1049         0x85, UCLOGIC_RDESC_UGEE_V2_BATTERY_ID,
1050                             /*      Report ID,                          */
1051         0x75, 0x08,         /*      Report Size (8),                    */
1052         0x95, 0x02,         /*      Report Count (2),                   */
1053         0x81, 0x01,         /*      Input (Constant),                   */
1054         0x05, 0x84,         /*      Usage Page (Power Device),          */
1055         0x05, 0x85,         /*      Usage Page (Battery System),        */
1056         0x09, 0x65,         /*      Usage Page (AbsoluteStateOfCharge), */
1057         0x75, 0x08,         /*      Report Size (8),                    */
1058         0x95, 0x01,         /*      Report Count (1),                   */
1059         0x15, 0x00,         /*      Logical Minimum (0),                */
1060         0x26, 0xff, 0x00,   /*      Logical Maximum (255),              */
1061         0x81, 0x02,         /*      Input (Variable),                   */
1062         0x75, 0x01,         /*      Report Size (1),                    */
1063         0x95, 0x01,         /*      Report Count (1),                   */
1064         0x15, 0x00,         /*      Logical Minimum (0),                */
1065         0x25, 0x01,         /*      Logical Maximum (1),                */
1066         0x09, 0x44,         /*      Usage Page (Charging),              */
1067         0x81, 0x02,         /*      Input (Variable),                   */
1068         0x95, 0x07,         /*      Report Count (7),                   */
1069         0x81, 0x01,         /*      Input (Constant),                   */
1070         0x75, 0x08,         /*      Report Size (8),                    */
1071         0x95, 0x07,         /*      Report Count (7),                   */
1072         0x81, 0x01,         /*      Input (Constant),                   */
1073         0xC0                /*  End Collection                          */
1074 };
1075 const size_t uclogic_rdesc_ugee_v2_battery_template_size =
1076                         sizeof(uclogic_rdesc_ugee_v2_battery_template_arr);
1077
1078 /* Fixed report descriptor for Ugee EX07 frame */
1079 const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = {
1080         0x05, 0x01,             /*  Usage Page (Desktop),                   */
1081         0x09, 0x07,             /*  Usage (Keypad),                         */
1082         0xA1, 0x01,             /*  Collection (Application),               */
1083         0x85, 0x06,             /*      Report ID (6),                      */
1084         0x05, 0x0D,             /*      Usage Page (Digitizer),             */
1085         0x09, 0x39,             /*      Usage (Tablet Function Keys),       */
1086         0xA0,                   /*      Collection (Physical),              */
1087         0x05, 0x09,             /*          Usage Page (Button),            */
1088         0x75, 0x01,             /*          Report Size (1),                */
1089         0x19, 0x03,             /*          Usage Minimum (03h),            */
1090         0x29, 0x06,             /*          Usage Maximum (06h),            */
1091         0x95, 0x04,             /*          Report Count (4),               */
1092         0x81, 0x02,             /*          Input (Variable),               */
1093         0x95, 0x1A,             /*          Report Count (26),              */
1094         0x81, 0x03,             /*          Input (Constant, Variable),     */
1095         0x19, 0x01,             /*          Usage Minimum (01h),            */
1096         0x29, 0x02,             /*          Usage Maximum (02h),            */
1097         0x95, 0x02,             /*          Report Count (2),               */
1098         0x81, 0x02,             /*          Input (Variable),               */
1099         0xC0,                   /*      End Collection,                     */
1100         0xC0                    /*  End Collection                          */
1101 };
1102 const size_t uclogic_rdesc_ugee_ex07_frame_size =
1103                         sizeof(uclogic_rdesc_ugee_ex07_frame_arr);
1104
1105 /* Fixed report descriptor for Ugee G5 frame controls */
1106 const __u8 uclogic_rdesc_ugee_g5_frame_arr[] = {
1107         0x05, 0x01,         /*  Usage Page (Desktop),               */
1108         0x09, 0x07,         /*  Usage (Keypad),                     */
1109         0xA1, 0x01,         /*  Collection (Application),           */
1110         0x85, 0x06,         /*      Report ID (6),                  */
1111         0x05, 0x0D,         /*      Usage Page (Digitizer),         */
1112         0x09, 0x39,         /*      Usage (Tablet Function Keys),   */
1113         0xA0,               /*      Collection (Physical),          */
1114         0x14,               /*          Logical Minimum (0),        */
1115         0x25, 0x01,         /*          Logical Maximum (1),        */
1116         0x05, 0x01,         /*          Usage Page (Desktop),       */
1117         0x05, 0x09,         /*          Usage Page (Button),        */
1118         0x19, 0x01,         /*          Usage Minimum (01h),        */
1119         0x29, 0x05,         /*          Usage Maximum (05h),        */
1120         0x75, 0x01,         /*          Report Size (1),            */
1121         0x95, 0x05,         /*          Report Count (5),           */
1122         0x81, 0x02,         /*          Input (Variable),           */
1123         0x75, 0x01,         /*          Report Size (1),            */
1124         0x95, 0x03,         /*          Report Count (3),           */
1125         0x81, 0x01,         /*          Input (Constant),           */
1126         0x05, 0x0D,         /*          Usage Page (Digitizer),     */
1127         0x0A, 0xFF, 0xFF,   /*          Usage (FFFFh),              */
1128         0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
1129         0x75, 0x08,         /*          Report Size (8),            */
1130         0x95, 0x01,         /*          Report Count (1),           */
1131         0x81, 0x02,         /*          Input (Variable),           */
1132         0x25, 0x01,         /*          Logical Maximum (1),        */
1133         0x09, 0x44,         /*          Usage (Barrel Switch),      */
1134         0x75, 0x01,         /*          Report Size (1),            */
1135         0x95, 0x01,         /*          Report Count (1),           */
1136         0x81, 0x02,         /*          Input (Variable),           */
1137         0x05, 0x01,         /*          Usage Page (Desktop),       */
1138         0x09, 0x30,         /*          Usage (X),                  */
1139         0x09, 0x31,         /*          Usage (Y),                  */
1140         0x75, 0x01,         /*          Report Size (1),            */
1141         0x95, 0x02,         /*          Report Count (2),           */
1142         0x81, 0x02,         /*          Input (Variable),           */
1143         0x75, 0x01,         /*          Report Size (1),            */
1144         0x95, 0x0B,         /*          Report Count (11),          */
1145         0x81, 0x01,         /*          Input (Constant),           */
1146         0x05, 0x01,         /*          Usage Page (Desktop),       */
1147         0x09, 0x38,         /*          Usage (Wheel),              */
1148         0x15, 0xFF,         /*          Logical Minimum (-1),       */
1149         0x25, 0x01,         /*          Logical Maximum (1),        */
1150         0x75, 0x02,         /*          Report Size (2),            */
1151         0x95, 0x01,         /*          Report Count (1),           */
1152         0x81, 0x06,         /*          Input (Variable, Relative), */
1153         0xC0,               /*      End Collection,                 */
1154         0xC0                /*  End Collection                      */
1155 };
1156 const size_t uclogic_rdesc_ugee_g5_frame_size =
1157                         sizeof(uclogic_rdesc_ugee_g5_frame_arr);
1158
1159 /* Fixed report descriptor for XP-Pen Deco 01 frame controls */
1160 const __u8 uclogic_rdesc_xppen_deco01_frame_arr[] = {
1161         0x05, 0x01, /*  Usage Page (Desktop),               */
1162         0x09, 0x07, /*  Usage (Keypad),                     */
1163         0xA1, 0x01, /*  Collection (Application),           */
1164         0x85, 0x06, /*      Report ID (6),                  */
1165         0x14,       /*      Logical Minimum (0),            */
1166         0x25, 0x01, /*      Logical Maximum (1),            */
1167         0x75, 0x01, /*      Report Size (1),                */
1168         0x05, 0x0D, /*      Usage Page (Digitizer),         */
1169         0x09, 0x39, /*      Usage (Tablet Function Keys),   */
1170         0xA0,       /*      Collection (Physical),          */
1171         0x05, 0x09, /*          Usage Page (Button),        */
1172         0x19, 0x01, /*          Usage Minimum (01h),        */
1173         0x29, 0x08, /*          Usage Maximum (08h),        */
1174         0x95, 0x08, /*          Report Count (8),           */
1175         0x81, 0x02, /*          Input (Variable),           */
1176         0x05, 0x0D, /*          Usage Page (Digitizer),     */
1177         0x09, 0x44, /*          Usage (Barrel Switch),      */
1178         0x95, 0x01, /*          Report Count (1),           */
1179         0x81, 0x02, /*          Input (Variable),           */
1180         0x05, 0x01, /*          Usage Page (Desktop),       */
1181         0x09, 0x30, /*          Usage (X),                  */
1182         0x09, 0x31, /*          Usage (Y),                  */
1183         0x95, 0x02, /*          Report Count (2),           */
1184         0x81, 0x02, /*          Input (Variable),           */
1185         0x95, 0x15, /*          Report Count (21),          */
1186         0x81, 0x01, /*          Input (Constant),           */
1187         0xC0,       /*      End Collection,                 */
1188         0xC0        /*  End Collection                      */
1189 };
1190
1191 const size_t uclogic_rdesc_xppen_deco01_frame_size =
1192                         sizeof(uclogic_rdesc_xppen_deco01_frame_arr);
1193
1194 /**
1195  * uclogic_rdesc_template_apply() - apply report descriptor parameters to a
1196  * report descriptor template, creating a report descriptor. Copies the
1197  * template over to the new report descriptor and replaces every occurrence of
1198  * the template placeholders, followed by an index byte, with the value from the
1199  * parameter list at that index.
1200  *
1201  * @template_ptr:       Pointer to the template buffer.
1202  * @template_size:      Size of the template buffer.
1203  * @param_list:         List of template parameters.
1204  * @param_num:          Number of parameters in the list.
1205  *
1206  * Returns:
1207  *      Kmalloc-allocated pointer to the created report descriptor,
1208  *      or NULL if allocation failed.
1209  */
1210 __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr,
1211                                    size_t template_size,
1212                                    const s32 *param_list,
1213                                    size_t param_num)
1214 {
1215         static const __u8 btn_head[] = {UCLOGIC_RDESC_FRAME_PH_BTN_HEAD};
1216         static const __u8 pen_head[] = {UCLOGIC_RDESC_PEN_PH_HEAD};
1217         __u8 *rdesc_ptr;
1218         __u8 *p;
1219         s32 v;
1220
1221         rdesc_ptr = kmemdup(template_ptr, template_size, GFP_KERNEL);
1222         if (rdesc_ptr == NULL)
1223                 return NULL;
1224
1225         for (p = rdesc_ptr; p + sizeof(btn_head) < rdesc_ptr + template_size;) {
1226                 if (p + sizeof(pen_head) < rdesc_ptr + template_size &&
1227                     memcmp(p, pen_head, sizeof(pen_head)) == 0 &&
1228                     p[sizeof(pen_head)] < param_num) {
1229                         v = param_list[p[sizeof(pen_head)]];
1230                         put_unaligned((__force u32)cpu_to_le32(v), (s32 *)p);
1231                         p += sizeof(pen_head) + 1;
1232                 } else if (memcmp(p, btn_head, sizeof(btn_head)) == 0 &&
1233                            p[sizeof(btn_head)] < param_num) {
1234                         v = param_list[p[sizeof(btn_head)]];
1235                         put_unaligned((__u8)0x2A, p); /* Usage Maximum */
1236                         put_unaligned((__force u16)cpu_to_le16(v), (s16 *)(p + 1));
1237                         p += sizeof(btn_head) + 1;
1238                 } else {
1239                         p++;
1240                 }
1241         }
1242
1243         return rdesc_ptr;
1244 }