Merge branch 'for-5.20/apple' into for-linus
[linux-2.6-microblaze.git] / drivers / hid / hid-uclogic-params.c
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  */
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  */
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  */
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  */
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, &params->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, &params->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  */
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  */
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  */
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_PEN_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  */
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  */
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_PEN_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  */
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  */
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  */
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  */
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(&params->pen);
630                 for (i = 0; i < ARRAY_SIZE(params->frame_list); i++)
631                         uclogic_params_frame_cleanup(&params->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  */
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  */
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  */
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  */
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                                                 &params_ptr, &params_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_params_init() - initialize a tablet interface and discover its
1011  * parameters.
1012  *
1013  * @params:     Parameters to fill in (to be cleaned with
1014  *              uclogic_params_cleanup()). Not modified in case of error.
1015  *              Cannot be NULL.
1016  * @hdev:       The HID device of the tablet interface to initialize and get
1017  *              parameters from. Cannot be NULL. Must be using the USB low-level
1018  *              driver, i.e. be an actual USB tablet.
1019  *
1020  * Returns:
1021  *      Zero, if successful. A negative errno code on error.
1022  */
1023 int uclogic_params_init(struct uclogic_params *params,
1024                         struct hid_device *hdev)
1025 {
1026         int rc;
1027         struct usb_device *udev;
1028         __u8  bNumInterfaces;
1029         struct usb_interface *iface;
1030         __u8 bInterfaceNumber;
1031         bool found;
1032         /* The resulting parameters (noop) */
1033         struct uclogic_params p = {0, };
1034
1035         /* Check arguments */
1036         if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) {
1037                 rc = -EINVAL;
1038                 goto cleanup;
1039         }
1040
1041         udev = hid_to_usb_dev(hdev);
1042         bNumInterfaces = udev->config->desc.bNumInterfaces;
1043         iface = to_usb_interface(hdev->dev.parent);
1044         bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1045
1046         /*
1047          * Set replacement report descriptor if the original matches the
1048          * specified size. Otherwise keep interface unchanged.
1049          */
1050 #define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \
1051         uclogic_params_init_with_opt_desc(                  \
1052                 &p, hdev,                                   \
1053                 UCLOGIC_RDESC_##_orig_desc_token##_SIZE,    \
1054                 uclogic_rdesc_##_new_desc_token##_arr,      \
1055                 uclogic_rdesc_##_new_desc_token##_size)
1056
1057 #define VID_PID(_vid, _pid) \
1058         (((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX))
1059
1060         /*
1061          * Handle specific interfaces for specific tablets.
1062          *
1063          * Observe the following logic:
1064          *
1065          * If the interface is recognized as producing certain useful input:
1066          *      Mark interface as valid.
1067          *      Output interface parameters.
1068          * Else, if the interface is recognized as *not* producing any useful
1069          * input:
1070          *      Mark interface as invalid.
1071          * Else:
1072          *      Mark interface as valid.
1073          *      Output noop parameters.
1074          *
1075          * Rule of thumb: it is better to disable a broken interface than let
1076          *                it spew garbage input.
1077          */
1078
1079         switch (VID_PID(hdev->vendor, hdev->product)) {
1080         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1081                      USB_DEVICE_ID_UCLOGIC_TABLET_PF1209):
1082                 rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed);
1083                 if (rc != 0)
1084                         goto cleanup;
1085                 break;
1086         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1087                      USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U):
1088                 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed);
1089                 if (rc != 0)
1090                         goto cleanup;
1091                 break;
1092         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1093                      USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U):
1094                 if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) {
1095                         if (bInterfaceNumber == 0) {
1096                                 /* Try to probe v1 pen parameters */
1097                                 rc = uclogic_params_pen_init_v1(&p.pen,
1098                                                                 &found, hdev);
1099                                 if (rc != 0) {
1100                                         hid_err(hdev,
1101                                                 "pen probing failed: %d\n",
1102                                                 rc);
1103                                         goto cleanup;
1104                                 }
1105                                 if (!found) {
1106                                         hid_warn(hdev,
1107                                                  "pen parameters not found");
1108                                 }
1109                         } else {
1110                                 uclogic_params_init_invalid(&p);
1111                         }
1112                 } else {
1113                         rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed);
1114                         if (rc != 0)
1115                                 goto cleanup;
1116                 }
1117                 break;
1118         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1119                      USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U):
1120                 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed);
1121                 if (rc != 0)
1122                         goto cleanup;
1123                 break;
1124         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1125                      USB_DEVICE_ID_UCLOGIC_TABLET_WP1062):
1126                 rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed);
1127                 if (rc != 0)
1128                         goto cleanup;
1129                 break;
1130         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1131                      USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850):
1132                 switch (bInterfaceNumber) {
1133                 case 0:
1134                         rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0);
1135                         if (rc != 0)
1136                                 goto cleanup;
1137                         break;
1138                 case 1:
1139                         rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1);
1140                         if (rc != 0)
1141                                 goto cleanup;
1142                         break;
1143                 case 2:
1144                         rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2);
1145                         if (rc != 0)
1146                                 goto cleanup;
1147                         break;
1148                 }
1149                 break;
1150         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1151                      USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60):
1152                 /*
1153                  * If it is not a three-interface version, which is known to
1154                  * respond to initialization.
1155                  */
1156                 if (bNumInterfaces != 3) {
1157                         switch (bInterfaceNumber) {
1158                         case 0:
1159                                 rc = WITH_OPT_DESC(TWHA60_ORIG0,
1160                                                         twha60_fixed0);
1161                                 if (rc != 0)
1162                                         goto cleanup;
1163                                 break;
1164                         case 1:
1165                                 rc = WITH_OPT_DESC(TWHA60_ORIG1,
1166                                                         twha60_fixed1);
1167                                 if (rc != 0)
1168                                         goto cleanup;
1169                                 break;
1170                         }
1171                         break;
1172                 }
1173                 fallthrough;
1174         case VID_PID(USB_VENDOR_ID_HUION,
1175                      USB_DEVICE_ID_HUION_TABLET):
1176         case VID_PID(USB_VENDOR_ID_HUION,
1177                      USB_DEVICE_ID_HUION_TABLET2):
1178         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1179                      USB_DEVICE_ID_HUION_TABLET):
1180         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1181                      USB_DEVICE_ID_YIYNOVA_TABLET):
1182         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1183                      USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81):
1184         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1185                      USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3):
1186         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1187                      USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45):
1188         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1189                      USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47):
1190                 rc = uclogic_params_huion_init(&p, hdev);
1191                 if (rc != 0)
1192                         goto cleanup;
1193                 break;
1194         case VID_PID(USB_VENDOR_ID_UGTIZER,
1195                      USB_DEVICE_ID_UGTIZER_TABLET_GP0610):
1196         case VID_PID(USB_VENDOR_ID_UGTIZER,
1197                      USB_DEVICE_ID_UGTIZER_TABLET_GT5040):
1198         case VID_PID(USB_VENDOR_ID_UGEE,
1199                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
1200         case VID_PID(USB_VENDOR_ID_UGEE,
1201                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640):
1202         case VID_PID(USB_VENDOR_ID_UGEE,
1203                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06):
1204         case VID_PID(USB_VENDOR_ID_UGEE,
1205                      USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720):
1206                 /* If this is the pen interface */
1207                 if (bInterfaceNumber == 1) {
1208                         /* Probe v1 pen parameters */
1209                         rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1210                         if (rc != 0) {
1211                                 hid_err(hdev, "pen probing failed: %d\n", rc);
1212                                 goto cleanup;
1213                         }
1214                         if (!found) {
1215                                 hid_warn(hdev, "pen parameters not found");
1216                                 uclogic_params_init_invalid(&p);
1217                         }
1218                 } else {
1219                         uclogic_params_init_invalid(&p);
1220                 }
1221                 break;
1222         case VID_PID(USB_VENDOR_ID_UGEE,
1223                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01):
1224                 /* If this is the pen and frame interface */
1225                 if (bInterfaceNumber == 1) {
1226                         /* Probe v1 pen parameters */
1227                         rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1228                         if (rc != 0) {
1229                                 hid_err(hdev, "pen probing failed: %d\n", rc);
1230                                 goto cleanup;
1231                         }
1232                         /* Initialize frame parameters */
1233                         rc = uclogic_params_frame_init_with_desc(
1234                                 &p.frame_list[0],
1235                                 uclogic_rdesc_xppen_deco01_frame_arr,
1236                                 uclogic_rdesc_xppen_deco01_frame_size,
1237                                 0);
1238                         if (rc != 0)
1239                                 goto cleanup;
1240                 } else {
1241                         uclogic_params_init_invalid(&p);
1242                 }
1243                 break;
1244         case VID_PID(USB_VENDOR_ID_TRUST,
1245                      USB_DEVICE_ID_TRUST_PANORA_TABLET):
1246         case VID_PID(USB_VENDOR_ID_UGEE,
1247                      USB_DEVICE_ID_UGEE_TABLET_G5):
1248                 /* Ignore non-pen interfaces */
1249                 if (bInterfaceNumber != 1) {
1250                         uclogic_params_init_invalid(&p);
1251                         break;
1252                 }
1253
1254                 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1255                 if (rc != 0) {
1256                         hid_err(hdev, "pen probing failed: %d\n", rc);
1257                         goto cleanup;
1258                 } else if (found) {
1259                         rc = uclogic_params_frame_init_with_desc(
1260                                 &p.frame_list[0],
1261                                 uclogic_rdesc_ugee_g5_frame_arr,
1262                                 uclogic_rdesc_ugee_g5_frame_size,
1263                                 UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
1264                         if (rc != 0) {
1265                                 hid_err(hdev,
1266                                         "failed creating frame parameters: %d\n",
1267                                         rc);
1268                                 goto cleanup;
1269                         }
1270                         p.frame_list[0].re_lsb =
1271                                 UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
1272                         p.frame_list[0].dev_id_byte =
1273                                 UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
1274                 } else {
1275                         hid_warn(hdev, "pen parameters not found");
1276                         uclogic_params_init_invalid(&p);
1277                 }
1278
1279                 break;
1280         case VID_PID(USB_VENDOR_ID_UGEE,
1281                      USB_DEVICE_ID_UGEE_TABLET_EX07S):
1282                 /* Ignore non-pen interfaces */
1283                 if (bInterfaceNumber != 1) {
1284                         uclogic_params_init_invalid(&p);
1285                         break;
1286                 }
1287
1288                 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1289                 if (rc != 0) {
1290                         hid_err(hdev, "pen probing failed: %d\n", rc);
1291                         goto cleanup;
1292                 } else if (found) {
1293                         rc = uclogic_params_frame_init_with_desc(
1294                                 &p.frame_list[0],
1295                                 uclogic_rdesc_ugee_ex07_frame_arr,
1296                                 uclogic_rdesc_ugee_ex07_frame_size,
1297                                 0);
1298                         if (rc != 0) {
1299                                 hid_err(hdev,
1300                                         "failed creating frame parameters: %d\n",
1301                                         rc);
1302                                 goto cleanup;
1303                         }
1304                 } else {
1305                         hid_warn(hdev, "pen parameters not found");
1306                         uclogic_params_init_invalid(&p);
1307                 }
1308
1309                 break;
1310         }
1311
1312 #undef VID_PID
1313 #undef WITH_OPT_DESC
1314
1315         /* Output parameters */
1316         memcpy(params, &p, sizeof(*params));
1317         memset(&p, 0, sizeof(p));
1318         rc = 0;
1319 cleanup:
1320         uclogic_params_cleanup(&p);
1321         return rc;
1322 }