Revert "mm/compaction: fix set skip in fast_find_migrateblock"
[platform/kernel/linux-starfive.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         /* The XP-PEN Deco LW vendor, product and version are identical to the
1226          * Deco L. The only difference reported by their firmware is the product
1227          * name. Add a quirk to support battery reporting on the wireless
1228          * version.
1229          */
1230         if (hdev->vendor == USB_VENDOR_ID_UGEE &&
1231             hdev->product == USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) {
1232                 struct usb_device *udev = hid_to_usb_dev(hdev);
1233
1234                 if (strstarts(udev->product, "Deco LW"))
1235                         return true;
1236         }
1237
1238         return false;
1239 }
1240
1241 /**
1242  * uclogic_params_ugee_v2_init_battery() - initialize UGEE v2 battery reporting.
1243  * @hdev:       The HID device of the tablet interface, cannot be NULL.
1244  * @p:          Parameters to fill in, cannot be NULL.
1245  *
1246  * Returns:
1247  *      Zero, if successful. A negative errno code on error.
1248  */
1249 static int uclogic_params_ugee_v2_init_battery(struct hid_device *hdev,
1250                                                struct uclogic_params *p)
1251 {
1252         int rc = 0;
1253
1254         if (!hdev || !p)
1255                 return -EINVAL;
1256
1257         /* Some tablets contain invalid characters in hdev->uniq, throwing a
1258          * "hwmon: '<name>' is not a valid name attribute, please fix" error.
1259          * Use the device vendor and product IDs instead.
1260          */
1261         snprintf(hdev->uniq, sizeof(hdev->uniq), "%x-%x", hdev->vendor,
1262                  hdev->product);
1263
1264         rc = uclogic_params_frame_init_with_desc(&p->frame_list[1],
1265                                                  uclogic_rdesc_ugee_v2_battery_template_arr,
1266                                                  uclogic_rdesc_ugee_v2_battery_template_size,
1267                                                  UCLOGIC_RDESC_UGEE_V2_BATTERY_ID);
1268         if (rc)
1269                 return rc;
1270
1271         p->frame_list[1].suffix = "Battery";
1272         p->pen.subreport_list[1].value = 0xf2;
1273         p->pen.subreport_list[1].id = UCLOGIC_RDESC_UGEE_V2_BATTERY_ID;
1274
1275         return rc;
1276 }
1277
1278 /**
1279  * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by
1280  * discovering their parameters.
1281  *
1282  * These tables, internally designed as v2 to differentiate them from older
1283  * models, expect a payload of magic data in orther to be switched to the fully
1284  * functional mode and expose their parameters in a similar way to the
1285  * information present in uclogic_params_pen_init_v1() but with some
1286  * differences.
1287  *
1288  * @params:     Parameters to fill in (to be cleaned with
1289  *              uclogic_params_cleanup()). Not modified in case of error.
1290  *              Cannot be NULL.
1291  * @hdev:       The HID device of the tablet interface to initialize and get
1292  *              parameters from. Cannot be NULL.
1293  *
1294  * Returns:
1295  *      Zero, if successful. A negative errno code on error.
1296  */
1297 static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
1298                                        struct hid_device *hdev)
1299 {
1300         int rc = 0;
1301         struct usb_interface *iface;
1302         __u8 bInterfaceNumber;
1303         const int str_desc_len = 12;
1304         __u8 *str_desc = NULL;
1305         __u8 *rdesc_pen = NULL;
1306         s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
1307         enum uclogic_params_frame_type frame_type;
1308         __u8 magic_arr[] = {
1309                 0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1310         };
1311         /* The resulting parameters (noop) */
1312         struct uclogic_params p = {0, };
1313
1314         if (!params || !hdev) {
1315                 rc = -EINVAL;
1316                 goto cleanup;
1317         }
1318
1319         iface = to_usb_interface(hdev->dev.parent);
1320         bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1321
1322         if (bInterfaceNumber == 0) {
1323                 rc = uclogic_params_ugee_v2_init_frame_mouse(&p);
1324                 if (rc)
1325                         goto cleanup;
1326
1327                 goto output;
1328         }
1329
1330         if (bInterfaceNumber != 2) {
1331                 uclogic_params_init_invalid(&p);
1332                 goto output;
1333         }
1334
1335         /*
1336          * Initialize the interface by sending magic data.
1337          * The specific data was discovered by sniffing the Windows driver
1338          * traffic.
1339          */
1340         rc = uclogic_probe_interface(hdev, magic_arr, sizeof(magic_arr), 0x03);
1341         if (rc) {
1342                 uclogic_params_init_invalid(&p);
1343                 goto output;
1344         }
1345
1346         /*
1347          * Read the string descriptor containing pen and frame parameters.
1348          * The specific string descriptor and data were discovered by sniffing
1349          * the Windows driver traffic.
1350          */
1351         rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len);
1352         if (rc != str_desc_len) {
1353                 hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc);
1354                 uclogic_params_init_invalid(&p);
1355                 goto output;
1356         }
1357
1358         rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len,
1359                                                desc_params,
1360                                                ARRAY_SIZE(desc_params),
1361                                                &frame_type);
1362         if (rc)
1363                 goto cleanup;
1364
1365         kfree(str_desc);
1366         str_desc = NULL;
1367
1368         /* Initialize the pen interface */
1369         rdesc_pen = uclogic_rdesc_template_apply(
1370                                 uclogic_rdesc_ugee_v2_pen_template_arr,
1371                                 uclogic_rdesc_ugee_v2_pen_template_size,
1372                                 desc_params, ARRAY_SIZE(desc_params));
1373         if (!rdesc_pen) {
1374                 rc = -ENOMEM;
1375                 goto cleanup;
1376         }
1377
1378         p.pen.desc_ptr = rdesc_pen;
1379         p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size;
1380         p.pen.id = 0x02;
1381         p.pen.subreport_list[0].value = 0xf0;
1382         p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
1383
1384         /* Initialize the frame interface */
1385         switch (frame_type) {
1386         case UCLOGIC_PARAMS_FRAME_DIAL:
1387         case UCLOGIC_PARAMS_FRAME_MOUSE:
1388                 rc = uclogic_params_ugee_v2_init_frame_dial(&p, desc_params,
1389                                                             ARRAY_SIZE(desc_params));
1390                 break;
1391         case UCLOGIC_PARAMS_FRAME_BUTTONS:
1392         default:
1393                 rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params,
1394                                                                ARRAY_SIZE(desc_params));
1395                 break;
1396         }
1397
1398         if (rc)
1399                 goto cleanup;
1400
1401         /* Initialize the battery interface*/
1402         if (uclogic_params_ugee_v2_has_battery(hdev)) {
1403                 rc = uclogic_params_ugee_v2_init_battery(hdev, &p);
1404                 if (rc) {
1405                         hid_err(hdev, "error initializing battery: %d\n", rc);
1406                         goto cleanup;
1407                 }
1408         }
1409
1410 output:
1411         /* Output parameters */
1412         memcpy(params, &p, sizeof(*params));
1413         memset(&p, 0, sizeof(p));
1414         rc = 0;
1415 cleanup:
1416         kfree(str_desc);
1417         uclogic_params_cleanup(&p);
1418         return rc;
1419 }
1420
1421 /**
1422  * uclogic_params_init() - initialize a tablet interface and discover its
1423  * parameters.
1424  *
1425  * @params:     Parameters to fill in (to be cleaned with
1426  *              uclogic_params_cleanup()). Not modified in case of error.
1427  *              Cannot be NULL.
1428  * @hdev:       The HID device of the tablet interface to initialize and get
1429  *              parameters from. Cannot be NULL. Must be using the USB low-level
1430  *              driver, i.e. be an actual USB tablet.
1431  *
1432  * Returns:
1433  *      Zero, if successful. A negative errno code on error.
1434  */
1435 int uclogic_params_init(struct uclogic_params *params,
1436                         struct hid_device *hdev)
1437 {
1438         int rc;
1439         struct usb_device *udev;
1440         __u8  bNumInterfaces;
1441         struct usb_interface *iface;
1442         __u8 bInterfaceNumber;
1443         bool found;
1444         /* The resulting parameters (noop) */
1445         struct uclogic_params p = {0, };
1446
1447         /* Check arguments */
1448         if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) {
1449                 rc = -EINVAL;
1450                 goto cleanup;
1451         }
1452
1453         udev = hid_to_usb_dev(hdev);
1454         bNumInterfaces = udev->config->desc.bNumInterfaces;
1455         iface = to_usb_interface(hdev->dev.parent);
1456         bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1457
1458         /*
1459          * Set replacement report descriptor if the original matches the
1460          * specified size. Otherwise keep interface unchanged.
1461          */
1462 #define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \
1463         uclogic_params_init_with_opt_desc(                  \
1464                 &p, hdev,                                   \
1465                 UCLOGIC_RDESC_##_orig_desc_token##_SIZE,    \
1466                 uclogic_rdesc_##_new_desc_token##_arr,      \
1467                 uclogic_rdesc_##_new_desc_token##_size)
1468
1469 #define VID_PID(_vid, _pid) \
1470         (((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX))
1471
1472         /*
1473          * Handle specific interfaces for specific tablets.
1474          *
1475          * Observe the following logic:
1476          *
1477          * If the interface is recognized as producing certain useful input:
1478          *      Mark interface as valid.
1479          *      Output interface parameters.
1480          * Else, if the interface is recognized as *not* producing any useful
1481          * input:
1482          *      Mark interface as invalid.
1483          * Else:
1484          *      Mark interface as valid.
1485          *      Output noop parameters.
1486          *
1487          * Rule of thumb: it is better to disable a broken interface than let
1488          *                it spew garbage input.
1489          */
1490
1491         switch (VID_PID(hdev->vendor, hdev->product)) {
1492         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1493                      USB_DEVICE_ID_UCLOGIC_TABLET_PF1209):
1494                 rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed);
1495                 if (rc != 0)
1496                         goto cleanup;
1497                 break;
1498         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1499                      USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U):
1500                 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed);
1501                 if (rc != 0)
1502                         goto cleanup;
1503                 break;
1504         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1505                      USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U):
1506                 if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) {
1507                         if (bInterfaceNumber == 0) {
1508                                 /* Try to probe v1 pen parameters */
1509                                 rc = uclogic_params_pen_init_v1(&p.pen,
1510                                                                 &found, hdev);
1511                                 if (rc != 0) {
1512                                         hid_err(hdev,
1513                                                 "pen probing failed: %d\n",
1514                                                 rc);
1515                                         goto cleanup;
1516                                 }
1517                                 if (!found) {
1518                                         hid_warn(hdev,
1519                                                  "pen parameters not found");
1520                                 }
1521                         } else {
1522                                 uclogic_params_init_invalid(&p);
1523                         }
1524                 } else {
1525                         rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed);
1526                         if (rc != 0)
1527                                 goto cleanup;
1528                 }
1529                 break;
1530         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1531                      USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U):
1532                 rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed);
1533                 if (rc != 0)
1534                         goto cleanup;
1535                 break;
1536         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1537                      USB_DEVICE_ID_UCLOGIC_TABLET_WP1062):
1538                 rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed);
1539                 if (rc != 0)
1540                         goto cleanup;
1541                 break;
1542         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1543                      USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850):
1544                 switch (bInterfaceNumber) {
1545                 case 0:
1546                         rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0);
1547                         if (rc != 0)
1548                                 goto cleanup;
1549                         break;
1550                 case 1:
1551                         rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1);
1552                         if (rc != 0)
1553                                 goto cleanup;
1554                         break;
1555                 case 2:
1556                         rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2);
1557                         if (rc != 0)
1558                                 goto cleanup;
1559                         break;
1560                 }
1561                 break;
1562         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1563                      USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60):
1564                 /*
1565                  * If it is not a three-interface version, which is known to
1566                  * respond to initialization.
1567                  */
1568                 if (bNumInterfaces != 3) {
1569                         switch (bInterfaceNumber) {
1570                         case 0:
1571                                 rc = WITH_OPT_DESC(TWHA60_ORIG0,
1572                                                         twha60_fixed0);
1573                                 if (rc != 0)
1574                                         goto cleanup;
1575                                 break;
1576                         case 1:
1577                                 rc = WITH_OPT_DESC(TWHA60_ORIG1,
1578                                                         twha60_fixed1);
1579                                 if (rc != 0)
1580                                         goto cleanup;
1581                                 break;
1582                         }
1583                         break;
1584                 }
1585                 fallthrough;
1586         case VID_PID(USB_VENDOR_ID_HUION,
1587                      USB_DEVICE_ID_HUION_TABLET):
1588         case VID_PID(USB_VENDOR_ID_HUION,
1589                      USB_DEVICE_ID_HUION_TABLET2):
1590         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1591                      USB_DEVICE_ID_HUION_TABLET):
1592         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1593                      USB_DEVICE_ID_YIYNOVA_TABLET):
1594         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1595                      USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81):
1596         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1597                      USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3):
1598         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1599                      USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45):
1600         case VID_PID(USB_VENDOR_ID_UCLOGIC,
1601                      USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47):
1602                 rc = uclogic_params_huion_init(&p, hdev);
1603                 if (rc != 0)
1604                         goto cleanup;
1605                 break;
1606         case VID_PID(USB_VENDOR_ID_UGTIZER,
1607                      USB_DEVICE_ID_UGTIZER_TABLET_GP0610):
1608         case VID_PID(USB_VENDOR_ID_UGTIZER,
1609                      USB_DEVICE_ID_UGTIZER_TABLET_GT5040):
1610         case VID_PID(USB_VENDOR_ID_UGEE,
1611                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
1612         case VID_PID(USB_VENDOR_ID_UGEE,
1613                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640):
1614         case VID_PID(USB_VENDOR_ID_UGEE,
1615                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06):
1616         case VID_PID(USB_VENDOR_ID_UGEE,
1617                      USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720):
1618                 /* If this is the pen interface */
1619                 if (bInterfaceNumber == 1) {
1620                         /* Probe v1 pen parameters */
1621                         rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1622                         if (rc != 0) {
1623                                 hid_err(hdev, "pen probing failed: %d\n", rc);
1624                                 goto cleanup;
1625                         }
1626                         if (!found) {
1627                                 hid_warn(hdev, "pen parameters not found");
1628                                 uclogic_params_init_invalid(&p);
1629                         }
1630                 } else {
1631                         uclogic_params_init_invalid(&p);
1632                 }
1633                 break;
1634         case VID_PID(USB_VENDOR_ID_UGEE,
1635                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01):
1636                 /* If this is the pen and frame interface */
1637                 if (bInterfaceNumber == 1) {
1638                         /* Probe v1 pen parameters */
1639                         rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1640                         if (rc != 0) {
1641                                 hid_err(hdev, "pen probing failed: %d\n", rc);
1642                                 goto cleanup;
1643                         }
1644                         /* Initialize frame parameters */
1645                         rc = uclogic_params_frame_init_with_desc(
1646                                 &p.frame_list[0],
1647                                 uclogic_rdesc_xppen_deco01_frame_arr,
1648                                 uclogic_rdesc_xppen_deco01_frame_size,
1649                                 0);
1650                         if (rc != 0)
1651                                 goto cleanup;
1652                 } else {
1653                         uclogic_params_init_invalid(&p);
1654                 }
1655                 break;
1656         case VID_PID(USB_VENDOR_ID_UGEE,
1657                      USB_DEVICE_ID_UGEE_PARBLO_A610_PRO):
1658         case VID_PID(USB_VENDOR_ID_UGEE,
1659                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L):
1660         case VID_PID(USB_VENDOR_ID_UGEE,
1661                      USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S):
1662                 rc = uclogic_params_ugee_v2_init(&p, hdev);
1663                 if (rc != 0)
1664                         goto cleanup;
1665                 break;
1666         case VID_PID(USB_VENDOR_ID_TRUST,
1667                      USB_DEVICE_ID_TRUST_PANORA_TABLET):
1668         case VID_PID(USB_VENDOR_ID_UGEE,
1669                      USB_DEVICE_ID_UGEE_TABLET_G5):
1670                 /* Ignore non-pen interfaces */
1671                 if (bInterfaceNumber != 1) {
1672                         uclogic_params_init_invalid(&p);
1673                         break;
1674                 }
1675
1676                 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1677                 if (rc != 0) {
1678                         hid_err(hdev, "pen probing failed: %d\n", rc);
1679                         goto cleanup;
1680                 } else if (found) {
1681                         rc = uclogic_params_frame_init_with_desc(
1682                                 &p.frame_list[0],
1683                                 uclogic_rdesc_ugee_g5_frame_arr,
1684                                 uclogic_rdesc_ugee_g5_frame_size,
1685                                 UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
1686                         if (rc != 0) {
1687                                 hid_err(hdev,
1688                                         "failed creating frame parameters: %d\n",
1689                                         rc);
1690                                 goto cleanup;
1691                         }
1692                         p.frame_list[0].re_lsb =
1693                                 UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
1694                         p.frame_list[0].dev_id_byte =
1695                                 UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
1696                 } else {
1697                         hid_warn(hdev, "pen parameters not found");
1698                         uclogic_params_init_invalid(&p);
1699                 }
1700
1701                 break;
1702         case VID_PID(USB_VENDOR_ID_UGEE,
1703                      USB_DEVICE_ID_UGEE_TABLET_EX07S):
1704                 /* Ignore non-pen interfaces */
1705                 if (bInterfaceNumber != 1) {
1706                         uclogic_params_init_invalid(&p);
1707                         break;
1708                 }
1709
1710                 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1711                 if (rc != 0) {
1712                         hid_err(hdev, "pen probing failed: %d\n", rc);
1713                         goto cleanup;
1714                 } else if (found) {
1715                         rc = uclogic_params_frame_init_with_desc(
1716                                 &p.frame_list[0],
1717                                 uclogic_rdesc_ugee_ex07_frame_arr,
1718                                 uclogic_rdesc_ugee_ex07_frame_size,
1719                                 0);
1720                         if (rc != 0) {
1721                                 hid_err(hdev,
1722                                         "failed creating frame parameters: %d\n",
1723                                         rc);
1724                                 goto cleanup;
1725                         }
1726                 } else {
1727                         hid_warn(hdev, "pen parameters not found");
1728                         uclogic_params_init_invalid(&p);
1729                 }
1730
1731                 break;
1732         }
1733
1734 #undef VID_PID
1735 #undef WITH_OPT_DESC
1736
1737         /* Output parameters */
1738         memcpy(params, &p, sizeof(*params));
1739         memset(&p, 0, sizeof(p));
1740         rc = 0;
1741 cleanup:
1742         uclogic_params_cleanup(&p);
1743         return rc;
1744 }
1745
1746 #ifdef CONFIG_HID_KUNIT_TEST
1747 #include "hid-uclogic-params-test.c"
1748 #endif