Linux Audio

Check our new training course

Loading...
v6.8
   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
v5.14.15
   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 <asm/unaligned.h>
  22
  23/**
  24 * uclogic_params_pen_inrange_to_str() - Convert a pen in-range reporting type
  25 *                                       to a string.
  26 *
  27 * @inrange:	The in-range reporting type to convert.
  28 *
  29 * Returns:
  30 *	The string representing the type, or NULL if the type is unknown.
 
  31 */
  32const char *uclogic_params_pen_inrange_to_str(
  33			enum uclogic_params_pen_inrange inrange)
  34{
  35	switch (inrange) {
  36	case UCLOGIC_PARAMS_PEN_INRANGE_NORMAL:
  37		return "normal";
  38	case UCLOGIC_PARAMS_PEN_INRANGE_INVERTED:
  39		return "inverted";
  40	case UCLOGIC_PARAMS_PEN_INRANGE_NONE:
  41		return "none";
  42	default:
  43		return NULL;
  44	}
  45}
  46
  47/**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  48 * uclogic_params_get_str_desc - retrieve a string descriptor from a HID
  49 * device interface, putting it into a kmalloc-allocated buffer as is, without
  50 * character encoding conversion.
  51 *
  52 * @pbuf:	Location for the kmalloc-allocated buffer pointer containing
  53 *		the retrieved descriptor. Not modified in case of error.
  54 *		Can be NULL to have retrieved descriptor discarded.
  55 * @hdev:	The HID device of the tablet interface to retrieve the string
  56 *		descriptor from. Cannot be NULL.
  57 * @idx:	Index of the string descriptor to request from the device.
  58 * @len:	Length of the buffer to allocate and the data to retrieve.
  59 *
  60 * Returns:
  61 *	number of bytes retrieved (<= len),
  62 *	-EPIPE, if the descriptor was not found, or
  63 *	another negative errno code in case of other error.
  64 */
  65static int uclogic_params_get_str_desc(__u8 **pbuf, struct hid_device *hdev,
  66					__u8 idx, size_t len)
  67{
  68	int rc;
  69	struct usb_device *udev = hid_to_usb_dev(hdev);
  70	__u8 *buf = NULL;
  71
  72	/* Check arguments */
  73	if (hdev == NULL) {
  74		rc = -EINVAL;
  75		goto cleanup;
  76	}
  77
 
 
  78	buf = kmalloc(len, GFP_KERNEL);
  79	if (buf == NULL) {
  80		rc = -ENOMEM;
  81		goto cleanup;
  82	}
  83
  84	rc = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
  85				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
  86				(USB_DT_STRING << 8) + idx,
  87				0x0409, buf, len,
  88				USB_CTRL_GET_TIMEOUT);
  89	if (rc == -EPIPE) {
  90		hid_dbg(hdev, "string descriptor #%hhu not found\n", idx);
  91		goto cleanup;
  92	} else if (rc < 0) {
  93		hid_err(hdev,
  94			"failed retrieving string descriptor #%u: %d\n",
  95			idx, rc);
  96		goto cleanup;
  97	}
  98
  99	if (pbuf != NULL) {
 100		*pbuf = buf;
 101		buf = NULL;
 102	}
 103
 104cleanup:
 105	kfree(buf);
 106	return rc;
 107}
 108
 109/**
 110 * uclogic_params_pen_cleanup - free resources used by struct
 111 * uclogic_params_pen (tablet interface's pen input parameters).
 112 * Can be called repeatedly.
 113 *
 114 * @pen:	Pen input parameters to cleanup. Cannot be NULL.
 115 */
 116static void uclogic_params_pen_cleanup(struct uclogic_params_pen *pen)
 117{
 118	kfree(pen->desc_ptr);
 119	memset(pen, 0, sizeof(*pen));
 120}
 121
 122/**
 123 * uclogic_params_pen_init_v1() - initialize tablet interface pen
 124 * input and retrieve its parameters from the device, using v1 protocol.
 125 *
 126 * @pen:	Pointer to the pen parameters to initialize (to be
 127 *		cleaned up with uclogic_params_pen_cleanup()). Not modified in
 128 *		case of error, or if parameters are not found. Cannot be NULL.
 129 * @pfound:	Location for a flag which is set to true if the parameters
 130 *		were found, and to false if not (e.g. device was
 131 *		incompatible). Not modified in case of error. Cannot be NULL.
 132 * @hdev:	The HID device of the tablet interface to initialize and get
 133 *		parameters from. Cannot be NULL.
 134 *
 135 * Returns:
 136 *	Zero, if successful. A negative errno code on error.
 137 */
 138static int uclogic_params_pen_init_v1(struct uclogic_params_pen *pen,
 139				      bool *pfound,
 140				      struct hid_device *hdev)
 141{
 142	int rc;
 143	bool found = false;
 144	/* Buffer for (part of) the string descriptor */
 145	__u8 *buf = NULL;
 146	/* Minimum descriptor length required, maximum seen so far is 18 */
 147	const int len = 12;
 148	s32 resolution;
 149	/* Pen report descriptor template parameters */
 150	s32 desc_params[UCLOGIC_RDESC_PEN_PH_ID_NUM];
 151	__u8 *desc_ptr = NULL;
 152
 153	/* Check arguments */
 154	if (pen == NULL || pfound == NULL || hdev == NULL) {
 155		rc = -EINVAL;
 156		goto cleanup;
 157	}
 158
 159	/*
 160	 * Read string descriptor containing pen input parameters.
 161	 * The specific string descriptor and data were discovered by sniffing
 162	 * the Windows driver traffic.
 163	 * NOTE: This enables fully-functional tablet mode.
 164	 */
 165	rc = uclogic_params_get_str_desc(&buf, hdev, 100, len);
 166	if (rc == -EPIPE) {
 167		hid_dbg(hdev,
 168			"string descriptor with pen parameters not found, assuming not compatible\n");
 169		goto finish;
 170	} else if (rc < 0) {
 171		hid_err(hdev, "failed retrieving pen parameters: %d\n", rc);
 172		goto cleanup;
 173	} else if (rc != len) {
 174		hid_dbg(hdev,
 175			"string descriptor with pen parameters has invalid length (got %d, expected %d), assuming not compatible\n",
 176			rc, len);
 177		goto finish;
 178	}
 179
 180	/*
 181	 * Fill report descriptor parameters from the string descriptor
 182	 */
 183	desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] =
 184		get_unaligned_le16(buf + 2);
 185	desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] =
 186		get_unaligned_le16(buf + 4);
 187	desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] =
 188		get_unaligned_le16(buf + 8);
 189	resolution = get_unaligned_le16(buf + 10);
 190	if (resolution == 0) {
 191		desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0;
 192		desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0;
 193	} else {
 194		desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] =
 195			desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 /
 196			resolution;
 197		desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] =
 198			desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 /
 199			resolution;
 200	}
 201	kfree(buf);
 202	buf = NULL;
 203
 204	/*
 205	 * Generate pen report descriptor
 206	 */
 207	desc_ptr = uclogic_rdesc_template_apply(
 208				uclogic_rdesc_pen_v1_template_arr,
 209				uclogic_rdesc_pen_v1_template_size,
 210				desc_params, ARRAY_SIZE(desc_params));
 211	if (desc_ptr == NULL) {
 212		rc = -ENOMEM;
 213		goto cleanup;
 214	}
 215
 216	/*
 217	 * Fill-in the parameters
 218	 */
 219	memset(pen, 0, sizeof(*pen));
 220	pen->desc_ptr = desc_ptr;
 221	desc_ptr = NULL;
 222	pen->desc_size = uclogic_rdesc_pen_v1_template_size;
 223	pen->id = UCLOGIC_RDESC_PEN_V1_ID;
 224	pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_INVERTED;
 225	found = true;
 226finish:
 227	*pfound = found;
 228	rc = 0;
 229cleanup:
 230	kfree(desc_ptr);
 231	kfree(buf);
 232	return rc;
 233}
 234
 235/**
 236 * uclogic_params_get_le24() - get a 24-bit little-endian number from a
 237 * buffer.
 238 *
 239 * @p:	The pointer to the number buffer.
 240 *
 241 * Returns:
 242 *	The retrieved number
 243 */
 244static s32 uclogic_params_get_le24(const void *p)
 245{
 246	const __u8 *b = p;
 247	return b[0] | (b[1] << 8UL) | (b[2] << 16UL);
 248}
 249
 250/**
 251 * uclogic_params_pen_init_v2() - initialize tablet interface pen
 252 * input and retrieve its parameters from the device, using v2 protocol.
 253 *
 254 * @pen:	Pointer to the pen parameters to initialize (to be
 255 *		cleaned up with uclogic_params_pen_cleanup()). Not modified in
 256 *		case of error, or if parameters are not found. Cannot be NULL.
 257 * @pfound:	Location for a flag which is set to true if the parameters
 258 *		were found, and to false if not (e.g. device was
 259 *		incompatible). Not modified in case of error. Cannot be NULL.
 260 * @hdev:	The HID device of the tablet interface to initialize and get
 261 *		parameters from. Cannot be NULL.
 
 
 
 
 
 
 
 
 
 
 262 *
 263 * Returns:
 264 *	Zero, if successful. A negative errno code on error.
 265 */
 266static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen,
 267					bool *pfound,
 
 
 268					struct hid_device *hdev)
 269{
 270	int rc;
 271	bool found = false;
 272	/* Buffer for (part of) the string descriptor */
 273	__u8 *buf = NULL;
 274	/* Descriptor length required */
 275	const int len = 18;
 
 
 
 
 
 276	s32 resolution;
 277	/* Pen report descriptor template parameters */
 278	s32 desc_params[UCLOGIC_RDESC_PEN_PH_ID_NUM];
 279	__u8 *desc_ptr = NULL;
 280
 281	/* Check arguments */
 282	if (pen == NULL || pfound == NULL || hdev == NULL) {
 283		rc = -EINVAL;
 284		goto cleanup;
 285	}
 286
 287	/*
 288	 * Read string descriptor containing pen input parameters.
 289	 * The specific string descriptor and data were discovered by sniffing
 290	 * the Windows driver traffic.
 291	 * NOTE: This enables fully-functional tablet mode.
 292	 */
 293	rc = uclogic_params_get_str_desc(&buf, hdev, 200, len);
 294	if (rc == -EPIPE) {
 295		hid_dbg(hdev,
 296			"string descriptor with pen parameters not found, assuming not compatible\n");
 297		goto finish;
 298	} else if (rc < 0) {
 299		hid_err(hdev, "failed retrieving pen parameters: %d\n", rc);
 300		goto cleanup;
 301	} else if (rc != len) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 302		hid_dbg(hdev,
 303			"string descriptor with pen parameters has invalid length (got %d, expected %d), assuming not compatible\n",
 304			rc, len);
 305		goto finish;
 306	} else {
 307		size_t i;
 308		/*
 309		 * Check it's not just a catch-all UTF-16LE-encoded ASCII
 310		 * string (such as the model name) some tablets put into all
 311		 * unknown string descriptors.
 312		 */
 313		for (i = 2;
 314		     i < len &&
 315			(buf[i] >= 0x20 && buf[i] < 0x7f && buf[i + 1] == 0);
 316		     i += 2);
 317		if (i >= len) {
 318			hid_dbg(hdev,
 319				"string descriptor with pen parameters seems to contain only text, assuming not compatible\n");
 320			goto finish;
 321		}
 322	}
 323
 324	/*
 325	 * Fill report descriptor parameters from the string descriptor
 326	 */
 327	desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] =
 328		uclogic_params_get_le24(buf + 2);
 329	desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] =
 330		uclogic_params_get_le24(buf + 5);
 331	desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] =
 332		get_unaligned_le16(buf + 8);
 333	resolution = get_unaligned_le16(buf + 10);
 334	if (resolution == 0) {
 335		desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0;
 336		desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0;
 337	} else {
 338		desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] =
 339			desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 /
 340			resolution;
 341		desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] =
 342			desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 /
 343			resolution;
 344	}
 345	kfree(buf);
 346	buf = NULL;
 347
 348	/*
 349	 * Generate pen report descriptor
 350	 */
 351	desc_ptr = uclogic_rdesc_template_apply(
 352				uclogic_rdesc_pen_v2_template_arr,
 353				uclogic_rdesc_pen_v2_template_size,
 354				desc_params, ARRAY_SIZE(desc_params));
 355	if (desc_ptr == NULL) {
 356		rc = -ENOMEM;
 357		goto cleanup;
 358	}
 359
 360	/*
 361	 * Fill-in the parameters
 362	 */
 363	memset(pen, 0, sizeof(*pen));
 364	pen->desc_ptr = desc_ptr;
 365	desc_ptr = NULL;
 366	pen->desc_size = uclogic_rdesc_pen_v2_template_size;
 367	pen->id = UCLOGIC_RDESC_PEN_V2_ID;
 368	pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_NONE;
 369	pen->fragmented_hires = true;
 
 370	found = true;
 
 
 
 
 
 
 
 371finish:
 372	*pfound = found;
 373	rc = 0;
 374cleanup:
 375	kfree(desc_ptr);
 376	kfree(buf);
 377	return rc;
 378}
 379
 380/**
 381 * uclogic_params_frame_cleanup - free resources used by struct
 382 * uclogic_params_frame (tablet interface's frame controls input parameters).
 383 * Can be called repeatedly.
 384 *
 385 * @frame:	Frame controls input parameters to cleanup. Cannot be NULL.
 386 */
 387static void uclogic_params_frame_cleanup(struct uclogic_params_frame *frame)
 388{
 389	kfree(frame->desc_ptr);
 390	memset(frame, 0, sizeof(*frame));
 391}
 392
 393/**
 394 * uclogic_params_frame_init_with_desc() - initialize tablet's frame control
 395 * parameters with a static report descriptor.
 396 *
 397 * @frame:	Pointer to the frame parameters to initialize (to be cleaned
 398 *		up with uclogic_params_frame_cleanup()). Not modified in case
 399 *		of error. Cannot be NULL.
 400 * @desc_ptr:	Report descriptor pointer. Can be NULL, if desc_size is zero.
 401 * @desc_size:	Report descriptor size.
 402 * @id:		Report ID used for frame reports, if they should be tweaked,
 403 *		zero if not.
 404 *
 405 * Returns:
 406 *	Zero, if successful. A negative errno code on error.
 407 */
 408static int uclogic_params_frame_init_with_desc(
 409					struct uclogic_params_frame *frame,
 410					const __u8 *desc_ptr,
 411					size_t desc_size,
 412					unsigned int id)
 413{
 414	__u8 *copy_desc_ptr;
 415
 416	if (frame == NULL || (desc_ptr == NULL && desc_size != 0))
 417		return -EINVAL;
 418
 419	copy_desc_ptr = kmemdup(desc_ptr, desc_size, GFP_KERNEL);
 420	if (copy_desc_ptr == NULL)
 421		return -ENOMEM;
 422
 423	memset(frame, 0, sizeof(*frame));
 424	frame->desc_ptr = copy_desc_ptr;
 425	frame->desc_size = desc_size;
 426	frame->id = id;
 427	return 0;
 428}
 429
 430/**
 431 * uclogic_params_frame_init_v1_buttonpad() - initialize abstract buttonpad
 432 * on a v1 tablet interface.
 433 *
 434 * @frame:	Pointer to the frame parameters to initialize (to be cleaned
 435 *		up with uclogic_params_frame_cleanup()). Not modified in case
 436 *		of error, or if parameters are not found. Cannot be NULL.
 437 * @pfound:	Location for a flag which is set to true if the parameters
 438 *		were found, and to false if not (e.g. device was
 439 *		incompatible). Not modified in case of error. Cannot be NULL.
 440 * @hdev:	The HID device of the tablet interface to initialize and get
 441 *		parameters from. Cannot be NULL.
 442 *
 443 * Returns:
 444 *	Zero, if successful. A negative errno code on error.
 445 */
 446static int uclogic_params_frame_init_v1_buttonpad(
 447					struct uclogic_params_frame *frame,
 448					bool *pfound,
 449					struct hid_device *hdev)
 450{
 451	int rc;
 452	bool found = false;
 453	struct usb_device *usb_dev = hid_to_usb_dev(hdev);
 454	char *str_buf = NULL;
 455	const size_t str_len = 16;
 456
 457	/* Check arguments */
 458	if (frame == NULL || pfound == NULL || hdev == NULL) {
 459		rc = -EINVAL;
 460		goto cleanup;
 461	}
 462
 
 
 463	/*
 464	 * Enable generic button mode
 465	 */
 466	str_buf = kzalloc(str_len, GFP_KERNEL);
 467	if (str_buf == NULL) {
 468		rc = -ENOMEM;
 469		goto cleanup;
 470	}
 471
 472	rc = usb_string(usb_dev, 123, str_buf, str_len);
 473	if (rc == -EPIPE) {
 474		hid_dbg(hdev,
 475			"generic button -enabling string descriptor not found\n");
 476	} else if (rc < 0) {
 477		goto cleanup;
 478	} else if (strncmp(str_buf, "HK On", rc) != 0) {
 479		hid_dbg(hdev,
 480			"invalid response to enabling generic buttons: \"%s\"\n",
 481			str_buf);
 482	} else {
 483		hid_dbg(hdev, "generic buttons enabled\n");
 484		rc = uclogic_params_frame_init_with_desc(
 485				frame,
 486				uclogic_rdesc_buttonpad_v1_arr,
 487				uclogic_rdesc_buttonpad_v1_size,
 488				UCLOGIC_RDESC_BUTTONPAD_V1_ID);
 489		if (rc != 0)
 490			goto cleanup;
 491		found = true;
 492	}
 493
 494	*pfound = found;
 495	rc = 0;
 496cleanup:
 497	kfree(str_buf);
 498	return rc;
 499}
 500
 501/**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 502 * uclogic_params_cleanup - free resources used by struct uclogic_params
 503 * (tablet interface's parameters).
 504 * Can be called repeatedly.
 505 *
 506 * @params:	Input parameters to cleanup. Cannot be NULL.
 507 */
 508void uclogic_params_cleanup(struct uclogic_params *params)
 509{
 510	if (!params->invalid) {
 
 511		kfree(params->desc_ptr);
 512		if (!params->pen_unused)
 513			uclogic_params_pen_cleanup(&params->pen);
 514		uclogic_params_frame_cleanup(&params->frame);
 
 
 515		memset(params, 0, sizeof(*params));
 516	}
 517}
 518
 519/**
 520 * uclogic_params_get_desc() - Get a replacement report descriptor for a
 521 *                             tablet's interface.
 522 *
 523 * @params:	The parameters of a tablet interface to get report
 524 *		descriptor for. Cannot be NULL.
 525 * @pdesc:	Location for the resulting, kmalloc-allocated report
 526 *		descriptor pointer, or for NULL, if there's no replacement
 527 *		report descriptor. Not modified in case of error. Cannot be
 528 *		NULL.
 529 * @psize:	Location for the resulting report descriptor size, not set if
 530 *		there's no replacement report descriptor. Not modified in case
 531 *		of error. Cannot be NULL.
 532 *
 533 * Returns:
 534 *	Zero, if successful.
 535 *	-EINVAL, if invalid arguments are supplied.
 536 *	-ENOMEM, if failed to allocate memory.
 537 */
 538int uclogic_params_get_desc(const struct uclogic_params *params,
 539				__u8 **pdesc,
 540				unsigned int *psize)
 541{
 542	bool common_present;
 543	bool pen_present;
 544	bool frame_present;
 545	unsigned int size;
 546	__u8 *desc = NULL;
 
 547
 548	/* Check arguments */
 549	if (params == NULL || pdesc == NULL || psize == NULL)
 550		return -EINVAL;
 551
 552	size = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 553
 554	common_present = (params->desc_ptr != NULL);
 555	pen_present = (!params->pen_unused && params->pen.desc_ptr != NULL);
 556	frame_present = (params->frame.desc_ptr != NULL);
 557
 558	if (common_present)
 559		size += params->desc_size;
 560	if (pen_present)
 561		size += params->pen.desc_size;
 562	if (frame_present)
 563		size += params->frame.desc_size;
 564
 565	if (common_present || pen_present || frame_present) {
 566		__u8 *p;
 567
 568		desc = kmalloc(size, GFP_KERNEL);
 569		if (desc == NULL)
 570			return -ENOMEM;
 571		p = desc;
 572
 573		if (common_present) {
 574			memcpy(p, params->desc_ptr,
 575				params->desc_size);
 576			p += params->desc_size;
 577		}
 578		if (pen_present) {
 579			memcpy(p, params->pen.desc_ptr,
 580				params->pen.desc_size);
 581			p += params->pen.desc_size;
 582		}
 583		if (frame_present) {
 584			memcpy(p, params->frame.desc_ptr,
 585				params->frame.desc_size);
 586			p += params->frame.desc_size;
 587		}
 588
 589		WARN_ON(p != desc + size);
 590
 
 
 591		*psize = size;
 
 592	}
 593
 594	*pdesc = desc;
 595	return 0;
 
 596}
 597
 598/**
 599 * uclogic_params_init_invalid() - initialize tablet interface parameters,
 600 * specifying the interface is invalid.
 601 *
 602 * @params:		Parameters to initialize (to be cleaned with
 603 *			uclogic_params_cleanup()). Cannot be NULL.
 604 */
 605static void uclogic_params_init_invalid(struct uclogic_params *params)
 606{
 607	params->invalid = true;
 608}
 609
 610/**
 611 * uclogic_params_init_with_opt_desc() - initialize tablet interface
 612 * parameters with an optional replacement report descriptor. Only modify
 613 * report descriptor, if the original report descriptor matches the expected
 614 * size.
 615 *
 616 * @params:		Parameters to initialize (to be cleaned with
 617 *			uclogic_params_cleanup()). Not modified in case of
 618 *			error. Cannot be NULL.
 619 * @hdev:		The HID device of the tablet interface create the
 620 *			parameters for. Cannot be NULL.
 621 * @orig_desc_size:	Expected size of the original report descriptor to
 622 *			be replaced.
 623 * @desc_ptr:		Pointer to the replacement report descriptor.
 624 *			Can be NULL, if desc_size is zero.
 625 * @desc_size:		Size of the replacement report descriptor.
 626 *
 627 * Returns:
 628 *	Zero, if successful. -EINVAL if an invalid argument was passed.
 629 *	-ENOMEM, if failed to allocate memory.
 630 */
 631static int uclogic_params_init_with_opt_desc(struct uclogic_params *params,
 632					     struct hid_device *hdev,
 633					     unsigned int orig_desc_size,
 634					     __u8 *desc_ptr,
 635					     unsigned int desc_size)
 636{
 637	__u8 *desc_copy_ptr = NULL;
 638	unsigned int desc_copy_size;
 639	int rc;
 640
 641	/* Check arguments */
 642	if (params == NULL || hdev == NULL ||
 643	    (desc_ptr == NULL && desc_size != 0)) {
 644		rc = -EINVAL;
 645		goto cleanup;
 646	}
 647
 648	/* Replace report descriptor, if it matches */
 649	if (hdev->dev_rsize == orig_desc_size) {
 650		hid_dbg(hdev,
 651			"device report descriptor matches the expected size, replacing\n");
 652		desc_copy_ptr = kmemdup(desc_ptr, desc_size, GFP_KERNEL);
 653		if (desc_copy_ptr == NULL) {
 654			rc = -ENOMEM;
 655			goto cleanup;
 656		}
 657		desc_copy_size = desc_size;
 658	} else {
 659		hid_dbg(hdev,
 660			"device report descriptor doesn't match the expected size (%u != %u), preserving\n",
 661			hdev->dev_rsize, orig_desc_size);
 662		desc_copy_ptr = NULL;
 663		desc_copy_size = 0;
 664	}
 665
 666	/* Output parameters */
 667	memset(params, 0, sizeof(*params));
 668	params->desc_ptr = desc_copy_ptr;
 669	desc_copy_ptr = NULL;
 670	params->desc_size = desc_copy_size;
 671
 672	rc = 0;
 673cleanup:
 674	kfree(desc_copy_ptr);
 675	return rc;
 676}
 677
 678/**
 679 * uclogic_params_init_with_pen_unused() - initialize tablet interface
 680 * parameters preserving original reports and generic HID processing, but
 681 * disabling pen usage.
 682 *
 683 * @params:		Parameters to initialize (to be cleaned with
 684 *			uclogic_params_cleanup()). Not modified in case of
 685 *			error. Cannot be NULL.
 686 */
 687static void uclogic_params_init_with_pen_unused(struct uclogic_params *params)
 688{
 689	memset(params, 0, sizeof(*params));
 690	params->pen_unused = true;
 691}
 692
 693/**
 694 * uclogic_params_huion_init() - initialize a Huion tablet interface and discover
 695 * its parameters.
 696 *
 697 * @params:	Parameters to fill in (to be cleaned with
 698 *		uclogic_params_cleanup()). Not modified in case of error.
 699 *		Cannot be NULL.
 700 * @hdev:	The HID device of the tablet interface to initialize and get
 701 *		parameters from. Cannot be NULL.
 702 *
 703 * Returns:
 704 *	Zero, if successful. A negative errno code on error.
 705 */
 706static int uclogic_params_huion_init(struct uclogic_params *params,
 707				     struct hid_device *hdev)
 708{
 709	int rc;
 710	struct usb_device *udev = hid_to_usb_dev(hdev);
 711	struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
 712	__u8 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
 713	bool found;
 714	/* The resulting parameters (noop) */
 715	struct uclogic_params p = {0, };
 716	static const char transition_ver[] = "HUION_T153_160607";
 717	char *ver_ptr = NULL;
 718	const size_t ver_len = sizeof(transition_ver) + 1;
 
 
 
 
 
 
 
 
 719
 720	/* Check arguments */
 721	if (params == NULL || hdev == NULL) {
 722		rc = -EINVAL;
 723		goto cleanup;
 724	}
 725
 726	/* If it's not a pen interface */
 727	if (bInterfaceNumber != 0) {
 728		/* TODO: Consider marking the interface invalid */
 729		uclogic_params_init_with_pen_unused(&p);
 
 
 
 
 
 
 
 
 730		goto output;
 731	}
 732
 733	/* Try to get firmware version */
 734	ver_ptr = kzalloc(ver_len, GFP_KERNEL);
 735	if (ver_ptr == NULL) {
 736		rc = -ENOMEM;
 737		goto cleanup;
 738	}
 739	rc = usb_string(udev, 201, ver_ptr, ver_len);
 740	if (rc == -EPIPE) {
 741		*ver_ptr = '\0';
 742	} else if (rc < 0) {
 743		hid_err(hdev,
 744			"failed retrieving Huion firmware version: %d\n", rc);
 745		goto cleanup;
 746	}
 747
 748	/* If this is a transition firmware */
 749	if (strcmp(ver_ptr, transition_ver) == 0) {
 750		hid_dbg(hdev,
 751			"transition firmware detected, not probing pen v2 parameters\n");
 752	} else {
 753		/* Try to probe v2 pen parameters */
 754		rc = uclogic_params_pen_init_v2(&p.pen, &found, hdev);
 
 
 755		if (rc != 0) {
 756			hid_err(hdev,
 757				"failed probing pen v2 parameters: %d\n", rc);
 758			goto cleanup;
 759		} else if (found) {
 760			hid_dbg(hdev, "pen v2 parameters found\n");
 761			/* Create v2 buttonpad parameters */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 762			rc = uclogic_params_frame_init_with_desc(
 763					&p.frame,
 764					uclogic_rdesc_buttonpad_v2_arr,
 765					uclogic_rdesc_buttonpad_v2_size,
 766					UCLOGIC_RDESC_BUTTONPAD_V2_ID);
 767			if (rc != 0) {
 768				hid_err(hdev,
 769					"failed creating v2 buttonpad parameters: %d\n",
 770					rc);
 771				goto cleanup;
 772			}
 773			/* Set bitmask marking frame reports in pen reports */
 774			p.pen_frame_flag = 0x20;
 
 
 
 
 
 
 
 
 775			goto output;
 776		}
 777		hid_dbg(hdev, "pen v2 parameters not found\n");
 778	}
 779
 780	/* Try to probe v1 pen parameters */
 781	rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
 782	if (rc != 0) {
 783		hid_err(hdev,
 784			"failed probing pen v1 parameters: %d\n", rc);
 785		goto cleanup;
 786	} else if (found) {
 787		hid_dbg(hdev, "pen v1 parameters found\n");
 788		/* Try to probe v1 buttonpad */
 789		rc = uclogic_params_frame_init_v1_buttonpad(
 790						&p.frame,
 791						&found, hdev);
 792		if (rc != 0) {
 793			hid_err(hdev, "v1 buttonpad probing failed: %d\n", rc);
 794			goto cleanup;
 795		}
 796		hid_dbg(hdev, "buttonpad v1 parameters%s found\n",
 797			(found ? "" : " not"));
 798		if (found) {
 799			/* Set bitmask marking frame reports */
 800			p.pen_frame_flag = 0x20;
 
 
 801		}
 802		goto output;
 803	}
 804	hid_dbg(hdev, "pen v1 parameters not found\n");
 805
 806	uclogic_params_init_invalid(&p);
 807
 808output:
 809	/* Output parameters */
 810	memcpy(params, &p, sizeof(*params));
 811	memset(&p, 0, sizeof(p));
 812	rc = 0;
 813cleanup:
 
 814	kfree(ver_ptr);
 815	uclogic_params_cleanup(&p);
 816	return rc;
 817}
 818
 819/**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 820 * uclogic_params_init() - initialize a tablet interface and discover its
 821 * parameters.
 822 *
 823 * @params:	Parameters to fill in (to be cleaned with
 824 *		uclogic_params_cleanup()). Not modified in case of error.
 825 *		Cannot be NULL.
 826 * @hdev:	The HID device of the tablet interface to initialize and get
 827 *		parameters from. Cannot be NULL. Must be using the USB low-level
 828 *		driver, i.e. be an actual USB tablet.
 829 *
 830 * Returns:
 831 *	Zero, if successful. A negative errno code on error.
 832 */
 833int uclogic_params_init(struct uclogic_params *params,
 834			struct hid_device *hdev)
 835{
 836	int rc;
 837	struct usb_device *udev = hid_to_usb_dev(hdev);
 838	__u8  bNumInterfaces = udev->config->desc.bNumInterfaces;
 839	struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
 840	__u8 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
 841	bool found;
 842	/* The resulting parameters (noop) */
 843	struct uclogic_params p = {0, };
 844
 845	/* Check arguments */
 846	if (params == NULL || hdev == NULL ||
 847	    !hid_is_using_ll_driver(hdev, &usb_hid_driver)) {
 848		rc = -EINVAL;
 849		goto cleanup;
 850	}
 851
 
 
 
 
 
 852	/*
 853	 * Set replacement report descriptor if the original matches the
 854	 * specified size. Otherwise keep interface unchanged.
 855	 */
 856#define WITH_OPT_DESC(_orig_desc_token, _new_desc_token) \
 857	uclogic_params_init_with_opt_desc(                  \
 858		&p, hdev,                                   \
 859		UCLOGIC_RDESC_##_orig_desc_token##_SIZE,    \
 860		uclogic_rdesc_##_new_desc_token##_arr,      \
 861		uclogic_rdesc_##_new_desc_token##_size)
 862
 863#define VID_PID(_vid, _pid) \
 864	(((__u32)(_vid) << 16) | ((__u32)(_pid) & U16_MAX))
 865
 866	/*
 867	 * Handle specific interfaces for specific tablets.
 868	 *
 869	 * Observe the following logic:
 870	 *
 871	 * If the interface is recognized as producing certain useful input:
 872	 *	Mark interface as valid.
 873	 *	Output interface parameters.
 874	 * Else, if the interface is recognized as *not* producing any useful
 875	 * input:
 876	 *	Mark interface as invalid.
 877	 * Else:
 878	 *	Mark interface as valid.
 879	 *	Output noop parameters.
 880	 *
 881	 * Rule of thumb: it is better to disable a broken interface than let
 882	 *		  it spew garbage input.
 883	 */
 884
 885	switch (VID_PID(hdev->vendor, hdev->product)) {
 886	case VID_PID(USB_VENDOR_ID_UCLOGIC,
 887		     USB_DEVICE_ID_UCLOGIC_TABLET_PF1209):
 888		rc = WITH_OPT_DESC(PF1209_ORIG, pf1209_fixed);
 889		if (rc != 0)
 890			goto cleanup;
 891		break;
 892	case VID_PID(USB_VENDOR_ID_UCLOGIC,
 893		     USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U):
 894		rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp4030u_fixed);
 895		if (rc != 0)
 896			goto cleanup;
 897		break;
 898	case VID_PID(USB_VENDOR_ID_UCLOGIC,
 899		     USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U):
 900		if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) {
 901			if (bInterfaceNumber == 0) {
 902				/* Try to probe v1 pen parameters */
 903				rc = uclogic_params_pen_init_v1(&p.pen,
 904								&found, hdev);
 905				if (rc != 0) {
 906					hid_err(hdev,
 907						"pen probing failed: %d\n",
 908						rc);
 909					goto cleanup;
 910				}
 911				if (!found) {
 912					hid_warn(hdev,
 913						 "pen parameters not found");
 914				}
 915			} else {
 916				uclogic_params_init_invalid(&p);
 917			}
 918		} else {
 919			rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp5540u_fixed);
 920			if (rc != 0)
 921				goto cleanup;
 922		}
 923		break;
 924	case VID_PID(USB_VENDOR_ID_UCLOGIC,
 925		     USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U):
 926		rc = WITH_OPT_DESC(WPXXXXU_ORIG, wp8060u_fixed);
 927		if (rc != 0)
 928			goto cleanup;
 929		break;
 930	case VID_PID(USB_VENDOR_ID_UCLOGIC,
 931		     USB_DEVICE_ID_UCLOGIC_TABLET_WP1062):
 932		rc = WITH_OPT_DESC(WP1062_ORIG, wp1062_fixed);
 933		if (rc != 0)
 934			goto cleanup;
 935		break;
 936	case VID_PID(USB_VENDOR_ID_UCLOGIC,
 937		     USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850):
 938		switch (bInterfaceNumber) {
 939		case 0:
 940			rc = WITH_OPT_DESC(TWHL850_ORIG0, twhl850_fixed0);
 941			if (rc != 0)
 942				goto cleanup;
 943			break;
 944		case 1:
 945			rc = WITH_OPT_DESC(TWHL850_ORIG1, twhl850_fixed1);
 946			if (rc != 0)
 947				goto cleanup;
 948			break;
 949		case 2:
 950			rc = WITH_OPT_DESC(TWHL850_ORIG2, twhl850_fixed2);
 951			if (rc != 0)
 952				goto cleanup;
 953			break;
 954		}
 955		break;
 956	case VID_PID(USB_VENDOR_ID_UCLOGIC,
 957		     USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60):
 958		/*
 959		 * If it is not a three-interface version, which is known to
 960		 * respond to initialization.
 961		 */
 962		if (bNumInterfaces != 3) {
 963			switch (bInterfaceNumber) {
 964			case 0:
 965				rc = WITH_OPT_DESC(TWHA60_ORIG0,
 966							twha60_fixed0);
 967				if (rc != 0)
 968					goto cleanup;
 969				break;
 970			case 1:
 971				rc = WITH_OPT_DESC(TWHA60_ORIG1,
 972							twha60_fixed1);
 973				if (rc != 0)
 974					goto cleanup;
 975				break;
 976			}
 977			break;
 978		}
 979		fallthrough;
 980	case VID_PID(USB_VENDOR_ID_HUION,
 981		     USB_DEVICE_ID_HUION_TABLET):
 982	case VID_PID(USB_VENDOR_ID_HUION,
 983		     USB_DEVICE_ID_HUION_HS64):
 984	case VID_PID(USB_VENDOR_ID_UCLOGIC,
 985		     USB_DEVICE_ID_HUION_TABLET):
 986	case VID_PID(USB_VENDOR_ID_UCLOGIC,
 987		     USB_DEVICE_ID_YIYNOVA_TABLET):
 988	case VID_PID(USB_VENDOR_ID_UCLOGIC,
 989		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_81):
 990	case VID_PID(USB_VENDOR_ID_UCLOGIC,
 991		     USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3):
 992	case VID_PID(USB_VENDOR_ID_UCLOGIC,
 993		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_45):
 994	case VID_PID(USB_VENDOR_ID_UCLOGIC,
 995		     USB_DEVICE_ID_UCLOGIC_UGEE_TABLET_47):
 996		rc = uclogic_params_huion_init(&p, hdev);
 997		if (rc != 0)
 998			goto cleanup;
 999		break;
