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 * @inrange: The in-range reporting type to convert. 27 * 28 * Return: 29 * * The string representing the type, or 30 * * %NULL if the type is unknown. 31 */ 32 static 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_pen_hid_dbg() - Dump tablet interface pen parameters 49 * @hdev: The HID device the pen parameters describe. 50 * @pen: The pen parameters to dump. 51 * 52 * Dump tablet interface pen parameters with hid_dbg(). The dump is indented 53 * with a tab. 54 */ 55 static void uclogic_params_pen_hid_dbg(const struct hid_device *hdev, 56 const struct uclogic_params_pen *pen) 57 { 58 size_t i; 59 60 hid_dbg(hdev, "\t.usage_invalid = %s\n", 61 (pen->usage_invalid ? "true" : "false")); 62 hid_dbg(hdev, "\t.desc_ptr = %p\n", pen->desc_ptr); 63 hid_dbg(hdev, "\t.desc_size = %u\n", pen->desc_size); 64 hid_dbg(hdev, "\t.id = %u\n", pen->id); 65 hid_dbg(hdev, "\t.subreport_list = {\n"); 66 for (i = 0; i < ARRAY_SIZE(pen->subreport_list); i++) { 67 hid_dbg(hdev, "\t\t{0x%02hhx, %hhu}%s\n", 68 pen->subreport_list[i].value, 69 pen->subreport_list[i].id, 70 i < (ARRAY_SIZE(pen->subreport_list) - 1) ? "," : ""); 71 } 72 hid_dbg(hdev, "\t}\n"); 73 hid_dbg(hdev, "\t.inrange = %s\n", 74 uclogic_params_pen_inrange_to_str(pen->inrange)); 75 hid_dbg(hdev, "\t.fragmented_hires = %s\n", 76 (pen->fragmented_hires ? "true" : "false")); 77 hid_dbg(hdev, "\t.tilt_y_flipped = %s\n", 78 (pen->tilt_y_flipped ? "true" : "false")); 79 } 80 81 /** 82 * uclogic_params_frame_hid_dbg() - Dump tablet interface frame parameters 83 * @hdev: The HID device the pen parameters describe. 84 * @frame: The frame parameters to dump. 85 * 86 * Dump tablet interface frame parameters with hid_dbg(). The dump is 87 * indented with two tabs. 88 */ 89 static void uclogic_params_frame_hid_dbg( 90 const struct hid_device *hdev, 91 const struct uclogic_params_frame *frame) 92 { 93 hid_dbg(hdev, "\t\t.desc_ptr = %p\n", frame->desc_ptr); 94 hid_dbg(hdev, "\t\t.desc_size = %u\n", frame->desc_size); 95 hid_dbg(hdev, "\t\t.id = %u\n", frame->id); 96 hid_dbg(hdev, "\t\t.suffix = %s\n", frame->suffix); 97 hid_dbg(hdev, "\t\t.re_lsb = %u\n", frame->re_lsb); 98 hid_dbg(hdev, "\t\t.dev_id_byte = %u\n", frame->dev_id_byte); 99 hid_dbg(hdev, "\t\t.touch_byte = %u\n", frame->touch_byte); 100 hid_dbg(hdev, "\t\t.touch_max = %hhd\n", frame->touch_max); 101 hid_dbg(hdev, "\t\t.touch_flip_at = %hhd\n", 102 frame->touch_flip_at); 103 hid_dbg(hdev, "\t\t.bitmap_dial_byte = %u\n", 104 frame->bitmap_dial_byte); 105 } 106 107 /** 108 * uclogic_params_hid_dbg() - Dump tablet interface parameters 109 * @hdev: The HID device the parameters describe. 110 * @params: The parameters to dump. 111 * 112 * Dump tablet interface parameters with hid_dbg(). 113 */ 114 void uclogic_params_hid_dbg(const struct hid_device *hdev, 115 const struct uclogic_params *params) 116 { 117 size_t i; 118 119 hid_dbg(hdev, ".invalid = %s\n", 120 params->invalid ? "true" : "false"); 121 hid_dbg(hdev, ".desc_ptr = %p\n", params->desc_ptr); 122 hid_dbg(hdev, ".desc_size = %u\n", params->desc_size); 123 hid_dbg(hdev, ".pen = {\n"); 124 uclogic_params_pen_hid_dbg(hdev, ¶ms->pen); 125 hid_dbg(hdev, "\t}\n"); 126 hid_dbg(hdev, ".frame_list = {\n"); 127 for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) { 128 hid_dbg(hdev, "\t{\n"); 129 uclogic_params_frame_hid_dbg(hdev, ¶ms->frame_list[i]); 130 hid_dbg(hdev, "\t}%s\n", 131 i < (ARRAY_SIZE(params->frame_list) - 1) ? "," : ""); 132 } 133 hid_dbg(hdev, "}\n"); 134 } 135 136 /** 137 * uclogic_params_get_str_desc - retrieve a string descriptor from a HID 138 * device interface, putting it into a kmalloc-allocated buffer as is, without 139 * character encoding conversion. 140 * 141 * @pbuf: Location for the kmalloc-allocated buffer pointer containing 142 * the retrieved descriptor. Not modified in case of error. 143 * Can be NULL to have retrieved descriptor discarded. 144 * @hdev: The HID device of the tablet interface to retrieve the string 145 * descriptor from. Cannot be NULL. 146 * @idx: Index of the string descriptor to request from the device. 147 * @len: Length of the buffer to allocate and the data to retrieve. 148 * 149 * Returns: 150 * number of bytes retrieved (<= len), 151 * -EPIPE, if the descriptor was not found, or 152 * another negative errno code in case of other error. 153 */ 154 static int uclogic_params_get_str_desc(__u8 **pbuf, struct hid_device *hdev, 155 __u8 idx, size_t len) 156 { 157 int rc; 158 struct usb_device *udev; 159 __u8 *buf = NULL; 160 161 /* Check arguments */ 162 if (hdev == NULL) { 163 rc = -EINVAL; 164 goto cleanup; 165 } 166 167 udev = hid_to_usb_dev(hdev); 168 169 buf = kmalloc(len, GFP_KERNEL); 170 if (buf == NULL) { 171 rc = -ENOMEM; 172 goto cleanup; 173 } 174 175 rc = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 176 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, 177 (USB_DT_STRING << 8) + idx, 178 0x0409, buf, len, 179 USB_CTRL_GET_TIMEOUT); 180 if (rc == -EPIPE) { 181 hid_dbg(hdev, "string descriptor #%hhu not found\n", idx); 182 goto cleanup; 183 } else if (rc < 0) { 184 hid_err(hdev, 185 "failed retrieving string descriptor #%u: %d\n", 186 idx, rc); 187 goto cleanup; 188 } 189 190 if (pbuf != NULL) { 191 *pbuf = buf; 192 buf = NULL; 193 } 194 195 cleanup: 196 kfree(buf); 197 return rc; 198 } 199 200 /** 201 * uclogic_params_pen_cleanup - free resources used by struct 202 * uclogic_params_pen (tablet interface's pen input parameters). 203 * Can be called repeatedly. 204 * 205 * @pen: Pen input parameters to cleanup. Cannot be NULL. 206 */ 207 static void uclogic_params_pen_cleanup(struct uclogic_params_pen *pen) 208 { 209 kfree(pen->desc_ptr); 210 memset(pen, 0, sizeof(*pen)); 211 } 212 213 /** 214 * uclogic_params_pen_init_v1() - initialize tablet interface pen 215 * input and retrieve its parameters from the device, using v1 protocol. 216 * 217 * @pen: Pointer to the pen parameters to initialize (to be 218 * cleaned up with uclogic_params_pen_cleanup()). Not modified in 219 * case of error, or if parameters are not found. Cannot be NULL. 220 * @pfound: Location for a flag which is set to true if the parameters 221 * were found, and to false if not (e.g. device was 222 * incompatible). Not modified in case of error. Cannot be NULL. 223 * @hdev: The HID device of the tablet interface to initialize and get 224 * parameters from. Cannot be NULL. 225 * 226 * Returns: 227 * Zero, if successful. A negative errno code on error. 228 */ 229 static int uclogic_params_pen_init_v1(struct uclogic_params_pen *pen, 230 bool *pfound, 231 struct hid_device *hdev) 232 { 233 int rc; 234 bool found = false; 235 /* Buffer for (part of) the string descriptor */ 236 __u8 *buf = NULL; 237 /* Minimum descriptor length required, maximum seen so far is 18 */ 238 const int len = 12; 239 s32 resolution; 240 /* Pen report descriptor template parameters */ 241 s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; 242 __u8 *desc_ptr = NULL; 243 244 /* Check arguments */ 245 if (pen == NULL || pfound == NULL || hdev == NULL) { 246 rc = -EINVAL; 247 goto cleanup; 248 } 249 250 /* 251 * Read string descriptor containing pen input parameters. 252 * The specific string descriptor and data were discovered by sniffing 253 * the Windows driver traffic. 254 * NOTE: This enables fully-functional tablet mode. 255 */ 256 rc = uclogic_params_get_str_desc(&buf, hdev, 100, len); 257 if (rc == -EPIPE) { 258 hid_dbg(hdev, 259 "string descriptor with pen parameters not found, assuming not compatible\n"); 260 goto finish; 261 } else if (rc < 0) { 262 hid_err(hdev, "failed retrieving pen parameters: %d\n", rc); 263 goto cleanup; 264 } else if (rc != len) { 265 hid_dbg(hdev, 266 "string descriptor with pen parameters has invalid length (got %d, expected %d), assuming not compatible\n", 267 rc, len); 268 goto finish; 269 } 270 271 /* 272 * Fill report descriptor parameters from the string descriptor 273 */ 274 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 275 get_unaligned_le16(buf + 2); 276 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 277 get_unaligned_le16(buf + 4); 278 desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 279 get_unaligned_le16(buf + 8); 280 resolution = get_unaligned_le16(buf + 10); 281 if (resolution == 0) { 282 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0; 283 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0; 284 } else { 285 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 286 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 / 287 resolution; 288 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 289 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 / 290 resolution; 291 } 292 kfree(buf); 293 buf = NULL; 294 295 /* 296 * Generate pen report descriptor 297 */ 298 desc_ptr = uclogic_rdesc_template_apply( 299 uclogic_rdesc_v1_pen_template_arr, 300 uclogic_rdesc_v1_pen_template_size, 301 desc_params, ARRAY_SIZE(desc_params)); 302 if (desc_ptr == NULL) { 303 rc = -ENOMEM; 304 goto cleanup; 305 } 306 307 /* 308 * Fill-in the parameters 309 */ 310 memset(pen, 0, sizeof(*pen)); 311 pen->desc_ptr = desc_ptr; 312 desc_ptr = NULL; 313 pen->desc_size = uclogic_rdesc_v1_pen_template_size; 314 pen->id = UCLOGIC_RDESC_V1_PEN_ID; 315 pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_INVERTED; 316 found = true; 317 finish: 318 *pfound = found; 319 rc = 0; 320 cleanup: 321 kfree(desc_ptr); 322 kfree(buf); 323 return rc; 324 } 325 326 /** 327 * uclogic_params_get_le24() - get a 24-bit little-endian number from a 328 * buffer. 329 * 330 * @p: The pointer to the number buffer. 331 * 332 * Returns: 333 * The retrieved number 334 */ 335 static s32 uclogic_params_get_le24(const void *p) 336 { 337 const __u8 *b = p; 338 return b[0] | (b[1] << 8UL) | (b[2] << 16UL); 339 } 340 341 /** 342 * uclogic_params_pen_init_v2() - initialize tablet interface pen 343 * input and retrieve its parameters from the device, using v2 protocol. 344 * 345 * @pen: Pointer to the pen parameters to initialize (to be 346 * cleaned up with uclogic_params_pen_cleanup()). Not 347 * modified in case of error, or if parameters are not 348 * found. Cannot be NULL. 349 * @pfound: Location for a flag which is set to true if the 350 * parameters were found, and to false if not (e.g. 351 * device was incompatible). Not modified in case of 352 * error. Cannot be NULL. 353 * @pparams_ptr: Location for a kmalloc'ed pointer to the retrieved raw 354 * parameters, which could be used to identify the tablet 355 * to some extent. Should be freed with kfree after use. 356 * NULL, if not needed. Not modified in case of error. 357 * Only set if *pfound is set to true. 358 * @pparams_len: Location for the length of the retrieved raw 359 * parameters. NULL, if not needed. Not modified in case 360 * of error. Only set if *pfound is set to true. 361 * @hdev: The HID device of the tablet interface to initialize 362 * and get parameters from. Cannot be NULL. 363 * 364 * Returns: 365 * Zero, if successful. A negative errno code on error. 366 */ 367 static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen, 368 bool *pfound, 369 __u8 **pparams_ptr, 370 size_t *pparams_len, 371 struct hid_device *hdev) 372 { 373 int rc; 374 bool found = false; 375 /* Buffer for (part of) the parameter string descriptor */ 376 __u8 *buf = NULL; 377 /* Parameter string descriptor required length */ 378 const int params_len_min = 18; 379 /* Parameter string descriptor accepted length */ 380 const int params_len_max = 32; 381 /* Parameter string descriptor received length */ 382 int params_len; 383 size_t i; 384 s32 resolution; 385 /* Pen report descriptor template parameters */ 386 s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; 387 __u8 *desc_ptr = NULL; 388 389 /* Check arguments */ 390 if (pen == NULL || pfound == NULL || hdev == NULL) { 391 rc = -EINVAL; 392 goto cleanup; 393 } 394 395 /* 396 * Read string descriptor containing pen input parameters. 397 * The specific string descriptor and data were discovered by sniffing 398 * the Windows driver traffic. 399 * NOTE: This enables fully-functional tablet mode. 400 */ 401 rc = uclogic_params_get_str_desc(&buf, hdev, 200, params_len_max); 402 if (rc == -EPIPE) { 403 hid_dbg(hdev, 404 "string descriptor with pen parameters not found, assuming not compatible\n"); 405 goto finish; 406 } else if (rc < 0) { 407 hid_err(hdev, "failed retrieving pen parameters: %d\n", rc); 408 goto cleanup; 409 } else if (rc < params_len_min) { 410 hid_dbg(hdev, 411 "string descriptor with pen parameters is too short (got %d, expected at least %d), assuming not compatible\n", 412 rc, params_len_min); 413 goto finish; 414 } 415 416 params_len = rc; 417 418 /* 419 * Check it's not just a catch-all UTF-16LE-encoded ASCII 420 * string (such as the model name) some tablets put into all 421 * unknown string descriptors. 422 */ 423 for (i = 2; 424 i < params_len && 425 (buf[i] >= 0x20 && buf[i] < 0x7f && buf[i + 1] == 0); 426 i += 2); 427 if (i >= params_len) { 428 hid_dbg(hdev, 429 "string descriptor with pen parameters seems to contain only text, assuming not compatible\n"); 430 goto finish; 431 } 432 433 /* 434 * Fill report descriptor parameters from the string descriptor 435 */ 436 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 437 uclogic_params_get_le24(buf + 2); 438 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 439 uclogic_params_get_le24(buf + 5); 440 desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 441 get_unaligned_le16(buf + 8); 442 resolution = get_unaligned_le16(buf + 10); 443 if (resolution == 0) { 444 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0; 445 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0; 446 } else { 447 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 448 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 / 449 resolution; 450 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 451 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 / 452 resolution; 453 } 454 455 /* 456 * Generate pen report descriptor 457 */ 458 desc_ptr = uclogic_rdesc_template_apply( 459 uclogic_rdesc_v2_pen_template_arr, 460 uclogic_rdesc_v2_pen_template_size, 461 desc_params, ARRAY_SIZE(desc_params)); 462 if (desc_ptr == NULL) { 463 rc = -ENOMEM; 464 goto cleanup; 465 } 466 467 /* 468 * Fill-in the parameters 469 */ 470 memset(pen, 0, sizeof(*pen)); 471 pen->desc_ptr = desc_ptr; 472 desc_ptr = NULL; 473 pen->desc_size = uclogic_rdesc_v2_pen_template_size; 474 pen->id = UCLOGIC_RDESC_V2_PEN_ID; 475 pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_NONE; 476 pen->fragmented_hires = true; 477 pen->tilt_y_flipped = true; 478 found = true; 479 if (pparams_ptr != NULL) { 480 *pparams_ptr = buf; 481 buf = NULL; 482 } 483 if (pparams_len != NULL) 484 *pparams_len = params_len; 485 486 finish: 487 *pfound = found; 488 rc = 0; 489 cleanup: 490 kfree(desc_ptr); 491 kfree(buf); 492 return rc; 493 } 494 495 /** 496 * uclogic_params_frame_cleanup - free resources used by struct 497 * uclogic_params_frame (tablet interface's frame controls input parameters). 498 * Can be called repeatedly. 499 * 500 * @frame: Frame controls input parameters to cleanup. Cannot be NULL. 501 */ 502 static void uclogic_params_frame_cleanup(struct uclogic_params_frame *frame) 503 { 504 kfree(frame->desc_ptr); 505 memset(frame, 0, sizeof(*frame)); 506 } 507 508 /** 509 * uclogic_params_frame_init_with_desc() - initialize tablet's frame control 510 * parameters with a static report descriptor. 511 * 512 * @frame: Pointer to the frame parameters to initialize (to be cleaned 513 * up with uclogic_params_frame_cleanup()). Not modified in case 514 * of error. Cannot be NULL. 515 * @desc_ptr: Report descriptor pointer. Can be NULL, if desc_size is zero. 516 * @desc_size: Report descriptor size. 517 * @id: Report ID used for frame reports, if they should be tweaked, 518 * zero if not. 519 * 520 * Returns: 521 * Zero, if successful. A negative errno code on error. 522 */ 523 static int uclogic_params_frame_init_with_desc( 524 struct uclogic_params_frame *frame, 525 const __u8 *desc_ptr, 526 size_t desc_size, 527 unsigned int id) 528 { 529 __u8 *copy_desc_ptr; 530 531 if (frame == NULL || (desc_ptr == NULL && desc_size != 0)) 532 return -EINVAL; 533 534 copy_desc_ptr = kmemdup(desc_ptr, desc_size, GFP_KERNEL); 535 if (copy_desc_ptr == NULL) 536 return -ENOMEM; 537 538 memset(frame, 0, sizeof(*frame)); 539 frame->desc_ptr = copy_desc_ptr; 540 frame->desc_size = desc_size; 541 frame->id = id; 542 return 0; 543 } 544 545 /** 546 * uclogic_params_frame_init_v1() - initialize v1 tablet interface frame 547 * controls. 548 * 549 * @frame: Pointer to the frame parameters to initialize (to be cleaned 550 * up with uclogic_params_frame_cleanup()). Not modified in case 551 * of error, or if parameters are not found. Cannot be NULL. 552 * @pfound: Location for a flag which is set to true if the parameters 553 * were found, and to false if not (e.g. device was 554 * incompatible). Not modified in case of error. Cannot be NULL. 555 * @hdev: The HID device of the tablet interface to initialize and get 556 * parameters from. Cannot be NULL. 557 * 558 * Returns: 559 * Zero, if successful. A negative errno code on error. 560 */ 561 static int uclogic_params_frame_init_v1(struct uclogic_params_frame *frame, 562 bool *pfound, 563 struct hid_device *hdev) 564 { 565 int rc; 566 bool found = false; 567 struct usb_device *usb_dev; 568 char *str_buf = NULL; 569 const size_t str_len = 16; 570 571 /* Check arguments */ 572 if (frame == NULL || pfound == NULL || hdev == NULL) { 573 rc = -EINVAL; 574 goto cleanup; 575 } 576 577 usb_dev = hid_to_usb_dev(hdev); 578 579 /* 580 * Enable generic button mode 581 */ 582 str_buf = kzalloc(str_len, GFP_KERNEL); 583 if (str_buf == NULL) { 584 rc = -ENOMEM; 585 goto cleanup; 586 } 587 588 rc = usb_string(usb_dev, 123, str_buf, str_len); 589 if (rc == -EPIPE) { 590 hid_dbg(hdev, 591 "generic button -enabling string descriptor not found\n"); 592 } else if (rc < 0) { 593 goto cleanup; 594 } else if (strncmp(str_buf, "HK On", rc) != 0) { 595 hid_dbg(hdev, 596 "invalid response to enabling generic buttons: \"%s\"\n", 597 str_buf); 598 } else { 599 hid_dbg(hdev, "generic buttons enabled\n"); 600 rc = uclogic_params_frame_init_with_desc( 601 frame, 602 uclogic_rdesc_v1_frame_arr, 603 uclogic_rdesc_v1_frame_size, 604 UCLOGIC_RDESC_V1_FRAME_ID); 605 if (rc != 0) 606 goto cleanup; 607 found = true; 608 } 609 610 *pfound = found; 611 rc = 0; 612 cleanup: 613 kfree(str_buf); 614 return rc; 615 } 616 617 /** 618 * uclogic_params_cleanup - free resources used by struct uclogic_params 619 * (tablet interface's parameters). 620 * Can be called repeatedly. 621 * 622 * @params: Input parameters to cleanup. Cannot be NULL. 623 */ 624 void uclogic_params_cleanup(struct uclogic_params *params) 625 { 626 if (!params->invalid) { 627 size_t i; 628 kfree(params->desc_ptr); 629 uclogic_params_pen_cleanup(¶ms->pen); 630 for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) 631 uclogic_params_frame_cleanup(¶ms->frame_list[i]); 632 633 memset(params, 0, sizeof(*params)); 634 } 635 } 636 637 /** 638 * uclogic_params_get_desc() - Get a replacement report descriptor for a 639 * tablet's interface. 640 * 641 * @params: The parameters of a tablet interface to get report 642 * descriptor for. Cannot be NULL. 643 * @pdesc: Location for the resulting, kmalloc-allocated report 644 * descriptor pointer, or for NULL, if there's no replacement 645 * report descriptor. Not modified in case of error. Cannot be 646 * NULL. 647 * @psize: Location for the resulting report descriptor size, not set if 648 * there's no replacement report descriptor. Not modified in case 649 * of error. Cannot be NULL. 650 * 651 * Returns: 652 * Zero, if successful. 653 * -EINVAL, if invalid arguments are supplied. 654 * -ENOMEM, if failed to allocate memory. 655 */ 656 int uclogic_params_get_desc(const struct uclogic_params *params, 657 __u8 **pdesc, 658 unsigned int *psize) 659 { 660 int rc = -ENOMEM; 661 bool present = false; 662 unsigned int size = 0; 663 __u8 *desc = NULL; 664 size_t i; 665 666 /* Check arguments */ 667 if (params == NULL || pdesc == NULL || psize == NULL) 668 return -EINVAL; 669 670 /* Concatenate descriptors */ 671 #define ADD_DESC(_desc_ptr, _desc_size) \ 672 do { \ 673 unsigned int new_size; \ 674 __u8 *new_desc; \ 675 if ((_desc_ptr) == NULL) { \ 676 break; \ 677 } \ 678 new_size = size + (_desc_size); \ 679 new_desc = krealloc(desc, new_size, GFP_KERNEL); \ 680 if (new_desc == NULL) { \ 681 goto cleanup; \ 682 } \ 683 memcpy(new_desc + size, (_desc_ptr), (_desc_size)); \ 684 desc = new_desc; \ 685 size = new_size; \ 686 present = true; \ 687 } while (0) 688 689 ADD_DESC(params->desc_ptr, params->desc_size); 690 ADD_DESC(params->pen.desc_ptr, params->pen.desc_size); 691 for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) { 692 ADD_DESC(params->frame_list[i].desc_ptr, 693 params->frame_list[i].desc_size); 694 } 695 696 #undef ADD_DESC 697 698 if (present) { 699 *pdesc = desc; 700 *psize = size; 701 desc = NULL; 702 } 703 rc = 0; 704 cleanup: 705 kfree(desc); 706 return rc; 707 } 708 709 /** 710 * uclogic_params_init_invalid() - initialize tablet interface parameters, 711 * specifying the interface is invalid. 712 * 713 * @params: Parameters to initialize (to be cleaned with 714 * uclogic_params_cleanup()). Cannot be NULL. 715 */ 716 static void uclogic_params_init_invalid(struct uclogic_params *params) 717 { 718 params->invalid = true; 719 } 720 721 /** 722 * uclogic_params_init_with_opt_desc() - initialize tablet interface 723 * parameters with an optional replacement report descriptor. Only modify 724 * report descriptor, if the original report descriptor matches the expected 725 * size. 726 * 727 * @params: Parameters to initialize (to be cleaned with 728 * uclogic_params_cleanup()). Not modified in case of 729 * error. Cannot be NULL. 730 * @hdev: The HID device of the tablet interface create the 731 * parameters for. Cannot be NULL. 732 * @orig_desc_size: Expected size of the original report descriptor to 733 * be replaced. 734 * @desc_ptr: Pointer to the replacement report descriptor. 735 * Can be NULL, if desc_size is zero. 736 * @desc_size: Size of the replacement report descriptor. 737 * 738 * Returns: 739 * Zero, if successful. -EINVAL if an invalid argument was passed. 740 * -ENOMEM, if failed to allocate memory. 741 */ 742 static int uclogic_params_init_with_opt_desc(struct uclogic_params *params, 743 struct hid_device *hdev, 744 unsigned int orig_desc_size, 745 __u8 *desc_ptr, 746 unsigned int desc_size) 747 { 748 __u8 *desc_copy_ptr = NULL; 749 unsigned int desc_copy_size; 750 int rc; 751 752 /* Check arguments */ 753 if (params == NULL || hdev == NULL || 754 (desc_ptr == NULL && desc_size != 0)) { 755 rc = -EINVAL; 756 goto cleanup; 757 } 758 759 /* Replace report descriptor, if it matches */ 760 if (hdev->dev_rsize == orig_desc_size) { 761 hid_dbg(hdev, 762 "device report descriptor matches the expected size, replacing\n"); 763 desc_copy_ptr = kmemdup(desc_ptr, desc_size, GFP_KERNEL); 764 if (desc_copy_ptr == NULL) { 765 rc = -ENOMEM; 766 goto cleanup; 767 } 768 desc_copy_size = desc_size; 769 } else { 770 hid_dbg(hdev, 771 "device report descriptor doesn't match the expected size (%u != %u), preserving\n", 772 hdev->dev_rsize, orig_desc_size); 773 desc_copy_ptr = NULL; 774 desc_copy_size = 0; 775 } 776 777 /* Output parameters */ 778 memset(params, 0, sizeof(*params)); 779 params->desc_ptr = desc_copy_ptr; 780 desc_copy_ptr = NULL; 781 params->desc_size = desc_copy_size; 782 783 rc = 0; 784 cleanup: 785 kfree(desc_copy_ptr); 786 return rc; 787 } 788 789 /** 790 * uclogic_params_huion_init() - initialize a Huion tablet interface and discover 791 * its parameters. 792 * 793 * @params: Parameters to fill in (to be cleaned with 794 * uclogic_params_cleanup()). Not modified in case of error. 795 * Cannot be NULL. 796 * @hdev: The HID device of the tablet interface to initialize and get 797 * parameters from. Cannot be NULL. 798 * 799 * Returns: 800 * Zero, if successful. A negative errno code on error. 801 */ 802 static int uclogic_params_huion_init(struct uclogic_params *params, 803 struct hid_device *hdev) 804 { 805 int rc; 806 struct usb_device *udev; 807 struct usb_interface *iface; 808 __u8 bInterfaceNumber; 809 bool found; 810 /* The resulting parameters (noop) */ 811 struct uclogic_params p = {0, }; 812 static const char transition_ver[] = "HUION_T153_160607"; 813 char *ver_ptr = NULL; 814 const size_t ver_len = sizeof(transition_ver) + 1; 815 __u8 *params_ptr = NULL; 816 size_t params_len = 0; 817 /* Parameters string descriptor of a model with touch ring (HS610) */ 818 const __u8 touch_ring_model_params_buf[] = { 819 0x13, 0x03, 0x70, 0xC6, 0x00, 0x06, 0x7C, 0x00, 820 0xFF, 0x1F, 0xD8, 0x13, 0x03, 0x0D, 0x10, 0x01, 821 0x04, 0x3C, 0x3E 822 }; 823 824 /* Check arguments */ 825 if (params == NULL || hdev == NULL) { 826 rc = -EINVAL; 827 goto cleanup; 828 } 829 830 udev = hid_to_usb_dev(hdev); 831 iface = to_usb_interface(hdev->dev.parent); 832 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; 833 834 /* If it's a custom keyboard interface */ 835 if (bInterfaceNumber == 1) { 836 /* Keep everything intact, but mark pen usage invalid */ 837 p.pen.usage_invalid = true; 838 goto output; 839 /* Else, if it's not a pen interface */ 840 } else if (bInterfaceNumber != 0) { 841 uclogic_params_init_invalid(&p); 842 goto output; 843 } 844 845 /* Try to get firmware version */ 846 ver_ptr = kzalloc(ver_len, GFP_KERNEL); 847 if (ver_ptr == NULL) { 848 rc = -ENOMEM; 849 goto cleanup; 850 } 851 rc = usb_string(udev, 201, ver_ptr, ver_len); 852 if (rc == -EPIPE) { 853 *ver_ptr = '\0'; 854 } else if (rc < 0) { 855 hid_err(hdev, 856 "failed retrieving Huion firmware version: %d\n", rc); 857 goto cleanup; 858 } 859 860 /* If this is a transition firmware */ 861 if (strcmp(ver_ptr, transition_ver) == 0) { 862 hid_dbg(hdev, 863 "transition firmware detected, not probing pen v2 parameters\n"); 864 } else { 865 /* Try to probe v2 pen parameters */ 866 rc = uclogic_params_pen_init_v2(&p.pen, &found, 867 ¶ms_ptr, ¶ms_len, 868 hdev); 869 if (rc != 0) { 870 hid_err(hdev, 871 "failed probing pen v2 parameters: %d\n", rc); 872 goto cleanup; 873 } else if (found) { 874 hid_dbg(hdev, "pen v2 parameters found\n"); 875 /* Create v2 frame button parameters */ 876 rc = uclogic_params_frame_init_with_desc( 877 &p.frame_list[0], 878 uclogic_rdesc_v2_frame_buttons_arr, 879 uclogic_rdesc_v2_frame_buttons_size, 880 UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID); 881 if (rc != 0) { 882 hid_err(hdev, 883 "failed creating v2 frame button parameters: %d\n", 884 rc); 885 goto cleanup; 886 } 887 888 /* Link from pen sub-report */ 889 p.pen.subreport_list[0].value = 0xe0; 890 p.pen.subreport_list[0].id = 891 UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID; 892 893 /* If this is the model with touch ring */ 894 if (params_ptr != NULL && 895 params_len == sizeof(touch_ring_model_params_buf) && 896 memcmp(params_ptr, touch_ring_model_params_buf, 897 params_len) == 0) { 898 /* Create touch ring parameters */ 899 rc = uclogic_params_frame_init_with_desc( 900 &p.frame_list[1], 901 uclogic_rdesc_v2_frame_touch_ring_arr, 902 uclogic_rdesc_v2_frame_touch_ring_size, 903 UCLOGIC_RDESC_V2_FRAME_TOUCH_ID); 904 if (rc != 0) { 905 hid_err(hdev, 906 "failed creating v2 frame touch ring parameters: %d\n", 907 rc); 908 goto cleanup; 909 } 910 p.frame_list[1].suffix = "Touch Ring"; 911 p.frame_list[1].dev_id_byte = 912 UCLOGIC_RDESC_V2_FRAME_TOUCH_DEV_ID_BYTE; 913 p.frame_list[1].touch_byte = 5; 914 p.frame_list[1].touch_max = 12; 915 p.frame_list[1].touch_flip_at = 7; 916 } else { 917 /* Create touch strip parameters */ 918 rc = uclogic_params_frame_init_with_desc( 919 &p.frame_list[1], 920 uclogic_rdesc_v2_frame_touch_strip_arr, 921 uclogic_rdesc_v2_frame_touch_strip_size, 922 UCLOGIC_RDESC_V2_FRAME_TOUCH_ID); 923 if (rc != 0) { 924 hid_err(hdev, 925 "failed creating v2 frame touch strip parameters: %d\n", 926 rc); 927 goto cleanup; 928 } 929 p.frame_list[1].suffix = "Touch Strip"; 930 p.frame_list[1].dev_id_byte = 931 UCLOGIC_RDESC_V2_FRAME_TOUCH_DEV_ID_BYTE; 932 p.frame_list[1].touch_byte = 5; 933 p.frame_list[1].touch_max = 8; 934 } 935 936 /* Link from pen sub-report */ 937 p.pen.subreport_list[1].value = 0xf0; 938 p.pen.subreport_list[1].id = 939 UCLOGIC_RDESC_V2_FRAME_TOUCH_ID; 940 941 /* Create v2 frame dial parameters */ 942 rc = uclogic_params_frame_init_with_desc( 943 &p.frame_list[2], 944 uclogic_rdesc_v2_frame_dial_arr, 945 uclogic_rdesc_v2_frame_dial_size, 946 UCLOGIC_RDESC_V2_FRAME_DIAL_ID); 947 if (rc != 0) { 948 hid_err(hdev, 949 "failed creating v2 frame dial parameters: %d\n", 950 rc); 951 goto cleanup; 952 } 953 p.frame_list[2].suffix = "Dial"; 954 p.frame_list[2].dev_id_byte = 955 UCLOGIC_RDESC_V2_FRAME_DIAL_DEV_ID_BYTE; 956 p.frame_list[2].bitmap_dial_byte = 5; 957 958 /* Link from pen sub-report */ 959 p.pen.subreport_list[2].value = 0xf1; 960 p.pen.subreport_list[2].id = 961 UCLOGIC_RDESC_V2_FRAME_DIAL_ID; 962 963 goto output; 964 } 965 hid_dbg(hdev, "pen v2 parameters not found\n"); 966 } 967 968 /* Try to probe v1 pen parameters */ 969 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 970 if (rc != 0) { 971 hid_err(hdev, 972 "failed probing pen v1 parameters: %d\n", rc); 973 goto cleanup; 974 } else if (found) { 975 hid_dbg(hdev, "pen v1 parameters found\n"); 976 /* Try to probe v1 frame */ 977 rc = uclogic_params_frame_init_v1(&p.frame_list[0], 978 &found, hdev); 979 if (rc != 0) { 980 hid_err(hdev, "v1 frame probing failed: %d\n", rc); 981 goto cleanup; 982 } 983 hid_dbg(hdev, "frame v1 parameters%s found\n", 984 (found ? "" : " not")); 985 if (found) { 986 /* Link frame button subreports from pen reports */ 987 p.pen.subreport_list[0].value = 0xe0; 988 p.pen.subreport_list[0].id = 989 UCLOGIC_RDESC_V1_FRAME_ID; 990 } 991 goto output; 992 } 993 hid_dbg(hdev, "pen v1 parameters not found\n"); 994 995 uclogic_params_init_invalid(&p); 996 997 output: 998 /* Output parameters */ 999 memcpy(params, &p, sizeof(*params)); 1000 memset(&p, 0, sizeof(p)); 1001 rc = 0; 1002 cleanup: 1003 kfree(params_ptr); 1004 kfree(ver_ptr); 1005 uclogic_params_cleanup(&p); 1006 return rc; 1007 } 1008 1009 /** 1010 * uclogic_probe_interface() - some tablets, like the Parblo A610 PLUS V2 or 1011 * the XP-PEN Deco Mini 7, need to be initialized by sending them magic data. 1012 * 1013 * @hdev: The HID device of the tablet interface to initialize and get 1014 * parameters from. Cannot be NULL. 1015 * @magic_arr: The magic data that should be sent to probe the interface. 1016 * Cannot be NULL. 1017 * @magic_size: Size of the magic data. 1018 * @endpoint: Endpoint where the magic data should be sent. 1019 * 1020 * Returns: 1021 * Zero, if successful. A negative errno code on error. 1022 */ 1023 static int uclogic_probe_interface(struct hid_device *hdev, u8 *magic_arr, 1024 int magic_size, int endpoint) 1025 { 1026 struct usb_device *udev; 1027 unsigned int pipe = 0; 1028 int sent; 1029 u8 *buf = NULL; 1030 int rc = 0; 1031 1032 if (!hdev || !magic_arr) { 1033 rc = -EINVAL; 1034 goto cleanup; 1035 } 1036 1037 buf = kmemdup(magic_arr, magic_size, GFP_KERNEL); 1038 if (!buf) { 1039 rc = -ENOMEM; 1040 goto cleanup; 1041 } 1042 1043 udev = hid_to_usb_dev(hdev); 1044 pipe = usb_sndintpipe(udev, endpoint); 1045 1046 rc = usb_interrupt_msg(udev, pipe, buf, magic_size, &sent, 1000); 1047 if (rc || sent != magic_size) { 1048 hid_err(hdev, "Interface probing failed: %d\n", rc); 1049 rc = -1; 1050 goto cleanup; 1051 } 1052 1053 rc = 0; 1054 cleanup: 1055 kfree(buf); 1056 return rc; 1057 } 1058 1059 /** 1060 * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by 1061 * discovering their parameters. 1062 * 1063 * These tables, internally designed as v2 to differentiate them from older 1064 * models, expect a payload of magic data in orther to be switched to the fully 1065 * functional mode and expose their parameters in a similar way to the 1066 * information present in uclogic_params_pen_init_v1() but with some 1067 * differences. 1068 * 1069 * @params: Parameters to fill in (to be cleaned with 1070 * uclogic_params_cleanup()). Not modified in case of error. 1071 * Cannot be NULL. 1072 * @hdev: The HID device of the tablet interface to initialize and get 1073 * parameters from. Cannot be NULL. 1074 * 1075 * Returns: 1076 * Zero, if successful. A negative errno code on error. 1077 */ 1078 static int uclogic_params_ugee_v2_init(struct uclogic_params *params, 1079 struct hid_device *hdev) 1080 { 1081 int rc = 0; 1082 struct usb_interface *iface; 1083 __u8 bInterfaceNumber; 1084 const int str_desc_len = 12; 1085 __u8 *str_desc = NULL; 1086 __u8 *rdesc_pen = NULL; 1087 __u8 *rdesc_frame = NULL; 1088 s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; 1089 s32 resolution; 1090 __u8 magic_arr[] = { 1091 0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 1092 }; 1093 /* The resulting parameters (noop) */ 1094 struct uclogic_params p = {0, }; 1095 1096 if (!params || !hdev) { 1097 rc = -EINVAL; 1098 goto cleanup; 1099 } 1100 1101 iface = to_usb_interface(hdev->dev.parent); 1102 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; 1103 if (bInterfaceNumber != 2) { 1104 uclogic_params_init_invalid(&p); 1105 goto output; 1106 } 1107 1108 /* 1109 * Initialize the interface by sending magic data. 1110 * The specific data was discovered by sniffing the Windows driver 1111 * traffic. 1112 */ 1113 rc = uclogic_probe_interface(hdev, magic_arr, sizeof(magic_arr), 0x03); 1114 if (rc) { 1115 uclogic_params_init_invalid(&p); 1116 goto output; 1117 } 1118 1119 /* 1120 * Read the string descriptor containing pen and frame parameters. 1121 * The specific string descriptor and data were discovered by sniffing 1122 * the Windows driver traffic. 1123 */ 1124 rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len); 1125 if (rc != str_desc_len) { 1126 hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc); 1127 uclogic_params_init_invalid(&p); 1128 goto output; 1129 } 1130 1131 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 1132 get_unaligned_le16(str_desc + 2); 1133 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 1134 get_unaligned_le16(str_desc + 4); 1135 desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = str_desc[6]; 1136 desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 1137 get_unaligned_le16(str_desc + 8); 1138 resolution = get_unaligned_le16(str_desc + 10); 1139 if (resolution == 0) { 1140 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0; 1141 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0; 1142 } else { 1143 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 1144 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 / 1145 resolution; 1146 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 1147 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 / 1148 resolution; 1149 } 1150 kfree(str_desc); 1151 str_desc = NULL; 1152 1153 /* Initialize the pen interface */ 1154 rdesc_pen = uclogic_rdesc_template_apply( 1155 uclogic_rdesc_ugee_v2_pen_template_arr, 1156 uclogic_rdesc_ugee_v2_pen_template_size, 1157 desc_params, ARRAY_SIZE(desc_params)); 1158 if (!rdesc_pen) { 1159 rc = -ENOMEM; 1160 goto cleanup; 1161 } 1162 1163 p.pen.desc_ptr = rdesc_pen; 1164 p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size; 1165 p.pen.id = 0x02; 1166 p.pen.subreport_list[0].value = 0xf0; 1167 p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID; 1168 1169 /* Initialize the frame interface */ 1170 rdesc_frame = uclogic_rdesc_template_apply( 1171 uclogic_rdesc_ugee_v2_frame_btn_template_arr, 1172 uclogic_rdesc_ugee_v2_frame_btn_template_size, 1173 desc_params, ARRAY_SIZE(desc_params)); 1174 if (!rdesc_frame) { 1175 rc = -ENOMEM; 1176 goto cleanup; 1177 } 1178 1179 rc = uclogic_params_frame_init_with_desc(&p.frame_list[0], 1180 rdesc_frame, 1181 uclogic_rdesc_ugee_v2_frame_btn_template_size, 1182 UCLOGIC_RDESC_V1_FRAME_ID); 1183 kfree(rdesc_frame); 1184 if (rc) { 1185 uclogic_params_init_invalid(&p); 1186 goto output; 1187 } 1188 1189 output: 1190 /* Output parameters */ 1191 memcpy(params, &p, sizeof(*params)); 1192 memset(&p, 0, sizeof(p)); 1193 rc = 0; 1194 cleanup: 1195 kfree(str_desc); 1196 uclogic_params_cleanup(&p); 1197 return rc; 1198 } 1199 1200 /** 1201 * uclogic_params_init() - initialize a tablet interface and discover its 1202 * parameters. 1203 * 1204 * @params: Parameters to fill in (to be cleaned with 1205 * uclogic_params_cleanup()). Not modified in case of error. 1206 * Cannot be NULL. 1207 * @hdev: The HID device of the tablet interface to initialize and get 1208 * parameters from. Cannot be NULL. Must be using the USB low-level 1209 * driver, i.e. be an actual USB tablet. 1210 * 1211 * Returns: 1212 * Zero, if successful. A negative errno code on error. 1213 */ 1214 int uclogic_params_init(struct uclogic_params *params, 1215 struct hid_device *hdev) 1216 { 1217 int rc; 1218 struct usb_device *udev; 1219 __u8 bNumInterfaces; 1220 struct usb_interface *iface; 1221 __u8 bInterfaceNumber; 1222 bool found; 1223 /* The resulting parameters (noop) */ 1224 struct uclogic_params p = {0, }; 1225 1226 /* Check arguments */ 1227 if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) { 1228 rc = -EINVAL; 1229 goto cleanup; 1230 } 1231 1232 udev = hid_to_usb_dev(hdev); 1233 bNumInterfaces = udev->config->desc.bNumInterfaces; 1234 iface = to_usb_interface(hdev->dev.parent); 1235 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; 1236 1237 /* 1238 * Set replacement report descriptor if the original matches the 1239 * specified size. Otherwise keep interface unchanged. 1240 */ 1241 #define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \ 1242 uclogic_params_init_with_opt_desc( \ 1243 &p, hdev, \ 1244 UCLOGIC_RDESC_##_orig_desc_token##_SIZE, \ 1245 uclogic_rdesc_##_new_desc_token##_arr, \ 1246 uclogic_rdesc_##_new_desc_token##_size) 1247 1248 #define VID_PID(_vid, _pid) \ 1249 (((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX)) 1250 1251 /* 1252 * Handle specific interfaces for specific tablets. 1253 * 1254 * Observe the following logic: 1255 * 1256 * If the interface is recognized as producing certain useful input: 1257 * Mark interface as valid. 1258 * Output interface parameters. 1259 * Else, if the interface is recognized as *not* producing any useful 1260 * input: 1261 * Mark interface as invalid. 1262 * Else: 1263 * Mark interface as valid. 1264 * Output noop parameters. 1265 * 1266 * Rule of thumb: it is better to disable a broken interface than let 1267 * it spew garbage input. 1268 */ 1269 1270 switch (VID_PID(hdev->vendor, hdev->product)) { 1271 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1272 USB_DEVICE_ID_UCLOGIC_TABLET_PF1209): 1273 rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed); 1274 if (rc != 0) 1275 goto cleanup; 1276 break; 1277 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1278 USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U): 1279 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed); 1280 if (rc != 0) 1281 goto cleanup; 1282 break; 1283 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1284 USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U): 1285 if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) { 1286 if (bInterfaceNumber == 0) { 1287 /* Try to probe v1 pen parameters */ 1288 rc = uclogic_params_pen_init_v1(&p.pen, 1289 &found, hdev); 1290 if (rc != 0) { 1291 hid_err(hdev, 1292 "pen probing failed: %d\n", 1293 rc); 1294 goto cleanup; 1295 } 1296 if (!found) { 1297 hid_warn(hdev, 1298 "pen parameters not found"); 1299 } 1300 } else { 1301 uclogic_params_init_invalid(&p); 1302 } 1303 } else { 1304 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed); 1305 if (rc != 0) 1306 goto cleanup; 1307 } 1308 break; 1309 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1310 USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U): 1311 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed); 1312 if (rc != 0) 1313 goto cleanup; 1314 break; 1315 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1316 USB_DEVICE_ID_UCLOGIC_TABLET_WP1062): 1317 rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed); 1318 if (rc != 0) 1319 goto cleanup; 1320 break; 1321 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1322 USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850): 1323 switch (bInterfaceNumber) { 1324 case 0: 1325 rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0); 1326 if (rc != 0) 1327 goto cleanup; 1328 break; 1329 case 1: 1330 rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1); 1331 if (rc != 0) 1332 goto cleanup; 1333 break; 1334 case 2: 1335 rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2); 1336 if (rc != 0) 1337 goto cleanup; 1338 break; 1339 } 1340 break; 1341 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1342 USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60): 1343 /* 1344 * If it is not a three-interface version, which is known to 1345 * respond to initialization. 1346 */ 1347 if (bNumInterfaces != 3) { 1348 switch (bInterfaceNumber) { 1349 case 0: 1350 rc = WITH_OPT_DESC(TWHA60_ORIG0, 1351 twha60_fixed0); 1352 if (rc != 0) 1353 goto cleanup; 1354 break; 1355 case 1: 1356 rc = WITH_OPT_DESC(TWHA60_ORIG1, 1357 twha60_fixed1); 1358 if (rc != 0) 1359 goto cleanup; 1360 break; 1361 } 1362 break; 1363 } 1364 fallthrough; 1365 case VID_PID(USB_VENDOR_ID_HUION, 1366 USB_DEVICE_ID_HUION_TABLET): 1367 case VID_PID(USB_VENDOR_ID_HUION, 1368 USB_DEVICE_ID_HUION_TABLET2): 1369 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1370 USB_DEVICE_ID_HUION_TABLET): 1371 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1372 USB_DEVICE_ID_YIYNOVA_TABLET): 1373 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1374 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81): 1375 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1376 USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3): 1377 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1378 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45): 1379 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1380 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47): 1381 rc = uclogic_params_huion_init(&p, hdev); 1382 if (rc != 0) 1383 goto cleanup; 1384 break; 1385 case VID_PID(USB_VENDOR_ID_UGTIZER, 1386 USB_DEVICE_ID_UGTIZER_TABLET_GP0610): 1387 case VID_PID(USB_VENDOR_ID_UGTIZER, 1388 USB_DEVICE_ID_UGTIZER_TABLET_GT5040): 1389 case VID_PID(USB_VENDOR_ID_UGEE, 1390 USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540): 1391 case VID_PID(USB_VENDOR_ID_UGEE, 1392 USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640): 1393 case VID_PID(USB_VENDOR_ID_UGEE, 1394 USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06): 1395 case VID_PID(USB_VENDOR_ID_UGEE, 1396 USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720): 1397 /* If this is the pen interface */ 1398 if (bInterfaceNumber == 1) { 1399 /* Probe v1 pen parameters */ 1400 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1401 if (rc != 0) { 1402 hid_err(hdev, "pen probing failed: %d\n", rc); 1403 goto cleanup; 1404 } 1405 if (!found) { 1406 hid_warn(hdev, "pen parameters not found"); 1407 uclogic_params_init_invalid(&p); 1408 } 1409 } else { 1410 uclogic_params_init_invalid(&p); 1411 } 1412 break; 1413 case VID_PID(USB_VENDOR_ID_UGEE, 1414 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01): 1415 /* If this is the pen and frame interface */ 1416 if (bInterfaceNumber == 1) { 1417 /* Probe v1 pen parameters */ 1418 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1419 if (rc != 0) { 1420 hid_err(hdev, "pen probing failed: %d\n", rc); 1421 goto cleanup; 1422 } 1423 /* Initialize frame parameters */ 1424 rc = uclogic_params_frame_init_with_desc( 1425 &p.frame_list[0], 1426 uclogic_rdesc_xppen_deco01_frame_arr, 1427 uclogic_rdesc_xppen_deco01_frame_size, 1428 0); 1429 if (rc != 0) 1430 goto cleanup; 1431 } else { 1432 uclogic_params_init_invalid(&p); 1433 } 1434 break; 1435 case VID_PID(USB_VENDOR_ID_UGEE, 1436 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L): 1437 rc = uclogic_params_ugee_v2_init(&p, hdev); 1438 if (rc != 0) 1439 goto cleanup; 1440 break; 1441 case VID_PID(USB_VENDOR_ID_TRUST, 1442 USB_DEVICE_ID_TRUST_PANORA_TABLET): 1443 case VID_PID(USB_VENDOR_ID_UGEE, 1444 USB_DEVICE_ID_UGEE_TABLET_G5): 1445 /* Ignore non-pen interfaces */ 1446 if (bInterfaceNumber != 1) { 1447 uclogic_params_init_invalid(&p); 1448 break; 1449 } 1450 1451 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1452 if (rc != 0) { 1453 hid_err(hdev, "pen probing failed: %d\n", rc); 1454 goto cleanup; 1455 } else if (found) { 1456 rc = uclogic_params_frame_init_with_desc( 1457 &p.frame_list[0], 1458 uclogic_rdesc_ugee_g5_frame_arr, 1459 uclogic_rdesc_ugee_g5_frame_size, 1460 UCLOGIC_RDESC_UGEE_G5_FRAME_ID); 1461 if (rc != 0) { 1462 hid_err(hdev, 1463 "failed creating frame parameters: %d\n", 1464 rc); 1465 goto cleanup; 1466 } 1467 p.frame_list[0].re_lsb = 1468 UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB; 1469 p.frame_list[0].dev_id_byte = 1470 UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE; 1471 } else { 1472 hid_warn(hdev, "pen parameters not found"); 1473 uclogic_params_init_invalid(&p); 1474 } 1475 1476 break; 1477 case VID_PID(USB_VENDOR_ID_UGEE, 1478 USB_DEVICE_ID_UGEE_TABLET_EX07S): 1479 /* Ignore non-pen interfaces */ 1480 if (bInterfaceNumber != 1) { 1481 uclogic_params_init_invalid(&p); 1482 break; 1483 } 1484 1485 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1486 if (rc != 0) { 1487 hid_err(hdev, "pen probing failed: %d\n", rc); 1488 goto cleanup; 1489 } else if (found) { 1490 rc = uclogic_params_frame_init_with_desc( 1491 &p.frame_list[0], 1492 uclogic_rdesc_ugee_ex07_frame_arr, 1493 uclogic_rdesc_ugee_ex07_frame_size, 1494 0); 1495 if (rc != 0) { 1496 hid_err(hdev, 1497 "failed creating frame parameters: %d\n", 1498 rc); 1499 goto cleanup; 1500 } 1501 } else { 1502 hid_warn(hdev, "pen parameters not found"); 1503 uclogic_params_init_invalid(&p); 1504 } 1505 1506 break; 1507 } 1508 1509 #undef VID_PID 1510 #undef WITH_OPT_DESC 1511 1512 /* Output parameters */ 1513 memcpy(params, &p, sizeof(*params)); 1514 memset(&p, 0, sizeof(p)); 1515 rc = 0; 1516 cleanup: 1517 uclogic_params_cleanup(&p); 1518 return rc; 1519 } 1520