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