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