mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
Merge branch 'for-6.17/uclogic' into for-linus
- support for XP-PEN Artist 22R Pro (Joshua Goins)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
@@ -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;
|
||||
|
||||
/* Discard invalid pen usages */
|
||||
if (params->pen.usage_invalid && (field->application == HID_DG_PEN))
|
||||
return -1;
|
||||
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)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Let hid-core decide what to do */
|
||||
return 0;
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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
|
||||
};
|
||||
@@ -1529,6 +1531,126 @@ cleanup:
|
||||
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.
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -210,4 +210,8 @@ extern const size_t uclogic_rdesc_ugee_g5_frame_size;
|
||||
/* Least-significant bit of Ugee G5 frame rotary encoder state */
|
||||
#define UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB 38
|
||||
|
||||
/* Fixed report descriptor for XP-Pen Arist 22R Pro frame */
|
||||
extern const __u8 uclogic_rdesc_xppen_artist_22r_pro_frame_arr[];
|
||||
extern const size_t uclogic_rdesc_xppen_artist_22r_pro_frame_size;
|
||||
|
||||
#endif /* _HID_UCLOGIC_RDESC_H */
|
||||
|
||||
Reference in New Issue
Block a user