Loading drivers/hid/hid-ids.h +1 −0 Original line number Diff line number Diff line Loading @@ -1409,6 +1409,7 @@ #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S 0x0909 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW 0x0933 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_22R_PRO 0x091b #define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074 #define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071 #define USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720 0x0055 Loading drivers/hid/hid-uclogic-core.c +62 −4 Original line number Diff line number Diff line Loading @@ -62,6 +62,30 @@ static const __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, return rdesc; } /* Buttons considered valid tablet pad inputs. */ static const unsigned int uclogic_extra_input_mapping[] = { BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8, BTN_RIGHT, BTN_MIDDLE, BTN_SIDE, BTN_EXTRA, BTN_FORWARD, BTN_BACK, BTN_B, BTN_A, BTN_BASE, BTN_BASE2, BTN_X }; static int uclogic_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, Loading @@ -72,9 +96,27 @@ static int uclogic_input_mapping(struct hid_device *hdev, struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); struct uclogic_params *params = &drvdata->params; if (field->application == HID_GD_KEYPAD) { /* * Remap input buttons to sensible ones that are not invalid. * This only affects previous behavior for devices with more than ten or so buttons. */ const int key = (usage->hid & HID_USAGE) - 1; if (key < ARRAY_SIZE(uclogic_extra_input_mapping)) { hid_map_usage(hi, usage, bit, max, EV_KEY, uclogic_extra_input_mapping[key]); return 1; } } else if (field->application == HID_DG_PEN) { /* Discard invalid pen usages */ if (params->pen.usage_invalid && (field->application == HID_DG_PEN)) if (params->pen.usage_invalid) return -1; } /* Let hid-core decide what to do */ return 0; Loading Loading @@ -407,8 +449,22 @@ static int uclogic_raw_event_frame( /* If need to, and can, transform the bitmap dial reports */ if (frame->bitmap_dial_byte > 0 && frame->bitmap_dial_byte < size) { if (data[frame->bitmap_dial_byte] == 2) switch (data[frame->bitmap_dial_byte]) { case 2: data[frame->bitmap_dial_byte] = -1; break; /* Everything below here is for tablets that shove multiple dials into 1 byte */ case 16: data[frame->bitmap_dial_byte] = 0; data[frame->bitmap_second_dial_destination_byte] = 1; break; case 32: data[frame->bitmap_dial_byte] = 0; data[frame->bitmap_second_dial_destination_byte] = -1; break; } } return 0; Loading Loading @@ -546,6 +602,8 @@ static const struct hid_device_id uclogic_devices[] = { .driver_data = UCLOGIC_MOUSE_FRAME_QUIRK | UCLOGIC_BATTERY_QUIRK }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_22R_PRO) }, { } }; MODULE_DEVICE_TABLE(hid, uclogic_devices); Loading drivers/hid/hid-uclogic-params.c +133 −1 Original line number Diff line number Diff line Loading @@ -103,6 +103,8 @@ static void uclogic_params_frame_hid_dbg( frame->touch_flip_at); hid_dbg(hdev, "\t\t.bitmap_dial_byte = %u\n", frame->bitmap_dial_byte); hid_dbg(hdev, "\t\t.bitmap_second_dial_destination_byte = %u\n", frame->bitmap_second_dial_destination_byte); } /** Loading Loading @@ -1341,7 +1343,7 @@ static int uclogic_params_ugee_v2_init_event_hooks(struct hid_device *hdev, struct uclogic_params *p) { struct uclogic_raw_event_hook *event_hook; __u8 reconnect_event[] = { static const __u8 reconnect_event[] = { /* Event received on wireless tablet reconnection */ 0x02, 0xF8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; Loading Loading @@ -1529,6 +1531,126 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, return rc; } /* * uclogic_params_init_ugee_xppen_pro_22r() - Initializes a UGEE XP-Pen Pro 22R tablet device. * * @hdev: The HID device of the tablet interface to initialize and get * parameters from. Cannot be NULL. * @params: Parameters to fill in (to be cleaned with * uclogic_params_cleanup()). Not modified in case of error. * Cannot be NULL. * * Returns: * Zero, if successful. A negative errno code on error. */ static int uclogic_params_init_ugee_xppen_pro_22r(struct uclogic_params *params, struct hid_device *hdev, const u8 rdesc_frame_arr[], const size_t rdesc_frame_size) { int rc = 0; struct usb_interface *iface; __u8 bInterfaceNumber; const int str_desc_len = 12; u8 *str_desc = NULL; __u8 *rdesc_pen = NULL; s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; enum uclogic_params_frame_type frame_type; /* The resulting parameters (noop) */ struct uclogic_params p = {0, }; if (!hdev || !params) { rc = -EINVAL; goto cleanup; } iface = to_usb_interface(hdev->dev.parent); bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; /* Ignore non-pen interfaces */ if (bInterfaceNumber != 2) { rc = -EINVAL; uclogic_params_init_invalid(&p); goto cleanup; } /* * Initialize the interface by sending magic data. * This magic data is the same as other UGEE v2 tablets. */ rc = uclogic_probe_interface(hdev, uclogic_ugee_v2_probe_arr, uclogic_ugee_v2_probe_size, uclogic_ugee_v2_probe_endpoint); if (rc) { uclogic_params_init_invalid(&p); goto cleanup; } /** * Read the string descriptor containing pen and frame parameters. * These are slightly different than typical UGEE v2 devices. */ rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len); if (rc != str_desc_len) { rc = (rc < 0) ? rc : -EINVAL; hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc); uclogic_params_init_invalid(&p); goto cleanup; } rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len, desc_params, ARRAY_SIZE(desc_params), &frame_type); if (rc) goto cleanup; // str_desc doesn't report the correct amount of buttons, so manually fix it desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 20; kfree(str_desc); str_desc = NULL; /* Initialize the pen interface */ rdesc_pen = uclogic_rdesc_template_apply( uclogic_rdesc_ugee_v2_pen_template_arr, uclogic_rdesc_ugee_v2_pen_template_size, desc_params, ARRAY_SIZE(desc_params)); if (!rdesc_pen) { rc = -ENOMEM; goto cleanup; } p.pen.desc_ptr = rdesc_pen; p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size; p.pen.id = 0x02; p.pen.subreport_list[0].value = 0xf0; p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID; /* Initialize the frame interface */ rc = uclogic_params_frame_init_with_desc( &p.frame_list[0], rdesc_frame_arr, rdesc_frame_size, UCLOGIC_RDESC_V1_FRAME_ID); if (rc < 0) { hid_err(hdev, "initializing frame params failed: %d\n", rc); goto cleanup; } p.frame_list[0].bitmap_dial_byte = 7; p.frame_list[0].bitmap_second_dial_destination_byte = 8; /* Output parameters */ memcpy(params, &p, sizeof(*params)); memset(&p, 0, sizeof(p)); cleanup: kfree(str_desc); uclogic_params_cleanup(&p); return rc; } /** * uclogic_params_init() - initialize a tablet interface and discover its * parameters. Loading Loading @@ -1845,6 +1967,16 @@ int uclogic_params_init(struct uclogic_params *params, uclogic_params_init_invalid(&p); } break; case VID_PID(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_22R_PRO): rc = uclogic_params_init_ugee_xppen_pro_22r(&p, hdev, uclogic_rdesc_xppen_artist_22r_pro_frame_arr, uclogic_rdesc_xppen_artist_22r_pro_frame_size); if (rc != 0) goto cleanup; break; } Loading drivers/hid/hid-uclogic-params.h +5 −0 Original line number Diff line number Diff line Loading @@ -175,6 +175,11 @@ struct uclogic_params_frame { * counterclockwise, as opposed to the normal 1 and -1. */ unsigned int bitmap_dial_byte; /* * Destination offset for the second bitmap dial byte, if the tablet * supports a second dial at all. */ unsigned int bitmap_second_dial_destination_byte; }; /* Loading drivers/hid/hid-uclogic-rdesc.c +44 −0 Original line number Diff line number Diff line Loading @@ -1193,6 +1193,50 @@ const __u8 uclogic_rdesc_xppen_deco01_frame_arr[] = { const size_t uclogic_rdesc_xppen_deco01_frame_size = sizeof(uclogic_rdesc_xppen_deco01_frame_arr); /* Fixed report descriptor for XP-Pen Arist 22R Pro frame */ const __u8 uclogic_rdesc_xppen_artist_22r_pro_frame_arr[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x07, /* Usage (Keypad), */ 0xA1, 0x01, /* Collection (Application), */ 0x85, UCLOGIC_RDESC_V1_FRAME_ID, /* Report ID (Virtual report), */ 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x39, /* Usage (Tablet Function Keys), */ 0xA0, /* Collection (Physical), */ 0x14, /* Logical Minimum (0), */ 0x25, 0x01, /* Logical Maximum (1), */ 0x75, 0x01, /* Report Size (1), */ 0x95, 0x08, /* Report Count (8), */ 0x81, 0x01, /* Input (Constant), */ 0x05, 0x09, /* Usage Page (Button), */ 0x19, 0x01, /* Usage Minimum (01h), */ 0x29, 0x14, /* Usage Maximum (14h), */ 0x95, 0x14, /* Report Count (20), */ 0x81, 0x02, /* Input (Variable), */ 0x95, 0x14, /* Report Count (20), */ 0x81, 0x01, /* Input (Constant), */ 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x38, /* Usage (Wheel), */ 0x75, 0x08, /* Report Size (8), */ 0x95, 0x01, /* Report Count (1), */ 0x15, 0xFF, /* Logical Minimum (-1), */ 0x25, 0x08, /* Logical Maximum (8), */ 0x81, 0x06, /* Input (Variable, Relative), */ 0x05, 0x0C, /* Usage Page (Consumer Devices), */ 0x0A, 0x38, 0x02, /* Usage (AC PAN), */ 0x95, 0x01, /* Report Count (1), */ 0x81, 0x06, /* Input (Variable, Relative), */ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 0x75, 0x08, /* Report Size (8), */ 0x95, 0x01, /* Report Count (1), */ 0x81, 0x02, /* Input (Variable), */ 0xC0, /* End Collection */ 0xC0, /* End Collection */ }; const size_t uclogic_rdesc_xppen_artist_22r_pro_frame_size = sizeof(uclogic_rdesc_xppen_artist_22r_pro_frame_arr); /** * uclogic_rdesc_template_apply() - apply report descriptor parameters to a * report descriptor template, creating a report descriptor. Copies the Loading Loading
drivers/hid/hid-ids.h +1 −0 Original line number Diff line number Diff line Loading @@ -1409,6 +1409,7 @@ #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S 0x0909 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW 0x0933 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_22R_PRO 0x091b #define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074 #define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071 #define USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720 0x0055 Loading
drivers/hid/hid-uclogic-core.c +62 −4 Original line number Diff line number Diff line Loading @@ -62,6 +62,30 @@ static const __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, return rdesc; } /* Buttons considered valid tablet pad inputs. */ static const unsigned int uclogic_extra_input_mapping[] = { BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8, BTN_RIGHT, BTN_MIDDLE, BTN_SIDE, BTN_EXTRA, BTN_FORWARD, BTN_BACK, BTN_B, BTN_A, BTN_BASE, BTN_BASE2, BTN_X }; static int uclogic_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, Loading @@ -72,9 +96,27 @@ static int uclogic_input_mapping(struct hid_device *hdev, struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); struct uclogic_params *params = &drvdata->params; if (field->application == HID_GD_KEYPAD) { /* * Remap input buttons to sensible ones that are not invalid. * This only affects previous behavior for devices with more than ten or so buttons. */ const int key = (usage->hid & HID_USAGE) - 1; if (key < ARRAY_SIZE(uclogic_extra_input_mapping)) { hid_map_usage(hi, usage, bit, max, EV_KEY, uclogic_extra_input_mapping[key]); return 1; } } else if (field->application == HID_DG_PEN) { /* Discard invalid pen usages */ if (params->pen.usage_invalid && (field->application == HID_DG_PEN)) if (params->pen.usage_invalid) return -1; } /* Let hid-core decide what to do */ return 0; Loading Loading @@ -407,8 +449,22 @@ static int uclogic_raw_event_frame( /* If need to, and can, transform the bitmap dial reports */ if (frame->bitmap_dial_byte > 0 && frame->bitmap_dial_byte < size) { if (data[frame->bitmap_dial_byte] == 2) switch (data[frame->bitmap_dial_byte]) { case 2: data[frame->bitmap_dial_byte] = -1; break; /* Everything below here is for tablets that shove multiple dials into 1 byte */ case 16: data[frame->bitmap_dial_byte] = 0; data[frame->bitmap_second_dial_destination_byte] = 1; break; case 32: data[frame->bitmap_dial_byte] = 0; data[frame->bitmap_second_dial_destination_byte] = -1; break; } } return 0; Loading Loading @@ -546,6 +602,8 @@ static const struct hid_device_id uclogic_devices[] = { .driver_data = UCLOGIC_MOUSE_FRAME_QUIRK | UCLOGIC_BATTERY_QUIRK }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_22R_PRO) }, { } }; MODULE_DEVICE_TABLE(hid, uclogic_devices); Loading
drivers/hid/hid-uclogic-params.c +133 −1 Original line number Diff line number Diff line Loading @@ -103,6 +103,8 @@ static void uclogic_params_frame_hid_dbg( frame->touch_flip_at); hid_dbg(hdev, "\t\t.bitmap_dial_byte = %u\n", frame->bitmap_dial_byte); hid_dbg(hdev, "\t\t.bitmap_second_dial_destination_byte = %u\n", frame->bitmap_second_dial_destination_byte); } /** Loading Loading @@ -1341,7 +1343,7 @@ static int uclogic_params_ugee_v2_init_event_hooks(struct hid_device *hdev, struct uclogic_params *p) { struct uclogic_raw_event_hook *event_hook; __u8 reconnect_event[] = { static const __u8 reconnect_event[] = { /* Event received on wireless tablet reconnection */ 0x02, 0xF8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; Loading Loading @@ -1529,6 +1531,126 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, return rc; } /* * uclogic_params_init_ugee_xppen_pro_22r() - Initializes a UGEE XP-Pen Pro 22R tablet device. * * @hdev: The HID device of the tablet interface to initialize and get * parameters from. Cannot be NULL. * @params: Parameters to fill in (to be cleaned with * uclogic_params_cleanup()). Not modified in case of error. * Cannot be NULL. * * Returns: * Zero, if successful. A negative errno code on error. */ static int uclogic_params_init_ugee_xppen_pro_22r(struct uclogic_params *params, struct hid_device *hdev, const u8 rdesc_frame_arr[], const size_t rdesc_frame_size) { int rc = 0; struct usb_interface *iface; __u8 bInterfaceNumber; const int str_desc_len = 12; u8 *str_desc = NULL; __u8 *rdesc_pen = NULL; s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; enum uclogic_params_frame_type frame_type; /* The resulting parameters (noop) */ struct uclogic_params p = {0, }; if (!hdev || !params) { rc = -EINVAL; goto cleanup; } iface = to_usb_interface(hdev->dev.parent); bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; /* Ignore non-pen interfaces */ if (bInterfaceNumber != 2) { rc = -EINVAL; uclogic_params_init_invalid(&p); goto cleanup; } /* * Initialize the interface by sending magic data. * This magic data is the same as other UGEE v2 tablets. */ rc = uclogic_probe_interface(hdev, uclogic_ugee_v2_probe_arr, uclogic_ugee_v2_probe_size, uclogic_ugee_v2_probe_endpoint); if (rc) { uclogic_params_init_invalid(&p); goto cleanup; } /** * Read the string descriptor containing pen and frame parameters. * These are slightly different than typical UGEE v2 devices. */ rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len); if (rc != str_desc_len) { rc = (rc < 0) ? rc : -EINVAL; hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc); uclogic_params_init_invalid(&p); goto cleanup; } rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len, desc_params, ARRAY_SIZE(desc_params), &frame_type); if (rc) goto cleanup; // str_desc doesn't report the correct amount of buttons, so manually fix it desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 20; kfree(str_desc); str_desc = NULL; /* Initialize the pen interface */ rdesc_pen = uclogic_rdesc_template_apply( uclogic_rdesc_ugee_v2_pen_template_arr, uclogic_rdesc_ugee_v2_pen_template_size, desc_params, ARRAY_SIZE(desc_params)); if (!rdesc_pen) { rc = -ENOMEM; goto cleanup; } p.pen.desc_ptr = rdesc_pen; p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size; p.pen.id = 0x02; p.pen.subreport_list[0].value = 0xf0; p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID; /* Initialize the frame interface */ rc = uclogic_params_frame_init_with_desc( &p.frame_list[0], rdesc_frame_arr, rdesc_frame_size, UCLOGIC_RDESC_V1_FRAME_ID); if (rc < 0) { hid_err(hdev, "initializing frame params failed: %d\n", rc); goto cleanup; } p.frame_list[0].bitmap_dial_byte = 7; p.frame_list[0].bitmap_second_dial_destination_byte = 8; /* Output parameters */ memcpy(params, &p, sizeof(*params)); memset(&p, 0, sizeof(p)); cleanup: kfree(str_desc); uclogic_params_cleanup(&p); return rc; } /** * uclogic_params_init() - initialize a tablet interface and discover its * parameters. Loading Loading @@ -1845,6 +1967,16 @@ int uclogic_params_init(struct uclogic_params *params, uclogic_params_init_invalid(&p); } break; case VID_PID(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_22R_PRO): rc = uclogic_params_init_ugee_xppen_pro_22r(&p, hdev, uclogic_rdesc_xppen_artist_22r_pro_frame_arr, uclogic_rdesc_xppen_artist_22r_pro_frame_size); if (rc != 0) goto cleanup; break; } Loading
drivers/hid/hid-uclogic-params.h +5 −0 Original line number Diff line number Diff line Loading @@ -175,6 +175,11 @@ struct uclogic_params_frame { * counterclockwise, as opposed to the normal 1 and -1. */ unsigned int bitmap_dial_byte; /* * Destination offset for the second bitmap dial byte, if the tablet * supports a second dial at all. */ unsigned int bitmap_second_dial_destination_byte; }; /* Loading
drivers/hid/hid-uclogic-rdesc.c +44 −0 Original line number Diff line number Diff line Loading @@ -1193,6 +1193,50 @@ const __u8 uclogic_rdesc_xppen_deco01_frame_arr[] = { const size_t uclogic_rdesc_xppen_deco01_frame_size = sizeof(uclogic_rdesc_xppen_deco01_frame_arr); /* Fixed report descriptor for XP-Pen Arist 22R Pro frame */ const __u8 uclogic_rdesc_xppen_artist_22r_pro_frame_arr[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x07, /* Usage (Keypad), */ 0xA1, 0x01, /* Collection (Application), */ 0x85, UCLOGIC_RDESC_V1_FRAME_ID, /* Report ID (Virtual report), */ 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x39, /* Usage (Tablet Function Keys), */ 0xA0, /* Collection (Physical), */ 0x14, /* Logical Minimum (0), */ 0x25, 0x01, /* Logical Maximum (1), */ 0x75, 0x01, /* Report Size (1), */ 0x95, 0x08, /* Report Count (8), */ 0x81, 0x01, /* Input (Constant), */ 0x05, 0x09, /* Usage Page (Button), */ 0x19, 0x01, /* Usage Minimum (01h), */ 0x29, 0x14, /* Usage Maximum (14h), */ 0x95, 0x14, /* Report Count (20), */ 0x81, 0x02, /* Input (Variable), */ 0x95, 0x14, /* Report Count (20), */ 0x81, 0x01, /* Input (Constant), */ 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x38, /* Usage (Wheel), */ 0x75, 0x08, /* Report Size (8), */ 0x95, 0x01, /* Report Count (1), */ 0x15, 0xFF, /* Logical Minimum (-1), */ 0x25, 0x08, /* Logical Maximum (8), */ 0x81, 0x06, /* Input (Variable, Relative), */ 0x05, 0x0C, /* Usage Page (Consumer Devices), */ 0x0A, 0x38, 0x02, /* Usage (AC PAN), */ 0x95, 0x01, /* Report Count (1), */ 0x81, 0x06, /* Input (Variable, Relative), */ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 0x75, 0x08, /* Report Size (8), */ 0x95, 0x01, /* Report Count (1), */ 0x81, 0x02, /* Input (Variable), */ 0xC0, /* End Collection */ 0xC0, /* End Collection */ }; const size_t uclogic_rdesc_xppen_artist_22r_pro_frame_size = sizeof(uclogic_rdesc_xppen_artist_22r_pro_frame_arr); /** * uclogic_rdesc_template_apply() - apply report descriptor parameters to a * report descriptor template, creating a report descriptor. Copies the Loading