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