xref: /linux/drivers/hid/hid-uclogic-params.c (revision 7ec462100ef9142344ddbf86f2c3008b97acddbe)
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 <linux/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,const __u8 ** pdesc,unsigned int * psize)683 int uclogic_params_get_desc(const struct uclogic_params *params,
684 				const __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,const __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 					     const __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 	/* The firmware is used in userspace as unique identifier */
888 	strscpy(hdev->uniq, ver_ptr, sizeof(hdev->uniq));
889 
890 	/* If this is a transition firmware */
891 	if (strcmp(ver_ptr, transition_ver) == 0) {
892 		hid_dbg(hdev,
893 			"transition firmware detected, not probing pen v2 parameters\n");
894 	} else {
895 		/* Try to probe v2 pen parameters */
896 		rc = uclogic_params_pen_init_v2(&p.pen, &found,
897 						&params_ptr, &params_len,
898 						hdev);
899 		if (rc != 0) {
900 			hid_err(hdev,
901 				"failed probing pen v2 parameters: %d\n", rc);
902 			goto cleanup;
903 		} else if (found) {
904 			hid_dbg(hdev, "pen v2 parameters found\n");
905 			/* Create v2 frame button parameters */
906 			rc = uclogic_params_frame_init_with_desc(
907 					&p.frame_list[0],
908 					uclogic_rdesc_v2_frame_buttons_arr,
909 					uclogic_rdesc_v2_frame_buttons_size,
910 					UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID);
911 			if (rc != 0) {
912 				hid_err(hdev,
913 					"failed creating v2 frame button parameters: %d\n",
914 					rc);
915 				goto cleanup;
916 			}
917 
918 			/* Link from pen sub-report */
919 			p.pen.subreport_list[0].value = 0xe0;
920 			p.pen.subreport_list[0].id =
921 				UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID;
922 
923 			/* If this is the model with touch ring */
924 			if (params_ptr != NULL &&
925 			    params_len == sizeof(touch_ring_model_params_buf) &&
926 			    memcmp(params_ptr, touch_ring_model_params_buf,
927 				   params_len) == 0) {
928 				/* Create touch ring parameters */
929 				rc = uclogic_params_frame_init_with_desc(
930 					&p.frame_list[1],
931 					uclogic_rdesc_v2_frame_touch_ring_arr,
932 					uclogic_rdesc_v2_frame_touch_ring_size,
933 					UCLOGIC_RDESC_V2_FRAME_TOUCH_ID);
934 				if (rc != 0) {
935 					hid_err(hdev,
936 						"failed creating v2 frame touch ring parameters: %d\n",
937 						rc);
938 					goto cleanup;
939 				}
940 				p.frame_list[1].suffix = "Touch Ring";
941 				p.frame_list[1].dev_id_byte =
942 					UCLOGIC_RDESC_V2_FRAME_TOUCH_DEV_ID_BYTE;
943 				p.frame_list[1].touch_byte = 5;
944 				p.frame_list[1].touch_max = 12;
945 				p.frame_list[1].touch_flip_at = 7;
946 			} else {
947 				/* Create touch strip parameters */
948 				rc = uclogic_params_frame_init_with_desc(
949 					&p.frame_list[1],
950 					uclogic_rdesc_v2_frame_touch_strip_arr,
951 					uclogic_rdesc_v2_frame_touch_strip_size,
952 					UCLOGIC_RDESC_V2_FRAME_TOUCH_ID);
953 				if (rc != 0) {
954 					hid_err(hdev,
955 						"failed creating v2 frame touch strip parameters: %d\n",
956 						rc);
957 					goto cleanup;
958 				}
959 				p.frame_list[1].suffix = "Touch Strip";
960 				p.frame_list[1].dev_id_byte =
961 					UCLOGIC_RDESC_V2_FRAME_TOUCH_DEV_ID_BYTE;
962 				p.frame_list[1].touch_byte = 5;
963 				p.frame_list[1].touch_max = 8;
964 			}
965 
966 			/* Link from pen sub-report */
967 			p.pen.subreport_list[1].value = 0xf0;
968 			p.pen.subreport_list[1].id =
969 				UCLOGIC_RDESC_V2_FRAME_TOUCH_ID;
970 
971 			/* Create v2 frame dial parameters */
972 			rc = uclogic_params_frame_init_with_desc(
973 					&p.frame_list[2],
974 					uclogic_rdesc_v2_frame_dial_arr,
975 					uclogic_rdesc_v2_frame_dial_size,
976 					UCLOGIC_RDESC_V2_FRAME_DIAL_ID);
977 			if (rc != 0) {
978 				hid_err(hdev,
979 					"failed creating v2 frame dial parameters: %d\n",
980 					rc);
981 				goto cleanup;
982 			}
983 			p.frame_list[2].suffix = "Dial";
984 			p.frame_list[2].dev_id_byte =
985 				UCLOGIC_RDESC_V2_FRAME_DIAL_DEV_ID_BYTE;
986 			p.frame_list[2].bitmap_dial_byte = 5;
987 
988 			/* Link from pen sub-report */
989 			p.pen.subreport_list[2].value = 0xf1;
990 			p.pen.subreport_list[2].id =
991 				UCLOGIC_RDESC_V2_FRAME_DIAL_ID;
992 
993 			goto output;
994 		}
995 		hid_dbg(hdev, "pen v2 parameters not found\n");
996 	}
997 
998 	/* Try to probe v1 pen parameters */
999 	rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1000 	if (rc != 0) {
1001 		hid_err(hdev,
1002 			"failed probing pen v1 parameters: %d\n", rc);
1003 		goto cleanup;
1004 	} else if (found) {
1005 		hid_dbg(hdev, "pen v1 parameters found\n");
1006 		/* Try to probe v1 frame */
1007 		rc = uclogic_params_frame_init_v1(&p.frame_list[0],
1008 						  &found, hdev);
1009 		if (rc != 0) {
1010 			hid_err(hdev, "v1 frame probing failed: %d\n", rc);
1011 			goto cleanup;
1012 		}
1013 		hid_dbg(hdev, "frame v1 parameters%s found\n",
1014 			(found ? "" : " not"));
1015 		if (found) {
1016 			/* Link frame button subreports from pen reports */
1017 			p.pen.subreport_list[0].value = 0xe0;
1018 			p.pen.subreport_list[0].id =
1019 				UCLOGIC_RDESC_V1_FRAME_ID;
1020 		}
1021 		goto output;
1022 	}
1023 	hid_dbg(hdev, "pen v1 parameters not found\n");
1024 
1025 	uclogic_params_init_invalid(&p);
1026 
1027 output:
1028 	/* Output parameters */
1029 	memcpy(params, &p, sizeof(*params));
1030 	memset(&p, 0, sizeof(p));
1031 	rc = 0;
1032 cleanup:
1033 	kfree(params_ptr);
1034 	kfree(ver_ptr);
1035 	uclogic_params_cleanup(&p);
1036 	return rc;
1037 }
1038 
1039 /**
1040  * uclogic_probe_interface() - some tablets, like the Parblo A610 PLUS V2 or
1041  * the XP-PEN Deco Mini 7, need to be initialized by sending them magic data.
1042  *
1043  * @hdev:	The HID device of the tablet interface to initialize and get
1044  *		parameters from. Cannot be NULL.
1045  * @magic_arr:	The magic data that should be sent to probe the interface.
1046  *		Cannot be NULL.
1047  * @magic_size:	Size of the magic data.
1048  * @endpoint:	Endpoint where the magic data should be sent.
1049  *
1050  * Returns:
1051  *	Zero, if successful. A negative errno code on error.
1052  */
uclogic_probe_interface(struct hid_device * hdev,const u8 * magic_arr,size_t magic_size,int endpoint)1053 static int uclogic_probe_interface(struct hid_device *hdev, const u8 *magic_arr,
1054 				   size_t magic_size, int endpoint)
1055 {
1056 	struct usb_device *udev;
1057 	unsigned int pipe = 0;
1058 	int sent;
1059 	u8 *buf = NULL;
1060 	int rc = 0;
1061 
1062 	if (!hdev || !magic_arr) {
1063 		rc = -EINVAL;
1064 		goto cleanup;
1065 	}
1066 
1067 	buf = kmemdup(magic_arr, magic_size, GFP_KERNEL);
1068 	if (!buf) {
1069 		rc = -ENOMEM;
1070 		goto cleanup;
1071 	}
1072 
1073 	udev = hid_to_usb_dev(hdev);
1074 	pipe = usb_sndintpipe(udev, endpoint);
1075 
1076 	rc = usb_interrupt_msg(udev, pipe, buf, magic_size, &sent, 1000);
1077 	if (rc || sent != magic_size) {
1078 		hid_err(hdev, "Interface probing failed: %d\n", rc);
1079 		rc = -1;
1080 		goto cleanup;
1081 	}
1082 
1083 	rc = 0;
1084 cleanup:
1085 	kfree(buf);
1086 	return rc;
1087 }
1088 
1089 /**
1090  * uclogic_params_parse_ugee_v2_desc - parse the string descriptor containing
1091  * pen and frame parameters returned by UGEE v2 devices.
1092  *
1093  * @str_desc:		String descriptor, cannot be NULL.
1094  * @str_desc_size:	Size of the string descriptor.
1095  * @desc_params:	Output description params list.
1096  * @desc_params_size:	Size of the output description params list.
1097  * @frame_type:		Output frame type.
1098  *
1099  * Returns:
1100  *	Zero, if successful. A negative errno code on error.
1101  */
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)1102 static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc,
1103 					     size_t str_desc_size,
1104 					     s32 *desc_params,
1105 					     size_t desc_params_size,
1106 					     enum uclogic_params_frame_type *frame_type)
1107 {
1108 	s32 pen_x_lm, pen_y_lm;
1109 	s32 pen_x_pm, pen_y_pm;
1110 	s32 pen_pressure_lm;
1111 	s32 frame_num_buttons;
1112 	s32 resolution;
1113 
1114 	/* Minimum descriptor length required, maximum seen so far is 14 */
1115 	const int min_str_desc_size = 12;
1116 
1117 	if (!str_desc || str_desc_size < min_str_desc_size)
1118 		return -EINVAL;
1119 
1120 	if (desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
1121 		return -EINVAL;
1122 
1123 	pen_x_lm = get_unaligned_le16(str_desc + 2);
1124 	pen_y_lm = get_unaligned_le16(str_desc + 4);
1125 	frame_num_buttons = str_desc[6];
1126 	*frame_type = str_desc[7];
1127 	pen_pressure_lm = get_unaligned_le16(str_desc + 8);
1128 
1129 	resolution = get_unaligned_le16(str_desc + 10);
1130 	if (resolution == 0) {
1131 		pen_x_pm = 0;
1132 		pen_y_pm = 0;
1133 	} else {
1134 		pen_x_pm = pen_x_lm * 1000 / resolution;
1135 		pen_y_pm = pen_y_lm * 1000 / resolution;
1136 	}
1137 
1138 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = pen_x_lm;
1139 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = pen_x_pm;
1140 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = pen_y_lm;
1141 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = pen_y_pm;
1142 	desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = pen_pressure_lm;
1143 	desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = frame_num_buttons;
1144 
1145 	return 0;
1146 }
1147 
1148 /**
1149  * uclogic_params_ugee_v2_init_frame_buttons() - initialize a UGEE v2 frame with
1150  * buttons.
1151  * @p:			Parameters to fill in, cannot be NULL.
1152  * @desc_params:	Device description params list.
1153  * @desc_params_size:	Size of the description params list.
1154  *
1155  * Returns:
1156  *	Zero, if successful. A negative errno code on error.
1157  */
uclogic_params_ugee_v2_init_frame_buttons(struct uclogic_params * p,const s32 * desc_params,size_t desc_params_size)1158 static int uclogic_params_ugee_v2_init_frame_buttons(struct uclogic_params *p,
1159 						     const s32 *desc_params,
1160 						     size_t desc_params_size)
1161 {
1162 	__u8 *rdesc_frame = NULL;
1163 	int rc = 0;
1164 
1165 	if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
1166 		return -EINVAL;
1167 
1168 	rdesc_frame = uclogic_rdesc_template_apply(
1169 				uclogic_rdesc_ugee_v2_frame_btn_template_arr,
1170 				uclogic_rdesc_ugee_v2_frame_btn_template_size,
1171 				desc_params, UCLOGIC_RDESC_PH_ID_NUM);
1172 	if (!rdesc_frame)
1173 		return -ENOMEM;
1174 
1175 	rc = uclogic_params_frame_init_with_desc(&p->frame_list[0],
1176 						 rdesc_frame,
1177 						 uclogic_rdesc_ugee_v2_frame_btn_template_size,
1178 						 UCLOGIC_RDESC_V1_FRAME_ID);
1179 	kfree(rdesc_frame);
1180 	return rc;
1181 }
1182 
1183 /**
1184  * uclogic_params_ugee_v2_init_frame_dial() - initialize a UGEE v2 frame with a
1185  * bitmap dial.
1186  * @p:			Parameters to fill in, cannot be NULL.
1187  * @desc_params:	Device description params list.
1188  * @desc_params_size:	Size of the description params list.
1189  *
1190  * Returns:
1191  *	Zero, if successful. A negative errno code on error.
1192  */
uclogic_params_ugee_v2_init_frame_dial(struct uclogic_params * p,const s32 * desc_params,size_t desc_params_size)1193 static int uclogic_params_ugee_v2_init_frame_dial(struct uclogic_params *p,
1194 						  const s32 *desc_params,
1195 						  size_t desc_params_size)
1196 {
1197 	__u8 *rdesc_frame = NULL;
1198 	int rc = 0;
1199 
1200 	if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
1201 		return -EINVAL;
1202 
1203 	rdesc_frame = uclogic_rdesc_template_apply(
1204 				uclogic_rdesc_ugee_v2_frame_dial_template_arr,
1205 				uclogic_rdesc_ugee_v2_frame_dial_template_size,
1206 				desc_params, UCLOGIC_RDESC_PH_ID_NUM);
1207 	if (!rdesc_frame)
1208 		return -ENOMEM;
1209 
1210 	rc = uclogic_params_frame_init_with_desc(&p->frame_list[0],
1211 						 rdesc_frame,
1212 						 uclogic_rdesc_ugee_v2_frame_dial_template_size,
1213 						 UCLOGIC_RDESC_V1_FRAME_ID);
1214 	kfree(rdesc_frame);
1215 	if (rc)
1216 		return rc;
1217 
1218 	p->frame_list[0].bitmap_dial_byte = 7;
1219 	return 0;
1220 }
1221 
1222 /**
1223  * uclogic_params_ugee_v2_init_frame_mouse() - initialize a UGEE v2 frame with a
1224  * mouse.
1225  * @p:			Parameters to fill in, cannot be NULL.
1226  *
1227  * Returns:
1228  *	Zero, if successful. A negative errno code on error.
1229  */
uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params * p)1230 static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p)
1231 {
1232 	int rc = 0;
1233 
1234 	if (!p)
1235 		return -EINVAL;
1236 
1237 	rc = uclogic_params_frame_init_with_desc(&p->frame_list[1],
1238 						 uclogic_rdesc_ugee_v2_frame_mouse_template_arr,
1239 						 uclogic_rdesc_ugee_v2_frame_mouse_template_size,
1240 						 UCLOGIC_RDESC_V1_FRAME_ID);
1241 	return rc;
1242 }
1243 
1244 /**
1245  * uclogic_params_ugee_v2_has_battery() - check whether a UGEE v2 device has
1246  * battery or not.
1247  * @hdev:	The HID device of the tablet interface.
1248  *
1249  * Returns:
1250  *	True if the device has battery, false otherwise.
1251  */
uclogic_params_ugee_v2_has_battery(struct hid_device * hdev)1252 static bool uclogic_params_ugee_v2_has_battery(struct hid_device *hdev)
1253 {
1254 	struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
1255 
1256 	if (drvdata->quirks & UCLOGIC_BATTERY_QUIRK)
1257 		return true;
1258 
1259 	/* The XP-PEN Deco LW vendor, product and version are identical to the
1260 	 * Deco L. The only difference reported by their firmware is the product
1261 	 * name. Add a quirk to support battery reporting on the wireless
1262 	 * version.
1263 	 */
1264 	if (hdev->vendor == USB_VENDOR_ID_UGEE &&
1265 	    hdev->product == USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) {
1266 		struct usb_device *udev = hid_to_usb_dev(hdev);
1267 
1268 		if (strstarts(udev->product, "Deco LW"))
1269 			return true;
1270 	}
1271 
1272 	return false;
1273 }
1274 
1275 /**
1276  * uclogic_params_ugee_v2_init_battery() - initialize UGEE v2 battery reporting.
1277  * @hdev:	The HID device of the tablet interface, cannot be NULL.
1278  * @p:		Parameters to fill in, cannot be NULL.
1279  *
1280  * Returns:
1281  *	Zero, if successful. A negative errno code on error.
1282  */
uclogic_params_ugee_v2_init_battery(struct hid_device * hdev,struct uclogic_params * p)1283 static int uclogic_params_ugee_v2_init_battery(struct hid_device *hdev,
1284 					       struct uclogic_params *p)
1285 {
1286 	int rc = 0;
1287 
1288 	if (!hdev || !p)
1289 		return -EINVAL;
1290 
1291 	/* Some tablets contain invalid characters in hdev->uniq, throwing a
1292 	 * "hwmon: '<name>' is not a valid name attribute, please fix" error.
1293 	 * Use the device vendor and product IDs instead.
1294 	 */
1295 	snprintf(hdev->uniq, sizeof(hdev->uniq), "%x-%x", hdev->vendor,
1296 		 hdev->product);
1297 
1298 	rc = uclogic_params_frame_init_with_desc(&p->frame_list[1],
1299 						 uclogic_rdesc_ugee_v2_battery_template_arr,
1300 						 uclogic_rdesc_ugee_v2_battery_template_size,
1301 						 UCLOGIC_RDESC_UGEE_V2_BATTERY_ID);
1302 	if (rc)
1303 		return rc;
1304 
1305 	p->frame_list[1].suffix = "Battery";
1306 	p->pen.subreport_list[1].value = 0xf2;
1307 	p->pen.subreport_list[1].id = UCLOGIC_RDESC_UGEE_V2_BATTERY_ID;
1308 
1309 	return rc;
1310 }
1311 
1312 /**
1313  * uclogic_params_ugee_v2_reconnect_work() - When a wireless tablet looses
1314  * connection to the USB dongle and reconnects, either because of its physical
1315  * distance or because it was switches off and on using the frame's switch,
1316  * uclogic_probe_interface() needs to be called again to enable the tablet.
1317  *
1318  * @work: The work that triggered this function.
1319  */
uclogic_params_ugee_v2_reconnect_work(struct work_struct * work)1320 static void uclogic_params_ugee_v2_reconnect_work(struct work_struct *work)
1321 {
1322 	struct uclogic_raw_event_hook *event_hook;
1323 
1324 	event_hook = container_of(work, struct uclogic_raw_event_hook, work);
1325 	uclogic_probe_interface(event_hook->hdev, uclogic_ugee_v2_probe_arr,
1326 				uclogic_ugee_v2_probe_size,
1327 				uclogic_ugee_v2_probe_endpoint);
1328 }
1329 
1330 /**
1331  * uclogic_params_ugee_v2_init_event_hooks() - initialize the list of events
1332  * to be hooked for UGEE v2 devices.
1333  * @hdev:	The HID device of the tablet interface to initialize and get
1334  *		parameters from.
1335  * @p:		Parameters to fill in, cannot be NULL.
1336  *
1337  * Returns:
1338  *	Zero, if successful. A negative errno code on error.
1339  */
uclogic_params_ugee_v2_init_event_hooks(struct hid_device * hdev,struct uclogic_params * p)1340 static int uclogic_params_ugee_v2_init_event_hooks(struct hid_device *hdev,
1341 						   struct uclogic_params *p)
1342 {
1343 	struct uclogic_raw_event_hook *event_hook;
1344 	__u8 reconnect_event[] = {
1345 		/* Event received on wireless tablet reconnection */
1346 		0x02, 0xF8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1347 	};
1348 
1349 	if (!p)
1350 		return -EINVAL;
1351 
1352 	/* The reconnection event is only received if the tablet has battery */
1353 	if (!uclogic_params_ugee_v2_has_battery(hdev))
1354 		return 0;
1355 
1356 	p->event_hooks = kzalloc(sizeof(*p->event_hooks), GFP_KERNEL);
1357 	if (!p->event_hooks)
1358 		return -ENOMEM;
1359 
1360 	INIT_LIST_HEAD(&p->event_hooks->list);
1361 
1362 	event_hook = kzalloc(sizeof(*event_hook), GFP_KERNEL);
1363 	if (!event_hook)
1364 		return -ENOMEM;
1365 
1366 	INIT_WORK(&event_hook->work, uclogic_params_ugee_v2_reconnect_work);
1367 	event_hook->hdev = hdev;
1368 	event_hook->size = ARRAY_SIZE(reconnect_event);
1369 	event_hook->event = kmemdup(reconnect_event, event_hook->size, GFP_KERNEL);
1370 	if (!event_hook->event)
1371 		return -ENOMEM;
1372 
1373 	list_add_tail(&event_hook->list, &p->event_hooks->list);
1374 
1375 	return 0;
1376 }
1377 
1378 /**
1379  * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by
1380  * discovering their parameters.
1381  *
1382  * These tables, internally designed as v2 to differentiate them from older
1383  * models, expect a payload of magic data in orther to be switched to the fully
1384  * functional mode and expose their parameters in a similar way to the
1385  * information present in uclogic_params_pen_init_v1() but with some
1386  * differences.
1387  *
1388  * @params:	Parameters to fill in (to be cleaned with
1389  *		uclogic_params_cleanup()). Not modified in case of error.
1390  *		Cannot be NULL.
1391  * @hdev:	The HID device of the tablet interface to initialize and get
1392  *		parameters from. Cannot be NULL.
1393  *
1394  * Returns:
1395  *	Zero, if successful. A negative errno code on error.
1396  */
uclogic_params_ugee_v2_init(struct uclogic_params * params,struct hid_device * hdev)1397 static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
1398 				       struct hid_device *hdev)
1399 {
1400 	int rc = 0;
1401 	struct uclogic_drvdata *drvdata;
1402 	struct usb_interface *iface;
1403 	__u8 bInterfaceNumber;
1404 	const int str_desc_len = 12;
1405 	__u8 *str_desc = NULL;
1406 	__u8 *rdesc_pen = NULL;
1407 	s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
1408 	enum uclogic_params_frame_type frame_type;
1409 	/* The resulting parameters (noop) */
1410 	struct uclogic_params p = {0, };
1411 
1412 	if (!params || !hdev) {
1413 		rc = -EINVAL;
1414 		goto cleanup;
1415 	}
1416 
1417 	drvdata = hid_get_drvdata(hdev);
1418 	iface = to_usb_interface(hdev->dev.parent);
1419 	bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1420 
1421 	if (bInterfaceNumber == 0) {
1422 		rc = uclogic_params_ugee_v2_init_frame_mouse(&p);
1423 		if (rc)
1424 			goto cleanup;
1425 
1426 		goto output;
1427 	}
1428 
1429 	if (bInterfaceNumber != 2) {
1430 		uclogic_params_init_invalid(&p);
1431 		goto output;
1432 	}
1433 
1434 	/*
1435 	 * Initialize the interface by sending magic data.
1436 	 * The specific data was discovered by sniffing the Windows driver
1437 	 * traffic.
1438 	 */
1439 	rc = uclogic_probe_interface(hdev, uclogic_ugee_v2_probe_arr,
1440 				     uclogic_ugee_v2_probe_size,
1441 				     uclogic_ugee_v2_probe_endpoint);
1442 	if (rc) {
1443 		uclogic_params_init_invalid(&p);
1444 		goto output;
1445 	}
1446 
1447 	/*
1448 	 * Read the string descriptor containing pen and frame parameters.
1449 	 * The specific string descriptor and data were discovered by sniffing
1450 	 * the Windows driver traffic.
1451 	 */
1452 	rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len);
1453 	if (rc != str_desc_len) {
1454 		hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc);
1455 		uclogic_params_init_invalid(&p);
1456 		goto output;
1457 	}
1458 
1459 	rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len,
1460 					       desc_params,
1461 					       ARRAY_SIZE(desc_params),
1462 					       &frame_type);
1463 	if (rc)
1464 		goto cleanup;
1465 
1466 	kfree(str_desc);
1467 	str_desc = NULL;
1468 
1469 	/* Initialize the pen interface */
1470 	rdesc_pen = uclogic_rdesc_template_apply(
1471 				uclogic_rdesc_ugee_v2_pen_template_arr,
1472 				uclogic_rdesc_ugee_v2_pen_template_size,
1473 				desc_params, ARRAY_SIZE(desc_params));
1474 	if (!rdesc_pen) {
1475 		rc = -ENOMEM;
1476 		goto cleanup;
1477 	}
1478 
1479 	p.pen.desc_ptr = rdesc_pen;
1480 	p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size;
1481 	p.pen.id = 0x02;
1482 	p.pen.subreport_list[0].value = 0xf0;
1483 	p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
1484 
1485 	/* Initialize the frame interface */
1486 	if (drvdata->quirks & UCLOGIC_MOUSE_FRAME_QUIRK)
1487 		frame_type = UCLOGIC_PARAMS_FRAME_MOUSE;
1488 
1489 	switch (frame_type) {
1490 	case UCLOGIC_PARAMS_FRAME_DIAL:
1491 	case UCLOGIC_PARAMS_FRAME_MOUSE:
1492 		rc = uclogic_params_ugee_v2_init_frame_dial(&p, desc_params,
1493 							    ARRAY_SIZE(desc_params));
1494 		break;
1495 	case UCLOGIC_PARAMS_FRAME_BUTTONS:
1496 	default:
1497 		rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params,
1498 							       ARRAY_SIZE(desc_params));
1499 		break;
1500 	}
1501 
1502 	if (rc)
1503 		goto cleanup;
1504 
1505 	/* Initialize the battery interface*/
1506 	if (uclogic_params_ugee_v2_has_battery(hdev)) {
1507 		rc = uclogic_params_ugee_v2_init_battery(hdev, &p);
1508 		if (rc) {
1509 			hid_err(hdev, "error initializing battery: %d\n", rc);
1510 			goto cleanup;
1511 		}
1512 	}
1513 
1514 	/* Create a list of raw events to be ignored */
1515 	rc = uclogic_params_ugee_v2_init_event_hooks(hdev, &p);
1516 	if (rc) {
1517 		hid_err(hdev, "error initializing event hook list: %d\n", rc);
1518 		goto cleanup;
1519 	}
1520 
1521 output:
1522 	/* Output parameters */
1523 	memcpy(params, &p, sizeof(*params));
1524 	memset(&p, 0, sizeof(p));
1525 	rc = 0;
1526 cleanup:
1527 	kfree(str_desc);
1528 	uclogic_params_cleanup(&p);
1529 	return rc;
1530 }
1531 
1532 /**
1533  * uclogic_params_init() - initialize a tablet interface and discover its
1534  * parameters.
1535  *
1536  * @params:	Parameters to fill in (to be cleaned with
1537  *		uclogic_params_cleanup()). Not modified in case of error.
1538  *		Cannot be NULL.
1539  * @hdev:	The HID device of the tablet interface to initialize and get
1540  *		parameters from. Cannot be NULL. Must be using the USB low-level
1541  *		driver, i.e. be an actual USB tablet.
1542  *
1543  * Returns:
1544  *	Zero, if successful. A negative errno code on error.
1545  */
uclogic_params_init(struct uclogic_params * params,struct hid_device * hdev)1546 int uclogic_params_init(struct uclogic_params *params,
1547 			struct hid_device *hdev)
1548 {
1549 	int rc;
1550 	struct usb_device *udev;
1551 	__u8  bNumInterfaces;
1552 	struct usb_interface *iface;
1553 	__u8 bInterfaceNumber;
1554 	bool found;
1555 	/* The resulting parameters (noop) */
1556 	struct uclogic_params p = {0, };
1557 
1558 	/* Check arguments */
1559 	if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) {
1560 		rc = -EINVAL;
1561 		goto cleanup;
1562 	}
1563 
1564 	udev = hid_to_usb_dev(hdev);
1565 	bNumInterfaces = udev->config->desc.bNumInterfaces;
1566 	iface = to_usb_interface(hdev->dev.parent);
1567 	bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1568 
1569 	/*
1570 	 * Set replacement report descriptor if the original matches the
1571 	 * specified size. Otherwise keep interface unchanged.
1572 	 */
1573 #define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \
1574 	uclogic_params_init_with_opt_desc(                  \
1575 		&p, hdev,                                   \
1576 		UCLOGIC_RDESC_##_orig_desc_token##_SIZE,    \
1577 		uclogic_rdesc_##_new_desc_token##_arr,      \
1578 		uclogic_rdesc_##_new_desc_token##_size)
1579 
1580 #define VID_PID(_vid, _pid) \
1581 	(((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX))
1582 
1583 	/*
1584 	 * Handle specific interfaces for specific tablets.
1585 	 *
1586 	 * Observe the following logic:
1587 	 *
1588 	 * If the interface is recognized as producing certain useful input:
1589 	 *	Mark interface as valid.
1590 	 *	Output interface parameters.
1591 	 * Else, if the interface is recognized as *not* producing any useful
1592 	 * input:
1593 	 *	Mark interface as invalid.
1594 	 * Else:
1595 	 *	Mark interface as valid.
1596 	 *	Output noop parameters.
1597 	 *
1598 	 * Rule of thumb: it is better to disable a broken interface than let
1599 	 *		  it spew garbage input.
1600 	 */
1601 
1602 	switch (VID_PID(hdev->vendor, hdev->product)) {
1603 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1604 		     USB_DEVICE_ID_UCLOGIC_TABLET_PF1209):
1605 		rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed);
1606 		if (rc != 0)
1607 			goto cleanup;
1608 		break;
1609 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1610 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U):
1611 		rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed);
1612 		if (rc != 0)
1613 			goto cleanup;
1614 		break;
1615 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1616 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U):
1617 		if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) {
1618 			if (bInterfaceNumber == 0) {
1619 				/* Try to probe v1 pen parameters */
1620 				rc = uclogic_params_pen_init_v1(&p.pen,
1621 								&found, hdev);
1622 				if (rc != 0) {
1623 					hid_err(hdev,
1624 						"pen probing failed: %d\n",
1625 						rc);
1626 					goto cleanup;
1627 				}
1628 				if (!found) {
1629 					hid_warn(hdev,
1630 						 "pen parameters not found");
1631 				}
1632 			} else {
1633 				uclogic_params_init_invalid(&p);
1634 			}
1635 		} else {
1636 			rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed);
1637 			if (rc != 0)
1638 				goto cleanup;
1639 		}
1640 		break;
1641 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1642 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U):
1643 		rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed);
1644 		if (rc != 0)
1645 			goto cleanup;
1646 		break;
1647 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1648 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP1062):
1649 		rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed);
1650 		if (rc != 0)
1651 			goto cleanup;
1652 		break;
1653 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1654 		     USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850):
1655 		switch (bInterfaceNumber) {
1656 		case 0:
1657 			rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0);
1658 			if (rc != 0)
1659 				goto cleanup;
1660 			break;
1661 		case 1:
1662 			rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1);
1663 			if (rc != 0)
1664 				goto cleanup;
1665 			break;
1666 		case 2:
1667 			rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2);
1668 			if (rc != 0)
1669 				goto cleanup;
1670 			break;
1671 		}
1672 		break;
1673 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1674 		     USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60):
1675 		/*
1676 		 * If it is not a three-interface version, which is known to
1677 		 * respond to initialization.
1678 		 */
1679 		if (bNumInterfaces != 3) {
1680 			switch (bInterfaceNumber) {
1681 			case 0:
1682 				rc = WITH_OPT_DESC(TWHA60_ORIG0,
1683 							twha60_fixed0);
1684 				if (rc != 0)
1685 					goto cleanup;
1686 				break;
1687 			case 1:
1688 				rc = WITH_OPT_DESC(TWHA60_ORIG1,
1689 							twha60_fixed1);
1690 				if (rc != 0)
1691 					goto cleanup;
1692 				break;
1693 			}
1694 			break;
1695 		}
1696 		fallthrough;
1697 	case VID_PID(USB_VENDOR_ID_HUION,
1698 		     USB_DEVICE_ID_HUION_TABLET):
1699 	case VID_PID(USB_VENDOR_ID_HUION,
1700 		     USB_DEVICE_ID_HUION_TABLET2):
1701 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1702 		     USB_DEVICE_ID_HUION_TABLET):
1703 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1704 		     USB_DEVICE_ID_YIYNOVA_TABLET):
1705 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1706 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81):
1707 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1708 		     USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3):
1709 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1710 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45):
1711 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1712 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47):
1713 		rc = uclogic_params_huion_init(&p, hdev);
1714 		if (rc != 0)
1715 			goto cleanup;
1716 		break;
1717 	case VID_PID(USB_VENDOR_ID_UGTIZER,
1718 		     USB_DEVICE_ID_UGTIZER_TABLET_GP0610):
1719 	case VID_PID(USB_VENDOR_ID_UGTIZER,
1720 		     USB_DEVICE_ID_UGTIZER_TABLET_GT5040):
1721 	case VID_PID(USB_VENDOR_ID_UGEE,
1722 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
1723 	case VID_PID(USB_VENDOR_ID_UGEE,
1724 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640):
1725 	case VID_PID(USB_VENDOR_ID_UGEE,
1726 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06):
1727 	case VID_PID(USB_VENDOR_ID_UGEE,
1728 		     USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720):
1729 		/* If this is the pen interface */
1730 		if (bInterfaceNumber == 1) {
1731 			/* Probe v1 pen parameters */
1732 			rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1733 			if (rc != 0) {
1734 				hid_err(hdev, "pen probing failed: %d\n", rc);
1735 				goto cleanup;
1736 			}
1737 			if (!found) {
1738 				hid_warn(hdev, "pen parameters not found");
1739 				uclogic_params_init_invalid(&p);
1740 			}
1741 		} else {
1742 			uclogic_params_init_invalid(&p);
1743 		}
1744 		break;
1745 	case VID_PID(USB_VENDOR_ID_UGEE,
1746 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01):
1747 		/* If this is the pen and frame interface */
1748 		if (bInterfaceNumber == 1) {
1749 			/* Probe v1 pen parameters */
1750 			rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1751 			if (rc != 0) {
1752 				hid_err(hdev, "pen probing failed: %d\n", rc);
1753 				goto cleanup;
1754 			}
1755 			/* Initialize frame parameters */
1756 			rc = uclogic_params_frame_init_with_desc(
1757 				&p.frame_list[0],
1758 				uclogic_rdesc_xppen_deco01_frame_arr,
1759 				uclogic_rdesc_xppen_deco01_frame_size,
1760 				0);
1761 			if (rc != 0)
1762 				goto cleanup;
1763 		} else {
1764 			uclogic_params_init_invalid(&p);
1765 		}
1766 		break;
1767 	case VID_PID(USB_VENDOR_ID_UGEE,
1768 		     USB_DEVICE_ID_UGEE_PARBLO_A610_PRO):
1769 	case VID_PID(USB_VENDOR_ID_UGEE,
1770 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2):
1771 	case VID_PID(USB_VENDOR_ID_UGEE,
1772 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L):
1773 	case VID_PID(USB_VENDOR_ID_UGEE,
1774 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW):
1775 	case VID_PID(USB_VENDOR_ID_UGEE,
1776 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S):
1777 	case VID_PID(USB_VENDOR_ID_UGEE,
1778 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW):
1779 		rc = uclogic_params_ugee_v2_init(&p, hdev);
1780 		if (rc != 0)
1781 			goto cleanup;
1782 		break;
1783 	case VID_PID(USB_VENDOR_ID_TRUST,
1784 		     USB_DEVICE_ID_TRUST_PANORA_TABLET):
1785 	case VID_PID(USB_VENDOR_ID_UGEE,
1786 		     USB_DEVICE_ID_UGEE_TABLET_G5):
1787 		/* Ignore non-pen interfaces */
1788 		if (bInterfaceNumber != 1) {
1789 			uclogic_params_init_invalid(&p);
1790 			break;
1791 		}
1792 
1793 		rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1794 		if (rc != 0) {
1795 			hid_err(hdev, "pen probing failed: %d\n", rc);
1796 			goto cleanup;
1797 		} else if (found) {
1798 			rc = uclogic_params_frame_init_with_desc(
1799 				&p.frame_list[0],
1800 				uclogic_rdesc_ugee_g5_frame_arr,
1801 				uclogic_rdesc_ugee_g5_frame_size,
1802 				UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
1803 			if (rc != 0) {
1804 				hid_err(hdev,
1805 					"failed creating frame parameters: %d\n",
1806 					rc);
1807 				goto cleanup;
1808 			}
1809 			p.frame_list[0].re_lsb =
1810 				UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
1811 			p.frame_list[0].dev_id_byte =
1812 				UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
1813 		} else {
1814 			hid_warn(hdev, "pen parameters not found");
1815 			uclogic_params_init_invalid(&p);
1816 		}
1817 
1818 		break;
1819 	case VID_PID(USB_VENDOR_ID_UGEE,
1820 		     USB_DEVICE_ID_UGEE_TABLET_EX07S):
1821 		/* Ignore non-pen interfaces */
1822 		if (bInterfaceNumber != 1) {
1823 			uclogic_params_init_invalid(&p);
1824 			break;
1825 		}
1826 
1827 		rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1828 		if (rc != 0) {
1829 			hid_err(hdev, "pen probing failed: %d\n", rc);
1830 			goto cleanup;
1831 		} else if (found) {
1832 			rc = uclogic_params_frame_init_with_desc(
1833 				&p.frame_list[0],
1834 				uclogic_rdesc_ugee_ex07_frame_arr,
1835 				uclogic_rdesc_ugee_ex07_frame_size,
1836 				0);
1837 			if (rc != 0) {
1838 				hid_err(hdev,
1839 					"failed creating frame parameters: %d\n",
1840 					rc);
1841 				goto cleanup;
1842 			}
1843 		} else {
1844 			hid_warn(hdev, "pen parameters not found");
1845 			uclogic_params_init_invalid(&p);
1846 		}
1847 
1848 		break;
1849 	}
1850 
1851 #undef VID_PID
1852 #undef WITH_OPT_DESC
1853 
1854 	/* Output parameters */
1855 	memcpy(params, &p, sizeof(*params));
1856 	memset(&p, 0, sizeof(p));
1857 	rc = 0;
1858 cleanup:
1859 	uclogic_params_cleanup(&p);
1860 	return rc;
1861 }
1862 
1863 #ifdef CONFIG_HID_KUNIT_TEST
1864 #include "hid-uclogic-params-test.c"
1865 #endif
1866