Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XP-Pen Arist 15.6 Pro Support #291

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions hid-ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640 0x0094
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_A156P 0x090d
#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
Expand Down
54 changes: 54 additions & 0 deletions hid-uclogic-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "compat.h"
#include <linux/version.h>
#include <asm/unaligned.h>

/* Driver data */
struct uclogic_drvdata {
Expand Down Expand Up @@ -458,6 +459,57 @@ static int uclogic_raw_event(struct hid_device *hdev,
report_id = data[0] = subreport->id;
continue;
} else {
/* A156P tilt compensation */
if (hdev->product == USB_DEVICE_ID_UGEE_XPPEN_TABLET_A156P &&
hdev->vendor == USB_VENDOR_ID_UGEE) {
/* All tangent lengths for pen angles 1-64
* degrees with a sensor height of 1.8mm
*/
const u16 tangents[] = {
3, 6, 9, 12, 15, 18, 21, 25, 28, 30, 33, 36,
39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70,
73, 76, 79, 82, 85, 88, 92, 95, 98, 102,
105, 109, 112, 116, 120, 124, 127, 131,
135, 140, 144, 148, 153, 158, 162, 167,
173, 178, 184, 189, 195, 202, 208, 215,
223, 231, 239, 247, 257, 266, 277
};
// sqrt(8) / 4 = 0.7071067811865476
const s32 discriminant = 707106781;
s8 tx = data[8];
s8 ty = data[9];
s8 abs_tilt;
s32 skew;

if (tx != 0 && ty != 0) {
abs_tilt = abs(tx);
skew = get_unaligned_le16(&data[2]) -
(tx / abs_tilt) * tangents[abs_tilt] *
discriminant / 10000000;
skew = clamp(skew, 0, 34419);
put_unaligned_le16(skew, &data[2]);

abs_tilt = abs(ty);
skew = get_unaligned_le16(&data[4]) -
(ty / abs_tilt) * tangents[abs_tilt] *
discriminant / 10000000;
skew = clamp(skew, 0, 19461);
put_unaligned_le16(skew, &data[4]);
} else if (tx != 0) {
abs_tilt = abs(tx);
skew = get_unaligned_le16(&data[2]) -
(tx / abs_tilt) * tangents[abs_tilt];
skew = clamp(skew, 0, 34419);
put_unaligned_le16(skew, &data[2]);
} else if (ty != 0) {
abs_tilt = abs(ty);
skew = get_unaligned_le16(&data[4]) -
(ty / abs_tilt) * tangents[abs_tilt];
skew = clamp(skew, 0, 19461);
put_unaligned_le16(skew, &data[4]);
}
}

return uclogic_raw_event_pen(drvdata, data, size);
}
}
Expand Down Expand Up @@ -534,6 +586,8 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01) },
{ 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_A156P) },
{ }
};
MODULE_DEVICE_TABLE(hid, uclogic_devices);
Expand Down
153 changes: 153 additions & 0 deletions hid-uclogic-params.c
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,135 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
return rc;
}

