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 #include <linux/string_choices.h>
24
25 /**
26 * uclogic_params_pen_inrange_to_str() - Convert a pen in-range reporting type
27 * to a string.
28 * @inrange: The in-range reporting type to convert.
29 *
30 * Return:
31 * * The string representing the type, or
32 * * %NULL if the type is unknown.
33 */
uclogic_params_pen_inrange_to_str(enum uclogic_params_pen_inrange inrange)34 static const char *uclogic_params_pen_inrange_to_str(
35 enum uclogic_params_pen_inrange inrange)
36 {
37 switch (inrange) {
38 case UCLOGIC_PARAMS_PEN_INRANGE_NORMAL:
39 return "normal";
40 case UCLOGIC_PARAMS_PEN_INRANGE_INVERTED:
41 return "inverted";
42 case UCLOGIC_PARAMS_PEN_INRANGE_NONE:
43 return "none";
44 default:
45 return NULL;
46 }
47 }
48
49 /**
50 * uclogic_params_pen_hid_dbg() - Dump tablet interface pen parameters
51 * @hdev: The HID device the pen parameters describe.
52 * @pen: The pen parameters to dump.
53 *
54 * Dump tablet interface pen parameters with hid_dbg(). The dump is indented
55 * with a tab.
56 */
uclogic_params_pen_hid_dbg(const struct hid_device * hdev,const struct uclogic_params_pen * pen)57 static void uclogic_params_pen_hid_dbg(const struct hid_device *hdev,
58 const struct uclogic_params_pen *pen)
59 {
60 size_t i;
61
62 hid_dbg(hdev, "\t.usage_invalid = %s\n",
63 str_true_false(pen->usage_invalid));
64 hid_dbg(hdev, "\t.desc_ptr = %p\n", pen->desc_ptr);
65 hid_dbg(hdev, "\t.desc_size = %u\n", pen->desc_size);
66 hid_dbg(hdev, "\t.id = %u\n", pen->id);
67 hid_dbg(hdev, "\t.subreport_list = {\n");
68 for (i = 0; i < ARRAY_SIZE(pen->subreport_list); i++) {
69 hid_dbg(hdev, "\t\t{0x%02hhx, %hhu}%s\n",
70 pen->subreport_list[i].value,
71 pen->subreport_list[i].id,
72 i < (ARRAY_SIZE(pen->subreport_list) - 1) ? "," : "");
73 }
74 hid_dbg(hdev, "\t}\n");
75 hid_dbg(hdev, "\t.inrange = %s\n",
76 uclogic_params_pen_inrange_to_str(pen->inrange));
77 hid_dbg(hdev, "\t.fragmented_hires = %s\n",
78 str_true_false(pen->fragmented_hires));
79 hid_dbg(hdev, "\t.tilt_y_flipped = %s\n",
80 str_true_false(pen->tilt_y_flipped));
81 }
82
83 /**
84 * uclogic_params_frame_hid_dbg() - Dump tablet interface frame parameters
85 * @hdev: The HID device the pen parameters describe.
86 * @frame: The frame parameters to dump.
87 *
88 * Dump tablet interface frame parameters with hid_dbg(). The dump is
89 * indented with two tabs.
90 */
uclogic_params_frame_hid_dbg(const struct hid_device * hdev,const struct uclogic_params_frame * frame)91 static void uclogic_params_frame_hid_dbg(
92 const struct hid_device *hdev,
93 const struct uclogic_params_frame *frame)
94 {
95 hid_dbg(hdev, "\t\t.desc_ptr = %p\n", frame->desc_ptr);
96 hid_dbg(hdev, "\t\t.desc_size = %u\n", frame->desc_size);
97 hid_dbg(hdev, "\t\t.id = %u\n", frame->id);
98 hid_dbg(hdev, "\t\t.suffix = %s\n", frame->suffix);
99 hid_dbg(hdev, "\t\t.re_lsb = %u\n", frame->re_lsb);
100 hid_dbg(hdev, "\t\t.dev_id_byte = %u\n", frame->dev_id_byte);
101 hid_dbg(hdev, "\t\t.touch_byte = %u\n", frame->touch_byte);
102 hid_dbg(hdev, "\t\t.touch_max = %hhd\n", frame->touch_max);
103 hid_dbg(hdev, "\t\t.touch_flip_at = %hhd\n",
104 frame->touch_flip_at);
105 hid_dbg(hdev, "\t\t.bitmap_dial_byte = %u\n",
106 frame->bitmap_dial_byte);
107 hid_dbg(hdev, "\t\t.bitmap_second_dial_destination_byte = %u\n",
108 frame->bitmap_second_dial_destination_byte);
109 }
110
111 /**
112 * uclogic_params_hid_dbg() - Dump tablet interface parameters
113 * @hdev: The HID device the parameters describe.
114 * @params: The parameters to dump.
115 *
116 * Dump tablet interface parameters with hid_dbg().
117 */
uclogic_params_hid_dbg(const struct hid_device * hdev,const struct uclogic_params * params)118 void uclogic_params_hid_dbg(const struct hid_device *hdev,
119 const struct uclogic_params *params)
120 {
121 size_t i;
122
123 hid_dbg(hdev, ".invalid = %s\n", str_true_false(params->invalid));
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 kfree(event_hook);
1374 return -ENOMEM;
1375 }
1376
1377 list_add_tail(&event_hook->list, &p->event_hooks->list);
1378
1379 return 0;
1380 }
1381
1382 /**
1383 * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by
1384 * discovering their parameters.
1385 *
1386 * These tables, internally designed as v2 to differentiate them from older
1387 * models, expect a payload of magic data in orther to be switched to the fully
1388 * functional mode and expose their parameters in a similar way to the
1389 * information present in uclogic_params_pen_init_v1() but with some
1390 * differences.
1391 *
1392 * @params: Parameters to fill in (to be cleaned with
1393 * uclogic_params_cleanup()). Not modified in case of error.
1394 * Cannot be NULL.
1395 * @hdev: The HID device of the tablet interface to initialize and get
1396 * parameters from. Cannot be NULL.
1397 *
1398 * Returns:
1399 * Zero, if successful. A negative errno code on error.
1400 */
uclogic_params_ugee_v2_init(struct uclogic_params * params,struct hid_device * hdev)1401 static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
1402 struct hid_device *hdev)
1403 {
1404 int rc = 0;
1405 struct uclogic_drvdata *drvdata;
1406 struct usb_interface *iface;
1407 __u8 bInterfaceNumber;
1408 const int str_desc_len = 12;
1409 __u8 *str_desc = NULL;
1410 __u8 *rdesc_pen = NULL;
1411 s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
1412 enum uclogic_params_frame_type frame_type;
1413 /* The resulting parameters (noop) */
1414 struct uclogic_params p = {0, };
1415
1416 if (!params || !hdev) {
1417 rc = -EINVAL;
1418 goto cleanup;
1419 }
1420
1421 drvdata = hid_get_drvdata(hdev);
1422 iface = to_usb_interface(hdev->dev.parent);
1423 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1424
1425 if (bInterfaceNumber == 0) {
1426 rc = uclogic_params_ugee_v2_init_frame_mouse(&p);
1427 if (rc)
1428 goto cleanup;
1429
1430 goto output;
1431 }
1432
1433 if (bInterfaceNumber != 2) {
1434 uclogic_params_init_invalid(&p);
1435 goto output;
1436 }
1437
1438 /*
1439 * Initialize the interface by sending magic data.
1440 * The specific data was discovered by sniffing the Windows driver
1441 * traffic.
1442 */
1443 rc = uclogic_probe_interface(hdev, uclogic_ugee_v2_probe_arr,
1444 uclogic_ugee_v2_probe_size,
1445 uclogic_ugee_v2_probe_endpoint);
1446 if (rc) {
1447 uclogic_params_init_invalid(&p);
1448 goto output;
1449 }
1450
1451 /*
1452 * Read the string descriptor containing pen and frame parameters.
1453 * The specific string descriptor and data were discovered by sniffing
1454 * the Windows driver traffic.
1455 */
1456 rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len);
1457 if (rc != str_desc_len) {
1458 hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc);
1459 uclogic_params_init_invalid(&p);
1460 goto output;
1461 }
1462
1463 rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len,
1464 desc_params,
1465 ARRAY_SIZE(desc_params),
1466 &frame_type);
1467 if (rc)
1468 goto cleanup;
1469
1470 kfree(str_desc);
1471 str_desc = NULL;
1472
1473 /* Initialize the pen interface */
1474 rdesc_pen = uclogic_rdesc_template_apply(
1475 uclogic_rdesc_ugee_v2_pen_template_arr,
1476 uclogic_rdesc_ugee_v2_pen_template_size,
1477 desc_params, ARRAY_SIZE(desc_params));
1478 if (!rdesc_pen) {
1479 rc = -ENOMEM;
1480 goto cleanup;
1481 }
1482
1483 p.pen.desc_ptr = rdesc_pen;
1484 p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size;
1485 p.pen.id = 0x02;
1486 p.pen.subreport_list[0].value = 0xf0;
1487 p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
1488
1489 /* Initialize the frame interface */
1490 if (drvdata->quirks & UCLOGIC_MOUSE_FRAME_QUIRK)
1491 frame_type = UCLOGIC_PARAMS_FRAME_MOUSE;
1492
1493 switch (frame_type) {
1494 case UCLOGIC_PARAMS_FRAME_DIAL:
1495 case UCLOGIC_PARAMS_FRAME_MOUSE:
1496 rc = uclogic_params_ugee_v2_init_frame_dial(&p, desc_params,
1497 ARRAY_SIZE(desc_params));
1498 break;
1499 case UCLOGIC_PARAMS_FRAME_BUTTONS:
1500 default:
1501 rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params,
1502 ARRAY_SIZE(desc_params));
1503 break;
1504 }
1505
1506 if (rc)
1507 goto cleanup;
1508
1509 /* Initialize the battery interface*/
1510 if (uclogic_params_ugee_v2_has_battery(hdev)) {
1511 rc = uclogic_params_ugee_v2_init_battery(hdev, &p);
1512 if (rc) {
1513 hid_err(hdev, "error initializing battery: %d\n", rc);
1514 goto cleanup;
1515 }
1516 }
1517
1518 /* Create a list of raw events to be ignored */
1519 rc = uclogic_params_ugee_v2_init_event_hooks(hdev, &p);
1520 if (rc) {
1521 hid_err(hdev, "error initializing event hook list: %d\n", rc);
1522 goto cleanup;
1523 }
1524
1525 output:
1526 /* Output parameters */
1527 memcpy(params, &p, sizeof(*params));
1528 memset(&p, 0, sizeof(p));
1529 rc = 0;
1530 cleanup:
1531 kfree(str_desc);
1532 uclogic_params_cleanup(&p);
1533 return rc;
1534 }
1535
1536 /*
1537 * uclogic_params_init_ugee_xppen_pro_22r() - Initializes a UGEE XP-Pen Pro 22R tablet device.
1538 *
1539 * @hdev: The HID device of the tablet interface to initialize and get
1540 * parameters from. Cannot be NULL.
1541 * @params: Parameters to fill in (to be cleaned with
1542 * uclogic_params_cleanup()). Not modified in case of error.
1543 * Cannot be NULL.
1544 *
1545 * Returns:
1546 * Zero, if successful. A negative errno code on error.
1547 */
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)1548 static int uclogic_params_init_ugee_xppen_pro_22r(struct uclogic_params *params,
1549 struct hid_device *hdev,
1550 const u8 rdesc_frame_arr[],
1551 const size_t rdesc_frame_size)
1552 {
1553 int rc = 0;
1554 struct usb_interface *iface;
1555 __u8 bInterfaceNumber;
1556 const int str_desc_len = 12;
1557 u8 *str_desc = NULL;
1558 __u8 *rdesc_pen = NULL;
1559 s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
1560 enum uclogic_params_frame_type frame_type;
1561 /* The resulting parameters (noop) */
1562 struct uclogic_params p = {0, };
1563
1564 if (!hdev || !params) {
1565 rc = -EINVAL;
1566 goto cleanup;
1567 }
1568
1569 iface = to_usb_interface(hdev->dev.parent);
1570 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1571
1572 /* Ignore non-pen interfaces */
1573 if (bInterfaceNumber != 2) {
1574 rc = -EINVAL;
1575 uclogic_params_init_invalid(&p);
1576 goto cleanup;
1577 }
1578
1579 /*
1580 * Initialize the interface by sending magic data.
1581 * This magic data is the same as other UGEE v2 tablets.
1582 */
1583 rc = uclogic_probe_interface(hdev,
1584 uclogic_ugee_v2_probe_arr,
1585 uclogic_ugee_v2_probe_size,
1586 uclogic_ugee_v2_probe_endpoint);
1587 if (rc) {
1588 uclogic_params_init_invalid(&p);
1589 goto cleanup;
1590 }
1591
1592 /**
1593 * Read the string descriptor containing pen and frame parameters.
1594 * These are slightly different than typical UGEE v2 devices.
1595 */
1596 rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len);
1597 if (rc != str_desc_len) {
1598 rc = (rc < 0) ? rc : -EINVAL;
1599 hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc);
1600 uclogic_params_init_invalid(&p);
1601 goto cleanup;
1602 }
1603
1604 rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len,
1605 desc_params,
1606 ARRAY_SIZE(desc_params),
1607 &frame_type);
1608 if (rc)
1609 goto cleanup;
1610
1611 // str_desc doesn't report the correct amount of buttons, so manually fix it
1612 desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 20;
1613
1614 kfree(str_desc);
1615 str_desc = NULL;
1616
1617 /* Initialize the pen interface */
1618 rdesc_pen = uclogic_rdesc_template_apply(
1619 uclogic_rdesc_ugee_v2_pen_template_arr,
1620 uclogic_rdesc_ugee_v2_pen_template_size,
1621 desc_params, ARRAY_SIZE(desc_params));
1622 if (!rdesc_pen) {
1623 rc = -ENOMEM;
1624 goto cleanup;
1625 }
1626
1627 p.pen.desc_ptr = rdesc_pen;
1628 p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size;
1629 p.pen.id = 0x02;
1630 p.pen.subreport_list[0].value = 0xf0;
1631 p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
1632
1633 /* Initialize the frame interface */
1634 rc = uclogic_params_frame_init_with_desc(
1635 &p.frame_list[0],
1636 rdesc_frame_arr,
1637 rdesc_frame_size,
1638 UCLOGIC_RDESC_V1_FRAME_ID);
1639 if (rc < 0) {
1640 hid_err(hdev, "initializing frame params failed: %d\n", rc);
1641 goto cleanup;
1642 }
1643
1644 p.frame_list[0].bitmap_dial_byte = 7;
1645 p.frame_list[0].bitmap_second_dial_destination_byte = 8;
1646
1647 /* Output parameters */
1648 memcpy(params, &p, sizeof(*params));
1649 memset(&p, 0, sizeof(p));
1650 cleanup:
1651 kfree(str_desc);
1652 uclogic_params_cleanup(&p);
1653 return rc;
1654 }
1655
1656 /**
1657 * uclogic_params_init() - initialize a tablet interface and discover its
1658 * parameters.
1659 *
1660 * @params: Parameters to fill in (to be cleaned with
1661 * uclogic_params_cleanup()). Not modified in case of error.
1662 * Cannot be NULL.
1663 * @hdev: The HID device of the tablet interface to initialize and get
1664 * parameters from. Cannot be NULL. Must be using the USB low-level
1665 * driver, i.e. be an actual USB tablet.
1666 *
1667 * Returns:
1668 * Zero, if successful. A negative errno code on error.
1669 */
uclogic_params_init(struct uclogic_params * params,struct hid_device * hdev)1670 int uclogic_params_init(struct uclogic_params *params,
1671 struct hid_device *hdev)
1672 {
1673 int rc;
1674 struct usb_device *udev;
1675 __u8 bNumInterfaces;
1676 struct usb_interface *iface;
1677 __u8 bInterfaceNumber;
1678 bool found;
1679 /* The resulting parameters (noop) */
1680 struct uclogic_params p = {0, };
1681
1682 /* Check arguments */
1683 if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) {
1684 rc = -EINVAL;
1685 goto cleanup;
1686 }
1687
1688 udev = hid_to_usb_dev(hdev);
1689 bNumInterfaces = udev->config->desc.bNumInterfaces;
1690 iface = to_usb_interface(hdev->dev.parent);
1691 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1692
1693 /*
1694 * Set replacement report descriptor if the original matches the
1695 * specified size. Otherwise keep interface unchanged.
1696 */
1697 #define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \
1698 uclogic_params_init_with_opt_desc( \
1699 &p, hdev, \
1700 UCLOGIC_RDESC_##_orig_desc_token##_SIZE, \
1701 uclogic_rdesc_##_new_desc_token##_arr, \
1702 uclogic_rdesc_##_new_desc_token##_size)
1703
1704 #define VID_PID(_vid, _pid) \
1705 (((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX))
1706
1707 /*
1708 * Handle specific interfaces for specific tablets.
1709 *
1710 * Observe the following logic:
1711 *
1712 * If the interface is recognized as producing certain useful input:
1713 * Mark interface as valid.
1714 * Output interface parameters.
1715 * Else, if the interface is recognized as *not* producing any useful
1716 * input:
1717 * Mark interface as invalid.
1718 * Else:
1719 * Mark interface as valid.
1720 * Output noop parameters.
1721 *
1722 * Rule of thumb: it is better to disable a broken interface than let
1723 * it spew garbage input.
1724 */
1725
1726 switch (VID_PID(hdev->vendor, hdev->product)) {
1727 case VID_PID(USB_VENDOR_ID_UCLOGIC,
1728 USB_DEVICE_ID_UCLOGIC_TABLET_PF1209):
1729 rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed);
1730 if (rc != 0)
1731 goto cleanup;
1732 break;
1733 case VID_PID(USB_VENDOR_ID_UCLOGIC,
1734 USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U):
1735 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed);
1736 if (rc != 0)
1737 goto cleanup;
1738 break;
1739 case VID_PID(USB_VENDOR_ID_UCLOGIC,
1740 USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U):
1741 if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) {
1742 if (bInterfaceNumber == 0) {
1743 /* Try to probe v1 pen parameters */
1744 rc = uclogic_params_pen_init_v1(&p.pen,
1745 &found, hdev);
1746 if (rc != 0) {
1747 hid_err(hdev,
1748 "pen probing failed: %d\n",
1749 rc);
1750 goto cleanup;
1751 }
1752 if (!found) {
1753 hid_warn(hdev,
1754 "pen parameters not found");
1755 }
1756 } else {
1757 uclogic_params_init_invalid(&p);
1758 }
1759 } else {
1760 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed);
1761 if (rc != 0)
1762 goto cleanup;
1763 }
1764 break;
1765 case VID_PID(USB_VENDOR_ID_UCLOGIC,
1766 USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U):
1767 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed);
1768 if (rc != 0)
1769 goto cleanup;
1770 break;
1771 case VID_PID(USB_VENDOR_ID_UCLOGIC,
1772 USB_DEVICE_ID_UCLOGIC_TABLET_WP1062):
1773 rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed);
1774 if (rc != 0)
1775 goto cleanup;
1776 break;
1777 case VID_PID(USB_VENDOR_ID_UCLOGIC,
1778 USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850):
1779 switch (bInterfaceNumber) {
1780 case 0:
1781 rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0);
1782 if (rc != 0)
1783 goto cleanup;
1784 break;
1785 case 1:
1786 rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1);
1787 if (rc != 0)
1788 goto cleanup;
1789 break;
1790 case 2:
1791 rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2);
1792 if (rc != 0)
1793 goto cleanup;
1794 break;
1795 }
1796 break;
1797 case VID_PID(USB_VENDOR_ID_UCLOGIC,
1798 USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60):
1799 /*
1800 * If it is not a three-interface version, which is known to
1801 * respond to initialization.
1802 */
1803 if (bNumInterfaces != 3) {
1804 switch (bInterfaceNumber) {
1805 case 0:
1806 rc = WITH_OPT_DESC(TWHA60_ORIG0,
1807 twha60_fixed0);
1808 if (rc != 0)
1809 goto cleanup;
1810 break;
1811 case 1:
1812 rc = WITH_OPT_DESC(TWHA60_ORIG1,
1813 twha60_fixed1);
1814 if (rc != 0)
1815 goto cleanup;
1816 break;
1817 }
1818 break;
1819 }
1820 fallthrough;
1821 case VID_PID(USB_VENDOR_ID_HUION,
1822 USB_DEVICE_ID_HUION_TABLET):
1823 case VID_PID(USB_VENDOR_ID_HUION,
1824 USB_DEVICE_ID_HUION_TABLET2):
1825 case VID_PID(USB_VENDOR_ID_UCLOGIC,
1826 USB_DEVICE_ID_HUION_TABLET):
1827 case VID_PID(USB_VENDOR_ID_UCLOGIC,
1828 USB_DEVICE_ID_YIYNOVA_TABLET):
1829 case VID_PID(USB_VENDOR_ID_UCLOGIC,
1830 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81):
1831 case VID_PID(USB_VENDOR_ID_UCLOGIC,
1832 USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3):
1833 case VID_PID(USB_VENDOR_ID_UCLOGIC,
1834 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45):
1835 case VID_PID(USB_VENDOR_ID_UCLOGIC,
1836 USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47):
1837 rc = uclogic_params_huion_init(&p, hdev);
1838 if (rc != 0)
1839 goto cleanup;
1840 break;
1841 case VID_PID(USB_VENDOR_ID_UGTIZER,
1842 USB_DEVICE_ID_UGTIZER_TABLET_GP0610):
1843 case VID_PID(USB_VENDOR_ID_UGTIZER,
1844 USB_DEVICE_ID_UGTIZER_TABLET_GT5040):
1845 case VID_PID(USB_VENDOR_ID_UGEE,
1846 USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
1847 case VID_PID(USB_VENDOR_ID_UGEE,
1848 USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640):
1849 case VID_PID(USB_VENDOR_ID_UGEE,
1850 USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06):
1851 case VID_PID(USB_VENDOR_ID_UGEE,
1852 USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720):
1853 /* If this is the pen interface */
1854 if (bInterfaceNumber == 1) {
1855 /* Probe v1 pen parameters */
1856 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1857 if (rc != 0) {
1858 hid_err(hdev, "pen probing failed: %d\n", rc);
1859 goto cleanup;
1860 }
1861 if (!found) {
1862 hid_warn(hdev, "pen parameters not found");
1863 uclogic_params_init_invalid(&p);
1864 }
1865 } else {
1866 uclogic_params_init_invalid(&p);
1867 }
1868 break;
1869 case VID_PID(USB_VENDOR_ID_UGEE,
1870 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01):
1871 /* If this is the pen and frame interface */
1872 if (bInterfaceNumber == 1) {
1873 /* Probe v1 pen parameters */
1874 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1875 if (rc != 0) {
1876 hid_err(hdev, "pen probing failed: %d\n", rc);
1877 goto cleanup;
1878 }
1879 /* Initialize frame parameters */
1880 rc = uclogic_params_frame_init_with_desc(
1881 &p.frame_list[0],
1882 uclogic_rdesc_xppen_deco01_frame_arr,
1883 uclogic_rdesc_xppen_deco01_frame_size,
1884 0);
1885 if (rc != 0)
1886 goto cleanup;
1887 } else {
1888 uclogic_params_init_invalid(&p);
1889 }
1890 break;
1891 case VID_PID(USB_VENDOR_ID_UGEE,
1892 USB_DEVICE_ID_UGEE_PARBLO_A610_PRO):
1893 case VID_PID(USB_VENDOR_ID_UGEE,
1894 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2):
1895 case VID_PID(USB_VENDOR_ID_UGEE,
1896 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L):
1897 case VID_PID(USB_VENDOR_ID_UGEE,
1898 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW):
1899 case VID_PID(USB_VENDOR_ID_UGEE,
1900 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S):
1901 case VID_PID(USB_VENDOR_ID_UGEE,
1902 USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW):
1903 rc = uclogic_params_ugee_v2_init(&p, hdev);
1904 if (rc != 0)
1905 goto cleanup;
1906 break;
1907 case VID_PID(USB_VENDOR_ID_TRUST,
1908 USB_DEVICE_ID_TRUST_PANORA_TABLET):
1909 case VID_PID(USB_VENDOR_ID_UGEE,
1910 USB_DEVICE_ID_UGEE_TABLET_G5):
1911 /* Ignore non-pen interfaces */
1912 if (bInterfaceNumber != 1) {
1913 uclogic_params_init_invalid(&p);
1914 break;
1915 }
1916
1917 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1918 if (rc != 0) {
1919 hid_err(hdev, "pen probing failed: %d\n", rc);
1920 goto cleanup;
1921 } else if (found) {
1922 rc = uclogic_params_frame_init_with_desc(
1923 &p.frame_list[0],
1924 uclogic_rdesc_ugee_g5_frame_arr,
1925 uclogic_rdesc_ugee_g5_frame_size,
1926 UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
1927 if (rc != 0) {
1928 hid_err(hdev,
1929 "failed creating frame parameters: %d\n",
1930 rc);
1931 goto cleanup;
1932 }
1933 p.frame_list[0].re_lsb =
1934 UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
1935 p.frame_list[0].dev_id_byte =
1936 UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
1937 } else {
1938 hid_warn(hdev, "pen parameters not found");
1939 uclogic_params_init_invalid(&p);
1940 }
1941
1942 break;
1943 case VID_PID(USB_VENDOR_ID_UGEE,
1944 USB_DEVICE_ID_UGEE_TABLET_EX07S):
1945 /* Ignore non-pen interfaces */
1946 if (bInterfaceNumber != 1) {
1947 uclogic_params_init_invalid(&p);
1948 break;
1949 }
1950
1951 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1952 if (rc != 0) {
1953 hid_err(hdev, "pen probing failed: %d\n", rc);
1954 goto cleanup;
1955 } else if (found) {
1956 rc = uclogic_params_frame_init_with_desc(
1957 &p.frame_list[0],
1958 uclogic_rdesc_ugee_ex07_frame_arr,
1959 uclogic_rdesc_ugee_ex07_frame_size,
1960 0);
1961 if (rc != 0) {
1962 hid_err(hdev,
1963 "failed creating frame parameters: %d\n",
1964 rc);
1965 goto cleanup;
1966 }
1967 } else {
1968 hid_warn(hdev, "pen parameters not found");
1969 uclogic_params_init_invalid(&p);
1970 }
1971
1972 break;
1973 case VID_PID(USB_VENDOR_ID_UGEE,
1974 USB_DEVICE_ID_UGEE_XPPEN_TABLET_22R_PRO):
1975 rc = uclogic_params_init_ugee_xppen_pro_22r(&p,
1976 hdev,
1977 uclogic_rdesc_xppen_artist_22r_pro_frame_arr,
1978 uclogic_rdesc_xppen_artist_22r_pro_frame_size);
1979 if (rc != 0)
1980 goto cleanup;
1981
1982 break;
1983 }
1984
1985 #undef VID_PID
1986 #undef WITH_OPT_DESC
1987
1988 /* Output parameters */
1989 memcpy(params, &p, sizeof(*params));
1990 memset(&p, 0, sizeof(p));
1991 rc = 0;
1992 cleanup:
1993 uclogic_params_cleanup(&p);
1994 return rc;
1995 }
1996
1997 #ifdef CONFIG_HID_KUNIT_TEST
1998 #include "hid-uclogic-params-test.c"
1999 #endif
2000