Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  *  HID driver for UC-Logic devices not fully compliant with HID standard
0004  *  - original and fixed report descriptors
0005  *
0006  *  Copyright (c) 2010-2017 Nikolai Kondrashov
0007  *  Copyright (c) 2013 Martin Rusko
0008  */
0009 
0010 /*
0011  * This program is free software; you can redistribute it and/or modify it
0012  * under the terms of the GNU General Public License as published by the Free
0013  * Software Foundation; either version 2 of the License, or (at your option)
0014  * any later version.
0015  */
0016 
0017 #include "hid-uclogic-rdesc.h"
0018 #include <linux/slab.h>
0019 #include <asm/unaligned.h>
0020 
0021 /* Fixed WP4030U report descriptor */
0022 __u8 uclogic_rdesc_wp4030u_fixed_arr[] = {
0023     0x05, 0x0D,         /*  Usage Page (Digitizer),             */
0024     0x09, 0x01,         /*  Usage (Digitizer),                  */
0025     0xA1, 0x01,         /*  Collection (Application),           */
0026     0x85, 0x09,         /*      Report ID (9),                  */
0027     0x09, 0x20,         /*      Usage (Stylus),                 */
0028     0xA0,               /*      Collection (Physical),          */
0029     0x75, 0x01,         /*          Report Size (1),            */
0030     0x09, 0x42,         /*          Usage (Tip Switch),         */
0031     0x09, 0x44,         /*          Usage (Barrel Switch),      */
0032     0x09, 0x46,         /*          Usage (Tablet Pick),        */
0033     0x14,               /*          Logical Minimum (0),        */
0034     0x25, 0x01,         /*          Logical Maximum (1),        */
0035     0x95, 0x03,         /*          Report Count (3),           */
0036     0x81, 0x02,         /*          Input (Variable),           */
0037     0x95, 0x05,         /*          Report Count (5),           */
0038     0x81, 0x01,         /*          Input (Constant),           */
0039     0x75, 0x10,         /*          Report Size (16),           */
0040     0x95, 0x01,         /*          Report Count (1),           */
0041     0x14,               /*          Logical Minimum (0),        */
0042     0xA4,               /*          Push,                       */
0043     0x05, 0x01,         /*          Usage Page (Desktop),       */
0044     0x55, 0xFD,         /*          Unit Exponent (-3),         */
0045     0x65, 0x13,         /*          Unit (Inch),                */
0046     0x34,               /*          Physical Minimum (0),       */
0047     0x09, 0x30,         /*          Usage (X),                  */
0048     0x46, 0xA0, 0x0F,   /*          Physical Maximum (4000),    */
0049     0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
0050     0x81, 0x02,         /*          Input (Variable),           */
0051     0x09, 0x31,         /*          Usage (Y),                  */
0052     0x46, 0xB8, 0x0B,   /*          Physical Maximum (3000),    */
0053     0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
0054     0x81, 0x02,         /*          Input (Variable),           */
0055     0xB4,               /*          Pop,                        */
0056     0x09, 0x30,         /*          Usage (Tip Pressure),       */
0057     0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
0058     0x81, 0x02,         /*          Input (Variable),           */
0059     0xC0,               /*      End Collection,                 */
0060     0xC0                /*  End Collection                      */
0061 };
0062 
0063 const size_t uclogic_rdesc_wp4030u_fixed_size =
0064             sizeof(uclogic_rdesc_wp4030u_fixed_arr);
0065 
0066 /* Fixed WP5540U report descriptor */
0067 __u8 uclogic_rdesc_wp5540u_fixed_arr[] = {
0068     0x05, 0x0D,         /*  Usage Page (Digitizer),             */
0069     0x09, 0x01,         /*  Usage (Digitizer),                  */
0070     0xA1, 0x01,         /*  Collection (Application),           */
0071     0x85, 0x09,         /*      Report ID (9),                  */
0072     0x09, 0x20,         /*      Usage (Stylus),                 */
0073     0xA0,               /*      Collection (Physical),          */
0074     0x75, 0x01,         /*          Report Size (1),            */
0075     0x09, 0x42,         /*          Usage (Tip Switch),         */
0076     0x09, 0x44,         /*          Usage (Barrel Switch),      */
0077     0x09, 0x46,         /*          Usage (Tablet Pick),        */
0078     0x14,               /*          Logical Minimum (0),        */
0079     0x25, 0x01,         /*          Logical Maximum (1),        */
0080     0x95, 0x03,         /*          Report Count (3),           */
0081     0x81, 0x02,         /*          Input (Variable),           */
0082     0x95, 0x05,         /*          Report Count (5),           */
0083     0x81, 0x01,         /*          Input (Constant),           */
0084     0x75, 0x10,         /*          Report Size (16),           */
0085     0x95, 0x01,         /*          Report Count (1),           */
0086     0x14,               /*          Logical Minimum (0),        */
0087     0xA4,               /*          Push,                       */
0088     0x05, 0x01,         /*          Usage Page (Desktop),       */
0089     0x55, 0xFD,         /*          Unit Exponent (-3),         */
0090     0x65, 0x13,         /*          Unit (Inch),                */
0091     0x34,               /*          Physical Minimum (0),       */
0092     0x09, 0x30,         /*          Usage (X),                  */
0093     0x46, 0x7C, 0x15,   /*          Physical Maximum (5500),    */
0094     0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
0095     0x81, 0x02,         /*          Input (Variable),           */
0096     0x09, 0x31,         /*          Usage (Y),                  */
0097     0x46, 0xA0, 0x0F,   /*          Physical Maximum (4000),    */
0098     0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
0099     0x81, 0x02,         /*          Input (Variable),           */
0100     0xB4,               /*          Pop,                        */
0101     0x09, 0x30,         /*          Usage (Tip Pressure),       */
0102     0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
0103     0x81, 0x02,         /*          Input (Variable),           */
0104     0xC0,               /*      End Collection,                 */
0105     0xC0,               /*  End Collection,                     */
0106     0x05, 0x01,         /*  Usage Page (Desktop),               */
0107     0x09, 0x02,         /*  Usage (Mouse),                      */
0108     0xA1, 0x01,         /*  Collection (Application),           */
0109     0x85, 0x08,         /*      Report ID (8),                  */
0110     0x09, 0x01,         /*      Usage (Pointer),                */
0111     0xA0,               /*      Collection (Physical),          */
0112     0x75, 0x01,         /*          Report Size (1),            */
0113     0x05, 0x09,         /*          Usage Page (Button),        */
0114     0x19, 0x01,         /*          Usage Minimum (01h),        */
0115     0x29, 0x03,         /*          Usage Maximum (03h),        */
0116     0x14,               /*          Logical Minimum (0),        */
0117     0x25, 0x01,         /*          Logical Maximum (1),        */
0118     0x95, 0x03,         /*          Report Count (3),           */
0119     0x81, 0x02,         /*          Input (Variable),           */
0120     0x95, 0x05,         /*          Report Count (5),           */
0121     0x81, 0x01,         /*          Input (Constant),           */
0122     0x05, 0x01,         /*          Usage Page (Desktop),       */
0123     0x75, 0x08,         /*          Report Size (8),            */
0124     0x09, 0x30,         /*          Usage (X),                  */
0125     0x09, 0x31,         /*          Usage (Y),                  */
0126     0x15, 0x81,         /*          Logical Minimum (-127),     */
0127     0x25, 0x7F,         /*          Logical Maximum (127),      */
0128     0x95, 0x02,         /*          Report Count (2),           */
0129     0x81, 0x06,         /*          Input (Variable, Relative), */
0130     0x09, 0x38,         /*          Usage (Wheel),              */
0131     0x15, 0xFF,         /*          Logical Minimum (-1),       */
0132     0x25, 0x01,         /*          Logical Maximum (1),        */
0133     0x95, 0x01,         /*          Report Count (1),           */
0134     0x81, 0x06,         /*          Input (Variable, Relative), */
0135     0x81, 0x01,         /*          Input (Constant),           */
0136     0xC0,               /*      End Collection,                 */
0137     0xC0                /*  End Collection                      */
0138 };
0139 
0140 const size_t uclogic_rdesc_wp5540u_fixed_size =
0141             sizeof(uclogic_rdesc_wp5540u_fixed_arr);
0142 
0143 /* Fixed WP8060U report descriptor */
0144 __u8 uclogic_rdesc_wp8060u_fixed_arr[] = {
0145     0x05, 0x0D,         /*  Usage Page (Digitizer),             */
0146     0x09, 0x01,         /*  Usage (Digitizer),                  */
0147     0xA1, 0x01,         /*  Collection (Application),           */
0148     0x85, 0x09,         /*      Report ID (9),                  */
0149     0x09, 0x20,         /*      Usage (Stylus),                 */
0150     0xA0,               /*      Collection (Physical),          */
0151     0x75, 0x01,         /*          Report Size (1),            */
0152     0x09, 0x42,         /*          Usage (Tip Switch),         */
0153     0x09, 0x44,         /*          Usage (Barrel Switch),      */
0154     0x09, 0x46,         /*          Usage (Tablet Pick),        */
0155     0x14,               /*          Logical Minimum (0),        */
0156     0x25, 0x01,         /*          Logical Maximum (1),        */
0157     0x95, 0x03,         /*          Report Count (3),           */
0158     0x81, 0x02,         /*          Input (Variable),           */
0159     0x95, 0x05,         /*          Report Count (5),           */
0160     0x81, 0x01,         /*          Input (Constant),           */
0161     0x75, 0x10,         /*          Report Size (16),           */
0162     0x95, 0x01,         /*          Report Count (1),           */
0163     0x14,               /*          Logical Minimum (0),        */
0164     0xA4,               /*          Push,                       */
0165     0x05, 0x01,         /*          Usage Page (Desktop),       */
0166     0x55, 0xFD,         /*          Unit Exponent (-3),         */
0167     0x65, 0x13,         /*          Unit (Inch),                */
0168     0x34,               /*          Physical Minimum (0),       */
0169     0x09, 0x30,         /*          Usage (X),                  */
0170     0x46, 0x40, 0x1F,   /*          Physical Maximum (8000),    */
0171     0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
0172     0x81, 0x02,         /*          Input (Variable),           */
0173     0x09, 0x31,         /*          Usage (Y),                  */
0174     0x46, 0x70, 0x17,   /*          Physical Maximum (6000),    */
0175     0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
0176     0x81, 0x02,         /*          Input (Variable),           */
0177     0xB4,               /*          Pop,                        */
0178     0x09, 0x30,         /*          Usage (Tip Pressure),       */
0179     0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
0180     0x81, 0x02,         /*          Input (Variable),           */
0181     0xC0,               /*      End Collection,                 */
0182     0xC0,               /*  End Collection,                     */
0183     0x05, 0x01,         /*  Usage Page (Desktop),               */
0184     0x09, 0x02,         /*  Usage (Mouse),                      */
0185     0xA1, 0x01,         /*  Collection (Application),           */
0186     0x85, 0x08,         /*      Report ID (8),                  */
0187     0x09, 0x01,         /*      Usage (Pointer),                */
0188     0xA0,               /*      Collection (Physical),          */
0189     0x75, 0x01,         /*          Report Size (1),            */
0190     0x05, 0x09,         /*          Usage Page (Button),        */
0191     0x19, 0x01,         /*          Usage Minimum (01h),        */
0192     0x29, 0x03,         /*          Usage Maximum (03h),        */
0193     0x14,               /*          Logical Minimum (0),        */
0194     0x25, 0x01,         /*          Logical Maximum (1),        */
0195     0x95, 0x03,         /*          Report Count (3),           */
0196     0x81, 0x02,         /*          Input (Variable),           */
0197     0x95, 0x05,         /*          Report Count (5),           */
0198     0x81, 0x01,         /*          Input (Constant),           */
0199     0x05, 0x01,         /*          Usage Page (Desktop),       */
0200     0x75, 0x08,         /*          Report Size (8),            */
0201     0x09, 0x30,         /*          Usage (X),                  */
0202     0x09, 0x31,         /*          Usage (Y),                  */
0203     0x15, 0x81,         /*          Logical Minimum (-127),     */
0204     0x25, 0x7F,         /*          Logical Maximum (127),      */
0205     0x95, 0x02,         /*          Report Count (2),           */
0206     0x81, 0x06,         /*          Input (Variable, Relative), */
0207     0x09, 0x38,         /*          Usage (Wheel),              */
0208     0x15, 0xFF,         /*          Logical Minimum (-1),       */
0209     0x25, 0x01,         /*          Logical Maximum (1),        */
0210     0x95, 0x01,         /*          Report Count (1),           */
0211     0x81, 0x06,         /*          Input (Variable, Relative), */
0212     0x81, 0x01,         /*          Input (Constant),           */
0213     0xC0,               /*      End Collection,                 */
0214     0xC0                /*  End Collection                      */
0215 };
0216 
0217 const size_t uclogic_rdesc_wp8060u_fixed_size =
0218             sizeof(uclogic_rdesc_wp8060u_fixed_arr);
0219 
0220 /* Fixed WP1062 report descriptor */
0221 __u8 uclogic_rdesc_wp1062_fixed_arr[] = {
0222     0x05, 0x0D,         /*  Usage Page (Digitizer),             */
0223     0x09, 0x01,         /*  Usage (Digitizer),                  */
0224     0xA1, 0x01,         /*  Collection (Application),           */
0225     0x85, 0x09,         /*      Report ID (9),                  */
0226     0x09, 0x20,         /*      Usage (Stylus),                 */
0227     0xA0,               /*      Collection (Physical),          */
0228     0x75, 0x01,         /*          Report Size (1),            */
0229     0x09, 0x42,         /*          Usage (Tip Switch),         */
0230     0x09, 0x44,         /*          Usage (Barrel Switch),      */
0231     0x09, 0x46,         /*          Usage (Tablet Pick),        */
0232     0x14,               /*          Logical Minimum (0),        */
0233     0x25, 0x01,         /*          Logical Maximum (1),        */
0234     0x95, 0x03,         /*          Report Count (3),           */
0235     0x81, 0x02,         /*          Input (Variable),           */
0236     0x95, 0x04,         /*          Report Count (4),           */
0237     0x81, 0x01,         /*          Input (Constant),           */
0238     0x09, 0x32,         /*          Usage (In Range),           */
0239     0x95, 0x01,         /*          Report Count (1),           */
0240     0x81, 0x02,         /*          Input (Variable),           */
0241     0x75, 0x10,         /*          Report Size (16),           */
0242     0x95, 0x01,         /*          Report Count (1),           */
0243     0x14,               /*          Logical Minimum (0),        */
0244     0xA4,               /*          Push,                       */
0245     0x05, 0x01,         /*          Usage Page (Desktop),       */
0246     0x55, 0xFD,         /*          Unit Exponent (-3),         */
0247     0x65, 0x13,         /*          Unit (Inch),                */
0248     0x34,               /*          Physical Minimum (0),       */
0249     0x09, 0x30,         /*          Usage (X),                  */
0250     0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
0251     0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
0252     0x81, 0x02,         /*          Input (Variable),           */
0253     0x09, 0x31,         /*          Usage (Y),                  */
0254     0x46, 0xB7, 0x19,   /*          Physical Maximum (6583),    */
0255     0x26, 0x6E, 0x33,   /*          Logical Maximum (13166),    */
0256     0x81, 0x02,         /*          Input (Variable),           */
0257     0xB4,               /*          Pop,                        */
0258     0x09, 0x30,         /*          Usage (Tip Pressure),       */
0259     0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
0260     0x81, 0x02,         /*          Input (Variable),           */
0261     0xC0,               /*      End Collection,                 */
0262     0xC0                /*  End Collection                      */
0263 };
0264 
0265 const size_t uclogic_rdesc_wp1062_fixed_size =
0266             sizeof(uclogic_rdesc_wp1062_fixed_arr);
0267 
0268 /* Fixed PF1209 report descriptor */
0269 __u8 uclogic_rdesc_pf1209_fixed_arr[] = {
0270     0x05, 0x0D,         /*  Usage Page (Digitizer),             */
0271     0x09, 0x01,         /*  Usage (Digitizer),                  */
0272     0xA1, 0x01,         /*  Collection (Application),           */
0273     0x85, 0x09,         /*      Report ID (9),                  */
0274     0x09, 0x20,         /*      Usage (Stylus),                 */
0275     0xA0,               /*      Collection (Physical),          */
0276     0x75, 0x01,         /*          Report Size (1),            */
0277     0x09, 0x42,         /*          Usage (Tip Switch),         */
0278     0x09, 0x44,         /*          Usage (Barrel Switch),      */
0279     0x09, 0x46,         /*          Usage (Tablet Pick),        */
0280     0x14,               /*          Logical Minimum (0),        */
0281     0x25, 0x01,         /*          Logical Maximum (1),        */
0282     0x95, 0x03,         /*          Report Count (3),           */
0283     0x81, 0x02,         /*          Input (Variable),           */
0284     0x95, 0x05,         /*          Report Count (5),           */
0285     0x81, 0x01,         /*          Input (Constant),           */
0286     0x75, 0x10,         /*          Report Size (16),           */
0287     0x95, 0x01,         /*          Report Count (1),           */
0288     0x14,               /*          Logical Minimum (0),        */
0289     0xA4,               /*          Push,                       */
0290     0x05, 0x01,         /*          Usage Page (Desktop),       */
0291     0x55, 0xFD,         /*          Unit Exponent (-3),         */
0292     0x65, 0x13,         /*          Unit (Inch),                */
0293     0x34,               /*          Physical Minimum (0),       */
0294     0x09, 0x30,         /*          Usage (X),                  */
0295     0x46, 0xE0, 0x2E,   /*          Physical Maximum (12000),   */
0296     0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
0297     0x81, 0x02,         /*          Input (Variable),           */
0298     0x09, 0x31,         /*          Usage (Y),                  */
0299     0x46, 0x28, 0x23,   /*          Physical Maximum (9000),    */
0300     0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
0301     0x81, 0x02,         /*          Input (Variable),           */
0302     0xB4,               /*          Pop,                        */
0303     0x09, 0x30,         /*          Usage (Tip Pressure),       */
0304     0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
0305     0x81, 0x02,         /*          Input (Variable),           */
0306     0xC0,               /*      End Collection,                 */
0307     0xC0,               /*  End Collection,                     */
0308     0x05, 0x01,         /*  Usage Page (Desktop),               */
0309     0x09, 0x02,         /*  Usage (Mouse),                      */
0310     0xA1, 0x01,         /*  Collection (Application),           */
0311     0x85, 0x08,         /*      Report ID (8),                  */
0312     0x09, 0x01,         /*      Usage (Pointer),                */
0313     0xA0,               /*      Collection (Physical),          */
0314     0x75, 0x01,         /*          Report Size (1),            */
0315     0x05, 0x09,         /*          Usage Page (Button),        */
0316     0x19, 0x01,         /*          Usage Minimum (01h),        */
0317     0x29, 0x03,         /*          Usage Maximum (03h),        */
0318     0x14,               /*          Logical Minimum (0),        */
0319     0x25, 0x01,         /*          Logical Maximum (1),        */
0320     0x95, 0x03,         /*          Report Count (3),           */
0321     0x81, 0x02,         /*          Input (Variable),           */
0322     0x95, 0x05,         /*          Report Count (5),           */
0323     0x81, 0x01,         /*          Input (Constant),           */
0324     0x05, 0x01,         /*          Usage Page (Desktop),       */
0325     0x75, 0x08,         /*          Report Size (8),            */
0326     0x09, 0x30,         /*          Usage (X),                  */
0327     0x09, 0x31,         /*          Usage (Y),                  */
0328     0x15, 0x81,         /*          Logical Minimum (-127),     */
0329     0x25, 0x7F,         /*          Logical Maximum (127),      */
0330     0x95, 0x02,         /*          Report Count (2),           */
0331     0x81, 0x06,         /*          Input (Variable, Relative), */
0332     0x09, 0x38,         /*          Usage (Wheel),              */
0333     0x15, 0xFF,         /*          Logical Minimum (-1),       */
0334     0x25, 0x01,         /*          Logical Maximum (1),        */
0335     0x95, 0x01,         /*          Report Count (1),           */
0336     0x81, 0x06,         /*          Input (Variable, Relative), */
0337     0x81, 0x01,         /*          Input (Constant),           */
0338     0xC0,               /*      End Collection,                 */
0339     0xC0                /*  End Collection                      */
0340 };
0341 
0342 const size_t uclogic_rdesc_pf1209_fixed_size =
0343             sizeof(uclogic_rdesc_pf1209_fixed_arr);
0344 
0345 /* Fixed PID 0522 tablet report descriptor, interface 0 (stylus) */
0346 __u8 uclogic_rdesc_twhl850_fixed0_arr[] = {
0347     0x05, 0x0D,         /*  Usage Page (Digitizer),             */
0348     0x09, 0x01,         /*  Usage (Digitizer),                  */
0349     0xA1, 0x01,         /*  Collection (Application),           */
0350     0x85, 0x09,         /*      Report ID (9),                  */
0351     0x09, 0x20,         /*      Usage (Stylus),                 */
0352     0xA0,               /*      Collection (Physical),          */
0353     0x14,               /*          Logical Minimum (0),        */
0354     0x25, 0x01,         /*          Logical Maximum (1),        */
0355     0x75, 0x01,         /*          Report Size (1),            */
0356     0x95, 0x03,         /*          Report Count (3),           */
0357     0x09, 0x42,         /*          Usage (Tip Switch),         */
0358     0x09, 0x44,         /*          Usage (Barrel Switch),      */
0359     0x09, 0x46,         /*          Usage (Tablet Pick),        */
0360     0x81, 0x02,         /*          Input (Variable),           */
0361     0x81, 0x03,         /*          Input (Constant, Variable), */
0362     0x95, 0x01,         /*          Report Count (1),           */
0363     0x09, 0x32,         /*          Usage (In Range),           */
0364     0x81, 0x02,         /*          Input (Variable),           */
0365     0x81, 0x03,         /*          Input (Constant, Variable), */
0366     0x75, 0x10,         /*          Report Size (16),           */
0367     0xA4,               /*          Push,                       */
0368     0x05, 0x01,         /*          Usage Page (Desktop),       */
0369     0x65, 0x13,         /*          Unit (Inch),                */
0370     0x55, 0xFD,         /*          Unit Exponent (-3),         */
0371     0x34,               /*          Physical Minimum (0),       */
0372     0x09, 0x30,         /*          Usage (X),                  */
0373     0x46, 0x40, 0x1F,   /*          Physical Maximum (8000),    */
0374     0x26, 0x00, 0x7D,   /*          Logical Maximum (32000),    */
0375     0x81, 0x02,         /*          Input (Variable),           */
0376     0x09, 0x31,         /*          Usage (Y),                  */
0377     0x46, 0x88, 0x13,   /*          Physical Maximum (5000),    */
0378     0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
0379     0x81, 0x02,         /*          Input (Variable),           */
0380     0xB4,               /*          Pop,                        */
0381     0x09, 0x30,         /*          Usage (Tip Pressure),       */
0382     0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
0383     0x81, 0x02,         /*          Input (Variable),           */
0384     0xC0,               /*      End Collection,                 */
0385     0xC0                /*  End Collection                      */
0386 };
0387 
0388 const size_t uclogic_rdesc_twhl850_fixed0_size =
0389             sizeof(uclogic_rdesc_twhl850_fixed0_arr);
0390 
0391 /* Fixed PID 0522 tablet report descriptor, interface 1 (mouse) */
0392 __u8 uclogic_rdesc_twhl850_fixed1_arr[] = {
0393     0x05, 0x01,         /*  Usage Page (Desktop),               */
0394     0x09, 0x02,         /*  Usage (Mouse),                      */
0395     0xA1, 0x01,         /*  Collection (Application),           */
0396     0x85, 0x01,         /*      Report ID (1),                  */
0397     0x09, 0x01,         /*      Usage (Pointer),                */
0398     0xA0,               /*      Collection (Physical),          */
0399     0x05, 0x09,         /*          Usage Page (Button),        */
0400     0x75, 0x01,         /*          Report Size (1),            */
0401     0x95, 0x03,         /*          Report Count (3),           */
0402     0x19, 0x01,         /*          Usage Minimum (01h),        */
0403     0x29, 0x03,         /*          Usage Maximum (03h),        */
0404     0x14,               /*          Logical Minimum (0),        */
0405     0x25, 0x01,         /*          Logical Maximum (1),        */
0406     0x81, 0x02,         /*          Input (Variable),           */
0407     0x95, 0x05,         /*          Report Count (5),           */
0408     0x81, 0x03,         /*          Input (Constant, Variable), */
0409     0x05, 0x01,         /*          Usage Page (Desktop),       */
0410     0x09, 0x30,         /*          Usage (X),                  */
0411     0x09, 0x31,         /*          Usage (Y),                  */
0412     0x16, 0x00, 0x80,   /*          Logical Minimum (-32768),   */
0413     0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
0414     0x75, 0x10,         /*          Report Size (16),           */
0415     0x95, 0x02,         /*          Report Count (2),           */
0416     0x81, 0x06,         /*          Input (Variable, Relative), */
0417     0x09, 0x38,         /*          Usage (Wheel),              */
0418     0x15, 0xFF,         /*          Logical Minimum (-1),       */
0419     0x25, 0x01,         /*          Logical Maximum (1),        */
0420     0x95, 0x01,         /*          Report Count (1),           */
0421     0x75, 0x08,         /*          Report Size (8),            */
0422     0x81, 0x06,         /*          Input (Variable, Relative), */
0423     0x81, 0x03,         /*          Input (Constant, Variable), */
0424     0xC0,               /*      End Collection,                 */
0425     0xC0                /*  End Collection                      */
0426 };
0427 
0428 const size_t uclogic_rdesc_twhl850_fixed1_size =
0429             sizeof(uclogic_rdesc_twhl850_fixed1_arr);
0430 
0431 /* Fixed PID 0522 tablet report descriptor, interface 2 (frame buttons) */
0432 __u8 uclogic_rdesc_twhl850_fixed2_arr[] = {
0433     0x05, 0x01,         /*  Usage Page (Desktop),               */
0434     0x09, 0x06,         /*  Usage (Keyboard),                   */
0435     0xA1, 0x01,         /*  Collection (Application),           */
0436     0x85, 0x03,         /*      Report ID (3),                  */
0437     0x05, 0x07,         /*      Usage Page (Keyboard),          */
0438     0x14,               /*      Logical Minimum (0),            */
0439     0x19, 0xE0,         /*      Usage Minimum (KB Leftcontrol), */
0440     0x29, 0xE7,         /*      Usage Maximum (KB Right GUI),   */
0441     0x25, 0x01,         /*      Logical Maximum (1),            */
0442     0x75, 0x01,         /*      Report Size (1),                */
0443     0x95, 0x08,         /*      Report Count (8),               */
0444     0x81, 0x02,         /*      Input (Variable),               */
0445     0x18,               /*      Usage Minimum (None),           */
0446     0x29, 0xFF,         /*      Usage Maximum (FFh),            */
0447     0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
0448     0x75, 0x08,         /*      Report Size (8),                */
0449     0x95, 0x06,         /*      Report Count (6),               */
0450     0x80,               /*      Input,                          */
0451     0xC0                /*  End Collection                      */
0452 };
0453 
0454 const size_t uclogic_rdesc_twhl850_fixed2_size =
0455             sizeof(uclogic_rdesc_twhl850_fixed2_arr);
0456 
0457 /* Fixed TWHA60 report descriptor, interface 0 (stylus) */
0458 __u8 uclogic_rdesc_twha60_fixed0_arr[] = {
0459     0x05, 0x0D,         /*  Usage Page (Digitizer),             */
0460     0x09, 0x01,         /*  Usage (Digitizer),                  */
0461     0xA1, 0x01,         /*  Collection (Application),           */
0462     0x85, 0x09,         /*      Report ID (9),                  */
0463     0x09, 0x20,         /*      Usage (Stylus),                 */
0464     0xA0,               /*      Collection (Physical),          */
0465     0x75, 0x01,         /*          Report Size (1),            */
0466     0x09, 0x42,         /*          Usage (Tip Switch),         */
0467     0x09, 0x44,         /*          Usage (Barrel Switch),      */
0468     0x09, 0x46,         /*          Usage (Tablet Pick),        */
0469     0x14,               /*          Logical Minimum (0),        */
0470     0x25, 0x01,         /*          Logical Maximum (1),        */
0471     0x95, 0x03,         /*          Report Count (3),           */
0472     0x81, 0x02,         /*          Input (Variable),           */
0473     0x95, 0x04,         /*          Report Count (4),           */
0474     0x81, 0x01,         /*          Input (Constant),           */
0475     0x09, 0x32,         /*          Usage (In Range),           */
0476     0x95, 0x01,         /*          Report Count (1),           */
0477     0x81, 0x02,         /*          Input (Variable),           */
0478     0x75, 0x10,         /*          Report Size (16),           */
0479     0x95, 0x01,         /*          Report Count (1),           */
0480     0x14,               /*          Logical Minimum (0),        */
0481     0xA4,               /*          Push,                       */
0482     0x05, 0x01,         /*          Usage Page (Desktop),       */
0483     0x55, 0xFD,         /*          Unit Exponent (-3),         */
0484     0x65, 0x13,         /*          Unit (Inch),                */
0485     0x34,               /*          Physical Minimum (0),       */
0486     0x09, 0x30,         /*          Usage (X),                  */
0487     0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
0488     0x27, 0x3F, 0x9C,
0489         0x00, 0x00, /*          Logical Maximum (39999),    */
0490     0x81, 0x02,         /*          Input (Variable),           */
0491     0x09, 0x31,         /*          Usage (Y),                  */
0492     0x46, 0x6A, 0x18,   /*          Physical Maximum (6250),    */
0493     0x26, 0xA7, 0x61,   /*          Logical Maximum (24999),    */
0494     0x81, 0x02,         /*          Input (Variable),           */
0495     0xB4,               /*          Pop,                        */
0496     0x09, 0x30,         /*          Usage (Tip Pressure),       */
0497     0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
0498     0x81, 0x02,         /*          Input (Variable),           */
0499     0xC0,               /*      End Collection,                 */
0500     0xC0                /*  End Collection                      */
0501 };
0502 
0503 const size_t uclogic_rdesc_twha60_fixed0_size =
0504             sizeof(uclogic_rdesc_twha60_fixed0_arr);
0505 
0506 /* Fixed TWHA60 report descriptor, interface 1 (frame buttons) */
0507 __u8 uclogic_rdesc_twha60_fixed1_arr[] = {
0508     0x05, 0x01, /*  Usage Page (Desktop),       */
0509     0x09, 0x06, /*  Usage (Keyboard),           */
0510     0xA1, 0x01, /*  Collection (Application),   */
0511     0x85, 0x05, /*      Report ID (5),          */
0512     0x05, 0x07, /*      Usage Page (Keyboard),  */
0513     0x14,       /*      Logical Minimum (0),    */
0514     0x25, 0x01, /*      Logical Maximum (1),    */
0515     0x75, 0x01, /*      Report Size (1),        */
0516     0x95, 0x08, /*      Report Count (8),       */
0517     0x81, 0x01, /*      Input (Constant),       */
0518     0x95, 0x0C, /*      Report Count (12),      */
0519     0x19, 0x3A, /*      Usage Minimum (KB F1),  */
0520     0x29, 0x45, /*      Usage Maximum (KB F12), */
0521     0x81, 0x02, /*      Input (Variable),       */
0522     0x95, 0x0C, /*      Report Count (12),      */
0523     0x19, 0x68, /*      Usage Minimum (KB F13), */
0524     0x29, 0x73, /*      Usage Maximum (KB F24), */
0525     0x81, 0x02, /*      Input (Variable),       */
0526     0x95, 0x08, /*      Report Count (8),       */
0527     0x81, 0x01, /*      Input (Constant),       */
0528     0xC0        /*  End Collection              */
0529 };
0530 
0531 const size_t uclogic_rdesc_twha60_fixed1_size =
0532             sizeof(uclogic_rdesc_twha60_fixed1_arr);
0533 
0534 /* Fixed report descriptor template for (tweaked) v1 pen reports */
0535 const __u8 uclogic_rdesc_v1_pen_template_arr[] = {
0536     0x05, 0x0D,             /*  Usage Page (Digitizer),                 */
0537     0x09, 0x01,             /*  Usage (Digitizer),                      */
0538     0xA1, 0x01,             /*  Collection (Application),               */
0539     0x85, 0x07,             /*      Report ID (7),                      */
0540     0x09, 0x20,             /*      Usage (Stylus),                     */
0541     0xA0,                   /*      Collection (Physical),              */
0542     0x14,                   /*          Logical Minimum (0),            */
0543     0x25, 0x01,             /*          Logical Maximum (1),            */
0544     0x75, 0x01,             /*          Report Size (1),                */
0545     0x09, 0x42,             /*          Usage (Tip Switch),             */
0546     0x09, 0x44,             /*          Usage (Barrel Switch),          */
0547     0x09, 0x46,             /*          Usage (Tablet Pick),            */
0548     0x95, 0x03,             /*          Report Count (3),               */
0549     0x81, 0x02,             /*          Input (Variable),               */
0550     0x95, 0x03,             /*          Report Count (3),               */
0551     0x81, 0x03,             /*          Input (Constant, Variable),     */
0552     0x09, 0x32,             /*          Usage (In Range),               */
0553     0x95, 0x01,             /*          Report Count (1),               */
0554     0x81, 0x02,             /*          Input (Variable),               */
0555     0x95, 0x01,             /*          Report Count (1),               */
0556     0x81, 0x03,             /*          Input (Constant, Variable),     */
0557     0x75, 0x10,             /*          Report Size (16),               */
0558     0x95, 0x01,             /*          Report Count (1),               */
0559     0xA4,                   /*          Push,                           */
0560     0x05, 0x01,             /*          Usage Page (Desktop),           */
0561     0x65, 0x13,             /*          Unit (Inch),                    */
0562     0x55, 0xFD,             /*          Unit Exponent (-3),             */
0563     0x34,                   /*          Physical Minimum (0),           */
0564     0x09, 0x30,             /*          Usage (X),                      */
0565     0x27, UCLOGIC_RDESC_PEN_PH(X_LM),
0566                 /*          Logical Maximum (PLACEHOLDER),  */
0567     0x47, UCLOGIC_RDESC_PEN_PH(X_PM),
0568                 /*          Physical Maximum (PLACEHOLDER), */
0569     0x81, 0x02,             /*          Input (Variable),               */
0570     0x09, 0x31,             /*          Usage (Y),                      */
0571     0x27, UCLOGIC_RDESC_PEN_PH(Y_LM),
0572                 /*          Logical Maximum (PLACEHOLDER),  */
0573     0x47, UCLOGIC_RDESC_PEN_PH(Y_PM),
0574                 /*          Physical Maximum (PLACEHOLDER), */
0575     0x81, 0x02,             /*          Input (Variable),               */
0576     0xB4,                   /*          Pop,                            */
0577     0x09, 0x30,             /*          Usage (Tip Pressure),           */
0578     0x27, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM),
0579                 /*          Logical Maximum (PLACEHOLDER),  */
0580     0x81, 0x02,             /*          Input (Variable),               */
0581     0xC0,                   /*      End Collection,                     */
0582     0xC0                    /*  End Collection                          */
0583 };
0584 
0585 const size_t uclogic_rdesc_v1_pen_template_size =
0586             sizeof(uclogic_rdesc_v1_pen_template_arr);
0587 
0588 /* Fixed report descriptor template for (tweaked) v2 pen reports */
0589 const __u8 uclogic_rdesc_v2_pen_template_arr[] = {
0590     0x05, 0x0D,             /*  Usage Page (Digitizer),                 */
0591     0x09, 0x01,             /*  Usage (Digitizer),                      */
0592     0xA1, 0x01,             /*  Collection (Application),               */
0593     0x85, 0x08,             /*      Report ID (8),                      */
0594     0x09, 0x20,             /*      Usage (Stylus),                     */
0595     0xA0,                   /*      Collection (Physical),              */
0596     0x14,                   /*          Logical Minimum (0),            */
0597     0x25, 0x01,             /*          Logical Maximum (1),            */
0598     0x75, 0x01,             /*          Report Size (1),                */
0599     0x09, 0x42,             /*          Usage (Tip Switch),             */
0600     0x09, 0x44,             /*          Usage (Barrel Switch),          */
0601     0x09, 0x46,             /*          Usage (Tablet Pick),            */
0602     0x95, 0x03,             /*          Report Count (3),               */
0603     0x81, 0x02,             /*          Input (Variable),               */
0604     0x95, 0x03,             /*          Report Count (3),               */
0605     0x81, 0x03,             /*          Input (Constant, Variable),     */
0606     0x09, 0x32,             /*          Usage (In Range),               */
0607     0x95, 0x01,             /*          Report Count (1),               */
0608     0x81, 0x02,             /*          Input (Variable),               */
0609     0x95, 0x01,             /*          Report Count (1),               */
0610     0x81, 0x03,             /*          Input (Constant, Variable),     */
0611     0x95, 0x01,             /*          Report Count (1),               */
0612     0xA4,                   /*          Push,                           */
0613     0x05, 0x01,             /*          Usage Page (Desktop),           */
0614     0x65, 0x13,             /*          Unit (Inch),                    */
0615     0x55, 0xFD,             /*          Unit Exponent (-3),             */
0616     0x75, 0x18,             /*          Report Size (24),               */
0617     0x34,                   /*          Physical Minimum (0),           */
0618     0x09, 0x30,             /*          Usage (X),                      */
0619     0x27, UCLOGIC_RDESC_PEN_PH(X_LM),
0620                 /*          Logical Maximum (PLACEHOLDER),  */
0621     0x47, UCLOGIC_RDESC_PEN_PH(X_PM),
0622                 /*          Physical Maximum (PLACEHOLDER), */
0623     0x81, 0x02,             /*          Input (Variable),               */
0624     0x09, 0x31,             /*          Usage (Y),                      */
0625     0x27, UCLOGIC_RDESC_PEN_PH(Y_LM),
0626                 /*          Logical Maximum (PLACEHOLDER),  */
0627     0x47, UCLOGIC_RDESC_PEN_PH(Y_PM),
0628                 /*          Physical Maximum (PLACEHOLDER), */
0629     0x81, 0x02,             /*          Input (Variable),               */
0630     0xB4,                   /*          Pop,                            */
0631     0x09, 0x30,             /*          Usage (Tip Pressure),           */
0632     0x75, 0x10,             /*          Report Size (16),               */
0633     0x27, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM),
0634                 /*          Logical Maximum (PLACEHOLDER),  */
0635     0x81, 0x02,             /*          Input (Variable),               */
0636     0x54,                   /*          Unit Exponent (0),              */
0637     0x65, 0x14,             /*          Unit (Degrees),                 */
0638     0x35, 0xC4,             /*          Physical Minimum (-60),         */
0639     0x45, 0x3C,             /*          Physical Maximum (60),          */
0640     0x15, 0xC4,             /*          Logical Minimum (-60),          */
0641     0x25, 0x3C,             /*          Logical Maximum (60),           */
0642     0x75, 0x08,             /*          Report Size (8),                */
0643     0x95, 0x02,             /*          Report Count (2),               */
0644     0x09, 0x3D,             /*          Usage (X Tilt),                 */
0645     0x09, 0x3E,             /*          Usage (Y Tilt),                 */
0646     0x81, 0x02,             /*          Input (Variable),               */
0647     0xC0,                   /*      End Collection,                     */
0648     0xC0                    /*  End Collection                          */
0649 };
0650 
0651 const size_t uclogic_rdesc_v2_pen_template_size =
0652             sizeof(uclogic_rdesc_v2_pen_template_arr);
0653 
0654 /*
0655  * Expand to the contents of a generic frame buttons report descriptor.
0656  *
0657  * @_id:    The report ID to use.
0658  * @_size:  Size of the report to pad to, including report ID, bytes.
0659  */
0660 #define UCLOGIC_RDESC_FRAME_BUTTONS_BYTES(_id, _size) \
0661     0x05, 0x01,     /*  Usage Page (Desktop),               */ \
0662     0x09, 0x07,     /*  Usage (Keypad),                     */ \
0663     0xA1, 0x01,     /*  Collection (Application),           */ \
0664     0x85, (_id),    /*      Report ID (_id),                */ \
0665     0x14,           /*      Logical Minimum (0),            */ \
0666     0x25, 0x01,     /*      Logical Maximum (1),            */ \
0667     0x75, 0x01,     /*      Report Size (1),                */ \
0668     0x05, 0x0D,     /*      Usage Page (Digitizer),         */ \
0669     0x09, 0x39,     /*      Usage (Tablet Function Keys),   */ \
0670     0xA0,           /*      Collection (Physical),          */ \
0671     0x09, 0x44,     /*          Usage (Barrel Switch),      */ \
0672     0x95, 0x01,     /*          Report Count (1),           */ \
0673     0x81, 0x02,     /*          Input (Variable),           */ \
0674     0x05, 0x01,     /*          Usage Page (Desktop),       */ \
0675     0x09, 0x30,     /*          Usage (X),                  */ \
0676     0x09, 0x31,     /*          Usage (Y),                  */ \
0677     0x95, 0x02,     /*          Report Count (2),           */ \
0678     0x81, 0x02,     /*          Input (Variable),           */ \
0679     0x95, 0x15,     /*          Report Count (21),          */ \
0680     0x81, 0x01,     /*          Input (Constant),           */ \
0681     0x05, 0x09,     /*          Usage Page (Button),        */ \
0682     0x19, 0x01,     /*          Usage Minimum (01h),        */ \
0683     0x29, 0x0A,     /*          Usage Maximum (0Ah),        */ \
0684     0x95, 0x0A,     /*          Report Count (10),          */ \
0685     0x81, 0x02,     /*          Input (Variable),           */ \
0686     0xC0,           /*      End Collection,                 */ \
0687     0x05, 0x01,     /*      Usage Page (Desktop),           */ \
0688     0x09, 0x05,     /*      Usage (Gamepad),                */ \
0689     0xA0,           /*      Collection (Physical),          */ \
0690     0x05, 0x09,     /*          Usage Page (Button),        */ \
0691     0x19, 0x01,     /*          Usage Minimum (01h),        */ \
0692     0x29, 0x03,     /*          Usage Maximum (03h),        */ \
0693     0x95, 0x03,     /*          Report Count (3),           */ \
0694     0x81, 0x02,     /*          Input (Variable),           */ \
0695     0x95, ((_size) * 8 - 45),                                  \
0696             /*          Report Count (padding),     */ \
0697     0x81, 0x01,     /*          Input (Constant),           */ \
0698     0xC0,           /*      End Collection,                 */ \
0699     0xC0            /*  End Collection                      */
0700 
0701 /* Fixed report descriptor for (tweaked) v1 frame reports */
0702 const __u8 uclogic_rdesc_v1_frame_arr[] = {
0703     UCLOGIC_RDESC_FRAME_BUTTONS_BYTES(UCLOGIC_RDESC_V1_FRAME_ID, 8)
0704 };
0705 const size_t uclogic_rdesc_v1_frame_size =
0706             sizeof(uclogic_rdesc_v1_frame_arr);
0707 
0708 /* Fixed report descriptor for (tweaked) v2 frame button reports */
0709 const __u8 uclogic_rdesc_v2_frame_buttons_arr[] = {
0710     UCLOGIC_RDESC_FRAME_BUTTONS_BYTES(UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID,
0711                       12)
0712 };
0713 const size_t uclogic_rdesc_v2_frame_buttons_size =
0714             sizeof(uclogic_rdesc_v2_frame_buttons_arr);
0715 
0716 /* Fixed report descriptor for (tweaked) v2 frame touch ring reports */
0717 const __u8 uclogic_rdesc_v2_frame_touch_ring_arr[] = {
0718     0x05, 0x01,         /*  Usage Page (Desktop),               */
0719     0x09, 0x07,         /*  Usage (Keypad),                     */
0720     0xA1, 0x01,         /*  Collection (Application),           */
0721     0x85, UCLOGIC_RDESC_V2_FRAME_TOUCH_ID,
0722                 /*      Report ID (TOUCH_ID),           */
0723     0x14,               /*      Logical Minimum (0),            */
0724     0x05, 0x0D,         /*      Usage Page (Digitizer),         */
0725     0x09, 0x39,         /*      Usage (Tablet Function Keys),   */
0726     0xA0,               /*      Collection (Physical),          */
0727     0x25, 0x01,         /*          Logical Maximum (1),        */
0728     0x75, 0x01,         /*          Report Size (1),            */
0729     0x05, 0x09,         /*          Usage Page (Button),        */
0730     0x09, 0x01,         /*          Usage (01h),                */
0731     0x95, 0x01,         /*          Report Count (1),           */
0732     0x81, 0x02,         /*          Input (Variable),           */
0733     0x95, 0x07,         /*          Report Count (7),           */
0734     0x81, 0x01,         /*          Input (Constant),           */
0735     0x75, 0x08,         /*          Report Size (8),            */
0736     0x95, 0x02,         /*          Report Count (2),           */
0737     0x81, 0x01,         /*          Input (Constant),           */
0738     0x05, 0x0D,         /*          Usage Page (Digitizer),     */
0739     0x0A, 0xFF, 0xFF,   /*          Usage (FFFFh),              */
0740     0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
0741     0x95, 0x01,         /*          Report Count (1),           */
0742     0x81, 0x02,         /*          Input (Variable),           */
0743     0x05, 0x01,         /*          Usage Page (Desktop),       */
0744     0x09, 0x38,         /*          Usage (Wheel),              */
0745     0x95, 0x01,         /*          Report Count (1),           */
0746     0x15, 0x00,         /*          Logical Minimum (0),        */
0747     0x25, 0x0B,         /*          Logical Maximum (11),       */
0748     0x81, 0x02,         /*          Input (Variable),           */
0749     0x09, 0x30,         /*          Usage (X),                  */
0750     0x09, 0x31,         /*          Usage (Y),                  */
0751     0x14,               /*          Logical Minimum (0),        */
0752     0x25, 0x01,         /*          Logical Maximum (1),        */
0753     0x75, 0x01,         /*          Report Size (1),            */
0754     0x95, 0x02,         /*          Report Count (2),           */
0755     0x81, 0x02,         /*          Input (Variable),           */
0756     0x95, 0x2E,         /*          Report Count (46),          */
0757     0x81, 0x01,         /*          Input (Constant),           */
0758     0xC0,               /*      End Collection,                 */
0759     0xC0                /*  End Collection                      */
0760 };
0761 const size_t uclogic_rdesc_v2_frame_touch_ring_size =
0762             sizeof(uclogic_rdesc_v2_frame_touch_ring_arr);
0763 
0764 /* Fixed report descriptor for (tweaked) v2 frame touch strip reports */
0765 const __u8 uclogic_rdesc_v2_frame_touch_strip_arr[] = {
0766     0x05, 0x01,         /*  Usage Page (Desktop),               */
0767     0x09, 0x07,         /*  Usage (Keypad),                     */
0768     0xA1, 0x01,         /*  Collection (Application),           */
0769     0x85, UCLOGIC_RDESC_V2_FRAME_TOUCH_ID,
0770                 /*      Report ID (TOUCH_ID),           */
0771     0x14,               /*      Logical Minimum (0),            */
0772     0x05, 0x0D,         /*      Usage Page (Digitizer),         */
0773     0x09, 0x39,         /*      Usage (Tablet Function Keys),   */
0774     0xA0,               /*      Collection (Physical),          */
0775     0x25, 0x01,         /*          Logical Maximum (1),        */
0776     0x75, 0x01,         /*          Report Size (1),            */
0777     0x05, 0x09,         /*          Usage Page (Button),        */
0778     0x09, 0x01,         /*          Usage (01h),                */
0779     0x95, 0x01,         /*          Report Count (1),           */
0780     0x81, 0x02,         /*          Input (Variable),           */
0781     0x95, 0x07,         /*          Report Count (7),           */
0782     0x81, 0x01,         /*          Input (Constant),           */
0783     0x75, 0x08,         /*          Report Size (8),            */
0784     0x95, 0x02,         /*          Report Count (2),           */
0785     0x81, 0x01,         /*          Input (Constant),           */
0786     0x05, 0x0D,         /*          Usage Page (Digitizer),     */
0787     0x0A, 0xFF, 0xFF,   /*          Usage (FFFFh),              */
0788     0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
0789     0x95, 0x01,         /*          Report Count (1),           */
0790     0x81, 0x02,         /*          Input (Variable),           */
0791     0x05, 0x01,         /*          Usage Page (Desktop),       */
0792     0x09, 0x38,         /*          Usage (Wheel),              */
0793     0x95, 0x01,         /*          Report Count (1),           */
0794     0x15, 0x00,         /*          Logical Minimum (0),        */
0795     0x25, 0x07,         /*          Logical Maximum (7),        */
0796     0x81, 0x02,         /*          Input (Variable),           */
0797     0x09, 0x30,         /*          Usage (X),                  */
0798     0x09, 0x31,         /*          Usage (Y),                  */
0799     0x14,               /*          Logical Minimum (0),        */
0800     0x25, 0x01,         /*          Logical Maximum (1),        */
0801     0x75, 0x01,         /*          Report Size (1),            */
0802     0x95, 0x02,         /*          Report Count (2),           */
0803     0x81, 0x02,         /*          Input (Variable),           */
0804     0x95, 0x2E,         /*          Report Count (46),          */
0805     0x81, 0x01,         /*          Input (Constant),           */
0806     0xC0,               /*      End Collection,                 */
0807     0xC0                /*  End Collection                      */
0808 };
0809 const size_t uclogic_rdesc_v2_frame_touch_strip_size =
0810             sizeof(uclogic_rdesc_v2_frame_touch_strip_arr);
0811 
0812 /* Fixed report descriptor for (tweaked) v2 frame dial reports */
0813 const __u8 uclogic_rdesc_v2_frame_dial_arr[] = {
0814     0x05, 0x01,         /*  Usage Page (Desktop),               */
0815     0x09, 0x07,         /*  Usage (Keypad),                     */
0816     0xA1, 0x01,         /*  Collection (Application),           */
0817     0x85, UCLOGIC_RDESC_V2_FRAME_DIAL_ID,
0818                 /*      Report ID (DIAL_ID),            */
0819     0x14,               /*      Logical Minimum (0),            */
0820     0x05, 0x0D,         /*      Usage Page (Digitizer),         */
0821     0x09, 0x39,         /*      Usage (Tablet Function Keys),   */
0822     0xA0,               /*      Collection (Physical),          */
0823     0x25, 0x01,         /*          Logical Maximum (1),        */
0824     0x75, 0x01,         /*          Report Size (1),            */
0825     0x95, 0x01,         /*          Report Count (1),           */
0826     0x81, 0x01,         /*          Input (Constant),           */
0827     0x05, 0x09,         /*          Usage Page (Button),        */
0828     0x09, 0x01,         /*          Usage (01h),                */
0829     0x95, 0x01,         /*          Report Count (1),           */
0830     0x81, 0x02,         /*          Input (Variable),           */
0831     0x95, 0x06,         /*          Report Count (6),           */
0832     0x81, 0x01,         /*          Input (Constant),           */
0833     0x75, 0x08,         /*          Report Size (8),            */
0834     0x95, 0x02,         /*          Report Count (2),           */
0835     0x81, 0x01,         /*          Input (Constant),           */
0836     0x05, 0x0D,         /*          Usage Page (Digitizer),     */
0837     0x0A, 0xFF, 0xFF,   /*          Usage (FFFFh),              */
0838     0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
0839     0x95, 0x01,         /*          Report Count (1),           */
0840     0x81, 0x02,         /*          Input (Variable),           */
0841     0x05, 0x01,         /*          Usage Page (Desktop),       */
0842     0x09, 0x38,         /*          Usage (Wheel),              */
0843     0x95, 0x01,         /*          Report Count (1),           */
0844     0x15, 0xFF,         /*          Logical Minimum (-1),       */
0845     0x25, 0x01,         /*          Logical Maximum (1),        */
0846     0x81, 0x06,         /*          Input (Variable, Relative), */
0847     0x09, 0x30,         /*          Usage (X),                  */
0848     0x09, 0x31,         /*          Usage (Y),                  */
0849     0x14,               /*          Logical Minimum (0),        */
0850     0x25, 0x01,         /*          Logical Maximum (1),        */
0851     0x75, 0x01,         /*          Report Size (1),            */
0852     0x95, 0x02,         /*          Report Count (2),           */
0853     0x81, 0x02,         /*          Input (Variable),           */
0854     0x95, 0x2E,         /*          Report Count (46),          */
0855     0x81, 0x01,         /*          Input (Constant),           */
0856     0xC0,               /*      End Collection,                 */
0857     0xC0                /*  End Collection                      */
0858 };
0859 const size_t uclogic_rdesc_v2_frame_dial_size =
0860             sizeof(uclogic_rdesc_v2_frame_dial_arr);
0861 
0862 /* Fixed report descriptor template for UGEE v2 pen reports */
0863 const __u8 uclogic_rdesc_ugee_v2_pen_template_arr[] = {
0864     0x05, 0x0d,         /*  Usage Page (Digitizers),                */
0865     0x09, 0x01,         /*  Usage (Digitizer),                      */
0866     0xa1, 0x01,         /*  Collection (Application),               */
0867     0x85, 0x02,         /*      Report ID (2),                      */
0868     0x09, 0x20,         /*      Usage (Stylus),                     */
0869     0xa1, 0x00,         /*      Collection (Physical),              */
0870     0x09, 0x42,         /*          Usage (Tip Switch),             */
0871     0x09, 0x44,         /*          Usage (Barrel Switch),          */
0872     0x09, 0x46,         /*          Usage (Tablet Pick),            */
0873     0x75, 0x01,         /*          Report Size (1),                */
0874     0x95, 0x03,         /*          Report Count (3),               */
0875     0x14,               /*          Logical Minimum (0),            */
0876     0x25, 0x01,         /*          Logical Maximum (1),            */
0877     0x81, 0x02,         /*          Input (Variable),               */
0878     0x95, 0x02,         /*          Report Count (2),               */
0879     0x81, 0x03,         /*          Input (Constant, Variable),     */
0880     0x09, 0x32,         /*          Usage (In Range),               */
0881     0x95, 0x01,         /*          Report Count (1),               */
0882     0x81, 0x02,         /*          Input (Variable),               */
0883     0x95, 0x02,         /*          Report Count (2),               */
0884     0x81, 0x03,         /*          Input (Constant, Variable),     */
0885     0x75, 0x10,         /*          Report Size (16),               */
0886     0x95, 0x01,         /*          Report Count (1),               */
0887     0x35, 0x00,         /*          Physical Minimum (0),           */
0888     0xa4,               /*          Push,                           */
0889     0x05, 0x01,         /*          Usage Page (Desktop),           */
0890     0x09, 0x30,         /*          Usage (X),                      */
0891     0x65, 0x13,         /*          Unit (Inch),                    */
0892     0x55, 0x0d,         /*          Unit Exponent (-3),             */
0893     0x27, UCLOGIC_RDESC_PEN_PH(X_LM),
0894                 /*          Logical Maximum (PLACEHOLDER),  */
0895     0x47, UCLOGIC_RDESC_PEN_PH(X_PM),
0896                 /*          Physical Maximum (PLACEHOLDER), */
0897     0x81, 0x02,         /*          Input (Variable),               */
0898     0x09, 0x31,         /*          Usage (Y),                      */
0899     0x27, UCLOGIC_RDESC_PEN_PH(Y_LM),
0900                 /*          Logical Maximum (PLACEHOLDER),  */
0901     0x47, UCLOGIC_RDESC_PEN_PH(Y_PM),
0902                 /*          Physical Maximum (PLACEHOLDER), */
0903     0x81, 0x02,         /*          Input (Variable),               */
0904     0xb4,               /*          Pop,                            */
0905     0x09, 0x30,         /*          Usage (Tip Pressure),           */
0906     0x45, 0x00,         /*          Physical Maximum (0),           */
0907     0x27, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM),
0908                 /*          Logical Maximum (PLACEHOLDER),  */
0909     0x75, 0x0D,         /*          Report Size (13),               */
0910     0x95, 0x01,         /*          Report Count (1),               */
0911     0x81, 0x02,         /*          Input (Variable),               */
0912     0x75, 0x01,         /*          Report Size (1),                */
0913     0x95, 0x03,         /*          Report Count (3),               */
0914     0x81, 0x01,         /*          Input (Constant),               */
0915     0x09, 0x3d,         /*          Usage (X Tilt),                 */
0916     0x35, 0xC3,         /*          Physical Minimum (-61),         */
0917     0x45, 0x3C,         /*          Physical Maximum (60),          */
0918     0x15, 0xC3,         /*          Logical Minimum (-61),          */
0919     0x25, 0x3C,         /*          Logical Maximum (60),           */
0920     0x75, 0x08,         /*          Report Size (8),                */
0921     0x95, 0x01,         /*          Report Count (1),               */
0922     0x81, 0x02,         /*          Input (Variable),               */
0923     0x09, 0x3e,         /*          Usage (Y Tilt),                 */
0924     0x35, 0xC3,         /*          Physical Minimum (-61),         */
0925     0x45, 0x3C,         /*          Physical Maximum (60),          */
0926     0x15, 0xC3,         /*          Logical Minimum (-61),          */
0927     0x25, 0x3C,         /*          Logical Maximum (60),           */
0928     0x81, 0x02,         /*          Input (Variable),               */
0929     0xc0,               /*      End Collection,                     */
0930     0xc0,               /*  End Collection                          */
0931 };
0932 const size_t uclogic_rdesc_ugee_v2_pen_template_size =
0933             sizeof(uclogic_rdesc_ugee_v2_pen_template_arr);
0934 
0935 /* Fixed report descriptor template for UGEE v2 frame reports (buttons only) */
0936 const __u8 uclogic_rdesc_ugee_v2_frame_btn_template_arr[] = {
0937     0x05, 0x01,         /*  Usage Page (Desktop),                   */
0938     0x09, 0x07,         /*  Usage (Keypad),                         */
0939     0xA1, 0x01,         /*  Collection (Application),               */
0940     0x85, UCLOGIC_RDESC_V1_FRAME_ID,
0941                 /*      Report ID,                          */
0942     0x05, 0x0D,         /*      Usage Page (Digitizer),             */
0943     0x09, 0x39,         /*      Usage (Tablet Function Keys),       */
0944     0xA0,               /*      Collection (Physical),              */
0945     0x75, 0x01,         /*          Report Size (1),                */
0946     0x95, 0x08,         /*          Report Count (8),               */
0947     0x81, 0x01,         /*          Input (Constant),               */
0948     0x05, 0x09,         /*          Usage Page (Button),            */
0949     0x19, 0x01,         /*          Usage Minimum (01h),            */
0950     UCLOGIC_RDESC_FRAME_PH_BTN,
0951                 /*          Usage Maximum (PLACEHOLDER),    */
0952     0x95, 0x0A,         /*          Report Count (10),              */
0953     0x14,               /*          Logical Minimum (0),            */
0954     0x25, 0x01,         /*          Logical Maximum (1),            */
0955     0x81, 0x02,         /*          Input (Variable),               */
0956     0x95, 0x46,         /*          Report Count (70),              */
0957     0x81, 0x01,         /*          Input (Constant),               */
0958     0xC0,               /*      End Collection,                     */
0959     0xC0                /*  End Collection                          */
0960 };
0961 const size_t uclogic_rdesc_ugee_v2_frame_btn_template_size =
0962             sizeof(uclogic_rdesc_ugee_v2_frame_btn_template_arr);
0963 
0964 /* Fixed report descriptor for Ugee EX07 frame */
0965 const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = {
0966     0x05, 0x01,             /*  Usage Page (Desktop),                   */
0967     0x09, 0x07,             /*  Usage (Keypad),                         */
0968     0xA1, 0x01,             /*  Collection (Application),               */
0969     0x85, 0x06,             /*      Report ID (6),                      */
0970     0x05, 0x0D,             /*      Usage Page (Digitizer),             */
0971     0x09, 0x39,             /*      Usage (Tablet Function Keys),       */
0972     0xA0,                   /*      Collection (Physical),              */
0973     0x05, 0x09,             /*          Usage Page (Button),            */
0974     0x75, 0x01,             /*          Report Size (1),                */
0975     0x19, 0x03,             /*          Usage Minimum (03h),            */
0976     0x29, 0x06,             /*          Usage Maximum (06h),            */
0977     0x95, 0x04,             /*          Report Count (4),               */
0978     0x81, 0x02,             /*          Input (Variable),               */
0979     0x95, 0x1A,             /*          Report Count (26),              */
0980     0x81, 0x03,             /*          Input (Constant, Variable),     */
0981     0x19, 0x01,             /*          Usage Minimum (01h),            */
0982     0x29, 0x02,             /*          Usage Maximum (02h),            */
0983     0x95, 0x02,             /*          Report Count (2),               */
0984     0x81, 0x02,             /*          Input (Variable),               */
0985     0xC0,                   /*      End Collection,                     */
0986     0xC0                    /*  End Collection                          */
0987 };
0988 const size_t uclogic_rdesc_ugee_ex07_frame_size =
0989             sizeof(uclogic_rdesc_ugee_ex07_frame_arr);
0990 
0991 /* Fixed report descriptor for Ugee G5 frame controls */
0992 const __u8 uclogic_rdesc_ugee_g5_frame_arr[] = {
0993     0x05, 0x01,         /*  Usage Page (Desktop),               */
0994     0x09, 0x07,         /*  Usage (Keypad),                     */
0995     0xA1, 0x01,         /*  Collection (Application),           */
0996     0x85, 0x06,         /*      Report ID (6),                  */
0997     0x05, 0x0D,         /*      Usage Page (Digitizer),         */
0998     0x09, 0x39,         /*      Usage (Tablet Function Keys),   */
0999     0xA0,               /*      Collection (Physical),          */
1000     0x14,               /*          Logical Minimum (0),        */
1001     0x25, 0x01,         /*          Logical Maximum (1),        */
1002     0x05, 0x01,         /*          Usage Page (Desktop),       */
1003     0x05, 0x09,         /*          Usage Page (Button),        */
1004     0x19, 0x01,         /*          Usage Minimum (01h),        */
1005     0x29, 0x05,         /*          Usage Maximum (05h),        */
1006     0x75, 0x01,         /*          Report Size (1),            */
1007     0x95, 0x05,         /*          Report Count (5),           */
1008     0x81, 0x02,         /*          Input (Variable),           */
1009     0x75, 0x01,         /*          Report Size (1),            */
1010     0x95, 0x03,         /*          Report Count (3),           */
1011     0x81, 0x01,         /*          Input (Constant),           */
1012     0x05, 0x0D,         /*          Usage Page (Digitizer),     */
1013     0x0A, 0xFF, 0xFF,   /*          Usage (FFFFh),              */
1014     0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
1015     0x75, 0x08,         /*          Report Size (8),            */
1016     0x95, 0x01,         /*          Report Count (1),           */
1017     0x81, 0x02,         /*          Input (Variable),           */
1018     0x25, 0x01,         /*          Logical Maximum (1),        */
1019     0x09, 0x44,         /*          Usage (Barrel Switch),      */
1020     0x75, 0x01,         /*          Report Size (1),            */
1021     0x95, 0x01,         /*          Report Count (1),           */
1022     0x81, 0x02,         /*          Input (Variable),           */
1023     0x05, 0x01,         /*          Usage Page (Desktop),       */
1024     0x09, 0x30,         /*          Usage (X),                  */
1025     0x09, 0x31,         /*          Usage (Y),                  */
1026     0x75, 0x01,         /*          Report Size (1),            */
1027     0x95, 0x02,         /*          Report Count (2),           */
1028     0x81, 0x02,         /*          Input (Variable),           */
1029     0x75, 0x01,         /*          Report Size (1),            */
1030     0x95, 0x0B,         /*          Report Count (11),          */
1031     0x81, 0x01,         /*          Input (Constant),           */
1032     0x05, 0x01,         /*          Usage Page (Desktop),       */
1033     0x09, 0x38,         /*          Usage (Wheel),              */
1034     0x15, 0xFF,         /*          Logical Minimum (-1),       */
1035     0x25, 0x01,         /*          Logical Maximum (1),        */
1036     0x75, 0x02,         /*          Report Size (2),            */
1037     0x95, 0x01,         /*          Report Count (1),           */
1038     0x81, 0x06,         /*          Input (Variable, Relative), */
1039     0xC0,               /*      End Collection,                 */
1040     0xC0                /*  End Collection                      */
1041 };
1042 const size_t uclogic_rdesc_ugee_g5_frame_size =
1043             sizeof(uclogic_rdesc_ugee_g5_frame_arr);
1044 
1045 /* Fixed report descriptor for XP-Pen Deco 01 frame controls */
1046 const __u8 uclogic_rdesc_xppen_deco01_frame_arr[] = {
1047     0x05, 0x01, /*  Usage Page (Desktop),               */
1048     0x09, 0x07, /*  Usage (Keypad),                     */
1049     0xA1, 0x01, /*  Collection (Application),           */
1050     0x85, 0x06, /*      Report ID (6),                  */
1051     0x14,       /*      Logical Minimum (0),            */
1052     0x25, 0x01, /*      Logical Maximum (1),            */
1053     0x75, 0x01, /*      Report Size (1),                */
1054     0x05, 0x0D, /*      Usage Page (Digitizer),         */
1055     0x09, 0x39, /*      Usage (Tablet Function Keys),   */
1056     0xA0,       /*      Collection (Physical),          */
1057     0x05, 0x09, /*          Usage Page (Button),        */
1058     0x19, 0x01, /*          Usage Minimum (01h),        */
1059     0x29, 0x08, /*          Usage Maximum (08h),        */
1060     0x95, 0x08, /*          Report Count (8),           */
1061     0x81, 0x02, /*          Input (Variable),           */
1062     0x05, 0x0D, /*          Usage Page (Digitizer),     */
1063     0x09, 0x44, /*          Usage (Barrel Switch),      */
1064     0x95, 0x01, /*          Report Count (1),           */
1065     0x81, 0x02, /*          Input (Variable),           */
1066     0x05, 0x01, /*          Usage Page (Desktop),       */
1067     0x09, 0x30, /*          Usage (X),                  */
1068     0x09, 0x31, /*          Usage (Y),                  */
1069     0x95, 0x02, /*          Report Count (2),           */
1070     0x81, 0x02, /*          Input (Variable),           */
1071     0x95, 0x15, /*          Report Count (21),          */
1072     0x81, 0x01, /*          Input (Constant),           */
1073     0xC0,       /*      End Collection,                 */
1074     0xC0        /*  End Collection                      */
1075 };
1076 
1077 const size_t uclogic_rdesc_xppen_deco01_frame_size =
1078             sizeof(uclogic_rdesc_xppen_deco01_frame_arr);
1079 
1080 /**
1081  * uclogic_rdesc_template_apply() - apply report descriptor parameters to a
1082  * report descriptor template, creating a report descriptor. Copies the
1083  * template over to the new report descriptor and replaces every occurrence of
1084  * the template placeholders, followed by an index byte, with the value from the
1085  * parameter list at that index.
1086  *
1087  * @template_ptr:   Pointer to the template buffer.
1088  * @template_size:  Size of the template buffer.
1089  * @param_list:     List of template parameters.
1090  * @param_num:      Number of parameters in the list.
1091  *
1092  * Returns:
1093  *  Kmalloc-allocated pointer to the created report descriptor,
1094  *  or NULL if allocation failed.
1095  */
1096 __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr,
1097                    size_t template_size,
1098                    const s32 *param_list,
1099                    size_t param_num)
1100 {
1101     static const __u8 btn_head[] = {UCLOGIC_RDESC_FRAME_PH_BTN_HEAD};
1102     static const __u8 pen_head[] = {UCLOGIC_RDESC_PEN_PH_HEAD};
1103     __u8 *rdesc_ptr;
1104     __u8 *p;
1105     s32 v;
1106 
1107     rdesc_ptr = kmemdup(template_ptr, template_size, GFP_KERNEL);
1108     if (rdesc_ptr == NULL)
1109         return NULL;
1110 
1111     for (p = rdesc_ptr; p + sizeof(btn_head) < rdesc_ptr + template_size;) {
1112         if (p + sizeof(pen_head) < rdesc_ptr + template_size &&
1113             memcmp(p, pen_head, sizeof(pen_head)) == 0 &&
1114             p[sizeof(pen_head)] < param_num) {
1115             v = param_list[p[sizeof(pen_head)]];
1116             put_unaligned(cpu_to_le32(v), (s32 *)p);
1117             p += sizeof(pen_head) + 1;
1118         } else if (memcmp(p, btn_head, sizeof(btn_head)) == 0 &&
1119                p[sizeof(btn_head)] < param_num) {
1120             v = param_list[p[sizeof(btn_head)]];
1121             put_unaligned((__u8)0x2A, p); /* Usage Maximum */
1122             put_unaligned_le16((__force u16)cpu_to_le16(v), p + 1);
1123             p += sizeof(btn_head) + 1;
1124         } else {
1125             p++;
1126         }
1127     }
1128 
1129     return rdesc_ptr;
1130 }