xref: /linux/drivers/hid/hid-uclogic-params.c (revision 0678f5630429a5049d7663703b897e1bf8d13cd1)
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 #include <linux/string_choices.h>
24 
25 /**
26  * uclogic_params_pen_inrange_to_str() - Convert a pen in-range reporting type
27  *                                       to a string.
28  * @inrange:	The in-range reporting type to convert.
29  *
30  * Return:
31  * * The string representing the type, or
32  * * %NULL if the type is unknown.
33  */
uclogic_params_pen_inrange_to_str(enum uclogic_params_pen_inrange inrange)34 static const char *uclogic_params_pen_inrange_to_str(
35 				enum uclogic_params_pen_inrange inrange)
36 {
37 	switch (inrange) {
38 	case UCLOGIC_PARAMS_PEN_INRANGE_NORMAL:
39 		return "normal";
40 	case UCLOGIC_PARAMS_PEN_INRANGE_INVERTED:
41 		return "inverted";
42 	case UCLOGIC_PARAMS_PEN_INRANGE_NONE:
43 		return "none";
44 	default:
45 		return NULL;
46 	}
47 }
48 
49 /**
50  * uclogic_params_pen_hid_dbg() - Dump tablet interface pen parameters
51  * @hdev:	The HID device the pen parameters describe.
52  * @pen:	The pen parameters to dump.
53  *
54  * Dump tablet interface pen parameters with hid_dbg(). The dump is indented
55  * with a tab.
56  */
uclogic_params_pen_hid_dbg(const struct hid_device * hdev,const struct uclogic_params_pen * pen)57 static void uclogic_params_pen_hid_dbg(const struct hid_device *hdev,
58 					const struct uclogic_params_pen *pen)
59 {
60 	size_t i;
61 
62 	hid_dbg(hdev, "\t.usage_invalid = %s\n",
63 		str_true_false(pen->usage_invalid));
64 	hid_dbg(hdev, "\t.desc_ptr = %p\n", pen->desc_ptr);
65 	hid_dbg(hdev, "\t.desc_size = %u\n", pen->desc_size);
66 	hid_dbg(hdev, "\t.id = %u\n", pen->id);
67 	hid_dbg(hdev, "\t.subreport_list = {\n");
68 	for (i = 0; i < ARRAY_SIZE(pen->subreport_list); i++) {
69 		hid_dbg(hdev, "\t\t{0x%02hhx, %hhu}%s\n",
70 			pen->subreport_list[i].value,
71 			pen->subreport_list[i].id,
72 			i < (ARRAY_SIZE(pen->subreport_list) - 1) ? "," : "");
73 	}
74 	hid_dbg(hdev, "\t}\n");
75 	hid_dbg(hdev, "\t.inrange = %s\n",
76 		uclogic_params_pen_inrange_to_str(pen->inrange));
77 	hid_dbg(hdev, "\t.fragmented_hires = %s\n",
78 		str_true_false(pen->fragmented_hires));
79 	hid_dbg(hdev, "\t.tilt_y_flipped = %s\n",
80 		str_true_false(pen->tilt_y_flipped));
81 }
82 
83 /**
84  * uclogic_params_frame_hid_dbg() - Dump tablet interface frame parameters
85  * @hdev:	The HID device the pen parameters describe.
86  * @frame:	The frame parameters to dump.
87  *
88  * Dump tablet interface frame parameters with hid_dbg(). The dump is
89  * indented with two tabs.
90  */
uclogic_params_frame_hid_dbg(const struct hid_device * hdev,const struct uclogic_params_frame * frame)91 static void uclogic_params_frame_hid_dbg(
92 				const struct hid_device *hdev,
93 				const struct uclogic_params_frame *frame)
94 {
95 	hid_dbg(hdev, "\t\t.desc_ptr = %p\n", frame->desc_ptr);
96 	hid_dbg(hdev, "\t\t.desc_size = %u\n", frame->desc_size);
97 	hid_dbg(hdev, "\t\t.id = %u\n", frame->id);
98 	hid_dbg(hdev, "\t\t.suffix = %s\n", frame->suffix);
99 	hid_dbg(hdev, "\t\t.re_lsb = %u\n", frame->re_lsb);
100 	hid_dbg(hdev, "\t\t.dev_id_byte = %u\n", frame->dev_id_byte);
101 	hid_dbg(hdev, "\t\t.touch_byte = %u\n", frame->touch_byte);
102 	hid_dbg(hdev, "\t\t.touch_max = %hhd\n", frame->touch_max);
103 	hid_dbg(hdev, "\t\t.touch_flip_at = %hhd\n",
104 		frame->touch_flip_at);
105 	hid_dbg(hdev, "\t\t.bitmap_dial_byte = %u\n",
106 		frame->bitmap_dial_byte);
107 	hid_dbg(hdev, "\t\t.bitmap_second_dial_destination_byte = %u\n",
108 			frame->bitmap_second_dial_destination_byte);
109 }
110 
111 /**
112  * uclogic_params_hid_dbg() - Dump tablet interface parameters
113  * @hdev:	The HID device the parameters describe.
114  * @params:	The parameters to dump.
115  *
116  * Dump tablet interface parameters with hid_dbg().
117  */
uclogic_params_hid_dbg(const struct hid_device * hdev,const struct uclogic_params * params)118 void uclogic_params_hid_dbg(const struct hid_device *hdev,
119 				const struct uclogic_params *params)
120 {
121 	size_t i;
122 
123 	hid_dbg(hdev, ".invalid = %s\n", str_true_false(params->invalid));
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 		kfree(event_hook);
1374 		return -ENOMEM;
1375 	}
1376 
1377 	list_add_tail(&event_hook->list, &p->event_hooks->list);
1378 
1379 	return 0;
1380 }
1381 
1382 /**
1383  * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by
1384  * discovering their parameters.
1385  *
1386  * These tables, internally designed as v2 to differentiate them from older
1387  * models, expect a payload of magic data in orther to be switched to the fully
1388  * functional mode and expose their parameters in a similar way to the
1389  * information present in uclogic_params_pen_init_v1() but with some
1390  * differences.
1391  *
1392  * @params:	Parameters to fill in (to be cleaned with
1393  *		uclogic_params_cleanup()). Not modified in case of error.
1394  *		Cannot be NULL.
1395  * @hdev:	The HID device of the tablet interface to initialize and get
1396  *		parameters from. Cannot be NULL.
1397  *
1398  * Returns:
1399  *	Zero, if successful. A negative errno code on error.
1400  */
uclogic_params_ugee_v2_init(struct uclogic_params * params,struct hid_device * hdev)1401 static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
1402 				       struct hid_device *hdev)
1403 {
1404 	int rc = 0;
1405 	struct uclogic_drvdata *drvdata;
1406 	struct usb_interface *iface;
1407 	__u8 bInterfaceNumber;
1408 	const int str_desc_len = 12;
1409 	__u8 *str_desc = NULL;
1410 	__u8 *rdesc_pen = NULL;
1411 	s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
1412 	enum uclogic_params_frame_type frame_type;
1413 	/* The resulting parameters (noop) */
1414 	struct uclogic_params p = {0, };
1415 
1416 	if (!params || !hdev) {
1417 		rc = -EINVAL;
1418 		goto cleanup;
1419 	}
1420 
1421 	drvdata = hid_get_drvdata(hdev);
1422 	iface = to_usb_interface(hdev->dev.parent);
1423 	bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1424 
1425 	if (bInterfaceNumber == 0) {
1426 		rc = uclogic_params_ugee_v2_init_frame_mouse(&p);
1427 		if (rc)
1428 			goto cleanup;
1429 
1430 		goto output;
1431 	}
1432 
1433 	if (bInterfaceNumber != 2) {
1434 		uclogic_params_init_invalid(&p);
1435 		goto output;
1436 	}
1437 
1438 	/*
1439 	 * Initialize the interface by sending magic data.
1440 	 * The specific data was discovered by sniffing the Windows driver
1441 	 * traffic.
1442 	 */
1443 	rc = uclogic_probe_interface(hdev, uclogic_ugee_v2_probe_arr,
1444 				     uclogic_ugee_v2_probe_size,
1445 				     uclogic_ugee_v2_probe_endpoint);
1446 	if (rc) {
1447 		uclogic_params_init_invalid(&p);
1448 		goto output;
1449 	}
1450 
1451 	/*
1452 	 * Read the string descriptor containing pen and frame parameters.
1453 	 * The specific string descriptor and data were discovered by sniffing
1454 	 * the Windows driver traffic.
1455 	 */
1456 	rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len);
1457 	if (rc != str_desc_len) {
1458 		hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc);
1459 		uclogic_params_init_invalid(&p);
1460 		goto output;
1461 	}
1462 
1463 	rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len,
1464 					       desc_params,
1465 					       ARRAY_SIZE(desc_params),
1466 					       &frame_type);
1467 	if (rc)
1468 		goto cleanup;
1469 
1470 	kfree(str_desc);
1471 	str_desc = NULL;
1472 
1473 	/* Initialize the pen interface */
1474 	rdesc_pen = uclogic_rdesc_template_apply(
1475 				uclogic_rdesc_ugee_v2_pen_template_arr,
1476 				uclogic_rdesc_ugee_v2_pen_template_size,
1477 				desc_params, ARRAY_SIZE(desc_params));
1478 	if (!rdesc_pen) {
1479 		rc = -ENOMEM;
1480 		goto cleanup;
1481 	}
1482 
1483 	p.pen.desc_ptr = rdesc_pen;
1484 	p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size;
1485 	p.pen.id = 0x02;
1486 	p.pen.subreport_list[0].value = 0xf0;
1487 	p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
1488 
1489 	/* Initialize the frame interface */
1490 	if (drvdata->quirks & UCLOGIC_MOUSE_FRAME_QUIRK)
1491 		frame_type = UCLOGIC_PARAMS_FRAME_MOUSE;
1492 
1493 	switch (frame_type) {
1494 	case UCLOGIC_PARAMS_FRAME_DIAL:
1495 	case UCLOGIC_PARAMS_FRAME_MOUSE:
1496 		rc = uclogic_params_ugee_v2_init_frame_dial(&p, desc_params,
1497 							    ARRAY_SIZE(desc_params));
1498 		break;
1499 	case UCLOGIC_PARAMS_FRAME_BUTTONS:
1500 	default:
1501 		rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params,
1502 							       ARRAY_SIZE(desc_params));
1503 		break;
1504 	}
1505 
1506 	if (rc)
1507 		goto cleanup;
1508 
1509 	/* Initialize the battery interface*/
1510 	if (uclogic_params_ugee_v2_has_battery(hdev)) {
1511 		rc = uclogic_params_ugee_v2_init_battery(hdev, &p);
1512 		if (rc) {
1513 			hid_err(hdev, "error initializing battery: %d\n", rc);
1514 			goto cleanup;
1515 		}
1516 	}
1517 
1518 	/* Create a list of raw events to be ignored */
1519 	rc = uclogic_params_ugee_v2_init_event_hooks(hdev, &p);
1520 	if (rc) {
1521 		hid_err(hdev, "error initializing event hook list: %d\n", rc);
1522 		goto cleanup;
1523 	}
1524 
1525 output:
1526 	/* Output parameters */
1527 	memcpy(params, &p, sizeof(*params));
1528 	memset(&p, 0, sizeof(p));
1529 	rc = 0;
1530 cleanup:
1531 	kfree(str_desc);
1532 	uclogic_params_cleanup(&p);
1533 	return rc;
1534 }
1535 
1536 /*
1537  * uclogic_params_init_ugee_xppen_pro_22r() - Initializes a UGEE XP-Pen Pro 22R tablet device.
1538  *
1539  * @hdev:	The HID device of the tablet interface to initialize and get
1540  *		parameters from. Cannot be NULL.
1541  * @params:	Parameters to fill in (to be cleaned with
1542  *		uclogic_params_cleanup()). Not modified in case of error.
1543  *		Cannot be NULL.
1544  *
1545  * Returns:
1546  *	Zero, if successful. A negative errno code on error.
1547  */
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)1548 static int uclogic_params_init_ugee_xppen_pro_22r(struct uclogic_params *params,
1549 						  struct hid_device *hdev,
1550 						  const u8 rdesc_frame_arr[],
1551 						  const size_t rdesc_frame_size)
1552 {
1553 	int rc = 0;
1554 	struct usb_interface *iface;
1555 	__u8 bInterfaceNumber;
1556 	const int str_desc_len = 12;
1557 	u8 *str_desc = NULL;
1558 	__u8 *rdesc_pen = NULL;
1559 	s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
1560 	enum uclogic_params_frame_type frame_type;
1561 	/* The resulting parameters (noop) */
1562 	struct uclogic_params p = {0, };
1563 
1564 	if (!hdev || !params) {
1565 		rc = -EINVAL;
1566 		goto cleanup;
1567 	}
1568 
1569 	iface = to_usb_interface(hdev->dev.parent);
1570 	bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1571 
1572 	/* Ignore non-pen interfaces */
1573 	if (bInterfaceNumber != 2) {
1574 		rc = -EINVAL;
1575 		uclogic_params_init_invalid(&p);
1576 		goto cleanup;
1577 	}
1578 
1579 	/*
1580 	 * Initialize the interface by sending magic data.
1581 	 * This magic data is the same as other UGEE v2 tablets.
1582 	 */
1583 	rc = uclogic_probe_interface(hdev,
1584 				     uclogic_ugee_v2_probe_arr,
1585 				     uclogic_ugee_v2_probe_size,
1586 				     uclogic_ugee_v2_probe_endpoint);
1587 	if (rc) {
1588 		uclogic_params_init_invalid(&p);
1589 		goto cleanup;
1590 	}
1591 
1592 	/**
1593 	 * Read the string descriptor containing pen and frame parameters.
1594 	 * These are slightly different than typical UGEE v2 devices.
1595 	 */
1596 	rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len);
1597 	if (rc != str_desc_len) {
1598 		rc = (rc < 0) ? rc : -EINVAL;
1599 		hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc);
1600 		uclogic_params_init_invalid(&p);
1601 		goto cleanup;
1602 	}
1603 
1604 	rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len,
1605 					       desc_params,
1606 					       ARRAY_SIZE(desc_params),
1607 					       &frame_type);
1608 	if (rc)
1609 		goto cleanup;
1610 
1611 	// str_desc doesn't report the correct amount of buttons, so manually fix it
1612 	desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 20;
1613 
1614 	kfree(str_desc);
1615 	str_desc = NULL;
1616 
1617 	/* Initialize the pen interface */
1618 	rdesc_pen = uclogic_rdesc_template_apply(
1619 				uclogic_rdesc_ugee_v2_pen_template_arr,
1620 				uclogic_rdesc_ugee_v2_pen_template_size,
1621 				desc_params, ARRAY_SIZE(desc_params));
1622 	if (!rdesc_pen) {
1623 		rc = -ENOMEM;
1624 		goto cleanup;
1625 	}
1626 
1627 	p.pen.desc_ptr = rdesc_pen;
1628 	p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size;
1629 	p.pen.id = 0x02;
1630 	p.pen.subreport_list[0].value = 0xf0;
1631 	p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
1632 
1633 	/* Initialize the frame interface */
1634 	rc = uclogic_params_frame_init_with_desc(
1635 		&p.frame_list[0],
1636 		rdesc_frame_arr,
1637 		rdesc_frame_size,
1638 		UCLOGIC_RDESC_V1_FRAME_ID);
1639 	if (rc < 0) {
1640 		hid_err(hdev, "initializing frame params failed: %d\n", rc);
1641 		goto cleanup;
1642 	}
1643 
1644 	p.frame_list[0].bitmap_dial_byte = 7;
1645 	p.frame_list[0].bitmap_second_dial_destination_byte = 8;
1646 
1647 	/* Output parameters */
1648 	memcpy(params, &p, sizeof(*params));
1649 	memset(&p, 0, sizeof(p));
1650 cleanup:
1651 	kfree(str_desc);
1652 	uclogic_params_cleanup(&p);
1653 	return rc;
1654 }
1655 
1656 /**
1657  * uclogic_params_init() - initialize a tablet interface and discover its
1658  * parameters.
1659  *
1660  * @params:	Parameters to fill in (to be cleaned with
1661  *		uclogic_params_cleanup()). Not modified in case of error.
1662  *		Cannot be NULL.
1663  * @hdev:	The HID device of the tablet interface to initialize and get
1664  *		parameters from. Cannot be NULL. Must be using the USB low-level
1665  *		driver, i.e. be an actual USB tablet.
1666  *
1667  * Returns:
1668  *	Zero, if successful. A negative errno code on error.
1669  */
uclogic_params_init(struct uclogic_params * params,struct hid_device * hdev)1670 int uclogic_params_init(struct uclogic_params *params,
1671 			struct hid_device *hdev)
1672 {
1673 	int rc;
1674 	struct usb_device *udev;
1675 	__u8  bNumInterfaces;
1676 	struct usb_interface *iface;
1677 	__u8 bInterfaceNumber;
1678 	bool found;
1679 	/* The resulting parameters (noop) */
1680 	struct uclogic_params p = {0, };
1681 
1682 	/* Check arguments */
1683 	if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) {
1684 		rc = -EINVAL;
1685 		goto cleanup;
1686 	}
1687 
1688 	udev = hid_to_usb_dev(hdev);
1689 	bNumInterfaces = udev->config->desc.bNumInterfaces;
1690 	iface = to_usb_interface(hdev->dev.parent);
1691 	bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1692 
1693 	/*
1694 	 * Set replacement report descriptor if the original matches the
1695 	 * specified size. Otherwise keep interface unchanged.
1696 	 */
1697 #define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \
1698 	uclogic_params_init_with_opt_desc(                  \
1699 		&p, hdev,                                   \
1700 		UCLOGIC_RDESC_##_orig_desc_token##_SIZE,    \
1701 		uclogic_rdesc_##_new_desc_token##_arr,      \
1702 		uclogic_rdesc_##_new_desc_token##_size)
1703 
1704 #define VID_PID(_vid, _pid) \
1705 	(((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX))
1706 
1707 	/*
1708 	 * Handle specific interfaces for specific tablets.
1709 	 *
1710 	 * Observe the following logic:
1711 	 *
1712 	 * If the interface is recognized as producing certain useful input:
1713 	 *	Mark interface as valid.
1714 	 *	Output interface parameters.
1715 	 * Else, if the interface is recognized as *not* producing any useful
1716 	 * input:
1717 	 *	Mark interface as invalid.
1718 	 * Else:
1719 	 *	Mark interface as valid.
1720 	 *	Output noop parameters.
1721 	 *
1722 	 * Rule of thumb: it is better to disable a broken interface than let
1723 	 *		  it spew garbage input.
1724 	 */
1725 
1726 	switch (VID_PID(hdev->vendor, hdev->product)) {
1727 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1728 		     USB_DEVICE_ID_UCLOGIC_TABLET_PF1209):
1729 		rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed);
1730 		if (rc != 0)
1731 			goto cleanup;
1732 		break;
1733 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1734 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U):
1735 		rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed);
1736 		if (rc != 0)
1737 			goto cleanup;
1738 		break;
1739 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1740 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U):
1741 		if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) {
1742 			if (bInterfaceNumber == 0) {
1743 				/* Try to probe v1 pen parameters */
1744 				rc = uclogic_params_pen_init_v1(&p.pen,
1745 								&found, hdev);
1746 				if (rc != 0) {
1747 					hid_err(hdev,
1748 						"pen probing failed: %d\n",
1749 						rc);
1750 					goto cleanup;
1751 				}
1752 				if (!found) {
1753 					hid_warn(hdev,
1754 						 "pen parameters not found");
1755 				}
1756 			} else {
1757 				uclogic_params_init_invalid(&p);
1758 			}
1759 		} else {
1760 			rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed);
1761 			if (rc != 0)
1762 				goto cleanup;
1763 		}
1764 		break;
1765 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1766 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U):
1767 		rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed);
1768 		if (rc != 0)
1769 			goto cleanup;
1770 		break;
1771 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1772 		     USB_DEVICE_ID_UCLOGIC_TABLET_WP1062):
1773 		rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed);
1774 		if (rc != 0)
1775 			goto cleanup;
1776 		break;
1777 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1778 		     USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850):
1779 		switch (bInterfaceNumber) {
1780 		case 0:
1781 			rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0);
1782 			if (rc != 0)
1783 				goto cleanup;
1784 			break;
1785 		case 1:
1786 			rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1);
1787 			if (rc != 0)
1788 				goto cleanup;
1789 			break;
1790 		case 2:
1791 			rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2);
1792 			if (rc != 0)
1793 				goto cleanup;
1794 			break;
1795 		}
1796 		break;
1797 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1798 		     USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60):
1799 		/*
1800 		 * If it is not a three-interface version, which is known to
1801 		 * respond to initialization.
1802 		 */
1803 		if (bNumInterfaces != 3) {
1804 			switch (bInterfaceNumber) {
1805 			case 0:
1806 				rc = WITH_OPT_DESC(TWHA60_ORIG0,
1807 							twha60_fixed0);
1808 				if (rc != 0)
1809 					goto cleanup;
1810 				break;
1811 			case 1:
1812 				rc = WITH_OPT_DESC(TWHA60_ORIG1,
1813 							twha60_fixed1);
1814 				if (rc != 0)
1815 					goto cleanup;
1816 				break;
1817 			}
1818 			break;
1819 		}
1820 		fallthrough;
1821 	case VID_PID(USB_VENDOR_ID_HUION,
1822 		     USB_DEVICE_ID_HUION_TABLET):
1823 	case VID_PID(USB_VENDOR_ID_HUION,
1824 		     USB_DEVICE_ID_HUION_TABLET2):
1825 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1826 		     USB_DEVICE_ID_HUION_TABLET):
1827 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1828 		     USB_DEVICE_ID_YIYNOVA_TABLET):
1829 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1830 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81):
1831 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1832 		     USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3):
1833 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1834 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45):
1835 	case VID_PID(USB_VENDOR_ID_UCLOGIC,
1836 		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47):
1837 		rc = uclogic_params_huion_init(&p, hdev);
1838 		if (rc != 0)
1839 			goto cleanup;
1840 		break;
1841 	case VID_PID(USB_VENDOR_ID_UGTIZER,
1842 		     USB_DEVICE_ID_UGTIZER_TABLET_GP0610):
1843 	case VID_PID(USB_VENDOR_ID_UGTIZER,
1844 		     USB_DEVICE_ID_UGTIZER_TABLET_GT5040):
1845 	case VID_PID(USB_VENDOR_ID_UGEE,
1846 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
1847 	case VID_PID(USB_VENDOR_ID_UGEE,
1848 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640):
1849 	case VID_PID(USB_VENDOR_ID_UGEE,
1850 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06):
1851 	case VID_PID(USB_VENDOR_ID_UGEE,
1852 		     USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720):
1853 		/* If this is the pen interface */
1854 		if (bInterfaceNumber == 1) {
1855 			/* Probe v1 pen parameters */
1856 			rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1857 			if (rc != 0) {
1858 				hid_err(hdev, "pen probing failed: %d\n", rc);
1859 				goto cleanup;
1860 			}
1861 			if (!found) {
1862 				hid_warn(hdev, "pen parameters not found");
1863 				uclogic_params_init_invalid(&p);
1864 			}
1865 		} else {
1866 			uclogic_params_init_invalid(&p);
1867 		}
1868 		break;
1869 	case VID_PID(USB_VENDOR_ID_UGEE,
1870 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01):
1871 		/* If this is the pen and frame interface */
1872 		if (bInterfaceNumber == 1) {
1873 			/* Probe v1 pen parameters */
1874 			rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1875 			if (rc != 0) {
1876 				hid_err(hdev, "pen probing failed: %d\n", rc);
1877 				goto cleanup;
1878 			}
1879 			/* Initialize frame parameters */
1880 			rc = uclogic_params_frame_init_with_desc(
1881 				&p.frame_list[0],
1882 				uclogic_rdesc_xppen_deco01_frame_arr,
1883 				uclogic_rdesc_xppen_deco01_frame_size,
1884 				0);
1885 			if (rc != 0)
1886 				goto cleanup;
1887 		} else {
1888 			uclogic_params_init_invalid(&p);
1889 		}
1890 		break;
1891 	case VID_PID(USB_VENDOR_ID_UGEE,
1892 		     USB_DEVICE_ID_UGEE_PARBLO_A610_PRO):
1893 	case VID_PID(USB_VENDOR_ID_UGEE,
1894 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2):
1895 	case VID_PID(USB_VENDOR_ID_UGEE,
1896 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L):
1897 	case VID_PID(USB_VENDOR_ID_UGEE,
1898 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW):
1899 	case VID_PID(USB_VENDOR_ID_UGEE,
1900 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S):
1901 	case VID_PID(USB_VENDOR_ID_UGEE,
1902 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW):
1903 		rc = uclogic_params_ugee_v2_init(&p, hdev);
1904 		if (rc != 0)
1905 			goto cleanup;
1906 		break;
1907 	case VID_PID(USB_VENDOR_ID_TRUST,
1908 		     USB_DEVICE_ID_TRUST_PANORA_TABLET):
1909 	case VID_PID(USB_VENDOR_ID_UGEE,
1910 		     USB_DEVICE_ID_UGEE_TABLET_G5):
1911 		/* Ignore non-pen interfaces */
1912 		if (bInterfaceNumber != 1) {
1913 			uclogic_params_init_invalid(&p);
1914 			break;
1915 		}
1916 
1917 		rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1918 		if (rc != 0) {
1919 			hid_err(hdev, "pen probing failed: %d\n", rc);
1920 			goto cleanup;
1921 		} else if (found) {
1922 			rc = uclogic_params_frame_init_with_desc(
1923 				&p.frame_list[0],
1924 				uclogic_rdesc_ugee_g5_frame_arr,
1925 				uclogic_rdesc_ugee_g5_frame_size,
1926 				UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
1927 			if (rc != 0) {
1928 				hid_err(hdev,
1929 					"failed creating frame parameters: %d\n",
1930 					rc);
1931 				goto cleanup;
1932 			}
1933 			p.frame_list[0].re_lsb =
1934 				UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
1935 			p.frame_list[0].dev_id_byte =
1936 				UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
1937 		} else {
1938 			hid_warn(hdev, "pen parameters not found");
1939 			uclogic_params_init_invalid(&p);
1940 		}
1941 
1942 		break;
1943 	case VID_PID(USB_VENDOR_ID_UGEE,
1944 		     USB_DEVICE_ID_UGEE_TABLET_EX07S):
1945 		/* Ignore non-pen interfaces */
1946 		if (bInterfaceNumber != 1) {
1947 			uclogic_params_init_invalid(&p);
1948 			break;
1949 		}
1950 
1951 		rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1952 		if (rc != 0) {
1953 			hid_err(hdev, "pen probing failed: %d\n", rc);
1954 			goto cleanup;
1955 		} else if (found) {
1956 			rc = uclogic_params_frame_init_with_desc(
1957 				&p.frame_list[0],
1958 				uclogic_rdesc_ugee_ex07_frame_arr,
1959 				uclogic_rdesc_ugee_ex07_frame_size,
1960 				0);
1961 			if (rc != 0) {
1962 				hid_err(hdev,
1963 					"failed creating frame parameters: %d\n",
1964 					rc);
1965 				goto cleanup;
1966 			}
1967 		} else {
1968 			hid_warn(hdev, "pen parameters not found");
1969 			uclogic_params_init_invalid(&p);
1970 		}
1971 
1972 		break;
1973 	case VID_PID(USB_VENDOR_ID_UGEE,
1974 			USB_DEVICE_ID_UGEE_XPPEN_TABLET_22R_PRO):
1975 		rc = uclogic_params_init_ugee_xppen_pro_22r(&p,
1976 			hdev,
1977 			uclogic_rdesc_xppen_artist_22r_pro_frame_arr,
1978 			uclogic_rdesc_xppen_artist_22r_pro_frame_size);
1979 		if (rc != 0)
1980 			goto cleanup;
1981 
1982 		break;
1983 	}
1984 
1985 #undef VID_PID
1986 #undef WITH_OPT_DESC
1987 
1988 	/* Output parameters */
1989 	memcpy(params, &p, sizeof(*params));
1990 	memset(&p, 0, sizeof(p));
1991 	rc = 0;
1992 cleanup:
1993 	uclogic_params_cleanup(&p);
1994 	return rc;
1995 }
1996 
1997 #ifdef CONFIG_HID_KUNIT_TEST
1998 #include "hid-uclogic-params-test.c"
1999 #endif
2000