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_parse_ugee_v2_desc - parse the string descriptor containing
1061  * pen and frame parameters returned by UGEE v2 devices.
1062  *
1063  * @str_desc:		String descriptor, cannot be NULL.
1064  * @str_desc_size:	Size of the string descriptor.
1065  * @desc_params:	Output description params list.
1066  * @desc_params_size:	Size of the output description params list.
1067  *
1068  * Returns:
1069  *	Zero, if successful. A negative errno code on error.
1070  */
1071 static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc,
1072 					     size_t str_desc_size,
1073 					     s32 *desc_params,
1074 					     size_t desc_params_size)
1075 {
1076 	s32 pen_x_lm, pen_y_lm;
1077 	s32 pen_x_pm, pen_y_pm;
1078 	s32 pen_pressure_lm;
1079 	s32 frame_num_buttons;
1080 	s32 resolution;
1081 
1082 	/* Minimum descriptor length required, maximum seen so far is 14 */
1083 	const int min_str_desc_size = 12;
1084 
1085 	if (!str_desc || str_desc_size < min_str_desc_size)
1086 		return -EINVAL;
1087 
1088 	if (desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
1089 		return -EINVAL;
1090 
1091 	pen_x_lm = get_unaligned_le16(str_desc + 2);
1092 	pen_y_lm = get_unaligned_le16(str_desc + 4);
1093 	frame_num_buttons = str_desc[6];
1094 	pen_pressure_lm = get_unaligned_le16(str_desc + 8);
1095 
1096 	resolution = get_unaligned_le16(str_desc + 10);
1097 	if (resolution == 0) {
1098 		pen_x_pm = 0;
1099 		pen_y_pm = 0;
1100 	} else {
1101 		pen_x_pm = pen_x_lm * 1000 / resolution;
1102 		pen_y_pm = pen_y_lm * 1000 / resolution;
1103 	}
1104 
1105 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = pen_x_lm;
1106 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = pen_x_pm;
1107 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = pen_y_lm;
1108 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = pen_y_pm;
1109 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = pen_pressure_lm;
1110 	desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = frame_num_buttons;
1111 
1112 	return 0;
1113 }
1114 
1115 /**
1116  * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by
1117  * discovering their parameters.
1118  *
1119  * These tables, internally designed as v2 to differentiate them from older
1120  * models, expect a payload of magic data in orther to be switched to the fully
1121  * functional mode and expose their parameters in a similar way to the
1122  * information present in uclogic_params_pen_init_v1() but with some
1123  * differences.
1124  *
1125  * @params:	Parameters to fill in (to be cleaned with
1126  *		uclogic_params_cleanup()). Not modified in case of error.
1127  *		Cannot be NULL.
1128  * @hdev:	The HID device of the tablet interface to initialize and get
1129  *		parameters from. Cannot be NULL.
1130  *
1131  * Returns:
1132  *	Zero, if successful. A negative errno code on error.
1133  */
1134 static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
1135 				       struct hid_device *hdev)
1136 {
1137 	int rc = 0;
1138 	struct usb_interface *iface;
1139 	__u8 bInterfaceNumber;
1140 	const int str_desc_len = 12;
1141 	__u8 *str_desc = NULL;
1142 	__u8 *rdesc_pen = NULL;
1143 	__u8 *rdesc_frame = NULL;
1144 	s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
1145 	__u8 magic_arr[] = {
1146 		0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1147 	};
1148 	/* The resulting parameters (noop) */
1149 	struct uclogic_params p = {0, };
1150 
1151 	if (!params || !hdev) {
1152 		rc = -EINVAL;
1153 		goto cleanup;
1154 	}
1155 
1156 	iface = to_usb_interface(hdev->dev.parent);
1157 	bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1158 	if (bInterfaceNumber != 2) {
1159 		uclogic_params_init_invalid(&p);
1160 		goto output;
1161 	}
1162 
1163 	/*
1164 	 * Initialize the interface by sending magic data.
1165 	 * The specific data was discovered by sniffing the Windows driver
1166 	 * traffic.
1167 	 */
1168 	rc = uclogic_probe_interface(hdev, magic_arr, sizeof(magic_arr), 0x03);
1169 	if (rc) {
1170 		uclogic_params_init_invalid(&p);
1171 		goto output;
1172 	}
1173 
1174 	/*
1175 	 * Read the string descriptor containing pen and frame parameters.
1176 	 * The specific string descriptor and data were discovered by sniffing
1177 	 * the Windows driver traffic.
1178 	 */
1179 	rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len);
1180 	if (rc != str_desc_len) {
1181 		hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc);
1182 		uclogic_params_init_invalid(&p);
1183 		goto output;
1184 	}
1185 
1186 	rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len,
1187 					       desc_params,
1188 					       ARRAY_SIZE(desc_params));
1189 	if (rc)
1190 		goto cleanup;
1191 
1192 	kfree(str_desc);
1193 	str_desc = NULL;
1194 
1195 	/* Initialize the pen interface */
1196 	rdesc_pen = uclogic_rdesc_template_apply(
1197 				uclogic_rdesc_ugee_v2_pen_template_arr,
1198 				uclogic_rdesc_ugee_v2_pen_template_size,
1199 				desc_params, ARRAY_SIZE(desc_params));
1200 	if (!rdesc_pen) {
1201 		rc = -ENOMEM;
1202 		goto cleanup;
1203 	}
1204 
1205 	p.pen.desc_ptr = rdesc_pen;
1206 	p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size;
1207 	p.pen.id = 0x02;
1208 	p.pen.subreport_list[0].value = 0xf0;
1209 	p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
1210 
1211 	/* Initialize the frame interface */
1212 	rdesc_frame = uclogic_rdesc_template_apply(
1213 				uclogic_rdesc_ugee_v2_frame_btn_template_arr,
1214 				uclogic_rdesc_ugee_v2_frame_btn_template_size,
1215 				desc_params, ARRAY_SIZE(desc_params));
1216 	if (!rdesc_frame) {
1217 		rc = -ENOMEM;
1218 		goto cleanup;
1219 	}
1220 
1221 	rc = uclogic_params_frame_init_with_desc(&p.frame_list[0],
1222 						 rdesc_frame,
1223 						 uclogic_rdesc_ugee_v2_frame_btn_template_size,
1224 						 UCLOGIC_RDESC_V1_FRAME_ID);
1225 	kfree(rdesc_frame);
1226 	if (rc) {
1227 		uclogic_params_init_invalid(&p);
1228 		goto output;
1229 	}
1230 
1231 output:
1232 	/* Output parameters */
1233 	memcpy(params, &p, sizeof(*params));
1234 	memset(&p, 0, sizeof(p));
1235 	rc = 0;
1236 cleanup:
1237 	kfree(str_desc);
1238 	uclogic_params_cleanup(&p);
1239 	return rc;
1240 }
1241 
1242 /**
1243  * uclogic_params_init() - initialize a tablet interface and discover its
1244  * parameters.
1245  *
1246  * @params:	Parameters to fill in (to be cleaned with
1247  *		uclogic_params_cleanup()). Not modified in case of error.
1248  *		Cannot be NULL.
1249  * @hdev:	The HID device of the tablet interface to initialize and get
1250  *		parameters from. Cannot be NULL. Must be using the USB low-level
1251  *		driver, i.e. be an actual USB tablet.
1252  *
1253  * Returns:
1254  *	Zero, if successful. A negative errno code on error.
1255  */
1256 int uclogic_params_init(struct uclogic_params *params,
1257 			struct hid_device *hdev)
1258 {
1259 	int rc;
1260 	struct usb_device *udev;
1261 	__u8  bNumInterfaces;
1262 	struct usb_interface *iface;
1263 	__u8 bInterfaceNumber;
1264 	bool found;
1265 	/* The resulting parameters (noop) */
1266 	struct uclogic_params p = {0, };
1267 
1268 	/* Check arguments */
1269 	if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) {
1270 		rc = -EINVAL;
1271 		goto cleanup;
1272 	}
1273 
1274 	udev = hid_to_usb_dev(hdev);
1275 	bNumInterfaces = udev->config->desc.bNumInterfaces;
1276 	iface = to_usb_interface(hdev->dev.parent);
1277 	bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1278 
1279 	/*
1280 	 * Set replacement report descriptor if the original matches the
1281 	 * specified size. Otherwise keep interface unchanged.
1282 	 */
1283 #define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \
1284 	uclogic_params_init_with_opt_desc(                  \
1285 		&p, hdev,                                   \
1286 		UCLOGIC_RDESC_##_orig_desc_token##_SIZE,    \
1287 		uclogic_rdesc_##_new_desc_token##_arr,      \
1288 		uclogic_rdesc_##_new_desc_token##_size)
1289 
1290 #define VID_PID(_vid, _pid) \
1291 	(((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX))
1292 
1293 	/*
1294 	 * Handle specific interfaces for specific tablets.
1295 	 *
1296 	 * Observe the following logic:
1297 	 *
1298 	 * If the interface is recognized as producing certain useful input:
1299 	 *	Mark interface as valid.
1300 	 *	Output interface parameters.
1301 	 * Else, if the interface is recognized as *not* producing any useful
1302 	 * input:
1303 	 *	Mark interface as invalid.
1304 	 * Else:
1305 	 *	Mark interface as valid.
1306 	 *	Output noop parameters.
1307 	 *
1308 	 * Rule of thumb: it is better to disable a broken interface than let
1309 	 *		  it spew garbage input.
1310 	 */
1311 
1312 	switch (VID_PID(hdev->vendor, hdev->product)) {
1313 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1314 		     USB_DEVICE_ID_UCLOGIC_TABLET_PF1209):
1315 		rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed);
1316 		if (rc != 0)
1317 			goto cleanup;
1318 		break;
1319 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1320 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U):
1321 		rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed);
1322 		if (rc != 0)
1323 			goto cleanup;
1324 		break;
1325 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1326 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U):
1327 		if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) {
1328 			if (bInterfaceNumber == 0) {
1329 				/* Try to probe v1 pen parameters */
1330 				rc = uclogic_params_pen_init_v1(&p.pen,
1331 								&found, hdev);
1332 				if (rc != 0) {
1333 					hid_err(hdev,
1334 						"pen probing failed: %d\n",
1335 						rc);
1336 					goto cleanup;
1337 				}
1338 				if (!found) {
1339 					hid_warn(hdev,
1340 						 "pen parameters not found");
1341 				}
1342 			} else {
1343 				uclogic_params_init_invalid(&p);
1344 			}
1345 		} else {
1346 			rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed);
1347 			if (rc != 0)
1348 				goto cleanup;
1349 		}
1350 		break;
1351 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1352 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U):
1353 		rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed);
1354 		if (rc != 0)
1355 			goto cleanup;
1356 		break;
1357 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1358 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP1062):
1359 		rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed);
1360 		if (rc != 0)
1361 			goto cleanup;
1362 		break;
1363 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1364 		     USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850):
1365 		switch (bInterfaceNumber) {
1366 		case 0:
1367 			rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0);
1368 			if (rc != 0)
1369 				goto cleanup;
1370 			break;
1371 		case 1:
1372 			rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1);
1373 			if (rc != 0)
1374 				goto cleanup;
1375 			break;
1376 		case 2:
1377 			rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2);
1378 			if (rc != 0)
1379 				goto cleanup;
1380 			break;
1381 		}
1382 		break;
1383 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1384 		     USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60):
1385 		/*
1386 		 * If it is not a three-interface version, which is known to
1387 		 * respond to initialization.
1388 		 */
1389 		if (bNumInterfaces != 3) {
1390 			switch (bInterfaceNumber) {
1391 			case 0:
1392 				rc = WITH_OPT_DESC(TWHA60_ORIG0,
1393 							twha60_fixed0);
1394 				if (rc != 0)
1395 					goto cleanup;
1396 				break;
1397 			case 1:
1398 				rc = WITH_OPT_DESC(TWHA60_ORIG1,
1399 							twha60_fixed1);
1400 				if (rc != 0)
1401 					goto cleanup;
1402 				break;
1403 			}
1404 			break;
1405 		}
1406 		fallthrough;
1407 	case VID_PID(USB_VENDOR_ID_HUION,
1408 		     USB_DEVICE_ID_HUION_TABLET):
1409 	case VID_PID(USB_VENDOR_ID_HUION,
1410 		     USB_DEVICE_ID_HUION_TABLET2):
1411 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1412 		     USB_DEVICE_ID_HUION_TABLET):
1413 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1414 		     USB_DEVICE_ID_YIYNOVA_TABLET):
1415 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1416 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81):
1417 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1418 		     USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3):
1419 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1420 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45):
1421 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1422 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47):
1423 		rc = uclogic_params_huion_init(&p, hdev);
1424 		if (rc != 0)
1425 			goto cleanup;
1426 		break;
1427 	case VID_PID(USB_VENDOR_ID_UGTIZER,
1428 		     USB_DEVICE_ID_UGTIZER_TABLET_GP0610):
1429 	case VID_PID(USB_VENDOR_ID_UGTIZER,
1430 		     USB_DEVICE_ID_UGTIZER_TABLET_GT5040):
1431 	case VID_PID(USB_VENDOR_ID_UGEE,
1432 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
1433 	case VID_PID(USB_VENDOR_ID_UGEE,
1434 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640):
1435 	case VID_PID(USB_VENDOR_ID_UGEE,
1436 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06):
1437 	case VID_PID(USB_VENDOR_ID_UGEE,
1438 		     USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720):
1439 		/* If this is the pen interface */
1440 		if (bInterfaceNumber == 1) {
1441 			/* Probe v1 pen parameters */
1442 			rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1443 			if (rc != 0) {
1444 				hid_err(hdev, "pen probing failed: %d\n", rc);
1445 				goto cleanup;
1446 			}
1447 			if (!found) {
1448 				hid_warn(hdev, "pen parameters not found");
1449 				uclogic_params_init_invalid(&p);
1450 			}
1451 		} else {
1452 			uclogic_params_init_invalid(&p);
1453 		}
1454 		break;
1455 	case VID_PID(USB_VENDOR_ID_UGEE,
1456 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01):
1457 		/* If this is the pen and frame interface */
1458 		if (bInterfaceNumber == 1) {
1459 			/* Probe v1 pen parameters */
1460 			rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1461 			if (rc != 0) {
1462 				hid_err(hdev, "pen probing failed: %d\n", rc);
1463 				goto cleanup;
1464 			}
1465 			/* Initialize frame parameters */
1466 			rc = uclogic_params_frame_init_with_desc(
1467 				&p.frame_list[0],
1468 				uclogic_rdesc_xppen_deco01_frame_arr,
1469 				uclogic_rdesc_xppen_deco01_frame_size,
1470 				0);
1471 			if (rc != 0)
1472 				goto cleanup;
1473 		} else {
1474 			uclogic_params_init_invalid(&p);
1475 		}
1476 		break;
1477 	case VID_PID(USB_VENDOR_ID_UGEE,
1478 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L):
1479 		rc = uclogic_params_ugee_v2_init(&p, hdev);
1480 		if (rc != 0)
1481 			goto cleanup;
1482 		break;
1483 	case VID_PID(USB_VENDOR_ID_TRUST,
1484 		     USB_DEVICE_ID_TRUST_PANORA_TABLET):
1485 	case VID_PID(USB_VENDOR_ID_UGEE,
1486 		     USB_DEVICE_ID_UGEE_TABLET_G5):
1487 		/* Ignore non-pen interfaces */
1488 		if (bInterfaceNumber != 1) {
1489 			uclogic_params_init_invalid(&p);
1490 			break;
1491 		}
1492 
1493 		rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1494 		if (rc != 0) {
1495 			hid_err(hdev, "pen probing failed: %d\n", rc);
1496 			goto cleanup;
1497 		} else if (found) {
1498 			rc = uclogic_params_frame_init_with_desc(
1499 				&p.frame_list[0],
1500 				uclogic_rdesc_ugee_g5_frame_arr,
1501 				uclogic_rdesc_ugee_g5_frame_size,
1502 				UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
1503 			if (rc != 0) {
1504 				hid_err(hdev,
1505 					"failed creating frame parameters: %d\n",
1506 					rc);
1507 				goto cleanup;
1508 			}
1509 			p.frame_list[0].re_lsb =
1510 				UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
1511 			p.frame_list[0].dev_id_byte =
1512 				UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
1513 		} else {
1514 			hid_warn(hdev, "pen parameters not found");
1515 			uclogic_params_init_invalid(&p);
1516 		}
1517 
1518 		break;
1519 	case VID_PID(USB_VENDOR_ID_UGEE,
1520 		     USB_DEVICE_ID_UGEE_TABLET_EX07S):
1521 		/* Ignore non-pen interfaces */
1522 		if (bInterfaceNumber != 1) {
1523 			uclogic_params_init_invalid(&p);
1524 			break;
1525 		}
1526 
1527 		rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1528 		if (rc != 0) {
1529 			hid_err(hdev, "pen probing failed: %d\n", rc);
1530 			goto cleanup;
1531 		} else if (found) {
1532 			rc = uclogic_params_frame_init_with_desc(
1533 				&p.frame_list[0],
1534 				uclogic_rdesc_ugee_ex07_frame_arr,
1535 				uclogic_rdesc_ugee_ex07_frame_size,
1536 				0);
1537 			if (rc != 0) {
1538 				hid_err(hdev,
1539 					"failed creating frame parameters: %d\n",
1540 					rc);
1541 				goto cleanup;
1542 			}
1543 		} else {
1544 			hid_warn(hdev, "pen parameters not found");
1545 			uclogic_params_init_invalid(&p);
1546 		}
1547 
1548 		break;
1549 	}
1550 
1551 #undef VID_PID
1552 #undef WITH_OPT_DESC
1553 
1554 	/* Output parameters */
1555 	memcpy(params, &p, sizeof(*params));
1556 	memset(&p, 0, sizeof(p));
1557 	rc = 0;
1558 cleanup:
1559 	uclogic_params_cleanup(&p);
1560 	return rc;
1561 }
1562 
1563 #ifdef CONFIG_HID_KUNIT_TEST
1564 #include "hid-uclogic-params-test.c"
1565 #endif
1566