Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: 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>

authored by

José Expósito and committed by
Jiri Kosina
14b71e6a d264dd3b

+29 -19
+1 -19
drivers/hid/hid-uclogic-core.c
··· 22 22 23 23 #include "hid-ids.h" 24 24 25 - /* Driver data */ 26 - struct uclogic_drvdata { 27 - /* Interface parameters */ 28 - struct uclogic_params params; 29 - /* Pointer to the replacement report descriptor. NULL if none. */ 30 - __u8 *desc_ptr; 31 - /* 32 - * Size of the replacement report descriptor. 33 - * Only valid if desc_ptr is not NULL 34 - */ 35 - unsigned int desc_size; 36 - /* Pen input device */ 37 - struct input_dev *pen_input; 38 - /* In-range timer */ 39 - struct timer_list inrange_timer; 40 - /* Last rotary encoder state, or U8_MAX for none */ 41 - u8 re_state; 42 - }; 43 - 44 25 /** 45 26 * uclogic_inrange_timeout - handle pen in-range state timeout. 46 27 * Emulate input events normally generated when pen goes out of range for ··· 183 202 } 184 203 timer_setup(&drvdata->inrange_timer, uclogic_inrange_timeout, 0); 185 204 drvdata->re_state = U8_MAX; 205 + drvdata->quirks = id->driver_data; 186 206 hid_set_drvdata(hdev, drvdata); 187 207 188 208 /* Initialize the device and retrieve interface parameters */
+5
drivers/hid/hid-uclogic-params.c
··· 1298 1298 struct hid_device *hdev) 1299 1299 { 1300 1300 int rc = 0; 1301 + struct uclogic_drvdata *drvdata; 1301 1302 struct usb_interface *iface; 1302 1303 __u8 bInterfaceNumber; 1303 1304 const int str_desc_len = 12; ··· 1317 1316 goto cleanup; 1318 1317 } 1319 1318 1319 + drvdata = hid_get_drvdata(hdev); 1320 1320 iface = to_usb_interface(hdev->dev.parent); 1321 1321 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; 1322 1322 ··· 1384 1382 p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID; 1385 1383 1386 1384 /* Initialize the frame interface */ 1385 + if (drvdata->quirks & UCLOGIC_MOUSE_FRAME_QUIRK) 1386 + frame_type = UCLOGIC_PARAMS_FRAME_MOUSE; 1387 + 1387 1388 switch (frame_type) { 1388 1389 case UCLOGIC_PARAMS_FRAME_DIAL: 1389 1390 case UCLOGIC_PARAMS_FRAME_MOUSE:
+23
drivers/hid/hid-uclogic-params.h
··· 19 19 #include <linux/usb.h> 20 20 #include <linux/hid.h> 21 21 22 + #define UCLOGIC_MOUSE_FRAME_QUIRK BIT(0) 23 + 22 24 /* Types of pen in-range reporting */ 23 25 enum uclogic_params_pen_inrange { 24 26 /* Normal reports: zero - out of proximity, one - in proximity */ ··· 215 213 * parts. Only valid, if "invalid" is false. 216 214 */ 217 215 struct uclogic_params_frame frame_list[3]; 216 + }; 217 + 218 + /* Driver data */ 219 + struct uclogic_drvdata { 220 + /* Interface parameters */ 221 + struct uclogic_params params; 222 + /* Pointer to the replacement report descriptor. NULL if none. */ 223 + __u8 *desc_ptr; 224 + /* 225 + * Size of the replacement report descriptor. 226 + * Only valid if desc_ptr is not NULL 227 + */ 228 + unsigned int desc_size; 229 + /* Pen input device */ 230 + struct input_dev *pen_input; 231 + /* In-range timer */ 232 + struct timer_list inrange_timer; 233 + /* Last rotary encoder state, or U8_MAX for none */ 234 + u8 re_state; 235 + /* Device quirks */ 236 + unsigned long quirks; 218 237 }; 219 238 220 239 /* Initialize a tablet interface and discover its parameters */