Skip to content

Commit f9ce4db

Browse files
JoseExpositoJiri Kosina
authored andcommitted
HID: uclogic: Add support for XP-PEN Deco LW
The XP-PEN Deco LW is a UGEE v2 device with a frame with 8 buttons. Its pen has 2 buttons, supports tilt and pressure. It can be connected by USB cable or using a USB Bluetooth dongle to use it in wireless mode. When it is connected using the dongle, the device battery is used to power it. Its vendor, product and version are identical to the Deco L. The only difference reported by its firmware is the product name. In order to add support for battery reporting, add a new HID descriptor and a quirk to detect the wireless version of the tablet. Link: DIGImend/digimend-kernel-drivers#635 Tested-by: Mia Kanashi <[email protected]> Tested-by: Andreas Grosse <[email protected]> Tested-by: Mia Kanashi <[email protected]> Signed-off-by: José Expósito <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 037c1aa commit f9ce4db

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

drivers/hid/hid-uclogic-params.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "usbhid/usbhid.h"
1919
#include "hid-ids.h"
2020
#include <linux/ctype.h>
21+
#include <linux/string.h>
2122
#include <asm/unaligned.h>
2223

2324
/**
@@ -1211,6 +1212,69 @@ static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p)
12111212
return rc;
12121213
}
12131214

1215+
/**
1216+
* uclogic_params_ugee_v2_has_battery() - check whether a UGEE v2 device has
1217+
* battery or not.
1218+
* @hdev: The HID device of the tablet interface.
1219+
*
1220+
* Returns:
1221+
* True if the device has battery, false otherwise.
1222+
*/
1223+
static bool uclogic_params_ugee_v2_has_battery(struct hid_device *hdev)
1224+
{
1225+
/* The XP-PEN Deco LW vendor, product and version are identical to the
1226+
* Deco L. The only difference reported by their firmware is the product
1227+
* name. Add a quirk to support battery reporting on the wireless
1228+
* version.
1229+
*/
1230+
if (hdev->vendor == USB_VENDOR_ID_UGEE &&
1231+
hdev->product == USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) {
1232+
struct usb_device *udev = hid_to_usb_dev(hdev);
1233+
1234+
if (strstarts(udev->product, "Deco LW"))
1235+
return true;
1236+
}
1237+
1238+
return false;
1239+
}
1240+
1241+
/**
1242+
* uclogic_params_ugee_v2_init_battery() - initialize UGEE v2 battery reporting.
1243+
* @hdev: The HID device of the tablet interface, cannot be NULL.
1244+
* @p: Parameters to fill in, cannot be NULL.
1245+
*
1246+
* Returns:
1247+
* Zero, if successful. A negative errno code on error.
1248+
*/
1249+
static int uclogic_params_ugee_v2_init_battery(struct hid_device *hdev,
1250+
struct uclogic_params *p)
1251+
{
1252+
int rc = 0;
1253+
1254+
if (!hdev || !p)
1255+
return -EINVAL;
1256+
1257+
/* Some tablets contain invalid characters in hdev->uniq, throwing a
1258+
* "hwmon: '<name>' is not a valid name attribute, please fix" error.
1259+
* Use the device vendor and product IDs instead.
1260+
*/
1261+
snprintf(hdev->uniq, sizeof(hdev->uniq), "%x-%x", hdev->vendor,
1262+
hdev->product);
1263+
1264+
rc = uclogic_params_frame_init_with_desc(&p->frame_list[1],
1265+
uclogic_rdesc_ugee_v2_battery_template_arr,
1266+
uclogic_rdesc_ugee_v2_battery_template_size,
1267+
UCLOGIC_RDESC_UGEE_V2_BATTERY_ID);
1268+
if (rc)
1269+
return rc;
1270+
1271+
p->frame_list[1].suffix = "Battery";
1272+
p->pen.subreport_list[1].value = 0xf2;
1273+
p->pen.subreport_list[1].id = UCLOGIC_RDESC_UGEE_V2_BATTERY_ID;
1274+
1275+
return rc;
1276+
}
1277+
12141278
/**
12151279
* uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by
12161280
* discovering their parameters.
@@ -1334,6 +1398,15 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
13341398
if (rc)
13351399
goto cleanup;
13361400

1401+
/* Initialize the battery interface*/
1402+
if (uclogic_params_ugee_v2_has_battery(hdev)) {
1403+
rc = uclogic_params_ugee_v2_init_battery(hdev, &p);
1404+
if (rc) {
1405+
hid_err(hdev, "error initializing battery: %d\n", rc);
1406+
goto cleanup;
1407+
}
1408+
}
1409+
13371410
output:
13381411
/* Output parameters */
13391412
memcpy(params, &p, sizeof(*params));

