hid-waltop.c (39539B)
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 */ 46static __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 */ 97static __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 */ 148static __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 */ 201static __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 */ 252static __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 */ 365static __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 */ 476static __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 602static __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 652static 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 718static 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}; 735MODULE_DEVICE_TABLE(hid, waltop_devices); 736 737static 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}; 743module_hid_driver(waltop_driver); 744 745MODULE_LICENSE("GPL");