root/drivers/hid/hid-waltop.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. waltop_report_fixup
  2. waltop_raw_event

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

/* [<][>][^][v][top][bottom][index][help] */