linux/drivers/hid/hid-uclogic-rdesc.c
<<
>>
Prefs
   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, 0x02,         /*  Usage (Pen),                        */
  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
  63const 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, 0x02,         /*  Usage (Pen),                        */
  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
 140const 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, 0x02,         /*  Usage (Pen),                        */
 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
 217const 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, 0x02,         /*  Usage (Pen),                        */
 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
 265const 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, 0x02,         /*  Usage (Pen),                        */
 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
 342const 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, 0x02,         /*  Usage (Pen),                        */
 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
 388const 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
 428const 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
 454const 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, 0x02,         /*  Usage (Pen),                        */
 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
 503const 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
 531const 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 */
 535const __u8 uclogic_rdesc_pen_v1_template_arr[] = {
 536        0x05, 0x0D,             /*  Usage Page (Digitizer),                 */
 537        0x09, 0x02,             /*  Usage (Pen),                            */
 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
 585const size_t uclogic_rdesc_pen_v1_template_size =
 586                        sizeof(uclogic_rdesc_pen_v1_template_arr);
 587
 588/* Fixed report descriptor template for (tweaked) v2 pen reports */
 589const __u8 uclogic_rdesc_pen_v2_template_arr[] = {
 590        0x05, 0x0D,             /*  Usage Page (Digitizer),                 */
 591        0x09, 0x02,             /*  Usage (Pen),                            */
 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        0x81, 0x03,             /*          Input (Constant, Variable),     */
 637        0xC0,                   /*      End Collection,                     */
 638        0xC0                    /*  End Collection                          */
 639};
 640
 641const size_t uclogic_rdesc_pen_v2_template_size =
 642                        sizeof(uclogic_rdesc_pen_v2_template_arr);
 643
 644/*
 645 * Expand to the contents of a generic buttonpad report descriptor.
 646 *
 647 * @_padding:   Padding from the end of button bits at bit 44, until
 648 *              the end of the report, in bits.
 649 */
 650#define UCLOGIC_RDESC_BUTTONPAD_BYTES(_padding) \
 651        0x05, 0x01,     /*  Usage Page (Desktop),               */ \
 652        0x09, 0x07,     /*  Usage (Keypad),                     */ \
 653        0xA1, 0x01,     /*  Collection (Application),           */ \
 654        0x85, 0xF7,     /*      Report ID (247),                */ \
 655        0x14,           /*      Logical Minimum (0),            */ \
 656        0x25, 0x01,     /*      Logical Maximum (1),            */ \
 657        0x75, 0x01,     /*      Report Size (1),                */ \
 658        0x05, 0x0D,     /*      Usage Page (Digitizer),         */ \
 659        0x09, 0x39,     /*      Usage (Tablet Function Keys),   */ \
 660        0xA0,           /*      Collection (Physical),          */ \
 661        0x09, 0x44,     /*          Usage (Barrel Switch),      */ \
 662        0x95, 0x01,     /*          Report Count (1),           */ \
 663        0x81, 0x02,     /*          Input (Variable),           */ \
 664        0x05, 0x01,     /*          Usage Page (Desktop),       */ \
 665        0x09, 0x30,     /*          Usage (X),                  */ \
 666        0x09, 0x31,     /*          Usage (Y),                  */ \
 667        0x95, 0x02,     /*          Report Count (2),           */ \
 668        0x81, 0x02,     /*          Input (Variable),           */ \
 669        0x95, 0x15,     /*          Report Count (21),          */ \
 670        0x81, 0x01,     /*          Input (Constant),           */ \
 671        0x05, 0x09,     /*          Usage Page (Button),        */ \
 672        0x19, 0x01,     /*          Usage Minimum (01h),        */ \
 673        0x29, 0x0A,     /*          Usage Maximum (0Ah),        */ \
 674        0x95, 0x0A,     /*          Report Count (10),          */ \
 675        0x81, 0x02,     /*          Input (Variable),           */ \
 676        0xC0,           /*      End Collection,                 */ \
 677        0x05, 0x01,     /*      Usage Page (Desktop),           */ \
 678        0x09, 0x05,     /*      Usage (Gamepad),                */ \
 679        0xA0,           /*      Collection (Physical),          */ \
 680        0x05, 0x09,     /*          Usage Page (Button),        */ \
 681        0x19, 0x01,     /*          Usage Minimum (01h),        */ \
 682        0x29, 0x02,     /*          Usage Maximum (02h),        */ \
 683        0x95, 0x02,     /*          Report Count (2),           */ \
 684        0x81, 0x02,     /*          Input (Variable),           */ \
 685        0x95, _padding, /*          Report Count (_padding),    */ \
 686        0x81, 0x01,     /*          Input (Constant),           */ \
 687        0xC0,           /*      End Collection,                 */ \
 688        0xC0            /*  End Collection                      */
 689
 690/* Fixed report descriptor for (tweaked) v1 buttonpad reports */
 691const __u8 uclogic_rdesc_buttonpad_v1_arr[] = {
 692        UCLOGIC_RDESC_BUTTONPAD_BYTES(20)
 693};
 694const size_t uclogic_rdesc_buttonpad_v1_size =
 695                        sizeof(uclogic_rdesc_buttonpad_v1_arr);
 696
 697/* Fixed report descriptor for (tweaked) v2 buttonpad reports */
 698const __u8 uclogic_rdesc_buttonpad_v2_arr[] = {
 699        UCLOGIC_RDESC_BUTTONPAD_BYTES(52)
 700};
 701const size_t uclogic_rdesc_buttonpad_v2_size =
 702                        sizeof(uclogic_rdesc_buttonpad_v2_arr);
 703
 704/* Fixed report descriptor for Ugee EX07 buttonpad */
 705const __u8 uclogic_rdesc_ugee_ex07_buttonpad_arr[] = {
 706        0x05, 0x01,             /*  Usage Page (Desktop),                   */
 707        0x09, 0x07,             /*  Usage (Keypad),                         */
 708        0xA1, 0x01,             /*  Collection (Application),               */
 709        0x85, 0x06,             /*      Report ID (6),                      */
 710        0x05, 0x0D,             /*      Usage Page (Digitizer),             */
 711        0x09, 0x39,             /*      Usage (Tablet Function Keys),       */
 712        0xA0,                   /*      Collection (Physical),              */
 713        0x05, 0x09,             /*          Usage Page (Button),            */
 714        0x75, 0x01,             /*          Report Size (1),                */
 715        0x19, 0x03,             /*          Usage Minimum (03h),            */
 716        0x29, 0x06,             /*          Usage Maximum (06h),            */
 717        0x95, 0x04,             /*          Report Count (4),               */
 718        0x81, 0x02,             /*          Input (Variable),               */
 719        0x95, 0x1A,             /*          Report Count (26),              */
 720        0x81, 0x03,             /*          Input (Constant, Variable),     */
 721        0x19, 0x01,             /*          Usage Minimum (01h),            */
 722        0x29, 0x02,             /*          Usage Maximum (02h),            */
 723        0x95, 0x02,             /*          Report Count (2),               */
 724        0x81, 0x02,             /*          Input (Variable),               */
 725        0xC0,                   /*      End Collection,                     */
 726        0xC0                    /*  End Collection                          */
 727};
 728const size_t uclogic_rdesc_ugee_ex07_buttonpad_size =
 729                        sizeof(uclogic_rdesc_ugee_ex07_buttonpad_arr);
 730
 731/* Fixed report descriptor for Ugee G5 frame controls */
 732const __u8 uclogic_rdesc_ugee_g5_frame_arr[] = {
 733        0x05, 0x01,         /*  Usage Page (Desktop),               */
 734        0x09, 0x07,         /*  Usage (Keypad),                     */
 735        0xA1, 0x01,         /*  Collection (Application),           */
 736        0x85, 0x06,         /*      Report ID (6),                  */
 737        0x05, 0x0D,         /*      Usage Page (Digitizer),         */
 738        0x09, 0x39,         /*      Usage (Tablet Function Keys),   */
 739        0xA0,               /*      Collection (Physical),          */
 740        0x14,               /*          Logical Minimum (0),        */
 741        0x25, 0x01,         /*          Logical Maximum (1),        */
 742        0x05, 0x01,         /*          Usage Page (Desktop),       */
 743        0x05, 0x09,         /*          Usage Page (Button),        */
 744        0x19, 0x01,         /*          Usage Minimum (01h),        */
 745        0x29, 0x05,         /*          Usage Maximum (05h),        */
 746        0x75, 0x01,         /*          Report Size (1),            */
 747        0x95, 0x05,         /*          Report Count (5),           */
 748        0x81, 0x02,         /*          Input (Variable),           */
 749        0x75, 0x01,         /*          Report Size (1),            */
 750        0x95, 0x03,         /*          Report Count (3),           */
 751        0x81, 0x01,         /*          Input (Constant),           */
 752        0x05, 0x0D,         /*          Usage Page (Digitizer),     */
 753        0x0A, 0xFF, 0xFF,   /*          Usage (FFFFh),              */
 754        0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
 755        0x75, 0x08,         /*          Report Size (8),            */
 756        0x95, 0x01,         /*          Report Count (1),           */
 757        0x81, 0x02,         /*          Input (Variable),           */
 758        0x25, 0x01,         /*          Logical Maximum (1),        */
 759        0x09, 0x44,         /*          Usage (Barrel Switch),      */
 760        0x75, 0x01,         /*          Report Size (1),            */
 761        0x95, 0x01,         /*          Report Count (1),           */
 762        0x81, 0x02,         /*          Input (Variable),           */
 763        0x05, 0x01,         /*          Usage Page (Desktop),       */
 764        0x09, 0x30,         /*          Usage (X),                  */
 765        0x09, 0x31,         /*          Usage (Y),                  */
 766        0x75, 0x01,         /*          Report Size (1),            */
 767        0x95, 0x02,         /*          Report Count (2),           */
 768        0x81, 0x02,         /*          Input (Variable),           */
 769        0x75, 0x01,         /*          Report Size (1),            */
 770        0x95, 0x0B,         /*          Report Count (11),          */
 771        0x81, 0x01,         /*          Input (Constant),           */
 772        0x05, 0x01,         /*          Usage Page (Desktop),       */
 773        0x09, 0x38,         /*          Usage (Wheel),              */
 774        0x15, 0xFF,         /*          Logical Minimum (-1),       */
 775        0x25, 0x01,         /*          Logical Maximum (1),        */
 776        0x75, 0x02,         /*          Report Size (2),            */
 777        0x95, 0x01,         /*          Report Count (1),           */
 778        0x81, 0x06,         /*          Input (Variable, Relative), */
 779        0xC0,               /*      End Collection,                 */
 780        0xC0                /*  End Collection                      */
 781};
 782const size_t uclogic_rdesc_ugee_g5_frame_size =
 783                        sizeof(uclogic_rdesc_ugee_g5_frame_arr);
 784
 785/* Fixed report descriptor for XP-Pen Deco 01 frame controls */
 786const __u8 uclogic_rdesc_xppen_deco01_frame_arr[] = {
 787        0x05, 0x01, /*  Usage Page (Desktop),               */
 788        0x09, 0x07, /*  Usage (Keypad),                     */
 789        0xA1, 0x01, /*  Collection (Application),           */
 790        0x85, 0x06, /*      Report ID (6),                  */
 791        0x14,       /*      Logical Minimum (0),            */
 792        0x25, 0x01, /*      Logical Maximum (1),            */
 793        0x75, 0x01, /*      Report Size (1),                */
 794        0x05, 0x0D, /*      Usage Page (Digitizer),         */
 795        0x09, 0x39, /*      Usage (Tablet Function Keys),   */
 796        0xA0,       /*      Collection (Physical),          */
 797        0x05, 0x09, /*          Usage Page (Button),        */
 798        0x19, 0x01, /*          Usage Minimum (01h),        */
 799        0x29, 0x08, /*          Usage Maximum (08h),        */
 800        0x95, 0x08, /*          Report Count (8),           */
 801        0x81, 0x02, /*          Input (Variable),           */
 802        0x05, 0x0D, /*          Usage Page (Digitizer),     */
 803        0x09, 0x44, /*          Usage (Barrel Switch),      */
 804        0x95, 0x01, /*          Report Count (1),           */
 805        0x81, 0x02, /*          Input (Variable),           */
 806        0x05, 0x01, /*          Usage Page (Desktop),       */
 807        0x09, 0x30, /*          Usage (X),                  */
 808        0x09, 0x31, /*          Usage (Y),                  */
 809        0x95, 0x02, /*          Report Count (2),           */
 810        0x81, 0x02, /*          Input (Variable),           */
 811        0x95, 0x15, /*          Report Count (21),          */
 812        0x81, 0x01, /*          Input (Constant),           */
 813        0xC0,       /*      End Collection,                 */
 814        0xC0        /*  End Collection                      */
 815};
 816
 817const size_t uclogic_rdesc_xppen_deco01_frame_size =
 818                        sizeof(uclogic_rdesc_xppen_deco01_frame_arr);
 819
 820/**
 821 * uclogic_rdesc_template_apply() - apply report descriptor parameters to a
 822 * report descriptor template, creating a report descriptor. Copies the
 823 * template over to the new report descriptor and replaces every occurrence of
 824 * UCLOGIC_RDESC_PH_HEAD, followed by an index byte, with the value from the
 825 * parameter list at that index.
 826 *
 827 * @template_ptr:       Pointer to the template buffer.
 828 * @template_size:      Size of the template buffer.
 829 * @param_list:         List of template parameters.
 830 * @param_num:          Number of parameters in the list.
 831 *
 832 * Returns:
 833 *      Kmalloc-allocated pointer to the created report descriptor,
 834 *      or NULL if allocation failed.
 835 */
 836__u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr,
 837                                   size_t template_size,
 838                                   const s32 *param_list,
 839                                   size_t param_num)
 840{
 841        static const __u8 head[] = {UCLOGIC_RDESC_PH_HEAD};
 842        __u8 *rdesc_ptr;
 843        __u8 *p;
 844        s32 v;
 845
 846        rdesc_ptr = kmemdup(template_ptr, template_size, GFP_KERNEL);
 847        if (rdesc_ptr == NULL)
 848                return NULL;
 849
 850        for (p = rdesc_ptr; p + sizeof(head) < rdesc_ptr + template_size;) {
 851                if (memcmp(p, head, sizeof(head)) == 0 &&
 852                    p[sizeof(head)] < param_num) {
 853                        v = param_list[p[sizeof(head)]];
 854                        put_unaligned(cpu_to_le32(v), (s32 *)p);
 855                        p += sizeof(head) + 1;
 856                } else {
 857                        p++;
 858                }
 859        }
 860
 861        return rdesc_ptr;
 862}
 863