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 }
1520