hid-uclogic-params.c 49 KB

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