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 <linux/string.h>
22 #include <asm/unaligned.h>
23 
24 /**
25  * uclogic_params_pen_inrange_to_str() - Convert a pen in-range reporting type
26  *                                       to a string.
27  * @inrange:	The in-range reporting type to convert.
28  *
29  * Return:
30  * * The string representing the type, or
31  * * %NULL if the type is unknown.
32  */
uclogic_params_pen_inrange_to_str(enum uclogic_params_pen_inrange inrange)33 static const char *uclogic_params_pen_inrange_to_str(
34 				enum uclogic_params_pen_inrange inrange)
35 {
36 	switch (inrange) {
37 	case UCLOGIC_PARAMS_PEN_INRANGE_NORMAL:
38 		return "normal";
39 	case UCLOGIC_PARAMS_PEN_INRANGE_INVERTED:
40 		return "inverted";
41 	case UCLOGIC_PARAMS_PEN_INRANGE_NONE:
42 		return "none";
43 	default:
44 		return NULL;
45 	}
46 }
47 
48 /**
49  * uclogic_params_pen_hid_dbg() - Dump tablet interface pen parameters
50  * @hdev:	The HID device the pen parameters describe.
51  * @pen:	The pen parameters to dump.
52  *
53  * Dump tablet interface pen parameters with hid_dbg(). The dump is indented
54  * with a tab.
55  */
uclogic_params_pen_hid_dbg(const struct hid_device * hdev,const struct uclogic_params_pen * pen)56 static void uclogic_params_pen_hid_dbg(const struct hid_device *hdev,
57 					const struct uclogic_params_pen *pen)
58 {
59 	size_t i;
60 
61 	hid_dbg(hdev, "\t.usage_invalid = %s\n",
62 		(pen->usage_invalid ? "true" : "false"));
63 	hid_dbg(hdev, "\t.desc_ptr = %p\n", pen->desc_ptr);
64 	hid_dbg(hdev, "\t.desc_size = %u\n", pen->desc_size);
65 	hid_dbg(hdev, "\t.id = %u\n", pen->id);
66 	hid_dbg(hdev, "\t.subreport_list = {\n");
67 	for (i = 0; i < ARRAY_SIZE(pen->subreport_list); i++) {
68 		hid_dbg(hdev, "\t\t{0x%02hhx, %hhu}%s\n",
69 			pen->subreport_list[i].value,
70 			pen->subreport_list[i].id,
71 			i < (ARRAY_SIZE(pen->subreport_list) - 1) ? "," : "");
72 	}
73 	hid_dbg(hdev, "\t}\n");
74 	hid_dbg(hdev, "\t.inrange = %s\n",
75 		uclogic_params_pen_inrange_to_str(pen->inrange));
76 	hid_dbg(hdev, "\t.fragmented_hires = %s\n",
77 		(pen->fragmented_hires ? "true" : "false"));
78 	hid_dbg(hdev, "\t.tilt_y_flipped = %s\n",
79 		(pen->tilt_y_flipped ? "true" : "false"));
80 }
81 
82 /**
83  * uclogic_params_frame_hid_dbg() - Dump tablet interface frame parameters
84  * @hdev:	The HID device the pen parameters describe.
85  * @frame:	The frame parameters to dump.
86  *
87  * Dump tablet interface frame parameters with hid_dbg(). The dump is
88  * indented with two tabs.
89  */
uclogic_params_frame_hid_dbg(const struct hid_device * hdev,const struct uclogic_params_frame * frame)90 static void uclogic_params_frame_hid_dbg(
91 				const struct hid_device *hdev,
92 				const struct uclogic_params_frame *frame)
93 {
94 	hid_dbg(hdev, "\t\t.desc_ptr = %p\n", frame->desc_ptr);
95 	hid_dbg(hdev, "\t\t.desc_size = %u\n", frame->desc_size);
96 	hid_dbg(hdev, "\t\t.id = %u\n", frame->id);
97 	hid_dbg(hdev, "\t\t.suffix = %s\n", frame->suffix);
98 	hid_dbg(hdev, "\t\t.re_lsb = %u\n", frame->re_lsb);
99 	hid_dbg(hdev, "\t\t.dev_id_byte = %u\n", frame->dev_id_byte);
100 	hid_dbg(hdev, "\t\t.touch_byte = %u\n", frame->touch_byte);
101 	hid_dbg(hdev, "\t\t.touch_max = %hhd\n", frame->touch_max);
102 	hid_dbg(hdev, "\t\t.touch_flip_at = %hhd\n",
103 		frame->touch_flip_at);
104 	hid_dbg(hdev, "\t\t.bitmap_dial_byte = %u\n",
105 		frame->bitmap_dial_byte);
106 }
107 
108 /**
109  * uclogic_params_hid_dbg() - Dump tablet interface parameters
110  * @hdev:	The HID device the parameters describe.
111  * @params:	The parameters to dump.
112  *
113  * Dump tablet interface parameters with hid_dbg().
114  */
uclogic_params_hid_dbg(const struct hid_device * hdev,const struct uclogic_params * params)115 void uclogic_params_hid_dbg(const struct hid_device *hdev,
116 				const struct uclogic_params *params)
117 {
118 	size_t i;
119 
120 	hid_dbg(hdev, ".invalid = %s\n",
121 		params->invalid ? "true" : "false");
122 	hid_dbg(hdev, ".desc_ptr = %p\n", params->desc_ptr);
123 	hid_dbg(hdev, ".desc_size = %u\n", params->desc_size);
124 	hid_dbg(hdev, ".pen = {\n");
125 	uclogic_params_pen_hid_dbg(hdev, &params->pen);
126 	hid_dbg(hdev, "\t}\n");
127 	hid_dbg(hdev, ".frame_list = {\n");
128 	for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) {
129 		hid_dbg(hdev, "\t{\n");
130 		uclogic_params_frame_hid_dbg(hdev, &params->frame_list[i]);
131 		hid_dbg(hdev, "\t}%s\n",
132 			i < (ARRAY_SIZE(params->frame_list) - 1) ? "," : "");
133 	}
134 	hid_dbg(hdev, "}\n");
135 }
136 
137 /**
138  * uclogic_params_get_str_desc - retrieve a string descriptor from a HID
139  * device interface, putting it into a kmalloc-allocated buffer as is, without
140  * character encoding conversion.
141  *
142  * @pbuf:	Location for the kmalloc-allocated buffer pointer containing
143  *		the retrieved descriptor. Not modified in case of error.
144  *		Can be NULL to have retrieved descriptor discarded.
145  * @hdev:	The HID device of the tablet interface to retrieve the string
146  *		descriptor from. Cannot be NULL.
147  * @idx:	Index of the string descriptor to request from the device.
148  * @len:	Length of the buffer to allocate and the data to retrieve.
149  *
150  * Returns:
151  *	number of bytes retrieved (<= len),
152  *	-EPIPE, if the descriptor was not found, or
153  *	another negative errno code in case of other error.
154  */
uclogic_params_get_str_desc(__u8 ** pbuf,struct hid_device * hdev,__u8 idx,size_t len)155 static int uclogic_params_get_str_desc(__u8 **pbuf, struct hid_device *hdev,
156 					__u8 idx, size_t len)
157 {
158 	int rc;
159 	struct usb_device *udev;
160 	__u8 *buf = NULL;
161 
162 	/* Check arguments */
163 	if (hdev == NULL) {
164 		rc = -EINVAL;
165 		goto cleanup;
166 	}
167 
168 	udev = hid_to_usb_dev(hdev);
169 
170 	buf = kmalloc(len, GFP_KERNEL);
171 	if (buf == NULL) {
172 		rc = -ENOMEM;
173 		goto cleanup;
174 	}
175 
176 	rc = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
177 				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
178 				(USB_DT_STRING << 8) + idx,
179 				0x0409, buf, len,
180 				USB_CTRL_GET_TIMEOUT);
181 	if (rc == -EPIPE) {
182 		hid_dbg(hdev, "string descriptor #%hhu not found\n", idx);
183 		goto cleanup;
184 	} else if (rc < 0) {
185 		hid_err(hdev,
186 			"failed retrieving string descriptor #%u: %d\n",
187 			idx, rc);
188 		goto cleanup;
189 	}
190 
191 	if (pbuf != NULL) {
192 		*pbuf = buf;
193 		buf = NULL;
194 	}
195 
196 cleanup:
197 	kfree(buf);
198 	return rc;
199 }
200 
201 /**
202  * uclogic_params_pen_cleanup - free resources used by struct
203  * uclogic_params_pen (tablet interface's pen input parameters).
204  * Can be called repeatedly.
205  *
206  * @pen:	Pen input parameters to cleanup. Cannot be NULL.
207  */
uclogic_params_pen_cleanup(struct uclogic_params_pen * pen)208 static void uclogic_params_pen_cleanup(struct uclogic_params_pen *pen)
209 {
210 	kfree(pen->desc_ptr);
211 	memset(pen, 0, sizeof(*pen));
212 }
213 
214 /**
215  * uclogic_params_pen_init_v1() - initialize tablet interface pen
216  * input and retrieve its parameters from the device, using v1 protocol.
217  *
218  * @pen:	Pointer to the pen parameters to initialize (to be
219  *		cleaned up with uclogic_params_pen_cleanup()). Not modified in
220  *		case of error, or if parameters are not found. Cannot be NULL.
221  * @pfound:	Location for a flag which is set to true if the parameters
222  *		were found, and to false if not (e.g. device was
223  *		incompatible). Not modified in case of error. Cannot be NULL.
224  * @hdev:	The HID device of the tablet interface to initialize and get
225  *		parameters from. Cannot be NULL.
226  *
227  * Returns:
228  *	Zero, if successful. A negative errno code on error.
229  */
uclogic_params_pen_init_v1(struct uclogic_params_pen * pen,bool * pfound,struct hid_device * hdev)230 static int uclogic_params_pen_init_v1(struct uclogic_params_pen *pen,
231 				      bool *pfound,
232 				      struct hid_device *hdev)
233 {
234 	int rc;
235 	bool found = false;
236 	/* Buffer for (part of) the string descriptor */
237 	__u8 *buf = NULL;
238 	/* Minimum descriptor length required, maximum seen so far is 18 */
239 	const int len = 12;
240 	s32 resolution;
241 	/* Pen report descriptor template parameters */
242 	s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
243 	__u8 *desc_ptr = NULL;
244 
245 	/* Check arguments */
246 	if (pen == NULL || pfound == NULL || hdev == NULL) {
247 		rc = -EINVAL;
248 		goto cleanup;
249 	}
250 
251 	/*
252 	 * Read string descriptor containing pen input parameters.
253 	 * The specific string descriptor and data were discovered by sniffing
254 	 * the Windows driver traffic.
255 	 * NOTE: This enables fully-functional tablet mode.
256 	 */
257 	rc = uclogic_params_get_str_desc(&buf, hdev, 100, len);
258 	if (rc == -EPIPE) {
259 		hid_dbg(hdev,
260 			"string descriptor with pen parameters not found, assuming not compatible\n");
261 		goto finish;
262 	} else if (rc < 0) {
263 		hid_err(hdev, "failed retrieving pen parameters: %d\n", rc);
264 		goto cleanup;
265 	} else if (rc != len) {
266 		hid_dbg(hdev,
267 			"string descriptor with pen parameters has invalid length (got %d, expected %d), assuming not compatible\n",
268 			rc, len);
269 		goto finish;
270 	}
271 
272 	/*
273 	 * Fill report descriptor parameters from the string descriptor
274 	 */
275 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] =
276 		get_unaligned_le16(buf + 2);
277 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] =
278 		get_unaligned_le16(buf + 4);
279 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] =
280 		get_unaligned_le16(buf + 8);
281 	resolution = get_unaligned_le16(buf + 10);
282 	if (resolution == 0) {
283 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0;
284 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0;
285 	} else {
286 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] =
287 			desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 /
288 			resolution;
289 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] =
290 			desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 /
291 			resolution;
292 	}
293 	kfree(buf);
294 	buf = NULL;
295 
296 	/*
297 	 * Generate pen report descriptor
298 	 */
299 	desc_ptr = uclogic_rdesc_template_apply(
300 				uclogic_rdesc_v1_pen_template_arr,
301 				uclogic_rdesc_v1_pen_template_size,
302 				desc_params, ARRAY_SIZE(desc_params));
303 	if (desc_ptr == NULL) {
304 		rc = -ENOMEM;
305 		goto cleanup;
306 	}
307 
308 	/*
309 	 * Fill-in the parameters
310 	 */
311 	memset(pen, 0, sizeof(*pen));
312 	pen->desc_ptr = desc_ptr;
313 	desc_ptr = NULL;
314 	pen->desc_size = uclogic_rdesc_v1_pen_template_size;
315 	pen->id = UCLOGIC_RDESC_V1_PEN_ID;
316 	pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_INVERTED;
317 	found = true;
318 finish:
319 	*pfound = found;
320 	rc = 0;
321 cleanup:
322 	kfree(desc_ptr);
323 	kfree(buf);
324 	return rc;
325 }
326 
327 /**
328  * uclogic_params_get_le24() - get a 24-bit little-endian number from a
329  * buffer.
330  *
331  * @p:	The pointer to the number buffer.
332  *
333  * Returns:
334  *	The retrieved number
335  */
uclogic_params_get_le24(const void * p)336 static s32 uclogic_params_get_le24(const void *p)
337 {
338 	const __u8 *b = p;
339 	return b[0] | (b[1] << 8UL) | (b[2] << 16UL);
340 }
341 
342 /**
343  * uclogic_params_pen_init_v2() - initialize tablet interface pen
344  * input and retrieve its parameters from the device, using v2 protocol.
345  *
346  * @pen:		Pointer to the pen parameters to initialize (to be
347  *			cleaned up with uclogic_params_pen_cleanup()). Not
348  *			modified in case of error, or if parameters are not
349  *			found. Cannot be NULL.
350  * @pfound:		Location for a flag which is set to true if the
351  *			parameters were found, and to false if not (e.g.
352  *			device was incompatible). Not modified in case of
353  *			error. Cannot be NULL.
354  * @pparams_ptr:	Location for a kmalloc'ed pointer to the retrieved raw
355  *			parameters, which could be used to identify the tablet
356  *			to some extent. Should be freed with kfree after use.
357  *			NULL, if not needed. Not modified in case of error.
358  *			Only set if *pfound is set to true.
359  * @pparams_len:	Location for the length of the retrieved raw
360  *			parameters. NULL, if not needed. Not modified in case
361  *			of error. Only set if *pfound is set to true.
362  * @hdev:		The HID device of the tablet interface to initialize
363  *			and get parameters from. Cannot be NULL.
364  *
365  * Returns:
366  *	Zero, if successful. A negative errno code on error.
367  */
uclogic_params_pen_init_v2(struct uclogic_params_pen * pen,bool * pfound,__u8 ** pparams_ptr,size_t * pparams_len,struct hid_device * hdev)368 static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen,
369 					bool *pfound,
370 					__u8 **pparams_ptr,
371 					size_t *pparams_len,
372 					struct hid_device *hdev)
373 {
374 	int rc;
375 	bool found = false;
376 	/* Buffer for (part of) the parameter string descriptor */
377 	__u8 *buf = NULL;
378 	/* Parameter string descriptor required length */
379 	const int params_len_min = 18;
380 	/* Parameter string descriptor accepted length */
381 	const int params_len_max = 32;
382 	/* Parameter string descriptor received length */
383 	int params_len;
384 	size_t i;
385 	s32 resolution;
386 	/* Pen report descriptor template parameters */
387 	s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
388 	__u8 *desc_ptr = NULL;
389 
390 	/* Check arguments */
391 	if (pen == NULL || pfound == NULL || hdev == NULL) {
392 		rc = -EINVAL;
393 		goto cleanup;
394 	}
395 
396 	/*
397 	 * Read string descriptor containing pen input parameters.
398 	 * The specific string descriptor and data were discovered by sniffing
399 	 * the Windows driver traffic.
400 	 * NOTE: This enables fully-functional tablet mode.
401 	 */
402 	rc = uclogic_params_get_str_desc(&buf, hdev, 200, params_len_max);
403 	if (rc == -EPIPE) {
404 		hid_dbg(hdev,
405 			"string descriptor with pen parameters not found, assuming not compatible\n");
406 		goto finish;
407 	} else if (rc < 0) {
408 		hid_err(hdev, "failed retrieving pen parameters: %d\n", rc);
409 		goto cleanup;
410 	} else if (rc < params_len_min) {
411 		hid_dbg(hdev,
412 			"string descriptor with pen parameters is too short (got %d, expected at least %d), assuming not compatible\n",
413 			rc, params_len_min);
414 		goto finish;
415 	}
416 
417 	params_len = rc;
418 
419 	/*
420 	 * Check it's not just a catch-all UTF-16LE-encoded ASCII
421 	 * string (such as the model name) some tablets put into all
422 	 * unknown string descriptors.
423 	 */
424 	for (i = 2;
425 	     i < params_len &&
426 		(buf[i] >= 0x20 && buf[i] < 0x7f && buf[i + 1] == 0);
427 	     i += 2);
428 	if (i >= params_len) {
429 		hid_dbg(hdev,
430 			"string descriptor with pen parameters seems to contain only text, assuming not compatible\n");
431 		goto finish;
432 	}
433 
434 	/*
435 	 * Fill report descriptor parameters from the string descriptor
436 	 */
437 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] =
438 		uclogic_params_get_le24(buf + 2);
439 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] =
440 		uclogic_params_get_le24(buf + 5);
441 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] =
442 		get_unaligned_le16(buf + 8);
443 	resolution = get_unaligned_le16(buf + 10);
444 	if (resolution == 0) {
445 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0;
446 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0;
447 	} else {
448 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] =
449 			desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 /
450 			resolution;
451 		desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] =
452 			desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 /
453 			resolution;
454 	}
455 
456 	/*
457 	 * Generate pen report descriptor
458 	 */
459 	desc_ptr = uclogic_rdesc_template_apply(
460 				uclogic_rdesc_v2_pen_template_arr,
461 				uclogic_rdesc_v2_pen_template_size,
462 				desc_params, ARRAY_SIZE(desc_params));
463 	if (desc_ptr == NULL) {
464 		rc = -ENOMEM;
465 		goto cleanup;
466 	}
467 
468 	/*
469 	 * Fill-in the parameters
470 	 */
471 	memset(pen, 0, sizeof(*pen));
472 	pen->desc_ptr = desc_ptr;
473 	desc_ptr = NULL;
474 	pen->desc_size = uclogic_rdesc_v2_pen_template_size;
475 	pen->id = UCLOGIC_RDESC_V2_PEN_ID;
476 	pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_NONE;
477 	pen->fragmented_hires = true;
478 	pen->tilt_y_flipped = true;
479 	found = true;
480 	if (pparams_ptr != NULL) {
481 		*pparams_ptr = buf;
482 		buf = NULL;
483 	}
484 	if (pparams_len != NULL)
485 		*pparams_len = params_len;
486 
487 finish:
488 	*pfound = found;
489 	rc = 0;
490 cleanup:
491 	kfree(desc_ptr);
492 	kfree(buf);
493 	return rc;
494 }
495 
496 /**
497  * uclogic_params_frame_cleanup - free resources used by struct
498  * uclogic_params_frame (tablet interface's frame controls input parameters).
499  * Can be called repeatedly.
500  *
501  * @frame:	Frame controls input parameters to cleanup. Cannot be NULL.
502  */
uclogic_params_frame_cleanup(struct uclogic_params_frame * frame)503 static void uclogic_params_frame_cleanup(struct uclogic_params_frame *frame)
504 {
505 	kfree(frame->desc_ptr);
506 	memset(frame, 0, sizeof(*frame));
507 }
508 
509 /**
510  * uclogic_params_frame_init_with_desc() - initialize tablet's frame control
511  * parameters with a static report descriptor.
512  *
513  * @frame:	Pointer to the frame parameters to initialize (to be cleaned
514  *		up with uclogic_params_frame_cleanup()). Not modified in case
515  *		of error. Cannot be NULL.
516  * @desc_ptr:	Report descriptor pointer. Can be NULL, if desc_size is zero.
517  * @desc_size:	Report descriptor size.
518  * @id:		Report ID used for frame reports, if they should be tweaked,
519  *		zero if not.
520  *
521  * Returns:
522  *	Zero, if successful. A negative errno code on error.
523  */
uclogic_params_frame_init_with_desc(struct uclogic_params_frame * frame,const __u8 * desc_ptr,size_t desc_size,unsigned int id)524 static int uclogic_params_frame_init_with_desc(
525 					struct uclogic_params_frame *frame,
526 					const __u8 *desc_ptr,
527 					size_t desc_size,
528 					unsigned int id)
529 {
530 	__u8 *copy_desc_ptr;
531 
532 	if (frame == NULL || (desc_ptr == NULL && desc_size != 0))
533 		return -EINVAL;
534 
535 	copy_desc_ptr = kmemdup(desc_ptr, desc_size, GFP_KERNEL);
536 	if (copy_desc_ptr == NULL)
537 		return -ENOMEM;
538 
539 	memset(frame, 0, sizeof(*frame));
540 	frame->desc_ptr = copy_desc_ptr;
541 	frame->desc_size = desc_size;
542 	frame->id = id;
543 	return 0;
544 }
545 
546 /**
547  * uclogic_params_frame_init_v1() - initialize v1 tablet interface frame
548  * controls.
549  *
550  * @frame:	Pointer to the frame parameters to initialize (to be cleaned
551  *		up with uclogic_params_frame_cleanup()). Not modified in case
552  *		of error, or if parameters are not found. Cannot be NULL.
553  * @pfound:	Location for a flag which is set to true if the parameters
554  *		were found, and to false if not (e.g. device was
555  *		incompatible). Not modified in case of error. Cannot be NULL.
556  * @hdev:	The HID device of the tablet interface to initialize and get
557  *		parameters from. Cannot be NULL.
558  *
559  * Returns:
560  *	Zero, if successful. A negative errno code on error.
561  */
uclogic_params_frame_init_v1(struct uclogic_params_frame * frame,bool * pfound,struct hid_device * hdev)562 static int uclogic_params_frame_init_v1(struct uclogic_params_frame *frame,
563 					bool *pfound,
564 					struct hid_device *hdev)
565 {
566 	int rc;
567 	bool found = false;
568 	struct usb_device *usb_dev;
569 	char *str_buf = NULL;
570 	const size_t str_len = 16;
571 
572 	/* Check arguments */
573 	if (frame == NULL || pfound == NULL || hdev == NULL) {
574 		rc = -EINVAL;
575 		goto cleanup;
576 	}
577 
578 	usb_dev = hid_to_usb_dev(hdev);
579 
580 	/*
581 	 * Enable generic button mode
582 	 */
583 	str_buf = kzalloc(str_len, GFP_KERNEL);
584 	if (str_buf == NULL) {
585 		rc = -ENOMEM;
586 		goto cleanup;
587 	}
588 
589 	rc = usb_string(usb_dev, 123, str_buf, str_len);
590 	if (rc == -EPIPE) {
591 		hid_dbg(hdev,
592 			"generic button -enabling string descriptor not found\n");
593 	} else if (rc < 0) {
594 		goto cleanup;
595 	} else if (strncmp(str_buf, "HK On", rc) != 0) {
596 		hid_dbg(hdev,
597 			"invalid response to enabling generic buttons: \"%s\"\n",
598 			str_buf);
599 	} else {
600 		hid_dbg(hdev, "generic buttons enabled\n");
601 		rc = uclogic_params_frame_init_with_desc(
602 				frame,
603 				uclogic_rdesc_v1_frame_arr,
604 				uclogic_rdesc_v1_frame_size,
605 				UCLOGIC_RDESC_V1_FRAME_ID);
606 		if (rc != 0)
607 			goto cleanup;
608 		found = true;
609 	}
610 
611 	*pfound = found;
612 	rc = 0;
613 cleanup:
614 	kfree(str_buf);
615 	return rc;
616 }
617 
618 /**
619  * uclogic_params_cleanup_event_hooks - free resources used by the list of raw
620  * event hooks.
621  * Can be called repeatedly.
622  *
623  * @params: Input parameters to cleanup. Cannot be NULL.
624  */
uclogic_params_cleanup_event_hooks(struct uclogic_params * params)625 static void uclogic_params_cleanup_event_hooks(struct uclogic_params *params)
626 {
627 	struct uclogic_raw_event_hook *curr, *n;
628 
629 	if (!params || !params->event_hooks)
630 		return;
631 
632 	list_for_each_entry_safe(curr, n, &params->event_hooks->list, list) {
633 		cancel_work_sync(&curr->work);
634 		list_del(&curr->list);
635 		kfree(curr->event);
636 		kfree(curr);
637 	}
638 
639 	kfree(params->event_hooks);
640 	params->event_hooks = NULL;
641 }
642 
643 /**
644  * uclogic_params_cleanup - free resources used by struct uclogic_params
645  * (tablet interface's parameters).
646  * Can be called repeatedly.
647  *
648  * @params:	Input parameters to cleanup. Cannot be NULL.
649  */
uclogic_params_cleanup(struct uclogic_params * params)650 void uclogic_params_cleanup(struct uclogic_params *params)
651 {
652 	if (!params->invalid) {
653 		size_t i;
654 		kfree(params->desc_ptr);
655 		uclogic_params_pen_cleanup(&params->pen);
656 		for (i = 0; i < ARRAY_SIZE(params->frame_list); i++)
657 			uclogic_params_frame_cleanup(&params->frame_list[i]);
658 
659 		uclogic_params_cleanup_event_hooks(params);
660 		memset(params, 0, sizeof(*params));
661 	}
662 }
663 
664 /**
665  * uclogic_params_get_desc() - Get a replacement report descriptor for a
666  *                             tablet's interface.
667  *
668  * @params:	The parameters of a tablet interface to get report
669  *		descriptor for. Cannot be NULL.
670  * @pdesc:	Location for the resulting, kmalloc-allocated report
671  *		descriptor pointer, or for NULL, if there's no replacement
672  *		report descriptor. Not modified in case of error. Cannot be
673  *		NULL.
674  * @psize:	Location for the resulting report descriptor size, not set if
675  *		there's no replacement report descriptor. Not modified in case
676  *		of error. Cannot be NULL.
677  *
678  * Returns:
679  *	Zero, if successful.
680  *	-EINVAL, if invalid arguments are supplied.
681  *	-ENOMEM, if failed to allocate memory.
682  */
uclogic_params_get_desc(const struct uclogic_params * params,__u8 ** pdesc,unsigned int * psize)683 int uclogic_params_get_desc(const struct uclogic_params *params,
684 				__u8 **pdesc,
685 				unsigned int *psize)
686 {
687 	int rc = -ENOMEM;
688 	bool present = false;
689 	unsigned int size = 0;
690 	__u8 *desc = NULL;
691 	size_t i;
692 
693 	/* Check arguments */
694 	if (params == NULL || pdesc == NULL || psize == NULL)
695 		return -EINVAL;
696 
697 	/* Concatenate descriptors */
698 #define ADD_DESC(_desc_ptr, _desc_size) \
699 	do {                                                        \
700 		unsigned int new_size;                              \
701 		__u8 *new_desc;                                     \
702 		if ((_desc_ptr) == NULL) {                          \
703 			break;                                      \
704 		}                                                   \
705 		new_size = size + (_desc_size);                     \
706 		new_desc = krealloc(desc, new_size, GFP_KERNEL);    \
707 		if (new_desc == NULL) {                             \
708 			goto cleanup;                               \
709 		}                                                   \
710 		memcpy(new_desc + size, (_desc_ptr), (_desc_size)); \
711 		desc = new_desc;                                    \
712 		size = new_size;                                    \
713 		present = true;                                     \
714 	} while (0)
715 
716 	ADD_DESC(params->desc_ptr, params->desc_size);
717 	ADD_DESC(params->pen.desc_ptr, params->pen.desc_size);
718 	for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) {
719 		ADD_DESC(params->frame_list[i].desc_ptr,
720 				params->frame_list[i].desc_size);
721 	}
722 
723 #undef ADD_DESC
724 
725 	if (present) {
726 		*pdesc = desc;
727 		*psize = size;
728 		desc = NULL;
729 	}
730 	rc = 0;
731 cleanup:
732 	kfree(desc);
733 	return rc;
734 }
735 
736 /**
737  * uclogic_params_init_invalid() - initialize tablet interface parameters,
738  * specifying the interface is invalid.
739  *
740  * @params:		Parameters to initialize (to be cleaned with
741  *			uclogic_params_cleanup()). Cannot be NULL.
742  */
uclogic_params_init_invalid(struct uclogic_params * params)743 static void uclogic_params_init_invalid(struct uclogic_params *params)
744 {
745 	params->invalid = true;
746 }
747 
748 /**
749  * uclogic_params_init_with_opt_desc() - initialize tablet interface
750  * parameters with an optional replacement report descriptor. Only modify
751  * report descriptor, if the original report descriptor matches the expected
752  * size.
753  *
754  * @params:		Parameters to initialize (to be cleaned with
755  *			uclogic_params_cleanup()). Not modified in case of
756  *			error. Cannot be NULL.
757  * @hdev:		The HID device of the tablet interface create the
758  *			parameters for. Cannot be NULL.
759  * @orig_desc_size:	Expected size of the original report descriptor to
760  *			be replaced.
761  * @desc_ptr:		Pointer to the replacement report descriptor.
762  *			Can be NULL, if desc_size is zero.
763  * @desc_size:		Size of the replacement report descriptor.
764  *
765  * Returns:
766  *	Zero, if successful. -EINVAL if an invalid argument was passed.
767  *	-ENOMEM, if failed to allocate memory.
768  */
uclogic_params_init_with_opt_desc(struct uclogic_params * params,struct hid_device * hdev,unsigned int orig_desc_size,__u8 * desc_ptr,unsigned int desc_size)769 static int uclogic_params_init_with_opt_desc(struct uclogic_params *params,
770 					     struct hid_device *hdev,
771 					     unsigned int orig_desc_size,
772 					     __u8 *desc_ptr,
773 					     unsigned int desc_size)
774 {
775 	__u8 *desc_copy_ptr = NULL;
776 	unsigned int desc_copy_size;
777 	int rc;
778 
779 	/* Check arguments */
780 	if (params == NULL || hdev == NULL ||
781 	    (desc_ptr == NULL && desc_size != 0)) {
782 		rc = -EINVAL;
783 		goto cleanup;
784 	}
785 
786 	/* Replace report descriptor, if it matches */
787 	if (hdev->dev_rsize == orig_desc_size) {
788 		hid_dbg(hdev,
789 			"device report descriptor matches the expected size, replacing\n");
790 		desc_copy_ptr = kmemdup(desc_ptr, desc_size, GFP_KERNEL);
791 		if (desc_copy_ptr == NULL) {
792 			rc = -ENOMEM;
793 			goto cleanup;
794 		}
795 		desc_copy_size = desc_size;
796 	} else {
797 		hid_dbg(hdev,
798 			"device report descriptor doesn't match the expected size (%u != %u), preserving\n",
799 			hdev->dev_rsize, orig_desc_size);
800 		desc_copy_ptr = NULL;
801 		desc_copy_size = 0;
802 	}
803 
804 	/* Output parameters */
805 	memset(params, 0, sizeof(*params));
806 	params->desc_ptr = desc_copy_ptr;
807 	desc_copy_ptr = NULL;
808 	params->desc_size = desc_copy_size;
809 
810 	rc = 0;
811 cleanup:
812 	kfree(desc_copy_ptr);
813 	return rc;
814 }
815 
816 /**
817  * uclogic_params_huion_init() - initialize a Huion tablet interface and discover
818  * its parameters.
819  *
820  * @params:	Parameters to fill in (to be cleaned with
821  *		uclogic_params_cleanup()). Not modified in case of error.
822  *		Cannot be NULL.
823  * @hdev:	The HID device of the tablet interface to initialize and get
824  *		parameters from. Cannot be NULL.
825  *
826  * Returns:
827  *	Zero, if successful. A negative errno code on error.
828  */
uclogic_params_huion_init(struct uclogic_params * params,struct hid_device * hdev)829 static int uclogic_params_huion_init(struct uclogic_params *params,
830 				     struct hid_device *hdev)
831 {
832 	int rc;
833 	struct usb_device *udev;
834 	struct usb_interface *iface;
835 	__u8 bInterfaceNumber;
836 	bool found;
837 	/* The resulting parameters (noop) */
838 	struct uclogic_params p = {0, };
839 	static const char transition_ver[] = "HUION_T153_160607";
840 	char *ver_ptr = NULL;
841 	const size_t ver_len = sizeof(transition_ver) + 1;
842 	__u8 *params_ptr = NULL;
843 	size_t params_len = 0;
844 	/* Parameters string descriptor of a model with touch ring (HS610) */
845 	const __u8 touch_ring_model_params_buf[] = {
846 		0x13, 0x03, 0x70, 0xC6, 0x00, 0x06, 0x7C, 0x00,
847 		0xFF, 0x1F, 0xD8, 0x13, 0x03, 0x0D, 0x10, 0x01,
848 		0x04, 0x3C, 0x3E
849 	};
850 
851 	/* Check arguments */
852 	if (params == NULL || hdev == NULL) {
853 		rc = -EINVAL;
854 		goto cleanup;
855 	}
856 
857 	udev = hid_to_usb_dev(hdev);
858 	iface = to_usb_interface(hdev->dev.parent);
859 	bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
860 
861 	/* If it's a custom keyboard interface */
862 	if (bInterfaceNumber == 1) {
863 		/* Keep everything intact, but mark pen usage invalid */
864 		p.pen.usage_invalid = true;
865 		goto output;
866 	/* Else, if it's not a pen interface */
867 	} else if (bInterfaceNumber != 0) {
868 		uclogic_params_init_invalid(&p);
869 		goto output;
870 	}
871 
872 	/* Try to get firmware version */
873 	ver_ptr = kzalloc(ver_len, GFP_KERNEL);
874 	if (ver_ptr == NULL) {
875 		rc = -ENOMEM;
876 		goto cleanup;
877 	}
878 	rc = usb_string(udev, 201, ver_ptr, ver_len);
879 	if (rc == -EPIPE) {
880 		*ver_ptr = '\0';
881 	} else if (rc < 0) {
882 		hid_err(hdev,
883 			"failed retrieving Huion firmware version: %d\n", rc);
884 		goto cleanup;
885 	}
886 
887 	/* If this is a transition firmware */
888 	if (strcmp(ver_ptr, transition_ver) == 0) {
889 		hid_dbg(hdev,
890 			"transition firmware detected, not probing pen v2 parameters\n");
891 	} else {
892 		/* Try to probe v2 pen parameters */
893 		rc = uclogic_params_pen_init_v2(&p.pen, &found,
894 						&params_ptr, &params_len,
895 						hdev);
896 		if (rc != 0) {
897 			hid_err(hdev,
898 				"failed probing pen v2 parameters: %d\n", rc);
899 			goto cleanup;
900 		} else if (found) {
901 			hid_dbg(hdev, "pen v2 parameters found\n");
902 			/* Create v2 frame button parameters */
903 			rc = uclogic_params_frame_init_with_desc(
904 					&p.frame_list[0],
905 					uclogic_rdesc_v2_frame_buttons_arr,
906 					uclogic_rdesc_v2_frame_buttons_size,
907 					UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID);
908 			if (rc != 0) {
909 				hid_err(hdev,
910 					"failed creating v2 frame button parameters: %d\n",
911 					rc);
912 				goto cleanup;
913 			}
914 
915 			/* Link from pen sub-report */
916 			p.pen.subreport_list[0].value = 0xe0;
917 			p.pen.subreport_list[0].id =
918 				UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID;
919 
920 			/* If this is the model with touch ring */
921 			if (params_ptr != NULL &&
922 			    params_len == sizeof(touch_ring_model_params_buf) &&
923 			    memcmp(params_ptr, touch_ring_model_params_buf,
924 				   params_len) == 0) {
925 				/* Create touch ring parameters */
926 				rc = uclogic_params_frame_init_with_desc(
927 					&p.frame_list[1],
928 					uclogic_rdesc_v2_frame_touch_ring_arr,
929 					uclogic_rdesc_v2_frame_touch_ring_size,
930 					UCLOGIC_RDESC_V2_FRAME_TOUCH_ID);
931 				if (rc != 0) {
932 					hid_err(hdev,
933 						"failed creating v2 frame touch ring parameters: %d\n",
934 						rc);
935 					goto cleanup;
936 				}
937 				p.frame_list[1].suffix = "Touch Ring";
938 				p.frame_list[1].dev_id_byte =
939 					UCLOGIC_RDESC_V2_FRAME_TOUCH_DEV_ID_BYTE;
940 				p.frame_list[1].touch_byte = 5;
941 				p.frame_list[1].touch_max = 12;
942 				p.frame_list[1].touch_flip_at = 7;
943 			} else {
944 				/* Create touch strip parameters */
945 				rc = uclogic_params_frame_init_with_desc(
946 					&p.frame_list[1],
947 					uclogic_rdesc_v2_frame_touch_strip_arr,
948 					uclogic_rdesc_v2_frame_touch_strip_size,
949 					UCLOGIC_RDESC_V2_FRAME_TOUCH_ID);
950 				if (rc != 0) {
951 					hid_err(hdev,
952 						"failed creating v2 frame touch strip parameters: %d\n",
953 						rc);
954 					goto cleanup;
955 				}
956 				p.frame_list[1].suffix = "Touch Strip";
957 				p.frame_list[1].dev_id_byte =
958 					UCLOGIC_RDESC_V2_FRAME_TOUCH_DEV_ID_BYTE;
959 				p.frame_list[1].touch_byte = 5;
960 				p.frame_list[1].touch_max = 8;
961 			}
962 
963 			/* Link from pen sub-report */
964 			p.pen.subreport_list[1].value = 0xf0;
965 			p.pen.subreport_list[1].id =
966 				UCLOGIC_RDESC_V2_FRAME_TOUCH_ID;
967 
968 			/* Create v2 frame dial parameters */
969 			rc = uclogic_params_frame_init_with_desc(
970 					&p.frame_list[2],
971 					uclogic_rdesc_v2_frame_dial_arr,
972 					uclogic_rdesc_v2_frame_dial_size,
973 					UCLOGIC_RDESC_V2_FRAME_DIAL_ID);
974 			if (rc != 0) {
975 				hid_err(hdev,
976 					"failed creating v2 frame dial parameters: %d\n",
977 					rc);
978 				goto cleanup;
979 			}
980 			p.frame_list[2].suffix = "Dial";
981 			p.frame_list[2].dev_id_byte =
982 				UCLOGIC_RDESC_V2_FRAME_DIAL_DEV_ID_BYTE;
983 			p.frame_list[2].bitmap_dial_byte = 5;
984 
985 			/* Link from pen sub-report */
986 			p.pen.subreport_list[2].value = 0xf1;
987 			p.pen.subreport_list[2].id =
988 				UCLOGIC_RDESC_V2_FRAME_DIAL_ID;
989 
990 			goto output;
991 		}
992 		hid_dbg(hdev, "pen v2 parameters not found\n");
993 	}
994 
995 	/* Try to probe v1 pen parameters */
996 	rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
997 	if (rc != 0) {
998 		hid_err(hdev,
999 			"failed probing pen v1 parameters: %d\n", rc);
1000 		goto cleanup;
1001 	} else if (found) {
1002 		hid_dbg(hdev, "pen v1 parameters found\n");
1003 		/* Try to probe v1 frame */
1004 		rc = uclogic_params_frame_init_v1(&p.frame_list[0],
1005 						  &found, hdev);
1006 		if (rc != 0) {
1007 			hid_err(hdev, "v1 frame probing failed: %d\n", rc);
1008 			goto cleanup;
1009 		}
1010 		hid_dbg(hdev, "frame v1 parameters%s found\n",
1011 			(found ? "" : " not"));
1012 		if (found) {
1013 			/* Link frame button subreports from pen reports */
1014 			p.pen.subreport_list[0].value = 0xe0;
1015 			p.pen.subreport_list[0].id =
1016 				UCLOGIC_RDESC_V1_FRAME_ID;
1017 		}
1018 		goto output;
1019 	}
1020 	hid_dbg(hdev, "pen v1 parameters not found\n");
1021 
1022 	uclogic_params_init_invalid(&p);
1023 
1024 output:
1025 	/* Output parameters */
1026 	memcpy(params, &p, sizeof(*params));
1027 	memset(&p, 0, sizeof(p));
1028 	rc = 0;
1029 cleanup:
1030 	kfree(params_ptr);
1031 	kfree(ver_ptr);
1032 	uclogic_params_cleanup(&p);
1033 	return rc;
1034 }
1035 
1036 /**
1037  * uclogic_probe_interface() - some tablets, like the Parblo A610 PLUS V2 or
1038  * the XP-PEN Deco Mini 7, need to be initialized by sending them magic data.
1039  *
1040  * @hdev:	The HID device of the tablet interface to initialize and get
1041  *		parameters from. Cannot be NULL.
1042  * @magic_arr:	The magic data that should be sent to probe the interface.
1043  *		Cannot be NULL.
1044  * @magic_size:	Size of the magic data.
1045  * @endpoint:	Endpoint where the magic data should be sent.
1046  *
1047  * Returns:
1048  *	Zero, if successful. A negative errno code on error.
1049  */
uclogic_probe_interface(struct hid_device * hdev,const u8 * magic_arr,size_t magic_size,int endpoint)1050 static int uclogic_probe_interface(struct hid_device *hdev, const u8 *magic_arr,
1051 				   size_t magic_size, int endpoint)
1052 {
1053 	struct usb_device *udev;
1054 	unsigned int pipe = 0;
1055 	int sent;
1056 	u8 *buf = NULL;
1057 	int rc = 0;
1058 
1059 	if (!hdev || !magic_arr) {
1060 		rc = -EINVAL;
1061 		goto cleanup;
1062 	}
1063 
1064 	buf = kmemdup(magic_arr, magic_size, GFP_KERNEL);
1065 	if (!buf) {
1066 		rc = -ENOMEM;
1067 		goto cleanup;
1068 	}
1069 
1070 	udev = hid_to_usb_dev(hdev);
1071 	pipe = usb_sndintpipe(udev, endpoint);
1072 
1073 	rc = usb_interrupt_msg(udev, pipe, buf, magic_size, &sent, 1000);
1074 	if (rc || sent != magic_size) {
1075 		hid_err(hdev, "Interface probing failed: %d\n", rc);
1076 		rc = -1;
1077 		goto cleanup;
1078 	}
1079 
1080 	rc = 0;
1081 cleanup:
1082 	kfree(buf);
1083 	return rc;
1084 }
1085 
1086 /**
1087  * uclogic_params_parse_ugee_v2_desc - parse the string descriptor containing
1088  * pen and frame parameters returned by UGEE v2 devices.
1089  *
1090  * @str_desc:		String descriptor, cannot be NULL.
1091  * @str_desc_size:	Size of the string descriptor.
1092  * @desc_params:	Output description params list.
1093  * @desc_params_size:	Size of the output description params list.
1094  * @frame_type:		Output frame type.
1095  *
1096  * Returns:
1097  *	Zero, if successful. A negative errno code on error.
1098  */
uclogic_params_parse_ugee_v2_desc(const __u8 * str_desc,size_t str_desc_size,s32 * desc_params,size_t desc_params_size,enum uclogic_params_frame_type * frame_type)1099 static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc,
1100 					     size_t str_desc_size,
1101 					     s32 *desc_params,
1102 					     size_t desc_params_size,
1103 					     enum uclogic_params_frame_type *frame_type)
1104 {
1105 	s32 pen_x_lm, pen_y_lm;
1106 	s32 pen_x_pm, pen_y_pm;
1107 	s32 pen_pressure_lm;
1108 	s32 frame_num_buttons;
1109 	s32 resolution;
1110 
1111 	/* Minimum descriptor length required, maximum seen so far is 14 */
1112 	const int min_str_desc_size = 12;
1113 
1114 	if (!str_desc || str_desc_size < min_str_desc_size)
1115 		return -EINVAL;
1116 
1117 	if (desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
1118 		return -EINVAL;
1119 
1120 	pen_x_lm = get_unaligned_le16(str_desc + 2);
1121 	pen_y_lm = get_unaligned_le16(str_desc + 4);
1122 	frame_num_buttons = str_desc[6];
1123 	*frame_type = str_desc[7];
1124 	pen_pressure_lm = get_unaligned_le16(str_desc + 8);
1125 
1126 	resolution = get_unaligned_le16(str_desc + 10);
1127 	if (resolution == 0) {
1128 		pen_x_pm = 0;
1129 		pen_y_pm = 0;
1130 	} else {
1131 		pen_x_pm = pen_x_lm * 1000 / resolution;
1132 		pen_y_pm = pen_y_lm * 1000 / resolution;
1133 	}
1134 
1135 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = pen_x_lm;
1136 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = pen_x_pm;
1137 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = pen_y_lm;
1138 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = pen_y_pm;
1139 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = pen_pressure_lm;
1140 	desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = frame_num_buttons;
1141 
1142 	return 0;
1143 }
1144 
1145 /**
1146  * uclogic_params_ugee_v2_init_frame_buttons() - initialize a UGEE v2 frame with
1147  * buttons.
1148  * @p:			Parameters to fill in, cannot be NULL.
1149  * @desc_params:	Device description params list.
1150  * @desc_params_size:	Size of the description params list.
1151  *
1152  * Returns:
1153  *	Zero, if successful. A negative errno code on error.
1154  */
uclogic_params_ugee_v2_init_frame_buttons(struct uclogic_params * p,const s32 * desc_params,size_t desc_params_size)1155 static int uclogic_params_ugee_v2_init_frame_buttons(struct uclogic_params *p,
1156 						     const s32 *desc_params,
1157 						     size_t desc_params_size)
1158 {
1159 	__u8 *rdesc_frame = NULL;
1160 	int rc = 0;
1161 
1162 	if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
1163 		return -EINVAL;
1164 
1165 	rdesc_frame = uclogic_rdesc_template_apply(
1166 				uclogic_rdesc_ugee_v2_frame_btn_template_arr,
1167 				uclogic_rdesc_ugee_v2_frame_btn_template_size,
1168 				desc_params, UCLOGIC_RDESC_PH_ID_NUM);
1169 	if (!rdesc_frame)
1170 		return -ENOMEM;
1171 
1172 	rc = uclogic_params_frame_init_with_desc(&p->frame_list[0],
1173 						 rdesc_frame,
1174 						 uclogic_rdesc_ugee_v2_frame_btn_template_size,
1175 						 UCLOGIC_RDESC_V1_FRAME_ID);
1176 	kfree(rdesc_frame);
1177 	return rc;
1178 }
1179 
1180 /**
1181  * uclogic_params_ugee_v2_init_frame_dial() - initialize a UGEE v2 frame with a
1182  * bitmap dial.
1183  * @p:			Parameters to fill in, cannot be NULL.
1184  * @desc_params:	Device description params list.
1185  * @desc_params_size:	Size of the description params list.
1186  *
1187  * Returns:
1188  *	Zero, if successful. A negative errno code on error.
1189  */
uclogic_params_ugee_v2_init_frame_dial(struct uclogic_params * p,const s32 * desc_params,size_t desc_params_size)1190 static int uclogic_params_ugee_v2_init_frame_dial(struct uclogic_params *p,
1191 						  const s32 *desc_params,
1192 						  size_t desc_params_size)
1193 {
1194 	__u8 *rdesc_frame = NULL;
1195 	int rc = 0;
1196 
1197 	if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
1198 		return -EINVAL;
1199 
1200 	rdesc_frame = uclogic_rdesc_template_apply(
1201 				uclogic_rdesc_ugee_v2_frame_dial_template_arr,
1202 				uclogic_rdesc_ugee_v2_frame_dial_template_size,
1203 				desc_params, UCLOGIC_RDESC_PH_ID_NUM);
1204 	if (!rdesc_frame)
1205 		return -ENOMEM;
1206 
1207 	rc = uclogic_params_frame_init_with_desc(&p->frame_list[0],
1208 						 rdesc_frame,
1209 						 uclogic_rdesc_ugee_v2_frame_dial_template_size,
1210 						 UCLOGIC_RDESC_V1_FRAME_ID);
1211 	kfree(rdesc_frame);
1212 	if (rc)
1213 		return rc;
1214 
1215 	p->frame_list[0].bitmap_dial_byte = 7;
1216 	return 0;
1217 }
1218 
1219 /**
1220  * uclogic_params_ugee_v2_init_frame_mouse() - initialize a UGEE v2 frame with a
1221  * mouse.
1222  * @p:			Parameters to fill in, cannot be NULL.
1223  *
1224  * Returns:
1225  *	Zero, if successful. A negative errno code on error.
1226  */
uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params * p)1227 static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p)
1228 {
1229 	int rc = 0;
1230 
1231 	if (!p)
1232 		return -EINVAL;
1233 
1234 	rc = uclogic_params_frame_init_with_desc(&p->frame_list[1],
1235 						 uclogic_rdesc_ugee_v2_frame_mouse_template_arr,
1236 						 uclogic_rdesc_ugee_v2_frame_mouse_template_size,
1237 						 UCLOGIC_RDESC_V1_FRAME_ID);
1238 	return rc;
1239 }
1240 
1241 /**
1242  * uclogic_params_ugee_v2_has_battery() - check whether a UGEE v2 device has
1243  * battery or not.
1244  * @hdev:	The HID device of the tablet interface.
1245  *
1246  * Returns:
1247  *	True if the device has battery, false otherwise.
1248  */
uclogic_params_ugee_v2_has_battery(struct hid_device * hdev)1249 static bool uclogic_params_ugee_v2_has_battery(struct hid_device *hdev)
1250 {
1251 	struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
1252 
1253 	if (drvdata->quirks & UCLOGIC_BATTERY_QUIRK)
1254 		return true;
1255 
1256 	/* The XP-PEN Deco LW vendor, product and version are identical to the
1257 	 * Deco L. The only difference reported by their firmware is the product
1258 	 * name. Add a quirk to support battery reporting on the wireless
1259 	 * version.
1260 	 */
1261 	if (hdev->vendor == USB_VENDOR_ID_UGEE &&
1262 	    hdev->product == USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) {
1263 		struct usb_device *udev = hid_to_usb_dev(hdev);
1264 
1265 		if (strstarts(udev->product, "Deco LW"))
1266 			return true;
1267 	}
1268 
1269 	return false;
1270 }
1271 
1272 /**
1273  * uclogic_params_ugee_v2_init_battery() - initialize UGEE v2 battery reporting.
1274  * @hdev:	The HID device of the tablet interface, cannot be NULL.
1275  * @p:		Parameters to fill in, cannot be NULL.
1276  *
1277  * Returns:
1278  *	Zero, if successful. A negative errno code on error.
1279  */
uclogic_params_ugee_v2_init_battery(struct hid_device * hdev,struct uclogic_params * p)1280 static int uclogic_params_ugee_v2_init_battery(struct hid_device *hdev,
1281 					       struct uclogic_params *p)
1282 {
1283 	int rc = 0;
1284 
1285 	if (!hdev || !p)
1286 		return -EINVAL;
1287 
1288 	/* Some tablets contain invalid characters in hdev->uniq, throwing a
1289 	 * "hwmon: '<name>' is not a valid name attribute, please fix" error.
1290 	 * Use the device vendor and product IDs instead.
1291 	 */
1292 	snprintf(hdev->uniq, sizeof(hdev->uniq), "%x-%x", hdev->vendor,
1293 		 hdev->product);
1294 
1295 	rc = uclogic_params_frame_init_with_desc(&p->frame_list[1],
1296 						 uclogic_rdesc_ugee_v2_battery_template_arr,
1297 						 uclogic_rdesc_ugee_v2_battery_template_size,
1298 						 UCLOGIC_RDESC_UGEE_V2_BATTERY_ID);
1299 	if (rc)
1300 		return rc;
1301 
1302 	p->frame_list[1].suffix = "Battery";
1303 	p->pen.subreport_list[1].value = 0xf2;
1304 	p->pen.subreport_list[1].id = UCLOGIC_RDESC_UGEE_V2_BATTERY_ID;
1305 
1306 	return rc;
1307 }
1308 
1309 /**
1310  * uclogic_params_ugee_v2_reconnect_work() - When a wireless tablet looses
1311  * connection to the USB dongle and reconnects, either because of its physical
1312  * distance or because it was switches off and on using the frame's switch,
1313  * uclogic_probe_interface() needs to be called again to enable the tablet.
1314  *
1315  * @work: The work that triggered this function.
1316  */
uclogic_params_ugee_v2_reconnect_work(struct work_struct * work)1317 static void uclogic_params_ugee_v2_reconnect_work(struct work_struct *work)
1318 {
1319 	struct uclogic_raw_event_hook *event_hook;
1320 
1321 	event_hook = container_of(work, struct uclogic_raw_event_hook, work);
1322 	uclogic_probe_interface(event_hook->hdev, uclogic_ugee_v2_probe_arr,
1323 				uclogic_ugee_v2_probe_size,
1324 				uclogic_ugee_v2_probe_endpoint);
1325 }
1326 
1327 /**
1328  * uclogic_params_ugee_v2_init_event_hooks() - initialize the list of events
1329  * to be hooked for UGEE v2 devices.
1330  * @hdev:	The HID device of the tablet interface to initialize and get
1331  *		parameters from.
1332  * @p:		Parameters to fill in, cannot be NULL.
1333  *
1334  * Returns:
1335  *	Zero, if successful. A negative errno code on error.
1336  */
uclogic_params_ugee_v2_init_event_hooks(struct hid_device * hdev,struct uclogic_params * p)1337 static int uclogic_params_ugee_v2_init_event_hooks(struct hid_device *hdev,
1338 						   struct uclogic_params *p)
1339 {
1340 	struct uclogic_raw_event_hook *event_hook;
1341 	__u8 reconnect_event[] = {
1342 		/* Event received on wireless tablet reconnection */
1343 		0x02, 0xF8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1344 	};
1345 
1346 	if (!p)
1347 		return -EINVAL;
1348 
1349 	/* The reconnection event is only received if the tablet has battery */
1350 	if (!uclogic_params_ugee_v2_has_battery(hdev))
1351 		return 0;
1352 
1353 	p->event_hooks = kzalloc(sizeof(*p->event_hooks), GFP_KERNEL);
1354 	if (!p->event_hooks)
1355 		return -ENOMEM;
1356 
1357 	INIT_LIST_HEAD(&p->event_hooks->list);
1358 
1359 	event_hook = kzalloc(sizeof(*event_hook), GFP_KERNEL);
1360 	if (!event_hook)
1361 		return -ENOMEM;
1362 
1363 	INIT_WORK(&event_hook->work, uclogic_params_ugee_v2_reconnect_work);
1364 	event_hook->hdev = hdev;
1365 	event_hook->size = ARRAY_SIZE(reconnect_event);
1366 	event_hook->event = kmemdup(reconnect_event, event_hook->size, GFP_KERNEL);
1367 	if (!event_hook->event)
1368 		return -ENOMEM;
1369 
1370 	list_add_tail(&event_hook->list, &p->event_hooks->list);
1371 
1372 	return 0;
1373 }
1374 
1375 /**
1376  * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by
1377  * discovering their parameters.
1378  *
1379  * These tables, internally designed as v2 to differentiate them from older
1380  * models, expect a payload of magic data in orther to be switched to the fully
1381  * functional mode and expose their parameters in a similar way to the
1382  * information present in uclogic_params_pen_init_v1() but with some
1383  * differences.
1384  *
1385  * @params:	Parameters to fill in (to be cleaned with
1386  *		uclogic_params_cleanup()). Not modified in case of error.
1387  *		Cannot be NULL.
1388  * @hdev:	The HID device of the tablet interface to initialize and get
1389  *		parameters from. Cannot be NULL.
1390  *
1391  * Returns:
1392  *	Zero, if successful. A negative errno code on error.
1393  */
uclogic_params_ugee_v2_init(struct uclogic_params * params,struct hid_device * hdev)1394 static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
1395 				       struct hid_device *hdev)
1396 {
1397 	int rc = 0;
1398 	struct uclogic_drvdata *drvdata;
1399 	struct usb_interface *iface;
1400 	__u8 bInterfaceNumber;
1401 	const int str_desc_len = 12;
1402 	__u8 *str_desc = NULL;
1403 	__u8 *rdesc_pen = NULL;
1404 	s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
1405 	enum uclogic_params_frame_type frame_type;
1406 	/* The resulting parameters (noop) */
1407 	struct uclogic_params p = {0, };
1408 
1409 	if (!params || !hdev) {
1410 		rc = -EINVAL;
1411 		goto cleanup;
1412 	}
1413 
1414 	drvdata = hid_get_drvdata(hdev);
1415 	iface = to_usb_interface(hdev->dev.parent);
1416 	bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1417 
1418 	if (bInterfaceNumber == 0) {
1419 		rc = uclogic_params_ugee_v2_init_frame_mouse(&p);
1420 		if (rc)
1421 			goto cleanup;
1422 
1423 		goto output;
1424 	}
1425 
1426 	if (bInterfaceNumber != 2) {
1427 		uclogic_params_init_invalid(&p);
1428 		goto output;
1429 	}
1430 
1431 	/*
1432 	 * Initialize the interface by sending magic data.
1433 	 * The specific data was discovered by sniffing the Windows driver
1434 	 * traffic.
1435 	 */
1436 	rc = uclogic_probe_interface(hdev, uclogic_ugee_v2_probe_arr,
1437 				     uclogic_ugee_v2_probe_size,
1438 				     uclogic_ugee_v2_probe_endpoint);
1439 	if (rc) {
1440 		uclogic_params_init_invalid(&p);
1441 		goto output;
1442 	}
1443 
1444 	/*
1445 	 * Read the string descriptor containing pen and frame parameters.
1446 	 * The specific string descriptor and data were discovered by sniffing
1447 	 * the Windows driver traffic.
1448 	 */
1449 	rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len);
1450 	if (rc != str_desc_len) {
1451 		hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc);
1452 		uclogic_params_init_invalid(&p);
1453 		goto output;
1454 	}
1455 
1456 	rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len,
1457 					       desc_params,
1458 					       ARRAY_SIZE(desc_params),
1459 					       &frame_type);
1460 	if (rc)
1461 		goto cleanup;
1462 
1463 	kfree(str_desc);
1464 	str_desc = NULL;
1465 
1466 	/* Initialize the pen interface */
1467 	rdesc_pen = uclogic_rdesc_template_apply(
1468 				uclogic_rdesc_ugee_v2_pen_template_arr,
1469 				uclogic_rdesc_ugee_v2_pen_template_size,
1470 				desc_params, ARRAY_SIZE(desc_params));
1471 	if (!rdesc_pen) {
1472 		rc = -ENOMEM;
1473 		goto cleanup;
1474 	}
1475 
1476 	p.pen.desc_ptr = rdesc_pen;
1477 	p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size;
1478 	p.pen.id = 0x02;
1479 	p.pen.subreport_list[0].value = 0xf0;
1480 	p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
1481 
1482 	/* Initialize the frame interface */
1483 	if (drvdata->quirks & UCLOGIC_MOUSE_FRAME_QUIRK)
1484 		frame_type = UCLOGIC_PARAMS_FRAME_MOUSE;
1485 
1486 	switch (frame_type) {
1487 	case UCLOGIC_PARAMS_FRAME_DIAL:
1488 	case UCLOGIC_PARAMS_FRAME_MOUSE:
1489 		rc = uclogic_params_ugee_v2_init_frame_dial(&p, desc_params,
1490 							    ARRAY_SIZE(desc_params));
1491 		break;
1492 	case UCLOGIC_PARAMS_FRAME_BUTTONS:
1493 	default:
1494 		rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params,
1495 							       ARRAY_SIZE(desc_params));
1496 		break;
1497 	}
1498 
1499 	if (rc)
1500 		goto cleanup;
1501 
1502 	/* Initialize the battery interface*/
1503 	if (uclogic_params_ugee_v2_has_battery(hdev)) {
1504 		rc = uclogic_params_ugee_v2_init_battery(hdev, &p);
1505 		if (rc) {
1506 			hid_err(hdev, "error initializing battery: %d\n", rc);
1507 			goto cleanup;
1508 		}
1509 	}
1510 
1511 	/* Create a list of raw events to be ignored */
1512 	rc = uclogic_params_ugee_v2_init_event_hooks(hdev, &p);
1513 	if (rc) {
1514 		hid_err(hdev, "error initializing event hook list: %d\n", rc);
1515 		goto cleanup;
1516 	}
1517 
1518 output:
1519 	/* Output parameters */
1520 	memcpy(params, &p, sizeof(*params));
1521 	memset(&p, 0, sizeof(p));
1522 	rc = 0;
1523 cleanup:
1524 	kfree(str_desc);
1525 	uclogic_params_cleanup(&p);
1526 	return rc;
1527 }
1528 
1529 /**
1530  * uclogic_params_init() - initialize a tablet interface and discover its
1531  * parameters.
1532  *
1533  * @params:	Parameters to fill in (to be cleaned with
1534  *		uclogic_params_cleanup()). Not modified in case of error.
1535  *		Cannot be NULL.
1536  * @hdev:	The HID device of the tablet interface to initialize and get
1537  *		parameters from. Cannot be NULL. Must be using the USB low-level
1538  *		driver, i.e. be an actual USB tablet.
1539  *
1540  * Returns:
1541  *	Zero, if successful. A negative errno code on error.
1542  */
uclogic_params_init(struct uclogic_params * params,struct hid_device * hdev)1543 int uclogic_params_init(struct uclogic_params *params,
1544 			struct hid_device *hdev)
1545 {
1546 	int rc;
1547 	struct usb_device *udev;
1548 	__u8  bNumInterfaces;
1549 	struct usb_interface *iface;
1550 	__u8 bInterfaceNumber;
1551 	bool found;
1552 	/* The resulting parameters (noop) */
1553 	struct uclogic_params p = {0, };
1554 
1555 	/* Check arguments */
1556 	if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) {
1557 		rc = -EINVAL;
1558 		goto cleanup;
1559 	}
1560 
1561 	udev = hid_to_usb_dev(hdev);
1562 	bNumInterfaces = udev->config->desc.bNumInterfaces;
1563 	iface = to_usb_interface(hdev->dev.parent);
1564 	bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1565 
1566 	/*
1567 	 * Set replacement report descriptor if the original matches the
1568 	 * specified size. Otherwise keep interface unchanged.
1569 	 */
1570 #define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \
1571 	uclogic_params_init_with_opt_desc(                  \
1572 		&p, hdev,                                   \
1573 		UCLOGIC_RDESC_##_orig_desc_token##_SIZE,    \
1574 		uclogic_rdesc_##_new_desc_token##_arr,      \
1575 		uclogic_rdesc_##_new_desc_token##_size)
1576 
1577 #define VID_PID(_vid, _pid) \
1578 	(((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX))
1579 
1580 	/*
1581 	 * Handle specific interfaces for specific tablets.
1582 	 *
1583 	 * Observe the following logic:
1584 	 *
1585 	 * If the interface is recognized as producing certain useful input:
1586 	 *	Mark interface as valid.
1587 	 *	Output interface parameters.
1588 	 * Else, if the interface is recognized as *not* producing any useful
1589 	 * input:
1590 	 *	Mark interface as invalid.
1591 	 * Else:
1592 	 *	Mark interface as valid.
1593 	 *	Output noop parameters.
1594 	 *
1595 	 * Rule of thumb: it is better to disable a broken interface than let
1596 	 *		  it spew garbage input.
1597 	 */
1598 
1599 	switch (VID_PID(hdev->vendor, hdev->product)) {
1600 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1601 		     USB_DEVICE_ID_UCLOGIC_TABLET_PF1209):
1602 		rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed);
1603 		if (rc != 0)
1604 			goto cleanup;
1605 		break;
1606 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1607 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U):
1608 		rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed);
1609 		if (rc != 0)
1610 			goto cleanup;
1611 		break;
1612 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1613 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U):
1614 		if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) {
1615 			if (bInterfaceNumber == 0) {
1616 				/* Try to probe v1 pen parameters */
1617 				rc = uclogic_params_pen_init_v1(&p.pen,
1618 								&found, hdev);
1619 				if (rc != 0) {
1620 					hid_err(hdev,
1621 						"pen probing failed: %d\n",
1622 						rc);
1623 					goto cleanup;
1624 				}
1625 				if (!found) {
1626 					hid_warn(hdev,
1627 						 "pen parameters not found");
1628 				}
1629 			} else {
1630 				uclogic_params_init_invalid(&p);
1631 			}
1632 		} else {
1633 			rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed);
1634 			if (rc != 0)
1635 				goto cleanup;
1636 		}
1637 		break;
1638 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1639 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U):
1640 		rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed);
1641 		if (rc != 0)
1642 			goto cleanup;
1643 		break;
1644 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1645 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP1062):
1646 		rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed);
1647 		if (rc != 0)
1648 			goto cleanup;
1649 		break;
1650 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1651 		     USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850):
1652 		switch (bInterfaceNumber) {
1653 		case 0:
1654 			rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0);
1655 			if (rc != 0)
1656 				goto cleanup;
1657 			break;
1658 		case 1:
1659 			rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1);
1660 			if (rc != 0)
1661 				goto cleanup;
1662 			break;
1663 		case 2:
1664 			rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2);
1665 			if (rc != 0)
1666 				goto cleanup;
1667 			break;
1668 		}
1669 		break;
1670 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1671 		     USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60):
1672 		/*
1673 		 * If it is not a three-interface version, which is known to
1674 		 * respond to initialization.
1675 		 */
1676 		if (bNumInterfaces != 3) {
1677 			switch (bInterfaceNumber) {
1678 			case 0:
1679 				rc = WITH_OPT_DESC(TWHA60_ORIG0,
1680 							twha60_fixed0);
1681 				if (rc != 0)
1682 					goto cleanup;
1683 				break;
1684 			case 1:
1685 				rc = WITH_OPT_DESC(TWHA60_ORIG1,
1686 							twha60_fixed1);
1687 				if (rc != 0)
1688 					goto cleanup;
1689 				break;
1690 			}
1691 			break;
1692 		}
1693 		fallthrough;
1694 	case VID_PID(USB_VENDOR_ID_HUION,
1695 		     USB_DEVICE_ID_HUION_TABLET):
1696 	case VID_PID(USB_VENDOR_ID_HUION,
1697 		     USB_DEVICE_ID_HUION_TABLET2):
1698 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1699 		     USB_DEVICE_ID_HUION_TABLET):
1700 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1701 		     USB_DEVICE_ID_YIYNOVA_TABLET):
1702 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1703 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81):
1704 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1705 		     USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3):
1706 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1707 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45):
1708 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1709 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47):
1710 		rc = uclogic_params_huion_init(&p, hdev);
1711 		if (rc != 0)
1712 			goto cleanup;
1713 		break;
1714 	case VID_PID(USB_VENDOR_ID_UGTIZER,
1715 		     USB_DEVICE_ID_UGTIZER_TABLET_GP0610):
1716 	case VID_PID(USB_VENDOR_ID_UGTIZER,
1717 		     USB_DEVICE_ID_UGTIZER_TABLET_GT5040):
1718 	case VID_PID(USB_VENDOR_ID_UGEE,
1719 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
1720 	case VID_PID(USB_VENDOR_ID_UGEE,
1721 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640):
1722 	case VID_PID(USB_VENDOR_ID_UGEE,
1723 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06):
1724 	case VID_PID(USB_VENDOR_ID_UGEE,
1725 		     USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720):
1726 		/* If this is the pen interface */
1727 		if (bInterfaceNumber == 1) {
1728 			/* Probe v1 pen parameters */
1729 			rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1730 			if (rc != 0) {
1731 				hid_err(hdev, "pen probing failed: %d\n", rc);
1732 				goto cleanup;
1733 			}
1734 			if (!found) {
1735 				hid_warn(hdev, "pen parameters not found");
1736 				uclogic_params_init_invalid(&p);
1737 			}
1738 		} else {
1739 			uclogic_params_init_invalid(&p);
1740 		}
1741 		break;
1742 	case VID_PID(USB_VENDOR_ID_UGEE,
1743 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01):
1744 		/* If this is the pen and frame interface */
1745 		if (bInterfaceNumber == 1) {
1746 			/* Probe v1 pen parameters */
1747 			rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1748 			if (rc != 0) {
1749 				hid_err(hdev, "pen probing failed: %d\n", rc);
1750 				goto cleanup;
1751 			}
1752 			/* Initialize frame parameters */
1753 			rc = uclogic_params_frame_init_with_desc(
1754 				&p.frame_list[0],
1755 				uclogic_rdesc_xppen_deco01_frame_arr,
1756 				uclogic_rdesc_xppen_deco01_frame_size,
1757 				0);
1758 			if (rc != 0)
1759 				goto cleanup;
1760 		} else {
1761 			uclogic_params_init_invalid(&p);
1762 		}
1763 		break;
1764 	case VID_PID(USB_VENDOR_ID_UGEE,
1765 		     USB_DEVICE_ID_UGEE_PARBLO_A610_PRO):
1766 	case VID_PID(USB_VENDOR_ID_UGEE,
1767 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2):
1768 	case VID_PID(USB_VENDOR_ID_UGEE,
1769 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L):
1770 	case VID_PID(USB_VENDOR_ID_UGEE,
1771 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW):
1772 	case VID_PID(USB_VENDOR_ID_UGEE,
1773 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S):
1774 	case VID_PID(USB_VENDOR_ID_UGEE,
1775 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW):
1776 		rc = uclogic_params_ugee_v2_init(&p, hdev);
1777 		if (rc != 0)
1778 			goto cleanup;
1779 		break;
1780 	case VID_PID(USB_VENDOR_ID_TRUST,
1781 		     USB_DEVICE_ID_TRUST_PANORA_TABLET):
1782 	case VID_PID(USB_VENDOR_ID_UGEE,
1783 		     USB_DEVICE_ID_UGEE_TABLET_G5):
1784 		/* Ignore non-pen interfaces */
1785 		if (bInterfaceNumber != 1) {
1786 			uclogic_params_init_invalid(&p);
1787 			break;
1788 		}
1789 
1790 		rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1791 		if (rc != 0) {
1792 			hid_err(hdev, "pen probing failed: %d\n", rc);
1793 			goto cleanup;
1794 		} else if (found) {
1795 			rc = uclogic_params_frame_init_with_desc(
1796 				&p.frame_list[0],
1797 				uclogic_rdesc_ugee_g5_frame_arr,
1798 				uclogic_rdesc_ugee_g5_frame_size,
1799 				UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
1800 			if (rc != 0) {
1801 				hid_err(hdev,
1802 					"failed creating frame parameters: %d\n",
1803 					rc);
1804 				goto cleanup;
1805 			}
1806 			p.frame_list[0].re_lsb =
1807 				UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
1808 			p.frame_list[0].dev_id_byte =
1809 				UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
1810 		} else {
1811 			hid_warn(hdev, "pen parameters not found");
1812 			uclogic_params_init_invalid(&p);
1813 		}
1814 
1815 		break;
1816 	case VID_PID(USB_VENDOR_ID_UGEE,
1817 		     USB_DEVICE_ID_UGEE_TABLET_EX07S):
1818 		/* Ignore non-pen interfaces */
1819 		if (bInterfaceNumber != 1) {
1820 			uclogic_params_init_invalid(&p);
1821 			break;
1822 		}
1823 
1824 		rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1825 		if (rc != 0) {
1826 			hid_err(hdev, "pen probing failed: %d\n", rc);
1827 			goto cleanup;
1828 		} else if (found) {
1829 			rc = uclogic_params_frame_init_with_desc(
1830 				&p.frame_list[0],
1831 				uclogic_rdesc_ugee_ex07_frame_arr,
1832 				uclogic_rdesc_ugee_ex07_frame_size,
1833 				0);
1834 			if (rc != 0) {
1835 				hid_err(hdev,
1836 					"failed creating frame parameters: %d\n",
1837 					rc);
1838 				goto cleanup;
1839 			}
1840 		} else {
1841 			hid_warn(hdev, "pen parameters not found");
1842 			uclogic_params_init_invalid(&p);
1843 		}
1844 
1845 		break;
1846 	}
1847 
1848 #undef VID_PID
1849 #undef WITH_OPT_DESC
1850 
1851 	/* Output parameters */
1852 	memcpy(params, &p, sizeof(*params));
1853 	memset(&p, 0, sizeof(p));
1854 	rc = 0;
1855 cleanup:
1856 	uclogic_params_cleanup(&p);
1857 	return rc;
1858 }
1859 
1860 #ifdef CONFIG_HID_KUNIT_TEST
1861 #include "hid-uclogic-params-test.c"
1862 #endif
1863