Skip to content

Commit ba98c79

Browse files
author
zan
committed
XP-Pen Artist 15.6 Pro support
1 parent 691dae8 commit ba98c79

File tree

5 files changed

+303
-0
lines changed

5 files changed

+303
-0
lines changed

hid-ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640 0x0094
5555
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042
5656
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078
57+
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_A156P 0x090d
5758
#define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074
5859
#define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071
5960
#define USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720 0x0055

hid-uclogic-core.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "compat.h"
2626
#include <linux/version.h>
27+
#include <asm/unaligned.h>
2728

2829
/* Driver data */
2930
struct uclogic_drvdata {
@@ -474,6 +475,57 @@ static int uclogic_raw_event(struct hid_device *hdev,
474475
break;
475476
}
476477

478+
/* A156P tilt compensation */
479+
if (hdev->product == USB_DEVICE_ID_UGEE_XPPEN_TABLET_A156P &&
480+
hdev->vendor == USB_VENDOR_ID_UGEE) {
481+
/* All tangent lengths for pen angles 1-64
482+
* degrees with a sensor height of 1.8mm
483+
*/
484+
const u16 tangents[] = {
485+
3, 6, 9, 12, 15, 18, 21, 25, 28, 30, 33, 36,
486+
39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70,
487+
73, 76, 79, 82, 85, 88, 92, 95, 98, 102,
488+
105, 109, 112, 116, 120, 124, 127, 131,
489+
135, 140, 144, 148, 153, 158, 162, 167,
490+
173, 178, 184, 189, 195, 202, 208, 215,
491+
223, 231, 239, 247, 257, 266, 277
492+
};
493+
// sqrt(8) / 4 = 0.7071067811865476
494+
const s32 discriminant = 7071068;
495+
s8 tx = data[8];
496+
s8 ty = data[9];
497+
s8 abs_tilt;
498+
s32 skew;
499+
500+
if (tx != 0 && ty != 0) {
501+
abs_tilt = abs(tx);
502+
skew = get_unaligned_le16(&data[2]) -
503+
(tx / abs_tilt) * tangents[abs_tilt] *
504+
discriminant / 10000000;
505+
skew = clamp(skew, 0, 34419);
506+
put_unaligned_le16(skew, &data[2]);
507+
508+
abs_tilt = abs(ty);
509+
skew = get_unaligned_le16(&data[4]) -
510+
(ty / abs_tilt) * tangents[abs_tilt] *
511+
discriminant / 10000000;
512+
skew = clamp(skew, 0, 19461);
513+
put_unaligned_le16(skew, &data[4]);
514+
} else if (tx != 0) {
515+
abs_tilt = abs(tx);
516+
skew = get_unaligned_le16(&data[2]) -
517+
(tx / abs_tilt) * tangents[abs_tilt];
518+
skew = clamp(skew, 0, 34419);
519+
put_unaligned_le16(skew, &data[2]);
520+
} else if (ty != 0) {
521+
abs_tilt = abs(ty);
522+
skew = get_unaligned_le16(&data[4]) -
523+
(ty / abs_tilt) * tangents[abs_tilt];
524+
skew = clamp(skew, 0, 19461);
525+
put_unaligned_le16(skew, &data[4]);
526+
}
527+
}
528+
477529
return 0;
478530
}
479531

@@ -534,6 +586,8 @@ static const struct hid_device_id uclogic_devices[] = {
534586
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01) },
535587
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
536588
USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06) },
589+
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
590+
USB_DEVICE_ID_UGEE_XPPEN_TABLET_A156P) },
537591
{ }
538592
};
539593
MODULE_DEVICE_TABLE(hid, uclogic_devices);

hid-uclogic-params.c

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,129 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
998998
return rc;
999999
}
10001000

