diff options
Diffstat (limited to 'drivers/hid/hid-uclogic-params.c')
-rw-r--r-- | drivers/hid/hid-uclogic-params.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 34fa991e6267..cd1233d7e253 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -18,6 +18,7 @@ #include "usbhid/usbhid.h" #include "hid-ids.h" #include <linux/ctype.h> +#include <linux/string.h> #include <asm/unaligned.h> /** @@ -1212,6 +1213,69 @@ static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p) } /** + * uclogic_params_ugee_v2_has_battery() - check whether a UGEE v2 device has + * battery or not. + * @hdev: The HID device of the tablet interface. + * + * Returns: + * True if the device has battery, false otherwise. + */ +static bool uclogic_params_ugee_v2_has_battery(struct hid_device *hdev) +{ + /* The XP-PEN Deco LW vendor, product and version are identical to the + * Deco L. The only difference reported by their firmware is the product + * name. Add a quirk to support battery reporting on the wireless + * version. + */ + if (hdev->vendor == USB_VENDOR_ID_UGEE && + hdev->product == USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) { + struct usb_device *udev = hid_to_usb_dev(hdev); + + if (strstarts(udev->product, "Deco LW")) + return true; + } + + return false; +} + +/** + * uclogic_params_ugee_v2_init_battery() - initialize UGEE v2 battery reporting. + * @hdev: The HID device of the tablet interface, cannot be NULL. + * @p: Parameters to fill in, cannot be NULL. + * + * Returns: + * Zero, if successful. A negative errno code on error. + */ +static int uclogic_params_ugee_v2_init_battery(struct hid_device *hdev, + struct uclogic_params *p) +{ + int rc = 0; + + if (!hdev || !p) + return -EINVAL; + + /* Some tablets contain invalid characters in hdev->uniq, throwing a + * "hwmon: '<name>' is not a valid name attribute, please fix" error. + * Use the device vendor and product IDs instead. + */ + snprintf(hdev->uniq, sizeof(hdev->uniq), "%x-%x", hdev->vendor, + hdev->product); + + rc = uclogic_params_frame_init_with_desc(&p->frame_list[1], + uclogic_rdesc_ugee_v2_battery_template_arr, + uclogic_rdesc_ugee_v2_battery_template_size, + UCLOGIC_RDESC_UGEE_V2_BATTERY_ID); + if (rc) + return rc; + + p->frame_list[1].suffix = "Battery"; + p->pen.subreport_list[1].value = 0xf2; + p->pen.subreport_list[1].id = UCLOGIC_RDESC_UGEE_V2_BATTERY_ID; + + return rc; +} + +/** * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by * discovering their parameters. * @@ -1334,6 +1398,15 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, if (rc) goto cleanup; + /* Initialize the battery interface*/ + if (uclogic_params_ugee_v2_has_battery(hdev)) { + rc = uclogic_params_ugee_v2_init_battery(hdev, &p); + if (rc) { + hid_err(hdev, "error initializing battery: %d\n", rc); + goto cleanup; + } + } + output: /* Output parameters */ memcpy(params, &p, sizeof(*params)); |