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