drivers/hid/hid-uclogic-rdesc.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,40 @@ const __u8 uclogic_rdesc_ugee_v2_frame_mouse_template_arr[] = {
10351035
const size_t uclogic_rdesc_ugee_v2_frame_mouse_template_size =
10361036
sizeof(uclogic_rdesc_ugee_v2_frame_mouse_template_arr);
10371037

1038+
/* Fixed report descriptor template for UGEE v2 battery reports */
1039+
const __u8 uclogic_rdesc_ugee_v2_battery_template_arr[] = {
1040+
0x05, 0x01, /* Usage Page (Desktop), */
1041+
0x09, 0x07, /* Usage (Keypad), */
1042+
0xA1, 0x01, /* Collection (Application), */
1043+
0x85, UCLOGIC_RDESC_UGEE_V2_BATTERY_ID,
1044+
/* Report ID, */
1045+
0x75, 0x08, /* Report Size (8), */
1046+
0x95, 0x02, /* Report Count (2), */
1047+
0x81, 0x01, /* Input (Constant), */
1048+
0x05, 0x84, /* Usage Page (Power Device), */
1049+
0x05, 0x85, /* Usage Page (Battery System), */
1050+
0x09, 0x65, /* Usage Page (AbsoluteStateOfCharge), */
1051+
0x75, 0x08, /* Report Size (8), */
1052+
0x95, 0x01, /* Report Count (1), */
1053+
0x15, 0x00, /* Logical Minimum (0), */
1054+
0x26, 0xff, 0x00, /* Logical Maximum (255), */
1055+
0x81, 0x02, /* Input (Variable), */
1056+
0x75, 0x01, /* Report Size (1), */
1057+
0x95, 0x01, /* Report Count (1), */
1058+
0x15, 0x00, /* Logical Minimum (0), */
1059+
0x25, 0x01, /* Logical Maximum (1), */
1060+
0x09, 0x44, /* Usage Page (Charging), */
1061+
0x81, 0x02, /* Input (Variable), */
1062+
0x95, 0x07, /* Report Count (7), */
1063+
0x81, 0x01, /* Input (Constant), */
1064+
0x75, 0x08, /* Report Size (8), */
1065+
0x95, 0x07, /* Report Count (7), */
1066+
0x81, 0x01, /* Input (Constant), */
1067+
0xC0 /* End Collection */
1068+
};
1069+
const size_t uclogic_rdesc_ugee_v2_battery_template_size =
1070+
sizeof(uclogic_rdesc_ugee_v2_battery_template_arr);
1071+
10381072
/* Fixed report descriptor for Ugee EX07 frame */
10391073
const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = {
10401074
0x05, 0x01, /* Usage Page (Desktop), */

drivers/hid/hid-uclogic-rdesc.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ extern const size_t uclogic_rdesc_v2_frame_dial_size;
161161
/* Device ID byte offset in v2 frame dial reports */
162162
#define UCLOGIC_RDESC_V2_FRAME_DIAL_DEV_ID_BYTE 0x4
163163

164+
/* Report ID for tweaked UGEE v2 battery reports */
165+
#define UCLOGIC_RDESC_UGEE_V2_BATTERY_ID 0xba
166+
164167
/* Fixed report descriptor template for UGEE v2 pen reports */
165168
extern const __u8 uclogic_rdesc_ugee_v2_pen_template_arr[];
166169
extern const size_t uclogic_rdesc_ugee_v2_pen_template_size;
@@ -177,6 +180,10 @@ extern const size_t uclogic_rdesc_ugee_v2_frame_dial_template_size;
177180
extern const __u8 uclogic_rdesc_ugee_v2_frame_mouse_template_arr[];
178181
extern const size_t uclogic_rdesc_ugee_v2_frame_mouse_template_size;
179182

183+
/* Fixed report descriptor template for UGEE v2 battery reports */
184+
extern const __u8 uclogic_rdesc_ugee_v2_battery_template_arr[];
185+
extern const size_t uclogic_rdesc_ugee_v2_battery_template_size;
186+
180187
/* Fixed report descriptor for Ugee EX07 frame */
181188
extern const __u8 uclogic_rdesc_ugee_ex07_frame_arr[];
182189
extern const size_t uclogic_rdesc_ugee_ex07_frame_size;

0 commit comments

Comments
 (0)