Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
5a12d86c
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
5a12d86c
编写于
8月 20, 2018
作者:
J
Jiri Kosina
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-4.19/elan' into for-linus
Resolution/pressure fixes and new device support for hid-elan
上级
415d2b33
e7ad3dc9
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
184 addition
and
53 deletion
+184
-53
drivers/hid/hid-elan.c
drivers/hid/hid-elan.c
+182
-53
drivers/hid/hid-ids.h
drivers/hid/hid-ids.h
+2
-0
未找到文件。
drivers/hid/hid-elan.c
浏览文件 @
5a12d86c
...
...
@@ -19,38 +19,49 @@
#include "hid-ids.h"
#define ELAN_MT_I2C 0x5d
#define ELAN_SINGLE_FINGER 0x81
#define ELAN_MT_FIRST_FINGER 0x82
#define ELAN_MT_SECOND_FINGER 0x83
#define ELAN_INPUT_REPORT_SIZE 8
#define ELAN_I2C_REPORT_SIZE 32
#define ELAN_FINGER_DATA_LEN 5
#define ELAN_MAX_FINGERS 5
#define ELAN_MAX_PRESSURE 255
#define ELAN_TP_USB_INTF 1
#define ELAN_FEATURE_REPORT 0x0d
#define ELAN_FEATURE_SIZE 5
#define ELAN_PARAM_MAX_X 6
#define ELAN_PARAM_MAX_Y 7
#define ELAN_PARAM_RES 8
#define ELAN_MUTE_LED_REPORT 0xBC
#define ELAN_LED_REPORT_SIZE 8
struct
elan_touchpad_settings
{
u8
max_fingers
;
u16
max_x
;
u16
max_y
;
u8
max_area_x
;
u8
max_area_y
;
u8
max_w
;
int
usb_bInterfaceNumber
;
};
#define ELAN_HAS_LED BIT(0)
struct
elan_drvdata
{
struct
input_dev
*
input
;
u8
prev_report
[
ELAN_INPUT_REPORT_SIZE
];
struct
led_classdev
mute_led
;
u8
mute_led_state
;
struct
elan_touchpad_settings
*
settings
;
u16
max_x
;
u16
max_y
;
u16
res_x
;
u16
res_y
;
};
static
int
is_not_elan_touchpad
(
struct
hid_device
*
hdev
)
{
struct
usb_interface
*
intf
=
to_usb_interface
(
hdev
->
dev
.
parent
);
struct
elan_drvdata
*
drvdata
=
hid_get_drvdata
(
hdev
);
if
(
hdev
->
bus
==
BUS_USB
)
{
struct
usb_interface
*
intf
=
to_usb_interface
(
hdev
->
dev
.
parent
);
return
(
intf
->
altsetting
->
desc
.
bInterfaceNumber
!=
ELAN_TP_USB_INTF
);
}
return
(
intf
->
altsetting
->
desc
.
bInterfaceNumber
!=
drvdata
->
settings
->
usb_bInterfaceNumber
)
;
return
0
;
}
static
int
elan_input_mapping
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
,
...
...
@@ -62,12 +73,86 @@ static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
if
(
field
->
report
->
id
==
ELAN_SINGLE_FINGER
||
field
->
report
->
id
==
ELAN_MT_FIRST_FINGER
||
field
->
report
->
id
==
ELAN_MT_SECOND_FINGER
)
field
->
report
->
id
==
ELAN_MT_SECOND_FINGER
||
field
->
report
->
id
==
ELAN_MT_I2C
)
return
-
1
;
return
0
;
}
static
int
elan_get_device_param
(
struct
hid_device
*
hdev
,
unsigned
char
*
dmabuf
,
unsigned
char
param
)
{
int
ret
;
dmabuf
[
0
]
=
ELAN_FEATURE_REPORT
;
dmabuf
[
1
]
=
0x05
;
dmabuf
[
2
]
=
0x03
;
dmabuf
[
3
]
=
param
;
dmabuf
[
4
]
=
0x01
;
ret
=
hid_hw_raw_request
(
hdev
,
ELAN_FEATURE_REPORT
,
dmabuf
,
ELAN_FEATURE_SIZE
,
HID_FEATURE_REPORT
,
HID_REQ_SET_REPORT
);
if
(
ret
!=
ELAN_FEATURE_SIZE
)
{
hid_err
(
hdev
,
"Set report error for parm %d: %d
\n
"
,
param
,
ret
);
return
ret
;
}
ret
=
hid_hw_raw_request
(
hdev
,
ELAN_FEATURE_REPORT
,
dmabuf
,
ELAN_FEATURE_SIZE
,
HID_FEATURE_REPORT
,
HID_REQ_GET_REPORT
);
if
(
ret
!=
ELAN_FEATURE_SIZE
)
{
hid_err
(
hdev
,
"Get report error for parm %d: %d
\n
"
,
param
,
ret
);
return
ret
;
}
return
0
;
}
static
unsigned
int
elan_convert_res
(
char
val
)
{
/*
* (value from firmware) * 10 + 790 = dpi
* dpi * 10 / 254 = dots/mm
*/
return
(
val
*
10
+
790
)
*
10
/
254
;
}
static
int
elan_get_device_params
(
struct
hid_device
*
hdev
)
{
struct
elan_drvdata
*
drvdata
=
hid_get_drvdata
(
hdev
);
unsigned
char
*
dmabuf
;
int
ret
;
dmabuf
=
kmalloc
(
ELAN_FEATURE_SIZE
,
GFP_KERNEL
);
if
(
!
dmabuf
)
return
-
ENOMEM
;
ret
=
elan_get_device_param
(
hdev
,
dmabuf
,
ELAN_PARAM_MAX_X
);
if
(
ret
)
goto
err
;
drvdata
->
max_x
=
(
dmabuf
[
4
]
<<
8
)
|
dmabuf
[
3
];
ret
=
elan_get_device_param
(
hdev
,
dmabuf
,
ELAN_PARAM_MAX_Y
);
if
(
ret
)
goto
err
;
drvdata
->
max_y
=
(
dmabuf
[
4
]
<<
8
)
|
dmabuf
[
3
];
ret
=
elan_get_device_param
(
hdev
,
dmabuf
,
ELAN_PARAM_RES
);
if
(
ret
)
goto
err
;
drvdata
->
res_x
=
elan_convert_res
(
dmabuf
[
3
]);
drvdata
->
res_y
=
elan_convert_res
(
dmabuf
[
4
]);
err:
kfree
(
dmabuf
);
return
ret
;
}
static
int
elan_input_configured
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
)
{
int
ret
;
...
...
@@ -77,6 +162,10 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
if
(
is_not_elan_touchpad
(
hdev
))
return
0
;
ret
=
elan_get_device_params
(
hdev
);
if
(
ret
)
return
ret
;
input
=
devm_input_allocate_device
(
&
hdev
->
dev
);
if
(
!
input
)
return
-
ENOMEM
;
...
...
@@ -90,25 +179,25 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
input
->
id
.
version
=
hdev
->
version
;
input
->
dev
.
parent
=
&
hdev
->
dev
;
input_set_abs_params
(
input
,
ABS_MT_POSITION_X
,
0
,
drvdata
->
settings
->
max_x
,
0
,
0
);
input_set_abs_params
(
input
,
ABS_MT_POSITION_Y
,
0
,
drvdata
->
settings
->
max_y
,
0
,
0
);
input_set_abs_params
(
input
,
ABS_MT_TOUCH_MAJOR
,
0
,
drvdata
->
settings
->
max_fingers
,
0
,
0
);
input_set_abs_params
(
input
,
ABS_TOOL_WIDTH
,
0
,
drvdata
->
settings
->
max_w
,
0
,
0
);
input_set_abs_params
(
input
,
ABS_MT_POSITION_X
,
0
,
drvdata
->
max_x
,
0
,
0
);
input_set_abs_params
(
input
,
ABS_MT_POSITION_Y
,
0
,
drvdata
->
max_y
,
0
,
0
);
input_set_abs_params
(
input
,
ABS_MT_PRESSURE
,
0
,
ELAN_MAX_PRESSURE
,
0
,
0
);
__set_bit
(
BTN_LEFT
,
input
->
keybit
);
__set_bit
(
INPUT_PROP_BUTTONPAD
,
input
->
propbit
);
ret
=
input_mt_init_slots
(
input
,
drvdata
->
settings
->
max_fingers
,
INPUT_MT_POINTER
);
ret
=
input_mt_init_slots
(
input
,
ELAN_MAX_FINGERS
,
INPUT_MT_POINTER
);
if
(
ret
)
{
hid_err
(
hdev
,
"Failed to init elan MT slots: %d
\n
"
,
ret
);
return
ret
;
}
input_abs_set_res
(
input
,
ABS_X
,
drvdata
->
res_x
);
input_abs_set_res
(
input
,
ABS_Y
,
drvdata
->
res_y
);
ret
=
input_register_device
(
input
);
if
(
ret
)
{
hid_err
(
hdev
,
"Failed to register elan input device: %d
\n
"
,
...
...
@@ -126,7 +215,7 @@ static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data,
unsigned
int
slot_num
)
{
struct
input_dev
*
input
=
drvdata
->
input
;
int
x
,
y
,
w
;
int
x
,
y
,
p
;
bool
active
=
!!
data
;
...
...
@@ -134,17 +223,17 @@ static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data,
input_mt_report_slot_state
(
input
,
MT_TOOL_FINGER
,
active
);
if
(
active
)
{
x
=
((
data
[
0
]
&
0xF0
)
<<
4
)
|
data
[
1
];
y
=
drvdata
->
settings
->
max_y
-
y
=
drvdata
->
max_y
-
(((
data
[
0
]
&
0x07
)
<<
8
)
|
data
[
2
]);
w
=
data
[
4
];
p
=
data
[
4
];
input_report_abs
(
input
,
ABS_MT_POSITION_X
,
x
);
input_report_abs
(
input
,
ABS_MT_POSITION_Y
,
y
);
input_report_abs
(
input
,
ABS_
TOOL_WIDTH
,
w
);
input_report_abs
(
input
,
ABS_
MT_PRESSURE
,
p
);
}
}
static
void
elan_report_input
(
struct
elan_drvdata
*
drvdata
,
u8
*
data
)
static
void
elan_
usb_
report_input
(
struct
elan_drvdata
*
drvdata
,
u8
*
data
)
{
int
i
;
struct
input_dev
*
input
=
drvdata
->
input
;
...
...
@@ -162,7 +251,7 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
* byte 5: x8 x7 x6 x5 x4 x3 x2 x1
* byte 6: y8 y7 y6 y5 y4 y3 y2 y1
* byte 7: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
* byte 8:
w8 w7 w6 w5 w4 w3 w2 w
1
* byte 8:
p8 p7 p6 p5 p4 p3 p2 p
1
*
* packet structure for ELAN_MT_SECOND_FINGER:
*
...
...
@@ -171,19 +260,21 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
* byte 3: x8 x7 x6 x5 x4 x3 x2 x1
* byte 4: y8 y7 y6 y5 y4 y3 y2 y1
* byte 5: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
* byte 6:
w8 w7 w6 w5 w4 w3 w2 w
1
* byte 6:
p8 p7 p6 p5 p4 p3 p2 p
1
* byte 7: 0 0 0 0 0 0 0 0
* byte 8: 0 0 0 0 0 0 0 0
*
* f5-f1: finger touch bits
* L: clickpad button
* sy / sx: not sure yet, but this looks like rectangular
* area for finger
* w: looks like finger width
* sy / sx: finger width / height expressed in traces, the total number
* of traces can be queried by doing a HID_REQ_SET_REPORT
* { 0x0d, 0x05, 0x03, 0x05, 0x01 } followed by a GET, in the
* returned buf, buf[3]=no-x-traces, buf[4]=no-y-traces.
* p: pressure
*/
if
(
data
[
0
]
==
ELAN_SINGLE_FINGER
)
{
for
(
i
=
0
;
i
<
drvdata
->
settings
->
max_fingers
;
i
++
)
{
for
(
i
=
0
;
i
<
ELAN_MAX_FINGERS
;
i
++
)
{
if
(
data
[
2
]
&
BIT
(
i
+
3
))
elan_report_mt_slot
(
drvdata
,
data
+
3
,
i
);
else
...
...
@@ -210,7 +301,7 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
if
(
prev_report
[
0
]
!=
ELAN_MT_FIRST_FINGER
)
return
;
for
(
i
=
0
;
i
<
drvdata
->
settings
->
max_fingers
;
i
++
)
{
for
(
i
=
0
;
i
<
ELAN_MAX_FINGERS
;
i
++
)
{
if
(
prev_report
[
2
]
&
BIT
(
i
+
3
))
{
if
(
!
first
)
{
first
=
1
;
...
...
@@ -229,6 +320,46 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
input_sync
(
input
);
}
static
void
elan_i2c_report_input
(
struct
elan_drvdata
*
drvdata
,
u8
*
data
)
{
struct
input_dev
*
input
=
drvdata
->
input
;
u8
*
finger_data
;
int
i
;
/*
* Elan MT touchpads in i2c mode send finger data in the same format
* as in USB mode, but then with all fingers in a single packet.
*
* packet structure for ELAN_MT_I2C:
*
* byte 1: 1 0 0 1 1 1 0 1 // 0x5d
* byte 2: f5 f4 f3 f2 f1 0 0 L
* byte 3: x12 x11 x10 x9 0? y11 y10 y9
* byte 4: x8 x7 x6 x5 x4 x3 x2 x1
* byte 5: y8 y7 y6 y5 y4 y3 y2 y1
* byte 6: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
* byte 7: p8 p7 p6 p5 p4 p3 p2 p1
* byte 8-12: Same as byte 3-7 for second finger down
* byte 13-17: Same as byte 3-7 for third finger down
* byte 18-22: Same as byte 3-7 for fourth finger down
* byte 23-27: Same as byte 3-7 for fifth finger down
*/
finger_data
=
data
+
2
;
for
(
i
=
0
;
i
<
ELAN_MAX_FINGERS
;
i
++
)
{
if
(
data
[
1
]
&
BIT
(
i
+
3
))
{
elan_report_mt_slot
(
drvdata
,
finger_data
,
i
);
finger_data
+=
ELAN_FINGER_DATA_LEN
;
}
else
{
elan_report_mt_slot
(
drvdata
,
NULL
,
i
);
}
}
input_report_key
(
input
,
BTN_LEFT
,
data
[
1
]
&
0x01
);
input_mt_sync_frame
(
input
);
input_sync
(
input
);
}
static
int
elan_raw_event
(
struct
hid_device
*
hdev
,
struct
hid_report
*
report
,
u8
*
data
,
int
size
)
{
...
...
@@ -241,11 +372,16 @@ static int elan_raw_event(struct hid_device *hdev,
data
[
0
]
==
ELAN_MT_FIRST_FINGER
||
data
[
0
]
==
ELAN_MT_SECOND_FINGER
)
{
if
(
size
==
ELAN_INPUT_REPORT_SIZE
)
{
elan_report_input
(
drvdata
,
data
);
elan_
usb_
report_input
(
drvdata
,
data
);
return
1
;
}
}
if
(
data
[
0
]
==
ELAN_MT_I2C
&&
size
==
ELAN_I2C_REPORT_SIZE
)
{
elan_i2c_report_input
(
drvdata
,
data
);
return
1
;
}
return
0
;
}
...
...
@@ -343,7 +479,6 @@ static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id)
if
(
!
drvdata
)
return
-
ENOMEM
;
drvdata
->
settings
=
(
struct
elan_touchpad_settings
*
)
id
->
driver_data
;
hid_set_drvdata
(
hdev
,
drvdata
);
ret
=
hid_parse
(
hdev
);
...
...
@@ -371,9 +506,11 @@ static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id)
if
(
ret
)
goto
err
;
ret
=
elan_init_mute_led
(
hdev
);
if
(
ret
)
goto
err
;
if
(
id
->
driver_data
&
ELAN_HAS_LED
)
{
ret
=
elan_init_mute_led
(
hdev
);
if
(
ret
)
goto
err
;
}
return
0
;
err:
...
...
@@ -386,22 +523,14 @@ static void elan_remove(struct hid_device *hdev)
hid_hw_stop
(
hdev
);
}
static
const
struct
elan_touchpad_settings
hp_x2_10_touchpad_data
=
{
.
max_fingers
=
5
,
.
max_x
=
2930
,
.
max_y
=
1250
,
.
max_area_x
=
15
,
.
max_area_y
=
15
,
.
max_w
=
255
,
.
usb_bInterfaceNumber
=
1
,
};
static
const
struct
hid_device_id
elan_devices
[]
=
{
{
HID_USB_DEVICE
(
USB_VENDOR_ID_ELAN
,
USB_DEVICE_ID_HP_X2
),
.
driver_data
=
ELAN_HAS_LED
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_ELAN
,
USB_DEVICE_ID_HP_X2_10_COVER
),
(
kernel_ulong_t
)
&
hp_x2_10_touchpad_data
},
.
driver_data
=
ELAN_HAS_LED
},
{
HID_I2C_DEVICE
(
USB_VENDOR_ID_ELAN
,
USB_DEVICE_ID_TOSHIBA_CLICK_L9W
)
},
{
}
};
MODULE_DEVICE_TABLE
(
hid
,
elan_devices
);
static
struct
hid_driver
elan_driver
=
{
...
...
drivers/hid/hid-ids.h
浏览文件 @
5a12d86c
...
...
@@ -369,6 +369,8 @@
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001
#define USB_VENDOR_ID_ELAN 0x04f3
#define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401
#define USB_DEVICE_ID_HP_X2 0x074d
#define USB_DEVICE_ID_HP_X2_10_COVER 0x0755
#define USB_VENDOR_ID_ELECOM 0x056e
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录