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  *
27  * @inrange:	The in-range reporting type to convert.
28  *
29  * Returns:
30  *	The string representing the type, or NULL if the type is unknown.
31  */
32 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_get_str_desc - retrieve a string descriptor from a HID
49  * device interface, putting it into a kmalloc-allocated buffer as is, without
50  * character encoding conversion.
51  *
52  * @pbuf:	Location for the kmalloc-allocated buffer pointer containing
53  *		the retrieved descriptor. Not modified in case of error.
54  *		Can be NULL to have retrieved descriptor discarded.
55  * @hdev:	The HID device of the tablet interface to retrieve the string
56  *		descriptor from. Cannot be NULL.
57  * @idx:	Index of the string descriptor to request from the device.
58  * @len:	Length of the buffer to allocate and the data to retrieve.
59  *
60  * Returns:
61  *	number of bytes retrieved (<= len),
62  *	-EPIPE, if the descriptor was not found, or
63  *	another negative errno code in case of other error.
64  */
65 static int uclogic_params_get_str_desc(__u8 **pbuf, struct hid_device *hdev,
66 					__u8 idx, size_t len)
67 {
68 	int rc;
69 	struct usb_device *udev = hid_to_usb_dev(hdev);
70 	__u8 *buf = NULL;
71 
72 	/* Check arguments */
73 	if (hdev == NULL) {
74 		rc = -EINVAL;
75 		goto cleanup;
76 	}
77 
78 	buf = kmalloc(len, GFP_KERNEL);
79 	if (buf == NULL) {
80 		rc = -ENOMEM;
81 		goto cleanup;
82 	}
83 
84 	rc = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
85 				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
86 				(USB_DT_STRING << 8) + idx,
87 				0x0409, buf, len,
88 				USB_CTRL_GET_TIMEOUT);
89 	if (rc == -EPIPE) {
90 		hid_dbg(hdev, "string descriptor #%hhu not found\n", idx);
91 		goto cleanup;
92 	} else if (rc < 0) {
93 		hid_err(hdev,
94 			"failed retrieving string descriptor #%u: %d\n",
95 			idx, rc);
96 		goto cleanup;
97 	}
98 
99 	if (pbuf != NULL) {
100 		*pbuf = buf;
101 		buf = NULL;
102 	}
103 
104 cleanup:
105 	kfree(buf);
106 	return rc;
107 }
108 
109 /**
110  * uclogic_params_pen_cleanup - free resources used by struct
111  * uclogic_params_pen (tablet interface's pen input parameters).
112  * Can be called repeatedly.
113  *
114  * @pen:	Pen input parameters to cleanup. Cannot be NULL.
115  */
116 static void uclogic_params_pen_cleanup(struct uclogic_params_pen *pen)
117 {
118 	kfree(pen->desc_ptr);
119 	memset(pen, 0, sizeof(*pen));
120 }
121 
122 /**
123  * uclogic_params_pen_init_v1() - initialize tablet interface pen
124  * input and retrieve its parameters from the device, using v1 protocol.
125  *
126  * @pen:	Pointer to the pen parameters to initialize (to be
127  *		cleaned up with uclogic_params_pen_cleanup()). Not modified in
128  *		case of error, or if parameters are not found. Cannot be NULL.
129  * @pfound:	Location for a flag which is set to true if the parameters
130  *		were found, and to false if not (e.g. device was
131  *		incompatible). Not modified in case of error. Cannot be NULL.
132  * @hdev:	The HID device of the tablet interface to initialize and get
133  *		parameters from. Cannot be NULL.
134  *
135  * Returns:
136  *	Zero, if successful. A negative errno code on error.
137  */
138 static int uclogic_params_pen_init_v1(struct uclogic_params_pen *pen,
139 				      bool *pfound,
140 				      struct hid_device *hdev)
141 {
142 	int rc;
143 	bool found = false;
144 	/* Buffer for (part of) the string descriptor */
145 	__u8 *buf = NULL;
146 	/* Minimum descriptor length required, maximum seen so far is 18 */
147 	const int len = 12;
148 	s32 resolution;
149 	/* Pen report descriptor template parameters */
150 	s32 desc_params[UCLOGIC_RDESC_PEN_PH_ID_NUM];
151 	__u8 *desc_ptr = NULL;
152 
153 	/* Check arguments */
154 	if (pen == NULL || pfound == NULL || hdev == NULL) {
155 		rc = -EINVAL;
156 		goto cleanup;
157 	}
158 
159 	/*
160 	 * Read string descriptor containing pen input parameters.
161 	 * The specific string descriptor and data were discovered by sniffing
162 	 * the Windows driver traffic.
163 	 * NOTE: This enables fully-functional tablet mode.
164 	 */
165 	rc = uclogic_params_get_str_desc(&buf, hdev, 100, len);
166 	if (rc == -EPIPE) {
167 		hid_dbg(hdev,
168 			"string descriptor with pen parameters not found, assuming not compatible\n");
169 		goto finish;
170 	} else if (rc < 0) {
171 		hid_err(hdev, "failed retrieving pen parameters: %d\n", rc);
172 		goto cleanup;
173 	} else if (rc != len) {
174 		hid_dbg(hdev,
175 			"string descriptor with pen parameters has invalid length (got %d, expected %d), assuming not compatible\n",
176 			rc, len);
177 		goto finish;
178 	}
179 
180 	/*
181 	 * Fill report descriptor parameters from the string descriptor
182 	 */
183 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] =
184 		get_unaligned_le16(buf + 2);
185 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] =
186 		get_unaligned_le16(buf + 4);
187 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] =
188 		get_unaligned_le16(buf + 8);
189 	resolution = get_unaligned_le16(buf + 10);
190 	if (resolution == 0) {
191 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0;
192 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0;
193 	} else {
194 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] =
195 			desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 /
196 			resolution;
197 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] =
198 			desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 /
199 			resolution;
200 	}
201 	kfree(buf);
202 	buf = NULL;
203 
204 	/*
205 	 * Generate pen report descriptor
206 	 */
207 	desc_ptr = uclogic_rdesc_template_apply(
208 				uclogic_rdesc_pen_v1_template_arr,
209 				uclogic_rdesc_pen_v1_template_size,
210 				desc_params, ARRAY_SIZE(desc_params));
211 	if (desc_ptr == NULL) {
212 		rc = -ENOMEM;
213 		goto cleanup;
214 	}
215 
216 	/*
217 	 * Fill-in the parameters
218 	 */
219 	memset(pen, 0, sizeof(*pen));
220 	pen->desc_ptr = desc_ptr;
221 	desc_ptr = NULL;
222 	pen->desc_size = uclogic_rdesc_pen_v1_template_size;
223 	pen->id = UCLOGIC_RDESC_PEN_V1_ID;
224 	pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_INVERTED;
225 	found = true;
226 finish:
227 	*pfound = found;
228 	rc = 0;
229 cleanup:
230 	kfree(desc_ptr);
231 	kfree(buf);
232 	return rc;
233 }
234 
235 /**
236  * uclogic_params_get_le24() - get a 24-bit little-endian number from a
237  * buffer.
238  *
239  * @p:	The pointer to the number buffer.
240  *
241  * Returns:
242  *	The retrieved number
243  */
244 static s32 uclogic_params_get_le24(const void *p)
245 {
246 	const __u8 *b = p;
247 	return b[0] | (b[1] << 8UL) | (b[2] << 16UL);
248 }
249 
250 /**
251  * uclogic_params_pen_init_v2() - initialize tablet interface pen
252  * input and retrieve its parameters from the device, using v2 protocol.
253  *
254  * @pen:	Pointer to the pen parameters to initialize (to be
255  *		cleaned up with uclogic_params_pen_cleanup()). Not modified in
256  *		case of error, or if parameters are not found. Cannot be NULL.
257  * @pfound:	Location for a flag which is set to true if the parameters
258  *		were found, and to false if not (e.g. device was
259  *		incompatible). Not modified in case of error. Cannot be NULL.
260  * @hdev:	The HID device of the tablet interface to initialize and get
261  *		parameters from. Cannot be NULL.
262  *
263  * Returns:
264  *	Zero, if successful. A negative errno code on error.
265  */
266 static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen,
267 					bool *pfound,
268 					struct hid_device *hdev)
269 {
270 	int rc;
271 	bool found = false;
272 	/* Buffer for (part of) the string descriptor */
273 	__u8 *buf = NULL;
274 	/* Descriptor length required */
275 	const int len = 18;
276 	s32 resolution;
277 	/* Pen report descriptor template parameters */
278 	s32 desc_params[UCLOGIC_RDESC_PEN_PH_ID_NUM];
279 	__u8 *desc_ptr = NULL;
280 
281 	/* Check arguments */
282 	if (pen == NULL || pfound == NULL || hdev == NULL) {
283 		rc = -EINVAL;
284 		goto cleanup;
285 	}
286 
287 	/*
288 	 * Read string descriptor containing pen input parameters.
289 	 * The specific string descriptor and data were discovered by sniffing
290 	 * the Windows driver traffic.
291 	 * NOTE: This enables fully-functional tablet mode.
292 	 */
293 	rc = uclogic_params_get_str_desc(&buf, hdev, 200, len);
294 	if (rc == -EPIPE) {
295 		hid_dbg(hdev,
296 			"string descriptor with pen parameters not found, assuming not compatible\n");
297 		goto finish;
298 	} else if (rc < 0) {
299 		hid_err(hdev, "failed retrieving pen parameters: %d\n", rc);
300 		goto cleanup;
301 	} else if (rc != len) {
302 		hid_dbg(hdev,
303 			"string descriptor with pen parameters has invalid length (got %d, expected %d), assuming not compatible\n",
304 			rc, len);
305 		goto finish;
306 	} else {
307 		size_t i;
308 		/*
309 		 * Check it's not just a catch-all UTF-16LE-encoded ASCII
310 		 * string (such as the model name) some tablets put into all
311 		 * unknown string descriptors.
312 		 */
313 		for (i = 2;
314 		     i < len &&
315 			(buf[i] >= 0x20 && buf[i] < 0x7f && buf[i + 1] == 0);
316 		     i += 2);
317 		if (i >= len) {
318 			hid_dbg(hdev,
319 				"string descriptor with pen parameters seems to contain only text, assuming not compatible\n");
320 			goto finish;
321 		}
322 	}
323 
324 	/*
325 	 * Fill report descriptor parameters from the string descriptor
326 	 */
327 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] =
328 		uclogic_params_get_le24(buf + 2);
329 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] =
330 		uclogic_params_get_le24(buf + 5);
331 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] =
332 		get_unaligned_le16(buf + 8);
333 	resolution = get_unaligned_le16(buf + 10);
334 	if (resolution == 0) {
335 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0;
336 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0;
337 	} else {
338 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] =
339 			desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 /
340 			resolution;
341 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] =
342 			desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 /
343 			resolution;
344 	}
345 	kfree(buf);
346 	buf = NULL;
347 
348 	/*
349 	 * Generate pen report descriptor
350 	 */
351 	desc_ptr = uclogic_rdesc_template_apply(
352 				uclogic_rdesc_pen_v2_template_arr,
353 				uclogic_rdesc_pen_v2_template_size,
354 				desc_params, ARRAY_SIZE(desc_params));
355 	if (desc_ptr == NULL) {
356 		rc = -ENOMEM;
357 		goto cleanup;
358 	}
359 
360 	/*
361 	 * Fill-in the parameters
362 	 */
363 	memset(pen, 0, sizeof(*pen));
364 	pen->desc_ptr = desc_ptr;
365 	desc_ptr = NULL;
366 	pen->desc_size = uclogic_rdesc_pen_v2_template_size;
367 	pen->id = UCLOGIC_RDESC_PEN_V2_ID;
368 	pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_NONE;
369 	pen->fragmented_hires = true;
370 	found = true;
371 finish:
372 	*pfound = found;
373 	rc = 0;
374 cleanup:
375 	kfree(desc_ptr);
376 	kfree(buf);
377 	return rc;
378 }
379 
380 /**
381  * uclogic_params_frame_cleanup - free resources used by struct
382  * uclogic_params_frame (tablet interface's frame controls input parameters).
383  * Can be called repeatedly.
384  *
385  * @frame:	Frame controls input parameters to cleanup. Cannot be NULL.
386  */
387 static void uclogic_params_frame_cleanup(struct uclogic_params_frame *frame)
388 {
389 	kfree(frame->desc_ptr);
390 	memset(frame, 0, sizeof(*frame));
391 }
392 
393 /**
394  * uclogic_params_frame_init_with_desc() - initialize tablet's frame control
395  * parameters with a static report descriptor.
396  *
397  * @frame:	Pointer to the frame parameters to initialize (to be cleaned
398  *		up with uclogic_params_frame_cleanup()). Not modified in case
399  *		of error. Cannot be NULL.
400  * @desc_ptr:	Report descriptor pointer. Can be NULL, if desc_size is zero.
401  * @desc_size:	Report descriptor size.
402  * @id:		Report ID used for frame reports, if they should be tweaked,
403  *		zero if not.
404  *
405  * Returns:
406  *	Zero, if successful. A negative errno code on error.
407  */
408 static int uclogic_params_frame_init_with_desc(
409 					struct uclogic_params_frame *frame,
410 					const __u8 *desc_ptr,
411 					size_t desc_size,
412 					unsigned int id)
413 {
414 	__u8 *copy_desc_ptr;
415 
416 	if (frame == NULL || (desc_ptr == NULL && desc_size != 0))
417 		return -EINVAL;
418 
419 	copy_desc_ptr = kmemdup(desc_ptr, desc_size, GFP_KERNEL);
420 	if (copy_desc_ptr == NULL)
421 		return -ENOMEM;
422 
423 	memset(frame, 0, sizeof(*frame));
424 	frame->desc_ptr = copy_desc_ptr;
425 	frame->desc_size = desc_size;
426 	frame->id = id;
427 	return 0;
428 }
429 
430 /**
431  * uclogic_params_frame_init_v1_buttonpad() - initialize abstract buttonpad
432  * on a v1 tablet interface.
433  *
434  * @frame:	Pointer to the frame parameters to initialize (to be cleaned
435  *		up with uclogic_params_frame_cleanup()). Not modified in case
436  *		of error, or if parameters are not found. Cannot be NULL.
437  * @pfound:	Location for a flag which is set to true if the parameters
438  *		were found, and to false if not (e.g. device was
439  *		incompatible). Not modified in case of error. Cannot be NULL.
440  * @hdev:	The HID device of the tablet interface to initialize and get
441  *		parameters from. Cannot be NULL.
442  *
443  * Returns:
444  *	Zero, if successful. A negative errno code on error.
445  */
446 static int uclogic_params_frame_init_v1_buttonpad(
447 					struct uclogic_params_frame *frame,
448 					bool *pfound,
449 					struct hid_device *hdev)
450 {
451 	int rc;
452 	bool found = false;
453 	struct usb_device *usb_dev = hid_to_usb_dev(hdev);
454 	char *str_buf = NULL;
455 	const size_t str_len = 16;
456 
457 	/* Check arguments */
458 	if (frame == NULL || pfound == NULL || hdev == NULL) {
459 		rc = -EINVAL;
460 		goto cleanup;
461 	}
462 
463 	/*
464 	 * Enable generic button mode
465 	 */
466 	str_buf = kzalloc(str_len, GFP_KERNEL);
467 	if (str_buf == NULL) {
468 		rc = -ENOMEM;
469 		goto cleanup;
470 	}
471 
472 	rc = usb_string(usb_dev, 123, str_buf, str_len);
473 	if (rc == -EPIPE) {
474 		hid_dbg(hdev,
475 			"generic button -enabling string descriptor not found\n");
476 	} else if (rc < 0) {
477 		goto cleanup;
478 	} else if (strncmp(str_buf, "HK On", rc) != 0) {
479 		hid_dbg(hdev,
480 			"invalid response to enabling generic buttons: \"%s\"\n",
481 			str_buf);
482 	} else {
483 		hid_dbg(hdev, "generic buttons enabled\n");
484 		rc = uclogic_params_frame_init_with_desc(
485 				frame,
486 				uclogic_rdesc_buttonpad_v1_arr,
487 				uclogic_rdesc_buttonpad_v1_size,
488 				UCLOGIC_RDESC_BUTTONPAD_V1_ID);
489 		if (rc != 0)
490 			goto cleanup;
491 		found = true;
492 	}
493 
494 	*pfound = found;
495 	rc = 0;
496 cleanup:
497 	kfree(str_buf);
498 	return rc;
499 }
500 
501 /**
502  * uclogic_params_cleanup - free resources used by struct uclogic_params
503  * (tablet interface's parameters).
504  * Can be called repeatedly.
505  *
506  * @params:	Input parameters to cleanup. Cannot be NULL.
507  */
508 void uclogic_params_cleanup(struct uclogic_params *params)
509 {
510 	if (!params->invalid) {
511 		kfree(params->desc_ptr);
512 		if (!params->pen_unused)
513 			uclogic_params_pen_cleanup(&params->pen);
514 		uclogic_params_frame_cleanup(&params->frame);
515 		memset(params, 0, sizeof(*params));
516 	}
517 }
518 
519 /**
520  * uclogic_params_get_desc() - Get a replacement report descriptor for a
521  *                             tablet's interface.
522  *
523  * @params:	The parameters of a tablet interface to get report
524  *		descriptor for. Cannot be NULL.
525  * @pdesc:	Location for the resulting, kmalloc-allocated report
526  *		descriptor pointer, or for NULL, if there's no replacement
527  *		report descriptor. Not modified in case of error. Cannot be
528  *		NULL.
529  * @psize:	Location for the resulting report descriptor size, not set if
530  *		there's no replacement report descriptor. Not modified in case
531  *		of error. Cannot be NULL.
532  *
533  * Returns:
534  *	Zero, if successful.
535  *	-EINVAL, if invalid arguments are supplied.
536  *	-ENOMEM, if failed to allocate memory.
537  */
538 int uclogic_params_get_desc(const struct uclogic_params *params,
539 				__u8 **pdesc,
540 				unsigned int *psize)
541 {
542 	bool common_present;
543 	bool pen_present;
544 	bool frame_present;
545 	unsigned int size;
546 	__u8 *desc = NULL;
547 
548 	/* Check arguments */
549 	if (params == NULL || pdesc == NULL || psize == NULL)
550 		return -EINVAL;
551 
552 	size = 0;
553 
554 	common_present = (params->desc_ptr != NULL);
555 	pen_present = (!params->pen_unused && params->pen.desc_ptr != NULL);
556 	frame_present = (params->frame.desc_ptr != NULL);
557 
558 	if (common_present)
559 		size += params->desc_size;
560 	if (pen_present)
561 		size += params->pen.desc_size;
562 	if (frame_present)
563 		size += params->frame.desc_size;
564 
565 	if (common_present || pen_present || frame_present) {
566 		__u8 *p;
567 
568 		desc = kmalloc(size, GFP_KERNEL);
569 		if (desc == NULL)
570 			return -ENOMEM;
571 		p = desc;
572 
573 		if (common_present) {
574 			memcpy(p, params->desc_ptr,
575 				params->desc_size);
576 			p += params->desc_size;
577 		}
578 		if (pen_present) {
579 			memcpy(p, params->pen.desc_ptr,
580 				params->pen.desc_size);
581 			p += params->pen.desc_size;
582 		}
583 		if (frame_present) {
584 			memcpy(p, params->frame.desc_ptr,
585 				params->frame.desc_size);
586 			p += params->frame.desc_size;
587 		}
588 
589 		WARN_ON(p != desc + size);
590 
591 		*psize = size;
592 	}
593 
594 	*pdesc = desc;
595 	return 0;
596 }
597 
598 /**
599  * uclogic_params_init_invalid() - initialize tablet interface parameters,
600  * specifying the interface is invalid.
601  *
602  * @params:		Parameters to initialize (to be cleaned with
603  *			uclogic_params_cleanup()). Cannot be NULL.
604  */
605 static void uclogic_params_init_invalid(struct uclogic_params *params)
606 {
607 	params->invalid = true;
608 }
609 
610 /**
611  * uclogic_params_init_with_opt_desc() - initialize tablet interface
612  * parameters with an optional replacement report descriptor. Only modify
613  * report descriptor, if the original report descriptor matches the expected
614  * size.
615  *
616  * @params:		Parameters to initialize (to be cleaned with
617  *			uclogic_params_cleanup()). Not modified in case of
618  *			error. Cannot be NULL.
619  * @hdev:		The HID device of the tablet interface create the
620  *			parameters for. Cannot be NULL.
621  * @orig_desc_size:	Expected size of the original report descriptor to
622  *			be replaced.
623  * @desc_ptr:		Pointer to the replacement report descriptor.
624  *			Can be NULL, if desc_size is zero.
625  * @desc_size:		Size of the replacement report descriptor.
626  *
627  * Returns:
628  *	Zero, if successful. -EINVAL if an invalid argument was passed.
629  *	-ENOMEM, if failed to allocate memory.
630  */
631 static int uclogic_params_init_with_opt_desc(struct uclogic_params *params,
632 					     struct hid_device *hdev,
633 					     unsigned int orig_desc_size,
634 					     __u8 *desc_ptr,
635 					     unsigned int desc_size)
636 {
637 	__u8 *desc_copy_ptr = NULL;
638 	unsigned int desc_copy_size;
639 	int rc;
640 
641 	/* Check arguments */
642 	if (params == NULL || hdev == NULL ||
643 	    (desc_ptr == NULL && desc_size != 0)) {
644 		rc = -EINVAL;
645 		goto cleanup;
646 	}
647 
648 	/* Replace report descriptor, if it matches */
649 	if (hdev->dev_rsize == orig_desc_size) {
650 		hid_dbg(hdev,
651 			"device report descriptor matches the expected size, replacing\n");
652 		desc_copy_ptr = kmemdup(desc_ptr, desc_size, GFP_KERNEL);
653 		if (desc_copy_ptr == NULL) {
654 			rc = -ENOMEM;
655 			goto cleanup;
656 		}
657 		desc_copy_size = desc_size;
658 	} else {
659 		hid_dbg(hdev,
660 			"device report descriptor doesn't match the expected size (%u != %u), preserving\n",
661 			hdev->dev_rsize, orig_desc_size);
662 		desc_copy_ptr = NULL;
663 		desc_copy_size = 0;
664 	}
665 
666 	/* Output parameters */
667 	memset(params, 0, sizeof(*params));
668 	params->desc_ptr = desc_copy_ptr;
669 	desc_copy_ptr = NULL;
670 	params->desc_size = desc_copy_size;
671 
672 	rc = 0;
673 cleanup:
674 	kfree(desc_copy_ptr);
675 	return rc;
676 }
677 
678 /**
679  * uclogic_params_init_with_pen_unused() - initialize tablet interface
680  * parameters preserving original reports and generic HID processing, but
681  * disabling pen usage.
682  *
683  * @params:		Parameters to initialize (to be cleaned with
684  *			uclogic_params_cleanup()). Not modified in case of
685  *			error. Cannot be NULL.
686  */
687 static void uclogic_params_init_with_pen_unused(struct uclogic_params *params)
688 {
689 	memset(params, 0, sizeof(*params));
690 	params->pen_unused = true;
691 }
692 
693 /**
694  * uclogic_params_huion_init() - initialize a Huion tablet interface and discover
695  * its parameters.
696  *
697  * @params:	Parameters to fill in (to be cleaned with
698  *		uclogic_params_cleanup()). Not modified in case of error.
699  *		Cannot be NULL.
700  * @hdev:	The HID device of the tablet interface to initialize and get
701  *		parameters from. Cannot be NULL.
702  *
703  * Returns:
704  *	Zero, if successful. A negative errno code on error.
705  */
706 static int uclogic_params_huion_init(struct uclogic_params *params,
707 				     struct hid_device *hdev)
708 {
709 	int rc;
710 	struct usb_device *udev = hid_to_usb_dev(hdev);
711 	struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
712 	__u8 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
713 	bool found;
714 	/* The resulting parameters (noop) */
715 	struct uclogic_params p = {0, };
716 	static const char transition_ver[] = "HUION_T153_160607";
717 	char *ver_ptr = NULL;
718 	const size_t ver_len = sizeof(transition_ver) + 1;
719 
720 	/* Check arguments */
721 	if (params == NULL || hdev == NULL) {
722 		rc = -EINVAL;
723 		goto cleanup;
724 	}
725 
726 	/* If it's not a pen interface */
727 	if (bInterfaceNumber != 0) {
728 		/* TODO: Consider marking the interface invalid */
729 		uclogic_params_init_with_pen_unused(&p);
730 		goto output;
731 	}
732 
733 	/* Try to get firmware version */
734 	ver_ptr = kzalloc(ver_len, GFP_KERNEL);
735 	if (ver_ptr == NULL) {
736 		rc = -ENOMEM;
737 		goto cleanup;
738 	}
739 	rc = usb_string(udev, 201, ver_ptr, ver_len);
740 	if (rc == -EPIPE) {
741 		*ver_ptr = '\0';
742 	} else if (rc < 0) {
743 		hid_err(hdev,
744 			"failed retrieving Huion firmware version: %d\n", rc);
745 		goto cleanup;
746 	}
747 
748 	/* If this is a transition firmware */
749 	if (strcmp(ver_ptr, transition_ver) == 0) {
750 		hid_dbg(hdev,
751 			"transition firmware detected, not probing pen v2 parameters\n");
752 	} else {
753 		/* Try to probe v2 pen parameters */
754 		rc = uclogic_params_pen_init_v2(&p.pen, &found, hdev);
755 		if (rc != 0) {
756 			hid_err(hdev,
757 				"failed probing pen v2 parameters: %d\n", rc);
758 			goto cleanup;
759 		} else if (found) {
760 			hid_dbg(hdev, "pen v2 parameters found\n");
761 			/* Create v2 buttonpad parameters */
762 			rc = uclogic_params_frame_init_with_desc(
763 					&p.frame,
764 					uclogic_rdesc_buttonpad_v2_arr,
765 					uclogic_rdesc_buttonpad_v2_size,
766 					UCLOGIC_RDESC_BUTTONPAD_V2_ID);
767 			if (rc != 0) {
768 				hid_err(hdev,
769 					"failed creating v2 buttonpad parameters: %d\n",
770 					rc);
771 				goto cleanup;
772 			}
773 			/* Set bitmask marking frame reports in pen reports */
774 			p.pen_frame_flag = 0x20;
775 			goto output;
776 		}
777 		hid_dbg(hdev, "pen v2 parameters not found\n");
778 	}
779 
780 	/* Try to probe v1 pen parameters */
781 	rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
782 	if (rc != 0) {
783 		hid_err(hdev,
784 			"failed probing pen v1 parameters: %d\n", rc);
785 		goto cleanup;
786 	} else if (found) {
787 		hid_dbg(hdev, "pen v1 parameters found\n");
788 		/* Try to probe v1 buttonpad */
789 		rc = uclogic_params_frame_init_v1_buttonpad(
790 						&p.frame,
791 						&found, hdev);
792 		if (rc != 0) {
793 			hid_err(hdev, "v1 buttonpad probing failed: %d\n", rc);
794 			goto cleanup;
795 		}
796 		hid_dbg(hdev, "buttonpad v1 parameters%s found\n",
797 			(found ? "" : " not"));
798 		if (found) {
799 			/* Set bitmask marking frame reports */
800 			p.pen_frame_flag = 0x20;
801 		}
802 		goto output;
803 	}
804 	hid_dbg(hdev, "pen v1 parameters not found\n");
805 
806 	uclogic_params_init_invalid(&p);
807 
808 output:
809 	/* Output parameters */
810 	memcpy(params, &p, sizeof(*params));
811 	memset(&p, 0, sizeof(p));
812 	rc = 0;
813 cleanup:
814 	kfree(ver_ptr);
815 	uclogic_params_cleanup(&p);
816 	return rc;
817 }
818 
819 /**
820  * uclogic_params_init() - initialize a tablet interface and discover its
821  * parameters.
822  *
823  * @params:	Parameters to fill in (to be cleaned with
824  *		uclogic_params_cleanup()). Not modified in case of error.
825  *		Cannot be NULL.
826  * @hdev:	The HID device of the tablet interface to initialize and get
827  *		parameters from. Cannot be NULL. Must be using the USB low-level
828  *		driver, i.e. be an actual USB tablet.
829  *
830  * Returns:
831  *	Zero, if successful. A negative errno code on error.
832  */
833 int uclogic_params_init(struct uclogic_params *params,
834 			struct hid_device *hdev)
835 {
836 	int rc;
837 	struct usb_device *udev = hid_to_usb_dev(hdev);
838 	__u8  bNumInterfaces = udev->config->desc.bNumInterfaces;
839 	struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
840 	__u8 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
841 	bool found;
842 	/* The resulting parameters (noop) */
843 	struct uclogic_params p = {0, };
844 
845 	/* Check arguments */
846 	if (params == NULL || hdev == NULL ||
847 	    !hid_is_using_ll_driver(hdev, &usb_hid_driver)) {
848 		rc = -EINVAL;
849 		goto cleanup;
850 	}
851 
852 	/*
853 	 * Set replacement report descriptor if the original matches the
854 	 * specified size. Otherwise keep interface unchanged.
855 	 */
856 #define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \
857 	uclogic_params_init_with_opt_desc(                  \
858 		&p, hdev,                                   \
859 		UCLOGIC_RDESC_##_orig_desc_token##_SIZE,    \
860 		uclogic_rdesc_##_new_desc_token##_arr,      \
861 		uclogic_rdesc_##_new_desc_token##_size)
862 
863 #define VID_PID(_vid, _pid) \
864 	(((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX))
865 
866 	/*
867 	 * Handle specific interfaces for specific tablets.
868 	 *
869 	 * Observe the following logic:
870 	 *
871 	 * If the interface is recognized as producing certain useful input:
872 	 *	Mark interface as valid.
873 	 *	Output interface parameters.
874 	 * Else, if the interface is recognized as *not* producing any useful
875 	 * input:
876 	 *	Mark interface as invalid.
877 	 * Else:
878 	 *	Mark interface as valid.
879 	 *	Output noop parameters.
880 	 *
881 	 * Rule of thumb: it is better to disable a broken interface than let
882 	 *		  it spew garbage input.
883 	 */
884 
885 	switch (VID_PID(hdev->vendor, hdev->product)) {
886 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
887 		     USB_DEVICE_ID_UCLOGIC_TABLET_PF1209):
888 		rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed);
889 		if (rc != 0)
890 			goto cleanup;
891 		break;
892 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
893 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U):
894 		rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed);
895 		if (rc != 0)
896 			goto cleanup;
897 		break;
898 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
899 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U):
900 		if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) {
901 			if (bInterfaceNumber == 0) {
902 				/* Try to probe v1 pen parameters */
903 				rc = uclogic_params_pen_init_v1(&p.pen,
904 								&found, hdev);
905 				if (rc != 0) {
906 					hid_err(hdev,
907 						"pen probing failed: %d\n",
908 						rc);
909 					goto cleanup;
910 				}
911 				if (!found) {
912 					hid_warn(hdev,
913 						 "pen parameters not found");
914 				}
915 			} else {
916 				uclogic_params_init_invalid(&p);
917 			}
918 		} else {
919 			rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed);
920 			if (rc != 0)
921 				goto cleanup;
922 		}
923 		break;
924 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
925 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U):
926 		rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed);
927 		if (rc != 0)
928 			goto cleanup;
929 		break;
930 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
931 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP1062):
932 		rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed);
933 		if (rc != 0)
934 			goto cleanup;
935 		break;
936 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
937 		     USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850):
938 		switch (bInterfaceNumber) {
939 		case 0:
940 			rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0);
941 			if (rc != 0)
942 				goto cleanup;
943 			break;
944 		case 1:
945 			rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1);
946 			if (rc != 0)
947 				goto cleanup;
948 			break;
949 		case 2:
950 			rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2);
951 			if (rc != 0)
952 				goto cleanup;
953 			break;
954 		}
955 		break;
956 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
957 		     USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60):
958 		/*
959 		 * If it is not a three-interface version, which is known to
960 		 * respond to initialization.
961 		 */
962 		if (bNumInterfaces != 3) {
963 			switch (bInterfaceNumber) {
964 			case 0:
965 				rc = WITH_OPT_DESC(TWHA60_ORIG0,
966 							twha60_fixed0);
967 				if (rc != 0)
968 					goto cleanup;
969 				break;
970 			case 1:
971 				rc = WITH_OPT_DESC(TWHA60_ORIG1,
972 							twha60_fixed1);
973 				if (rc != 0)
974 					goto cleanup;
975 				break;
976 			}
977 			break;
978 		}
979 		fallthrough;
980 	case VID_PID(USB_VENDOR_ID_HUION,
981 		     USB_DEVICE_ID_HUION_TABLET):
982 	case VID_PID(USB_VENDOR_ID_HUION,
983 		     USB_DEVICE_ID_HUION_HS64):
984 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
985 		     USB_DEVICE_ID_HUION_TABLET):
986 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
987 		     USB_DEVICE_ID_YIYNOVA_TABLET):
988 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
989 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81):
990 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
991 		     USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3):
992 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
993 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45):
994 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
995 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47):
996 		rc = uclogic_params_huion_init(&p, hdev);
997 		if (rc != 0)
998 			goto cleanup;
999 		break;
1000 	case VID_PID(USB_VENDOR_ID_UGTIZER,
1001 		     USB_DEVICE_ID_UGTIZER_TABLET_GP0610):
1002 	case VID_PID(USB_VENDOR_ID_UGTIZER,
1003 		     USB_DEVICE_ID_UGTIZER_TABLET_GT5040):
1004 	case VID_PID(USB_VENDOR_ID_UGEE,
1005 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
1006 	case VID_PID(USB_VENDOR_ID_UGEE,
1007 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640):
1008 	case VID_PID(USB_VENDOR_ID_UGEE,
1009 		     USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720):
1010 		/* If this is the pen interface */
1011 		if (bInterfaceNumber == 1) {
1012 			/* Probe v1 pen parameters */
1013 			rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1014 			if (rc != 0) {
1015 				hid_err(hdev, "pen probing failed: %d\n", rc);
1016 				goto cleanup;
1017 			}
1018 			if (!found) {
1019 				hid_warn(hdev, "pen parameters not found");
1020 				uclogic_params_init_invalid(&p);
1021 			}
1022 		} else {
1023 			/* TODO: Consider marking the interface invalid */
1024 			uclogic_params_init_with_pen_unused(&p);
1025 		}
1026 		break;
1027 	case VID_PID(USB_VENDOR_ID_UGEE,
1028 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01):
1029 		/* If this is the pen and frame interface */
1030 		if (bInterfaceNumber == 1) {
1031 			/* Probe v1 pen parameters */
1032 			rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1033 			if (rc != 0) {
1034 				hid_err(hdev, "pen probing failed: %d\n", rc);
1035 				goto cleanup;
1036 			}
1037 			/* Initialize frame parameters */
1038 			rc = uclogic_params_frame_init_with_desc(
1039 				&p.frame,
1040 				uclogic_rdesc_xppen_deco01_frame_arr,
1041 				uclogic_rdesc_xppen_deco01_frame_size,
1042 				0);
1043 			if (rc != 0)
1044 				goto cleanup;
1045 		} else {
1046 			/* TODO: Consider marking the interface invalid */
1047 			uclogic_params_init_with_pen_unused(&p);
1048 		}
1049 		break;
1050 	case VID_PID(USB_VENDOR_ID_TRUST,
1051 		     USB_DEVICE_ID_TRUST_PANORA_TABLET):
1052 	case VID_PID(USB_VENDOR_ID_UGEE,
1053 		     USB_DEVICE_ID_UGEE_TABLET_G5):
1054 		/* Ignore non-pen interfaces */
1055 		if (bInterfaceNumber != 1) {
1056 			uclogic_params_init_invalid(&p);
1057 			break;
1058 		}
1059 
1060 		rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1061 		if (rc != 0) {
1062 			hid_err(hdev, "pen probing failed: %d\n", rc);
1063 			goto cleanup;
1064 		} else if (found) {
1065 			rc = uclogic_params_frame_init_with_desc(
1066 				&p.frame,
1067 				uclogic_rdesc_ugee_g5_frame_arr,
1068 				uclogic_rdesc_ugee_g5_frame_size,
1069 				UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
1070 			if (rc != 0) {
1071 				hid_err(hdev,
1072 					"failed creating buttonpad parameters: %d\n",
1073 					rc);
1074 				goto cleanup;
1075 			}
1076 			p.frame.re_lsb =
1077 				UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
1078 			p.frame.dev_id_byte =
1079 				UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
1080 		} else {
1081 			hid_warn(hdev, "pen parameters not found");
1082 			uclogic_params_init_invalid(&p);
1083 		}
1084 
1085 		break;
1086 	case VID_PID(USB_VENDOR_ID_UGEE,
1087 		     USB_DEVICE_ID_UGEE_TABLET_EX07S):
1088 		/* Ignore non-pen interfaces */
1089 		if (bInterfaceNumber != 1) {
1090 			uclogic_params_init_invalid(&p);
1091 			break;
1092 		}
1093 
1094 		rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1095 		if (rc != 0) {
1096 			hid_err(hdev, "pen probing failed: %d\n", rc);
1097 			goto cleanup;
1098 		} else if (found) {
1099 			rc = uclogic_params_frame_init_with_desc(
1100 				&p.frame,
1101 				uclogic_rdesc_ugee_ex07_buttonpad_arr,
1102 				uclogic_rdesc_ugee_ex07_buttonpad_size,
1103 				0);
1104 			if (rc != 0) {
1105 				hid_err(hdev,
1106 					"failed creating buttonpad parameters: %d\n",
1107 					rc);
1108 				goto cleanup;
1109 			}
1110 		} else {
1111 			hid_warn(hdev, "pen parameters not found");
1112 			uclogic_params_init_invalid(&p);
1113 		}
1114 
1115 		break;
1116 	}
1117 
1118 #undef VID_PID
1119 #undef WITH_OPT_DESC
1120 
1121 	/* Output parameters */
1122 	memcpy(params, &p, sizeof(*params));
1123 	memset(&p, 0, sizeof(p));
1124 	rc = 0;
1125 cleanup:
1126 	uclogic_params_cleanup(&p);
1127 	return rc;
1128 }
1129