1001+
/**
1002+
* uclogic_params_init_ugee_xppen_pro() - initialization procedure
1003+
* common to XP-Pen Pro series devices
1004+
*
1005+
* @hdev: The HID device of the tablet interface to initialize and get
1006+
* parameters from. Cannot be NULL.
1007+
* @params: Parameters to fill in (to be cleaned with
1008+
* uclogic_params_cleanup()). Not modified in case of error.
1009+
* Cannot be NULL.
1010+
*
1011+
* Returns:
1012+
* Zero, if successful. A negative errno code on error.
1013+
*/
1014+
static int uclogic_params_init_ugee_xppen_pro(struct hid_device *hdev,
1015+
struct uclogic_params *p)
1016+
{
1017+
static const u8 init_packet[] = {
1018+
0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1019+
};
1020+
const size_t packet_size = sizeof(init_packet);
1021+
const size_t str_desc_len = 12;
1022+
struct usb_device *udev = hid_to_usb_dev(hdev);
1023+
u8 *buf = kmemdup(init_packet, packet_size, GFP_KERNEL);
1024+
s32 desc_params[UCLOGIC_RDESC_PEN_PH_ID_NUM];
1025+
int actual_len, rc;
1026+
u16 resolution;
1027+
1028+
if (hdev == NULL || p == NULL)
1029+
return -EINVAL;
1030+
1031+
rc = usb_interrupt_msg(
1032+
udev,
1033+
usb_sndintpipe(udev, 0x03),
1034+
buf,
1035+
packet_size,
1036+
&actual_len,
1037+
USB_CTRL_SET_TIMEOUT);
1038+
kfree(buf);
1039+
if (rc == -EPIPE) {
1040+
hid_err(hdev,
1041+
"broken pipe sending init packet\n");
1042+
return rc;
1043+
} else if (rc < 0) {
1044+
hid_err(hdev, "failed sending init packet: %d\n", rc);
1045+
return rc;
1046+
} else if (actual_len != packet_size) {
1047+
hid_err(hdev,
1048+
"failed to transfer complete init packet, only %d bytes sent\n",
1049+
actual_len);
1050+
return -1;
1051+
}
1052+
1053+
rc = uclogic_params_get_str_desc(&buf, hdev, 100, str_desc_len);
1054+
if (rc != str_desc_len) {
1055+
if (rc == -EPIPE) {
1056+
hid_err(hdev,
1057+
"string descriptor with pen parameters not found\n");
1058+
} else if (rc < 0) {
1059+
hid_err(hdev,
1060+
"failed retrieving pen parameters: %d\n", rc);
1061+
} else {
1062+
hid_err(hdev,
1063+
"string descriptor with pen parameters has invalid length (got %d, expected %lu)\n",
1064+
rc, str_desc_len);
1065+
rc = -1;
1066+
}
1067+
kfree(buf);
1068+
return rc;
1069+
}
1070+
1071+
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] =
1072+
get_unaligned_le16(buf + 2);
1073+
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] =
1074+
get_unaligned_le16(buf + 4);
1075+
/* buf + 6 is the number of pad buttons? Its 0x0008 */
1076+
desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] =
1077+
get_unaligned_le16(buf + 8);
1078+
resolution = get_unaligned_le16(buf + 10);
1079+
kfree(buf);
1080+
if (resolution == 0) {
1081+
hid_err(hdev, "resolution of 0 in descriptor string\n");
1082+
return -1;
1083+
}
1084+
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] =
1085+
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 / resolution;
1086+
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] =
1087+
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 / resolution;
1088+
1089+
hid_dbg(
1090+
hdev,
1091+
"Received parameters: X: %d Y: %d Pressure: %d Resolution: %u\n",
1092+
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM],
1093+
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM],
1094+
desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM],
1095+
resolution
1096+
);
1097+
1098+
p->pen.desc_ptr = uclogic_rdesc_template_apply(
1099+
uclogic_rdesc_xppen_a156p_pen_arr,
1100+
uclogic_rdesc_xppen_a156p_pen_size,
1101+
desc_params,
1102+
ARRAY_SIZE(desc_params)
1103+
);
1104+
p->pen.desc_size = uclogic_rdesc_xppen_a156p_pen_size;
1105+
p->pen.id = 0x02;
1106+
1107+
rc = uclogic_params_frame_init_with_desc(
1108+
&p->frame_list[0],
1109+
uclogic_rdesc_xppen_a156p_frame_arr,
1110+
uclogic_rdesc_xppen_a156p_frame_size,
1111+
UCLOGIC_RDESC_V1_FRAME_ID
1112+
);
1113+
if (rc < 0) {
1114+
hid_err(hdev, "initializing frame params failed: %d\n", rc);
1115+
return rc;
1116+
}
1117+
1118+
p->pen.subreport_list[0].value = 0xf0;
1119+
p->pen.subreport_list[0].id = p->frame_list[0].id;
1120+
1121+
return 0;
1122+
}
1123+
10011124
/**
10021125
* uclogic_params_init() - initialize a tablet interface and discover its
10031126
* parameters.
@@ -1293,6 +1416,21 @@ int uclogic_params_init(struct uclogic_params *params,
12931416
uclogic_params_init_invalid(&p);
12941417
}
12951418

1419+
break;
1420+
case VID_PID(USB_VENDOR_ID_UGEE,
1421+
USB_DEVICE_ID_UGEE_XPPEN_TABLET_A156P):
1422+
/* Only use the uniform interface */
1423+
if (bInterfaceNumber != 2) {
1424+
uclogic_params_init_invalid(&p);
1425+
break;
1426+
}
1427+
1428+
rc = uclogic_params_init_ugee_xppen_pro (hdev, &p);
1429+
if (rc != 0) {
1430+
hid_err(hdev, "a156p init failed: %d\n", rc);
1431+
goto cleanup;
1432+
}
1433+
12961434
break;
12971435
}
12981436