/**
* uclogic_params_init_ugee_xppen_pro() - initialization procedure
* common to XP-Pen Pro series devices
*
* @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.
* @interface: The device interface the control packet is sent to.
* @init_packet: Magic packet to send on usb to activate device.
* @packet_size: Size of the init packet.
* @rdesc_pen_arr: Pen report descriptor array.
* @rdesc_pen_size: Size of the pen array.
* @rdesc_frame_arr: Frame report descriptor array.
* @rdesc_frame_size: Size of the frame array.
*
* Returns:
* Zero, if successful. A negative errno code on error.
*/
static int uclogic_params_init_ugee_xppen_pro(struct hid_device *hdev,
struct uclogic_params *p, const uint8_t interface,
const u8 init_packet[], const size_t packet_size,
const u8 rdesc_pen_arr[], const size_t rdesc_pen_size,
const u8 rdesc_frame_arr[], const size_t rdesc_frame_size)
{
const size_t str_desc_len = 12;
struct usb_device *udev = hid_to_usb_dev(hdev);
u8 *buf = kmemdup(init_packet, packet_size, GFP_KERNEL);
s32 desc_params[UCLOGIC_RDESC_PEN_PH_ID_NUM];
int actual_len, rc;
u16 resolution;

if (hdev == NULL || p == NULL)
return -EINVAL;

rc = usb_interrupt_msg(
udev,
usb_sndintpipe(udev, interface),
buf,
packet_size,
&actual_len,
USB_CTRL_SET_TIMEOUT);
kfree(buf);
if (rc == -EPIPE) {
hid_err(hdev,
"broken pipe sending init packet\n");
return rc;
} else if (rc < 0) {
hid_err(hdev, "failed sending init packet: %d\n", rc);
return rc;
} else if (actual_len != packet_size) {
hid_err(hdev,
"failed to transfer complete init packet, only %d bytes sent\n",
actual_len);
return -1;
}

rc = uclogic_params_get_str_desc(&buf, hdev, 100, str_desc_len);
if (rc != str_desc_len) {
if (rc == -EPIPE) {
hid_err(hdev,
"string descriptor with pen parameters not found\n");
} else if (rc < 0) {
hid_err(hdev,
"failed retrieving pen parameters: %d\n", rc);
} else {
hid_err(hdev,
"string descriptor with pen parameters has invalid length (got %d, expected %lu)\n",
rc, str_desc_len);
rc = -1;
}
kfree(buf);
return rc;
}

desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] =
get_unaligned_le16(buf + 2);
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] =
get_unaligned_le16(buf + 4);
/* buf + 6 is the number of pad buttons? Its 0x0008 */
desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] =
get_unaligned_le16(buf + 8);
resolution = get_unaligned_le16(buf + 10);
kfree(buf);
if (resolution == 0) {
hid_err(hdev, "resolution of 0 in descriptor string\n");
return -1;
}
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] =
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 / resolution;
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] =
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 / resolution;

hid_dbg(
hdev,
"Received parameters: X: %d Y: %d Pressure: %d Resolution: %u\n",
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM],
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM],
desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM],
resolution
);

p->pen.desc_ptr = uclogic_rdesc_template_apply(
rdesc_pen_arr,
rdesc_pen_size,
desc_params,
ARRAY_SIZE(desc_params)
);
p->pen.desc_size = rdesc_pen_size;
p->pen.id = 0x02;

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);
return rc;
}

p->pen.subreport_list[0].value = 0xf0;
p->pen.subreport_list[0].id = p->frame_list[0].id;

return 0;
}

/**
* uclogic_params_init() - initialize a tablet interface and discover its
* parameters.
Expand Down Expand Up @@ -1293,6 +1422,30 @@ 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_A156P):
static const u8 init_packet[] = {
0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const size_t packet_size = sizeof(init_packet);

/* Only use the uniform interface */
if (bInterfaceNumber != 2) {
uclogic_params_init_invalid(&p);
break;
}

rc = uclogic_params_init_ugee_xppen_pro(hdev, &p, 0x03, init_packet, packet_size,
uclogic_rdesc_xppen_a156p_pen_arr,
uclogic_rdesc_xppen_a156p_pen_size,
uclogic_rdesc_xppen_a156p_frame_arr,
uclogic_rdesc_xppen_a156p_frame_size);
if (rc != 0) {
hid_err(hdev, "a156p init failed: %d\n", rc);
goto cleanup;
}

break;
}

