File Index
Files and directories
Sign in
FILE

hid-uclogic-params.c

File preview with syntax highlighting.

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