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 <linux/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_event_hooks - free resources used by the list of raw 620 * event hooks. 621 * Can be called repeatedly. 622 * 623 * @params: Input parameters to cleanup. Cannot be NULL. 624 */ 625 static void uclogic_params_cleanup_event_hooks(struct uclogic_params *params) 626 { 627 struct uclogic_raw_event_hook *curr, *n; 628 629 if (!params || !params->event_hooks) 630 return; 631 632 list_for_each_entry_safe(curr, n, ¶ms->event_hooks->list, list) { 633 cancel_work_sync(&curr->work); 634 list_del(&curr->list); 635 kfree(curr->event); 636 kfree(curr); 637 } 638 639 kfree(params->event_hooks); 640 params->event_hooks = NULL; 641 } 642 643 /** 644 * uclogic_params_cleanup - free resources used by struct uclogic_params 645 * (tablet interface's parameters). 646 * Can be called repeatedly. 647 * 648 * @params: Input parameters to cleanup. Cannot be NULL. 649 */ 650 void uclogic_params_cleanup(struct uclogic_params *params) 651 { 652 if (!params->invalid) { 653 size_t i; 654 kfree(params->desc_ptr); 655 uclogic_params_pen_cleanup(¶ms->pen); 656 for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) 657 uclogic_params_frame_cleanup(¶ms->frame_list[i]); 658 659 uclogic_params_cleanup_event_hooks(params); 660 memset(params, 0, sizeof(*params)); 661 } 662 } 663 664 /** 665 * uclogic_params_get_desc() - Get a replacement report descriptor for a 666 * tablet's interface. 667 * 668 * @params: The parameters of a tablet interface to get report 669 * descriptor for. Cannot be NULL. 670 * @pdesc: Location for the resulting, kmalloc-allocated report 671 * descriptor pointer, or for NULL, if there's no replacement 672 * report descriptor. Not modified in case of error. Cannot be 673 * NULL. 674 * @psize: Location for the resulting report descriptor size, not set if 675 * there's no replacement report descriptor. Not modified in case 676 * of error. Cannot be NULL. 677 * 678 * Returns: 679 * Zero, if successful. 680 * -EINVAL, if invalid arguments are supplied. 681 * -ENOMEM, if failed to allocate memory. 682 */ 683 int uclogic_params_get_desc(const struct uclogic_params *params, 684 const __u8 **pdesc, 685 unsigned int *psize) 686 { 687 int rc = -ENOMEM; 688 bool present = false; 689 unsigned int size = 0; 690 __u8 *desc = NULL; 691 size_t i; 692 693 /* Check arguments */ 694 if (params == NULL || pdesc == NULL || psize == NULL) 695 return -EINVAL; 696 697 /* Concatenate descriptors */ 698 #define ADD_DESC(_desc_ptr, _desc_size) \ 699 do { \ 700 unsigned int new_size; \ 701 __u8 *new_desc; \ 702 if ((_desc_ptr) == NULL) { \ 703 break; \ 704 } \ 705 new_size = size + (_desc_size); \ 706 new_desc = krealloc(desc, new_size, GFP_KERNEL); \ 707 if (new_desc == NULL) { \ 708 goto cleanup; \ 709 } \ 710 memcpy(new_desc + size, (_desc_ptr), (_desc_size)); \ 711 desc = new_desc; \ 712 size = new_size; \ 713 present = true; \ 714 } while (0) 715 716 ADD_DESC(params->desc_ptr, params->desc_size); 717 ADD_DESC(params->pen.desc_ptr, params->pen.desc_size); 718 for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) { 719 ADD_DESC(params->frame_list[i].desc_ptr, 720 params->frame_list[i].desc_size); 721 } 722 723 #undef ADD_DESC 724 725 if (present) { 726 *pdesc = desc; 727 *psize = size; 728 desc = NULL; 729 } 730 rc = 0; 731 cleanup: 732 kfree(desc); 733 return rc; 734 } 735 736 /** 737 * uclogic_params_init_invalid() - initialize tablet interface parameters, 738 * specifying the interface is invalid. 739 * 740 * @params: Parameters to initialize (to be cleaned with 741 * uclogic_params_cleanup()). Cannot be NULL. 742 */ 743 static void uclogic_params_init_invalid(struct uclogic_params *params) 744 { 745 params->invalid = true; 746 } 747 748 /** 749 * uclogic_params_init_with_opt_desc() - initialize tablet interface 750 * parameters with an optional replacement report descriptor. Only modify 751 * report descriptor, if the original report descriptor matches the expected 752 * size. 753 * 754 * @params: Parameters to initialize (to be cleaned with 755 * uclogic_params_cleanup()). Not modified in case of 756 * error. Cannot be NULL. 757 * @hdev: The HID device of the tablet interface create the 758 * parameters for. Cannot be NULL. 759 * @orig_desc_size: Expected size of the original report descriptor to 760 * be replaced. 761 * @desc_ptr: Pointer to the replacement report descriptor. 762 * Can be NULL, if desc_size is zero. 763 * @desc_size: Size of the replacement report descriptor. 764 * 765 * Returns: 766 * Zero, if successful. -EINVAL if an invalid argument was passed. 767 * -ENOMEM, if failed to allocate memory. 768 */ 769 static int uclogic_params_init_with_opt_desc(struct uclogic_params *params, 770 struct hid_device *hdev, 771 unsigned int orig_desc_size, 772 const __u8 *desc_ptr, 773 unsigned int desc_size) 774 { 775 __u8 *desc_copy_ptr = NULL; 776 unsigned int desc_copy_size; 777 int rc; 778 779 /* Check arguments */ 780 if (params == NULL || hdev == NULL || 781 (desc_ptr == NULL && desc_size != 0)) { 782 rc = -EINVAL; 783 goto cleanup; 784 } 785 786 /* Replace report descriptor, if it matches */ 787 if (hdev->dev_rsize == orig_desc_size) { 788 hid_dbg(hdev, 789 "device report descriptor matches the expected size, replacing\n"); 790 desc_copy_ptr = kmemdup(desc_ptr, desc_size, GFP_KERNEL); 791 if (desc_copy_ptr == NULL) { 792 rc = -ENOMEM; 793 goto cleanup; 794 } 795 desc_copy_size = desc_size; 796 } else { 797 hid_dbg(hdev, 798 "device report descriptor doesn't match the expected size (%u != %u), preserving\n", 799 hdev->dev_rsize, orig_desc_size); 800 desc_copy_ptr = NULL; 801 desc_copy_size = 0; 802 } 803 804 /* Output parameters */ 805 memset(params, 0, sizeof(*params)); 806 params->desc_ptr = desc_copy_ptr; 807 desc_copy_ptr = NULL; 808 params->desc_size = desc_copy_size; 809 810 rc = 0; 811 cleanup: 812 kfree(desc_copy_ptr); 813 return rc; 814 } 815 816 /** 817 * uclogic_params_huion_init() - initialize a Huion tablet interface and discover 818 * its parameters. 819 * 820 * @params: Parameters to fill in (to be cleaned with 821 * uclogic_params_cleanup()). Not modified in case of error. 822 * Cannot be NULL. 823 * @hdev: The HID device of the tablet interface to initialize and get 824 * parameters from. Cannot be NULL. 825 * 826 * Returns: 827 * Zero, if successful. A negative errno code on error. 828 */ 829 static int uclogic_params_huion_init(struct uclogic_params *params, 830 struct hid_device *hdev) 831 { 832 int rc; 833 struct usb_device *udev; 834 struct usb_interface *iface; 835 __u8 bInterfaceNumber; 836 bool found; 837 /* The resulting parameters (noop) */ 838 struct uclogic_params p = {0, }; 839 static const char transition_ver[] = "HUION_T153_160607"; 840 char *ver_ptr = NULL; 841 const size_t ver_len = sizeof(transition_ver) + 1; 842 __u8 *params_ptr = NULL; 843 size_t params_len = 0; 844 /* Parameters string descriptor of a model with touch ring (HS610) */ 845 const __u8 touch_ring_model_params_buf[] = { 846 0x13, 0x03, 0x70, 0xC6, 0x00, 0x06, 0x7C, 0x00, 847 0xFF, 0x1F, 0xD8, 0x13, 0x03, 0x0D, 0x10, 0x01, 848 0x04, 0x3C, 0x3E 849 }; 850 851 /* Check arguments */ 852 if (params == NULL || hdev == NULL) { 853 rc = -EINVAL; 854 goto cleanup; 855 } 856 857 udev = hid_to_usb_dev(hdev); 858 iface = to_usb_interface(hdev->dev.parent); 859 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; 860 861 /* If it's a custom keyboard interface */ 862 if (bInterfaceNumber == 1) { 863 /* Keep everything intact, but mark pen usage invalid */ 864 p.pen.usage_invalid = true; 865 goto output; 866 /* Else, if it's not a pen interface */ 867 } else if (bInterfaceNumber != 0) { 868 uclogic_params_init_invalid(&p); 869 goto output; 870 } 871 872 /* Try to get firmware version */ 873 ver_ptr = kzalloc(ver_len, GFP_KERNEL); 874 if (ver_ptr == NULL) { 875 rc = -ENOMEM; 876 goto cleanup; 877 } 878 rc = usb_string(udev, 201, ver_ptr, ver_len); 879 if (rc == -EPIPE) { 880 *ver_ptr = '\0'; 881 } else if (rc < 0) { 882 hid_err(hdev, 883 "failed retrieving Huion firmware version: %d\n", rc); 884 goto cleanup; 885 } 886 887 /* The firmware is used in userspace as unique identifier */ 888 strscpy(hdev->uniq, ver_ptr, sizeof(hdev->uniq)); 889 890 /* If this is a transition firmware */ 891 if (strcmp(ver_ptr, transition_ver) == 0) { 892 hid_dbg(hdev, 893 "transition firmware detected, not probing pen v2 parameters\n"); 894 } else { 895 /* Try to probe v2 pen parameters */ 896 rc = uclogic_params_pen_init_v2(&p.pen, &found, 897 ¶ms_ptr, ¶ms_len, 898 hdev); 899 if (rc != 0) { 900 hid_err(hdev, 901 "failed probing pen v2 parameters: %d\n", rc); 902 goto cleanup; 903 } else if (found) { 904 hid_dbg(hdev, "pen v2 parameters found\n"); 905 /* Create v2 frame button parameters */ 906 rc = uclogic_params_frame_init_with_desc( 907 &p.frame_list[0], 908 uclogic_rdesc_v2_frame_buttons_arr, 909 uclogic_rdesc_v2_frame_buttons_size, 910 UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID); 911 if (rc != 0) { 912 hid_err(hdev, 913 "failed creating v2 frame button parameters: %d\n", 914 rc); 915 goto cleanup; 916 } 917 918 /* Link from pen sub-report */ 919 p.pen.subreport_list[0].value = 0xe0; 920 p.pen.subreport_list[0].id = 921 UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID; 922 923 /* If this is the model with touch ring */ 924 if (params_ptr != NULL && 925 params_len == sizeof(touch_ring_model_params_buf) && 926 memcmp(params_ptr, touch_ring_model_params_buf, 927 params_len) == 0) { 928 /* Create touch ring parameters */ 929 rc = uclogic_params_frame_init_with_desc( 930 &p.frame_list[1], 931 uclogic_rdesc_v2_frame_touch_ring_arr, 932 uclogic_rdesc_v2_frame_touch_ring_size, 933 UCLOGIC_RDESC_V2_FRAME_TOUCH_ID); 934 if (rc != 0) { 935 hid_err(hdev, 936 "failed creating v2 frame touch ring parameters: %d\n", 937 rc); 938 goto cleanup; 939 } 940 p.frame_list[1].suffix = "Touch Ring"; 941 p.frame_list[1].dev_id_byte = 942 UCLOGIC_RDESC_V2_FRAME_TOUCH_DEV_ID_BYTE; 943 p.frame_list[1].touch_byte = 5; 944 p.frame_list[1].touch_max = 12; 945 p.frame_list[1].touch_flip_at = 7; 946 } else { 947 /* Create touch strip parameters */ 948 rc = uclogic_params_frame_init_with_desc( 949 &p.frame_list[1], 950 uclogic_rdesc_v2_frame_touch_strip_arr, 951 uclogic_rdesc_v2_frame_touch_strip_size, 952 UCLOGIC_RDESC_V2_FRAME_TOUCH_ID); 953 if (rc != 0) { 954 hid_err(hdev, 955 "failed creating v2 frame touch strip parameters: %d\n", 956 rc); 957 goto cleanup; 958 } 959 p.frame_list[1].suffix = "Touch Strip"; 960 p.frame_list[1].dev_id_byte = 961 UCLOGIC_RDESC_V2_FRAME_TOUCH_DEV_ID_BYTE; 962 p.frame_list[1].touch_byte = 5; 963 p.frame_list[1].touch_max = 8; 964 } 965 966 /* Link from pen sub-report */ 967 p.pen.subreport_list[1].value = 0xf0; 968 p.pen.subreport_list[1].id = 969 UCLOGIC_RDESC_V2_FRAME_TOUCH_ID; 970 971 /* Create v2 frame dial parameters */ 972 rc = uclogic_params_frame_init_with_desc( 973 &p.frame_list[2], 974 uclogic_rdesc_v2_frame_dial_arr, 975 uclogic_rdesc_v2_frame_dial_size, 976 UCLOGIC_RDESC_V2_FRAME_DIAL_ID); 977 if (rc != 0) { 978 hid_err(hdev, 979 "failed creating v2 frame dial parameters: %d\n", 980 rc); 981 goto cleanup; 982 } 983 p.frame_list[2].suffix = "Dial"; 984 p.frame_list[2].dev_id_byte = 985 UCLOGIC_RDESC_V2_FRAME_DIAL_DEV_ID_BYTE; 986 p.frame_list[2].bitmap_dial_byte = 5; 987 988 /* Link from pen sub-report */ 989 p.pen.subreport_list[2].value = 0xf1; 990 p.pen.subreport_list[2].id = 991 UCLOGIC_RDESC_V2_FRAME_DIAL_ID; 992 993 goto output; 994 } 995 hid_dbg(hdev, "pen v2 parameters not found\n"); 996 } 997 998 /* Try to probe v1 pen parameters */ 999 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1000 if (rc != 0) { 1001 hid_err(hdev, 1002 "failed probing pen v1 parameters: %d\n", rc); 1003 goto cleanup; 1004 } else if (found) { 1005 hid_dbg(hdev, "pen v1 parameters found\n"); 1006 /* Try to probe v1 frame */ 1007 rc = uclogic_params_frame_init_v1(&p.frame_list[0], 1008 &found, hdev); 1009 if (rc != 0) { 1010 hid_err(hdev, "v1 frame probing failed: %d\n", rc); 1011 goto cleanup; 1012 } 1013 hid_dbg(hdev, "frame v1 parameters%s found\n", 1014 (found ? "" : " not")); 1015 if (found) { 1016 /* Link frame button subreports from pen reports */ 1017 p.pen.subreport_list[0].value = 0xe0; 1018 p.pen.subreport_list[0].id = 1019 UCLOGIC_RDESC_V1_FRAME_ID; 1020 } 1021 goto output; 1022 } 1023 hid_dbg(hdev, "pen v1 parameters not found\n"); 1024 1025 uclogic_params_init_invalid(&p); 1026 1027 output: 1028 /* Output parameters */ 1029 memcpy(params, &p, sizeof(*params)); 1030 memset(&p, 0, sizeof(p)); 1031 rc = 0; 1032 cleanup: 1033 kfree(params_ptr); 1034 kfree(ver_ptr); 1035 uclogic_params_cleanup(&p); 1036 return rc; 1037 } 1038 1039 /** 1040 * uclogic_probe_interface() - some tablets, like the Parblo A610 PLUS V2 or 1041 * the XP-PEN Deco Mini 7, need to be initialized by sending them magic data. 1042 * 1043 * @hdev: The HID device of the tablet interface to initialize and get 1044 * parameters from. Cannot be NULL. 1045 * @magic_arr: The magic data that should be sent to probe the interface. 1046 * Cannot be NULL. 1047 * @magic_size: Size of the magic data. 1048 * @endpoint: Endpoint where the magic data should be sent. 1049 * 1050 * Returns: 1051 * Zero, if successful. A negative errno code on error. 1052 */ 1053 static int uclogic_probe_interface(struct hid_device *hdev, const u8 *magic_arr, 1054 size_t magic_size, int endpoint) 1055 { 1056 struct usb_device *udev; 1057 unsigned int pipe = 0; 1058 int sent; 1059 u8 *buf = NULL; 1060 int rc = 0; 1061 1062 if (!hdev || !magic_arr) { 1063 rc = -EINVAL; 1064 goto cleanup; 1065 } 1066 1067 buf = kmemdup(magic_arr, magic_size, GFP_KERNEL); 1068 if (!buf) { 1069 rc = -ENOMEM; 1070 goto cleanup; 1071 } 1072 1073 udev = hid_to_usb_dev(hdev); 1074 pipe = usb_sndintpipe(udev, endpoint); 1075 1076 rc = usb_interrupt_msg(udev, pipe, buf, magic_size, &sent, 1000); 1077 if (rc || sent != magic_size) { 1078 hid_err(hdev, "Interface probing failed: %d\n", rc); 1079 rc = -1; 1080 goto cleanup; 1081 } 1082 1083 rc = 0; 1084 cleanup: 1085 kfree(buf); 1086 return rc; 1087 } 1088 1089 /** 1090 * uclogic_params_parse_ugee_v2_desc - parse the string descriptor containing 1091 * pen and frame parameters returned by UGEE v2 devices. 1092 * 1093 * @str_desc: String descriptor, cannot be NULL. 1094 * @str_desc_size: Size of the string descriptor. 1095 * @desc_params: Output description params list. 1096 * @desc_params_size: Size of the output description params list. 1097 * @frame_type: Output frame type. 1098 * 1099 * Returns: 1100 * Zero, if successful. A negative errno code on error. 1101 */ 1102 static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc, 1103 size_t str_desc_size, 1104 s32 *desc_params, 1105 size_t desc_params_size, 1106 enum uclogic_params_frame_type *frame_type) 1107 { 1108 s32 pen_x_lm, pen_y_lm; 1109 s32 pen_x_pm, pen_y_pm; 1110 s32 pen_pressure_lm; 1111 s32 frame_num_buttons; 1112 s32 resolution; 1113 1114 /* Minimum descriptor length required, maximum seen so far is 14 */ 1115 const int min_str_desc_size = 12; 1116 1117 if (!str_desc || str_desc_size < min_str_desc_size) 1118 return -EINVAL; 1119 1120 if (desc_params_size != UCLOGIC_RDESC_PH_ID_NUM) 1121 return -EINVAL; 1122 1123 pen_x_lm = get_unaligned_le16(str_desc + 2); 1124 pen_y_lm = get_unaligned_le16(str_desc + 4); 1125 frame_num_buttons = str_desc[6]; 1126 *frame_type = str_desc[7]; 1127 pen_pressure_lm = get_unaligned_le16(str_desc + 8); 1128 1129 resolution = get_unaligned_le16(str_desc + 10); 1130 if (resolution == 0) { 1131 pen_x_pm = 0; 1132 pen_y_pm = 0; 1133 } else { 1134 pen_x_pm = pen_x_lm * 1000 / resolution; 1135 pen_y_pm = pen_y_lm * 1000 / resolution; 1136 } 1137 1138 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = pen_x_lm; 1139 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = pen_x_pm; 1140 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = pen_y_lm; 1141 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = pen_y_pm; 1142 desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = pen_pressure_lm; 1143 desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = frame_num_buttons; 1144 1145 return 0; 1146 } 1147 1148 /** 1149 * uclogic_params_ugee_v2_init_frame_buttons() - initialize a UGEE v2 frame with 1150 * buttons. 1151 * @p: Parameters to fill in, cannot be NULL. 1152 * @desc_params: Device description params list. 1153 * @desc_params_size: Size of the description params list. 1154 * 1155 * Returns: 1156 * Zero, if successful. A negative errno code on error. 1157 */ 1158 static int uclogic_params_ugee_v2_init_frame_buttons(struct uclogic_params *p, 1159 const s32 *desc_params, 1160 size_t desc_params_size) 1161 { 1162 __u8 *rdesc_frame = NULL; 1163 int rc = 0; 1164 1165 if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM) 1166 return -EINVAL; 1167 1168 rdesc_frame = uclogic_rdesc_template_apply( 1169 uclogic_rdesc_ugee_v2_frame_btn_template_arr, 1170 uclogic_rdesc_ugee_v2_frame_btn_template_size, 1171 desc_params, UCLOGIC_RDESC_PH_ID_NUM); 1172 if (!rdesc_frame) 1173 return -ENOMEM; 1174 1175 rc = uclogic_params_frame_init_with_desc(&p->frame_list[0], 1176 rdesc_frame, 1177 uclogic_rdesc_ugee_v2_frame_btn_template_size, 1178 UCLOGIC_RDESC_V1_FRAME_ID); 1179 kfree(rdesc_frame); 1180 return rc; 1181 } 1182 1183 /** 1184 * uclogic_params_ugee_v2_init_frame_dial() - initialize a UGEE v2 frame with a 1185 * bitmap dial. 1186 * @p: Parameters to fill in, cannot be NULL. 1187 * @desc_params: Device description params list. 1188 * @desc_params_size: Size of the description params list. 1189 * 1190 * Returns: 1191 * Zero, if successful. A negative errno code on error. 1192 */ 1193 static int uclogic_params_ugee_v2_init_frame_dial(struct uclogic_params *p, 1194 const s32 *desc_params, 1195 size_t desc_params_size) 1196 { 1197 __u8 *rdesc_frame = NULL; 1198 int rc = 0; 1199 1200 if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM) 1201 return -EINVAL; 1202 1203 rdesc_frame = uclogic_rdesc_template_apply( 1204 uclogic_rdesc_ugee_v2_frame_dial_template_arr, 1205 uclogic_rdesc_ugee_v2_frame_dial_template_size, 1206 desc_params, UCLOGIC_RDESC_PH_ID_NUM); 1207 if (!rdesc_frame) 1208 return -ENOMEM; 1209 1210 rc = uclogic_params_frame_init_with_desc(&p->frame_list[0], 1211 rdesc_frame, 1212 uclogic_rdesc_ugee_v2_frame_dial_template_size, 1213 UCLOGIC_RDESC_V1_FRAME_ID); 1214 kfree(rdesc_frame); 1215 if (rc) 1216 return rc; 1217 1218 p->frame_list[0].bitmap_dial_byte = 7; 1219 return 0; 1220 } 1221 1222 /** 1223 * uclogic_params_ugee_v2_init_frame_mouse() - initialize a UGEE v2 frame with a 1224 * mouse. 1225 * @p: Parameters to fill in, cannot be NULL. 1226 * 1227 * Returns: 1228 * Zero, if successful. A negative errno code on error. 1229 */ 1230 static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p) 1231 { 1232 int rc = 0; 1233 1234 if (!p) 1235 return -EINVAL; 1236 1237 rc = uclogic_params_frame_init_with_desc(&p->frame_list[1], 1238 uclogic_rdesc_ugee_v2_frame_mouse_template_arr, 1239 uclogic_rdesc_ugee_v2_frame_mouse_template_size, 1240 UCLOGIC_RDESC_V1_FRAME_ID); 1241 return rc; 1242 } 1243 1244 /** 1245 * uclogic_params_ugee_v2_has_battery() - check whether a UGEE v2 device has 1246 * battery or not. 1247 * @hdev: The HID device of the tablet interface. 1248 * 1249 * Returns: 1250 * True if the device has battery, false otherwise. 1251 */ 1252 static bool uclogic_params_ugee_v2_has_battery(struct hid_device *hdev) 1253 { 1254 struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); 1255 1256 if (drvdata->quirks & UCLOGIC_BATTERY_QUIRK) 1257 return true; 1258 1259 /* The XP-PEN Deco LW vendor, product and version are identical to the 1260 * Deco L. The only difference reported by their firmware is the product 1261 * name. Add a quirk to support battery reporting on the wireless 1262 * version. 1263 */ 1264 if (hdev->vendor == USB_VENDOR_ID_UGEE && 1265 hdev->product == USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) { 1266 struct usb_device *udev = hid_to_usb_dev(hdev); 1267 1268 if (strstarts(udev->product, "Deco LW")) 1269 return true; 1270 } 1271 1272 return false; 1273 } 1274 1275 /** 1276 * uclogic_params_ugee_v2_init_battery() - initialize UGEE v2 battery reporting. 1277 * @hdev: The HID device of the tablet interface, cannot be NULL. 1278 * @p: Parameters to fill in, cannot be NULL. 1279 * 1280 * Returns: 1281 * Zero, if successful. A negative errno code on error. 1282 */ 1283 static int uclogic_params_ugee_v2_init_battery(struct hid_device *hdev, 1284 struct uclogic_params *p) 1285 { 1286 int rc = 0; 1287 1288 if (!hdev || !p) 1289 return -EINVAL; 1290 1291 /* Some tablets contain invalid characters in hdev->uniq, throwing a 1292 * "hwmon: '<name>' is not a valid name attribute, please fix" error. 1293 * Use the device vendor and product IDs instead. 1294 */ 1295 snprintf(hdev->uniq, sizeof(hdev->uniq), "%x-%x", hdev->vendor, 1296 hdev->product); 1297 1298 rc = uclogic_params_frame_init_with_desc(&p->frame_list[1], 1299 uclogic_rdesc_ugee_v2_battery_template_arr, 1300 uclogic_rdesc_ugee_v2_battery_template_size, 1301 UCLOGIC_RDESC_UGEE_V2_BATTERY_ID); 1302 if (rc) 1303 return rc; 1304 1305 p->frame_list[1].suffix = "Battery"; 1306 p->pen.subreport_list[1].value = 0xf2; 1307 p->pen.subreport_list[1].id = UCLOGIC_RDESC_UGEE_V2_BATTERY_ID; 1308 1309 return rc; 1310 } 1311 1312 /** 1313 * uclogic_params_ugee_v2_reconnect_work() - When a wireless tablet looses 1314 * connection to the USB dongle and reconnects, either because of its physical 1315 * distance or because it was switches off and on using the frame's switch, 1316 * uclogic_probe_interface() needs to be called again to enable the tablet. 1317 * 1318 * @work: The work that triggered this function. 1319 */ 1320 static void uclogic_params_ugee_v2_reconnect_work(struct work_struct *work) 1321 { 1322 struct uclogic_raw_event_hook *event_hook; 1323 1324 event_hook = container_of(work, struct uclogic_raw_event_hook, work); 1325 uclogic_probe_interface(event_hook->hdev, uclogic_ugee_v2_probe_arr, 1326 uclogic_ugee_v2_probe_size, 1327 uclogic_ugee_v2_probe_endpoint); 1328 } 1329 1330 /** 1331 * uclogic_params_ugee_v2_init_event_hooks() - initialize the list of events 1332 * to be hooked for UGEE v2 devices. 1333 * @hdev: The HID device of the tablet interface to initialize and get 1334 * parameters from. 1335 * @p: Parameters to fill in, cannot be NULL. 1336 * 1337 * Returns: 1338 * Zero, if successful. A negative errno code on error. 1339 */ 1340 static int uclogic_params_ugee_v2_init_event_hooks(struct hid_device *hdev, 1341 struct uclogic_params *p) 1342 { 1343 struct uclogic_raw_event_hook *event_hook; 1344 __u8 reconnect_event[] = { 1345 /* Event received on wireless tablet reconnection */ 1346 0x02, 0xF8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 1347 }; 1348 1349 if (!p) 1350 return -EINVAL; 1351 1352 /* The reconnection event is only received if the tablet has battery */ 1353 if (!uclogic_params_ugee_v2_has_battery(hdev)) 1354 return 0; 1355 1356 p->event_hooks = kzalloc(sizeof(*p->event_hooks), GFP_KERNEL); 1357 if (!p->event_hooks) 1358 return -ENOMEM; 1359 1360 INIT_LIST_HEAD(&p->event_hooks->list); 1361 1362 event_hook = kzalloc(sizeof(*event_hook), GFP_KERNEL); 1363 if (!event_hook) 1364 return -ENOMEM; 1365 1366 INIT_WORK(&event_hook->work, uclogic_params_ugee_v2_reconnect_work); 1367 event_hook->hdev = hdev; 1368 event_hook->size = ARRAY_SIZE(reconnect_event); 1369 event_hook->event = kmemdup(reconnect_event, event_hook->size, GFP_KERNEL); 1370 if (!event_hook->event) 1371 return -ENOMEM; 1372 1373 list_add_tail(&event_hook->list, &p->event_hooks->list); 1374 1375 return 0; 1376 } 1377 1378 /** 1379 * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by 1380 * discovering their parameters. 1381 * 1382 * These tables, internally designed as v2 to differentiate them from older 1383 * models, expect a payload of magic data in orther to be switched to the fully 1384 * functional mode and expose their parameters in a similar way to the 1385 * information present in uclogic_params_pen_init_v1() but with some 1386 * differences. 1387 * 1388 * @params: Parameters to fill in (to be cleaned with 1389 * uclogic_params_cleanup()). Not modified in case of error. 1390 * Cannot be NULL. 1391 * @hdev: The HID device of the tablet interface to initialize and get 1392 * parameters from. Cannot be NULL. 1393 * 1394 * Returns: 1395 * Zero, if successful. A negative errno code on error. 1396 */ 1397 static int uclogic_params_ugee_v2_init(struct uclogic_params *params, 1398 struct hid_device *hdev) 1399 { 1400 int rc = 0; 1401 struct uclogic_drvdata *drvdata; 1402 struct usb_interface *iface; 1403 __u8 bInterfaceNumber; 1404 const int str_desc_len = 12; 1405 __u8 *str_desc = NULL; 1406 __u8 *rdesc_pen = NULL; 1407 s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; 1408 enum uclogic_params_frame_type frame_type; 1409 /* The resulting parameters (noop) */ 1410 struct uclogic_params p = {0, }; 1411 1412 if (!params || !hdev) { 1413 rc = -EINVAL; 1414 goto cleanup; 1415 } 1416 1417 drvdata = hid_get_drvdata(hdev); 1418 iface = to_usb_interface(hdev->dev.parent); 1419 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; 1420 1421 if (bInterfaceNumber == 0) { 1422 rc = uclogic_params_ugee_v2_init_frame_mouse(&p); 1423 if (rc) 1424 goto cleanup; 1425 1426 goto output; 1427 } 1428 1429 if (bInterfaceNumber != 2) { 1430 uclogic_params_init_invalid(&p); 1431 goto output; 1432 } 1433 1434 /* 1435 * Initialize the interface by sending magic data. 1436 * The specific data was discovered by sniffing the Windows driver 1437 * traffic. 1438 */ 1439 rc = uclogic_probe_interface(hdev, uclogic_ugee_v2_probe_arr, 1440 uclogic_ugee_v2_probe_size, 1441 uclogic_ugee_v2_probe_endpoint); 1442 if (rc) { 1443 uclogic_params_init_invalid(&p); 1444 goto output; 1445 } 1446 1447 /* 1448 * Read the string descriptor containing pen and frame parameters. 1449 * The specific string descriptor and data were discovered by sniffing 1450 * the Windows driver traffic. 1451 */ 1452 rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len); 1453 if (rc != str_desc_len) { 1454 hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc); 1455 uclogic_params_init_invalid(&p); 1456 goto output; 1457 } 1458 1459 rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len, 1460 desc_params, 1461 ARRAY_SIZE(desc_params), 1462 &frame_type); 1463 if (rc) 1464 goto cleanup; 1465 1466 kfree(str_desc); 1467 str_desc = NULL; 1468 1469 /* Initialize the pen interface */ 1470 rdesc_pen = uclogic_rdesc_template_apply( 1471 uclogic_rdesc_ugee_v2_pen_template_arr, 1472 uclogic_rdesc_ugee_v2_pen_template_size, 1473 desc_params, ARRAY_SIZE(desc_params)); 1474 if (!rdesc_pen) { 1475 rc = -ENOMEM; 1476 goto cleanup; 1477 } 1478 1479 p.pen.desc_ptr = rdesc_pen; 1480 p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size; 1481 p.pen.id = 0x02; 1482 p.pen.subreport_list[0].value = 0xf0; 1483 p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID; 1484 1485 /* Initialize the frame interface */ 1486 if (drvdata->quirks & UCLOGIC_MOUSE_FRAME_QUIRK) 1487 frame_type = UCLOGIC_PARAMS_FRAME_MOUSE; 1488 1489 switch (frame_type) { 1490 case UCLOGIC_PARAMS_FRAME_DIAL: 1491 case UCLOGIC_PARAMS_FRAME_MOUSE: 1492 rc = uclogic_params_ugee_v2_init_frame_dial(&p, desc_params, 1493 ARRAY_SIZE(desc_params)); 1494 break; 1495 case UCLOGIC_PARAMS_FRAME_BUTTONS: 1496 default: 1497 rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params, 1498 ARRAY_SIZE(desc_params)); 1499 break; 1500 } 1501 1502 if (rc) 1503 goto cleanup; 1504 1505 /* Initialize the battery interface*/ 1506 if (uclogic_params_ugee_v2_has_battery(hdev)) { 1507 rc = uclogic_params_ugee_v2_init_battery(hdev, &p); 1508 if (rc) { 1509 hid_err(hdev, "error initializing battery: %d\n", rc); 1510 goto cleanup; 1511 } 1512 } 1513 1514 /* Create a list of raw events to be ignored */ 1515 rc = uclogic_params_ugee_v2_init_event_hooks(hdev, &p); 1516 if (rc) { 1517 hid_err(hdev, "error initializing event hook list: %d\n", rc); 1518 goto cleanup; 1519 } 1520 1521 output: 1522 /* Output parameters */ 1523 memcpy(params, &p, sizeof(*params)); 1524 memset(&p, 0, sizeof(p)); 1525 rc = 0; 1526 cleanup: 1527 kfree(str_desc); 1528 uclogic_params_cleanup(&p); 1529 return rc; 1530 } 1531 1532 /** 1533 * uclogic_params_init() - initialize a tablet interface and discover its 1534 * parameters. 1535 * 1536 * @params: Parameters to fill in (to be cleaned with 1537 * uclogic_params_cleanup()). Not modified in case of error. 1538 * Cannot be NULL. 1539 * @hdev: The HID device of the tablet interface to initialize and get 1540 * parameters from. Cannot be NULL. Must be using the USB low-level 1541 * driver, i.e. be an actual USB tablet. 1542 * 1543 * Returns: 1544 * Zero, if successful. A negative errno code on error. 1545 */ 1546 int uclogic_params_init(struct uclogic_params *params, 1547 struct hid_device *hdev) 1548 { 1549 int rc; 1550 struct usb_device *udev; 1551 __u8 bNumInterfaces; 1552 struct usb_interface *iface; 1553 __u8 bInterfaceNumber; 1554 bool found; 1555 /* The resulting parameters (noop) */ 1556 struct uclogic_params p = {0, }; 1557 1558 /* Check arguments */ 1559 if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) { 1560 rc = -EINVAL; 1561 goto cleanup; 1562 } 1563 1564 udev = hid_to_usb_dev(hdev); 1565 bNumInterfaces = udev->config->desc.bNumInterfaces; 1566 iface = to_usb_interface(hdev->dev.parent); 1567 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; 1568 1569 /* 1570 * Set replacement report descriptor if the original matches the 1571 * specified size. Otherwise keep interface unchanged. 1572 */ 1573 #define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \ 1574 uclogic_params_init_with_opt_desc( \ 1575 &p, hdev, \ 1576 UCLOGIC_RDESC_##_orig_desc_token##_SIZE, \ 1577 uclogic_rdesc_##_new_desc_token##_arr, \ 1578 uclogic_rdesc_##_new_desc_token##_size) 1579 1580 #define VID_PID(_vid, _pid) \ 1581 (((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX)) 1582 1583 /* 1584 * Handle specific interfaces for specific tablets. 1585 * 1586 * Observe the following logic: 1587 * 1588 * If the interface is recognized as producing certain useful input: 1589 * Mark interface as valid. 1590 * Output interface parameters. 1591 * Else, if the interface is recognized as *not* producing any useful 1592 * input: 1593 * Mark interface as invalid. 1594 * Else: 1595 * Mark interface as valid. 1596 * Output noop parameters. 1597 * 1598 * Rule of thumb: it is better to disable a broken interface than let 1599 * it spew garbage input. 1600 */ 1601 1602 switch (VID_PID(hdev->vendor, hdev->product)) { 1603 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1604 USB_DEVICE_ID_UCLOGIC_TABLET_PF1209): 1605 rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed); 1606 if (rc != 0) 1607 goto cleanup; 1608 break; 1609 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1610 USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U): 1611 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed); 1612 if (rc != 0) 1613 goto cleanup; 1614 break; 1615 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1616 USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U): 1617 if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) { 1618 if (bInterfaceNumber == 0) { 1619 /* Try to probe v1 pen parameters */ 1620 rc = uclogic_params_pen_init_v1(&p.pen, 1621 &found, hdev); 1622 if (rc != 0) { 1623 hid_err(hdev, 1624 "pen probing failed: %d\n", 1625 rc); 1626 goto cleanup; 1627 } 1628 if (!found) { 1629 hid_warn(hdev, 1630 "pen parameters not found"); 1631 } 1632 } else { 1633 uclogic_params_init_invalid(&p); 1634 } 1635 } else { 1636 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed); 1637 if (rc != 0) 1638 goto cleanup; 1639 } 1640 break; 1641 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1642 USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U): 1643 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed); 1644 if (rc != 0) 1645 goto cleanup; 1646 break; 1647 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1648 USB_DEVICE_ID_UCLOGIC_TABLET_WP1062): 1649 rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed); 1650 if (rc != 0) 1651 goto cleanup; 1652 break; 1653 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1654 USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850): 1655 switch (bInterfaceNumber) { 1656 case 0: 1657 rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0); 1658 if (rc != 0) 1659 goto cleanup; 1660 break; 1661 case 1: 1662 rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1); 1663 if (rc != 0) 1664 goto cleanup; 1665 break; 1666 case 2: 1667 rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2); 1668 if (rc != 0) 1669 goto cleanup; 1670 break; 1671 } 1672 break; 1673 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1674 USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60): 1675 /* 1676 * If it is not a three-interface version, which is known to 1677 * respond to initialization. 1678 */ 1679 if (bNumInterfaces != 3) { 1680 switch (bInterfaceNumber) { 1681 case 0: 1682 rc = WITH_OPT_DESC(TWHA60_ORIG0, 1683 twha60_fixed0); 1684 if (rc != 0) 1685 goto cleanup; 1686 break; 1687 case 1: 1688 rc = WITH_OPT_DESC(TWHA60_ORIG1, 1689 twha60_fixed1); 1690 if (rc != 0) 1691 goto cleanup; 1692 break; 1693 } 1694 break; 1695 } 1696 fallthrough; 1697 case VID_PID(USB_VENDOR_ID_HUION, 1698 USB_DEVICE_ID_HUION_TABLET): 1699 case VID_PID(USB_VENDOR_ID_HUION, 1700 USB_DEVICE_ID_HUION_TABLET2): 1701 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1702 USB_DEVICE_ID_HUION_TABLET): 1703 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1704 USB_DEVICE_ID_YIYNOVA_TABLET): 1705 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1706 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81): 1707 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1708 USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3): 1709 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1710 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45): 1711 case VID_PID(USB_VENDOR_ID_UCLOGIC, 1712 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47): 1713 rc = uclogic_params_huion_init(&p, hdev); 1714 if (rc != 0) 1715 goto cleanup; 1716 break; 1717 case VID_PID(USB_VENDOR_ID_UGTIZER, 1718 USB_DEVICE_ID_UGTIZER_TABLET_GP0610): 1719 case VID_PID(USB_VENDOR_ID_UGTIZER, 1720 USB_DEVICE_ID_UGTIZER_TABLET_GT5040): 1721 case VID_PID(USB_VENDOR_ID_UGEE, 1722 USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540): 1723 case VID_PID(USB_VENDOR_ID_UGEE, 1724 USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640): 1725 case VID_PID(USB_VENDOR_ID_UGEE, 1726 USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06): 1727 case VID_PID(USB_VENDOR_ID_UGEE, 1728 USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720): 1729 /* If this is the pen interface */ 1730 if (bInterfaceNumber == 1) { 1731 /* Probe v1 pen parameters */ 1732 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1733 if (rc != 0) { 1734 hid_err(hdev, "pen probing failed: %d\n", rc); 1735 goto cleanup; 1736 } 1737 if (!found) { 1738 hid_warn(hdev, "pen parameters not found"); 1739 uclogic_params_init_invalid(&p); 1740 } 1741 } else { 1742 uclogic_params_init_invalid(&p); 1743 } 1744 break; 1745 case VID_PID(USB_VENDOR_ID_UGEE, 1746 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01): 1747 /* If this is the pen and frame interface */ 1748 if (bInterfaceNumber == 1) { 1749 /* Probe v1 pen parameters */ 1750 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1751 if (rc != 0) { 1752 hid_err(hdev, "pen probing failed: %d\n", rc); 1753 goto cleanup; 1754 } 1755 /* Initialize frame parameters */ 1756 rc = uclogic_params_frame_init_with_desc( 1757 &p.frame_list[0], 1758 uclogic_rdesc_xppen_deco01_frame_arr, 1759 uclogic_rdesc_xppen_deco01_frame_size, 1760 0); 1761 if (rc != 0) 1762 goto cleanup; 1763 } else { 1764 uclogic_params_init_invalid(&p); 1765 } 1766 break; 1767 case VID_PID(USB_VENDOR_ID_UGEE, 1768 USB_DEVICE_ID_UGEE_PARBLO_A610_PRO): 1769 case VID_PID(USB_VENDOR_ID_UGEE, 1770 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2): 1771 case VID_PID(USB_VENDOR_ID_UGEE, 1772 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L): 1773 case VID_PID(USB_VENDOR_ID_UGEE, 1774 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW): 1775 case VID_PID(USB_VENDOR_ID_UGEE, 1776 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S): 1777 case VID_PID(USB_VENDOR_ID_UGEE, 1778 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW): 1779 rc = uclogic_params_ugee_v2_init(&p, hdev); 1780 if (rc != 0) 1781 goto cleanup; 1782 break; 1783 case VID_PID(USB_VENDOR_ID_TRUST, 1784 USB_DEVICE_ID_TRUST_PANORA_TABLET): 1785 case VID_PID(USB_VENDOR_ID_UGEE, 1786 USB_DEVICE_ID_UGEE_TABLET_G5): 1787 /* Ignore non-pen interfaces */ 1788 if (bInterfaceNumber != 1) { 1789 uclogic_params_init_invalid(&p); 1790 break; 1791 } 1792 1793 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1794 if (rc != 0) { 1795 hid_err(hdev, "pen probing failed: %d\n", rc); 1796 goto cleanup; 1797 } else if (found) { 1798 rc = uclogic_params_frame_init_with_desc( 1799 &p.frame_list[0], 1800 uclogic_rdesc_ugee_g5_frame_arr, 1801 uclogic_rdesc_ugee_g5_frame_size, 1802 UCLOGIC_RDESC_UGEE_G5_FRAME_ID); 1803 if (rc != 0) { 1804 hid_err(hdev, 1805 "failed creating frame parameters: %d\n", 1806 rc); 1807 goto cleanup; 1808 } 1809 p.frame_list[0].re_lsb = 1810 UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB; 1811 p.frame_list[0].dev_id_byte = 1812 UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE; 1813 } else { 1814 hid_warn(hdev, "pen parameters not found"); 1815 uclogic_params_init_invalid(&p); 1816 } 1817 1818 break; 1819 case VID_PID(USB_VENDOR_ID_UGEE, 1820 USB_DEVICE_ID_UGEE_TABLET_EX07S): 1821 /* Ignore non-pen interfaces */ 1822 if (bInterfaceNumber != 1) { 1823 uclogic_params_init_invalid(&p); 1824 break; 1825 } 1826 1827 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev); 1828 if (rc != 0) { 1829 hid_err(hdev, "pen probing failed: %d\n", rc); 1830 goto cleanup; 1831 } else if (found) { 1832 rc = uclogic_params_frame_init_with_desc( 1833 &p.frame_list[0], 1834 uclogic_rdesc_ugee_ex07_frame_arr, 1835 uclogic_rdesc_ugee_ex07_frame_size, 1836 0); 1837 if (rc != 0) { 1838 hid_err(hdev, 1839 "failed creating frame parameters: %d\n", 1840 rc); 1841 goto cleanup; 1842 } 1843 } else { 1844 hid_warn(hdev, "pen parameters not found"); 1845 uclogic_params_init_invalid(&p); 1846 } 1847 1848 break; 1849 } 1850 1851 #undef VID_PID 1852 #undef WITH_OPT_DESC 1853 1854 /* Output parameters */ 1855 memcpy(params, &p, sizeof(*params)); 1856 memset(&p, 0, sizeof(p)); 1857 rc = 0; 1858 cleanup: 1859 uclogic_params_cleanup(&p); 1860 return rc; 1861 } 1862 1863 #ifdef CONFIG_HID_KUNIT_TEST 1864 #include "hid-uclogic-params-test.c" 1865 #endif 1866