Skip to content

Commit

Permalink
HID: uclogic: Add frame type quirk
Browse files Browse the repository at this point in the history
The report descriptor used to get information about UGEE v2 devices is
incorrect in the XP-PEN Deco Pro SW. It indicates that the device frame
is of type UCLOGIC_PARAMS_FRAME_BUTTONS but the device has a frame of
type UCLOGIC_PARAMS_FRAME_MOUSE.

Here is the original report descriptor:

  0x0e 0x03 0xc8 0xb3 0x34 0x65 0x08 0x00 0xff 0x1f 0xd8 0x13 0x00 0x00
                                     ^ This byte should be 2

Add a quirk to be able to fix the reported frame type.

Tested-by: Mia Kanashi <chad@redpilled.dev>
Tested-by: Andreas Grosse <andig.mail@t-online.de>
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
  • Loading branch information
José Expósito authored and Jiri Kosina committed Jan 18, 2023
1 parent d264dd3 commit 14b71e6
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 19 deletions.
20 changes: 1 addition & 19 deletions drivers/hid/hid-uclogic-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,6 @@

#include "hid-ids.h"

/* Driver data */
struct uclogic_drvdata {
/* Interface parameters */
struct uclogic_params params;
/* Pointer to the replacement report descriptor. NULL if none. */
__u8 *desc_ptr;
/*
* Size of the replacement report descriptor.
* Only valid if desc_ptr is not NULL
*/
unsigned int desc_size;
/* Pen input device */
struct input_dev *pen_input;
/* In-range timer */
struct timer_list inrange_timer;
/* Last rotary encoder state, or U8_MAX for none */
u8 re_state;
};

/**
* uclogic_inrange_timeout - handle pen in-range state timeout.
* Emulate input events normally generated when pen goes out of range for
Expand Down Expand Up @@ -202,6 +183,7 @@ static int uclogic_probe(struct hid_device *hdev,
}
timer_setup(&drvdata->inrange_timer, uclogic_inrange_timeout, 0);
drvdata->re_state = U8_MAX;
drvdata->quirks = id->driver_data;
hid_set_drvdata(hdev, drvdata);

/* Initialize the device and retrieve interface parameters */
Expand Down
5 changes: 5 additions & 0 deletions drivers/hid/hid-uclogic-params.c
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,7 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
struct hid_device *hdev)
{
int rc = 0;
struct uclogic_drvdata *drvdata;
struct usb_interface *iface;
__u8 bInterfaceNumber;
const int str_desc_len = 12;
Expand All @@ -1316,6 +1317,7 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
goto cleanup;
}

drvdata = hid_get_drvdata(hdev);
iface = to_usb_interface(hdev->dev.parent);
bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;

Expand Down Expand Up @@ -1382,6 +1384,9 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;

/* Initialize the frame interface */
if (drvdata->quirks & UCLOGIC_MOUSE_FRAME_QUIRK)
frame_type = UCLOGIC_PARAMS_FRAME_MOUSE;

switch (frame_type) {
case UCLOGIC_PARAMS_FRAME_DIAL:
case UCLOGIC_PARAMS_FRAME_MOUSE:
Expand Down
23 changes: 23 additions & 0 deletions drivers/hid/hid-uclogic-params.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include <linux/usb.h>
#include <linux/hid.h>

#define UCLOGIC_MOUSE_FRAME_QUIRK BIT(0)

/* Types of pen in-range reporting */
enum uclogic_params_pen_inrange {
/* Normal reports: zero - out of proximity, one - in proximity */
Expand Down Expand Up @@ -215,6 +217,27 @@ struct uclogic_params {
struct uclogic_params_frame frame_list[3];
};

/* Driver data */
struct uclogic_drvdata {
/* Interface parameters */
struct uclogic_params params;
/* Pointer to the replacement report descriptor. NULL if none. */
__u8 *desc_ptr;
/*
* Size of the replacement report descriptor.
* Only valid if desc_ptr is not NULL
*/
unsigned int desc_size;
/* Pen input device */
struct input_dev *pen_input;
/* In-range timer */
struct timer_list inrange_timer;
/* Last rotary encoder state, or U8_MAX for none */
u8 re_state;
/* Device quirks */
unsigned long quirks;
};

/* Initialize a tablet interface and discover its parameters */
extern int uclogic_params_init(struct uclogic_params *params,
struct hid_device *hdev);
Expand Down

0 comments on commit 14b71e6

Please sign in to comment.