1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * HID driver for UC-Logic devices not fully compliant with HID standard 4 * - tablet initialization and parameter retrieval 5 * 6 * Copyright (c) 2018 Nikolai Kondrashov 7 */ 8 9 /* 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by the Free 12 * Software Foundation; either version 2 of the License, or (at your option) 13 * any later version. 14 */ 15 16 #include "hid-uclogic-params.h" 17 #include "hid-uclogic-rdesc.h" 18 #include "usbhid/usbhid.h" 19 #include "hid-ids.h" 20 #include <linux/ctype.h> 21 #include <asm/unaligned.h> 22 23 /** 24 * uclogic_params_pen_inrange_to_str() - Convert a pen in-range reporting type 25 * to a string. 26 * 27 * @inrange: The in-range reporting type to convert. 28 * 29 * Returns: 30 * The string representing the type, or NULL if the type is unknown. 31 */ 32 const char *uclogic_params_pen_inrange_to_str( 33 enum uclogic_params_pen_inrange inrange) 34 { 35 switch (inrange) { 36 case UCLOGIC_PARAMS_PEN_INRANGE_NORMAL: 37 return "normal"; 38 case UCLOGIC_PARAMS_PEN_INRANGE_INVERTED: 39 return "inverted"; 40 case UCLOGIC_PARAMS_PEN_INRANGE_NONE: 41 return "none"; 42 default: 43 return NULL; 44 } 45 } 46 47 /** 48 * uclogic_params_get_str_desc - retrieve a string descriptor from a HID 49 * device interface, putting it into a kmalloc-allocated buffer as is, without 50 * character encoding conversion. 51 * 52 * @pbuf: Location for the kmalloc-allocated buffer pointer containing 53 * the retrieved descriptor. Not modified in case of error. 54 * Can be NULL to have retrieved descriptor discarded. 55 * @hdev: The HID device of the tablet interface to retrieve the string 56 * descriptor from. Cannot be NULL. 57 * @idx: Index of the string descriptor to request from the device. 58 * @len: Length of the buffer to allocate and the data to retrieve. 59 * 60 * Returns: 61 * number of bytes retrieved (<= len), 62 * -EPIPE, if the descriptor was not found, or 63 * another negative errno code in case of other error. 64 */ 65 static int uclogic_params_get_str_desc(__u8 **pbuf, struct hid_device *hdev, 66 __u8 idx, size_t len) 67 { 68 int rc; 69 struct usb_device *udev = hid_to_usb_dev(hdev); 70 __u8 *buf = NULL; 71 72 /* Check arguments */ 73 if (hdev == NULL) { 74 rc = -EINVAL; 75 goto cleanup; 76 } 77 78 buf = kmalloc(len, GFP_KERNEL); 79 if (buf == NULL) { 80 rc = -ENOMEM; 81 goto cleanup; 82 } 83 84 rc = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 85 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, 86 (USB_DT_STRING << 8) + idx, 87 0x0409, buf, len, 88 USB_CTRL_GET_TIMEOUT); 89 if (rc == -EPIPE) { 90 hid_dbg(hdev, "string descriptor #%hhu not found\n", idx); 91 goto cleanup; 92 } else if (rc < 0) { 93 hid_err(hdev, 94 "failed retrieving string descriptor #%u: %d\n", 95 idx, rc); 96 goto cleanup; 97 } 98 99 if (pbuf != NULL) { 100 *pbuf = buf; 101 buf = NULL; 102 } 103 104 cleanup: 105 kfree(buf); 106 return rc; 107 } 108 109 /** 110 * uclogic_params_pen_cleanup - free resources used by struct 111 * uclogic_params_pen (tablet interface's pen input parameters). 112 * Can be called repeatedly. 113 * 114 * @pen: Pen input parameters to cleanup. Cannot be NULL. 115 */ 116 static void uclogic_params_pen_cleanup(struct uclogic_params_pen *pen) 117 { 118 kfree(pen->desc_ptr); 119 memset(pen, 0, sizeof(*pen)); 120 } 121 122 /** 123 * uclogic_params_pen_init_v1() - initialize tablet interface pen 124 * input and retrieve its parameters from the device, using v1 protocol. 125 * 126 * @pen: Pointer to the pen parameters to initialize (to be 127 * cleaned up with uclogic_params_pen_cleanup()). Not modified in 128 * case of error, or if parameters are not found. Cannot be NULL. 129 * @pfound: Location for a flag which is set to true if the parameters 130 * were found, and to false if not (e.g. device was 131 * incompatible). Not modified in case of error. Cannot be NULL. 132 * @hdev: The HID device of the tablet interface to initialize and get 133 * parameters from. Cannot be NULL. 134 * 135 * Returns: 136 * Zero, if successful. A negative errno code on error. 137 */ 138 static int uclogic_params_pen_init_v1(struct uclogic_params_pen *pen, 139 bool *pfound, 140 struct hid_device *hdev) 141 { 142 int rc; 143 bool found = false; 144 /* Buffer for (part of) the string descriptor */ 145 __u8 *buf = NULL; 146 /* Minimum descriptor length required, maximum seen so far is 18 */ 147 const int len = 12; 148 s32 resolution; 149 /* Pen report descriptor template parameters */ 150 s32 desc_params[UCLOGIC_RDESC_PEN_PH_ID_NUM]; 151 __u8 *desc_ptr = NULL; 152 153 /* Check arguments */ 154 if (pen == NULL || pfound == NULL || hdev == NULL) { 155 rc = -EINVAL; 156 goto cleanup; 157 } 158 159 /* 160 * Read string descriptor containing pen input parameters. 161 * The specific string descriptor and data were discovered by sniffing 162 * the Windows driver traffic. 163 * NOTE: This enables fully-functional tablet mode. 164 */ 165 rc = uclogic_params_get_str_desc(&buf, hdev, 100, len); 166 if (rc == -EPIPE) { 167 hid_dbg(hdev, 168 "string descriptor with pen parameters not found, assuming not compatible\n"); 169 goto finish; 170 } else if (rc < 0) { 171 hid_err(hdev, "failed retrieving pen parameters: %d\n", rc); 172 goto cleanup; 173 } else if (rc != len) { 174 hid_dbg(hdev, 175 "string descriptor with pen parameters has invalid length (got %d, expected %d), assuming not compatible\n", 176 rc, len); 177 goto finish; 178 } 179 180 /* 181 * Fill report descriptor parameters from the string descriptor 182 */ 183 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 184 get_unaligned_le16(buf + 2); 185 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 186 get_unaligned_le16(buf + 4); 187 desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 188 get_unaligned_le16(buf + 8); 189 resolution = get_unaligned_le16(buf + 10); 190 if (resolution == 0) { 191 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0; 192 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0; 193 } else { 194 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 195 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 / 196 resolution; 197 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 198 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 / 199 resolution; 200 } 201 kfree(buf); 202 buf = NULL; 203 204 /* 205 * Generate pen report descriptor 206 */ 207 desc_ptr = uclogic_rdesc_template_apply( 208 uclogic_rdesc_pen_v1_template_arr, 209 uclogic_rdesc_pen_v1_template_size, 210 desc_params, ARRAY_SIZE(desc_params)); 211 if (desc_ptr == NULL) { 212 rc = -ENOMEM; 213 goto cleanup; 214 } 215 216 /* 217 * Fill-in the parameters 218 */ 219 memset(pen, 0, sizeof(*pen)); 220 pen->desc_ptr = desc_ptr; 221 desc_ptr = NULL; 222 pen->desc_size = uclogic_rdesc_pen_v1_template_size; 223 pen->id = UCLOGIC_RDESC_PEN_V1_ID; 224 pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_INVERTED; 225 found = true; 226 finish: 227 *pfound = found; 228 rc = 0; 229 cleanup: 230 kfree(desc_ptr); 231 kfree(buf); 232 return rc; 233 } 234 235 /** 236 * uclogic_params_get_le24() - get a 24-bit little-endian number from a 237 * buffer. 238 * 239 * @p: The pointer to the number buffer. 240 * 241 * Returns: 242 * The retrieved number 243 */ 244 static s32 uclogic_params_get_le24(const void *p) 245 { 246 const __u8 *b = p; 247 return b[0] | (b[1] << 8UL) | (b[2] << 16UL); 248 } 249 250 /** 251 * uclogic_params_pen_init_v2() - initialize tablet interface pen 252 * input and retrieve its parameters from the device, using v2 protocol. 253 * 254 * @pen: Pointer to the pen parameters to initialize (to be 255 * cleaned up with uclogic_params_pen_cleanup()). Not modified in 256 * case of error, or if parameters are not found. Cannot be NULL. 257 * @pfound: Location for a flag which is set to true if the parameters 258 * were found, and to false if not (e.g. device was 259 * incompatible). Not modified in case of error. Cannot be NULL. 260 * @hdev: The HID device of the tablet interface to initialize and get 261 * parameters from. Cannot be NULL. 262 * 263 * Returns: 264 * Zero, if successful. A negative errno code on error. 265 */ 266 static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen, 267 bool *pfound, 268 struct hid_device *hdev) 269 { 270 int rc; 271 bool found = false; 272 /* Buffer for (part of) the string descriptor */ 273 __u8 *buf = NULL; 274 /* Descriptor length required */ 275 const int len = 18; 276 s32 resolution; 277 /* Pen report descriptor template parameters */ 278 s32 desc_params[UCLOGIC_RDESC_PEN_PH_ID_NUM]; 279 __u8 *desc_ptr = NULL; 280 281 /* Check arguments */ 282 if (pen == NULL || pfound == NULL || hdev == NULL) { 283 rc = -EINVAL; 284 goto cleanup; 285 } 286 287 /* 288 * Read string descriptor containing pen input parameters. 289 * The specific string descriptor and data were discovered by sniffing 290 * the Windows driver traffic. 291 * NOTE: This enables fully-functional tablet mode. 292 */ 293 rc = uclogic_params_get_str_desc(&buf, hdev, 200, len); 294 if (rc == -EPIPE) { 295 hid_dbg(hdev, 296 "string descriptor with pen parameters not found, assuming not compatible\n"); 297 goto finish; 298 } else if (rc < 0) { 299 hid_err(hdev, "failed retrieving pen parameters: %d\n", rc); 300 goto cleanup; 301 } else if (rc != len) { 302 hid_dbg(hdev, 303 "string descriptor with pen parameters has invalid length (got %d, expected %d), assuming not compatible\n", 304 rc, len); 305 goto finish; 306 } else { 307 size_t i; 308 /* 309 * Check it's not just a catch-all UTF-16LE-encoded ASCII 310 * string (such as the model name) some tablets put into all 311 * unknown string descriptors. 312 */ 313 for (i = 2; 314 i < len && 315 (buf[i] >= 0x20 && buf[i] < 0x7f && buf[i + 1] == 0); 316 i += 2); 317 if (i >= len) { 318 hid_dbg(hdev, 319 "string descriptor with pen parameters seems to contain only text, assuming not compatible\n"); 320 goto finish; 321 } 322 } 323 324 /* 325 * Fill report descriptor parameters from the string descriptor 326 */ 327 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 328 uclogic_params_get_le24(buf + 2); 329 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 330 uclogic_params_get_le24(buf + 5); 331 desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 332 get_unaligned_le16(buf + 8); 333 resolution = get_unaligned_le16(buf + 10); 334 if (resolution == 0) { 335 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0; 336 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0; 337 } else { 338 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 339 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 / 340 resolution; 341 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 342 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 / 343 resolution; 344 } 345 kfree(buf); 346 buf = NULL; 347 348 /* 349 * Generate pen report descriptor 350 */ 351 desc_ptr = uclogic_rdesc_template_apply( 352 uclogic_rdesc_pen_v2_template_arr, 353 uclogic_rdesc_pen_v2_template_size, 354 desc_params, ARRAY_SIZE(desc_params)); 355 if (desc_ptr == NULL) { 356 rc = -ENOMEM; 357 goto cleanup; 358 } 359 360 /* 361 * Fill-in the parameters 362 */ 363 memset(pen, 0, sizeof(*pen)); 364 pen->desc_ptr = desc_ptr; 365 desc_ptr = NULL; 366 pen->desc_size = uclogic_rdesc_pen_v2_template_size; 367 pen->id = UCLOGIC_RDESC_PEN_V2_ID; 368 pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_NONE; 369 pen->fragmented_hires = true; 370 found = true; 371 finish: 372 *pfound = found; 373 rc = 0; 374 cleanup: 375 kfree(desc_ptr); 376 kfree(buf); 377 return rc; 378 } 379 380 /** 381 * uclogic_params_frame_cleanup - free resources used by struct 382 * uclogic_params_frame (tablet interface's frame controls input parameters). 383 * Can be called repeatedly. 384 * 385 * @frame: Frame controls input parameters to cleanup. Cannot be NULL. 386 */ 387 static void uclogic_params_frame_cleanup(struct uclogic_params_frame *frame) 388 { 389 kfree(frame->desc_ptr); 390 memset(frame, 0, sizeof(*frame)); 391 } 392 393 /** 394 * uclogic_params_frame_init_with_desc() - initialize tablet's frame control 395 * parameters with a static report descriptor. 396 * 397 * @frame: Pointer to the frame parameters to initialize (to be cleaned 398 * up with uclogic_params_frame_cleanup()). Not modified in case 399 * of error. Cannot be NULL. 400 * @desc_ptr: Report descriptor pointer. Can be NULL, if desc_size is zero. 401 * @desc_size: Report descriptor size. 402 * @id: Report ID used for frame reports, if they should be tweaked, 403 * zero if not. 404 * 405 * Returns: 406 * Zero, if successful. A negative errno code on error. 407 */ 408 static int uclogic_params_frame_init_with_desc( 409 struct uclogic_params_frame *frame, 410 const __u8 *desc_ptr, 411 size_t desc_size, 412 unsigned int id) 413 { 414 __u8 *copy_desc_ptr; 415 416 if (frame == NULL || (desc_ptr == NULL && desc_size != 0)) 417 return -EINVAL; 418 419 copy_desc_ptr = kmemdup(desc_ptr, desc_size, GFP_KERNEL); 420 if (copy_desc_ptr == NULL) 421 return -ENOMEM; 422 423 memset(frame, 0, sizeof(*frame)); 424 frame->desc_ptr = copy_desc_ptr; 425 frame->desc_size = desc_size; 426 frame->id = id; 427 return 0; 428 } 429 430 /** 431 * uclogic_params_frame_init_v1_buttonpad() - initialize abstract buttonpad 432 * on a v1 tablet interface. 433 * 434 * @frame: Pointer to the frame parameters to initialize (to be cleaned 435 * up with uclogic_params_frame_cleanup()). Not modified in case 436 * of error, or if parameters are not found. Cannot be NULL. 437 * @pfound: Location for a flag which is set to true if the parameters 438 * were found, and to false if not (e.g. device was 439 * incompatible). Not modified in case of error. Cannot be NULL. 440 * @hdev: The HID device of the tablet interface to initialize and get 441 * parameters from. Cannot be NULL. 442 * 443 * Returns: 444 * Zero, if successful. A negative errno code on error. 445 */ 446 static int uclogic_params_frame_init_v1_buttonpad( 447 struct uclogic_params_frame *frame, 448 bool *pfound, 449 struct hid_device *hdev) 450 { 451 int rc; 452 bool found = false; 453 struct usb_device *usb_dev = hid_to_usb_dev(hdev); 454 char *str_buf = NULL; 455 const size_t str_len = 16; 456 457 /* Check arguments */ 458 if (frame == NULL || pfound == NULL || hdev == NULL) { 459 rc = -EINVAL; 460 goto cleanup; 461 } 462 463 /* 464 * Enable generic button mode 465 */ 466 str_buf = kzalloc(str_len, GFP_KERNEL); 467 if (str_buf == NULL) { 468 rc = -ENOMEM; 469 goto cleanup; 470 } 471 472 rc = usb_string(usb_dev, 123, str_buf, str_len); 473 if (rc == -EPIPE) { 474 hid_dbg(hdev, 475 "generic button -enabling string descriptor not found\n"); 476 } else if (rc < 0) { 477 goto cleanup; 478 } else if (strncmp(str_buf, "HK On", rc) != 0) { 479 hid_dbg(hdev, 480 "invalid response to enabling generic buttons: \"%s\"\n", 481 str_buf); 482 } else { 483 hid_dbg(hdev, "generic buttons enabled\n"); 484 rc = uclogic_params_frame_init_with_desc( 485 frame, 486 uclogic_rdesc_buttonpad_v1_arr, 487 uclogic_rdesc_buttonpad_v1_size, 488 UCLOGIC_RDESC_BUTTONPAD_V1_ID); 489 if (rc != 0) 490 goto cleanup; 491 found = true; 492 } 493 494 *pfound = found; 495 rc = 0; 496 cleanup: 497 kfree(str_buf); 498 return rc; 499 } 500 501 /** 502 * uclogic_params_cleanup - free resources used by struct uclogic_params 503 * (tablet interface's parameters). 504 * Can be called repeatedly. 505 * 506 * @params: Input parameters to cleanup. Cannot be NULL. 507 */ 508 void uclogic_params_cleanup(struct uclogic_params *params) 509 { 510 if (!params->invalid) { 511 kfree(params->desc_ptr); 512 if (!params->pen_unused) 513 uclogic_params_pen_cleanup(¶ms->pen); 514 uclogic_params_frame_cleanup(¶ms->frame); 515 memset(params, 0, sizeof(*params)); 516 } 517 } 518 519 /** 520 * uclogic_params_get_desc() - Get a replacement report descriptor for a 521 * tablet's interface. 522 * 523 * @params: The parameters of a tablet interface to get report 524 * descriptor for. Cannot be NULL. 525 * @pdesc: Location for the resulting, kmalloc-allocated report 526 * descriptor pointer, or for NULL, if there's no replacement 527 * report descriptor. Not modified in case of error. Cannot be 528 * NULL. 529 * @psize: Location for the resulting report descriptor size, not set if 530 * there's no replacement report descriptor. Not modified in case 531 * of error. Cannot be NULL. 532 * 533 * Returns: 534 * Zero, if successful. 535 * -EINVAL, if invalid arguments are supplied. 536 * -ENOMEM, if failed to allocate memory. 537 */ 538 int uclogic_params_get_desc(const struct uclogic_params *params, 539 __u8 **pdesc, 540 unsigned int *psize) 541 { 542 bool common_present; 543 bool pen_present; 544 bool frame_present; 545 unsigned int size; 546 __u8 *desc = NULL; 547 548 /* Check arguments */ 549 if (params == NULL || pdesc == NULL || psize == NULL) 550 return -EINVAL; 551 552 size = 0; 553 554 common_present = (params->desc_ptr != NULL); 555 pen_present = (!params->pen_unused && params->pen.desc_ptr != NULL); 556 frame_present = (params->frame.desc_ptr != NULL); 557 558 if (common_present) 559 size += params->desc_size; 560 if (pen_present) 561 size += params->pen.desc_size; 562 if (frame_present) 563 size += params->frame.desc_size; 564 565 if (common_present || pen_present || frame_present) { 566 __u8 *p; 567 568 desc = kmalloc(size, GFP_KERNEL); 569 if (desc == NULL) 570 return -ENOMEM; 571 p = desc; 572 573 if (common_present) { 574 memcpy(p, params->desc_ptr, 575 params->desc_size); 576 p += params->desc_size; 577 } 578 if (pen_present) { 579 memcpy(p, params->pen.desc_ptr, 580 params->pen.desc_size); 581 p += params->pen.desc_size; 582 } 583 if (frame_present) { 584 memcpy(p, params->frame.desc_ptr, 585 params->frame.desc_size); 586 p += params->frame.desc_size; 587 } 588 589 WARN_ON(p != desc + size); 590 591 *psize = size; 592 } 593 594 *pdesc = desc; 595 return 0; 596 } 597 598 /** 599 * uclogic_params_init_invalid() - initialize tablet interface parameters, 600 * specifying the interface is invalid. 601 * 602 * @params: Parameters to initialize (to be cleaned with 603 * uclogic_params_cleanup()). Cannot be NULL. 604 */ 605 static void uclogic_params_init_invalid(struct uclogic_params *params) 606 { 607 params->invalid = true; 608 } 609 610 /** 611 * uclogic_params_init_with_opt_desc() - initialize tablet interface 612 * parameters with an optional replacement report descriptor. Only modify 613 * report descriptor, if the original report descriptor matches the expected 614 * size. 615 * 616 * @params: Parameters to initialize (to be cleaned with 617 * uclogic_params_cleanup()). Not modified in case of 618 * error. Cannot be NULL. 619 * @hdev: The HID device of the tablet interface create the 620 * parameters for. Cannot be NULL. 621 * @orig_desc_size: Expected size of the original report descriptor to 622 * be replaced. 623 * @desc_ptr: Pointer to the replacement report descriptor. 624 * Can be NULL, if desc_size is zero. 625 * @desc_size: Size of the replacement report descriptor. 626 * 627 * Returns: 628 * Zero, if successful. -EINVAL if an invalid argument was passed. 629 * -ENOMEM, if failed to allocate memory. 630 */ 631 static int uclogic_params_init_with_opt_desc(struct uclogic_params *params, 632 struct hid_device *hdev, 633 unsigned int orig_desc_size, 634 __u8 *desc_ptr, 635 unsigned int desc_size) 636 { 637 __u8 *desc_copy_ptr = NULL; 638 unsigned int desc_copy_size; 639 int rc; 640 641 /* Check arguments */ 642 if (params == NULL || hdev == NULL || 643 (desc_ptr == NULL && desc_size != 0)) { 644 rc = -EINVAL; 645 goto cleanup; 646 } 647 648 /* Replace report descriptor, if it matches */ 649 if (hdev->dev_rsize == orig_desc_size) { 650 hid_dbg(hdev, 651 "device report descriptor matches the expected size, replacing\n"); 652 desc_copy_ptr = kmemdup(desc_ptr, desc_size, GFP_KERNEL); 653 if (desc_copy_ptr == NULL) { 654 rc = -ENOMEM; 655 goto cleanup; 656 } 657 desc_copy_size = desc_size; 658 } else { 659 hid_dbg(hdev, 660 "device report descriptor doesn't match the expected size (%u != %u), preserving\n", 661 hdev->dev_rsize, orig_desc_size); 662 desc_copy_ptr = NULL; 663 desc_copy_size = 0; 664 } 665 666 /* Output parameters */ 667 memset(params, 0, sizeof(*params)); 668 params->desc_ptr = desc_copy_ptr; 669 desc_copy_ptr = NULL; 670 params->desc_size = desc_copy_size; 671 672 rc = 0; 673 cleanup: 674 kfree(desc_copy_ptr); 675 return rc; 676 } 677 678 /** 679 * uclogic_params_init_with_pen_unused() - initialize tablet interface 680 * parameters preserving original reports and generic HID processing, but 681 * disabling pen usage. 682 * 683 * @params: Parameters to initialize (to be cleaned with 684 * uclogic_params_cleanup()). Not modified in case of 685 * error. Cannot be NULL. 686 */ 687 static void uclogic_params_init_with_pen_unused(struct uclogic_params *params) 688 { 689 memset(params, 0, sizeof(*params)); 690 params->pen_unused = true; 691 } 692 693 /** 694 * uclogic_params_huion_init() - initialize a Huion tablet interface and discover 695 * its parameters. 696 * 697 * @params: Parameters to fill in (to be cleaned with 698 * uclogic_params_cleanup()). Not modified in case of error. 699 * Cannot be NULL. 700 * @hdev: The HID device of the tablet interface to initialize and get 701 * parameters from. Cannot be NULL. 702 * 703 * Returns: 704 * Zero, if successful. A negative errno code on error. 705 */ 706 static int uclogic_params_huion_init(struct uclogic_params *params, 707 struct hid_device *hdev) 708 { 709 int rc; 710 struct usb_device *udev = hid_to_usb_dev(hdev); 711 struct usb_interface *iface = to_usb_interface(hdev->dev.parent); 712 __u8 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; 713 bool found; 714 /* The resulting parameters (noop) */ 715 struct uclogic_params p = {0, }; 716 static const char transition_ver[] = "HUION_T153_160607"; 717 char *ver_ptr = NULL; 718 const size_t ver_len = sizeof(transition_ver) + 1; 719 720 /* Check arguments */ 721 if (params == NULL || hdev == NULL) { 722 rc = -EINVAL; 723 goto cleanup; 724 } 725 726 /* If it's not a pen interface */ 727 if (bInterfaceNumber != 0) { 728 /* TODO: Consider marking the interface invalid */ 729 uclogic_params_init_with_pen_unused(&p); 730 goto output; 731 } 732 733 /* Try to get firmware version */ 734 ver_ptr = kzalloc(ver_len, GFP_KERNEL); 735 if (ver_ptr == NULL) { 736 rc = -ENOMEM; 737 goto cleanup; 738 } 739 rc = usb_string(udev, 201, ver_ptr, ver_len); 740 if (rc == -EPIPE) { 741 *ver_ptr = '\0'; 742 } else if (rc < 0) { 743 hid_err(hdev, 744 "failed retrieving Huion firmware version: %d\n", rc); 745 goto cleanup; 746 } 747 748 /* If this is a transition firmware */ 749 if (strcmp(ver_ptr, transition_ver) == 0) { 750 hid_dbg(hdev, 751 "transition firmware detected, not probing pen v2 parameters\n"); 752 } else { 753 /* Try to probe v2 pen parameters */ 754 rc = uclogic_params_pen_init_v2(&p.pen, &found, hdev); 755 if (rc != 0) { 756 hid_err(hdev, 757 "failed probing pen v2 parameters: %d\n", rc); 758 goto cleanup; 759 } else if (found) { 760 hid_dbg(hdev, "pen v2 parameters found\n"); 761 /* Create v2 buttonpad parameters */ 762 rc = uclogic_params_frame_init_with_desc( 763 &p.frame, 764 uclogic_rdesc_buttonpad_v2_arr, 765 uclogic_rdesc_buttonpad_v2_size, 766 UCLOGIC_RDESC_BUTTONPAD_V2_ID); 767 if (rc != 0) { 768 hid_err(hdev, 769 "failed creating v2 buttonpad parameters: %d\n", 770 rc); 771 goto cleanup; 772 } 773 /* Set bitmask marking frame reports in pen reports */ 774 p.pen_frame_flag = 0x20; 775 goto output; 776 } 777 hid_dbg(hdev, "pen v2 parameters not found\n"); 778 } 779 780 /* Try to probe v1 pen parameters */ 781 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 782 if (rc != 0) { 783 hid_err(hdev, 784 "failed probing pen v1 parameters: %d\n", rc); 785 goto cleanup; 786 } else if (found) { 787 hid_dbg(hdev, "pen v1 parameters found\n"); 788 /* Try to probe v1 buttonpad */ 789 rc = uclogic_params_frame_init_v1_buttonpad( 790 &p.frame, 791 &found, hdev); 792 if (rc != 0) { 793 hid_err(hdev, "v1 buttonpad probing failed: %d\n", rc); 794 goto cleanup; 795 } 796 hid_dbg(hdev, "buttonpad v1 parameters%s found\n", 797 (found ? "" : " not")); 798 if (found) { 799 /* Set bitmask marking frame reports */ 800 p.pen_frame_flag = 0x20; 801 } 802 goto output; 803 } 804 hid_dbg(hdev, "pen v1 parameters not found\n"); 805 806 uclogic_params_init_invalid(&p); 807 808 output: 809 /* Output parameters */ 810 memcpy(params, &p, sizeof(*params)); 811 memset(&p, 0, sizeof(p)); 812 rc = 0; 813 cleanup: 814 kfree(ver_ptr); 815 uclogic_params_cleanup(&p); 816 return rc; 817 } 818 819 /** 820 * uclogic_params_init() - initialize a tablet interface and discover its 821 * parameters. 822 * 823 * @params: Parameters to fill in (to be cleaned with 824 * uclogic_params_cleanup()). Not modified in case of error. 825 * Cannot be NULL. 826 * @hdev: The HID device of the tablet interface to initialize and get 827 * parameters from. Cannot be NULL. Must be using the USB low-level 828 * driver, i.e. be an actual USB tablet. 829 * 830 * Returns: 831 * Zero, if successful. A negative errno code on error. 832 */ 833 int uclogic_params_init(struct uclogic_params *params, 834 struct hid_device *hdev) 835 { 836 int rc; 837 struct usb_device *udev = hid_to_usb_dev(hdev); 838 __u8 bNumInterfaces = udev->config->desc.bNumInterfaces; 839 struct usb_interface *iface = to_usb_interface(hdev->dev.parent); 840 __u8 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; 841 bool found; 842 /* The resulting parameters (noop) */ 843 struct uclogic_params p = {0, }; 844 845 /* Check arguments */ 846 if (params == NULL || hdev == NULL || 847 !hid_is_using_ll_driver(hdev, &usb_hid_driver)) { 848 rc = -EINVAL; 849 goto cleanup; 850 } 851 852 /* 853 * Set replacement report descriptor if the original matches the 854 * specified size. Otherwise keep interface unchanged. 855 */ 856 #define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \ 857 uclogic_params_init_with_opt_desc( \ 858 &p, hdev, \ 859 UCLOGIC_RDESC_##_orig_desc_token##_SIZE, \ 860 uclogic_rdesc_##_new_desc_token##_arr, \ 861 uclogic_rdesc_##_new_desc_token##_size) 862 863 #define VID_PID(_vid, _pid) \ 864 (((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX)) 865 866 /* 867 * Handle specific interfaces for specific tablets. 868 * 869 * Observe the following logic: 870 * 871 * If the interface is recognized as producing certain useful input: 872 * Mark interface as valid. 873 * Output interface parameters. 874 * Else, if the interface is recognized as *not* producing any useful 875 * input: 876 * Mark interface as invalid. 877 * Else: 878 * Mark interface as valid. 879 * Output noop parameters. 880 * 881 * Rule of thumb: it is better to disable a broken interface than let 882 * it spew garbage input. 883 */ 884 885 switch (VID_PID(hdev->vendor, hdev->product)) { 886 case VID_PID(USB_VENDOR_ID_UCLOGIC, 887 USB_DEVICE_ID_UCLOGIC_TABLET_PF1209): 888 rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed); 889 if (rc != 0) 890 goto cleanup; 891 break; 892 case VID_PID(USB_VENDOR_ID_UCLOGIC, 893 USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U): 894 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed); 895 if (rc != 0) 896 goto cleanup; 897 break; 898 case VID_PID(USB_VENDOR_ID_UCLOGIC, 899 USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U): 900 if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) { 901 if (bInterfaceNumber == 0) { 902 /* Try to probe v1 pen parameters */ 903 rc = uclogic_params_pen_init_v1(&p.pen, 904 &found, hdev); 905 if (rc != 0) { 906 hid_err(hdev, 907 "pen probing failed: %d\n", 908 rc); 909 goto cleanup; 910 } 911 if (!found) { 912 hid_warn(hdev, 913 "pen parameters not found"); 914 } 915 } else { 916 uclogic_params_init_invalid(&p); 917 } 918 } else { 919 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed); 920 if (rc != 0) 921 goto cleanup; 922 } 923 break; 924 case VID_PID(USB_VENDOR_ID_UCLOGIC, 925 USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U): 926 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed); 927 if (rc != 0) 928 goto cleanup; 929 break; 930 case VID_PID(USB_VENDOR_ID_UCLOGIC, 931 USB_DEVICE_ID_UCLOGIC_TABLET_WP1062): 932 rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed); 933 if (rc != 0) 934 goto cleanup; 935 break; 936 case VID_PID(USB_VENDOR_ID_UCLOGIC, 937 USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850): 938 switch (bInterfaceNumber) { 939 case 0: 940 rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0); 941 if (rc != 0) 942 goto cleanup; 943 break; 944 case 1: 945 rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1); 946 if (rc != 0) 947 goto cleanup; 948 break; 949 case 2: 950 rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2); 951 if (rc != 0) 952 goto cleanup; 953 break; 954 } 955 break; 956 case VID_PID(USB_VENDOR_ID_UCLOGIC, 957 USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60): 958 /* 959 * If it is not a three-interface version, which is known to 960 * respond to initialization. 961 */ 962 if (bNumInterfaces != 3) { 963 switch (bInterfaceNumber) { 964 case 0: 965 rc = WITH_OPT_DESC(TWHA60_ORIG0, 966 twha60_fixed0); 967 if (rc != 0) 968 goto cleanup; 969 break; 970 case 1: 971 rc = WITH_OPT_DESC(TWHA60_ORIG1, 972 twha60_fixed1); 973 if (rc != 0) 974 goto cleanup; 975 break; 976 } 977 break; 978 } 979 fallthrough; 980 case VID_PID(USB_VENDOR_ID_HUION, 981 USB_DEVICE_ID_HUION_TABLET): 982 case VID_PID(USB_VENDOR_ID_HUION, 983 USB_DEVICE_ID_HUION_HS64): 984 case VID_PID(USB_VENDOR_ID_UCLOGIC, 985 USB_DEVICE_ID_HUION_TABLET): 986 case VID_PID(USB_VENDOR_ID_UCLOGIC, 987 USB_DEVICE_ID_YIYNOVA_TABLET): 988 case VID_PID(USB_VENDOR_ID_UCLOGIC, 989 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81): 990 case VID_PID(USB_VENDOR_ID_UCLOGIC, 991 USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3): 992 case VID_PID(USB_VENDOR_ID_UCLOGIC, 993 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45): 994 case VID_PID(USB_VENDOR_ID_UCLOGIC, 995 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47): 996 rc = uclogic_params_huion_init(&p, hdev); 997 if (rc != 0) 998 goto cleanup; 999 break; 1000 case VID_PID(USB_VENDOR_ID_UGTIZER, 1001 USB_DEVICE_ID_UGTIZER_TABLET_GP0610): 1002 case VID_PID(USB_VENDOR_ID_UGTIZER, 1003 USB_DEVICE_ID_UGTIZER_TABLET_GT5040): 1004 case VID_PID(USB_VENDOR_ID_UGEE, 1005 USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540): 1006 case VID_PID(USB_VENDOR_ID_UGEE, 1007 USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640): 1008 case VID_PID(USB_VENDOR_ID_UGEE, 1009 USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720): 1010 /* If this is the pen interface */ 1011 if (bInterfaceNumber == 1) { 1012 /* Probe v1 pen parameters */ 1013 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1014 if (rc != 0) { 1015 hid_err(hdev, "pen probing failed: %d\n", rc); 1016 goto cleanup; 1017 } 1018 if (!found) { 1019 hid_warn(hdev, "pen parameters not found"); 1020 uclogic_params_init_invalid(&p); 1021 } 1022 } else { 1023 /* TODO: Consider marking the interface invalid */ 1024 uclogic_params_init_with_pen_unused(&p); 1025 } 1026 break; 1027 case VID_PID(USB_VENDOR_ID_UGEE, 1028 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01): 1029 /* If this is the pen and frame interface */ 1030 if (bInterfaceNumber == 1) { 1031 /* Probe v1 pen parameters */ 1032 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1033 if (rc != 0) { 1034 hid_err(hdev, "pen probing failed: %d\n", rc); 1035 goto cleanup; 1036 } 1037 /* Initialize frame parameters */ 1038 rc = uclogic_params_frame_init_with_desc( 1039 &p.frame, 1040 uclogic_rdesc_xppen_deco01_frame_arr, 1041 uclogic_rdesc_xppen_deco01_frame_size, 1042 0); 1043 if (rc != 0) 1044 goto cleanup; 1045 } else { 1046 /* TODO: Consider marking the interface invalid */ 1047 uclogic_params_init_with_pen_unused(&p); 1048 } 1049 break; 1050 case VID_PID(USB_VENDOR_ID_TRUST, 1051 USB_DEVICE_ID_TRUST_PANORA_TABLET): 1052 case VID_PID(USB_VENDOR_ID_UGEE, 1053 USB_DEVICE_ID_UGEE_TABLET_G5): 1054 /* Ignore non-pen interfaces */ 1055 if (bInterfaceNumber != 1) { 1056 uclogic_params_init_invalid(&p); 1057 break; 1058 } 1059 1060 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1061 if (rc != 0) { 1062 hid_err(hdev, "pen probing failed: %d\n", rc); 1063 goto cleanup; 1064 } else if (found) { 1065 rc = uclogic_params_frame_init_with_desc( 1066 &p.frame, 1067 uclogic_rdesc_ugee_g5_frame_arr, 1068 uclogic_rdesc_ugee_g5_frame_size, 1069 UCLOGIC_RDESC_UGEE_G5_FRAME_ID); 1070 if (rc != 0) { 1071 hid_err(hdev, 1072 "failed creating buttonpad parameters: %d\n", 1073 rc); 1074 goto cleanup; 1075 } 1076 p.frame.re_lsb = 1077 UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB; 1078 p.frame.dev_id_byte = 1079 UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE; 1080 } else { 1081 hid_warn(hdev, "pen parameters not found"); 1082 uclogic_params_init_invalid(&p); 1083 } 1084 1085 break; 1086 case VID_PID(USB_VENDOR_ID_UGEE, 1087 USB_DEVICE_ID_UGEE_TABLET_EX07S): 1088 /* Ignore non-pen interfaces */ 1089 if (bInterfaceNumber != 1) { 1090 uclogic_params_init_invalid(&p); 1091 break; 1092 } 1093 1094 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1095 if (rc != 0) { 1096 hid_err(hdev, "pen probing failed: %d\n", rc); 1097 goto cleanup; 1098 } else if (found) { 1099 rc = uclogic_params_frame_init_with_desc( 1100 &p.frame, 1101 uclogic_rdesc_ugee_ex07_buttonpad_arr, 1102 uclogic_rdesc_ugee_ex07_buttonpad_size, 1103 0); 1104 if (rc != 0) { 1105 hid_err(hdev, 1106 "failed creating buttonpad parameters: %d\n", 1107 rc); 1108 goto cleanup; 1109 } 1110 } else { 1111 hid_warn(hdev, "pen parameters not found"); 1112 uclogic_params_init_invalid(&p); 1113 } 1114 1115 break; 1116 } 1117 1118 #undef VID_PID 1119 #undef WITH_OPT_DESC 1120 1121 /* Output parameters */ 1122 memcpy(params, &p, sizeof(*params)); 1123 memset(&p, 0, sizeof(p)); 1124 rc = 0; 1125 cleanup: 1126 uclogic_params_cleanup(&p); 1127 return rc; 1128 } 1129