Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
a7386881
K
Kernel
项目概览
openeuler
/
Kernel
大约 2 年 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
a7386881
编写于
2月 22, 2023
作者:
B
Benjamin Tissoires
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-6.3/uclogic' into for-linus
UClogic assorted fixes and new devices support (José Expósito)
上级
b838d36f
f5379a01
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
339 addition
and
27 deletion
+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
未找到文件。
drivers/hid/hid-ids.h
浏览文件 @
a7386881
...
@@ -1304,7 +1304,9 @@
...
@@ -1304,7 +1304,9 @@
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042
#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_DECO01_V2 0x0905
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L 0x0935
#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_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_XPPEN_TABLET_STAR06 0x0078
#define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074
#define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074
#define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071
#define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071
...
...
drivers/hid/hid-input.c
浏览文件 @
a7386881
...
@@ -378,6 +378,10 @@ static const struct hid_device_id hid_battery_quirks[] = {
...
@@ -378,6 +378,10 @@ static const struct hid_device_id hid_battery_quirks[] = {
HID_BATTERY_QUIRK_IGNORE
},
HID_BATTERY_QUIRK_IGNORE
},
{
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_L
),
HID_BATTERY_QUIRK_AVOID_QUERY
},
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_I2C_DEVICE
(
USB_VENDOR_ID_ELAN
,
I2C_DEVICE_ID_HP_ENVY_X360_15
),
HID_BATTERY_QUIRK_IGNORE
},
HID_BATTERY_QUIRK_IGNORE
},
{
HID_I2C_DEVICE
(
USB_VENDOR_ID_ELAN
,
I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100
),
{
HID_I2C_DEVICE
(
USB_VENDOR_ID_ELAN
,
I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100
),
...
...
drivers/hid/hid-uclogic-core-test.c
0 → 100644
浏览文件 @
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
浏览文件 @
a7386881
...
@@ -22,25 +22,6 @@
...
@@ -22,25 +22,6 @@
#include "hid-ids.h"
#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.
* uclogic_inrange_timeout - handle pen in-range state timeout.
* Emulate input events normally generated when pen goes out of range for
* Emulate input events normally generated when pen goes out of range for
...
@@ -202,6 +183,7 @@ static int uclogic_probe(struct hid_device *hdev,
...
@@ -202,6 +183,7 @@ static int uclogic_probe(struct hid_device *hdev,
}
}
timer_setup
(
&
drvdata
->
inrange_timer
,
uclogic_inrange_timeout
,
0
);
timer_setup
(
&
drvdata
->
inrange_timer
,
uclogic_inrange_timeout
,
0
);
drvdata
->
re_state
=
U8_MAX
;
drvdata
->
re_state
=
U8_MAX
;
drvdata
->
quirks
=
id
->
driver_data
;
hid_set_drvdata
(
hdev
,
drvdata
);
hid_set_drvdata
(
hdev
,
drvdata
);
/* Initialize the device and retrieve interface parameters */
/* Initialize the device and retrieve interface parameters */
...
@@ -267,6 +249,34 @@ static int uclogic_resume(struct hid_device *hdev)
...
@@ -267,6 +249,34 @@ static int uclogic_resume(struct hid_device *hdev)
}
}
#endif
#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).
* uclogic_raw_event_pen - handle raw pen events (pen HID reports).
*
*
...
@@ -425,6 +435,9 @@ static int uclogic_raw_event(struct hid_device *hdev,
...
@@ -425,6 +435,9 @@ static int uclogic_raw_event(struct hid_device *hdev,
if
(
report
->
type
!=
HID_INPUT_REPORT
)
if
(
report
->
type
!=
HID_INPUT_REPORT
)
return
0
;
return
0
;
if
(
uclogic_exec_event_hook
(
params
,
data
,
size
))
return
0
;
while
(
true
)
{
while
(
true
)
{
/* Tweak pen reports, if necessary */
/* Tweak pen reports, if necessary */
if
((
report_id
==
params
->
pen
.
id
)
&&
(
size
>=
2
))
{
if
((
report_id
==
params
->
pen
.
id
)
&&
(
size
>=
2
))
{
...
@@ -529,8 +542,14 @@ static const struct hid_device_id uclogic_devices[] = {
...
@@ -529,8 +542,14 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2
)
},
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UGEE
,
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L
)
},
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
,
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S
)
},
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
,
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06
)
},
USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06
)
},
{
}
{
}
...
@@ -556,3 +575,7 @@ module_hid_driver(uclogic_driver);
...
@@ -556,3 +575,7 @@ module_hid_driver(uclogic_driver);
MODULE_AUTHOR
(
"Martin Rusko"
);
MODULE_AUTHOR
(
"Martin Rusko"
);
MODULE_AUTHOR
(
"Nikolai Kondrashov"
);
MODULE_AUTHOR
(
"Nikolai Kondrashov"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
#ifdef CONFIG_HID_KUNIT_TEST
#include "hid-uclogic-core-test.c"
#endif
drivers/hid/hid-uclogic-params-test.c
浏览文件 @
a7386881
...
@@ -174,9 +174,25 @@ static void hid_test_uclogic_parse_ugee_v2_desc(struct kunit *test)
...
@@ -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
);
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
[]
=
{
static
struct
kunit_case
hid_uclogic_params_test_cases
[]
=
{
KUNIT_CASE_PARAM
(
hid_test_uclogic_parse_ugee_v2_desc
,
KUNIT_CASE_PARAM
(
hid_test_uclogic_parse_ugee_v2_desc
,
uclogic_parse_ugee_v2_desc_gen_params
),
uclogic_parse_ugee_v2_desc_gen_params
),
KUNIT_CASE
(
hid_test_uclogic_params_cleanup_event_hooks
),
{}
{}
};
};
...
...
drivers/hid/hid-uclogic-params.c
浏览文件 @
a7386881
...
@@ -615,6 +615,31 @@ static int uclogic_params_frame_init_v1(struct uclogic_params_frame *frame,
...
@@ -615,6 +615,31 @@ static int uclogic_params_frame_init_v1(struct uclogic_params_frame *frame,
return
rc
;
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
* uclogic_params_cleanup - free resources used by struct uclogic_params
* (tablet interface's parameters).
* (tablet interface's parameters).
...
@@ -631,6 +656,7 @@ void uclogic_params_cleanup(struct uclogic_params *params)
...
@@ -631,6 +656,7 @@ void uclogic_params_cleanup(struct uclogic_params *params)
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
params
->
frame_list
);
i
++
)
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
params
->
frame_list
);
i
++
)
uclogic_params_frame_cleanup
(
&
params
->
frame_list
[
i
]);
uclogic_params_frame_cleanup
(
&
params
->
frame_list
[
i
]);
uclogic_params_cleanup_event_hooks
(
params
);
memset
(
params
,
0
,
sizeof
(
*
params
));
memset
(
params
,
0
,
sizeof
(
*
params
));
}
}
}
}
...
@@ -1021,8 +1047,8 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
...
@@ -1021,8 +1047,8 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
* Returns:
* Returns:
* Zero, if successful. A negative errno code on error.
* Zero, if successful. A negative errno code on error.
*/
*/
static
int
uclogic_probe_interface
(
struct
hid_device
*
hdev
,
u8
*
magic_arr
,
static
int
uclogic_probe_interface
(
struct
hid_device
*
hdev
,
const
u8
*
magic_arr
,
in
t
magic_size
,
int
endpoint
)
size_
t
magic_size
,
int
endpoint
)
{
{
struct
usb_device
*
udev
;
struct
usb_device
*
udev
;
unsigned
int
pipe
=
0
;
unsigned
int
pipe
=
0
;
...
@@ -1222,6 +1248,11 @@ static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p)
...
@@ -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
)
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
/* 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
* Deco L. The only difference reported by their firmware is the product
* name. Add a quirk to support battery reporting on the wireless
* 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,
...
@@ -1275,6 +1306,72 @@ static int uclogic_params_ugee_v2_init_battery(struct hid_device *hdev,
return
rc
;
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
* uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by
* discovering their parameters.
* discovering their parameters.
...
@@ -1298,6 +1395,7 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
...
@@ -1298,6 +1395,7 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
struct
hid_device
*
hdev
)
struct
hid_device
*
hdev
)
{
{
int
rc
=
0
;
int
rc
=
0
;
struct
uclogic_drvdata
*
drvdata
;
struct
usb_interface
*
iface
;
struct
usb_interface
*
iface
;
__u8
bInterfaceNumber
;
__u8
bInterfaceNumber
;
const
int
str_desc_len
=
12
;
const
int
str_desc_len
=
12
;
...
@@ -1305,9 +1403,6 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
...
@@ -1305,9 +1403,6 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
__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
;
enum
uclogic_params_frame_type
frame_type
;
__u8
magic_arr
[]
=
{
0x02
,
0xb0
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
};
/* The resulting parameters (noop) */
/* The resulting parameters (noop) */
struct
uclogic_params
p
=
{
0
,
};
struct
uclogic_params
p
=
{
0
,
};
...
@@ -1316,6 +1411,7 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
...
@@ -1316,6 +1411,7 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
goto
cleanup
;
goto
cleanup
;
}
}
drvdata
=
hid_get_drvdata
(
hdev
);
iface
=
to_usb_interface
(
hdev
->
dev
.
parent
);
iface
=
to_usb_interface
(
hdev
->
dev
.
parent
);
bInterfaceNumber
=
iface
->
cur_altsetting
->
desc
.
bInterfaceNumber
;
bInterfaceNumber
=
iface
->
cur_altsetting
->
desc
.
bInterfaceNumber
;
...
@@ -1337,7 +1433,9 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
...
@@ -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
* The specific data was discovered by sniffing the Windows driver
* traffic.
* 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
)
{
if
(
rc
)
{
uclogic_params_init_invalid
(
&
p
);
uclogic_params_init_invalid
(
&
p
);
goto
output
;
goto
output
;
...
@@ -1382,6 +1480,9 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
...
@@ -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
;
p
.
pen
.
subreport_list
[
0
].
id
=
UCLOGIC_RDESC_V1_FRAME_ID
;
/* Initialize the frame interface */
/* Initialize the frame interface */
if
(
drvdata
->
quirks
&
UCLOGIC_MOUSE_FRAME_QUIRK
)
frame_type
=
UCLOGIC_PARAMS_FRAME_MOUSE
;
switch
(
frame_type
)
{
switch
(
frame_type
)
{
case
UCLOGIC_PARAMS_FRAME_DIAL
:
case
UCLOGIC_PARAMS_FRAME_DIAL
:
case
UCLOGIC_PARAMS_FRAME_MOUSE
:
case
UCLOGIC_PARAMS_FRAME_MOUSE
:
...
@@ -1407,6 +1508,13 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
...
@@ -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:
/* Output parameters */
/* Output parameters */
memcpy
(
params
,
&
p
,
sizeof
(
*
params
));
memcpy
(
params
,
&
p
,
sizeof
(
*
params
));
...
@@ -1659,8 +1767,12 @@ int uclogic_params_init(struct uclogic_params *params,
...
@@ -1659,8 +1767,12 @@ int uclogic_params_init(struct uclogic_params *params,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2
):
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2
):
case
VID_PID
(
USB_VENDOR_ID_UGEE
,
case
VID_PID
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L
):
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
,
case
VID_PID
(
USB_VENDOR_ID_UGEE
,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S
):
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
);
rc
=
uclogic_params_ugee_v2_init
(
&
p
,
hdev
);
if
(
rc
!=
0
)
if
(
rc
!=
0
)
goto
cleanup
;
goto
cleanup
;
...
...
drivers/hid/hid-uclogic-params.h
浏览文件 @
a7386881
...
@@ -18,6 +18,10 @@
...
@@ -18,6 +18,10 @@
#include <linux/usb.h>
#include <linux/usb.h>
#include <linux/hid.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 */
/* Types of pen in-range reporting */
enum
uclogic_params_pen_inrange
{
enum
uclogic_params_pen_inrange
{
...
@@ -173,6 +177,17 @@ struct uclogic_params_frame {
...
@@ -173,6 +177,17 @@ struct uclogic_params_frame {
unsigned
int
bitmap_dial_byte
;
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.
* Tablet interface report parameters.
*
*
...
@@ -213,6 +228,31 @@ struct uclogic_params {
...
@@ -213,6 +228,31 @@ struct uclogic_params {
* parts. Only valid, if "invalid" is false.
* parts. Only valid, if "invalid" is false.
*/
*/
struct
uclogic_params_frame
frame_list
[
3
];
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 */
/* Initialize a tablet interface and discover its parameters */
...
...
drivers/hid/hid-uclogic-rdesc-test.c
浏览文件 @
a7386881
...
@@ -197,8 +197,7 @@ static void hid_test_uclogic_template(struct kunit *test)
...
@@ -197,8 +197,7 @@ static void hid_test_uclogic_template(struct kunit *test)
params
->
param_list
,
params
->
param_list
,
params
->
param_num
);
params
->
param_num
);
KUNIT_ASSERT_NOT_ERR_OR_NULL
(
test
,
res
);
KUNIT_ASSERT_NOT_ERR_OR_NULL
(
test
,
res
);
KUNIT_EXPECT_EQ
(
test
,
0
,
KUNIT_EXPECT_MEMEQ
(
test
,
res
,
params
->
expected
,
params
->
template_size
);
memcmp
(
res
,
params
->
expected
,
params
->
template_size
));
kfree
(
res
);
kfree
(
res
);
}
}
...
...
drivers/hid/hid-uclogic-rdesc.c
浏览文件 @
a7386881
...
@@ -859,6 +859,12 @@ const __u8 uclogic_rdesc_v2_frame_dial_arr[] = {
...
@@ -859,6 +859,12 @@ const __u8 uclogic_rdesc_v2_frame_dial_arr[] = {
const
size_t
uclogic_rdesc_v2_frame_dial_size
=
const
size_t
uclogic_rdesc_v2_frame_dial_size
=
sizeof
(
uclogic_rdesc_v2_frame_dial_arr
);
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 */
/* Fixed report descriptor template for UGEE v2 pen reports */
const
__u8
uclogic_rdesc_ugee_v2_pen_template_arr
[]
=
{
const
__u8
uclogic_rdesc_ugee_v2_pen_template_arr
[]
=
{
0x05
,
0x0d
,
/* Usage Page (Digitizers), */
0x05
,
0x0d
,
/* Usage Page (Digitizers), */
...
...
drivers/hid/hid-uclogic-rdesc.h
浏览文件 @
a7386881
...
@@ -164,6 +164,11 @@ extern const size_t uclogic_rdesc_v2_frame_dial_size;
...
@@ -164,6 +164,11 @@ extern const size_t uclogic_rdesc_v2_frame_dial_size;
/* Report ID for tweaked UGEE v2 battery reports */
/* Report ID for tweaked UGEE v2 battery reports */
#define UCLOGIC_RDESC_UGEE_V2_BATTERY_ID 0xba
#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 */
/* Fixed report descriptor template for UGEE v2 pen reports */
extern
const
__u8
uclogic_rdesc_ugee_v2_pen_template_arr
[];
extern
const
__u8
uclogic_rdesc_ugee_v2_pen_template_arr
[];
extern
const
size_t
uclogic_rdesc_ugee_v2_pen_template_size
;
extern
const
size_t
uclogic_rdesc_ugee_v2_pen_template_size
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录