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