Lines Matching +full:pen +full:- +full:up
1 // SPDX-License-Identifier: GPL-2.0+
3 * HID driver for UC-Logic devices not fully compliant with HID standard
4 * - tablet initialization and parameter retrieval
16 #include "hid-uclogic-params.h"
17 #include "hid-uclogic-rdesc.h"
19 #include "hid-ids.h"
26 * uclogic_params_pen_inrange_to_str() - Convert a pen in-range reporting type
28 * @inrange: The in-range reporting type to convert.
50 * uclogic_params_pen_hid_dbg() - Dump tablet interface pen parameters
51 * @hdev: The HID device the pen parameters describe.
52 * @pen: The pen parameters to dump.
54 * Dump tablet interface pen parameters with hid_dbg(). The dump is indented
58 const struct uclogic_params_pen *pen)
63 str_true_false(pen->usage_invalid));
64 hid_dbg(hdev, "\t.desc_ptr = %p\n", pen->desc_ptr);
65 hid_dbg(hdev, "\t.desc_size = %u\n", pen->desc_size);
66 hid_dbg(hdev, "\t.id = %u\n", pen->id);
68 for (i = 0; i < ARRAY_SIZE(pen->subreport_list); i++) {
70 pen->subreport_list[i].value,
71 pen->subreport_list[i].id,
72 i < (ARRAY_SIZE(pen->subreport_list) - 1) ? "," : "");
76 uclogic_params_pen_inrange_to_str(pen->inrange));
78 str_true_false(pen->fragmented_hires));
80 str_true_false(pen->tilt_y_flipped));
84 * uclogic_params_frame_hid_dbg() - Dump tablet interface frame parameters
85 * @hdev: The HID device the pen parameters describe.
95 hid_dbg(hdev, "\t\t.desc_ptr = %p\n", frame->desc_ptr);
96 hid_dbg(hdev, "\t\t.desc_size = %u\n", frame->desc_size);
97 hid_dbg(hdev, "\t\t.id = %u\n", frame->id);
98 hid_dbg(hdev, "\t\t.suffix = %s\n", frame->suffix);
99 hid_dbg(hdev, "\t\t.re_lsb = %u\n", frame->re_lsb);
100 hid_dbg(hdev, "\t\t.dev_id_byte = %u\n", frame->dev_id_byte);
101 hid_dbg(hdev, "\t\t.touch_byte = %u\n", frame->touch_byte);
102 hid_dbg(hdev, "\t\t.touch_max = %hhd\n", frame->touch_max);
104 frame->touch_flip_at);
106 frame->bitmap_dial_byte);
108 frame->bitmap_second_dial_destination_byte);
112 * uclogic_params_hid_dbg() - Dump tablet interface parameters
123 hid_dbg(hdev, ".invalid = %s\n", str_true_false(params->invalid));
124 hid_dbg(hdev, ".desc_ptr = %p\n", params->desc_ptr);
125 hid_dbg(hdev, ".desc_size = %u\n", params->desc_size);
126 hid_dbg(hdev, ".pen = {\n");
127 uclogic_params_pen_hid_dbg(hdev, ¶ms->pen);
130 for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) {
132 uclogic_params_frame_hid_dbg(hdev, ¶ms->frame_list[i]);
134 i < (ARRAY_SIZE(params->frame_list) - 1) ? "," : "");
140 * uclogic_params_get_str_desc - retrieve a string descriptor from a HID
141 * device interface, putting it into a kmalloc-allocated buffer as is, without
144 * @pbuf: Location for the kmalloc-allocated buffer pointer containing
154 * -EPIPE, if the descriptor was not found, or
166 rc = -EINVAL;
174 rc = -ENOMEM;
183 if (rc == -EPIPE) {
204 * uclogic_params_pen_cleanup - free resources used by struct
205 * uclogic_params_pen (tablet interface's pen input parameters).
208 * @pen: Pen input parameters to cleanup. Cannot be NULL.
210 static void uclogic_params_pen_cleanup(struct uclogic_params_pen *pen)
212 kfree(pen->desc_ptr);
213 memset(pen, 0, sizeof(*pen));
217 * uclogic_params_pen_init_v1() - initialize tablet interface pen
220 * @pen: Pointer to the pen parameters to initialize (to be
221 * cleaned up with uclogic_params_pen_cleanup()). Not modified in
232 static int uclogic_params_pen_init_v1(struct uclogic_params_pen *pen,
243 /* Pen report descriptor template parameters */
248 if (pen == NULL || pfound == NULL || hdev == NULL) {
249 rc = -EINVAL;
254 * Read string descriptor containing pen input parameters.
257 * NOTE: This enables fully-functional tablet mode.
260 if (rc == -EPIPE) {
262 "string descriptor with pen parameters not found, assuming not compatible\n");
265 hid_err(hdev, "failed retrieving pen parameters: %d\n", rc);
269 "string descriptor with pen parameters has invalid length (got %d, expected %d), assuming not compatible\n",
299 * Generate pen report descriptor
306 rc = -ENOMEM;
311 * Fill-in the parameters
313 memset(pen, 0, sizeof(*pen));
314 pen->desc_ptr = desc_ptr;
316 pen->desc_size = uclogic_rdesc_v1_pen_template_size;
317 pen->id = UCLOGIC_RDESC_V1_PEN_ID;
318 pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_INVERTED;
330 * uclogic_params_get_le24() - get a 24-bit little-endian number from a
345 * uclogic_params_pen_init_v2() - initialize tablet interface pen
348 * @pen: Pointer to the pen parameters to initialize (to be
349 * cleaned up with uclogic_params_pen_cleanup()). Not
370 static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen,
388 /* Pen report descriptor template parameters */
393 if (pen == NULL || pfound == NULL || hdev == NULL) {
394 rc = -EINVAL;
399 * Read string descriptor containing pen input parameters.
402 * NOTE: This enables fully-functional tablet mode.
405 if (rc == -EPIPE) {
407 "string descriptor with pen parameters not found, assuming not compatible\n");
410 hid_err(hdev, "failed retrieving pen parameters: %d\n", rc);
414 "string descriptor with pen parameters is too short (got %d, expected at least %d), assuming not compatible\n",
422 * Check it's not just a catch-all UTF-16LE-encoded ASCII
432 "string descriptor with pen parameters seems to contain only text, assuming not compatible\n");
459 * Generate pen report descriptor
466 rc = -ENOMEM;
471 * Fill-in the parameters
473 memset(pen, 0, sizeof(*pen));
474 pen->desc_ptr = desc_ptr;
476 pen->desc_size = uclogic_rdesc_v2_pen_template_size;
477 pen->id = UCLOGIC_RDESC_V2_PEN_ID;
478 pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_NONE;
479 pen->fragmented_hires = true;
480 pen->tilt_y_flipped = true;
499 * uclogic_params_frame_cleanup - free resources used by struct
507 kfree(frame->desc_ptr);
512 * uclogic_params_frame_init_with_desc() - initialize tablet's frame control
516 * up with uclogic_params_frame_cleanup()). Not modified in case
535 return -EINVAL;
539 return -ENOMEM;
542 frame->desc_ptr = copy_desc_ptr;
543 frame->desc_size = desc_size;
544 frame->id = id;
549 * uclogic_params_frame_init_v1() - initialize v1 tablet interface frame
553 * up with uclogic_params_frame_cleanup()). Not modified in case
576 rc = -EINVAL;
587 rc = -ENOMEM;
592 if (rc == -EPIPE) {
594 "generic button -enabling string descriptor not found\n");
621 * uclogic_params_cleanup_event_hooks - free resources used by the list of raw
631 if (!params || !params->event_hooks)
634 list_for_each_entry_safe(curr, n, ¶ms->event_hooks->list, list) {
635 cancel_work_sync(&curr->work);
636 list_del(&curr->list);
637 kfree(curr->event);
641 kfree(params->event_hooks);
642 params->event_hooks = NULL;
646 * uclogic_params_cleanup - free resources used by struct uclogic_params
654 if (!params->invalid) {
656 kfree(params->desc_ptr);
657 uclogic_params_pen_cleanup(¶ms->pen);
658 for (i = 0; i < ARRAY_SIZE(params->frame_list); i++)
659 uclogic_params_frame_cleanup(¶ms->frame_list[i]);
667 * uclogic_params_get_desc() - Get a replacement report descriptor for a
672 * @pdesc: Location for the resulting, kmalloc-allocated report
682 * -EINVAL, if invalid arguments are supplied.
683 * -ENOMEM, if failed to allocate memory.
689 int rc = -ENOMEM;
697 return -EINVAL;
718 ADD_DESC(params->desc_ptr, params->desc_size);
719 ADD_DESC(params->pen.desc_ptr, params->pen.desc_size);
720 for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) {
721 ADD_DESC(params->frame_list[i].desc_ptr,
722 params->frame_list[i].desc_size);
739 * uclogic_params_init_invalid() - initialize tablet interface parameters,
747 params->invalid = true;
751 * uclogic_params_init_with_opt_desc() - initialize tablet interface
768 * Zero, if successful. -EINVAL if an invalid argument was passed.
769 * -ENOMEM, if failed to allocate memory.
784 rc = -EINVAL;
789 if (hdev->dev_rsize == orig_desc_size) {
794 rc = -ENOMEM;
801 hdev->dev_rsize, orig_desc_size);
808 params->desc_ptr = desc_copy_ptr;
810 params->desc_size = desc_copy_size;
819 * uclogic_params_huion_init() - initialize a Huion tablet interface and discover
855 rc = -EINVAL;
860 iface = to_usb_interface(hdev->dev.parent);
861 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
865 /* Keep everything intact, but mark pen usage invalid */
866 p.pen.usage_invalid = true;
868 /* Else, if it's not a pen interface */
877 rc = -ENOMEM;
881 if (rc == -EPIPE) {
890 strscpy(hdev->uniq, ver_ptr, sizeof(hdev->uniq));
895 "transition firmware detected, not probing pen v2 parameters\n");
897 /* Try to probe v2 pen parameters */
898 rc = uclogic_params_pen_init_v2(&p.pen, &found,
903 "failed probing pen v2 parameters: %d\n", rc);
906 hid_dbg(hdev, "pen v2 parameters found\n");
920 /* Link from pen sub-report */
921 p.pen.subreport_list[0].value = 0xe0;
922 p.pen.subreport_list[0].id =
968 /* Link from pen sub-report */
969 p.pen.subreport_list[1].value = 0xf0;
970 p.pen.subreport_list[1].id =
990 /* Link from pen sub-report */
991 p.pen.subreport_list[2].value = 0xf1;
992 p.pen.subreport_list[2].id =
997 hid_dbg(hdev, "pen v2 parameters not found\n");
1000 /* Try to probe v1 pen parameters */
1001 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1004 "failed probing pen v1 parameters: %d\n", rc);
1007 hid_dbg(hdev, "pen v1 parameters found\n");
1018 /* Link frame button subreports from pen reports */
1019 p.pen.subreport_list[0].value = 0xe0;
1020 p.pen.subreport_list[0].id =
1025 hid_dbg(hdev, "pen v1 parameters not found\n");
1042 * uclogic_probe_interface() - some tablets, like the Parblo A610 PLUS V2 or
1043 * the XP-PEN Deco Mini 7, need to be initialized by sending them magic data.
1065 rc = -EINVAL;
1071 rc = -ENOMEM;
1081 rc = -1;
1092 * uclogic_params_parse_ugee_v2_desc - parse the string descriptor containing
1093 * pen and frame parameters returned by UGEE v2 devices.
1120 return -EINVAL;
1123 return -EINVAL;
1154 * uclogic_params_ugee_v2_init_frame_buttons() - initialize a UGEE v2 frame with
1171 return -EINVAL;
1178 return -ENOMEM;
1180 rc = uclogic_params_frame_init_with_desc(&p->frame_list[0],
1189 * uclogic_params_ugee_v2_init_frame_dial() - initialize a UGEE v2 frame with a
1206 return -EINVAL;
1213 return -ENOMEM;
1215 rc = uclogic_params_frame_init_with_desc(&p->frame_list[0],
1223 p->frame_list[0].bitmap_dial_byte = 7;
1228 * uclogic_params_ugee_v2_init_frame_mouse() - initialize a UGEE v2 frame with a
1240 return -EINVAL;
1242 rc = uclogic_params_frame_init_with_desc(&p->frame_list[1],
1250 * uclogic_params_ugee_v2_has_battery() - check whether a UGEE v2 device has
1261 if (drvdata->quirks & UCLOGIC_BATTERY_QUIRK)
1264 /* The XP-PEN Deco LW vendor, product and version are identical to the
1269 if (hdev->vendor == USB_VENDOR_ID_UGEE &&
1270 hdev->product == USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) {
1273 if (strstarts(udev->product, "Deco LW"))
1281 * uclogic_params_ugee_v2_init_battery() - initialize UGEE v2 battery reporting.
1294 return -EINVAL;
1296 /* Some tablets contain invalid characters in hdev->uniq, throwing a
1300 snprintf(hdev->uniq, sizeof(hdev->uniq), "%x-%x", hdev->vendor,
1301 hdev->product);
1303 rc = uclogic_params_frame_init_with_desc(&p->frame_list[1],
1310 p->frame_list[1].suffix = "Battery";
1311 p->pen.subreport_list[1].value = 0xf2;
1312 p->pen.subreport_list[1].id = UCLOGIC_RDESC_UGEE_V2_BATTERY_ID;
1318 * uclogic_params_ugee_v2_reconnect_work() - When a wireless tablet looses
1330 uclogic_probe_interface(event_hook->hdev, uclogic_ugee_v2_probe_arr,
1336 * uclogic_params_ugee_v2_init_event_hooks() - initialize the list of events
1355 return -EINVAL;
1361 p->event_hooks = kzalloc(sizeof(*p->event_hooks), GFP_KERNEL);
1362 if (!p->event_hooks)
1363 return -ENOMEM;
1365 INIT_LIST_HEAD(&p->event_hooks->list);
1369 return -ENOMEM;
1371 INIT_WORK(&event_hook->work, uclogic_params_ugee_v2_reconnect_work);
1372 event_hook->hdev = hdev;
1373 event_hook->size = ARRAY_SIZE(reconnect_event);
1374 event_hook->event = kmemdup(reconnect_event, event_hook->size, GFP_KERNEL);
1375 if (!event_hook->event) {
1377 return -ENOMEM;
1380 list_add_tail(&event_hook->list, &p->event_hooks->list);
1386 * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by
1420 rc = -EINVAL;
1425 iface = to_usb_interface(hdev->dev.parent);
1426 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1455 * Read the string descriptor containing pen and frame parameters.
1461 hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc);
1476 /* Initialize the pen interface */
1482 rc = -ENOMEM;
1486 p.pen.desc_ptr = rdesc_pen;
1487 p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size;
1488 p.pen.id = 0x02;
1489 p.pen.subreport_list[0].value = 0xf0;
1490 p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
1493 if (drvdata->quirks & UCLOGIC_MOUSE_FRAME_QUIRK)
1540 * uclogic_params_init_ugee_xppen_pro() - Initializes a UGEE XP-Pen Pro tablet device.
1570 rc = -EINVAL;
1574 iface = to_usb_interface(hdev->dev.parent);
1575 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1577 /* Ignore non-pen interfaces */
1579 rc = -EINVAL;
1598 * Read the string descriptor containing pen and frame parameters.
1603 rc = (rc < 0) ? rc : -EINVAL;
1604 hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc);
1622 /* Initialize the pen interface */
1628 rc = -ENOMEM;
1632 p.pen.desc_ptr = rdesc_pen;
1633 p.pen.desc_size = rdesc_pen_size;
1634 p.pen.id = 0x02;
1635 p.pen.subreport_list[0].value = 0xf0;
1636 p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
1662 * uclogic_params_init() - initialize a tablet interface and discover its
1669 * parameters from. Cannot be NULL. Must be using the USB low-level
1689 rc = -EINVAL;
1694 bNumInterfaces = udev->config->desc.bNumInterfaces;
1695 iface = to_usb_interface(hdev->dev.parent);
1696 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
1731 switch (VID_PID(hdev->vendor, hdev->product)) {
1746 if (hdev->dev_rsize == UCLOGIC_RDESC_WP5540U_V2_ORIG_SIZE) {
1748 /* Try to probe v1 pen parameters */
1749 rc = uclogic_params_pen_init_v1(&p.pen,
1753 "pen probing failed: %d\n",
1759 "pen parameters not found");
1805 * If it is not a three-interface version, which is known to
1858 /* If this is the pen interface */
1860 /* Probe v1 pen parameters */
1861 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1863 hid_err(hdev, "pen probing failed: %d\n", rc);
1867 hid_warn(hdev, "pen parameters not found");
1876 /* If this is the pen and frame interface */
1878 /* Probe v1 pen parameters */
1879 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1881 hid_err(hdev, "pen probing failed: %d\n", rc);
1916 /* Ignore non-pen interfaces */
1922 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1924 hid_err(hdev, "pen probing failed: %d\n", rc);
1943 hid_warn(hdev, "pen parameters not found");
1950 /* Ignore non-pen interfaces */
1956 rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
1958 hid_err(hdev, "pen probing failed: %d\n", rc);
1973 hid_warn(hdev, "pen parameters not found");
2002 p.pen.fragmented_hires2 = true;
2023 #include "hid-uclogic-params-test.c"