Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.19 1090 lines 47 kB view raw
1/* 2 * HID driver for UC-Logic devices not fully compliant with HID standard 3 * 4 * Copyright (c) 2010-2014 Nikolai Kondrashov 5 * Copyright (c) 2013 Martin Rusko 6 */ 7 8/* 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the Free 11 * Software Foundation; either version 2 of the License, or (at your option) 12 * any later version. 13 */ 14 15#include <linux/device.h> 16#include <linux/hid.h> 17#include <linux/module.h> 18#include <linux/usb.h> 19#include <asm/unaligned.h> 20#include "usbhid/usbhid.h" 21 22#include "hid-ids.h" 23 24/* Size of the original descriptor of WPXXXXU tablets */ 25#define WPXXXXU_RDESC_ORIG_SIZE 212 26 27/* Fixed WP4030U report descriptor */ 28static __u8 wp4030u_rdesc_fixed[] = { 29 0x05, 0x0D, /* Usage Page (Digitizer), */ 30 0x09, 0x02, /* Usage (Pen), */ 31 0xA1, 0x01, /* Collection (Application), */ 32 0x85, 0x09, /* Report ID (9), */ 33 0x09, 0x20, /* Usage (Stylus), */ 34 0xA0, /* Collection (Physical), */ 35 0x75, 0x01, /* Report Size (1), */ 36 0x09, 0x42, /* Usage (Tip Switch), */ 37 0x09, 0x44, /* Usage (Barrel Switch), */ 38 0x09, 0x46, /* Usage (Tablet Pick), */ 39 0x14, /* Logical Minimum (0), */ 40 0x25, 0x01, /* Logical Maximum (1), */ 41 0x95, 0x03, /* Report Count (3), */ 42 0x81, 0x02, /* Input (Variable), */ 43 0x95, 0x05, /* Report Count (5), */ 44 0x81, 0x01, /* Input (Constant), */ 45 0x75, 0x10, /* Report Size (16), */ 46 0x95, 0x01, /* Report Count (1), */ 47 0x14, /* Logical Minimum (0), */ 48 0xA4, /* Push, */ 49 0x05, 0x01, /* Usage Page (Desktop), */ 50 0x55, 0xFD, /* Unit Exponent (-3), */ 51 0x65, 0x13, /* Unit (Inch), */ 52 0x34, /* Physical Minimum (0), */ 53 0x09, 0x30, /* Usage (X), */ 54 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */ 55 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 56 0x81, 0x02, /* Input (Variable), */ 57 0x09, 0x31, /* Usage (Y), */ 58 0x46, 0xB8, 0x0B, /* Physical Maximum (3000), */ 59 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 60 0x81, 0x02, /* Input (Variable), */ 61 0xB4, /* Pop, */ 62 0x09, 0x30, /* Usage (Tip Pressure), */ 63 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 64 0x81, 0x02, /* Input (Variable), */ 65 0xC0, /* End Collection, */ 66 0xC0 /* End Collection */ 67}; 68 69/* Fixed WP5540U report descriptor */ 70static __u8 wp5540u_rdesc_fixed[] = { 71 0x05, 0x0D, /* Usage Page (Digitizer), */ 72 0x09, 0x02, /* Usage (Pen), */ 73 0xA1, 0x01, /* Collection (Application), */ 74 0x85, 0x09, /* Report ID (9), */ 75 0x09, 0x20, /* Usage (Stylus), */ 76 0xA0, /* Collection (Physical), */ 77 0x75, 0x01, /* Report Size (1), */ 78 0x09, 0x42, /* Usage (Tip Switch), */ 79 0x09, 0x44, /* Usage (Barrel Switch), */ 80 0x09, 0x46, /* Usage (Tablet Pick), */ 81 0x14, /* Logical Minimum (0), */ 82 0x25, 0x01, /* Logical Maximum (1), */ 83 0x95, 0x03, /* Report Count (3), */ 84 0x81, 0x02, /* Input (Variable), */ 85 0x95, 0x05, /* Report Count (5), */ 86 0x81, 0x01, /* Input (Constant), */ 87 0x75, 0x10, /* Report Size (16), */ 88 0x95, 0x01, /* Report Count (1), */ 89 0x14, /* Logical Minimum (0), */ 90 0xA4, /* Push, */ 91 0x05, 0x01, /* Usage Page (Desktop), */ 92 0x55, 0xFD, /* Unit Exponent (-3), */ 93 0x65, 0x13, /* Unit (Inch), */ 94 0x34, /* Physical Minimum (0), */ 95 0x09, 0x30, /* Usage (X), */ 96 0x46, 0x7C, 0x15, /* Physical Maximum (5500), */ 97 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 98 0x81, 0x02, /* Input (Variable), */ 99 0x09, 0x31, /* Usage (Y), */ 100 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */ 101 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 102 0x81, 0x02, /* Input (Variable), */ 103 0xB4, /* Pop, */ 104 0x09, 0x30, /* Usage (Tip Pressure), */ 105 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 106 0x81, 0x02, /* Input (Variable), */ 107 0xC0, /* End Collection, */ 108 0xC0, /* End Collection, */ 109 0x05, 0x01, /* Usage Page (Desktop), */ 110 0x09, 0x02, /* Usage (Mouse), */ 111 0xA1, 0x01, /* Collection (Application), */ 112 0x85, 0x08, /* Report ID (8), */ 113 0x09, 0x01, /* Usage (Pointer), */ 114 0xA0, /* Collection (Physical), */ 115 0x75, 0x01, /* Report Size (1), */ 116 0x05, 0x09, /* Usage Page (Button), */ 117 0x19, 0x01, /* Usage Minimum (01h), */ 118 0x29, 0x03, /* Usage Maximum (03h), */ 119 0x14, /* Logical Minimum (0), */ 120 0x25, 0x01, /* Logical Maximum (1), */ 121 0x95, 0x03, /* Report Count (3), */ 122 0x81, 0x02, /* Input (Variable), */ 123 0x95, 0x05, /* Report Count (5), */ 124 0x81, 0x01, /* Input (Constant), */ 125 0x05, 0x01, /* Usage Page (Desktop), */ 126 0x75, 0x08, /* Report Size (8), */ 127 0x09, 0x30, /* Usage (X), */ 128 0x09, 0x31, /* Usage (Y), */ 129 0x15, 0x81, /* Logical Minimum (-127), */ 130 0x25, 0x7F, /* Logical Maximum (127), */ 131 0x95, 0x02, /* Report Count (2), */ 132 0x81, 0x06, /* Input (Variable, Relative), */ 133 0x09, 0x38, /* Usage (Wheel), */ 134 0x15, 0xFF, /* Logical Minimum (-1), */ 135 0x25, 0x01, /* Logical Maximum (1), */ 136 0x95, 0x01, /* Report Count (1), */ 137 0x81, 0x06, /* Input (Variable, Relative), */ 138 0x81, 0x01, /* Input (Constant), */ 139 0xC0, /* End Collection, */ 140 0xC0 /* End Collection */ 141}; 142 143/* Fixed WP8060U report descriptor */ 144static __u8 wp8060u_rdesc_fixed[] = { 145 0x05, 0x0D, /* Usage Page (Digitizer), */ 146 0x09, 0x02, /* Usage (Pen), */ 147 0xA1, 0x01, /* Collection (Application), */ 148 0x85, 0x09, /* Report ID (9), */ 149 0x09, 0x20, /* Usage (Stylus), */ 150 0xA0, /* Collection (Physical), */ 151 0x75, 0x01, /* Report Size (1), */ 152 0x09, 0x42, /* Usage (Tip Switch), */ 153 0x09, 0x44, /* Usage (Barrel Switch), */ 154 0x09, 0x46, /* Usage (Tablet Pick), */ 155 0x14, /* Logical Minimum (0), */ 156 0x25, 0x01, /* Logical Maximum (1), */ 157 0x95, 0x03, /* Report Count (3), */ 158 0x81, 0x02, /* Input (Variable), */ 159 0x95, 0x05, /* Report Count (5), */ 160 0x81, 0x01, /* Input (Constant), */ 161 0x75, 0x10, /* Report Size (16), */ 162 0x95, 0x01, /* Report Count (1), */ 163 0x14, /* Logical Minimum (0), */ 164 0xA4, /* Push, */ 165 0x05, 0x01, /* Usage Page (Desktop), */ 166 0x55, 0xFD, /* Unit Exponent (-3), */ 167 0x65, 0x13, /* Unit (Inch), */ 168 0x34, /* Physical Minimum (0), */ 169 0x09, 0x30, /* Usage (X), */ 170 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ 171 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 172 0x81, 0x02, /* Input (Variable), */ 173 0x09, 0x31, /* Usage (Y), */ 174 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ 175 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 176 0x81, 0x02, /* Input (Variable), */ 177 0xB4, /* Pop, */ 178 0x09, 0x30, /* Usage (Tip Pressure), */ 179 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 180 0x81, 0x02, /* Input (Variable), */ 181 0xC0, /* End Collection, */ 182 0xC0, /* End Collection, */ 183 0x05, 0x01, /* Usage Page (Desktop), */ 184 0x09, 0x02, /* Usage (Mouse), */ 185 0xA1, 0x01, /* Collection (Application), */ 186 0x85, 0x08, /* Report ID (8), */ 187 0x09, 0x01, /* Usage (Pointer), */ 188 0xA0, /* Collection (Physical), */ 189 0x75, 0x01, /* Report Size (1), */ 190 0x05, 0x09, /* Usage Page (Button), */ 191 0x19, 0x01, /* Usage Minimum (01h), */ 192 0x29, 0x03, /* Usage Maximum (03h), */ 193 0x14, /* Logical Minimum (0), */ 194 0x25, 0x01, /* Logical Maximum (1), */ 195 0x95, 0x03, /* Report Count (3), */ 196 0x81, 0x02, /* Input (Variable), */ 197 0x95, 0x05, /* Report Count (5), */ 198 0x81, 0x01, /* Input (Constant), */ 199 0x05, 0x01, /* Usage Page (Desktop), */ 200 0x75, 0x08, /* Report Size (8), */ 201 0x09, 0x30, /* Usage (X), */ 202 0x09, 0x31, /* Usage (Y), */ 203 0x15, 0x81, /* Logical Minimum (-127), */ 204 0x25, 0x7F, /* Logical Maximum (127), */ 205 0x95, 0x02, /* Report Count (2), */ 206 0x81, 0x06, /* Input (Variable, Relative), */ 207 0x09, 0x38, /* Usage (Wheel), */ 208 0x15, 0xFF, /* Logical Minimum (-1), */ 209 0x25, 0x01, /* Logical Maximum (1), */ 210 0x95, 0x01, /* Report Count (1), */ 211 0x81, 0x06, /* Input (Variable, Relative), */ 212 0x81, 0x01, /* Input (Constant), */ 213 0xC0, /* End Collection, */ 214 0xC0 /* End Collection */ 215}; 216 217/* Size of the original descriptor of WP1062 tablet */ 218#define WP1062_RDESC_ORIG_SIZE 254 219 220/* Fixed WP1062 report descriptor */ 221static __u8 wp1062_rdesc_fixed[] = { 222 0x05, 0x0D, /* Usage Page (Digitizer), */ 223 0x09, 0x02, /* Usage (Pen), */ 224 0xA1, 0x01, /* Collection (Application), */ 225 0x85, 0x09, /* Report ID (9), */ 226 0x09, 0x20, /* Usage (Stylus), */ 227 0xA0, /* Collection (Physical), */ 228 0x75, 0x01, /* Report Size (1), */ 229 0x09, 0x42, /* Usage (Tip Switch), */ 230 0x09, 0x44, /* Usage (Barrel Switch), */ 231 0x09, 0x46, /* Usage (Tablet Pick), */ 232 0x14, /* Logical Minimum (0), */ 233 0x25, 0x01, /* Logical Maximum (1), */ 234 0x95, 0x03, /* Report Count (3), */ 235 0x81, 0x02, /* Input (Variable), */ 236 0x95, 0x04, /* Report Count (4), */ 237 0x81, 0x01, /* Input (Constant), */ 238 0x09, 0x32, /* Usage (In Range), */ 239 0x95, 0x01, /* Report Count (1), */ 240 0x81, 0x02, /* Input (Variable), */ 241 0x75, 0x10, /* Report Size (16), */ 242 0x95, 0x01, /* Report Count (1), */ 243 0x14, /* Logical Minimum (0), */ 244 0xA4, /* Push, */ 245 0x05, 0x01, /* Usage Page (Desktop), */ 246 0x55, 0xFD, /* Unit Exponent (-3), */ 247 0x65, 0x13, /* Unit (Inch), */ 248 0x34, /* Physical Minimum (0), */ 249 0x09, 0x30, /* Usage (X), */ 250 0x46, 0x10, 0x27, /* Physical Maximum (10000), */ 251 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */ 252 0x81, 0x02, /* Input (Variable), */ 253 0x09, 0x31, /* Usage (Y), */ 254 0x46, 0xB7, 0x19, /* Physical Maximum (6583), */ 255 0x26, 0x6E, 0x33, /* Logical Maximum (13166), */ 256 0x81, 0x02, /* Input (Variable), */ 257 0xB4, /* Pop, */ 258 0x09, 0x30, /* Usage (Tip Pressure), */ 259 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 260 0x81, 0x02, /* Input (Variable), */ 261 0xC0, /* End Collection, */ 262 0xC0 /* End Collection */ 263}; 264 265/* Size of the original descriptor of PF1209 tablet */ 266#define PF1209_RDESC_ORIG_SIZE 234 267 268/* Fixed PF1209 report descriptor */ 269static __u8 pf1209_rdesc_fixed[] = { 270 0x05, 0x0D, /* Usage Page (Digitizer), */ 271 0x09, 0x02, /* Usage (Pen), */ 272 0xA1, 0x01, /* Collection (Application), */ 273 0x85, 0x09, /* Report ID (9), */ 274 0x09, 0x20, /* Usage (Stylus), */ 275 0xA0, /* Collection (Physical), */ 276 0x75, 0x01, /* Report Size (1), */ 277 0x09, 0x42, /* Usage (Tip Switch), */ 278 0x09, 0x44, /* Usage (Barrel Switch), */ 279 0x09, 0x46, /* Usage (Tablet Pick), */ 280 0x14, /* Logical Minimum (0), */ 281 0x25, 0x01, /* Logical Maximum (1), */ 282 0x95, 0x03, /* Report Count (3), */ 283 0x81, 0x02, /* Input (Variable), */ 284 0x95, 0x05, /* Report Count (5), */ 285 0x81, 0x01, /* Input (Constant), */ 286 0x75, 0x10, /* Report Size (16), */ 287 0x95, 0x01, /* Report Count (1), */ 288 0x14, /* Logical Minimum (0), */ 289 0xA4, /* Push, */ 290 0x05, 0x01, /* Usage Page (Desktop), */ 291 0x55, 0xFD, /* Unit Exponent (-3), */ 292 0x65, 0x13, /* Unit (Inch), */ 293 0x34, /* Physical Minimum (0), */ 294 0x09, 0x30, /* Usage (X), */ 295 0x46, 0xE0, 0x2E, /* Physical Maximum (12000), */ 296 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 297 0x81, 0x02, /* Input (Variable), */ 298 0x09, 0x31, /* Usage (Y), */ 299 0x46, 0x28, 0x23, /* Physical Maximum (9000), */ 300 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 301 0x81, 0x02, /* Input (Variable), */ 302 0xB4, /* Pop, */ 303 0x09, 0x30, /* Usage (Tip Pressure), */ 304 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 305 0x81, 0x02, /* Input (Variable), */ 306 0xC0, /* End Collection, */ 307 0xC0, /* End Collection, */ 308 0x05, 0x01, /* Usage Page (Desktop), */ 309 0x09, 0x02, /* Usage (Mouse), */ 310 0xA1, 0x01, /* Collection (Application), */ 311 0x85, 0x08, /* Report ID (8), */ 312 0x09, 0x01, /* Usage (Pointer), */ 313 0xA0, /* Collection (Physical), */ 314 0x75, 0x01, /* Report Size (1), */ 315 0x05, 0x09, /* Usage Page (Button), */ 316 0x19, 0x01, /* Usage Minimum (01h), */ 317 0x29, 0x03, /* Usage Maximum (03h), */ 318 0x14, /* Logical Minimum (0), */ 319 0x25, 0x01, /* Logical Maximum (1), */ 320 0x95, 0x03, /* Report Count (3), */ 321 0x81, 0x02, /* Input (Variable), */ 322 0x95, 0x05, /* Report Count (5), */ 323 0x81, 0x01, /* Input (Constant), */ 324 0x05, 0x01, /* Usage Page (Desktop), */ 325 0x75, 0x08, /* Report Size (8), */ 326 0x09, 0x30, /* Usage (X), */ 327 0x09, 0x31, /* Usage (Y), */ 328 0x15, 0x81, /* Logical Minimum (-127), */ 329 0x25, 0x7F, /* Logical Maximum (127), */ 330 0x95, 0x02, /* Report Count (2), */ 331 0x81, 0x06, /* Input (Variable, Relative), */ 332 0x09, 0x38, /* Usage (Wheel), */ 333 0x15, 0xFF, /* Logical Minimum (-1), */ 334 0x25, 0x01, /* Logical Maximum (1), */ 335 0x95, 0x01, /* Report Count (1), */ 336 0x81, 0x06, /* Input (Variable, Relative), */ 337 0x81, 0x01, /* Input (Constant), */ 338 0xC0, /* End Collection, */ 339 0xC0 /* End Collection */ 340}; 341 342/* Size of the original descriptors of TWHL850 tablet */ 343#define TWHL850_RDESC_ORIG_SIZE0 182 344#define TWHL850_RDESC_ORIG_SIZE1 161 345#define TWHL850_RDESC_ORIG_SIZE2 92 346 347/* Fixed PID 0522 tablet report descriptor, interface 0 (stylus) */ 348static __u8 twhl850_rdesc_fixed0[] = { 349 0x05, 0x0D, /* Usage Page (Digitizer), */ 350 0x09, 0x02, /* Usage (Pen), */ 351 0xA1, 0x01, /* Collection (Application), */ 352 0x85, 0x09, /* Report ID (9), */ 353 0x09, 0x20, /* Usage (Stylus), */ 354 0xA0, /* Collection (Physical), */ 355 0x14, /* Logical Minimum (0), */ 356 0x25, 0x01, /* Logical Maximum (1), */ 357 0x75, 0x01, /* Report Size (1), */ 358 0x95, 0x03, /* Report Count (3), */ 359 0x09, 0x42, /* Usage (Tip Switch), */ 360 0x09, 0x44, /* Usage (Barrel Switch), */ 361 0x09, 0x46, /* Usage (Tablet Pick), */ 362 0x81, 0x02, /* Input (Variable), */ 363 0x81, 0x03, /* Input (Constant, Variable), */ 364 0x95, 0x01, /* Report Count (1), */ 365 0x09, 0x32, /* Usage (In Range), */ 366 0x81, 0x02, /* Input (Variable), */ 367 0x81, 0x03, /* Input (Constant, Variable), */ 368 0x75, 0x10, /* Report Size (16), */ 369 0xA4, /* Push, */ 370 0x05, 0x01, /* Usage Page (Desktop), */ 371 0x65, 0x13, /* Unit (Inch), */ 372 0x55, 0xFD, /* Unit Exponent (-3), */ 373 0x34, /* Physical Minimum (0), */ 374 0x09, 0x30, /* Usage (X), */ 375 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ 376 0x26, 0x00, 0x7D, /* Logical Maximum (32000), */ 377 0x81, 0x02, /* Input (Variable), */ 378 0x09, 0x31, /* Usage (Y), */ 379 0x46, 0x88, 0x13, /* Physical Maximum (5000), */ 380 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */ 381 0x81, 0x02, /* Input (Variable), */ 382 0xB4, /* Pop, */ 383 0x09, 0x30, /* Usage (Tip Pressure), */ 384 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 385 0x81, 0x02, /* Input (Variable), */ 386 0xC0, /* End Collection, */ 387 0xC0 /* End Collection */ 388}; 389 390/* Fixed PID 0522 tablet report descriptor, interface 1 (mouse) */ 391static __u8 twhl850_rdesc_fixed1[] = { 392 0x05, 0x01, /* Usage Page (Desktop), */ 393 0x09, 0x02, /* Usage (Mouse), */ 394 0xA1, 0x01, /* Collection (Application), */ 395 0x85, 0x01, /* Report ID (1), */ 396 0x09, 0x01, /* Usage (Pointer), */ 397 0xA0, /* Collection (Physical), */ 398 0x05, 0x09, /* Usage Page (Button), */ 399 0x75, 0x01, /* Report Size (1), */ 400 0x95, 0x03, /* Report Count (3), */ 401 0x19, 0x01, /* Usage Minimum (01h), */ 402 0x29, 0x03, /* Usage Maximum (03h), */ 403 0x14, /* Logical Minimum (0), */ 404 0x25, 0x01, /* Logical Maximum (1), */ 405 0x81, 0x02, /* Input (Variable), */ 406 0x95, 0x05, /* Report Count (5), */ 407 0x81, 0x03, /* Input (Constant, Variable), */ 408 0x05, 0x01, /* Usage Page (Desktop), */ 409 0x09, 0x30, /* Usage (X), */ 410 0x09, 0x31, /* Usage (Y), */ 411 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ 412 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 413 0x75, 0x10, /* Report Size (16), */ 414 0x95, 0x02, /* Report Count (2), */ 415 0x81, 0x06, /* Input (Variable, Relative), */ 416 0x09, 0x38, /* Usage (Wheel), */ 417 0x15, 0xFF, /* Logical Minimum (-1), */ 418 0x25, 0x01, /* Logical Maximum (1), */ 419 0x95, 0x01, /* Report Count (1), */ 420 0x75, 0x08, /* Report Size (8), */ 421 0x81, 0x06, /* Input (Variable, Relative), */ 422 0x81, 0x03, /* Input (Constant, Variable), */ 423 0xC0, /* End Collection, */ 424 0xC0 /* End Collection */ 425}; 426 427/* Fixed PID 0522 tablet report descriptor, interface 2 (frame buttons) */ 428static __u8 twhl850_rdesc_fixed2[] = { 429 0x05, 0x01, /* Usage Page (Desktop), */ 430 0x09, 0x06, /* Usage (Keyboard), */ 431 0xA1, 0x01, /* Collection (Application), */ 432 0x85, 0x03, /* Report ID (3), */ 433 0x05, 0x07, /* Usage Page (Keyboard), */ 434 0x14, /* Logical Minimum (0), */ 435 0x19, 0xE0, /* Usage Minimum (KB Leftcontrol), */ 436 0x29, 0xE7, /* Usage Maximum (KB Right GUI), */ 437 0x25, 0x01, /* Logical Maximum (1), */ 438 0x75, 0x01, /* Report Size (1), */ 439 0x95, 0x08, /* Report Count (8), */ 440 0x81, 0x02, /* Input (Variable), */ 441 0x18, /* Usage Minimum (None), */ 442 0x29, 0xFF, /* Usage Maximum (FFh), */ 443 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 444 0x75, 0x08, /* Report Size (8), */ 445 0x95, 0x06, /* Report Count (6), */ 446 0x80, /* Input, */ 447 0xC0 /* End Collection */ 448}; 449 450/* Size of the original descriptors of TWHA60 tablet */ 451#define TWHA60_RDESC_ORIG_SIZE0 254 452#define TWHA60_RDESC_ORIG_SIZE1 139 453 454/* Fixed TWHA60 report descriptor, interface 0 (stylus) */ 455static __u8 twha60_rdesc_fixed0[] = { 456 0x05, 0x0D, /* Usage Page (Digitizer), */ 457 0x09, 0x02, /* Usage (Pen), */ 458 0xA1, 0x01, /* Collection (Application), */ 459 0x85, 0x09, /* Report ID (9), */ 460 0x09, 0x20, /* Usage (Stylus), */ 461 0xA0, /* Collection (Physical), */ 462 0x75, 0x01, /* Report Size (1), */ 463 0x09, 0x42, /* Usage (Tip Switch), */ 464 0x09, 0x44, /* Usage (Barrel Switch), */ 465 0x09, 0x46, /* Usage (Tablet Pick), */ 466 0x14, /* Logical Minimum (0), */ 467 0x25, 0x01, /* Logical Maximum (1), */ 468 0x95, 0x03, /* Report Count (3), */ 469 0x81, 0x02, /* Input (Variable), */ 470 0x95, 0x04, /* Report Count (4), */ 471 0x81, 0x01, /* Input (Constant), */ 472 0x09, 0x32, /* Usage (In Range), */ 473 0x95, 0x01, /* Report Count (1), */ 474 0x81, 0x02, /* Input (Variable), */ 475 0x75, 0x10, /* Report Size (16), */ 476 0x95, 0x01, /* Report Count (1), */ 477 0x14, /* Logical Minimum (0), */ 478 0xA4, /* Push, */ 479 0x05, 0x01, /* Usage Page (Desktop), */ 480 0x55, 0xFD, /* Unit Exponent (-3), */ 481 0x65, 0x13, /* Unit (Inch), */ 482 0x34, /* Physical Minimum (0), */ 483 0x09, 0x30, /* Usage (X), */ 484 0x46, 0x10, 0x27, /* Physical Maximum (10000), */ 485 0x27, 0x3F, 0x9C, 486 0x00, 0x00, /* Logical Maximum (39999), */ 487 0x81, 0x02, /* Input (Variable), */ 488 0x09, 0x31, /* Usage (Y), */ 489 0x46, 0x6A, 0x18, /* Physical Maximum (6250), */ 490 0x26, 0xA7, 0x61, /* Logical Maximum (24999), */ 491 0x81, 0x02, /* Input (Variable), */ 492 0xB4, /* Pop, */ 493 0x09, 0x30, /* Usage (Tip Pressure), */ 494 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 495 0x81, 0x02, /* Input (Variable), */ 496 0xC0, /* End Collection, */ 497 0xC0 /* End Collection */ 498}; 499 500/* Fixed TWHA60 report descriptor, interface 1 (frame buttons) */ 501static __u8 twha60_rdesc_fixed1[] = { 502 0x05, 0x01, /* Usage Page (Desktop), */ 503 0x09, 0x06, /* Usage (Keyboard), */ 504 0xA1, 0x01, /* Collection (Application), */ 505 0x85, 0x05, /* Report ID (5), */ 506 0x05, 0x07, /* Usage Page (Keyboard), */ 507 0x14, /* Logical Minimum (0), */ 508 0x25, 0x01, /* Logical Maximum (1), */ 509 0x75, 0x01, /* Report Size (1), */ 510 0x95, 0x08, /* Report Count (8), */ 511 0x81, 0x01, /* Input (Constant), */ 512 0x95, 0x0C, /* Report Count (12), */ 513 0x19, 0x3A, /* Usage Minimum (KB F1), */ 514 0x29, 0x45, /* Usage Maximum (KB F12), */ 515 0x81, 0x02, /* Input (Variable), */ 516 0x95, 0x0C, /* Report Count (12), */ 517 0x19, 0x68, /* Usage Minimum (KB F13), */ 518 0x29, 0x73, /* Usage Maximum (KB F24), */ 519 0x81, 0x02, /* Input (Variable), */ 520 0x95, 0x08, /* Report Count (8), */ 521 0x81, 0x01, /* Input (Constant), */ 522 0xC0 /* End Collection */ 523}; 524 525/* Report descriptor template placeholder head */ 526#define UCLOGIC_PH_HEAD 0xFE, 0xED, 0x1D 527 528/* Report descriptor template placeholder IDs */ 529enum uclogic_ph_id { 530 UCLOGIC_PH_ID_X_LM, 531 UCLOGIC_PH_ID_X_PM, 532 UCLOGIC_PH_ID_Y_LM, 533 UCLOGIC_PH_ID_Y_PM, 534 UCLOGIC_PH_ID_PRESSURE_LM, 535 UCLOGIC_PH_ID_NUM 536}; 537 538/* Report descriptor template placeholder */ 539#define UCLOGIC_PH(_ID) UCLOGIC_PH_HEAD, UCLOGIC_PH_ID_##_ID 540#define UCLOGIC_PEN_REPORT_ID 0x07 541 542/* Fixed report descriptor template */ 543static const __u8 uclogic_tablet_rdesc_template[] = { 544 0x05, 0x0D, /* Usage Page (Digitizer), */ 545 0x09, 0x02, /* Usage (Pen), */ 546 0xA1, 0x01, /* Collection (Application), */ 547 0x85, 0x07, /* Report ID (7), */ 548 0x09, 0x20, /* Usage (Stylus), */ 549 0xA0, /* Collection (Physical), */ 550 0x14, /* Logical Minimum (0), */ 551 0x25, 0x01, /* Logical Maximum (1), */ 552 0x75, 0x01, /* Report Size (1), */ 553 0x09, 0x42, /* Usage (Tip Switch), */ 554 0x09, 0x44, /* Usage (Barrel Switch), */ 555 0x09, 0x46, /* Usage (Tablet Pick), */ 556 0x95, 0x03, /* Report Count (3), */ 557 0x81, 0x02, /* Input (Variable), */ 558 0x95, 0x03, /* Report Count (3), */ 559 0x81, 0x03, /* Input (Constant, Variable), */ 560 0x09, 0x32, /* Usage (In Range), */ 561 0x95, 0x01, /* Report Count (1), */ 562 0x81, 0x02, /* Input (Variable), */ 563 0x95, 0x01, /* Report Count (1), */ 564 0x81, 0x03, /* Input (Constant, Variable), */ 565 0x75, 0x10, /* Report Size (16), */ 566 0x95, 0x01, /* Report Count (1), */ 567 0xA4, /* Push, */ 568 0x05, 0x01, /* Usage Page (Desktop), */ 569 0x65, 0x13, /* Unit (Inch), */ 570 0x55, 0xFD, /* Unit Exponent (-3), */ 571 0x34, /* Physical Minimum (0), */ 572 0x09, 0x30, /* Usage (X), */ 573 0x27, UCLOGIC_PH(X_LM), /* Logical Maximum (PLACEHOLDER), */ 574 0x47, UCLOGIC_PH(X_PM), /* Physical Maximum (PLACEHOLDER), */ 575 0x81, 0x02, /* Input (Variable), */ 576 0x09, 0x31, /* Usage (Y), */ 577 0x27, UCLOGIC_PH(Y_LM), /* Logical Maximum (PLACEHOLDER), */ 578 0x47, UCLOGIC_PH(Y_PM), /* Physical Maximum (PLACEHOLDER), */ 579 0x81, 0x02, /* Input (Variable), */ 580 0xB4, /* Pop, */ 581 0x09, 0x30, /* Usage (Tip Pressure), */ 582 0x27, 583 UCLOGIC_PH(PRESSURE_LM),/* Logical Maximum (PLACEHOLDER), */ 584 0x81, 0x02, /* Input (Variable), */ 585 0xC0, /* End Collection, */ 586 0xC0 /* End Collection */ 587}; 588 589/* Fixed virtual pad report descriptor */ 590static const __u8 uclogic_buttonpad_rdesc[] = { 591 0x05, 0x01, /* Usage Page (Desktop), */ 592 0x09, 0x07, /* Usage (Keypad), */ 593 0xA1, 0x01, /* Collection (Application), */ 594 0x85, 0xF7, /* Report ID (247), */ 595 0x05, 0x0D, /* Usage Page (Digitizers), */ 596 0x09, 0x39, /* Usage (Tablet Function Keys), */ 597 0xA0, /* Collection (Physical), */ 598 0x05, 0x09, /* Usage Page (Button), */ 599 0x75, 0x01, /* Report Size (1), */ 600 0x95, 0x18, /* Report Count (24), */ 601 0x81, 0x03, /* Input (Constant, Variable), */ 602 0x19, 0x01, /* Usage Minimum (01h), */ 603 0x29, 0x08, /* Usage Maximum (08h), */ 604 0x95, 0x08, /* Report Count (8), */ 605 0x81, 0x02, /* Input (Variable), */ 606 0xC0, /* End Collection */ 607 0xC0 /* End Collection */ 608}; 609 610/* Parameter indices */ 611enum uclogic_prm { 612 UCLOGIC_PRM_X_LM = 1, 613 UCLOGIC_PRM_Y_LM = 2, 614 UCLOGIC_PRM_PRESSURE_LM = 4, 615 UCLOGIC_PRM_RESOLUTION = 5, 616 UCLOGIC_PRM_NUM 617}; 618 619/* Driver data */ 620struct uclogic_drvdata { 621 __u8 *rdesc; 622 unsigned int rsize; 623 bool invert_pen_inrange; 624 bool ignore_pen_usage; 625 bool has_virtual_pad_interface; 626}; 627 628static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, 629 unsigned int *rsize) 630{ 631 struct usb_interface *iface = to_usb_interface(hdev->dev.parent); 632 __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber; 633 struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); 634 635 if (drvdata->rdesc != NULL) { 636 rdesc = drvdata->rdesc; 637 *rsize = drvdata->rsize; 638 return rdesc; 639 } 640 641 switch (hdev->product) { 642 case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209: 643 if (*rsize == PF1209_RDESC_ORIG_SIZE) { 644 rdesc = pf1209_rdesc_fixed; 645 *rsize = sizeof(pf1209_rdesc_fixed); 646 } 647 break; 648 case USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U: 649 if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { 650 rdesc = wp4030u_rdesc_fixed; 651 *rsize = sizeof(wp4030u_rdesc_fixed); 652 } 653 break; 654 case USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U: 655 if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { 656 rdesc = wp5540u_rdesc_fixed; 657 *rsize = sizeof(wp5540u_rdesc_fixed); 658 } 659 break; 660 case USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U: 661 if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { 662 rdesc = wp8060u_rdesc_fixed; 663 *rsize = sizeof(wp8060u_rdesc_fixed); 664 } 665 break; 666 case USB_DEVICE_ID_UCLOGIC_TABLET_WP1062: 667 if (*rsize == WP1062_RDESC_ORIG_SIZE) { 668 rdesc = wp1062_rdesc_fixed; 669 *rsize = sizeof(wp1062_rdesc_fixed); 670 } 671 break; 672 case USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850: 673 switch (iface_num) { 674 case 0: 675 if (*rsize == TWHL850_RDESC_ORIG_SIZE0) { 676 rdesc = twhl850_rdesc_fixed0; 677 *rsize = sizeof(twhl850_rdesc_fixed0); 678 } 679 break; 680 case 1: 681 if (*rsize == TWHL850_RDESC_ORIG_SIZE1) { 682 rdesc = twhl850_rdesc_fixed1; 683 *rsize = sizeof(twhl850_rdesc_fixed1); 684 } 685 break; 686 case 2: 687 if (*rsize == TWHL850_RDESC_ORIG_SIZE2) { 688 rdesc = twhl850_rdesc_fixed2; 689 *rsize = sizeof(twhl850_rdesc_fixed2); 690 } 691 break; 692 } 693 break; 694 case USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60: 695 switch (iface_num) { 696 case 0: 697 if (*rsize == TWHA60_RDESC_ORIG_SIZE0) { 698 rdesc = twha60_rdesc_fixed0; 699 *rsize = sizeof(twha60_rdesc_fixed0); 700 } 701 break; 702 case 1: 703 if (*rsize == TWHA60_RDESC_ORIG_SIZE1) { 704 rdesc = twha60_rdesc_fixed1; 705 *rsize = sizeof(twha60_rdesc_fixed1); 706 } 707 break; 708 } 709 break; 710 } 711 712 return rdesc; 713} 714 715static int uclogic_input_mapping(struct hid_device *hdev, struct hid_input *hi, 716 struct hid_field *field, struct hid_usage *usage, 717 unsigned long **bit, int *max) 718{ 719 struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); 720 721 /* discard the unused pen interface */ 722 if ((drvdata->ignore_pen_usage) && 723 (field->application == HID_DG_PEN)) 724 return -1; 725 726 /* let hid-core decide what to do */ 727 return 0; 728} 729 730static int uclogic_input_configured(struct hid_device *hdev, 731 struct hid_input *hi) 732{ 733 char *name; 734 const char *suffix = NULL; 735 struct hid_field *field; 736 size_t len; 737 738 /* no report associated (HID_QUIRK_MULTI_INPUT not set) */ 739 if (!hi->report) 740 return 0; 741 742 field = hi->report->field[0]; 743 744 switch (field->application) { 745 case HID_GD_KEYBOARD: 746 suffix = "Keyboard"; 747 break; 748 case HID_GD_MOUSE: 749 suffix = "Mouse"; 750 break; 751 case HID_GD_KEYPAD: 752 suffix = "Pad"; 753 break; 754 case HID_DG_PEN: 755 suffix = "Pen"; 756 break; 757 case HID_CP_CONSUMER_CONTROL: 758 suffix = "Consumer Control"; 759 break; 760 case HID_GD_SYSTEM_CONTROL: 761 suffix = "System Control"; 762 break; 763 } 764 765 if (suffix) { 766 len = strlen(hdev->name) + 2 + strlen(suffix); 767 name = devm_kzalloc(&hi->input->dev, len, GFP_KERNEL); 768 if (name) { 769 snprintf(name, len, "%s %s", hdev->name, suffix); 770 hi->input->name = name; 771 } 772 } 773 774 return 0; 775} 776 777/** 778 * Enable fully-functional tablet mode and determine device parameters. 779 * 780 * @hdev: HID device 781 */ 782static int uclogic_tablet_enable(struct hid_device *hdev) 783{ 784 int rc; 785 struct usb_device *usb_dev = hid_to_usb_dev(hdev); 786 struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); 787 __le16 *buf = NULL; 788 size_t len; 789 s32 params[UCLOGIC_PH_ID_NUM]; 790 s32 resolution; 791 __u8 *p; 792 s32 v; 793 794 /* 795 * Read string descriptor containing tablet parameters. The specific 796 * string descriptor and data were discovered by sniffing the Windows 797 * driver traffic. 798 * NOTE: This enables fully-functional tablet mode. 799 */ 800 len = UCLOGIC_PRM_NUM * sizeof(*buf); 801 buf = kmalloc(len, GFP_KERNEL); 802 if (buf == NULL) { 803 rc = -ENOMEM; 804 goto cleanup; 805 } 806 rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), 807 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, 808 (USB_DT_STRING << 8) + 0x64, 809 0x0409, buf, len, 810 USB_CTRL_GET_TIMEOUT); 811 if (rc == -EPIPE) { 812 hid_err(hdev, "device parameters not found\n"); 813 rc = -ENODEV; 814 goto cleanup; 815 } else if (rc < 0) { 816 hid_err(hdev, "failed to get device parameters: %d\n", rc); 817 rc = -ENODEV; 818 goto cleanup; 819 } else if (rc != len) { 820 hid_err(hdev, "invalid device parameters\n"); 821 rc = -ENODEV; 822 goto cleanup; 823 } 824 825 /* Extract device parameters */ 826 params[UCLOGIC_PH_ID_X_LM] = le16_to_cpu(buf[UCLOGIC_PRM_X_LM]); 827 params[UCLOGIC_PH_ID_Y_LM] = le16_to_cpu(buf[UCLOGIC_PRM_Y_LM]); 828 params[UCLOGIC_PH_ID_PRESSURE_LM] = 829 le16_to_cpu(buf[UCLOGIC_PRM_PRESSURE_LM]); 830 resolution = le16_to_cpu(buf[UCLOGIC_PRM_RESOLUTION]); 831 if (resolution == 0) { 832 params[UCLOGIC_PH_ID_X_PM] = 0; 833 params[UCLOGIC_PH_ID_Y_PM] = 0; 834 } else { 835 params[UCLOGIC_PH_ID_X_PM] = params[UCLOGIC_PH_ID_X_LM] * 836 1000 / resolution; 837 params[UCLOGIC_PH_ID_Y_PM] = params[UCLOGIC_PH_ID_Y_LM] * 838 1000 / resolution; 839 } 840 841 /* Allocate fixed report descriptor */ 842 drvdata->rdesc = devm_kzalloc(&hdev->dev, 843 sizeof(uclogic_tablet_rdesc_template), 844 GFP_KERNEL); 845 if (drvdata->rdesc == NULL) { 846 rc = -ENOMEM; 847 goto cleanup; 848 } 849 drvdata->rsize = sizeof(uclogic_tablet_rdesc_template); 850 851 /* Format fixed report descriptor */ 852 memcpy(drvdata->rdesc, uclogic_tablet_rdesc_template, 853 drvdata->rsize); 854 for (p = drvdata->rdesc; 855 p <= drvdata->rdesc + drvdata->rsize - 4;) { 856 if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D && 857 p[3] < ARRAY_SIZE(params)) { 858 v = params[p[3]]; 859 put_unaligned(cpu_to_le32(v), (s32 *)p); 860 p += 4; 861 } else { 862 p++; 863 } 864 } 865 866 rc = 0; 867 868cleanup: 869 kfree(buf); 870 return rc; 871} 872 873/** 874 * Enable actual button mode. 875 * 876 * @hdev: HID device 877 */ 878static int uclogic_button_enable(struct hid_device *hdev) 879{ 880 int rc; 881 struct usb_device *usb_dev = hid_to_usb_dev(hdev); 882 struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); 883 char *str_buf; 884 size_t str_len = 16; 885 unsigned char *rdesc; 886 size_t rdesc_len; 887 888 str_buf = kzalloc(str_len, GFP_KERNEL); 889 if (str_buf == NULL) { 890 rc = -ENOMEM; 891 goto cleanup; 892 } 893 894 /* Enable abstract keyboard mode */ 895 rc = usb_string(usb_dev, 0x7b, str_buf, str_len); 896 if (rc == -EPIPE) { 897 hid_info(hdev, "button mode setting not found\n"); 898 rc = 0; 899 goto cleanup; 900 } else if (rc < 0) { 901 hid_err(hdev, "failed to enable abstract keyboard\n"); 902 goto cleanup; 903 } else if (strncmp(str_buf, "HK On", rc)) { 904 hid_info(hdev, "invalid answer when requesting buttons: '%s'\n", 905 str_buf); 906 rc = -EINVAL; 907 goto cleanup; 908 } 909 910 /* Re-allocate fixed report descriptor */ 911 rdesc_len = drvdata->rsize + sizeof(uclogic_buttonpad_rdesc); 912 rdesc = devm_kzalloc(&hdev->dev, rdesc_len, GFP_KERNEL); 913 if (!rdesc) { 914 rc = -ENOMEM; 915 goto cleanup; 916 } 917 918 memcpy(rdesc, drvdata->rdesc, drvdata->rsize); 919 920 /* Append the buttonpad descriptor */ 921 memcpy(rdesc + drvdata->rsize, uclogic_buttonpad_rdesc, 922 sizeof(uclogic_buttonpad_rdesc)); 923 924 /* clean up old rdesc and use the new one */ 925 drvdata->rsize = rdesc_len; 926 devm_kfree(&hdev->dev, drvdata->rdesc); 927 drvdata->rdesc = rdesc; 928 929 rc = 0; 930 931cleanup: 932 kfree(str_buf); 933 return rc; 934} 935 936static int uclogic_probe(struct hid_device *hdev, 937 const struct hid_device_id *id) 938{ 939 int rc; 940 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 941 struct usb_device *udev = hid_to_usb_dev(hdev); 942 struct uclogic_drvdata *drvdata; 943 944 /* 945 * libinput requires the pad interface to be on a different node 946 * than the pen, so use QUIRK_MULTI_INPUT for all tablets. 947 */ 948 hdev->quirks |= HID_QUIRK_MULTI_INPUT; 949 950 /* Allocate and assign driver data */ 951 drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL); 952 if (drvdata == NULL) 953 return -ENOMEM; 954 955 hid_set_drvdata(hdev, drvdata); 956 957 switch (id->product) { 958 case USB_DEVICE_ID_HUION_TABLET: 959 case USB_DEVICE_ID_YIYNOVA_TABLET: 960 case USB_DEVICE_ID_UGEE_TABLET_81: 961 case USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3: 962 case USB_DEVICE_ID_UGEE_TABLET_45: 963 /* If this is the pen interface */ 964 if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { 965 rc = uclogic_tablet_enable(hdev); 966 if (rc) { 967 hid_err(hdev, "tablet enabling failed\n"); 968 return rc; 969 } 970 drvdata->invert_pen_inrange = true; 971 972 rc = uclogic_button_enable(hdev); 973 drvdata->has_virtual_pad_interface = !rc; 974 } else { 975 drvdata->ignore_pen_usage = true; 976 } 977 break; 978 case USB_DEVICE_ID_UGTIZER_TABLET_GP0610: 979 case USB_DEVICE_ID_UGEE_TABLET_EX07S: 980 /* If this is the pen interface */ 981 if (intf->cur_altsetting->desc.bInterfaceNumber == 1) { 982 rc = uclogic_tablet_enable(hdev); 983 if (rc) { 984 hid_err(hdev, "tablet enabling failed\n"); 985 return rc; 986 } 987 drvdata->invert_pen_inrange = true; 988 } else { 989 drvdata->ignore_pen_usage = true; 990 } 991 break; 992 case USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60: 993 /* 994 * If it is the three-interface version, which is known to 995 * respond to initialization. 996 */ 997 if (udev->config->desc.bNumInterfaces == 3) { 998 /* If it is the pen interface */ 999 if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { 1000 rc = uclogic_tablet_enable(hdev); 1001 if (rc) { 1002 hid_err(hdev, "tablet enabling failed\n"); 1003 return rc; 1004 } 1005 drvdata->invert_pen_inrange = true; 1006 1007 rc = uclogic_button_enable(hdev); 1008 drvdata->has_virtual_pad_interface = !rc; 1009 } else { 1010 drvdata->ignore_pen_usage = true; 1011 } 1012 } 1013 break; 1014 } 1015 1016 rc = hid_parse(hdev); 1017 if (rc) { 1018 hid_err(hdev, "parse failed\n"); 1019 return rc; 1020 } 1021 1022 rc = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 1023 if (rc) { 1024 hid_err(hdev, "hw start failed\n"); 1025 return rc; 1026 } 1027 1028 return 0; 1029} 1030 1031static int uclogic_raw_event(struct hid_device *hdev, struct hid_report *report, 1032 u8 *data, int size) 1033{ 1034 struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); 1035 1036 if ((report->type == HID_INPUT_REPORT) && 1037 (report->id == UCLOGIC_PEN_REPORT_ID) && 1038 (size >= 2)) { 1039 if (drvdata->has_virtual_pad_interface && (data[1] & 0x20)) 1040 /* Change to virtual frame button report ID */ 1041 data[0] = 0xf7; 1042 else if (drvdata->invert_pen_inrange) 1043 /* Invert the in-range bit */ 1044 data[1] ^= 0x40; 1045 } 1046 1047 return 0; 1048} 1049 1050static const struct hid_device_id uclogic_devices[] = { 1051 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, 1052 USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, 1053 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, 1054 USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, 1055 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, 1056 USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, 1057 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, 1058 USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, 1059 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, 1060 USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, 1061 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, 1062 USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) }, 1063 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, 1064 USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) }, 1065 { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) }, 1066 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET) }, 1067 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_YIYNOVA_TABLET) }, 1068 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_81) }, 1069 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_45) }, 1070 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) }, 1071 { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) }, 1072 { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_TABLET_EX07S) }, 1073 { } 1074}; 1075MODULE_DEVICE_TABLE(hid, uclogic_devices); 1076 1077static struct hid_driver uclogic_driver = { 1078 .name = "uclogic", 1079 .id_table = uclogic_devices, 1080 .probe = uclogic_probe, 1081 .report_fixup = uclogic_report_fixup, 1082 .raw_event = uclogic_raw_event, 1083 .input_mapping = uclogic_input_mapping, 1084 .input_configured = uclogic_input_configured, 1085}; 1086module_hid_driver(uclogic_driver); 1087 1088MODULE_AUTHOR("Martin Rusko"); 1089MODULE_AUTHOR("Nikolai Kondrashov"); 1090MODULE_LICENSE("GPL");