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_parse_ugee_v2_desc - parse the string descriptor containing 1061 * pen and frame parameters returned by UGEE v2 devices. 1062 * 1063 * @str_desc: String descriptor, cannot be NULL. 1064 * @str_desc_size: Size of the string descriptor. 1065 * @desc_params: Output description params list. 1066 * @desc_params_size: Size of the output description params list. 1067 * @frame_type: Output frame type. 1068 * 1069 * Returns: 1070 * Zero, if successful. A negative errno code on error. 1071 */ 1072 static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc, 1073 size_t str_desc_size, 1074 s32 *desc_params, 1075 size_t desc_params_size, 1076 enum uclogic_params_frame_type *frame_type) 1077 { 1078 s32 pen_x_lm, pen_y_lm; 1079 s32 pen_x_pm, pen_y_pm; 1080 s32 pen_pressure_lm; 1081 s32 frame_num_buttons; 1082 s32 resolution; 1083 1084 /* Minimum descriptor length required, maximum seen so far is 14 */ 1085 const int min_str_desc_size = 12; 1086 1087 if (!str_desc || str_desc_size < min_str_desc_size) 1088 return -EINVAL; 1089 1090 if (desc_params_size != UCLOGIC_RDESC_PH_ID_NUM) 1091 return -EINVAL; 1092 1093 pen_x_lm = get_unaligned_le16(str_desc + 2); 1094 pen_y_lm = get_unaligned_le16(str_desc + 4); 1095 frame_num_buttons = str_desc[6]; 1096 *frame_type = str_desc[7]; 1097 pen_pressure_lm = get_unaligned_le16(str_desc + 8); 1098 1099 resolution = get_unaligned_le16(str_desc + 10); 1100 if (resolution == 0) { 1101 pen_x_pm = 0; 1102 pen_y_pm = 0; 1103 } else { 1104 pen_x_pm = pen_x_lm * 1000 / resolution; 1105 pen_y_pm = pen_y_lm * 1000 / resolution; 1106 } 1107 1108 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = pen_x_lm; 1109 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = pen_x_pm; 1110 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = pen_y_lm; 1111 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = pen_y_pm; 1112 desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = pen_pressure_lm; 1113 desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = frame_num_buttons; 1114 1115 return 0; 1116 } 1117 1118 /** 1119 * uclogic_params_ugee_v2_init_frame_buttons() - initialize a UGEE v2 frame with 1120 * buttons. 1121 * @p: Parameters to fill in, cannot be NULL. 1122 * @desc_params: Device description params list. 1123 * @desc_params_size: Size of the description params list. 1124 * 1125 * Returns: 1126 * Zero, if successful. A negative errno code on error. 1127 */ 1128 static int uclogic_params_ugee_v2_init_frame_buttons(struct uclogic_params *p, 1129 const s32 *desc_params, 1130 size_t desc_params_size) 1131 { 1132 __u8 *rdesc_frame = NULL; 1133 int rc = 0; 1134 1135 if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM) 1136 return -EINVAL; 1137 1138 rdesc_frame = uclogic_rdesc_template_apply( 1139 uclogic_rdesc_ugee_v2_frame_btn_template_arr, 1140 uclogic_rdesc_ugee_v2_frame_btn_template_size, 1141 desc_params, UCLOGIC_RDESC_PH_ID_NUM); 1142 if (!rdesc_frame) 1143 return -ENOMEM; 1144 1145 rc = uclogic_params_frame_init_with_desc(&p->frame_list[0], 1146 rdesc_frame, 1147 uclogic_rdesc_ugee_v2_frame_btn_template_size, 1148 UCLOGIC_RDESC_V1_FRAME_ID); 1149 kfree(rdesc_frame); 1150 return rc; 1151 } 1152 1153 /** 1154 * uclogic_params_ugee_v2_init_frame_dial() - initialize a UGEE v2 frame with a 1155 * bitmap dial. 1156 * @p: Parameters to fill in, cannot be NULL. 1157 * @desc_params: Device description params list. 1158 * @desc_params_size: Size of the description params list. 1159 * 1160 * Returns: 1161 * Zero, if successful. A negative errno code on error. 1162 */ 1163 static int uclogic_params_ugee_v2_init_frame_dial(struct uclogic_params *p, 1164 const s32 *desc_params, 1165 size_t desc_params_size) 1166 { 1167 __u8 *rdesc_frame = NULL; 1168 int rc = 0; 1169 1170 if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM) 1171 return -EINVAL; 1172 1173 rdesc_frame = uclogic_rdesc_template_apply( 1174 uclogic_rdesc_ugee_v2_frame_dial_template_arr, 1175 uclogic_rdesc_ugee_v2_frame_dial_template_size, 1176 desc_params, UCLOGIC_RDESC_PH_ID_NUM); 1177 if (!rdesc_frame) 1178 return -ENOMEM; 1179 1180 rc = uclogic_params_frame_init_with_desc(&p->frame_list[0], 1181 rdesc_frame, 1182 uclogic_rdesc_ugee_v2_frame_dial_template_size, 1183 UCLOGIC_RDESC_V1_FRAME_ID); 1184 kfree(rdesc_frame); 1185 if (rc) 1186 return rc; 1187 1188 p->frame_list[0].bitmap_dial_byte = 7; 1189 return 0; 1190 } 1191 1192 /** 1193 * uclogic_params_ugee_v2_init_frame_mouse() - initialize a UGEE v2 frame with a 1194 * mouse. 1195 * @p: Parameters to fill in, cannot be NULL. 1196 * 1197 * Returns: 1198 * Zero, if successful. A negative errno code on error. 1199 */ 1200 static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p) 1201 { 1202 int rc = 0; 1203 1204 if (!p) 1205 return -EINVAL; 1206 1207 rc = uclogic_params_frame_init_with_desc(&p->frame_list[1], 1208 uclogic_rdesc_ugee_v2_frame_mouse_template_arr, 1209 uclogic_rdesc_ugee_v2_frame_mouse_template_size, 1210 UCLOGIC_RDESC_V1_FRAME_ID); 1211 return rc; 1212 } 1213 1214 /** 1215 * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by 1216 * discovering their parameters. 1217 * 1218 * These tables, internally designed as v2 to differentiate them from older 1219 * models, expect a payload of magic data in orther to be switched to the fully 1220 * functional mode and expose their parameters in a similar way to the 1221 * information present in uclogic_params_pen_init_v1() but with some 1222 * differences. 1223 * 1224 * @params: Parameters to fill in (to be cleaned with 1225 * uclogic_params_cleanup()). Not modified in case of error. 1226 * Cannot be NULL. 1227 * @hdev: The HID device of the tablet interface to initialize and get 1228 * parameters from. Cannot be NULL. 1229 * 1230 * Returns: 1231 * Zero, if successful. A negative errno code on error. 1232 */ 1233 static int uclogic_params_ugee_v2_init(struct uclogic_params *params, 1234 struct hid_device *hdev) 1235 { 1236 int rc = 0; 1237 struct usb_interface *iface; 1238 __u8 bInterfaceNumber; 1239 const int str_desc_len = 12; 1240 __u8 *str_desc = NULL; 1241 __u8 *rdesc_pen = NULL; 1242 s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; 1243 enum uclogic_params_frame_type frame_type; 1244 __u8 magic_arr[] = { 1245 0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 1246 }; 1247 /* The resulting parameters (noop) */ 1248 struct uclogic_params p = {0, }; 1249 1250 if (!params || !hdev) { 1251 rc = -EINVAL; 1252 goto cleanup; 1253 } 1254 1255 iface = to_usb_interface(hdev->dev.parent); 1256 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; 1257 1258 if (bInterfaceNumber == 0) { 1259 rc = uclogic_params_ugee_v2_init_frame_mouse(&p); 1260 if (rc) 1261 goto cleanup; 1262 1263 goto output; 1264 } 1265 1266 if (bInterfaceNumber != 2) { 1267 uclogic_params_init_invalid(&p); 1268 goto output; 1269 } 1270 1271 /* 1272 * Initialize the interface by sending magic data. 1273 * The specific data was discovered by sniffing the Windows driver 1274 * traffic. 1275 */ 1276 rc = uclogic_probe_interface(hdev, magic_arr, sizeof(magic_arr), 0x03); 1277 if (rc) { 1278 uclogic_params_init_invalid(&p); 1279 goto output; 1280 } 1281 1282 /* 1283 * Read the string descriptor containing pen and frame parameters. 1284 * The specific string descriptor and data were discovered by sniffing 1285 * the Windows driver traffic. 1286 */ 1287 rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len); 1288 if (rc != str_desc_len) { 1289 hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc); 1290 uclogic_params_init_invalid(&p); 1291 goto output; 1292 } 1293 1294 rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len, 1295 desc_params, 1296 ARRAY_SIZE(desc_params), 1297 &frame_type); 1298 if (rc) 1299 goto cleanup; 1300 1301 kfree(str_desc); 1302 str_desc = NULL; 1303 1304 /* Initialize the pen interface */ 1305 rdesc_pen = uclogic_rdesc_template_apply( 1306 uclogic_rdesc_ugee_v2_pen_template_arr, 1307 uclogic_rdesc_ugee_v2_pen_template_size, 1308 desc_params, ARRAY_SIZE(desc_params)); 1309 if (!rdesc_pen) { 1310 rc = -ENOMEM; 1311 goto cleanup; 1312 } 1313 1314 p.pen.desc_ptr = rdesc_pen; 1315 p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size; 1316 p.pen.id = 0x02; 1317 p.pen.subreport_list[0].value = 0xf0; 1318 p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID; 1319 1320 /* Initialize the frame interface */ 1321 switch (frame_type) { 1322 case UCLOGIC_PARAMS_FRAME_DIAL: 1323 case UCLOGIC_PARAMS_FRAME_MOUSE: 1324 rc = uclogic_params_ugee_v2_init_frame_dial(&p, desc_params, 1325 ARRAY_SIZE(desc_params)); 1326 break; 1327 case UCLOGIC_PARAMS_FRAME_BUTTONS: 1328 default: 1329 rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params, 1330 ARRAY_SIZE(desc_params)); 1331 break; 1332 } 1333 1334 if (rc) 1335 goto cleanup; 1336 1337 output: 1338 /* Output parameters */ 1339 memcpy(params, &p, sizeof(*params)); 1340 memset(&p, 0, sizeof(p)); 1341 rc = 0; 1342 cleanup: 1343 kfree(str_desc); 1344 uclogic_params_cleanup(&p); 1345 return rc; 1346 } 1347 1348 /** 1349 * uclogic_params_init() - initialize a tablet interface and discover its 1350 * parameters. 1351 * 1352 * @params: Parameters to fill in (to be cleaned with 1353 * uclogic_params_cleanup()). Not modified in case of error. 1354 * Cannot be NULL. 1355 * @hdev: The HID device of the tablet interface to initialize and get 1356 * parameters from. Cannot be NULL. Must be using the USB low-level 1357 * driver, i.e. be an actual USB tablet. 1358 * 1359 * Returns: 1360 * Zero, if successful. A negative errno code on error. 1361 */ 1362 int uclogic_params_init(struct uclogic_params *params, 1363 struct hid_device *hdev) 1364 { 1365 int rc; 1366 struct usb_device *udev; 1367 __u8 bNumInterfaces; 1368 struct usb_interface *iface; 1369 __u8 bInterfaceNumber; 1370 bool found; 1371 /* The resulting parameters (noop) */ 1372 struct uclogic_params p = {0, }; 1373 1374 /* Check arguments */ 1375 if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) { 1376 rc = -EINVAL; 1377 goto cleanup; 1378 } 1379 1380 udev = hid_to_usb_dev(hdev); 1381 bNumInterfaces = udev->config->desc.bNumInterfaces; 1382 iface = to_usb_interface(hdev->dev.parent); 1383 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; 1384 1385 /* 1386 * Set replacement report descriptor if the original matches the 1387 * specified size. Otherwise keep interface unchanged. 1388 */ 1389 #define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \ 1390 uclogic_params_init_with_opt_desc( \ 1391 &p, hdev, \ 1392 UCLOGIC_RDESC_##_orig_desc_token##_SIZE, \ 1393 uclogic_rdesc_##_new_desc_token##_arr, \ 1394 uclogic_rdesc_##_new_desc_token##_size) 1395 1396 #define VID_PID(_vid, _pid) \ 1397 (((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX)) 1398 1399 /* 1400 * Handle specific interfaces for specific tablets. 1401 * 1402 * Observe the following logic: 1403 * 1404 * If the interface is recognized as producing certain useful input: 1405 * Mark interface as valid. 1406 * Output interface parameters. 1407 * Else, if the interface is recognized as *not* producing any useful 1408 * input: 1409 * Mark interface as invalid. 1410 * Else: 1411 * Mark interface as valid. 1412 * Output noop parameters. 1413 * 1414 * Rule of thumb: it is better to disable a broken interface than let 1415 * it spew garbage input. 1416 */ 1417 1418 switch (VID_PID(hdev->vendor, hdev->product)) { 1419 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1420 USB_DEVICE_ID_UCLOGIC_TABLET_PF1209): 1421 rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed); 1422 if (rc != 0) 1423 goto cleanup; 1424 break; 1425 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1426 USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U): 1427 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed); 1428 if (rc != 0) 1429 goto cleanup; 1430 break; 1431 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1432 USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U): 1433 if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) { 1434 if (bInterfaceNumber == 0) { 1435 /* Try to probe v1 pen parameters */ 1436 rc = uclogic_params_pen_init_v1(&p.pen, 1437 &found, hdev); 1438 if (rc != 0) { 1439 hid_err(hdev, 1440 "pen probing failed: %d\n", 1441 rc); 1442 goto cleanup; 1443 } 1444 if (!found) { 1445 hid_warn(hdev, 1446 "pen parameters not found"); 1447 } 1448 } else { 1449 uclogic_params_init_invalid(&p); 1450 } 1451 } else { 1452 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed); 1453 if (rc != 0) 1454 goto cleanup; 1455 } 1456 break; 1457 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1458 USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U): 1459 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed); 1460 if (rc != 0) 1461 goto cleanup; 1462 break; 1463 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1464 USB_DEVICE_ID_UCLOGIC_TABLET_WP1062): 1465 rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed); 1466 if (rc != 0) 1467 goto cleanup; 1468 break; 1469 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1470 USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850): 1471 switch (bInterfaceNumber) { 1472 case 0: 1473 rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0); 1474 if (rc != 0) 1475 goto cleanup; 1476 break; 1477 case 1: 1478 rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1); 1479 if (rc != 0) 1480 goto cleanup; 1481 break; 1482 case 2: 1483 rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2); 1484 if (rc != 0) 1485 goto cleanup; 1486 break; 1487 } 1488 break; 1489 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1490 USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60): 1491 /* 1492 * If it is not a three-interface version, which is known to 1493 * respond to initialization. 1494 */ 1495 if (bNumInterfaces != 3) { 1496 switch (bInterfaceNumber) { 1497 case 0: 1498 rc = WITH_OPT_DESC(TWHA60_ORIG0, 1499 twha60_fixed0); 1500 if (rc != 0) 1501 goto cleanup; 1502 break; 1503 case 1: 1504 rc = WITH_OPT_DESC(TWHA60_ORIG1, 1505 twha60_fixed1); 1506 if (rc != 0) 1507 goto cleanup; 1508 break; 1509 } 1510 break; 1511 } 1512 fallthrough; 1513 case VID_PID(USB_VENDOR_ID_HUION, 1514 USB_DEVICE_ID_HUION_TABLET): 1515 case VID_PID(USB_VENDOR_ID_HUION, 1516 USB_DEVICE_ID_HUION_TABLET2): 1517 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1518 USB_DEVICE_ID_HUION_TABLET): 1519 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1520 USB_DEVICE_ID_YIYNOVA_TABLET): 1521 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1522 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81): 1523 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1524 USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3): 1525 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1526 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45): 1527 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1528 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47): 1529 rc = uclogic_params_huion_init(&p, hdev); 1530 if (rc != 0) 1531 goto cleanup; 1532 break; 1533 case VID_PID(USB_VENDOR_ID_UGTIZER, 1534 USB_DEVICE_ID_UGTIZER_TABLET_GP0610): 1535 case VID_PID(USB_VENDOR_ID_UGTIZER, 1536 USB_DEVICE_ID_UGTIZER_TABLET_GT5040): 1537 case VID_PID(USB_VENDOR_ID_UGEE, 1538 USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540): 1539 case VID_PID(USB_VENDOR_ID_UGEE, 1540 USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640): 1541 case VID_PID(USB_VENDOR_ID_UGEE, 1542 USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06): 1543 case VID_PID(USB_VENDOR_ID_UGEE, 1544 USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720): 1545 /* If this is the pen interface */ 1546 if (bInterfaceNumber == 1) { 1547 /* Probe v1 pen parameters */ 1548 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1549 if (rc != 0) { 1550 hid_err(hdev, "pen probing failed: %d\n", rc); 1551 goto cleanup; 1552 } 1553 if (!found) { 1554 hid_warn(hdev, "pen parameters not found"); 1555 uclogic_params_init_invalid(&p); 1556 } 1557 } else { 1558 uclogic_params_init_invalid(&p); 1559 } 1560 break; 1561 case VID_PID(USB_VENDOR_ID_UGEE, 1562 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01): 1563 /* If this is the pen and frame interface */ 1564 if (bInterfaceNumber == 1) { 1565 /* Probe v1 pen parameters */ 1566 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1567 if (rc != 0) { 1568 hid_err(hdev, "pen probing failed: %d\n", rc); 1569 goto cleanup; 1570 } 1571 /* Initialize frame parameters */ 1572 rc = uclogic_params_frame_init_with_desc( 1573 &p.frame_list[0], 1574 uclogic_rdesc_xppen_deco01_frame_arr, 1575 uclogic_rdesc_xppen_deco01_frame_size, 1576 0); 1577 if (rc != 0) 1578 goto cleanup; 1579 } else { 1580 uclogic_params_init_invalid(&p); 1581 } 1582 break; 1583 case VID_PID(USB_VENDOR_ID_UGEE, 1584 USB_DEVICE_ID_UGEE_PARBLO_A610_PRO): 1585 case VID_PID(USB_VENDOR_ID_UGEE, 1586 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L): 1587 case VID_PID(USB_VENDOR_ID_UGEE, 1588 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S): 1589 rc = uclogic_params_ugee_v2_init(&p, hdev); 1590 if (rc != 0) 1591 goto cleanup; 1592 break; 1593 case VID_PID(USB_VENDOR_ID_TRUST, 1594 USB_DEVICE_ID_TRUST_PANORA_TABLET): 1595 case VID_PID(USB_VENDOR_ID_UGEE, 1596 USB_DEVICE_ID_UGEE_TABLET_G5): 1597 /* Ignore non-pen interfaces */ 1598 if (bInterfaceNumber != 1) { 1599 uclogic_params_init_invalid(&p); 1600 break; 1601 } 1602 1603 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1604 if (rc != 0) { 1605 hid_err(hdev, "pen probing failed: %d\n", rc); 1606 goto cleanup; 1607 } else if (found) { 1608 rc = uclogic_params_frame_init_with_desc( 1609 &p.frame_list[0], 1610 uclogic_rdesc_ugee_g5_frame_arr, 1611 uclogic_rdesc_ugee_g5_frame_size, 1612 UCLOGIC_RDESC_UGEE_G5_FRAME_ID); 1613 if (rc != 0) { 1614 hid_err(hdev, 1615 "failed creating frame parameters: %d\n", 1616 rc); 1617 goto cleanup; 1618 } 1619 p.frame_list[0].re_lsb = 1620 UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB; 1621 p.frame_list[0].dev_id_byte = 1622 UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE; 1623 } else { 1624 hid_warn(hdev, "pen parameters not found"); 1625 uclogic_params_init_invalid(&p); 1626 } 1627 1628 break; 1629 case VID_PID(USB_VENDOR_ID_UGEE, 1630 USB_DEVICE_ID_UGEE_TABLET_EX07S): 1631 /* Ignore non-pen interfaces */ 1632 if (bInterfaceNumber != 1) { 1633 uclogic_params_init_invalid(&p); 1634 break; 1635 } 1636 1637 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1638 if (rc != 0) { 1639 hid_err(hdev, "pen probing failed: %d\n", rc); 1640 goto cleanup; 1641 } else if (found) { 1642 rc = uclogic_params_frame_init_with_desc( 1643 &p.frame_list[0], 1644 uclogic_rdesc_ugee_ex07_frame_arr, 1645 uclogic_rdesc_ugee_ex07_frame_size, 1646 0); 1647 if (rc != 0) { 1648 hid_err(hdev, 1649 "failed creating frame parameters: %d\n", 1650 rc); 1651 goto cleanup; 1652 } 1653 } else { 1654 hid_warn(hdev, "pen parameters not found"); 1655 uclogic_params_init_invalid(&p); 1656 } 1657 1658 break; 1659 } 1660 1661 #undef VID_PID 1662 #undef WITH_OPT_DESC 1663 1664 /* Output parameters */ 1665 memcpy(params, &p, sizeof(*params)); 1666 memset(&p, 0, sizeof(p)); 1667 rc = 0; 1668 cleanup: 1669 uclogic_params_cleanup(&p); 1670 return rc; 1671 } 1672 1673 #ifdef CONFIG_HID_KUNIT_TEST 1674 #include "hid-uclogic-params-test.c" 1675 #endif 1676