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