Expand Down
102 changes: 102 additions & 0 deletions hid-uclogic-rdesc.c
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,108 @@ const __u8 uclogic_rdesc_xppen_deco01_frame_arr[] = {
const size_t uclogic_rdesc_xppen_deco01_frame_size =
sizeof(uclogic_rdesc_xppen_deco01_frame_arr);

/* Report descriptor template for XP-Pen Artist 15.6 Pro pen */
const __u8 uclogic_rdesc_xppen_a156p_pen_arr[] = {
0x05, 0x0D, /* Usage Page (Digitizer), */
0x09, 0x02, /* Usage (Pen), */
0xA1, 0x01, /* Collection (Application), */
0x85, 0x02, /* Report ID (2), */
0x09, 0x20, /* Usage (Stylus), */
0xA0, /* Collection (Physical), */
0x14, /* Logical Minimum (0), */
0x25, 0x01, /* Logical Maximum (1), */
0x09, 0x42, /* Usage (Tip Switch), */
0x09, 0x44, /* Usage (Barrel Switch), */
0x09, 0x46, /* Usage (Tablet Pick), */
0x75, 0x01, /* Report Size (1), */
0x95, 0x03, /* Report Count (3), */
0x81, 0x02, /* Input (Variable), */
0x95, 0x02, /* Report Count (2), */
0x81, 0x01, /* Input (Constant), */
0x09, 0x32, /* Usage (In Range), */
0x95, 0x01, /* Report Count (1), */
0x81, 0x02, /* Input (Variable), */
0x95, 0x02, /* Report Count (2), */
0x81, 0x01, /* Input (Constant), */
0x75, 0x10, /* Report Size (16), */
0x95, 0x01, /* Report Count (1), */
0xA4, /* Push, */
0x05, 0x01, /* Usage Page (Desktop), */
0x55, 0xFD, /* Unit Exponent (-3), */
0x65, 0x13, /* Unit (Inch), */
0x34, /* Physical Minimum (0), */
0x09, 0x30, /* Usage (X), */
0x27, UCLOGIC_RDESC_PEN_PH(X_LM),
/* Logical Maximum (PLACEHOLDER), */
0x47, UCLOGIC_RDESC_PEN_PH(X_PM),
/* Physical Maximum (PLACEHOLDER), */
0x81, 0x02, /* Input (Variable), */
0x09, 0x31, /* Usage (Y), */
0x27, UCLOGIC_RDESC_PEN_PH(Y_LM),
/* Logical Maximum (PLACEHOLDER), */
0x47, UCLOGIC_RDESC_PEN_PH(Y_PM),
/* Physical Maximum (PLACEHOLDER), */
0x81, 0x02, /* Input (Variable), */
0xB4, /* Pop, */
0x09, 0x30, /* Usage (Tip Pressure), */
0x27, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM),
/* Logical Maximum (PLACEHOLDER), */
0x81, 0x02, /* Input (Variable), */
0xA4, /* Push, */
0x54, /* Unit Exponent (0), */
0x65, 0x14, /* Unit (Degrees), */
0x35, 0xC3, /* Physical Minimum (-61), */
0x45, 0x3C, /* Physical Maximum (60), */
0x15, 0xC3, /* Logical Minimum (-61), */
0x25, 0x3C, /* Logical Maximum (60), */
0x75, 0x08, /* Report Size (8), */
0x95, 0x02, /* Report Count (2), */
0x09, 0x3D, /* Usage (X Tilt), */
0x09, 0x3E, /* Usage (Y Tilt), */
0x81, 0x02, /* Input (Variable), */
0xB4, /* Pop, */
0xC0, /* End Collection, */
0xC0 /* End Collection */
};

const size_t uclogic_rdesc_xppen_a156p_pen_size =
sizeof(uclogic_rdesc_xppen_a156p_pen_arr);

/* Report descriptor template for XP-Pen Artist 15.6 Pro frame */
const __u8 uclogic_rdesc_xppen_a156p_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, 0x08, /* Usage Maximum (08h), */
0x95, 0x08, /* Report Count (8), */
0x81, 0x02, /* Input (Variable), */
0x95, 0x20, /* Report Count (32), */
0x81, 0x01, /* Input (Constant), */
0x19, 0x09, /* Usage Minimum (09h), */
0x29, 0x0A, /* Usage Maximum (0Ah), */
0x95, 0x02, /* Report Count (2), */
0x81, 0x02, /* Input (Variable), */
0x95, 0x16, /* Report Count (22), */
0x81, 0x01, /* Input (Constant), */
0xC0, /* End Collection, */
0xC0 /* End Collection */
};

const size_t uclogic_rdesc_xppen_a156p_frame_size =
sizeof(uclogic_rdesc_xppen_a156p_frame_arr);

/**
* uclogic_rdesc_template_apply() - apply report descriptor parameters to a
* report descriptor template, creating a report descriptor. Copies the
Expand Down
8 changes: 8 additions & 0 deletions hid-uclogic-rdesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,14 @@ extern const size_t uclogic_rdesc_xppen_deco01_frame_size;
extern const __u8 uclogic_rdesc_ugee_g5_frame_arr[];
extern const size_t uclogic_rdesc_ugee_g5_frame_size;

/* Report descriptor template for XP-Pen Artist 15.6 Pro pen */
extern const __u8 uclogic_rdesc_xppen_a156p_pen_arr[];
extern const size_t uclogic_rdesc_xppen_a156p_pen_size;

/* Report descriptor template for XP-Pen Artist 15.6 Pro frame */
extern const __u8 uclogic_rdesc_xppen_a156p_frame_arr[];
extern const size_t uclogic_rdesc_xppen_a156p_frame_size;

/* Report ID of Ugee G5 frame control reports */
#define UCLOGIC_RDESC_UGEE_G5_FRAME_ID 0x06

Expand Down