hid-uclogic-rdesc.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,108 @@ const __u8 uclogic_rdesc_xppen_deco01_frame_arr[] = {
975975
const size_t uclogic_rdesc_xppen_deco01_frame_size =
976976
sizeof(uclogic_rdesc_xppen_deco01_frame_arr);
977977

978+
/* Report descriptor template for XP-Pen Artist 15.6 Pro pen */
979+
const __u8 uclogic_rdesc_xppen_a156p_pen_arr[] = {
980+
0x05, 0x0D, /* Usage Page (Digitizer), */
981+
0x09, 0x02, /* Usage (Pen), */
982+
0xA1, 0x01, /* Collection (Application), */
983+
0x85, 0x02, /* Report ID (2), */
984+
0x09, 0x20, /* Usage (Stylus), */
985+
0xA0, /* Collection (Physical), */
986+
0x14, /* Logical Minimum (0), */
987+
0x25, 0x01, /* Logical Maximum (1), */
988+
0x09, 0x42, /* Usage (Tip Switch), */
989+
0x09, 0x44, /* Usage (Barrel Switch), */
990+
0x09, 0x46, /* Usage (Tablet Pick), */
991+
0x75, 0x01, /* Report Size (1), */
992+
0x95, 0x03, /* Report Count (3), */
993+
0x81, 0x02, /* Input (Variable), */
994+
0x95, 0x02, /* Report Count (2), */
995+
0x81, 0x01, /* Input (Constant), */
996+
0x09, 0x32, /* Usage (In Range), */
997+
0x95, 0x01, /* Report Count (1), */
998+
0x81, 0x02, /* Input (Variable), */
999+
0x95, 0x02, /* Report Count (2), */
1000+
0x81, 0x01, /* Input (Constant), */
1001+
0x75, 0x10, /* Report Size (16), */
1002+
0x95, 0x01, /* Report Count (1), */
1003+
0xA4, /* Push, */
1004+
0x05, 0x01, /* Usage Page (Desktop), */
1005+
0x55, 0xFD, /* Unit Exponent (-3), */
1006+
0x65, 0x13, /* Unit (Inch), */
1007+
0x34, /* Physical Minimum (0), */
1008+
0x09, 0x30, /* Usage (X), */
1009+
0x27, UCLOGIC_RDESC_PEN_PH(X_LM),
1010+
/* Logical Maximum (PLACEHOLDER), */
1011+
0x47, UCLOGIC_RDESC_PEN_PH(X_PM),
1012+
/* Physical Maximum (PLACEHOLDER), */
1013+
0x81, 0x02, /* Input (Variable), */
1014+
0x09, 0x31, /* Usage (Y), */
1015+
0x27, UCLOGIC_RDESC_PEN_PH(Y_LM),
1016+
/* Logical Maximum (PLACEHOLDER), */
1017+
0x47, UCLOGIC_RDESC_PEN_PH(Y_PM),
1018+
/* Physical Maximum (PLACEHOLDER), */
1019+
0x81, 0x02, /* Input (Variable), */
1020+
0xB4, /* Pop, */
1021+
0x09, 0x30, /* Usage (Tip Pressure), */
1022+
0x27, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM),
1023+
/* Logical Maximum (PLACEHOLDER), */
1024+
0x81, 0x02, /* Input (Variable), */
1025+
0xA4, /* Push, */
1026+
0x54, /* Unit Exponent (0), */
1027+
0x65, 0x14, /* Unit (Degrees), */
1028+
0x35, 0xC3, /* Physical Minimum (-61), */
1029+
0x45, 0x3C, /* Physical Maximum (60), */
1030+
0x15, 0xC3, /* Logical Minimum (-61), */
1031+
0x25, 0x3C, /* Logical Maximum (60), */
1032+
0x75, 0x08, /* Report Size (8), */
1033+
0x95, 0x02, /* Report Count (2), */
1034+
0x09, 0x3D, /* Usage (X Tilt), */
1035+
0x09, 0x3E, /* Usage (Y Tilt), */
1036+
0x81, 0x02, /* Input (Variable), */
1037+
0xB4, /* Pop, */
1038+
0xC0, /* End Collection, */
1039+
0xC0 /* End Collection */
1040+
};
1041+
1042+
const size_t uclogic_rdesc_xppen_a156p_pen_size =
1043+
sizeof(uclogic_rdesc_xppen_a156p_pen_arr);
1044+
1045+
/* Report descriptor template for XP-Pen Artist 15.6 Pro frame */
1046+
const __u8 uclogic_rdesc_xppen_a156p_frame_arr[] = {
1047+
0x05, 0x01, /* Usage Page (Desktop), */
1048+
0x09, 0x07, /* Usage (Keypad), */
1049+
0xA1, 0x01, /* Collection (Application), */
1050+
0x85, UCLOGIC_RDESC_V1_FRAME_ID,
1051+
/* Report ID (Virtual report), */
1052+
0x05, 0x0D, /* Usage Page (Digitizer), */
1053+
0x09, 0x39, /* Usage (Tablet Function Keys), */
1054+
0xA0, /* Collection (Physical), */
1055+
0x14, /* Logical Minimum (0), */
1056+
0x25, 0x01, /* Logical Maximum (1), */
1057+
0x75, 0x01, /* Report Size (1), */
1058+
0x95, 0x08, /* Report Count (8), */
1059+
0x81, 0x01, /* Input (Constant), */
1060+
0x05, 0x09, /* Usage Page (Button), */
1061+
0x19, 0x01, /* Usage Minimum (01h), */
1062+
0x29, 0x08, /* Usage Maximum (08h), */
1063+
0x95, 0x08, /* Report Count (8), */
1064+
0x81, 0x02, /* Input (Variable), */
1065+
0x95, 0x20, /* Report Count (32), */
1066+
0x81, 0x01, /* Input (Constant), */
1067+
0x19, 0x09, /* Usage Minimum (09h), */
1068+
0x29, 0x0A, /* Usage Maximum (0Ah), */
1069+
0x95, 0x02, /* Report Count (2), */
1070+
0x81, 0x02, /* Input (Variable), */
1071+
0x95, 0x16, /* Report Count (22), */
1072+
0x81, 0x01, /* Input (Constant), */
1073+
0xC0, /* End Collection, */
1074+
0xC0 /* End Collection */
1075+
};
1076+
1077+
const size_t uclogic_rdesc_xppen_a156p_frame_size =
1078+
sizeof(uclogic_rdesc_xppen_a156p_frame_arr);
1079+
9781080
/**
9791081
* uclogic_rdesc_template_apply() - apply report descriptor parameters to a
9801082
* report descriptor template, creating a report descriptor. Copies the

hid-uclogic-rdesc.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,14 @@ extern const size_t uclogic_rdesc_xppen_deco01_frame_size;
167167
extern const __u8 uclogic_rdesc_ugee_g5_frame_arr[];
168168
extern const size_t uclogic_rdesc_ugee_g5_frame_size;
169169

170+
/* Report descriptor template for XP-Pen Artist 15.6 Pro pen */
171+
extern const __u8 uclogic_rdesc_xppen_a156p_pen_arr[];
172+
extern const size_t uclogic_rdesc_xppen_a156p_pen_size;
173+
174+
/* Report descriptor template for XP-Pen Artist 15.6 Pro frame */
175+
extern const __u8 uclogic_rdesc_xppen_a156p_frame_arr[];
176+
extern const size_t uclogic_rdesc_xppen_a156p_frame_size;
177+
170178
/* Report ID of Ugee G5 frame control reports */
171179
#define UCLOGIC_RDESC_UGEE_G5_FRAME_ID 0x06
172180

0 commit comments

Comments
 (0)