Commit 14b71e6a authored by José Expósito's avatar José Expósito Committed by Jiri Kosina
Browse files

HID: uclogic: Add frame type quirk



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: default avatarMia Kanashi <chad@redpilled.dev>
Tested-by: default avatarAndreas Grosse <andig.mail@t-online.de>
Signed-off-by: default avatarJosé Expósito <jose.exposito89@gmail.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent d264dd3b
Loading
Loading
Loading
Loading
+1 −19
Original line number Diff line number Diff line
@@ -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
@@ -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 */
+5 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;

@@ -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:
+23 −0
Original line number Diff line number Diff line
@@ -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 */
@@ -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);