]> Git Repo - linux.git/blob - drivers/hid/hid-uclogic-params.c
Merge patch series "riscv: Extension parsing fixes"
[linux.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         /* The firmware is used in userspace as unique identifier */
888         strscpy(hdev->uniq, ver_ptr, sizeof(hdev->uniq));
889
890         /* If this is a transition firmware */
891         if (strcmp(ver_ptr, transition_ver) == 0) {
892                 hid_dbg(hdev,
893                         "transition firmware detected, not probing pen v2 parameters\n");
894         } else {
895                 /* Try to probe v2 pen parameters */
896                 rc = uclogic_params_pen_init_v2(&p.pen, &found,
897                                                 &params_ptr, &params_len,
898                                                 hdev);
899                 if (rc != 0) {
900                         hid_err(hdev,
901                                 "failed probing pen v2 parameters: %d\n", rc);
902                         goto cleanup;
903                 } else if (found) {
904                         hid_dbg(hdev, "pen v2 parameters found\n");
905                         /* Create v2 frame button parameters */
906                         rc = uclogic_params_frame_init_with_desc(
907                                         &p.frame_list[0],
908                                         uclogic_rdesc_v2_frame_buttons_arr,
909                                         uclogic_rdesc_v2_frame_buttons_size,
910                                         UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID);
911                         if (rc != 0) {
912                                 hid_err(hdev,
913                                         "failed creating v2 frame button parameters: %d\n",
914                                         rc);
915                                 goto cleanup;
916                         }
917
918                         /* Link from pen sub-report */
919                         p.pen.subreport_list[0].value = 0xe0;
920                         p.pen.subreport_list[0].id =
921                                 UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID;
922
923                         /* If this is the model with touch ring */
924                         if (params_ptr != NULL &&
925                             params_len == sizeof(touch_ring_model_params_buf) &&
926                             memcmp(params_ptr, touch_ring_model_params_buf,
927                                    params_len) == 0) {
928                                 /* Create touch ring parameters */
929                                 rc = uclogic_params_frame_init_with_desc(
930                                         &p.frame_list[1],
931                                         uclogic_rdesc_v2_frame_touch_ring_arr,
932                                         uclogic_rdesc_v2_frame_touch_ring_size,
933                                         UCLOGIC_RDESC_V2_FRAME_TOUCH_ID);
934                                 if (rc != 0) {
935                                         hid_err(hdev,
936                                                 "failed creating v2 frame touch ring parameters: %d\n",
937                                                 rc);
938                                         goto cleanup;
939                                 }
940                                 p.frame_list[1].suffix = "Touch Ring";
941                                 p.frame_list[1].dev_id_byte =
942                                         UCLOGIC_RDESC_V2_FRAME_TOUCH_DEV_ID_BYTE;
943                                 p.frame_list[1].touch_byte = 5;
944                                 p.frame_list[1].touch_max = 12;
945                                 p.frame_list[1].touch_flip_at = 7;
946                         } else {
947                                 /* Create touch strip parameters */
948                                 rc = uclogic_params_frame_init_with_desc(
949                                         &p.frame_list[1],
950                                         uclogic_rdesc_v2_frame_touch_strip_arr,
951                                         uclogic_rdesc_v2_frame_touch_strip_size,
952                                         UCLOGIC_RDESC_V2_FRAME_TOUCH_ID);
953                                 if (rc != 0) {
954                                         hid_err(hdev,
955                                                 "failed creating v2 frame touch strip parameters: %d\n",
956                                                 rc);
957                                         goto cleanup;
958                                 }
959                                 p.frame_list[1].suffix = "Touch Strip";
960                                 p.frame_list[1].dev_id_byte =
961                                         UCLOGIC_RDESC_V2_FRAME_TOUCH_DEV_ID_BYTE;
962                                 p.frame_list[1].touch_byte = 5;
963                                 p.frame_list[1].touch_max = 8;
964                         }
965
966                         /* Link from pen sub-report */
967                         p.pen.subreport_list[1].value = 0xf0;
968                         p.pen.subreport_list[1].id =
969                                 UCLOGIC_RDESC_V2_FRAME_TOUCH_ID;
970
971                         /* Create v2 frame dial parameters */
972                         rc = uclogic_params_frame_init_with_desc(
973                                         &p.frame_list[2],
974                                         uclogic_rdesc_v2_frame_dial_arr,
975                                         uclogic_rdesc_v2_frame_dial_size,
976                                         UCLOGIC_RDESC_V2_FRAME_DIAL_ID);
977                         if (rc != 0) {
978                                 hid_err(hdev,
979                                         "failed creating v2 frame dial parameters: %d\n",
980                                         rc);
981                                 goto cleanup;
982                         }
983                         p.frame_list[2].suffix = "Dial";
984                         p.frame_list[2].dev_id_byte =
985                                 UCLOGIC_RDESC_V2_FRAME_DIAL_DEV_ID_BYTE;
986                         p.frame_list[2].bitmap_dial_byte = 5;
987
988                         /* Link from pen sub-report */
989                         p.pen.subreport_list[2].value = 0xf1;
990                         p.pen.subreport_list[2].id =
991                                 UCLOGIC_RDESC_V2_FRAME_DIAL_ID;
992
993                         goto output;
994                 }
995                 hid_dbg(hdev, "pen v2 parameters not found\n");
996         }
997
998         /* Try to probe v1 pen parameters */
999         rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1000         if (rc != 0) {
1001                 hid_err(hdev,
1002                         "failed probing pen v1 parameters: %d\n", rc);
1003                 goto cleanup;
1004         } else if (found) {
1005                 hid_dbg(hdev, "pen v1 parameters found\n");
1006                 /* Try to probe v1 frame */
1007                 rc = uclogic_params_frame_init_v1(&p.frame_list[0],
1008                                                   &found, hdev);
1009                 if (rc != 0) {
1010                         hid_err(hdev, "v1 frame probing failed: %d\n", rc);
1011                         goto cleanup;
1012                 }
1013                 hid_dbg(hdev, "frame v1 parameters%s found\n",
1014                         (found ? "" : " not"));
1015                 if (found) {
1016                         /* Link frame button subreports from pen reports */
1017                         p.pen.subreport_list[0].value = 0xe0;
1018                         p.pen.subreport_list[0].id =
1019                                 UCLOGIC_RDESC_V1_FRAME_ID;
1020                 }
1021                 goto output;
1022         }
1023         hid_dbg(hdev, "pen v1 parameters not found\n");
1024
1025         uclogic_params_init_invalid(&p);
1026
1027 output:
1028         /* Output parameters */
1029         memcpy(params, &p, sizeof(*params));
1030         memset(&p, 0, sizeof(p));
1031         rc = 0;
1032 cleanup:
1033         kfree(params_ptr);
1034         kfree(ver_ptr);
1035         uclogic_params_cleanup(&p);
1036         return rc;
1037 }
1038
1039 /**
1040  * uclogic_probe_interface() - some tablets, like the Parblo A610 PLUS V2 or
1041  * the XP-PEN Deco Mini 7, need to be initialized by sending them magic data.
1042  *
1043  * @hdev:       The HID device of the tablet interface to initialize and get
1044  *              parameters from. Cannot be NULL.
1045  * @magic_arr:  The magic data that should be sent to probe the interface.
1046  *              Cannot be NULL.
1047  * @magic_size: Size of the magic data.
1048  * @endpoint:   Endpoint where the magic data should be sent.
1049  *
1050  * Returns:
1051  *      Zero, if successful. A negative errno code on error.
1052  */
1053 static int uclogic_probe_interface(struct hid_device *hdev, const u8 *magic_arr,
1054                                    size_t magic_size, int endpoint)
1055 {
1056         struct usb_device *udev;
1057         unsigned int pipe = 0;
1058         int sent;
1059         u8 *buf = NULL;
1060         int rc = 0;
1061
1062         if (!hdev || !magic_arr) {
1063                 rc = -EINVAL;
1064                 goto cleanup;
1065         }
1066
1067         buf = kmemdup(magic_arr, magic_size, GFP_KERNEL);
1068         if (!buf) {
1069                 rc = -ENOMEM;
1070                 goto cleanup;
1071         }
1072
1073         udev = hid_to_usb_dev(hdev);
1074         pipe = usb_sndintpipe(udev, endpoint);
1075
1076         rc = usb_interrupt_msg(udev, pipe, buf, magic_size, &sent, 1000);
1077         if (rc || sent != magic_size) {
1078                 hid_err(hdev, "Interface probing failed: %d\n", rc);
1079                 rc = -1;
1080                 goto cleanup;
1081         }
1082
1083         rc = 0;
1084 cleanup:
1085         kfree(buf);
1086         return rc;
1087 }
1088
1089 /**
1090  * uclogic_params_parse_ugee_v2_desc - parse the string descriptor containing
1091  * pen and frame parameters returned by UGEE v2 devices.
1092  *
1093  * @str_desc:           String descriptor, cannot be NULL.
1094  * @str_desc_size:      Size of the string descriptor.
1095  * @desc_params:        Output description params list.
1096  * @desc_params_size:   Size of the output description params list.
1097  * @frame_type:         Output frame type.
1098  *
1099  * Returns:
1100  *      Zero, if successful. A negative errno code on error.
1101  */
1102 static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc,
1103                                              size_t str_desc_size,
1104                                              s32 *desc_params,
1105                                              size_t desc_params_size,
1106                                              enum uclogic_params_frame_type *frame_type)
1107 {
1108         s32 pen_x_lm, pen_y_lm;
1109         s32 pen_x_pm, pen_y_pm;
1110         s32 pen_pressure_lm;
1111         s32 frame_num_buttons;
1112         s32 resolution;
1113
1114         /* Minimum descriptor length required, maximum seen so far is 14 */
1115         const int min_str_desc_size = 12;
1116
1117         if (!str_desc || str_desc_size < min_str_desc_size)
1118                 return -EINVAL;
1119
1120         if (desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
1121                 return -EINVAL;
1122
1123         pen_x_lm = get_unaligned_le16(str_desc + 2);
1124         pen_y_lm = get_unaligned_le16(str_desc + 4);
1125         frame_num_buttons = str_desc[6];
1126         *frame_type = str_desc[7];
1127         pen_pressure_lm = get_unaligned_le16(str_desc + 8);
1128
1129         resolution = get_unaligned_le16(str_desc + 10);
1130         if (resolution == 0) {
1131                 pen_x_pm = 0;
1132                 pen_y_pm = 0;
1133         } else {
1134                 pen_x_pm = pen_x_lm * 1000 / resolution;
1135                 pen_y_pm = pen_y_lm * 1000 / resolution;
1136         }
1137
1138         desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = pen_x_lm;
1139         desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = pen_x_pm;
1140         desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = pen_y_lm;
1141         desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = pen_y_pm;
1142         desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = pen_pressure_lm;
1143         desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = frame_num_buttons;
1144
1145         return 0;
1146 }
1147
1148 /**
1149  * uclogic_params_ugee_v2_init_frame_buttons() - initialize a UGEE v2 frame with
1150  * buttons.
1151  * @p:                  Parameters to fill in, cannot be NULL.
1152  * @desc_params:        Device description params list.
1153  * @desc_params_size:   Size of the description params list.
1154  *
1155  * Returns:
1156  *      Zero, if successful. A negative errno code on error.
1157  */
1158 static int uclogic_params_ugee_v2_init_frame_buttons(struct uclogic_params *p,
1159                                                      const s32 *desc_params,
1160                                                      size_t desc_params_size)
1161 {
1162         __u8 *rdesc_frame = NULL;
1163         int rc = 0;
1164
1165         if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
1166                 return -EINVAL;
1167
1168         rdesc_frame = uclogic_rdesc_template_apply(
1169                                 uclogic_rdesc_ugee_v2_frame_btn_template_arr,
1170                                 uclogic_rdesc_ugee_v2_frame_btn_template_size,
1171                                 desc_params, UCLOGIC_RDESC_PH_ID_NUM);
1172         if (!rdesc_frame)
1173                 return -ENOMEM;
1174
1175         rc = uclogic_params_frame_init_with_desc(&p->frame_list[0],
1176                                                  rdesc_frame,
1177                                                  uclogic_rdesc_ugee_v2_frame_btn_template_size,
1178                                                  UCLOGIC_RDESC_V1_FRAME_ID);
1179         kfree(rdesc_frame);
1180         return rc;
1181 }
1182
1183 /**
1184  * uclogic_params_ugee_v2_init_frame_dial() - initialize a UGEE v2 frame with a
1185  * bitmap dial.
1186  * @p:                  Parameters to fill in, cannot be NULL.
1187  * @desc_params:        Device description params list.
1188  * @desc_params_size:   Size of the description params list.
1189  *
1190  * Returns:
1191  *      Zero, if successful. A negative errno code on error.
1192  */
1193 static int uclogic_params_ugee_v2_init_frame_dial(struct uclogic_params *p,
1194                                                   const s32 *desc_params,
1195                                                   size_t desc_params_size)
1196 {
1197         __u8 *rdesc_frame = NULL;
1198         int rc = 0;
1199
1200         if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
1201                 return -EINVAL;
1202
1203         rdesc_frame = uclogic_rdesc_template_apply(
1204                                 uclogic_rdesc_ugee_v2_frame_dial_template_arr,
1205                                 uclogic_rdesc_ugee_v2_frame_dial_template_size,
1206                                 desc_params, UCLOGIC_RDESC_PH_ID_NUM);
1207         if (!rdesc_frame)
1208                 return -ENOMEM;
1209
1210         rc = uclogic_params_frame_init_with_desc(&p->frame_list[0],
1211                                                  rdesc_frame,
1212                                                  uclogic_rdesc_ugee_v2_frame_dial_template_size,
1213                                                  UCLOGIC_RDESC_V1_FRAME_ID);
1214         kfree(rdesc_frame);
1215         if (rc)
1216                 return rc;
1217
1218         p->frame_list[0].bitmap_dial_byte = 7;
1219         return 0;
1220 }
1221
1222 /**
1223  * uclogic_params_ugee_v2_init_frame_mouse() - initialize a UGEE v2 frame with a
1224  * mouse.
1225  * @p:                  Parameters to fill in, cannot be NULL.
1226  *
1227  * Returns:
1228  *      Zero, if successful. A negative errno code on error.
1229  */
1230 static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p)
1231 {
1232         int rc = 0;
1233
1234         if (!p)
1235                 return -EINVAL;
1236
1237         rc = uclogic_params_frame_init_with_desc(&p->frame_list[1],
1238                                                  uclogic_rdesc_ugee_v2_frame_mouse_template_arr,
1239                                                  uclogic_rdesc_ugee_v2_frame_mouse_template_size,
1240                                                  UCLOGIC_RDESC_V1_FRAME_ID);
1241         return rc;
1242 }
1243
1244 /**
1245  * uclogic_params_ugee_v2_has_battery() - check whether a UGEE v2 device has
1246  * battery or not.
1247  * @hdev:       The HID device of the tablet interface.
1248  *
1249  * Returns:
1250  *      True if the device has battery, false otherwise.
1251  */
1252 static bool uclogic_params_ugee_v2_has_battery(struct hid_device *hdev)
1253 {
1254         struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
1255
1256         if (drvdata->quirks & UCLOGIC_BATTERY_QUIRK)
1257                 return true;
1258
1259         /* The XP-PEN Deco LW vendor, product and version are identical to the
1260          * Deco L. The only difference reported by their firmware is the product
1261          * name. Add a quirk to support battery reporting on the wireless
1262          * version.
1263          */
1264         if (hdev->vendor == USB_VENDOR_ID_UGEE &&
1265             hdev->product == USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) {
1266                 struct usb_device *udev = hid_to_usb_dev(hdev);
1267
1268                 if (strstarts(udev->product, "Deco LW"))
1269                         return true;
1270         }
1271
1272         return false;
1273 }
1274
1275 /**
1276  * uclogic_params_ugee_v2_init_battery() - initialize UGEE v2 battery reporting.
1277  * @hdev:       The HID device of the tablet interface, cannot be NULL.
1278  * @p:          Parameters to fill in, cannot be NULL.
1279  *
1280  * Returns:
1281  *      Zero, if successful. A negative errno code on error.
1282  */
1283 static int uclogic_params_ugee_v2_init_battery(struct hid_device *hdev,
1284                                                struct uclogic_params *p)
1285 {
1286         int rc = 0;
1287
1288         if (!hdev || !p)
1289                 return -EINVAL;
1290
1291         /* Some tablets contain invalid characters in hdev->uniq, throwing a
1292          * "hwmon: '<name>' is not a valid name attribute, please fix" error.
1293          * Use the device vendor and product IDs instead.
1294          */
1295         snprintf(hdev->uniq, sizeof(hdev->uniq), "%x-%x", hdev->vendor,
1296                  hdev->product);
1297
1298         rc = uclogic_params_frame_init_with_desc(&p->frame_list[1],
1299                                                  uclogic_rdesc_ugee_v2_battery_template_arr,
1300                                                  uclogic_rdesc_ugee_v2_battery_template_size,
1301                                                  UCLOGIC_RDESC_UGEE_V2_BATTERY_ID);
1302         if (rc)
1303                 return rc;
1304
1305         p->frame_list[1].suffix = "Battery";
1306         p->pen.subreport_list[1].value = 0xf2;
1307         p->pen.subreport_list[1].id = UCLOGIC_RDESC_UGEE_V2_BATTERY_ID;
1308
1309         return rc;
1310 }
1311
1312 /**
1313  * uclogic_params_ugee_v2_reconnect_work() - When a wireless tablet looses
1314  * connection to the USB dongle and reconnects, either because of its physical
1315  * distance or because it was switches off and on using the frame's switch,
1316  * uclogic_probe_interface() needs to be called again to enable the tablet.
1317  *
1318  * @work: The work that triggered this function.
1319  */
1320 static void uclogic_params_ugee_v2_reconnect_work(struct work_struct *work)
1321 {
1322         struct uclogic_raw_event_hook *event_hook;
1323
1324         event_hook = container_of(work, struct uclogic_raw_event_hook, work);
1325         uclogic_probe_interface(event_hook->hdev, uclogic_ugee_v2_probe_arr,
1326                                 uclogic_ugee_v2_probe_size,
1327                                 uclogic_ugee_v2_probe_endpoint);
1328 }
1329
1330 /**
1331  * uclogic_params_ugee_v2_init_event_hooks() - initialize the list of events
1332  * to be hooked for UGEE v2 devices.
1333  * @hdev:       The HID device of the tablet interface to initialize and get
1334  *              parameters from.
1335  * @p:          Parameters to fill in, cannot be NULL.
1336  *
1337  * Returns:
1338  *      Zero, if successful. A negative errno code on error.
1339  */
1340 static int uclogic_params_ugee_v2_init_event_hooks(struct hid_device *hdev,
1341                                                    struct uclogic_params *p)
1342 {
1343         struct uclogic_raw_event_hook *event_hook;
1344         __u8 reconnect_event[] = {
1345                 /* Event received on wireless tablet reconnection */
1346                 0x02, 0xF8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1347         };
1348
1349         if (!p)
1350                 return -EINVAL;
1351
1352         /* The reconnection event is only received if the tablet has battery */
1353         if (!uclogic_params_ugee_v2_has_battery(hdev))
1354                 return 0;
1355
1356         p->event_hooks = kzalloc(sizeof(*p->event_hooks), GFP_KERNEL);
1357         if (!p->event_hooks)
1358                 return -ENOMEM;
1359
1360         INIT_LIST_HEAD(&p->event_hooks->list);
1361
1362         event_hook = kzalloc(sizeof(*event_hook), GFP_KERNEL);
1363         if (!event_hook)
1364                 return -ENOMEM;
1365
1366         INIT_WORK(&event_hook->work, uclogic_params_ugee_v2_reconnect_work);
1367         event_hook->hdev = hdev;
1368         event_hook->size = ARRAY_SIZE(reconnect_event);
1369         event_hook->event = kmemdup(reconnect_event, event_hook->size, GFP_KERNEL);
1370         if (!event_hook->event)
1371                 return -ENOMEM;
1372
1373         list_add_tail(&event_hook->list, &p->event_hooks->list);
1374
1375         return 0;
1376 }
1377
1378 /**
1379  * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by
1380  * discovering their parameters.
1381  *
1382  * These tables, internally designed as v2 to differentiate them from older
1383  * models, expect a payload of magic data in orther to be switched to the fully
1384  * functional mode and expose their parameters in a similar way to the
1385  * information present in uclogic_params_pen_init_v1() but with some
1386  * differences.
1387  *
1388  * @params:     Parameters to fill in (to be cleaned with
1389  *              uclogic_params_cleanup()). Not modified in case of error.
1390  *              Cannot be NULL.
1391  * @hdev:       The HID device of the tablet interface to initialize and get
1392  *              parameters from. Cannot be NULL.
1393  *
1394  * Returns:
1395  *      Zero, if successful. A negative errno code on error.
1396  */
1397 static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
1398                                        struct hid_device *hdev)
1399 {
1400         int rc = 0;
1401         struct uclogic_drvdata *drvdata;
1402         struct usb_interface *iface;
1403         __u8 bInterfaceNumber;
1404         const int str_desc_len = 12;
1405         __u8 *str_desc = NULL;
1406         __u8 *rdesc_pen = NULL;
1407         s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
1408         enum uclogic_params_frame_type frame_type;
1409         /* The resulting parameters (noop) */
1410         struct uclogic_params p = {0, };
1411
1412         if (!params || !hdev) {
1413                 rc = -EINVAL;
1414                 goto cleanup;
1415         }
1416
1417         drvdata = hid_get_drvdata(hdev);
1418         iface = to_usb_interface(hdev->dev.parent);
1419         bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1420
1421         if (bInterfaceNumber == 0) {
1422                 rc = uclogic_params_ugee_v2_init_frame_mouse(&p);
1423                 if (rc)
1424                         goto cleanup;
1425
1426                 goto output;
1427         }
1428
1429         if (bInterfaceNumber != 2) {
1430                 uclogic_params_init_invalid(&p);
1431                 goto output;
1432         }
1433
1434         /*
1435          * Initialize the interface by sending magic data.
1436          * The specific data was discovered by sniffing the Windows driver
1437          * traffic.
1438          */
1439         rc = uclogic_probe_interface(hdev, uclogic_ugee_v2_probe_arr,
1440                                      uclogic_ugee_v2_probe_size,
1441                                      uclogic_ugee_v2_probe_endpoint);
1442         if (rc) {
1443                 uclogic_params_init_invalid(&p);
1444                 goto output;
1445         }
1446
1447         /*
1448          * Read the string descriptor containing pen and frame parameters.
1449          * The specific string descriptor and data were discovered by sniffing
1450          * the Windows driver traffic.
1451          */
1452         rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len);
1453         if (rc != str_desc_len) {
1454                 hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc);
1455                 uclogic_params_init_invalid(&p);
1456                 goto output;
1457         }
1458
1459         rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len,
1460                                                desc_params,
1461                                                ARRAY_SIZE(desc_params),
1462                                                &frame_type);
1463         if (rc)
1464                 goto cleanup;
1465
1466         kfree(str_desc);
1467         str_desc = NULL;
1468
1469         /* Initialize the pen interface */
1470         rdesc_pen = uclogic_rdesc_template_apply(
1471                                 uclogic_rdesc_ugee_v2_pen_template_arr,
1472                                 uclogic_rdesc_ugee_v2_pen_template_size,
1473                                 desc_params, ARRAY_SIZE(desc_params));
1474         if (!rdesc_pen) {
1475                 rc = -ENOMEM;
1476                 goto cleanup;
1477         }
1478
1479         p.pen.desc_ptr = rdesc_pen;
1480         p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size;
1481         p.pen.id = 0x02;
1482         p.pen.subreport_list[0].value = 0xf0;
1483         p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
1484
1485         /* Initialize the frame interface */
1486         if (drvdata->quirks & UCLOGIC_MOUSE_FRAME_QUIRK)
1487                 frame_type = UCLOGIC_PARAMS_FRAME_MOUSE;
1488
1489         switch (frame_type) {
1490         case UCLOGIC_PARAMS_FRAME_DIAL:
1491         case UCLOGIC_PARAMS_FRAME_MOUSE:
1492                 rc = uclogic_params_ugee_v2_init_frame_dial(&p, desc_params,
1493                                                             ARRAY_SIZE(desc_params));
1494                 break;
1495         case UCLOGIC_PARAMS_FRAME_BUTTONS:
1496         default:
1497                 rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params,
1498                                                                ARRAY_SIZE(desc_params));
1499                 break;
1500         }
1501
1502         if (rc)
1503                 goto cleanup;
1504
1505         /* Initialize the battery interface*/
1506         if (uclogic_params_ugee_v2_has_battery(hdev)) {
1507                 rc = uclogic_params_ugee_v2_init_battery(hdev, &p);
1508                 if (rc) {
1509                         hid_err(hdev, "error initializing battery: %d\n", rc);
1510                         goto cleanup;
1511                 }
1512         }
1513
1514         /* Create a list of raw events to be ignored */
1515         rc = uclogic_params_ugee_v2_init_event_hooks(hdev, &p);
1516         if (rc) {
1517                 hid_err(hdev, "error initializing event hook list: %d\n", rc);
1518                 goto cleanup;
1519         }
1520
1521 output:
1522         /* Output parameters */
1523         memcpy(params, &p, sizeof(*params));
1524         memset(&p, 0, sizeof(p));
1525         rc = 0;
1526 cleanup:
1527         kfree(str_desc);
1528         uclogic_params_cleanup(&p);
1529         return rc;
1530 }
1531
1532 /**
1533  * uclogic_params_init() - initialize a tablet interface and discover its
1534  * parameters.
1535  *
1536  * @params:     Parameters to fill in (to be cleaned with
1537  *              uclogic_params_cleanup()). Not modified in case of error.
1538  *              Cannot be NULL.
1539  * @hdev:       The HID device of the tablet interface to initialize and get
1540  *              parameters from. Cannot be NULL. Must be using the USB low-level
1541  *              driver, i.e. be an actual USB tablet.
1542  *
1543  * Returns:
1544  *      Zero, if successful. A negative errno code on error.
1545  */
1546 int uclogic_params_init(struct uclogic_params *params,
1547                         struct hid_device *hdev)
1548 {
1549         int rc;
1550         struct usb_device *udev;
1551         __u8  bNumInterfaces;
1552         struct usb_interface *iface;
1553         __u8 bInterfaceNumber;
1554         bool found;
1555         /* The resulting parameters (noop) */
1556         struct uclogic_params p = {0, };
1557
1558         /* Check arguments */
1559         if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) {
1560                 rc = -EINVAL;
1561                 goto cleanup;
1562         }
1563
1564         udev = hid_to_usb_dev(hdev);
1565         bNumInterfaces = udev->config->desc.bNumInterfaces;
1566         iface = to_usb_interface(hdev->dev.parent);
1567         bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1568
1569         /*
1570          * Set replacement report descriptor if the original matches the
1571          * specified size. Otherwise keep interface unchanged.
1572          */
1573 #define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \
1574         uclogic_params_init_with_opt_desc(                  \
1575                 &p, hdev,                                   \
1576                 UCLOGIC_RDESC_##_orig_desc_token##_SIZE,    \
1577                 uclogic_rdesc_##_new_desc_token##_arr,      \
1578                 uclogic_rdesc_##_new_desc_token##_size)
1579
1580 #define VID_PID(_vid, _pid) \
1581         (((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX))
1582
1583         /*
1584          * Handle specific interfaces for specific tablets.
1585          *
1586          * Observe the following logic:
1587          *
1588          * If the interface is recognized as producing certain useful input:
1589          *      Mark interface as valid.
1590          *      Output interface parameters.
1591          * Else, if the interface is recognized as *not* producing any useful
1592          * input:
1593          *      Mark interface as invalid.
1594          * Else:
1595          *      Mark interface as valid.
1596          *      Output noop parameters.
1597          *
1598          * Rule of thumb: it is better to disable a broken interface than let
1599          *                it spew garbage input.
1600          */
1601
1602         switch (VID_PID(hdev->vendor, hdev->product)) {
1603         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1604                      USB_DEVICE_ID_UCLOGIC_TABLET_PF1209):
1605                 rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed);
1606                 if (rc != 0)
1607                         goto cleanup;
1608                 break;
1609         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1610                      USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U):
1611                 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed);
1612                 if (rc != 0)
1613                         goto cleanup;
1614                 break;
1615         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1616                      USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U):
1617                 if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) {
1618                         if (bInterfaceNumber == 0) {
1619                                 /* Try to probe v1 pen parameters */
1620                                 rc = uclogic_params_pen_init_v1(&p.pen,
1621                                                                 &found, hdev);
1622                                 if (rc != 0) {
1623                                         hid_err(hdev,
1624                                                 "pen probing failed: %d\n",
1625                                                 rc);
1626                                         goto cleanup;
1627                                 }
1628                                 if (!found) {
1629                                         hid_warn(hdev,
1630                                                  "pen parameters not found");
1631                                 }
1632                         } else {
1633                                 uclogic_params_init_invalid(&p);
1634                         }
1635                 } else {
1636                         rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed);
1637                         if (rc != 0)
1638                                 goto cleanup;
1639                 }
1640                 break;
1641         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1642                      USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U):
1643                 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed);
1644                 if (rc != 0)
1645                         goto cleanup;
1646                 break;
1647         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1648                      USB_DEVICE_ID_UCLOGIC_TABLET_WP1062):
1649                 rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed);
1650                 if (rc != 0)
1651                         goto cleanup;
1652                 break;
1653         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1654                      USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850):
1655                 switch (bInterfaceNumber) {
1656                 case 0:
1657                         rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0);
1658                         if (rc != 0)
1659                                 goto cleanup;
1660                         break;
1661                 case 1:
1662                         rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1);
1663                         if (rc != 0)
1664                                 goto cleanup;
1665                         break;
1666                 case 2:
1667                         rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2);
1668                         if (rc != 0)
1669                                 goto cleanup;
1670                         break;
1671                 }
1672                 break;
1673         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1674                      USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60):
1675                 /*
1676                  * If it is not a three-interface version, which is known to
1677                  * respond to initialization.
1678                  */
1679                 if (bNumInterfaces != 3) {
1680                         switch (bInterfaceNumber) {
1681                         case 0:
1682                                 rc = WITH_OPT_DESC(TWHA60_ORIG0,
1683                                                         twha60_fixed0);
1684                                 if (rc != 0)
1685                                         goto cleanup;
1686                                 break;
1687                         case 1:
1688                                 rc = WITH_OPT_DESC(TWHA60_ORIG1,
1689                                                         twha60_fixed1);
1690                                 if (rc != 0)
1691                                         goto cleanup;
1692                                 break;
1693                         }
1694                         break;
1695                 }
1696                 fallthrough;
1697         case VID_PID(USB_VENDOR_ID_HUION,
1698                      USB_DEVICE_ID_HUION_TABLET):
1699         case VID_PID(USB_VENDOR_ID_HUION,
1700                      USB_DEVICE_ID_HUION_TABLET2):
1701         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1702                      USB_DEVICE_ID_HUION_TABLET):
1703         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1704                      USB_DEVICE_ID_YIYNOVA_TABLET):
1705         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1706                      USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81):
1707         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1708                      USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3):
1709         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1710                      USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45):
1711         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1712                      USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47):
1713                 rc = uclogic_params_huion_init(&p, hdev);
1714                 if (rc != 0)
1715                         goto cleanup;
1716                 break;
1717         case VID_PID(USB_VENDOR_ID_UGTIZER,
1718                      USB_DEVICE_ID_UGTIZER_TABLET_GP0610):
1719         case VID_PID(USB_VENDOR_ID_UGTIZER,
1720                      USB_DEVICE_ID_UGTIZER_TABLET_GT5040):
1721         case VID_PID(USB_VENDOR_ID_UGEE,
1722                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
1723         case VID_PID(USB_VENDOR_ID_UGEE,
1724                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640):
1725         case VID_PID(USB_VENDOR_ID_UGEE,
1726                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06):
1727         case VID_PID(USB_VENDOR_ID_UGEE,
1728                      USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720):
1729                 /* If this is the pen interface */
1730                 if (bInterfaceNumber == 1) {
1731                         /* Probe v1 pen parameters */
1732                         rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1733                         if (rc != 0) {
1734                                 hid_err(hdev, "pen probing failed: %d\n", rc);
1735                                 goto cleanup;
1736                         }
1737                         if (!found) {
1738                                 hid_warn(hdev, "pen parameters not found");
1739                                 uclogic_params_init_invalid(&p);
1740                         }
1741                 } else {
1742                         uclogic_params_init_invalid(&p);
1743                 }
1744                 break;
1745         case VID_PID(USB_VENDOR_ID_UGEE,
1746                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01):
1747                 /* If this is the pen and frame interface */
1748                 if (bInterfaceNumber == 1) {
1749                         /* Probe v1 pen parameters */
1750                         rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1751                         if (rc != 0) {
1752                                 hid_err(hdev, "pen probing failed: %d\n", rc);
1753                                 goto cleanup;
1754                         }
1755                         /* Initialize frame parameters */
1756                         rc = uclogic_params_frame_init_with_desc(
1757                                 &p.frame_list[0],
1758                                 uclogic_rdesc_xppen_deco01_frame_arr,
1759                                 uclogic_rdesc_xppen_deco01_frame_size,
1760                                 0);
1761                         if (rc != 0)
1762                                 goto cleanup;
1763                 } else {
1764                         uclogic_params_init_invalid(&p);
1765                 }
1766                 break;
1767         case VID_PID(USB_VENDOR_ID_UGEE,
1768                      USB_DEVICE_ID_UGEE_PARBLO_A610_PRO):
1769         case VID_PID(USB_VENDOR_ID_UGEE,
1770                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2):
1771         case VID_PID(USB_VENDOR_ID_UGEE,
1772                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L):
1773         case VID_PID(USB_VENDOR_ID_UGEE,
1774                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW):
1775         case VID_PID(USB_VENDOR_ID_UGEE,
1776                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S):
1777         case VID_PID(USB_VENDOR_ID_UGEE,
1778                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW):
1779                 rc = uclogic_params_ugee_v2_init(&p, hdev);
1780                 if (rc != 0)
1781                         goto cleanup;
1782                 break;
1783         case VID_PID(USB_VENDOR_ID_TRUST,
1784                      USB_DEVICE_ID_TRUST_PANORA_TABLET):
1785         case VID_PID(USB_VENDOR_ID_UGEE,
1786                      USB_DEVICE_ID_UGEE_TABLET_G5):
1787                 /* Ignore non-pen interfaces */
1788                 if (bInterfaceNumber != 1) {
1789                         uclogic_params_init_invalid(&p);
1790                         break;
1791                 }
1792
1793                 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1794                 if (rc != 0) {
1795                         hid_err(hdev, "pen probing failed: %d\n", rc);
1796                         goto cleanup;
1797                 } else if (found) {
1798                         rc = uclogic_params_frame_init_with_desc(
1799                                 &p.frame_list[0],
1800                                 uclogic_rdesc_ugee_g5_frame_arr,
1801                                 uclogic_rdesc_ugee_g5_frame_size,
1802                                 UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
1803                         if (rc != 0) {
1804                                 hid_err(hdev,
1805                                         "failed creating frame parameters: %d\n",
1806                                         rc);
1807                                 goto cleanup;
1808                         }
1809                         p.frame_list[0].re_lsb =
1810                                 UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
1811                         p.frame_list[0].dev_id_byte =
1812                                 UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
1813                 } else {
1814                         hid_warn(hdev, "pen parameters not found");
1815                         uclogic_params_init_invalid(&p);
1816                 }
1817
1818                 break;
1819         case VID_PID(USB_VENDOR_ID_UGEE,
1820                      USB_DEVICE_ID_UGEE_TABLET_EX07S):
1821                 /* Ignore non-pen interfaces */
1822                 if (bInterfaceNumber != 1) {
1823                         uclogic_params_init_invalid(&p);
1824                         break;
1825                 }
1826
1827                 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1828                 if (rc != 0) {
1829                         hid_err(hdev, "pen probing failed: %d\n", rc);
1830                         goto cleanup;
1831                 } else if (found) {
1832                         rc = uclogic_params_frame_init_with_desc(
1833                                 &p.frame_list[0],
1834                                 uclogic_rdesc_ugee_ex07_frame_arr,
1835                                 uclogic_rdesc_ugee_ex07_frame_size,
1836                                 0);
1837                         if (rc != 0) {
1838                                 hid_err(hdev,
1839                                         "failed creating frame parameters: %d\n",
1840                                         rc);
1841                                 goto cleanup;
1842                         }
1843                 } else {
1844                         hid_warn(hdev, "pen parameters not found");
1845                         uclogic_params_init_invalid(&p);
1846                 }
1847
1848                 break;
1849         }
1850
1851 #undef VID_PID
1852 #undef WITH_OPT_DESC
1853
1854         /* Output parameters */
1855         memcpy(params, &p, sizeof(*params));
1856         memset(&p, 0, sizeof(p));
1857         rc = 0;
1858 cleanup:
1859         uclogic_params_cleanup(&p);
1860         return rc;
1861 }
1862
1863 #ifdef CONFIG_HID_KUNIT_TEST
1864 #include "hid-uclogic-params-test.c"
1865 #endif
This page took 0.15105 seconds and 4 git commands to generate.