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