GNU Linux-libre 6.1.24-gnu
[releases.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 - free resources used by struct uclogic_params
620  * (tablet interface's parameters).
621  * Can be called repeatedly.
622  *
623  * @params:     Input parameters to cleanup. Cannot be NULL.
624  */
625 void uclogic_params_cleanup(struct uclogic_params *params)
626 {
627         if (!params->invalid) {
628                 size_t i;
629                 kfree(params->desc_ptr);
630                 uclogic_params_pen_cleanup(&params->pen);
631                 for (i = 0; i < ARRAY_SIZE(params->frame_list); i++)
632                         uclogic_params_frame_cleanup(&params->frame_list[i]);
633
634                 memset(params, 0, sizeof(*params));
635         }
636 }
637
638 /**
639  * uclogic_params_get_desc() - Get a replacement report descriptor for a
640  *                             tablet's interface.
641  *
642  * @params:     The parameters of a tablet interface to get report
643  *              descriptor for. Cannot be NULL.
644  * @pdesc:      Location for the resulting, kmalloc-allocated report
645  *              descriptor pointer, or for NULL, if there's no replacement
646  *              report descriptor. Not modified in case of error. Cannot be
647  *              NULL.
648  * @psize:      Location for the resulting report descriptor size, not set if
649  *              there's no replacement report descriptor. Not modified in case
650  *              of error. Cannot be NULL.
651  *
652  * Returns:
653  *      Zero, if successful.
654  *      -EINVAL, if invalid arguments are supplied.
655  *      -ENOMEM, if failed to allocate memory.
656  */
657 int uclogic_params_get_desc(const struct uclogic_params *params,
658                                 __u8 **pdesc,
659                                 unsigned int *psize)
660 {
661         int rc = -ENOMEM;
662         bool present = false;
663         unsigned int size = 0;
664         __u8 *desc = NULL;
665         size_t i;
666
667         /* Check arguments */
668         if (params == NULL || pdesc == NULL || psize == NULL)
669                 return -EINVAL;
670
671         /* Concatenate descriptors */
672 #define ADD_DESC(_desc_ptr, _desc_size) \
673         do {                                                        \
674                 unsigned int new_size;                              \
675                 __u8 *new_desc;                                     \
676                 if ((_desc_ptr) == NULL) {                          \
677                         break;                                      \
678                 }                                                   \
679                 new_size = size + (_desc_size);                     \
680                 new_desc = krealloc(desc, new_size, GFP_KERNEL);    \
681                 if (new_desc == NULL) {                             \
682                         goto cleanup;                               \
683                 }                                                   \
684                 memcpy(new_desc + size, (_desc_ptr), (_desc_size)); \
685                 desc = new_desc;                                    \
686                 size = new_size;                                    \
687                 present = true;                                     \
688         } while (0)
689
690         ADD_DESC(params->desc_ptr, params->desc_size);
691         ADD_DESC(params->pen.desc_ptr, params->pen.desc_size);
692         for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) {
693                 ADD_DESC(params->frame_list[i].desc_ptr,
694                                 params->frame_list[i].desc_size);
695         }
696
697 #undef ADD_DESC
698
699         if (present) {
700                 *pdesc = desc;
701                 *psize = size;
702                 desc = NULL;
703         }
704         rc = 0;
705 cleanup:
706         kfree(desc);
707         return rc;
708 }
709
710 /**
711  * uclogic_params_init_invalid() - initialize tablet interface parameters,
712  * specifying the interface is invalid.
713  *
714  * @params:             Parameters to initialize (to be cleaned with
715  *                      uclogic_params_cleanup()). Cannot be NULL.
716  */
717 static void uclogic_params_init_invalid(struct uclogic_params *params)
718 {
719         params->invalid = true;
720 }
721
722 /**
723  * uclogic_params_init_with_opt_desc() - initialize tablet interface
724  * parameters with an optional replacement report descriptor. Only modify
725  * report descriptor, if the original report descriptor matches the expected
726  * size.
727  *
728  * @params:             Parameters to initialize (to be cleaned with
729  *                      uclogic_params_cleanup()). Not modified in case of
730  *                      error. Cannot be NULL.
731  * @hdev:               The HID device of the tablet interface create the
732  *                      parameters for. Cannot be NULL.
733  * @orig_desc_size:     Expected size of the original report descriptor to
734  *                      be replaced.
735  * @desc_ptr:           Pointer to the replacement report descriptor.
736  *                      Can be NULL, if desc_size is zero.
737  * @desc_size:          Size of the replacement report descriptor.
738  *
739  * Returns:
740  *      Zero, if successful. -EINVAL if an invalid argument was passed.
741  *      -ENOMEM, if failed to allocate memory.
742  */
743 static int uclogic_params_init_with_opt_desc(struct uclogic_params *params,
744                                              struct hid_device *hdev,
745                                              unsigned int orig_desc_size,
746                                              __u8 *desc_ptr,
747                                              unsigned int desc_size)
748 {
749         __u8 *desc_copy_ptr = NULL;
750         unsigned int desc_copy_size;
751         int rc;
752
753         /* Check arguments */
754         if (params == NULL || hdev == NULL ||
755             (desc_ptr == NULL && desc_size != 0)) {
756                 rc = -EINVAL;
757                 goto cleanup;
758         }
759
760         /* Replace report descriptor, if it matches */
761         if (hdev->dev_rsize == orig_desc_size) {
762                 hid_dbg(hdev,
763                         "device report descriptor matches the expected size, replacing\n");
764                 desc_copy_ptr = kmemdup(desc_ptr, desc_size, GFP_KERNEL);
765                 if (desc_copy_ptr == NULL) {
766                         rc = -ENOMEM;
767                         goto cleanup;
768                 }
769                 desc_copy_size = desc_size;
770         } else {
771                 hid_dbg(hdev,
772                         "device report descriptor doesn't match the expected size (%u != %u), preserving\n",
773                         hdev->dev_rsize, orig_desc_size);
774                 desc_copy_ptr = NULL;
775                 desc_copy_size = 0;
776         }
777
778         /* Output parameters */
779         memset(params, 0, sizeof(*params));
780         params->desc_ptr = desc_copy_ptr;
781         desc_copy_ptr = NULL;
782         params->desc_size = desc_copy_size;
783
784         rc = 0;
785 cleanup:
786         kfree(desc_copy_ptr);
787         return rc;
788 }
789
790 /**
791  * uclogic_params_huion_init() - initialize a Huion tablet interface and discover
792  * its parameters.
793  *
794  * @params:     Parameters to fill in (to be cleaned with
795  *              uclogic_params_cleanup()). Not modified in case of error.
796  *              Cannot be NULL.
797  * @hdev:       The HID device of the tablet interface to initialize and get
798  *              parameters from. Cannot be NULL.
799  *
800  * Returns:
801  *      Zero, if successful. A negative errno code on error.
802  */
803 static int uclogic_params_huion_init(struct uclogic_params *params,
804                                      struct hid_device *hdev)
805 {
806         int rc;
807         struct usb_device *udev;
808         struct usb_interface *iface;
809         __u8 bInterfaceNumber;
810         bool found;
811         /* The resulting parameters (noop) */
812         struct uclogic_params p = {0, };
813         static const char transition_ver[] = "HUION_T153_160607";
814         char *ver_ptr = NULL;
815         const size_t ver_len = sizeof(transition_ver) + 1;
816         __u8 *params_ptr = NULL;
817         size_t params_len = 0;
818         /* Parameters string descriptor of a model with touch ring (HS610) */
819         const __u8 touch_ring_model_params_buf[] = {
820                 0x13, 0x03, 0x70, 0xC6, 0x00, 0x06, 0x7C, 0x00,
821                 0xFF, 0x1F, 0xD8, 0x13, 0x03, 0x0D, 0x10, 0x01,
822                 0x04, 0x3C, 0x3E
823         };
824
825         /* Check arguments */
826         if (params == NULL || hdev == NULL) {
827                 rc = -EINVAL;
828                 goto cleanup;
829         }
830
831         udev = hid_to_usb_dev(hdev);
832         iface = to_usb_interface(hdev->dev.parent);
833         bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
834
835         /* If it's a custom keyboard interface */
836         if (bInterfaceNumber == 1) {
837                 /* Keep everything intact, but mark pen usage invalid */
838                 p.pen.usage_invalid = true;
839                 goto output;
840         /* Else, if it's not a pen interface */
841         } else if (bInterfaceNumber != 0) {
842                 uclogic_params_init_invalid(&p);
843                 goto output;
844         }
845
846         /* Try to get firmware version */
847         ver_ptr = kzalloc(ver_len, GFP_KERNEL);
848         if (ver_ptr == NULL) {
849                 rc = -ENOMEM;
850                 goto cleanup;
851         }
852         rc = usb_string(udev, 201, ver_ptr, ver_len);
853         if (rc == -EPIPE) {
854                 *ver_ptr = '\0';
855         } else if (rc < 0) {
856                 hid_err(hdev,
857                         "failed retrieving Huion firmware version: %d\n", rc);
858                 goto cleanup;
859         }
860
861         /* If this is a transition firmware */
862         if (strcmp(ver_ptr, transition_ver) == 0) {
863                 hid_dbg(hdev,
864                         "transition firmware detected, not probing pen v2 parameters\n");
865         } else {
866                 /* Try to probe v2 pen parameters */
867                 rc = uclogic_params_pen_init_v2(&p.pen, &found,
868                                                 &params_ptr, &params_len,
869                                                 hdev);
870                 if (rc != 0) {
871                         hid_err(hdev,
872                                 "failed probing pen v2 parameters: %d\n", rc);
873                         goto cleanup;
874                 } else if (found) {
875                         hid_dbg(hdev, "pen v2 parameters found\n");
876                         /* Create v2 frame button parameters */
877                         rc = uclogic_params_frame_init_with_desc(
878                                         &p.frame_list[0],
879                                         uclogic_rdesc_v2_frame_buttons_arr,
880                                         uclogic_rdesc_v2_frame_buttons_size,
881                                         UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID);
882                         if (rc != 0) {
883                                 hid_err(hdev,
884                                         "failed creating v2 frame button parameters: %d\n",
885                                         rc);
886                                 goto cleanup;
887                         }
888
889                         /* Link from pen sub-report */
890                         p.pen.subreport_list[0].value = 0xe0;
891                         p.pen.subreport_list[0].id =
892                                 UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID;
893
894                         /* If this is the model with touch ring */
895                         if (params_ptr != NULL &&
896                             params_len == sizeof(touch_ring_model_params_buf) &&
897                             memcmp(params_ptr, touch_ring_model_params_buf,
898                                    params_len) == 0) {
899                                 /* Create touch ring parameters */
900                                 rc = uclogic_params_frame_init_with_desc(
901                                         &p.frame_list[1],
902                                         uclogic_rdesc_v2_frame_touch_ring_arr,
903                                         uclogic_rdesc_v2_frame_touch_ring_size,
904                                         UCLOGIC_RDESC_V2_FRAME_TOUCH_ID);
905                                 if (rc != 0) {
906                                         hid_err(hdev,
907                                                 "failed creating v2 frame touch ring parameters: %d\n",
908                                                 rc);
909                                         goto cleanup;
910                                 }
911                                 p.frame_list[1].suffix = "Touch Ring";
912                                 p.frame_list[1].dev_id_byte =
913                                         UCLOGIC_RDESC_V2_FRAME_TOUCH_DEV_ID_BYTE;
914                                 p.frame_list[1].touch_byte = 5;
915                                 p.frame_list[1].touch_max = 12;
916                                 p.frame_list[1].touch_flip_at = 7;
917                         } else {
918                                 /* Create touch strip parameters */
919                                 rc = uclogic_params_frame_init_with_desc(
920                                         &p.frame_list[1],
921                                         uclogic_rdesc_v2_frame_touch_strip_arr,
922                                         uclogic_rdesc_v2_frame_touch_strip_size,
923                                         UCLOGIC_RDESC_V2_FRAME_TOUCH_ID);
924                                 if (rc != 0) {
925                                         hid_err(hdev,
926                                                 "failed creating v2 frame touch strip parameters: %d\n",
927                                                 rc);
928                                         goto cleanup;
929                                 }
930                                 p.frame_list[1].suffix = "Touch Strip";
931                                 p.frame_list[1].dev_id_byte =
932                                         UCLOGIC_RDESC_V2_FRAME_TOUCH_DEV_ID_BYTE;
933                                 p.frame_list[1].touch_byte = 5;
934                                 p.frame_list[1].touch_max = 8;
935                         }
936
937                         /* Link from pen sub-report */
938                         p.pen.subreport_list[1].value = 0xf0;
939                         p.pen.subreport_list[1].id =
940                                 UCLOGIC_RDESC_V2_FRAME_TOUCH_ID;
941
942                         /* Create v2 frame dial parameters */
943                         rc = uclogic_params_frame_init_with_desc(
944                                         &p.frame_list[2],
945                                         uclogic_rdesc_v2_frame_dial_arr,
946                                         uclogic_rdesc_v2_frame_dial_size,
947                                         UCLOGIC_RDESC_V2_FRAME_DIAL_ID);
948                         if (rc != 0) {
949                                 hid_err(hdev,
950                                         "failed creating v2 frame dial parameters: %d\n",
951                                         rc);
952                                 goto cleanup;
953                         }
954                         p.frame_list[2].suffix = "Dial";
955                         p.frame_list[2].dev_id_byte =
956                                 UCLOGIC_RDESC_V2_FRAME_DIAL_DEV_ID_BYTE;
957                         p.frame_list[2].bitmap_dial_byte = 5;
958
959                         /* Link from pen sub-report */
960                         p.pen.subreport_list[2].value = 0xf1;
961                         p.pen.subreport_list[2].id =
962                                 UCLOGIC_RDESC_V2_FRAME_DIAL_ID;
963
964                         goto output;
965                 }
966                 hid_dbg(hdev, "pen v2 parameters not found\n");
967         }
968
969         /* Try to probe v1 pen parameters */
970         rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
971         if (rc != 0) {
972                 hid_err(hdev,
973                         "failed probing pen v1 parameters: %d\n", rc);
974                 goto cleanup;
975         } else if (found) {
976                 hid_dbg(hdev, "pen v1 parameters found\n");
977                 /* Try to probe v1 frame */
978                 rc = uclogic_params_frame_init_v1(&p.frame_list[0],
979                                                   &found, hdev);
980                 if (rc != 0) {
981                         hid_err(hdev, "v1 frame probing failed: %d\n", rc);
982                         goto cleanup;
983                 }
984                 hid_dbg(hdev, "frame v1 parameters%s found\n",
985                         (found ? "" : " not"));
986                 if (found) {
987                         /* Link frame button subreports from pen reports */
988                         p.pen.subreport_list[0].value = 0xe0;
989                         p.pen.subreport_list[0].id =
990                                 UCLOGIC_RDESC_V1_FRAME_ID;
991                 }
992                 goto output;
993         }
994         hid_dbg(hdev, "pen v1 parameters not found\n");
995
996         uclogic_params_init_invalid(&p);
997
998 output:
999         /* Output parameters */
1000         memcpy(params, &p, sizeof(*params));
1001         memset(&p, 0, sizeof(p));
1002         rc = 0;
1003 cleanup:
1004         kfree(params_ptr);
1005         kfree(ver_ptr);
1006         uclogic_params_cleanup(&p);
1007         return rc;
1008 }
1009
1010 /**
1011  * uclogic_probe_interface() - some tablets, like the Parblo A610 PLUS V2 or
1012  * the XP-PEN Deco Mini 7, need to be initialized by sending them magic data.
1013  *
1014  * @hdev:       The HID device of the tablet interface to initialize and get
1015  *              parameters from. Cannot be NULL.
1016  * @magic_arr:  The magic data that should be sent to probe the interface.
1017  *              Cannot be NULL.
1018  * @magic_size: Size of the magic data.
1019  * @endpoint:   Endpoint where the magic data should be sent.
1020  *
1021  * Returns:
1022  *      Zero, if successful. A negative errno code on error.
1023  */
1024 static int uclogic_probe_interface(struct hid_device *hdev, u8 *magic_arr,
1025                                    int magic_size, int endpoint)
1026 {
1027         struct usb_device *udev;
1028         unsigned int pipe = 0;
1029         int sent;
1030         u8 *buf = NULL;
1031         int rc = 0;
1032
1033         if (!hdev || !magic_arr) {
1034                 rc = -EINVAL;
1035                 goto cleanup;
1036         }
1037
1038         buf = kmemdup(magic_arr, magic_size, GFP_KERNEL);
1039         if (!buf) {
1040                 rc = -ENOMEM;
1041                 goto cleanup;
1042         }
1043
1044         udev = hid_to_usb_dev(hdev);
1045         pipe = usb_sndintpipe(udev, endpoint);
1046
1047         rc = usb_interrupt_msg(udev, pipe, buf, magic_size, &sent, 1000);
1048         if (rc || sent != magic_size) {
1049                 hid_err(hdev, "Interface probing failed: %d\n", rc);
1050                 rc = -1;
1051                 goto cleanup;
1052         }
1053
1054         rc = 0;
1055 cleanup:
1056         kfree(buf);
1057         return rc;
1058 }
1059
1060 /**
1061  * uclogic_params_parse_ugee_v2_desc - parse the string descriptor containing
1062  * pen and frame parameters returned by UGEE v2 devices.
1063  *
1064  * @str_desc:           String descriptor, cannot be NULL.
1065  * @str_desc_size:      Size of the string descriptor.
1066  * @desc_params:        Output description params list.
1067  * @desc_params_size:   Size of the output description params list.
1068  * @frame_type:         Output frame type.
1069  *
1070  * Returns:
1071  *      Zero, if successful. A negative errno code on error.
1072  */
1073 static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc,
1074                                              size_t str_desc_size,
1075                                              s32 *desc_params,
1076                                              size_t desc_params_size,
1077                                              enum uclogic_params_frame_type *frame_type)
1078 {
1079         s32 pen_x_lm, pen_y_lm;
1080         s32 pen_x_pm, pen_y_pm;
1081         s32 pen_pressure_lm;
1082         s32 frame_num_buttons;
1083         s32 resolution;
1084
1085         /* Minimum descriptor length required, maximum seen so far is 14 */
1086         const int min_str_desc_size = 12;
1087
1088         if (!str_desc || str_desc_size < min_str_desc_size)
1089                 return -EINVAL;
1090
1091         if (desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
1092                 return -EINVAL;
1093
1094         pen_x_lm = get_unaligned_le16(str_desc + 2);
1095         pen_y_lm = get_unaligned_le16(str_desc + 4);
1096         frame_num_buttons = str_desc[6];
1097         *frame_type = str_desc[7];
1098         pen_pressure_lm = get_unaligned_le16(str_desc + 8);
1099
1100         resolution = get_unaligned_le16(str_desc + 10);
1101         if (resolution == 0) {
1102                 pen_x_pm = 0;
1103                 pen_y_pm = 0;
1104         } else {
1105                 pen_x_pm = pen_x_lm * 1000 / resolution;
1106                 pen_y_pm = pen_y_lm * 1000 / resolution;
1107         }
1108
1109         desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = pen_x_lm;
1110         desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = pen_x_pm;
1111         desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = pen_y_lm;
1112         desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = pen_y_pm;
1113         desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = pen_pressure_lm;
1114         desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = frame_num_buttons;
1115
1116         return 0;
1117 }
1118
1119 /**
1120  * uclogic_params_ugee_v2_init_frame_buttons() - initialize a UGEE v2 frame with
1121  * buttons.
1122  * @p:                  Parameters to fill in, cannot be NULL.
1123  * @desc_params:        Device description params list.
1124  * @desc_params_size:   Size of the description params list.
1125  *
1126  * Returns:
1127  *      Zero, if successful. A negative errno code on error.
1128  */
1129 static int uclogic_params_ugee_v2_init_frame_buttons(struct uclogic_params *p,
1130                                                      const s32 *desc_params,
1131                                                      size_t desc_params_size)
1132 {
1133         __u8 *rdesc_frame = NULL;
1134         int rc = 0;
1135
1136         if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
1137                 return -EINVAL;
1138
1139         rdesc_frame = uclogic_rdesc_template_apply(
1140                                 uclogic_rdesc_ugee_v2_frame_btn_template_arr,
1141                                 uclogic_rdesc_ugee_v2_frame_btn_template_size,
1142                                 desc_params, UCLOGIC_RDESC_PH_ID_NUM);
1143         if (!rdesc_frame)
1144                 return -ENOMEM;
1145
1146         rc = uclogic_params_frame_init_with_desc(&p->frame_list[0],
1147                                                  rdesc_frame,
1148                                                  uclogic_rdesc_ugee_v2_frame_btn_template_size,
1149                                                  UCLOGIC_RDESC_V1_FRAME_ID);
1150         kfree(rdesc_frame);
1151         return rc;
1152 }
1153
1154 /**
1155  * uclogic_params_ugee_v2_init_frame_dial() - initialize a UGEE v2 frame with a
1156  * bitmap dial.
1157  * @p:                  Parameters to fill in, cannot be NULL.
1158  * @desc_params:        Device description params list.
1159  * @desc_params_size:   Size of the description params list.
1160  *
1161  * Returns:
1162  *      Zero, if successful. A negative errno code on error.
1163  */
1164 static int uclogic_params_ugee_v2_init_frame_dial(struct uclogic_params *p,
1165                                                   const s32 *desc_params,
1166                                                   size_t desc_params_size)
1167 {
1168         __u8 *rdesc_frame = NULL;
1169         int rc = 0;
1170
1171         if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
1172                 return -EINVAL;
1173
1174         rdesc_frame = uclogic_rdesc_template_apply(
1175                                 uclogic_rdesc_ugee_v2_frame_dial_template_arr,
1176                                 uclogic_rdesc_ugee_v2_frame_dial_template_size,
1177                                 desc_params, UCLOGIC_RDESC_PH_ID_NUM);
1178         if (!rdesc_frame)
1179                 return -ENOMEM;
1180
1181         rc = uclogic_params_frame_init_with_desc(&p->frame_list[0],
1182                                                  rdesc_frame,
1183                                                  uclogic_rdesc_ugee_v2_frame_dial_template_size,
1184                                                  UCLOGIC_RDESC_V1_FRAME_ID);
1185         kfree(rdesc_frame);
1186         if (rc)
1187                 return rc;
1188
1189         p->frame_list[0].bitmap_dial_byte = 7;
1190         return 0;
1191 }
1192
1193 /**
1194  * uclogic_params_ugee_v2_init_frame_mouse() - initialize a UGEE v2 frame with a
1195  * mouse.
1196  * @p:                  Parameters to fill in, cannot be NULL.
1197  *
1198  * Returns:
1199  *      Zero, if successful. A negative errno code on error.
1200  */
1201 static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p)
1202 {
1203         int rc = 0;
1204
1205         if (!p)
1206                 return -EINVAL;
1207
1208         rc = uclogic_params_frame_init_with_desc(&p->frame_list[1],
1209                                                  uclogic_rdesc_ugee_v2_frame_mouse_template_arr,
1210                                                  uclogic_rdesc_ugee_v2_frame_mouse_template_size,
1211                                                  UCLOGIC_RDESC_V1_FRAME_ID);
1212         return rc;
1213 }
1214
1215 /**
1216  * uclogic_params_ugee_v2_has_battery() - check whether a UGEE v2 device has
1217  * battery or not.
1218  * @hdev:       The HID device of the tablet interface.
1219  *
1220  * Returns:
1221  *      True if the device has battery, false otherwise.
1222  */
1223 static bool uclogic_params_ugee_v2_has_battery(struct hid_device *hdev)
1224 {
1225         struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
1226
1227         if (drvdata->quirks & UCLOGIC_BATTERY_QUIRK)
1228                 return true;
1229
1230         /* The XP-PEN Deco LW vendor, product and version are identical to the
1231          * Deco L. The only difference reported by their firmware is the product
1232          * name. Add a quirk to support battery reporting on the wireless
1233          * version.
1234          */
1235         if (hdev->vendor == USB_VENDOR_ID_UGEE &&
1236             hdev->product == USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) {
1237                 struct usb_device *udev = hid_to_usb_dev(hdev);
1238
1239                 if (strstarts(udev->product, "Deco LW"))
1240                         return true;
1241         }
1242
1243         return false;
1244 }
1245
1246 /**
1247  * uclogic_params_ugee_v2_init_battery() - initialize UGEE v2 battery reporting.
1248  * @hdev:       The HID device of the tablet interface, cannot be NULL.
1249  * @p:          Parameters to fill in, cannot be NULL.
1250  *
1251  * Returns:
1252  *      Zero, if successful. A negative errno code on error.
1253  */
1254 static int uclogic_params_ugee_v2_init_battery(struct hid_device *hdev,
1255                                                struct uclogic_params *p)
1256 {
1257         int rc = 0;
1258
1259         if (!hdev || !p)
1260                 return -EINVAL;
1261
1262         /* Some tablets contain invalid characters in hdev->uniq, throwing a
1263          * "hwmon: '<name>' is not a valid name attribute, please fix" error.
1264          * Use the device vendor and product IDs instead.
1265          */
1266         snprintf(hdev->uniq, sizeof(hdev->uniq), "%x-%x", hdev->vendor,
1267                  hdev->product);
1268
1269         rc = uclogic_params_frame_init_with_desc(&p->frame_list[1],
1270                                                  uclogic_rdesc_ugee_v2_battery_template_arr,
1271                                                  uclogic_rdesc_ugee_v2_battery_template_size,
1272                                                  UCLOGIC_RDESC_UGEE_V2_BATTERY_ID);
1273         if (rc)
1274                 return rc;
1275
1276         p->frame_list[1].suffix = "Battery";
1277         p->pen.subreport_list[1].value = 0xf2;
1278         p->pen.subreport_list[1].id = UCLOGIC_RDESC_UGEE_V2_BATTERY_ID;
1279
1280         return rc;
1281 }
1282
1283 /**
1284  * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by
1285  * discovering their parameters.
1286  *
1287  * These tables, internally designed as v2 to differentiate them from older
1288  * models, expect a payload of magic data in orther to be switched to the fully
1289  * functional mode and expose their parameters in a similar way to the
1290  * information present in uclogic_params_pen_init_v1() but with some
1291  * differences.
1292  *
1293  * @params:     Parameters to fill in (to be cleaned with
1294  *              uclogic_params_cleanup()). Not modified in case of error.
1295  *              Cannot be NULL.
1296  * @hdev:       The HID device of the tablet interface to initialize and get
1297  *              parameters from. Cannot be NULL.
1298  *
1299  * Returns:
1300  *      Zero, if successful. A negative errno code on error.
1301  */
1302 static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
1303                                        struct hid_device *hdev)
1304 {
1305         int rc = 0;
1306         struct uclogic_drvdata *drvdata;
1307         struct usb_interface *iface;
1308         __u8 bInterfaceNumber;
1309         const int str_desc_len = 12;
1310         __u8 *str_desc = NULL;
1311         __u8 *rdesc_pen = NULL;
1312         s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
1313         enum uclogic_params_frame_type frame_type;
1314         __u8 magic_arr[] = {
1315                 0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1316         };
1317         /* The resulting parameters (noop) */
1318         struct uclogic_params p = {0, };
1319
1320         if (!params || !hdev) {
1321                 rc = -EINVAL;
1322                 goto cleanup;
1323         }
1324
1325         drvdata = hid_get_drvdata(hdev);
1326         iface = to_usb_interface(hdev->dev.parent);
1327         bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1328
1329         if (bInterfaceNumber == 0) {
1330                 rc = uclogic_params_ugee_v2_init_frame_mouse(&p);
1331                 if (rc)
1332                         goto cleanup;
1333
1334                 goto output;
1335         }
1336
1337         if (bInterfaceNumber != 2) {
1338                 uclogic_params_init_invalid(&p);
1339                 goto output;
1340         }
1341
1342         /*
1343          * Initialize the interface by sending magic data.
1344          * The specific data was discovered by sniffing the Windows driver
1345          * traffic.
1346          */
1347         rc = uclogic_probe_interface(hdev, magic_arr, sizeof(magic_arr), 0x03);
1348         if (rc) {
1349                 uclogic_params_init_invalid(&p);
1350                 goto output;
1351         }
1352
1353         /*
1354          * Read the string descriptor containing pen and frame parameters.
1355          * The specific string descriptor and data were discovered by sniffing
1356          * the Windows driver traffic.
1357          */
1358         rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len);
1359         if (rc != str_desc_len) {
1360                 hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc);
1361                 uclogic_params_init_invalid(&p);
1362                 goto output;
1363         }
1364
1365         rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len,
1366                                                desc_params,
1367                                                ARRAY_SIZE(desc_params),
1368                                                &frame_type);
1369         if (rc)
1370                 goto cleanup;
1371
1372         kfree(str_desc);
1373         str_desc = NULL;
1374
1375         /* Initialize the pen interface */
1376         rdesc_pen = uclogic_rdesc_template_apply(
1377                                 uclogic_rdesc_ugee_v2_pen_template_arr,
1378                                 uclogic_rdesc_ugee_v2_pen_template_size,
1379                                 desc_params, ARRAY_SIZE(desc_params));
1380         if (!rdesc_pen) {
1381                 rc = -ENOMEM;
1382                 goto cleanup;
1383         }
1384
1385         p.pen.desc_ptr = rdesc_pen;
1386         p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size;
1387         p.pen.id = 0x02;
1388         p.pen.subreport_list[0].value = 0xf0;
1389         p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
1390
1391         /* Initialize the frame interface */
1392         if (drvdata->quirks & UCLOGIC_MOUSE_FRAME_QUIRK)
1393                 frame_type = UCLOGIC_PARAMS_FRAME_MOUSE;
1394
1395         switch (frame_type) {
1396         case UCLOGIC_PARAMS_FRAME_DIAL:
1397         case UCLOGIC_PARAMS_FRAME_MOUSE:
1398                 rc = uclogic_params_ugee_v2_init_frame_dial(&p, desc_params,
1399                                                             ARRAY_SIZE(desc_params));
1400                 break;
1401         case UCLOGIC_PARAMS_FRAME_BUTTONS:
1402         default:
1403                 rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params,
1404                                                                ARRAY_SIZE(desc_params));
1405                 break;
1406         }
1407
1408         if (rc)
1409                 goto cleanup;
1410
1411         /* Initialize the battery interface*/
1412         if (uclogic_params_ugee_v2_has_battery(hdev)) {
1413                 rc = uclogic_params_ugee_v2_init_battery(hdev, &p);
1414                 if (rc) {
1415                         hid_err(hdev, "error initializing battery: %d\n", rc);
1416                         goto cleanup;
1417                 }
1418         }
1419
1420 output:
1421         /* Output parameters */
1422         memcpy(params, &p, sizeof(*params));
1423         memset(&p, 0, sizeof(p));
1424         rc = 0;
1425 cleanup:
1426         kfree(str_desc);
1427         uclogic_params_cleanup(&p);
1428         return rc;
1429 }
1430
1431 /**
1432  * uclogic_params_init() - initialize a tablet interface and discover its
1433  * parameters.
1434  *
1435  * @params:     Parameters to fill in (to be cleaned with
1436  *              uclogic_params_cleanup()). Not modified in case of error.
1437  *              Cannot be NULL.
1438  * @hdev:       The HID device of the tablet interface to initialize and get
1439  *              parameters from. Cannot be NULL. Must be using the USB low-level
1440  *              driver, i.e. be an actual USB tablet.
1441  *
1442  * Returns:
1443  *      Zero, if successful. A negative errno code on error.
1444  */
1445 int uclogic_params_init(struct uclogic_params *params,
1446                         struct hid_device *hdev)
1447 {
1448         int rc;
1449         struct usb_device *udev;
1450         __u8  bNumInterfaces;
1451         struct usb_interface *iface;
1452         __u8 bInterfaceNumber;
1453         bool found;
1454         /* The resulting parameters (noop) */
1455         struct uclogic_params p = {0, };
1456
1457         /* Check arguments */
1458         if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) {
1459                 rc = -EINVAL;
1460                 goto cleanup;
1461         }
1462
1463         udev = hid_to_usb_dev(hdev);
1464         bNumInterfaces = udev->config->desc.bNumInterfaces;
1465         iface = to_usb_interface(hdev->dev.parent);
1466         bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1467
1468         /*
1469          * Set replacement report descriptor if the original matches the
1470          * specified size. Otherwise keep interface unchanged.
1471          */
1472 #define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \
1473         uclogic_params_init_with_opt_desc(                  \
1474                 &p, hdev,                                   \
1475                 UCLOGIC_RDESC_##_orig_desc_token##_SIZE,    \
1476                 uclogic_rdesc_##_new_desc_token##_arr,      \
1477                 uclogic_rdesc_##_new_desc_token##_size)
1478
1479 #define VID_PID(_vid, _pid) \
1480         (((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX))
1481
1482         /*
1483          * Handle specific interfaces for specific tablets.
1484          *
1485          * Observe the following logic:
1486          *
1487          * If the interface is recognized as producing certain useful input:
1488          *      Mark interface as valid.
1489          *      Output interface parameters.
1490          * Else, if the interface is recognized as *not* producing any useful
1491          * input:
1492          *      Mark interface as invalid.
1493          * Else:
1494          *      Mark interface as valid.
1495          *      Output noop parameters.
1496          *
1497          * Rule of thumb: it is better to disable a broken interface than let
1498          *                it spew garbage input.
1499          */
1500
1501         switch (VID_PID(hdev->vendor, hdev->product)) {
1502         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1503                      USB_DEVICE_ID_UCLOGIC_TABLET_PF1209):
1504                 rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed);
1505                 if (rc != 0)
1506                         goto cleanup;
1507                 break;
1508         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1509                      USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U):
1510                 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed);
1511                 if (rc != 0)
1512                         goto cleanup;
1513                 break;
1514         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1515                      USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U):
1516                 if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) {
1517                         if (bInterfaceNumber == 0) {
1518                                 /* Try to probe v1 pen parameters */
1519                                 rc = uclogic_params_pen_init_v1(&p.pen,
1520                                                                 &found, hdev);
1521                                 if (rc != 0) {
1522                                         hid_err(hdev,
1523                                                 "pen probing failed: %d\n",
1524                                                 rc);
1525                                         goto cleanup;
1526                                 }
1527                                 if (!found) {
1528                                         hid_warn(hdev,
1529                                                  "pen parameters not found");
1530                                 }
1531                         } else {
1532                                 uclogic_params_init_invalid(&p);
1533                         }
1534                 } else {
1535                         rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed);
1536                         if (rc != 0)
1537                                 goto cleanup;
1538                 }
1539                 break;
1540         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1541                      USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U):
1542                 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed);
1543                 if (rc != 0)
1544                         goto cleanup;
1545                 break;
1546         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1547                      USB_DEVICE_ID_UCLOGIC_TABLET_WP1062):
1548                 rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed);
1549                 if (rc != 0)
1550                         goto cleanup;
1551                 break;
1552         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1553                      USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850):
1554                 switch (bInterfaceNumber) {
1555                 case 0:
1556                         rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0);
1557                         if (rc != 0)
1558                                 goto cleanup;
1559                         break;
1560                 case 1:
1561                         rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1);
1562                         if (rc != 0)
1563                                 goto cleanup;
1564                         break;
1565                 case 2:
1566                         rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2);
1567                         if (rc != 0)
1568                                 goto cleanup;
1569                         break;
1570                 }
1571                 break;
1572         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1573                      USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60):
1574                 /*
1575                  * If it is not a three-interface version, which is known to
1576                  * respond to initialization.
1577                  */
1578                 if (bNumInterfaces != 3) {
1579                         switch (bInterfaceNumber) {
1580                         case 0:
1581                                 rc = WITH_OPT_DESC(TWHA60_ORIG0,
1582                                                         twha60_fixed0);
1583                                 if (rc != 0)
1584                                         goto cleanup;
1585                                 break;
1586                         case 1:
1587                                 rc = WITH_OPT_DESC(TWHA60_ORIG1,
1588                                                         twha60_fixed1);
1589                                 if (rc != 0)
1590                                         goto cleanup;
1591                                 break;
1592                         }
1593                         break;
1594                 }
1595                 fallthrough;
1596         case VID_PID(USB_VENDOR_ID_HUION,
1597                      USB_DEVICE_ID_HUION_TABLET):
1598         case VID_PID(USB_VENDOR_ID_HUION,
1599                      USB_DEVICE_ID_HUION_TABLET2):
1600         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1601                      USB_DEVICE_ID_HUION_TABLET):
1602         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1603                      USB_DEVICE_ID_YIYNOVA_TABLET):
1604         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1605                      USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81):
1606         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1607                      USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3):
1608         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1609                      USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45):
1610         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1611                      USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47):
1612                 rc = uclogic_params_huion_init(&p, hdev);
1613                 if (rc != 0)
1614                         goto cleanup;
1615                 break;
1616         case VID_PID(USB_VENDOR_ID_UGTIZER,
1617                      USB_DEVICE_ID_UGTIZER_TABLET_GP0610):
1618         case VID_PID(USB_VENDOR_ID_UGTIZER,
1619                      USB_DEVICE_ID_UGTIZER_TABLET_GT5040):
1620         case VID_PID(USB_VENDOR_ID_UGEE,
1621                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
1622         case VID_PID(USB_VENDOR_ID_UGEE,
1623                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640):
1624         case VID_PID(USB_VENDOR_ID_UGEE,
1625                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06):
1626         case VID_PID(USB_VENDOR_ID_UGEE,
1627                      USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720):
1628                 /* If this is the pen interface */
1629                 if (bInterfaceNumber == 1) {
1630                         /* Probe v1 pen parameters */
1631                         rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1632                         if (rc != 0) {
1633                                 hid_err(hdev, "pen probing failed: %d\n", rc);
1634                                 goto cleanup;
1635                         }
1636                         if (!found) {
1637                                 hid_warn(hdev, "pen parameters not found");
1638                                 uclogic_params_init_invalid(&p);
1639                         }
1640                 } else {
1641                         uclogic_params_init_invalid(&p);
1642                 }
1643                 break;
1644         case VID_PID(USB_VENDOR_ID_UGEE,
1645                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01):
1646                 /* If this is the pen and frame interface */
1647                 if (bInterfaceNumber == 1) {
1648                         /* Probe v1 pen parameters */
1649                         rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1650                         if (rc != 0) {
1651                                 hid_err(hdev, "pen probing failed: %d\n", rc);
1652                                 goto cleanup;
1653                         }
1654                         /* Initialize frame parameters */
1655                         rc = uclogic_params_frame_init_with_desc(
1656                                 &p.frame_list[0],
1657                                 uclogic_rdesc_xppen_deco01_frame_arr,
1658                                 uclogic_rdesc_xppen_deco01_frame_size,
1659                                 0);
1660                         if (rc != 0)
1661                                 goto cleanup;
1662                 } else {
1663                         uclogic_params_init_invalid(&p);
1664                 }
1665                 break;
1666         case VID_PID(USB_VENDOR_ID_UGEE,
1667                      USB_DEVICE_ID_UGEE_PARBLO_A610_PRO):
1668         case VID_PID(USB_VENDOR_ID_UGEE,
1669                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2):
1670         case VID_PID(USB_VENDOR_ID_UGEE,
1671                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L):
1672         case VID_PID(USB_VENDOR_ID_UGEE,
1673                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW):
1674         case VID_PID(USB_VENDOR_ID_UGEE,
1675                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S):
1676         case VID_PID(USB_VENDOR_ID_UGEE,
1677                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW):
1678                 rc = uclogic_params_ugee_v2_init(&p, hdev);
1679                 if (rc != 0)
1680                         goto cleanup;
1681                 break;
1682         case VID_PID(USB_VENDOR_ID_TRUST,
1683                      USB_DEVICE_ID_TRUST_PANORA_TABLET):
1684         case VID_PID(USB_VENDOR_ID_UGEE,
1685                      USB_DEVICE_ID_UGEE_TABLET_G5):
1686                 /* Ignore non-pen interfaces */
1687                 if (bInterfaceNumber != 1) {
1688                         uclogic_params_init_invalid(&p);
1689                         break;
1690                 }
1691
1692                 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1693                 if (rc != 0) {
1694                         hid_err(hdev, "pen probing failed: %d\n", rc);
1695                         goto cleanup;
1696                 } else if (found) {
1697                         rc = uclogic_params_frame_init_with_desc(
1698                                 &p.frame_list[0],
1699                                 uclogic_rdesc_ugee_g5_frame_arr,
1700                                 uclogic_rdesc_ugee_g5_frame_size,
1701                                 UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
1702                         if (rc != 0) {
1703                                 hid_err(hdev,
1704                                         "failed creating frame parameters: %d\n",
1705                                         rc);
1706                                 goto cleanup;
1707                         }
1708                         p.frame_list[0].re_lsb =
1709                                 UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
1710                         p.frame_list[0].dev_id_byte =
1711                                 UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
1712                 } else {
1713                         hid_warn(hdev, "pen parameters not found");
1714                         uclogic_params_init_invalid(&p);
1715                 }
1716
1717                 break;
1718         case VID_PID(USB_VENDOR_ID_UGEE,
1719                      USB_DEVICE_ID_UGEE_TABLET_EX07S):
1720                 /* Ignore non-pen interfaces */
1721                 if (bInterfaceNumber != 1) {
1722                         uclogic_params_init_invalid(&p);
1723                         break;
1724                 }
1725
1726                 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1727                 if (rc != 0) {
1728                         hid_err(hdev, "pen probing failed: %d\n", rc);
1729                         goto cleanup;
1730                 } else if (found) {
1731                         rc = uclogic_params_frame_init_with_desc(
1732                                 &p.frame_list[0],
1733                                 uclogic_rdesc_ugee_ex07_frame_arr,
1734                                 uclogic_rdesc_ugee_ex07_frame_size,
1735                                 0);
1736                         if (rc != 0) {
1737                                 hid_err(hdev,
1738                                         "failed creating frame parameters: %d\n",
1739                                         rc);
1740                                 goto cleanup;
1741                         }
1742                 } else {
1743                         hid_warn(hdev, "pen parameters not found");
1744                         uclogic_params_init_invalid(&p);
1745                 }
1746
1747                 break;
1748         }
1749
1750 #undef VID_PID
1751 #undef WITH_OPT_DESC
1752
1753         /* Output parameters */
1754         memcpy(params, &p, sizeof(*params));
1755         memset(&p, 0, sizeof(p));
1756         rc = 0;
1757 cleanup:
1758         uclogic_params_cleanup(&p);
1759         return rc;
1760 }
1761
1762 #ifdef CONFIG_HID_KUNIT_TEST
1763 #include "hid-uclogic-params-test.c"
1764 #endif