747 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * HID driver for Waltop devices not fully compliant with HID standard4 *5 * Copyright (c) 2010 Nikolai Kondrashov6 */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, which19 * wasn't submitted to the kernel, for some reason. The official driver20 * 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 waltop23 * tablet input mode, switching it between "default", "tablet" and "ink".24 *25 * This driver only uses "default" mode for all the supported tablets. This26 * mode tries to be HID-compatible (not very successfully), but cripples the27 * resolution of some tablets.28 *29 * The "tablet" mode uses some proprietary, yet decipherable protocol, which30 * 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 default38 * 02 16 01 tablet39 * 02 16 02 ink40 */41 42/* Size of the original report descriptor of Slim Tablet 5.8 inch */43#define SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE 22244 45/* Fixed Slim Tablet 5.8 inch descriptor */46static const __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 26995 96/* Fixed Slim Tablet 12.1 inch descriptor */97static const __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 241146 147/* Fixed Q Pad descriptor */148static const __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 241197 198/*199 * Fixed report descriptor for tablet with PID 0038.200 */201static const __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 300250 251/* Fixed Media Tablet 10.6 inch descriptor */252static const __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 309363 364/* Fixed Media Tablet 14.1 inch descriptor */365static const __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 335474 475/* Fixed Sirius Battery Free Tablet descriptor */476static const __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 const __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 *rsize = sizeof(slim_tablet_5_8_inch_rdesc_fixed);609 return 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 *rsize = sizeof(slim_tablet_12_1_inch_rdesc_fixed);615 return 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 *rsize = sizeof(q_pad_rdesc_fixed);621 return q_pad_rdesc_fixed;622 }623 break;624 case USB_DEVICE_ID_WALTOP_PID_0038:625 if (*rsize == PID_0038_RDESC_ORIG_SIZE) {626 *rsize = sizeof(pid_0038_rdesc_fixed);627 return 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 *rsize = sizeof(media_tablet_10_6_inch_rdesc_fixed);633 return 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 *rsize = sizeof(media_tablet_14_1_inch_rdesc_fixed);639 return 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 *rsize = sizeof(sirius_battery_free_tablet_rdesc_fixed);645 return 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 60677 * degrees).678 *679 * This array stores angles as radians * 100, corresponding to680 * 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, 105685 };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 and697 * userspace expectations. See HID Usage Tables v1.12 16.3.2698 * Tilt Orientation.699 */700 sign_y *= -1;701 702 /*703 * This effectively clamps reported tilt to 60 degrees - the704 * range expected by userspace705 */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_DESCRIPTION("HID driver for Waltop devices not fully compliant with HID standard");746MODULE_LICENSE("GPL");747