Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
a7386881
Commit
a7386881
authored
Feb 22, 2023
by
Benjamin Tissoires
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-6.3/uclogic' into for-linus
UClogic assorted fixes and new devices support (José Expósito)
parents
b838d36f
f5379a01
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
339 additions
and
27 deletions
+339
-27
drivers/hid/hid-ids.h
drivers/hid/hid-ids.h
+2
-0
drivers/hid/hid-input.c
drivers/hid/hid-input.c
+4
-0
drivers/hid/hid-uclogic-core-test.c
drivers/hid/hid-uclogic-core-test.c
+105
-0
drivers/hid/hid-uclogic-core.c
drivers/hid/hid-uclogic-core.c
+42
-19
drivers/hid/hid-uclogic-params-test.c
drivers/hid/hid-uclogic-params-test.c
+16
-0
drivers/hid/hid-uclogic-params.c
drivers/hid/hid-uclogic-params.c
+118
-6
drivers/hid/hid-uclogic-params.h
drivers/hid/hid-uclogic-params.h
+40
-0
drivers/hid/hid-uclogic-rdesc-test.c
drivers/hid/hid-uclogic-rdesc-test.c
+1
-2
drivers/hid/hid-uclogic-rdesc.c
drivers/hid/hid-uclogic-rdesc.c
+6
-0
drivers/hid/hid-uclogic-rdesc.h
drivers/hid/hid-uclogic-rdesc.h
+5
-0
No files found.
drivers/hid/hid-ids.h
View file @
a7386881
...
...
@@ -1304,7 +1304,9 @@
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2 0x0905
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L 0x0935
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW 0x0934
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S 0x0909
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW 0x0933
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078
#define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074
#define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071
...
...
drivers/hid/hid-input.c
View file @
a7386881
...
...
@@ -378,6 +378,10 @@ static const struct hid_device_id hid_battery_quirks[] = {
HID_BATTERY_QUIRK_IGNORE
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L
),
HID_BATTERY_QUIRK_AVOID_QUERY
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW
),
HID_BATTERY_QUIRK_AVOID_QUERY
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW
),
HID_BATTERY_QUIRK_AVOID_QUERY
},
{
HID_I2C_DEVICE
(
USB_VENDOR_ID_ELAN
,
I2C_DEVICE_ID_HP_ENVY_X360_15
),
HID_BATTERY_QUIRK_IGNORE
},
{
HID_I2C_DEVICE
(
USB_VENDOR_ID_ELAN
,
I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100
),
...
...
drivers/hid/hid-uclogic-core-test.c
0 → 100644
View file @
a7386881
// SPDX-License-Identifier: GPL-2.0+
/*
* HID driver for UC-Logic devices not fully compliant with HID standard
*
* Copyright (c) 2022 José Expósito <jose.exposito89@gmail.com>
*/
#include <kunit/test.h>
#include "./hid-uclogic-params.h"
#define MAX_EVENT_SIZE 12
struct
uclogic_raw_event_hook_test
{
u8
event
[
MAX_EVENT_SIZE
];
size_t
size
;
bool
expected
;
};
static
struct
uclogic_raw_event_hook_test
hook_events
[]
=
{
{
.
event
=
{
0xA1
,
0xB2
,
0xC3
,
0xD4
},
.
size
=
4
,
},
{
.
event
=
{
0x1F
,
0x2E
,
0x3D
,
0x4C
,
0x5B
,
0x6A
},
.
size
=
6
,
},
};
static
struct
uclogic_raw_event_hook_test
test_events
[]
=
{
{
.
event
=
{
0xA1
,
0xB2
,
0xC3
,
0xD4
},
.
size
=
4
,
.
expected
=
true
,
},
{
.
event
=
{
0x1F
,
0x2E
,
0x3D
,
0x4C
,
0x5B
,
0x6A
},
.
size
=
6
,
.
expected
=
true
,
},
{
.
event
=
{
0xA1
,
0xB2
,
0xC3
},
.
size
=
3
,
.
expected
=
false
,
},
{
.
event
=
{
0xA1
,
0xB2
,
0xC3
,
0xD4
,
0x00
},
.
size
=
5
,
.
expected
=
false
,
},
{
.
event
=
{
0x2E
,
0x3D
,
0x4C
,
0x5B
,
0x6A
,
0x1F
},
.
size
=
6
,
.
expected
=
false
,
},
};
static
void
hid_test_uclogic_exec_event_hook_test
(
struct
kunit
*
test
)
{
struct
uclogic_params
p
=
{
0
,
};
struct
uclogic_raw_event_hook
*
filter
;
bool
res
;
int
n
;
/* Initialize the list of events to hook */
p
.
event_hooks
=
kunit_kzalloc
(
test
,
sizeof
(
*
p
.
event_hooks
),
GFP_KERNEL
);
KUNIT_ASSERT_NOT_ERR_OR_NULL
(
test
,
p
.
event_hooks
);
INIT_LIST_HEAD
(
&
p
.
event_hooks
->
list
);
for
(
n
=
0
;
n
<
ARRAY_SIZE
(
hook_events
);
n
++
)
{
filter
=
kunit_kzalloc
(
test
,
sizeof
(
*
filter
),
GFP_KERNEL
);
KUNIT_ASSERT_NOT_ERR_OR_NULL
(
test
,
filter
);
filter
->
size
=
hook_events
[
n
].
size
;
filter
->
event
=
kunit_kzalloc
(
test
,
filter
->
size
,
GFP_KERNEL
);
KUNIT_ASSERT_NOT_ERR_OR_NULL
(
test
,
filter
->
event
);
memcpy
(
filter
->
event
,
&
hook_events
[
n
].
event
[
0
],
filter
->
size
);
list_add_tail
(
&
filter
->
list
,
&
p
.
event_hooks
->
list
);
}
/* Test uclogic_exec_event_hook() */
for
(
n
=
0
;
n
<
ARRAY_SIZE
(
test_events
);
n
++
)
{
res
=
uclogic_exec_event_hook
(
&
p
,
&
test_events
[
n
].
event
[
0
],
test_events
[
n
].
size
);
KUNIT_ASSERT_EQ
(
test
,
res
,
test_events
[
n
].
expected
);
}
}
static
struct
kunit_case
hid_uclogic_core_test_cases
[]
=
{
KUNIT_CASE
(
hid_test_uclogic_exec_event_hook_test
),
{}
};
static
struct
kunit_suite
hid_uclogic_core_test_suite
=
{
.
name
=
"hid_uclogic_core_test"
,
.
test_cases
=
hid_uclogic_core_test_cases
,
};
kunit_test_suite
(
hid_uclogic_core_test_suite
);
MODULE_DESCRIPTION
(
"KUnit tests for the UC-Logic driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"José Expósito <jose.exposito89@gmail.com>"
);
drivers/hid/hid-uclogic-core.c
View file @
a7386881
...
...
@@ -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 */
...
...
@@ -267,6 +249,34 @@ static int uclogic_resume(struct hid_device *hdev)
}
#endif
/**
* uclogic_exec_event_hook - if the received event is hooked schedules the
* associated work.
*
* @p: Tablet interface report parameters.
* @event: Raw event.
* @size: The size of event.
*
* Returns:
* Whether the event was hooked or not.
*/
static
bool
uclogic_exec_event_hook
(
struct
uclogic_params
*
p
,
u8
*
event
,
int
size
)
{
struct
uclogic_raw_event_hook
*
curr
;
if
(
!
p
->
event_hooks
)
return
false
;
list_for_each_entry
(
curr
,
&
p
->
event_hooks
->
list
,
list
)
{
if
(
curr
->
size
==
size
&&
memcmp
(
curr
->
event
,
event
,
size
)
==
0
)
{
schedule_work
(
&
curr
->
work
);
return
true
;
}
}
return
false
;
}
/**
* uclogic_raw_event_pen - handle raw pen events (pen HID reports).
*
...
...
@@ -425,6 +435,9 @@ static int uclogic_raw_event(struct hid_device *hdev,
if
(
report
->
type
!=
HID_INPUT_REPORT
)
return
0
;
if
(
uclogic_exec_event_hook
(
params
,
data
,
size
))
return
0
;
while
(
true
)
{
/* Tweak pen reports, if necessary */
if
((
report_id
==
params
->
pen
.
id
)
&&
(
size
>=
2
))
{
...
...
@@ -529,8 +542,14 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW
),
.
driver_data
=
UCLOGIC_MOUSE_FRAME_QUIRK
|
UCLOGIC_BATTERY_QUIRK
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW
),
.
driver_data
=
UCLOGIC_MOUSE_FRAME_QUIRK
|
UCLOGIC_BATTERY_QUIRK
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06
)
},
{
}
...
...
@@ -556,3 +575,7 @@ module_hid_driver(uclogic_driver);
MODULE_AUTHOR
(
"Martin Rusko"
);
MODULE_AUTHOR
(
"Nikolai Kondrashov"
);
MODULE_LICENSE
(
"GPL"
);
#ifdef CONFIG_HID_KUNIT_TEST
#include "hid-uclogic-core-test.c"
#endif
drivers/hid/hid-uclogic-params-test.c
View file @
a7386881
...
...
@@ -174,9 +174,25 @@ static void hid_test_uclogic_parse_ugee_v2_desc(struct kunit *test)
KUNIT_EXPECT_EQ
(
test
,
params
->
frame_type
,
frame_type
);
}
static
void
hid_test_uclogic_params_cleanup_event_hooks
(
struct
kunit
*
test
)
{
int
res
,
n
;
struct
uclogic_params
p
=
{
0
,
};
res
=
uclogic_params_ugee_v2_init_event_hooks
(
NULL
,
&
p
);
KUNIT_ASSERT_EQ
(
test
,
res
,
0
);
/* Check that the function can be called repeatedly */
for
(
n
=
0
;
n
<
4
;
n
++
)
{
uclogic_params_cleanup_event_hooks
(
&
p
);
KUNIT_EXPECT_PTR_EQ
(
test
,
p
.
event_hooks
,
NULL
);
}
}
static
struct
kunit_case
hid_uclogic_params_test_cases
[]
=
{
KUNIT_CASE_PARAM
(
hid_test_uclogic_parse_ugee_v2_desc
,
uclogic_parse_ugee_v2_desc_gen_params
),
KUNIT_CASE
(
hid_test_uclogic_params_cleanup_event_hooks
),
{}
};
...
...
drivers/hid/hid-uclogic-params.c
View file @
a7386881
...
...
@@ -615,6 +615,31 @@ static int uclogic_params_frame_init_v1(struct uclogic_params_frame *frame,
return
rc
;
}
/**
* uclogic_params_cleanup_event_hooks - free resources used by the list of raw
* event hooks.
* Can be called repeatedly.
*
* @params: Input parameters to cleanup. Cannot be NULL.
*/
static
void
uclogic_params_cleanup_event_hooks
(
struct
uclogic_params
*
params
)
{
struct
uclogic_raw_event_hook
*
curr
,
*
n
;
if
(
!
params
||
!
params
->
event_hooks
)
return
;
list_for_each_entry_safe
(
curr
,
n
,
&
params
->
event_hooks
->
list
,
list
)
{
cancel_work_sync
(
&
curr
->
work
);
list_del
(
&
curr
->
list
);
kfree
(
curr
->
event
);
kfree
(
curr
);
}
kfree
(
params
->
event_hooks
);
params
->
event_hooks
=
NULL
;
}
/**
* uclogic_params_cleanup - free resources used by struct uclogic_params
* (tablet interface's parameters).
...
...
@@ -631,6 +656,7 @@ void uclogic_params_cleanup(struct uclogic_params *params)
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
params
->
frame_list
);
i
++
)
uclogic_params_frame_cleanup
(
&
params
->
frame_list
[
i
]);
uclogic_params_cleanup_event_hooks
(
params
);
memset
(
params
,
0
,
sizeof
(
*
params
));
}
}
...
...
@@ -1021,8 +1047,8 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
* Returns:
* Zero, if successful. A negative errno code on error.
*/
static
int
uclogic_probe_interface
(
struct
hid_device
*
hdev
,
u8
*
magic_arr
,
in
t
magic_size
,
int
endpoint
)
static
int
uclogic_probe_interface
(
struct
hid_device
*
hdev
,
const
u8
*
magic_arr
,
size_
t
magic_size
,
int
endpoint
)
{
struct
usb_device
*
udev
;
unsigned
int
pipe
=
0
;
...
...
@@ -1222,6 +1248,11 @@ static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p)
*/
static
bool
uclogic_params_ugee_v2_has_battery
(
struct
hid_device
*
hdev
)
{
struct
uclogic_drvdata
*
drvdata
=
hid_get_drvdata
(
hdev
);
if
(
drvdata
->
quirks
&
UCLOGIC_BATTERY_QUIRK
)
return
true
;
/* 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
...
...
@@ -1275,6 +1306,72 @@ static int uclogic_params_ugee_v2_init_battery(struct hid_device *hdev,
return
rc
;
}
/**
* uclogic_params_ugee_v2_reconnect_work() - When a wireless tablet looses
* connection to the USB dongle and reconnects, either because of its physical
* distance or because it was switches off and on using the frame's switch,
* uclogic_probe_interface() needs to be called again to enable the tablet.
*
* @work: The work that triggered this function.
*/
static
void
uclogic_params_ugee_v2_reconnect_work
(
struct
work_struct
*
work
)
{
struct
uclogic_raw_event_hook
*
event_hook
;
event_hook
=
container_of
(
work
,
struct
uclogic_raw_event_hook
,
work
);
uclogic_probe_interface
(
event_hook
->
hdev
,
uclogic_ugee_v2_probe_arr
,
uclogic_ugee_v2_probe_size
,
uclogic_ugee_v2_probe_endpoint
);
}
/**
* uclogic_params_ugee_v2_init_event_hooks() - initialize the list of events
* to be hooked for UGEE v2 devices.
* @hdev: The HID device of the tablet interface to initialize and get
* parameters from.
* @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_event_hooks
(
struct
hid_device
*
hdev
,
struct
uclogic_params
*
p
)
{
struct
uclogic_raw_event_hook
*
event_hook
;
__u8
reconnect_event
[]
=
{
/* Event received on wireless tablet reconnection */
0x02
,
0xF8
,
0x02
,
0x01
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
};
if
(
!
p
)
return
-
EINVAL
;
/* The reconnection event is only received if the tablet has battery */
if
(
!
uclogic_params_ugee_v2_has_battery
(
hdev
))
return
0
;
p
->
event_hooks
=
kzalloc
(
sizeof
(
*
p
->
event_hooks
),
GFP_KERNEL
);
if
(
!
p
->
event_hooks
)
return
-
ENOMEM
;
INIT_LIST_HEAD
(
&
p
->
event_hooks
->
list
);
event_hook
=
kzalloc
(
sizeof
(
*
event_hook
),
GFP_KERNEL
);
if
(
!
event_hook
)
return
-
ENOMEM
;
INIT_WORK
(
&
event_hook
->
work
,
uclogic_params_ugee_v2_reconnect_work
);
event_hook
->
hdev
=
hdev
;
event_hook
->
size
=
ARRAY_SIZE
(
reconnect_event
);
event_hook
->
event
=
kmemdup
(
reconnect_event
,
event_hook
->
size
,
GFP_KERNEL
);
if
(
!
event_hook
->
event
)
return
-
ENOMEM
;
list_add_tail
(
&
event_hook
->
list
,
&
p
->
event_hooks
->
list
);
return
0
;
}
/**
* uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by
* discovering their parameters.
...
...
@@ -1298,6 +1395,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
;
...
...
@@ -1305,9 +1403,6 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
__u8
*
rdesc_pen
=
NULL
;
s32
desc_params
[
UCLOGIC_RDESC_PH_ID_NUM
];
enum
uclogic_params_frame_type
frame_type
;
__u8
magic_arr
[]
=
{
0x02
,
0xb0
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
};
/* The resulting parameters (noop) */
struct
uclogic_params
p
=
{
0
,
};
...
...
@@ -1316,6 +1411,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
;
...
...
@@ -1337,7 +1433,9 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
* The specific data was discovered by sniffing the Windows driver
* traffic.
*/
rc
=
uclogic_probe_interface
(
hdev
,
magic_arr
,
sizeof
(
magic_arr
),
0x03
);
rc
=
uclogic_probe_interface
(
hdev
,
uclogic_ugee_v2_probe_arr
,
uclogic_ugee_v2_probe_size
,
uclogic_ugee_v2_probe_endpoint
);
if
(
rc
)
{
uclogic_params_init_invalid
(
&
p
);
goto
output
;
...
...
@@ -1382,6 +1480,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
:
...
...
@@ -1407,6 +1508,13 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
}
}
/* Create a list of raw events to be ignored */
rc
=
uclogic_params_ugee_v2_init_event_hooks
(
hdev
,
&
p
);
if
(
rc
)
{
hid_err
(
hdev
,
"error initializing event hook list: %d
\n
"
,
rc
);
goto
cleanup
;
}
output:
/* Output parameters */
memcpy
(
params
,
&
p
,
sizeof
(
*
params
));
...
...
@@ -1659,8 +1767,12 @@ int uclogic_params_init(struct uclogic_params *params,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2
):
case
VID_PID
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L
):
case
VID_PID
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW
):
case
VID_PID
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S
):
case
VID_PID
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW
):
rc
=
uclogic_params_ugee_v2_init
(
&
p
,
hdev
);
if
(
rc
!=
0
)
goto
cleanup
;
...
...
drivers/hid/hid-uclogic-params.h
View file @
a7386881
...
...
@@ -18,6 +18,10 @@
#include <linux/usb.h>
#include <linux/hid.h>
#include <linux/list.h>
#define UCLOGIC_MOUSE_FRAME_QUIRK BIT(0)
#define UCLOGIC_BATTERY_QUIRK BIT(1)
/* Types of pen in-range reporting */
enum
uclogic_params_pen_inrange
{
...
...
@@ -173,6 +177,17 @@ struct uclogic_params_frame {
unsigned
int
bitmap_dial_byte
;
};
/*
* List of works to be performed when a certain raw event is received.
*/
struct
uclogic_raw_event_hook
{
struct
hid_device
*
hdev
;
__u8
*
event
;
size_t
size
;
struct
work_struct
work
;
struct
list_head
list
;
};
/*
* Tablet interface report parameters.
*
...
...
@@ -213,6 +228,31 @@ struct uclogic_params {
* parts. Only valid, if "invalid" is false.
*/
struct
uclogic_params_frame
frame_list
[
3
];
/*
* List of event hooks.
*/
struct
uclogic_raw_event_hook
*
event_hooks
;
};
/* 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 */
...
...
drivers/hid/hid-uclogic-rdesc-test.c
View file @
a7386881
...
...
@@ -197,8 +197,7 @@ static void hid_test_uclogic_template(struct kunit *test)
params
->
param_list
,
params
->
param_num
);
KUNIT_ASSERT_NOT_ERR_OR_NULL
(
test
,
res
);
KUNIT_EXPECT_EQ
(
test
,
0
,
memcmp
(
res
,
params
->
expected
,
params
->
template_size
));
KUNIT_EXPECT_MEMEQ
(
test
,
res
,
params
->
expected
,
params
->
template_size
);
kfree
(
res
);
}
...
...
drivers/hid/hid-uclogic-rdesc.c
View file @
a7386881
...
...
@@ -859,6 +859,12 @@ const __u8 uclogic_rdesc_v2_frame_dial_arr[] = {
const
size_t
uclogic_rdesc_v2_frame_dial_size
=
sizeof
(
uclogic_rdesc_v2_frame_dial_arr
);
const
__u8
uclogic_ugee_v2_probe_arr
[]
=
{
0x02
,
0xb0
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
};
const
size_t
uclogic_ugee_v2_probe_size
=
sizeof
(
uclogic_ugee_v2_probe_arr
);
const
int
uclogic_ugee_v2_probe_endpoint
=
0x03
;
/* Fixed report descriptor template for UGEE v2 pen reports */
const
__u8
uclogic_rdesc_ugee_v2_pen_template_arr
[]
=
{
0x05
,
0x0d
,
/* Usage Page (Digitizers), */
...
...
drivers/hid/hid-uclogic-rdesc.h
View file @
a7386881
...
...
@@ -164,6 +164,11 @@ extern const size_t uclogic_rdesc_v2_frame_dial_size;
/* Report ID for tweaked UGEE v2 battery reports */
#define UCLOGIC_RDESC_UGEE_V2_BATTERY_ID 0xba
/* Magic data expected by UGEEv2 devices on probe */
extern
const
__u8
uclogic_ugee_v2_probe_arr
[];
extern
const
size_t
uclogic_ugee_v2_probe_size
;
extern
const
int
uclogic_ugee_v2_probe_endpoint
;
/* Fixed report descriptor template for UGEE v2 pen reports */
extern
const
__u8
uclogic_rdesc_ugee_v2_pen_template_arr
[];
extern
const
size_t
uclogic_rdesc_ugee_v2_pen_template_size
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment