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