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