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