HID: uclogic: Parse the UGEE v2 frame type
The string descriptor returned by UGEE v2 devices contains a byte indicating the device frame type. The values discovered so far are: - 0: Frame with buttons, present in the XP-PEN Deco L. - 1: Frame with buttons and dial, present in the PARBLO A610 PRO. - 2: Frame with buttons and a mouse, shaped as a dial + touchpad. Present in the XP-PEN Deco Pro S. Parse the frame type and add KUnit tests. Tested-by: Jouke Witteveen <j.witteveen@gmail.com> Signed-off-by: José Expósito <jose.exposito89@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
parent
8640229678
commit
a092986fc0
@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <kunit/test.h>
|
#include <kunit/test.h>
|
||||||
|
#include "./hid-uclogic-params.h"
|
||||||
#include "./hid-uclogic-rdesc.h"
|
#include "./hid-uclogic-rdesc.h"
|
||||||
|
|
||||||
#define MAX_STR_DESC_SIZE 14
|
#define MAX_STR_DESC_SIZE 14
|
||||||
@ -17,6 +18,7 @@ struct uclogic_parse_ugee_v2_desc_case {
|
|||||||
const __u8 str_desc[MAX_STR_DESC_SIZE];
|
const __u8 str_desc[MAX_STR_DESC_SIZE];
|
||||||
size_t str_desc_size;
|
size_t str_desc_size;
|
||||||
const s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
|
const s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
|
||||||
|
enum uclogic_params_frame_type frame_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct uclogic_parse_ugee_v2_desc_case uclogic_parse_ugee_v2_desc_cases[] = {
|
static struct uclogic_parse_ugee_v2_desc_case uclogic_parse_ugee_v2_desc_cases[] = {
|
||||||
@ -26,6 +28,7 @@ static struct uclogic_parse_ugee_v2_desc_case uclogic_parse_ugee_v2_desc_cases[]
|
|||||||
.str_desc = {},
|
.str_desc = {},
|
||||||
.str_desc_size = 0,
|
.str_desc_size = 0,
|
||||||
.desc_params = {},
|
.desc_params = {},
|
||||||
|
.frame_type = UCLOGIC_PARAMS_FRAME_BUTTONS,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "resolution_with_value_0",
|
.name = "resolution_with_value_0",
|
||||||
@ -48,6 +51,7 @@ static struct uclogic_parse_ugee_v2_desc_case uclogic_parse_ugee_v2_desc_cases[]
|
|||||||
[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF,
|
[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF,
|
||||||
[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x08,
|
[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x08,
|
||||||
},
|
},
|
||||||
|
.frame_type = UCLOGIC_PARAMS_FRAME_BUTTONS,
|
||||||
},
|
},
|
||||||
/* XP-PEN Deco L str_desc: Frame with 8 buttons */
|
/* XP-PEN Deco L str_desc: Frame with 8 buttons */
|
||||||
{
|
{
|
||||||
@ -71,6 +75,7 @@ static struct uclogic_parse_ugee_v2_desc_case uclogic_parse_ugee_v2_desc_cases[]
|
|||||||
[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF,
|
[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF,
|
||||||
[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x08,
|
[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x08,
|
||||||
},
|
},
|
||||||
|
.frame_type = UCLOGIC_PARAMS_FRAME_BUTTONS,
|
||||||
},
|
},
|
||||||
/* PARBLO A610 PRO str_desc: Frame with 9 buttons and dial */
|
/* PARBLO A610 PRO str_desc: Frame with 9 buttons and dial */
|
||||||
{
|
{
|
||||||
@ -94,6 +99,31 @@ static struct uclogic_parse_ugee_v2_desc_case uclogic_parse_ugee_v2_desc_cases[]
|
|||||||
[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF,
|
[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF,
|
||||||
[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x09,
|
[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x09,
|
||||||
},
|
},
|
||||||
|
.frame_type = UCLOGIC_PARAMS_FRAME_DIAL,
|
||||||
|
},
|
||||||
|
/* XP-PEN Deco Pro S str_desc: Frame with 8 buttons and mouse */
|
||||||
|
{
|
||||||
|
.name = "frame_type_mouse",
|
||||||
|
.res = 0,
|
||||||
|
.str_desc = {
|
||||||
|
0x0E, 0x03,
|
||||||
|
0xC8, 0xB3,
|
||||||
|
0x34, 0x65,
|
||||||
|
0x08,
|
||||||
|
0x02,
|
||||||
|
0xFF, 0x1F,
|
||||||
|
0xD8, 0x13,
|
||||||
|
},
|
||||||
|
.str_desc_size = 12,
|
||||||
|
.desc_params = {
|
||||||
|
[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 0xB3C8,
|
||||||
|
[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0x2363,
|
||||||
|
[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 0x6534,
|
||||||
|
[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0x13EC,
|
||||||
|
[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF,
|
||||||
|
[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x08,
|
||||||
|
},
|
||||||
|
.frame_type = UCLOGIC_PARAMS_FRAME_MOUSE,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -110,12 +140,14 @@ static void uclogic_parse_ugee_v2_desc_test(struct kunit *test)
|
|||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
|
s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
|
||||||
|
enum uclogic_params_frame_type frame_type;
|
||||||
const struct uclogic_parse_ugee_v2_desc_case *params = test->param_value;
|
const struct uclogic_parse_ugee_v2_desc_case *params = test->param_value;
|
||||||
|
|
||||||
res = uclogic_params_parse_ugee_v2_desc(params->str_desc,
|
res = uclogic_params_parse_ugee_v2_desc(params->str_desc,
|
||||||
params->str_desc_size,
|
params->str_desc_size,
|
||||||
desc_params,
|
desc_params,
|
||||||
ARRAY_SIZE(desc_params));
|
ARRAY_SIZE(desc_params),
|
||||||
|
&frame_type);
|
||||||
KUNIT_ASSERT_EQ(test, res, params->res);
|
KUNIT_ASSERT_EQ(test, res, params->res);
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
@ -139,6 +171,7 @@ static void uclogic_parse_ugee_v2_desc_test(struct kunit *test)
|
|||||||
KUNIT_EXPECT_EQ(test,
|
KUNIT_EXPECT_EQ(test,
|
||||||
params->desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM],
|
params->desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM],
|
||||||
desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM]);
|
desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM]);
|
||||||
|
KUNIT_EXPECT_EQ(test, params->frame_type, frame_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct kunit_case hid_uclogic_params_test_cases[] = {
|
static struct kunit_case hid_uclogic_params_test_cases[] = {
|
||||||
|
@ -1064,6 +1064,7 @@ cleanup:
|
|||||||
* @str_desc_size: Size of the string descriptor.
|
* @str_desc_size: Size of the string descriptor.
|
||||||
* @desc_params: Output description params list.
|
* @desc_params: Output description params list.
|
||||||
* @desc_params_size: Size of the output description params list.
|
* @desc_params_size: Size of the output description params list.
|
||||||
|
* @frame_type: Output frame type.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* Zero, if successful. A negative errno code on error.
|
* Zero, if successful. A negative errno code on error.
|
||||||
@ -1071,7 +1072,8 @@ cleanup:
|
|||||||
static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc,
|
static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc,
|
||||||
size_t str_desc_size,
|
size_t str_desc_size,
|
||||||
s32 *desc_params,
|
s32 *desc_params,
|
||||||
size_t desc_params_size)
|
size_t desc_params_size,
|
||||||
|
enum uclogic_params_frame_type *frame_type)
|
||||||
{
|
{
|
||||||
s32 pen_x_lm, pen_y_lm;
|
s32 pen_x_lm, pen_y_lm;
|
||||||
s32 pen_x_pm, pen_y_pm;
|
s32 pen_x_pm, pen_y_pm;
|
||||||
@ -1091,6 +1093,7 @@ static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc,
|
|||||||
pen_x_lm = get_unaligned_le16(str_desc + 2);
|
pen_x_lm = get_unaligned_le16(str_desc + 2);
|
||||||
pen_y_lm = get_unaligned_le16(str_desc + 4);
|
pen_y_lm = get_unaligned_le16(str_desc + 4);
|
||||||
frame_num_buttons = str_desc[6];
|
frame_num_buttons = str_desc[6];
|
||||||
|
*frame_type = str_desc[7];
|
||||||
pen_pressure_lm = get_unaligned_le16(str_desc + 8);
|
pen_pressure_lm = get_unaligned_le16(str_desc + 8);
|
||||||
|
|
||||||
resolution = get_unaligned_le16(str_desc + 10);
|
resolution = get_unaligned_le16(str_desc + 10);
|
||||||
@ -1176,6 +1179,7 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
|
|||||||
__u8 *str_desc = NULL;
|
__u8 *str_desc = NULL;
|
||||||
__u8 *rdesc_pen = NULL;
|
__u8 *rdesc_pen = NULL;
|
||||||
s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
|
s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
|
||||||
|
enum uclogic_params_frame_type frame_type;
|
||||||
__u8 magic_arr[] = {
|
__u8 magic_arr[] = {
|
||||||
0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
@ -1219,7 +1223,8 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
|
|||||||
|
|
||||||
rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len,
|
rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len,
|
||||||
desc_params,
|
desc_params,
|
||||||
ARRAY_SIZE(desc_params));
|
ARRAY_SIZE(desc_params),
|
||||||
|
&frame_type);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
@ -1243,8 +1248,14 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
|
|||||||
p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
|
p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
|
||||||
|
|
||||||
/* Initialize the frame interface */
|
/* Initialize the frame interface */
|
||||||
rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params,
|
switch (frame_type) {
|
||||||
ARRAY_SIZE(desc_params));
|
case UCLOGIC_PARAMS_FRAME_BUTTONS:
|
||||||
|
default:
|
||||||
|
rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params,
|
||||||
|
ARRAY_SIZE(desc_params));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
@ -29,6 +29,16 @@ enum uclogic_params_pen_inrange {
|
|||||||
UCLOGIC_PARAMS_PEN_INRANGE_NONE,
|
UCLOGIC_PARAMS_PEN_INRANGE_NONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Types of frames */
|
||||||
|
enum uclogic_params_frame_type {
|
||||||
|
/* Frame with buttons */
|
||||||
|
UCLOGIC_PARAMS_FRAME_BUTTONS = 0,
|
||||||
|
/* Frame with buttons and a dial */
|
||||||
|
UCLOGIC_PARAMS_FRAME_DIAL,
|
||||||
|
/* Frame with buttons and a mouse (shaped as a dial + touchpad) */
|
||||||
|
UCLOGIC_PARAMS_FRAME_MOUSE,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pen report's subreport data.
|
* Pen report's subreport data.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user