1000	case VID_PID(USB_VENDOR_ID_UGTIZER,
1001		     USB_DEVICE_ID_UGTIZER_TABLET_GP0610):
1002	case VID_PID(USB_VENDOR_ID_UGTIZER,
1003		     USB_DEVICE_ID_UGTIZER_TABLET_GT5040):
1004	case VID_PID(USB_VENDOR_ID_UGEE,
1005		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
1006	case VID_PID(USB_VENDOR_ID_UGEE,
1007		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640):
1008	case VID_PID(USB_VENDOR_ID_UGEE,
 
 
1009		     USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720):
1010		/* If this is the pen interface */
1011		if (bInterfaceNumber == 1) {
1012			/* Probe v1 pen parameters */
1013			rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1014			if (rc != 0) {
1015				hid_err(hdev, "pen probing failed: %d\n", rc);
1016				goto cleanup;
1017			}
1018			if (!found) {
1019				hid_warn(hdev, "pen parameters not found");
1020				uclogic_params_init_invalid(&p);
1021			}
1022		} else {
1023			/* TODO: Consider marking the interface invalid */
1024			uclogic_params_init_with_pen_unused(&p);
1025		}
1026		break;
1027	case VID_PID(USB_VENDOR_ID_UGEE,
1028		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01):
1029		/* If this is the pen and frame interface */
1030		if (bInterfaceNumber == 1) {
1031			/* Probe v1 pen parameters */
1032			rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1033			if (rc != 0) {
1034				hid_err(hdev, "pen probing failed: %d\n", rc);
1035				goto cleanup;
1036			}
1037			/* Initialize frame parameters */
1038			rc = uclogic_params_frame_init_with_desc(
1039				&p.frame,
1040				uclogic_rdesc_xppen_deco01_frame_arr,
1041				uclogic_rdesc_xppen_deco01_frame_size,
1042				0);
1043			if (rc != 0)
1044				goto cleanup;
1045		} else {
1046			/* TODO: Consider marking the interface invalid */
1047			uclogic_params_init_with_pen_unused(&p);
1048		}
1049		break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1050	case VID_PID(USB_VENDOR_ID_TRUST,
1051		     USB_DEVICE_ID_TRUST_PANORA_TABLET):
1052	case VID_PID(USB_VENDOR_ID_UGEE,
1053		     USB_DEVICE_ID_UGEE_TABLET_G5):
1054		/* Ignore non-pen interfaces */
1055		if (bInterfaceNumber != 1) {
1056			uclogic_params_init_invalid(&p);
1057			break;
1058		}
1059
1060		rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1061		if (rc != 0) {
1062			hid_err(hdev, "pen probing failed: %d\n", rc);
1063			goto cleanup;
1064		} else if (found) {
1065			rc = uclogic_params_frame_init_with_desc(
1066				&p.frame,
1067				uclogic_rdesc_ugee_g5_frame_arr,
1068				uclogic_rdesc_ugee_g5_frame_size,
1069				UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
1070			if (rc != 0) {
1071				hid_err(hdev,
1072					"failed creating buttonpad parameters: %d\n",
1073					rc);
1074				goto cleanup;
1075			}
1076			p.frame.re_lsb =
1077				UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
1078			p.frame.dev_id_byte =
1079				UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
1080		} else {
1081			hid_warn(hdev, "pen parameters not found");
1082			uclogic_params_init_invalid(&p);
1083		}
1084
1085		break;
1086	case VID_PID(USB_VENDOR_ID_UGEE,
1087		     USB_DEVICE_ID_UGEE_TABLET_EX07S):
1088		/* Ignore non-pen interfaces */
1089		if (bInterfaceNumber != 1) {
1090			uclogic_params_init_invalid(&p);
1091			break;
1092		}
1093
1094		rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1095		if (rc != 0) {
1096			hid_err(hdev, "pen probing failed: %d\n", rc);
1097			goto cleanup;
1098		} else if (found) {
1099			rc = uclogic_params_frame_init_with_desc(
1100				&p.frame,
1101				uclogic_rdesc_ugee_ex07_buttonpad_arr,
1102				uclogic_rdesc_ugee_ex07_buttonpad_size,
1103				0);
1104			if (rc != 0) {
1105				hid_err(hdev,
1106					"failed creating buttonpad parameters: %d\n",
1107					rc);
1108				goto cleanup;
1109			}
1110		} else {
1111			hid_warn(hdev, "pen parameters not found");
1112			uclogic_params_init_invalid(&p);
1113		}
1114
1115		break;
1116	}
1117
1118#undef VID_PID
1119#undef WITH_OPT_DESC
1120
1121	/* Output parameters */
1122	memcpy(params, &p, sizeof(*params));
1123	memset(&p, 0, sizeof(p));
1124	rc = 0;
1125cleanup:
1126	uclogic_params_cleanup(&p);
1127	return rc;
1128}