Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
   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