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