linux/drivers/hid/hid-waltop.c
<<
>>
Prefs
   1/*
   2 *  HID driver for Waltop 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
  18#include "hid-ids.h"
  19
  20/*
  21 * There exists an official driver on the manufacturer's website, which
  22 * wasn't submitted to the kernel, for some reason. The official driver
  23 * doesn't seem to support extra features of some tablets, like wheels.
  24 *
  25 * It shows that the feature report ID 2 could be used to control any waltop
  26 * tablet input mode, switching it between "default", "tablet" and "ink".
  27 *
  28 * This driver only uses "default" mode for all the supported tablets. This
  29 * mode tries to be HID-compatible (not very successfully), but cripples the
  30 * resolution of some tablets.
  31 *
  32 * The "tablet" mode uses some proprietary, yet decipherable protocol, which
  33 * represents the correct resolution, but is possibly HID-incompatible (i.e.
  34 * indescribable by a report descriptor).
  35 *
  36 * The purpose of the "ink" mode is unknown.
  37 *
  38 * The feature reports needed for switching to each mode are these:
  39 *
  40 * 02 16 00     default
  41 * 02 16 01     tablet
  42 * 02 16 02     ink
  43 */
  44
  45/*
  46 * See Slim Tablet 5.8 inch description, device and HID report descriptors at
  47 * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Slim_Tablet_5.8%22
  48 */
  49
  50/* Size of the original report descriptor of Slim Tablet 5.8 inch */
  51#define SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE    222
  52
  53/* Fixed Slim Tablet 5.8 inch descriptor */
  54static __u8 slim_tablet_5_8_inch_rdesc_fixed[] = {
  55        0x05, 0x0D,         /*  Usage Page (Digitizer),             */
  56        0x09, 0x02,         /*  Usage (Pen),                        */
  57        0xA1, 0x01,         /*  Collection (Application),           */
  58        0x85, 0x10,         /*      Report ID (16),                 */
  59        0x09, 0x20,         /*      Usage (Stylus),                 */
  60        0xA0,               /*      Collection (Physical),          */
  61        0x09, 0x42,         /*          Usage (Tip Switch),         */
  62        0x09, 0x44,         /*          Usage (Barrel Switch),      */
  63        0x09, 0x46,         /*          Usage (Tablet Pick),        */
  64        0x15, 0x01,         /*          Logical Minimum (1),        */
  65        0x25, 0x03,         /*          Logical Maximum (3),        */
  66        0x75, 0x04,         /*          Report Size (4),            */
  67        0x95, 0x01,         /*          Report Count (1),           */
  68        0x80,               /*          Input,                      */
  69        0x09, 0x32,         /*          Usage (In Range),           */
  70        0x14,               /*          Logical Minimum (0),        */
  71        0x25, 0x01,         /*          Logical Maximum (1),        */
  72        0x75, 0x01,         /*          Report Size (1),            */
  73        0x95, 0x01,         /*          Report Count (1),           */
  74        0x81, 0x02,         /*          Input (Variable),           */
  75        0x95, 0x03,         /*          Report Count (3),           */
  76        0x81, 0x03,         /*          Input (Constant, Variable), */
  77        0x75, 0x10,         /*          Report Size (16),           */
  78        0x95, 0x01,         /*          Report Count (1),           */
  79        0x14,               /*          Logical Minimum (0),        */
  80        0xA4,               /*          Push,                       */
  81        0x05, 0x01,         /*          Usage Page (Desktop),       */
  82        0x65, 0x13,         /*          Unit (Inch),                */
  83        0x55, 0xFD,         /*          Unit Exponent (-3),         */
  84        0x34,               /*          Physical Minimum (0),       */
  85        0x09, 0x30,         /*          Usage (X),                  */
  86        0x46, 0x88, 0x13,   /*          Physical Maximum (5000),    */
  87        0x26, 0x10, 0x27,   /*          Logical Maximum (10000),    */
  88        0x81, 0x02,         /*          Input (Variable),           */
  89        0x09, 0x31,         /*          Usage (Y),                  */
  90        0x46, 0xB8, 0x0B,   /*          Physical Maximum (3000),    */
  91        0x26, 0x70, 0x17,   /*          Logical Maximum (6000),     */
  92        0x81, 0x02,         /*          Input (Variable),           */
  93        0xB4,               /*          Pop,                        */
  94        0x09, 0x30,         /*          Usage (Tip Pressure),       */
  95        0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
  96        0x81, 0x02,         /*          Input (Variable),           */
  97        0xC0,               /*      End Collection,                 */
  98        0xC0                /*  End Collection                      */
  99};
 100
 101/*
 102 * See Slim Tablet 12.1 inch description, device and HID report descriptors at
 103 * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Slim_Tablet_12.1%22
 104 */
 105
 106/* Size of the original report descriptor of Slim Tablet 12.1 inch */
 107#define SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE   269
 108
 109/* Fixed Slim Tablet 12.1 inch descriptor */
 110static __u8 slim_tablet_12_1_inch_rdesc_fixed[] = {
 111        0x05, 0x0D,         /*  Usage Page (Digitizer),             */
 112        0x09, 0x02,         /*  Usage (Pen),                        */
 113        0xA1, 0x01,         /*  Collection (Application),           */
 114        0x85, 0x10,         /*      Report ID (16),                 */
 115        0x09, 0x20,         /*      Usage (Stylus),                 */
 116        0xA0,               /*      Collection (Physical),          */
 117        0x09, 0x42,         /*          Usage (Tip Switch),         */
 118        0x09, 0x44,         /*          Usage (Barrel Switch),      */
 119        0x09, 0x46,         /*          Usage (Tablet Pick),        */
 120        0x15, 0x01,         /*          Logical Minimum (1),        */
 121        0x25, 0x03,         /*          Logical Maximum (3),        */
 122        0x75, 0x04,         /*          Report Size (4),            */
 123        0x95, 0x01,         /*          Report Count (1),           */
 124        0x80,               /*          Input,                      */
 125        0x09, 0x32,         /*          Usage (In Range),           */
 126        0x14,               /*          Logical Minimum (0),        */
 127        0x25, 0x01,         /*          Logical Maximum (1),        */
 128        0x75, 0x01,         /*          Report Size (1),            */
 129        0x95, 0x01,         /*          Report Count (1),           */
 130        0x81, 0x02,         /*          Input (Variable),           */
 131        0x95, 0x03,         /*          Report Count (3),           */
 132        0x81, 0x03,         /*          Input (Constant, Variable), */
 133        0x75, 0x10,         /*          Report Size (16),           */
 134        0x95, 0x01,         /*          Report Count (1),           */
 135        0x14,               /*          Logical Minimum (0),        */
 136        0xA4,               /*          Push,                       */
 137        0x05, 0x01,         /*          Usage Page (Desktop),       */
 138        0x65, 0x13,         /*          Unit (Inch),                */
 139        0x55, 0xFD,         /*          Unit Exponent (-3),         */
 140        0x34,               /*          Physical Minimum (0),       */
 141        0x09, 0x30,         /*          Usage (X),                  */
 142        0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
 143        0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
 144        0x81, 0x02,         /*          Input (Variable),           */
 145        0x09, 0x31,         /*          Usage (Y),                  */
 146        0x46, 0x6A, 0x18,   /*          Physical Maximum (6250),    */
 147        0x26, 0xD4, 0x30,   /*          Logical Maximum (12500),    */
 148        0x81, 0x02,         /*          Input (Variable),           */
 149        0xB4,               /*          Pop,                        */
 150        0x09, 0x30,         /*          Usage (Tip Pressure),       */
 151        0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
 152        0x81, 0x02,         /*          Input (Variable),           */
 153        0xC0,               /*      End Collection,                 */
 154        0xC0                /*  End Collection                      */
 155};
 156
 157/*
 158 * See Q Pad description, device and HID report descriptors at
 159 * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Q_Pad
 160 */
 161
 162/* Size of the original report descriptor of Q Pad */
 163#define Q_PAD_RDESC_ORIG_SIZE   241
 164
 165/* Fixed Q Pad descriptor */
 166static __u8 q_pad_rdesc_fixed[] = {
 167        0x05, 0x0D,         /*  Usage Page (Digitizer),             */
 168        0x09, 0x02,         /*  Usage (Pen),                        */
 169        0xA1, 0x01,         /*  Collection (Application),           */
 170        0x85, 0x10,         /*      Report ID (16),                 */
 171        0x09, 0x20,         /*      Usage (Stylus),                 */
 172        0xA0,               /*      Collection (Physical),          */
 173        0x09, 0x42,         /*          Usage (Tip Switch),         */
 174        0x09, 0x44,         /*          Usage (Barrel Switch),      */
 175        0x09, 0x46,         /*          Usage (Tablet Pick),        */
 176        0x15, 0x01,         /*          Logical Minimum (1),        */
 177        0x25, 0x03,         /*          Logical Maximum (3),        */
 178        0x75, 0x04,         /*          Report Size (4),            */
 179        0x95, 0x01,         /*          Report Count (1),           */
 180        0x80,               /*          Input,                      */
 181        0x09, 0x32,         /*          Usage (In Range),           */
 182        0x14,               /*          Logical Minimum (0),        */
 183        0x25, 0x01,         /*          Logical Maximum (1),        */
 184        0x75, 0x01,         /*          Report Size (1),            */
 185        0x95, 0x01,         /*          Report Count (1),           */
 186        0x81, 0x02,         /*          Input (Variable),           */
 187        0x95, 0x03,         /*          Report Count (3),           */
 188        0x81, 0x03,         /*          Input (Constant, Variable), */
 189        0x75, 0x10,         /*          Report Size (16),           */
 190        0x95, 0x01,         /*          Report Count (1),           */
 191        0x14,               /*          Logical Minimum (0),        */
 192        0xA4,               /*          Push,                       */
 193        0x05, 0x01,         /*          Usage Page (Desktop),       */
 194        0x65, 0x13,         /*          Unit (Inch),                */
 195        0x55, 0xFD,         /*          Unit Exponent (-3),         */
 196        0x34,               /*          Physical Minimum (0),       */
 197        0x09, 0x30,         /*          Usage (X),                  */
 198        0x46, 0x70, 0x17,   /*          Physical Maximum (6000),    */
 199        0x26, 0x00, 0x30,   /*          Logical Maximum (12288),    */
 200        0x81, 0x02,         /*          Input (Variable),           */
 201        0x09, 0x31,         /*          Usage (Y),                  */
 202        0x46, 0x94, 0x11,   /*          Physical Maximum (4500),    */
 203        0x26, 0x00, 0x24,   /*          Logical Maximum (9216),     */
 204        0x81, 0x02,         /*          Input (Variable),           */
 205        0xB4,               /*          Pop,                        */
 206        0x09, 0x30,         /*          Usage (Tip Pressure),       */
 207        0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
 208        0x81, 0x02,         /*          Input (Variable),           */
 209        0xC0,               /*      End Collection,                 */
 210        0xC0                /*  End Collection                      */
 211};
 212
 213/*
 214 * See description, device and HID report descriptors of tablet with PID 0038 at
 215 * http://sf.net/apps/mediawiki/digimend/?title=Waltop_PID_0038
 216 */
 217
 218/* Size of the original report descriptor of tablet with PID 0038 */
 219#define PID_0038_RDESC_ORIG_SIZE        241
 220
 221/*
 222 * Fixed report descriptor for tablet with PID 0038.
 223 */
 224static __u8 pid_0038_rdesc_fixed[] = {
 225        0x05, 0x0D,         /*  Usage Page (Digitizer),             */
 226        0x09, 0x02,         /*  Usage (Pen),                        */
 227        0xA1, 0x01,         /*  Collection (Application),           */
 228        0x85, 0x10,         /*      Report ID (16),                 */
 229        0x09, 0x20,         /*      Usage (Stylus),                 */
 230        0xA0,               /*      Collection (Physical),          */
 231        0x09, 0x42,         /*          Usage (Tip Switch),         */
 232        0x09, 0x44,         /*          Usage (Barrel Switch),      */
 233        0x09, 0x46,         /*          Usage (Tablet Pick),        */
 234        0x15, 0x01,         /*          Logical Minimum (1),        */
 235        0x25, 0x03,         /*          Logical Maximum (3),        */
 236        0x75, 0x04,         /*          Report Size (4),            */
 237        0x95, 0x01,         /*          Report Count (1),           */
 238        0x80,               /*          Input,                      */
 239        0x09, 0x32,         /*          Usage (In Range),           */
 240        0x14,               /*          Logical Minimum (0),        */
 241        0x25, 0x01,         /*          Logical Maximum (1),        */
 242        0x75, 0x01,         /*          Report Size (1),            */
 243        0x95, 0x01,         /*          Report Count (1),           */
 244        0x81, 0x02,         /*          Input (Variable),           */
 245        0x95, 0x03,         /*          Report Count (3),           */
 246        0x81, 0x03,         /*          Input (Constant, Variable), */
 247        0x75, 0x10,         /*          Report Size (16),           */
 248        0x95, 0x01,         /*          Report Count (1),           */
 249        0x14,               /*          Logical Minimum (0),        */
 250        0xA4,               /*          Push,                       */
 251        0x05, 0x01,         /*          Usage Page (Desktop),       */
 252        0x65, 0x13,         /*          Unit (Inch),                */
 253        0x55, 0xFD,         /*          Unit Exponent (-3),         */
 254        0x34,               /*          Physical Minimum (0),       */
 255        0x09, 0x30,         /*          Usage (X),                  */
 256        0x46, 0x2E, 0x22,   /*          Physical Maximum (8750),    */
 257        0x26, 0x00, 0x46,   /*          Logical Maximum (17920),    */
 258        0x81, 0x02,         /*          Input (Variable),           */
 259        0x09, 0x31,         /*          Usage (Y),                  */
 260        0x46, 0x82, 0x14,   /*          Physical Maximum (5250),    */
 261        0x26, 0x00, 0x2A,   /*          Logical Maximum (10752),    */
 262        0x81, 0x02,         /*          Input (Variable),           */
 263        0xB4,               /*          Pop,                        */
 264        0x09, 0x30,         /*          Usage (Tip Pressure),       */
 265        0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
 266        0x81, 0x02,         /*          Input (Variable),           */
 267        0xC0,               /*      End Collection,                 */
 268        0xC0                /*  End Collection                      */
 269};
 270
 271/*
 272 * See Media Tablet 10.6 inch description, device and HID report descriptors at
 273 * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Media_Tablet_10.6%22
 274 */
 275
 276/* Size of the original report descriptor of Media Tablet 10.6 inch */
 277#define MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE  300
 278
 279/* Fixed Media Tablet 10.6 inch descriptor */
 280static __u8 media_tablet_10_6_inch_rdesc_fixed[] = {
 281        0x05, 0x0D,         /*  Usage Page (Digitizer),             */
 282        0x09, 0x02,         /*  Usage (Pen),                        */
 283        0xA1, 0x01,         /*  Collection (Application),           */
 284        0x85, 0x10,         /*      Report ID (16),                 */
 285        0x09, 0x20,         /*      Usage (Stylus),                 */
 286        0xA0,               /*      Collection (Physical),          */
 287        0x09, 0x42,         /*          Usage (Tip Switch),         */
 288        0x09, 0x44,         /*          Usage (Barrel Switch),      */
 289        0x09, 0x46,         /*          Usage (Tablet Pick),        */
 290        0x15, 0x01,         /*          Logical Minimum (1),        */
 291        0x25, 0x03,         /*          Logical Maximum (3),        */
 292        0x75, 0x04,         /*          Report Size (4),            */
 293        0x95, 0x01,         /*          Report Count (1),           */
 294        0x80,               /*          Input,                      */
 295        0x75, 0x01,         /*          Report Size (1),            */
 296        0x09, 0x32,         /*          Usage (In Range),           */
 297        0x14,               /*          Logical Minimum (0),        */
 298        0x25, 0x01,         /*          Logical Maximum (1),        */
 299        0x95, 0x01,         /*          Report Count (1),           */
 300        0x81, 0x02,         /*          Input (Variable),           */
 301        0x95, 0x03,         /*          Report Count (3),           */
 302        0x81, 0x03,         /*          Input (Constant, Variable), */
 303        0x75, 0x10,         /*          Report Size (16),           */
 304        0x95, 0x01,         /*          Report Count (1),           */
 305        0x14,               /*          Logical Minimum (0),        */
 306        0xA4,               /*          Push,                       */
 307        0x05, 0x01,         /*          Usage Page (Desktop),       */
 308        0x65, 0x13,         /*          Unit (Inch),                */
 309        0x55, 0xFD,         /*          Unit Exponent (-3),         */
 310        0x34,               /*          Physical Minimum (0),       */
 311        0x09, 0x30,         /*          Usage (X),                  */
 312        0x46, 0x28, 0x23,   /*          Physical Maximum (9000),    */
 313        0x26, 0x50, 0x46,   /*          Logical Maximum (18000),    */
 314        0x81, 0x02,         /*          Input (Variable),           */
 315        0x09, 0x31,         /*          Usage (Y),                  */
 316        0x46, 0x7C, 0x15,   /*          Physical Maximum (5500),    */
 317        0x26, 0xF8, 0x2A,   /*          Logical Maximum (11000),    */
 318        0x81, 0x02,         /*          Input (Variable),           */
 319        0xB4,               /*          Pop,                        */
 320        0x09, 0x30,         /*          Usage (Tip Pressure),       */
 321        0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
 322        0x81, 0x02,         /*          Input (Variable),           */
 323        0xC0,               /*      End Collection,                 */
 324        0xC0,               /*  End Collection,                     */
 325        0x05, 0x01,         /*  Usage Page (Desktop),               */
 326        0x09, 0x02,         /*  Usage (Mouse),                      */
 327        0xA1, 0x01,         /*  Collection (Application),           */
 328        0x85, 0x01,         /*      Report ID (1),                  */
 329        0x09, 0x01,         /*      Usage (Pointer),                */
 330        0xA0,               /*      Collection (Physical),          */
 331        0x75, 0x08,         /*          Report Size (8),            */
 332        0x95, 0x03,         /*          Report Count (3),           */
 333        0x81, 0x03,         /*          Input (Constant, Variable), */
 334        0x95, 0x02,         /*          Report Count (2),           */
 335        0x15, 0xFF,         /*          Logical Minimum (-1),       */
 336        0x25, 0x01,         /*          Logical Maximum (1),        */
 337        0x09, 0x38,         /*          Usage (Wheel),              */
 338        0x0B, 0x38, 0x02,   /*          Usage (Consumer AC Pan),    */
 339                0x0C, 0x00,
 340        0x81, 0x06,         /*          Input (Variable, Relative), */
 341        0x95, 0x02,         /*          Report Count (2),           */
 342        0x81, 0x03,         /*          Input (Constant, Variable), */
 343        0xC0,               /*      End Collection,                 */
 344        0xC0,               /*  End Collection,                     */
 345        0x05, 0x0C,         /*  Usage Page (Consumer),              */
 346        0x09, 0x01,         /*  Usage (Consumer Control),           */
 347        0xA1, 0x01,         /*  Collection (Application),           */
 348        0x85, 0x0D,         /*      Report ID (13),                 */
 349        0x95, 0x01,         /*      Report Count (1),               */
 350        0x75, 0x10,         /*      Report Size (16),               */
 351        0x81, 0x03,         /*      Input (Constant, Variable),     */
 352        0x0A, 0x2F, 0x02,   /*      Usage (AC Zoom),                */
 353        0x0A, 0x2E, 0x02,   /*      Usage (AC Zoom Out),            */
 354        0x0A, 0x2D, 0x02,   /*      Usage (AC Zoom In),             */
 355        0x09, 0xB6,         /*      Usage (Scan Previous Track),    */
 356        0x09, 0xB5,         /*      Usage (Scan Next Track),        */
 357        0x08,               /*      Usage (00h),                    */
 358        0x08,               /*      Usage (00h),                    */
 359        0x08,               /*      Usage (00h),                    */
 360        0x08,               /*      Usage (00h),                    */
 361        0x08,               /*      Usage (00h),                    */
 362        0x0A, 0x2E, 0x02,   /*      Usage (AC Zoom Out),            */
 363        0x0A, 0x2D, 0x02,   /*      Usage (AC Zoom In),             */
 364        0x15, 0x0C,         /*      Logical Minimum (12),           */
 365        0x25, 0x17,         /*      Logical Maximum (23),           */
 366        0x75, 0x05,         /*      Report Size (5),                */
 367        0x80,               /*      Input,                          */
 368        0x75, 0x03,         /*      Report Size (3),                */
 369        0x81, 0x03,         /*      Input (Constant, Variable),     */
 370        0x75, 0x20,         /*      Report Size (32),               */
 371        0x81, 0x03,         /*      Input (Constant, Variable),     */
 372        0xC0,               /*  End Collection,                     */
 373        0x09, 0x01,         /*  Usage (Consumer Control),           */
 374        0xA1, 0x01,         /*  Collection (Application),           */
 375        0x85, 0x0C,         /*      Report ID (12),                 */
 376        0x75, 0x01,         /*      Report Size (1),                */
 377        0x09, 0xE9,         /*      Usage (Volume Inc),             */
 378        0x09, 0xEA,         /*      Usage (Volume Dec),             */
 379        0x09, 0xE2,         /*      Usage (Mute),                   */
 380        0x14,               /*      Logical Minimum (0),            */
 381        0x25, 0x01,         /*      Logical Maximum (1),            */
 382        0x95, 0x03,         /*      Report Count (3),               */
 383        0x81, 0x06,         /*      Input (Variable, Relative),     */
 384        0x95, 0x35,         /*      Report Count (53),              */
 385        0x81, 0x03,         /*      Input (Constant, Variable),     */
 386        0xC0                /*  End Collection                      */
 387};
 388
 389/*
 390 * See Media Tablet 14.1 inch description, device and HID report descriptors at
 391 * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Media_Tablet_14.1%22
 392 */
 393
 394/* Size of the original report descriptor of Media Tablet 14.1 inch */
 395#define MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE  309
 396
 397/* Fixed Media Tablet 14.1 inch descriptor */
 398static __u8 media_tablet_14_1_inch_rdesc_fixed[] = {
 399        0x05, 0x0D,         /*  Usage Page (Digitizer),             */
 400        0x09, 0x02,         /*  Usage (Pen),                        */
 401        0xA1, 0x01,         /*  Collection (Application),           */
 402        0x85, 0x10,         /*      Report ID (16),                 */
 403        0x09, 0x20,         /*      Usage (Stylus),                 */
 404        0xA0,               /*      Collection (Physical),          */
 405        0x09, 0x42,         /*          Usage (Tip Switch),         */
 406        0x09, 0x44,         /*          Usage (Barrel Switch),      */
 407        0x09, 0x46,         /*          Usage (Tablet Pick),        */
 408        0x15, 0x01,         /*          Logical Minimum (1),        */
 409        0x25, 0x03,         /*          Logical Maximum (3),        */
 410        0x75, 0x04,         /*          Report Size (4),            */
 411        0x95, 0x01,         /*          Report Count (1),           */
 412        0x80,               /*          Input,                      */
 413        0x75, 0x01,         /*          Report Size (1),            */
 414        0x09, 0x32,         /*          Usage (In Range),           */
 415        0x14,               /*          Logical Minimum (0),        */
 416        0x25, 0x01,         /*          Logical Maximum (1),        */
 417        0x95, 0x01,         /*          Report Count (1),           */
 418        0x81, 0x02,         /*          Input (Variable),           */
 419        0x95, 0x03,         /*          Report Count (3),           */
 420        0x81, 0x03,         /*          Input (Constant, Variable), */
 421        0x75, 0x10,         /*          Report Size (16),           */
 422        0x95, 0x01,         /*          Report Count (1),           */
 423        0x14,               /*          Logical Minimum (0),        */
 424        0xA4,               /*          Push,                       */
 425        0x05, 0x01,         /*          Usage Page (Desktop),       */
 426        0x65, 0x13,         /*          Unit (Inch),                */
 427        0x55, 0xFD,         /*          Unit Exponent (-3),         */
 428        0x34,               /*          Physical Minimum (0),       */
 429        0x09, 0x30,         /*          Usage (X),                  */
 430        0x46, 0xE0, 0x2E,   /*          Physical Maximum (12000),   */
 431        0x26, 0xFF, 0x3F,   /*          Logical Maximum (16383),    */
 432        0x81, 0x02,         /*          Input (Variable),           */
 433        0x09, 0x31,         /*          Usage (Y),                  */
 434        0x46, 0x52, 0x1C,   /*          Physical Maximum (7250),    */
 435        0x26, 0xFF, 0x3F,   /*          Logical Maximum (16383),    */
 436        0x81, 0x02,         /*          Input (Variable),           */
 437        0xB4,               /*          Pop,                        */
 438        0x09, 0x30,         /*          Usage (Tip Pressure),       */
 439        0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
 440        0x81, 0x02,         /*          Input (Variable),           */
 441        0xC0,               /*      End Collection,                 */
 442        0xC0,               /*  End Collection,                     */
 443        0x05, 0x01,         /*  Usage Page (Desktop),               */
 444        0x09, 0x02,         /*  Usage (Mouse),                      */
 445        0xA1, 0x01,         /*  Collection (Application),           */
 446        0x85, 0x01,         /*      Report ID (1),                  */
 447        0x09, 0x01,         /*      Usage (Pointer),                */
 448        0xA0,               /*      Collection (Physical),          */
 449        0x75, 0x08,         /*          Report Size (8),            */
 450        0x95, 0x03,         /*          Report Count (3),           */
 451        0x81, 0x03,         /*          Input (Constant, Variable), */
 452        0x95, 0x02,         /*          Report Count (2),           */
 453        0x15, 0xFF,         /*          Logical Minimum (-1),       */
 454        0x25, 0x01,         /*          Logical Maximum (1),        */
 455        0x09, 0x38,         /*          Usage (Wheel),              */
 456        0x0B, 0x38, 0x02,   /*          Usage (Consumer AC Pan),    */
 457                0x0C, 0x00,
 458        0x81, 0x06,         /*          Input (Variable, Relative), */
 459        0xC0,               /*      End Collection,                 */
 460        0xC0,               /*  End Collection,                     */
 461        0x05, 0x0C,         /*  Usage Page (Consumer),              */
 462        0x09, 0x01,         /*  Usage (Consumer Control),           */
 463        0xA1, 0x01,         /*  Collection (Application),           */
 464        0x85, 0x0D,         /*      Report ID (13),                 */
 465        0x95, 0x01,         /*      Report Count (1),               */
 466        0x75, 0x10,         /*      Report Size (16),               */
 467        0x81, 0x03,         /*      Input (Constant, Variable),     */
 468        0x0A, 0x2F, 0x02,   /*      Usage (AC Zoom),                */
 469        0x0A, 0x2E, 0x02,   /*      Usage (AC Zoom Out),            */
 470        0x0A, 0x2D, 0x02,   /*      Usage (AC Zoom In),             */
 471        0x09, 0xB6,         /*      Usage (Scan Previous Track),    */
 472        0x09, 0xB5,         /*      Usage (Scan Next Track),        */
 473        0x08,               /*      Usage (00h),                    */
 474        0x08,               /*      Usage (00h),                    */
 475        0x08,               /*      Usage (00h),                    */
 476        0x08,               /*      Usage (00h),                    */
 477        0x08,               /*      Usage (00h),                    */
 478        0x0A, 0x2E, 0x02,   /*      Usage (AC Zoom Out),            */
 479        0x0A, 0x2D, 0x02,   /*      Usage (AC Zoom In),             */
 480        0x15, 0x0C,         /*      Logical Minimum (12),           */
 481        0x25, 0x17,         /*      Logical Maximum (23),           */
 482        0x75, 0x05,         /*      Report Size (5),                */
 483        0x80,               /*      Input,                          */
 484        0x75, 0x03,         /*      Report Size (3),                */
 485        0x81, 0x03,         /*      Input (Constant, Variable),     */
 486        0x75, 0x20,         /*      Report Size (32),               */
 487        0x81, 0x03,         /*      Input (Constant, Variable),     */
 488        0xC0,               /*  End Collection,                     */
 489        0x09, 0x01,         /*  Usage (Consumer Control),           */
 490        0xA1, 0x01,         /*  Collection (Application),           */
 491        0x85, 0x0C,         /*      Report ID (12),                 */
 492        0x75, 0x01,         /*      Report Size (1),                */
 493        0x09, 0xE9,         /*      Usage (Volume Inc),             */
 494        0x09, 0xEA,         /*      Usage (Volume Dec),             */
 495        0x09, 0xE2,         /*      Usage (Mute),                   */
 496        0x14,               /*      Logical Minimum (0),            */
 497        0x25, 0x01,         /*      Logical Maximum (1),            */
 498        0x95, 0x03,         /*      Report Count (3),               */
 499        0x81, 0x06,         /*      Input (Variable, Relative),     */
 500        0x75, 0x05,         /*      Report Size (5),                */
 501        0x81, 0x03,         /*      Input (Constant, Variable),     */
 502        0xC0                /*  End Collection                      */
 503};
 504
 505/*
 506 * See Sirius Battery Free Tablet description, device and HID report descriptors
 507 * at
 508 * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Sirius_Battery_Free_Tablet
 509 */
 510
 511/* Size of the original report descriptor of Sirius Battery Free Tablet */
 512#define SIRIUS_BATTERY_FREE_TABLET_RDESC_ORIG_SIZE      335
 513
 514/* Fixed Sirius Battery Free Tablet descriptor */
 515static __u8 sirius_battery_free_tablet_rdesc_fixed[] = {
 516        0x05, 0x0D,         /*  Usage Page (Digitizer),             */
 517        0x09, 0x02,         /*  Usage (Pen),                        */
 518        0xA1, 0x01,         /*  Collection (Application),           */
 519        0x85, 0x10,         /*      Report ID (16),                 */
 520        0x09, 0x20,         /*      Usage (Stylus),                 */
 521        0xA0,               /*      Collection (Physical),          */
 522        0x95, 0x01,         /*          Report Count (1),           */
 523        0x15, 0x01,         /*          Logical Minimum (1),        */
 524        0x25, 0x03,         /*          Logical Maximum (3),        */
 525        0x75, 0x02,         /*          Report Size (2),            */
 526        0x09, 0x42,         /*          Usage (Tip Switch),         */
 527        0x09, 0x44,         /*          Usage (Barrel Switch),      */
 528        0x09, 0x46,         /*          Usage (Tablet Pick),        */
 529        0x80,               /*          Input,                      */
 530        0x14,               /*          Logical Minimum (0),        */
 531        0x25, 0x01,         /*          Logical Maximum (1),        */
 532        0x75, 0x01,         /*          Report Size (1),            */
 533        0x09, 0x3C,         /*          Usage (Invert),             */
 534        0x81, 0x02,         /*          Input (Variable),           */
 535        0x81, 0x03,         /*          Input (Constant, Variable), */
 536        0x09, 0x32,         /*          Usage (In Range),           */
 537        0x81, 0x02,         /*          Input (Variable),           */
 538        0x95, 0x03,         /*          Report Count (3),           */
 539        0x81, 0x03,         /*          Input (Constant, Variable), */
 540        0xA4,               /*          Push,                       */
 541        0x05, 0x01,         /*          Usage Page (Desktop),       */
 542        0x55, 0xFD,         /*          Unit Exponent (-3),         */
 543        0x65, 0x13,         /*          Unit (Inch),                */
 544        0x34,               /*          Physical Minimum (0),       */
 545        0x14,               /*          Logical Minimum (0),        */
 546        0x75, 0x10,         /*          Report Size (16),           */
 547        0x95, 0x01,         /*          Report Count (1),           */
 548        0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
 549        0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
 550        0x09, 0x30,         /*          Usage (X),                  */
 551        0x81, 0x02,         /*          Input (Variable),           */
 552        0x46, 0x70, 0x17,   /*          Physical Maximum (6000),    */
 553        0x26, 0xE0, 0x2E,   /*          Logical Maximum (12000),    */
 554        0x09, 0x31,         /*          Usage (Y),                  */
 555        0x81, 0x02,         /*          Input (Variable),           */
 556        0xB4,               /*          Pop,                        */
 557        0x75, 0x10,         /*          Report Size (16),           */
 558        0x95, 0x01,         /*          Report Count (1),           */
 559        0x14,               /*          Logical Minimum (0),        */
 560        0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
 561        0x09, 0x30,         /*          Usage (Tip Pressure),       */
 562        0x81, 0x02,         /*          Input (Variable),           */
 563        0xA4,               /*          Push,                       */
 564        0x55, 0xFE,         /*          Unit Exponent (-2),         */
 565        0x65, 0x12,         /*          Unit (Radians),             */
 566        0x35, 0x97,         /*          Physical Minimum (-105),    */
 567        0x45, 0x69,         /*          Physical Maximum (105),     */
 568        0x15, 0x97,         /*          Logical Minimum (-105),     */
 569        0x25, 0x69,         /*          Logical Maximum (105),      */
 570        0x75, 0x08,         /*          Report Size (8),            */
 571        0x95, 0x02,         /*          Report Count (2),           */
 572        0x09, 0x3D,         /*          Usage (X Tilt),             */
 573        0x09, 0x3E,         /*          Usage (Y Tilt),             */
 574        0x81, 0x02,         /*          Input (Variable),           */
 575        0xB4,               /*          Pop,                        */
 576        0xC0,               /*      End Collection,                 */
 577        0xC0,               /*  End Collection,                     */
 578        0x05, 0x01,         /*  Usage Page (Desktop),               */
 579        0x09, 0x02,         /*  Usage (Mouse),                      */
 580        0xA1, 0x01,         /*  Collection (Application),           */
 581        0x85, 0x01,         /*      Report ID (1),                  */
 582        0x09, 0x01,         /*      Usage (Pointer),                */
 583        0xA0,               /*      Collection (Physical),          */
 584        0x75, 0x08,         /*          Report Size (8),            */
 585        0x95, 0x03,         /*          Report Count (3),           */
 586        0x81, 0x03,         /*          Input (Constant, Variable), */
 587        0x09, 0x38,         /*          Usage (Wheel),              */
 588        0x15, 0xFF,         /*          Logical Minimum (-1),       */
 589        0x25, 0x01,         /*          Logical Maximum (1),        */
 590        0x75, 0x08,         /*          Report Size (8),            */
 591        0x95, 0x01,         /*          Report Count (1),           */
 592        0x81, 0x06,         /*          Input (Variable, Relative), */
 593        0x75, 0x08,         /*          Report Size (8),            */
 594        0x95, 0x03,         /*          Report Count (3),           */
 595        0x81, 0x03,         /*          Input (Constant, Variable), */
 596        0xC0,               /*      End Collection,                 */
 597        0xC0,               /*  End Collection,                     */
 598        0x05, 0x01,         /*  Usage Page (Desktop),               */
 599        0x09, 0x06,         /*  Usage (Keyboard),                   */
 600        0xA1, 0x01,         /*  Collection (Application),           */
 601        0x85, 0x0D,         /*      Report ID (13),                 */
 602        0x05, 0x07,         /*      Usage Page (Keyboard),          */
 603        0x19, 0xE0,         /*      Usage Minimum (KB Leftcontrol), */
 604        0x29, 0xE7,         /*      Usage Maximum (KB Right GUI),   */
 605        0x14,               /*      Logical Minimum (0),            */
 606        0x25, 0x01,         /*      Logical Maximum (1),            */
 607        0x75, 0x01,         /*      Report Size (1),                */
 608        0x95, 0x08,         /*      Report Count (8),               */
 609        0x81, 0x02,         /*      Input (Variable),               */
 610        0x75, 0x08,         /*      Report Size (8),                */
 611        0x95, 0x01,         /*      Report Count (1),               */
 612        0x81, 0x01,         /*      Input (Constant),               */
 613        0x18,               /*      Usage Minimum (None),           */
 614        0x29, 0x65,         /*      Usage Maximum (KB Application), */
 615        0x14,               /*      Logical Minimum (0),            */
 616        0x25, 0x65,         /*      Logical Maximum (101),          */
 617        0x75, 0x08,         /*      Report Size (8),                */
 618        0x95, 0x05,         /*      Report Count (5),               */
 619        0x80,               /*      Input,                          */
 620        0xC0,               /*  End Collection,                     */
 621        0x05, 0x0C,         /*  Usage Page (Consumer),              */
 622        0x09, 0x01,         /*  Usage (Consumer Control),           */
 623        0xA1, 0x01,         /*  Collection (Application),           */
 624        0x85, 0x0C,         /*      Report ID (12),                 */
 625        0x09, 0xE9,         /*      Usage (Volume Inc),             */
 626        0x09, 0xEA,         /*      Usage (Volume Dec),             */
 627        0x14,               /*      Logical Minimum (0),            */
 628        0x25, 0x01,         /*      Logical Maximum (1),            */
 629        0x75, 0x01,         /*      Report Size (1),                */
 630        0x95, 0x02,         /*      Report Count (2),               */
 631        0x81, 0x02,         /*      Input (Variable),               */
 632        0x75, 0x06,         /*      Report Size (6),                */
 633        0x95, 0x01,         /*      Report Count (1),               */
 634        0x81, 0x03,         /*      Input (Constant, Variable),     */
 635        0x75, 0x10,         /*      Report Size (16),               */
 636        0x95, 0x03,         /*      Report Count (3),               */
 637        0x81, 0x03,         /*      Input (Constant, Variable),     */
 638        0xC0                /*  End Collection                      */
 639};
 640
 641static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 642                unsigned int *rsize)
 643{
 644        switch (hdev->product) {
 645        case USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH:
 646                if (*rsize == SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE) {
 647                        rdesc = slim_tablet_5_8_inch_rdesc_fixed;
 648                        *rsize = sizeof(slim_tablet_5_8_inch_rdesc_fixed);
 649                }
 650                break;
 651        case USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH:
 652                if (*rsize == SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE) {
 653                        rdesc = slim_tablet_12_1_inch_rdesc_fixed;
 654                        *rsize = sizeof(slim_tablet_12_1_inch_rdesc_fixed);
 655                }
 656                break;
 657        case USB_DEVICE_ID_WALTOP_Q_PAD:
 658                if (*rsize == Q_PAD_RDESC_ORIG_SIZE) {
 659                        rdesc = q_pad_rdesc_fixed;
 660                        *rsize = sizeof(q_pad_rdesc_fixed);
 661                }
 662                break;
 663        case USB_DEVICE_ID_WALTOP_PID_0038:
 664                if (*rsize == PID_0038_RDESC_ORIG_SIZE) {
 665                        rdesc = pid_0038_rdesc_fixed;
 666                        *rsize = sizeof(pid_0038_rdesc_fixed);
 667                }
 668                break;
 669        case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH:
 670                if (*rsize == MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE) {
 671                        rdesc = media_tablet_10_6_inch_rdesc_fixed;
 672                        *rsize = sizeof(media_tablet_10_6_inch_rdesc_fixed);
 673                }
 674                break;
 675        case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH:
 676                if (*rsize == MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE) {
 677                        rdesc = media_tablet_14_1_inch_rdesc_fixed;
 678                        *rsize = sizeof(media_tablet_14_1_inch_rdesc_fixed);
 679                }
 680                break;
 681        case USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET:
 682                if (*rsize == SIRIUS_BATTERY_FREE_TABLET_RDESC_ORIG_SIZE) {
 683                        rdesc = sirius_battery_free_tablet_rdesc_fixed;
 684                        *rsize = sizeof(sirius_battery_free_tablet_rdesc_fixed);
 685                }
 686                break;
 687        }
 688        return rdesc;
 689}
 690
 691static int waltop_raw_event(struct hid_device *hdev, struct hid_report *report,
 692                     u8 *data, int size)
 693{
 694        /* If this is a pen input report */
 695        if (report->type == HID_INPUT_REPORT && report->id == 16 && size >= 8) {
 696                /*
 697                 * Ignore reported pressure when a barrel button is pressed,
 698                 * because it is rarely correct.
 699                 */
 700
 701                /* If a barrel button is pressed */
 702                if ((data[1] & 0xF) > 1) {
 703                        /* Report zero pressure */
 704                        data[6] = 0;
 705                        data[7] = 0;
 706                }
 707        }
 708
 709        /* If this is a pen input report of Sirius Battery Free Tablet */
 710        if (hdev->product == USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET &&
 711            report->type == HID_INPUT_REPORT &&
 712            report->id == 16 &&
 713            size == 10) {
 714                /*
 715                 * The tablet reports tilt as roughly sin(a)*21 (18 means 60
 716                 * degrees).
 717                 *
 718                 * This array stores angles as radians * 100, corresponding to
 719                 * reported values up to 60 degrees, as expected by userspace.
 720                 */
 721                static const s8 tilt_to_radians[] = {
 722                        0, 5, 10, 14, 19, 24, 29, 34, 40, 45,
 723                        50, 56, 62, 68, 74, 81, 88, 96, 105
 724                };
 725
 726                s8 tilt_x = (s8)data[8];
 727                s8 tilt_y = (s8)data[9];
 728                s8 sign_x = tilt_x >= 0 ? 1 : -1;
 729                s8 sign_y = tilt_y >= 0 ? 1 : -1;
 730
 731                tilt_x *= sign_x;
 732                tilt_y *= sign_y;
 733
 734                /*
 735                 * Reverse the Y Tilt direction to match the HID standard and
 736                 * userspace expectations. See HID Usage Tables v1.12 16.3.2
 737                 * Tilt Orientation.
 738                 */
 739                sign_y *= -1;
 740
 741                /*
 742                 * This effectively clamps reported tilt to 60 degrees - the
 743                 * range expected by userspace
 744                 */
 745                if (tilt_x > ARRAY_SIZE(tilt_to_radians) - 1)
 746                        tilt_x = ARRAY_SIZE(tilt_to_radians) - 1;
 747                if (tilt_y > ARRAY_SIZE(tilt_to_radians) - 1)
 748                        tilt_y = ARRAY_SIZE(tilt_to_radians) - 1;
 749
 750                data[8] = tilt_to_radians[tilt_x] * sign_x;
 751                data[9] = tilt_to_radians[tilt_y] * sign_y;
 752        }
 753
 754        return 0;
 755}
 756
 757static const struct hid_device_id waltop_devices[] = {
 758        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
 759                                USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
 760        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
 761                                USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
 762        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
 763                                USB_DEVICE_ID_WALTOP_Q_PAD) },
 764        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
 765                                USB_DEVICE_ID_WALTOP_PID_0038) },
 766        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
 767                                USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) },
 768        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
 769                                USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
 770        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
 771                         USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) },
 772        { }
 773};
 774MODULE_DEVICE_TABLE(hid, waltop_devices);
 775
 776static struct hid_driver waltop_driver = {
 777        .name = "waltop",
 778        .id_table = waltop_devices,
 779        .report_fixup = waltop_report_fixup,
 780        .raw_event = waltop_raw_event,
 781};
 782
 783static int __init waltop_init(void)
 784{
 785        return hid_register_driver(&waltop_driver);
 786}
 787
 788static void __exit waltop_exit(void)
 789{
 790        hid_unregister_driver(&waltop_driver);
 791}
 792
 793module_init(waltop_init);
 794module_exit(waltop_exit);
 795MODULE_LICENSE("GPL");
 796
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.