Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
b3d07e03
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 3 年多
通知
13
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
b3d07e03
编写于
5月 22, 2012
作者:
J
Jiri Kosina
浏览文件
操作
浏览文件
下载
差异文件
Merge branches 'device-groups', 'logitech' and 'multitouch' into for-linus
上级
b565a390
c6e6dc87
3ac36d15
变更
4
显示空白变更内容
内联
并排
Showing
4 changed file
with
287 addition
and
89 deletion
+287
-89
drivers/hid/hid-lg.c
drivers/hid/hid-lg.c
+32
-23
drivers/hid/hid-lg.h
drivers/hid/hid-lg.h
+5
-0
drivers/hid/hid-lg4ff.c
drivers/hid/hid-lg4ff.c
+204
-54
drivers/hid/hid-multitouch.c
drivers/hid/hid-multitouch.c
+46
-12
未找到文件。
drivers/hid/hid-lg.c
浏览文件 @
b3d07e03
...
@@ -109,23 +109,23 @@ static __u8 dfp_rdesc_fixed[] = {
...
@@ -109,23 +109,23 @@ static __u8 dfp_rdesc_fixed[] = {
static
__u8
*
lg_report_fixup
(
struct
hid_device
*
hdev
,
__u8
*
rdesc
,
static
__u8
*
lg_report_fixup
(
struct
hid_device
*
hdev
,
__u8
*
rdesc
,
unsigned
int
*
rsize
)
unsigned
int
*
rsize
)
{
{
unsigned
long
quirks
=
(
unsigned
long
)
hid_get_drvdata
(
hdev
);
struct
lg_drv_data
*
drv_data
=
(
struct
lg_drv_data
*
)
hid_get_drvdata
(
hdev
);
if
((
quirks
&
LG_RDESC
)
&&
*
rsize
>=
90
&&
rdesc
[
83
]
==
0x26
&&
if
((
drv_data
->
quirks
&
LG_RDESC
)
&&
*
rsize
>=
90
&&
rdesc
[
83
]
==
0x26
&&
rdesc
[
84
]
==
0x8c
&&
rdesc
[
85
]
==
0x02
)
{
rdesc
[
84
]
==
0x8c
&&
rdesc
[
85
]
==
0x02
)
{
hid_info
(
hdev
,
hid_info
(
hdev
,
"fixing up Logitech keyboard report descriptor
\n
"
);
"fixing up Logitech keyboard report descriptor
\n
"
);
rdesc
[
84
]
=
rdesc
[
89
]
=
0x4d
;
rdesc
[
84
]
=
rdesc
[
89
]
=
0x4d
;
rdesc
[
85
]
=
rdesc
[
90
]
=
0x10
;
rdesc
[
85
]
=
rdesc
[
90
]
=
0x10
;
}
}
if
((
quirks
&
LG_RDESC_REL_ABS
)
&&
*
rsize
>=
50
&&
if
((
drv_data
->
quirks
&
LG_RDESC_REL_ABS
)
&&
*
rsize
>=
50
&&
rdesc
[
32
]
==
0x81
&&
rdesc
[
33
]
==
0x06
&&
rdesc
[
32
]
==
0x81
&&
rdesc
[
33
]
==
0x06
&&
rdesc
[
49
]
==
0x81
&&
rdesc
[
50
]
==
0x06
)
{
rdesc
[
49
]
==
0x81
&&
rdesc
[
50
]
==
0x06
)
{
hid_info
(
hdev
,
hid_info
(
hdev
,
"fixing up rel/abs in Logitech report descriptor
\n
"
);
"fixing up rel/abs in Logitech report descriptor
\n
"
);
rdesc
[
33
]
=
rdesc
[
50
]
=
0x02
;
rdesc
[
33
]
=
rdesc
[
50
]
=
0x02
;
}
}
if
((
quirks
&
LG_FF4
)
&&
*
rsize
>=
101
&&
if
((
drv_data
->
quirks
&
LG_FF4
)
&&
*
rsize
>=
101
&&
rdesc
[
41
]
==
0x95
&&
rdesc
[
42
]
==
0x0B
&&
rdesc
[
41
]
==
0x95
&&
rdesc
[
42
]
==
0x0B
&&
rdesc
[
47
]
==
0x05
&&
rdesc
[
48
]
==
0x09
)
{
rdesc
[
47
]
==
0x05
&&
rdesc
[
48
]
==
0x09
)
{
hid_info
(
hdev
,
"fixing up Logitech Speed Force Wireless button descriptor
\n
"
);
hid_info
(
hdev
,
"fixing up Logitech Speed Force Wireless button descriptor
\n
"
);
...
@@ -278,7 +278,7 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -278,7 +278,7 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
0
,
0
,
0
,
0
,
0
,
183
,
184
,
185
,
186
,
187
,
0
,
0
,
0
,
0
,
0
,
183
,
184
,
185
,
186
,
187
,
188
,
189
,
190
,
191
,
192
,
193
,
194
,
0
,
0
,
0
188
,
189
,
190
,
191
,
192
,
193
,
194
,
0
,
0
,
0
};
};
unsigned
long
quirks
=
(
unsigned
long
)
hid_get_drvdata
(
hdev
);
struct
lg_drv_data
*
drv_data
=
(
struct
lg_drv_data
*
)
hid_get_drvdata
(
hdev
);
unsigned
int
hid
=
usage
->
hid
;
unsigned
int
hid
=
usage
->
hid
;
if
(
hdev
->
product
==
USB_DEVICE_ID_LOGITECH_RECEIVER
&&
if
(
hdev
->
product
==
USB_DEVICE_ID_LOGITECH_RECEIVER
&&
...
@@ -289,7 +289,7 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -289,7 +289,7 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
lg_dinovo_mapping
(
hi
,
usage
,
bit
,
max
))
lg_dinovo_mapping
(
hi
,
usage
,
bit
,
max
))
return
1
;
return
1
;
if
((
quirks
&
LG_WIRELESS
)
&&
lg_wireless_mapping
(
hi
,
usage
,
bit
,
max
))
if
((
drv_data
->
quirks
&
LG_WIRELESS
)
&&
lg_wireless_mapping
(
hi
,
usage
,
bit
,
max
))
return
1
;
return
1
;
if
((
hid
&
HID_USAGE_PAGE
)
!=
HID_UP_BUTTON
)
if
((
hid
&
HID_USAGE_PAGE
)
!=
HID_UP_BUTTON
)
...
@@ -299,11 +299,11 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -299,11 +299,11 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
/* Special handling for Logitech Cordless Desktop */
/* Special handling for Logitech Cordless Desktop */
if
(
field
->
application
==
HID_GD_MOUSE
)
{
if
(
field
->
application
==
HID_GD_MOUSE
)
{
if
((
quirks
&
LG_IGNORE_DOUBLED_WHEEL
)
&&
if
((
drv_data
->
quirks
&
LG_IGNORE_DOUBLED_WHEEL
)
&&
(
hid
==
7
||
hid
==
8
))
(
hid
==
7
||
hid
==
8
))
return
-
1
;
return
-
1
;
}
else
{
}
else
{
if
((
quirks
&
LG_EXPANDED_KEYMAP
)
&&
if
((
drv_data
->
quirks
&
LG_EXPANDED_KEYMAP
)
&&
hid
<
ARRAY_SIZE
(
e_keymap
)
&&
hid
<
ARRAY_SIZE
(
e_keymap
)
&&
e_keymap
[
hid
]
!=
0
)
{
e_keymap
[
hid
]
!=
0
)
{
hid_map_usage
(
hi
,
usage
,
bit
,
max
,
EV_KEY
,
hid_map_usage
(
hi
,
usage
,
bit
,
max
,
EV_KEY
,
...
@@ -319,13 +319,13 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
...
@@ -319,13 +319,13 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
unsigned
long
**
bit
,
int
*
max
)
unsigned
long
**
bit
,
int
*
max
)
{
{
unsigned
long
quirks
=
(
unsigned
long
)
hid_get_drvdata
(
hdev
);
struct
lg_drv_data
*
drv_data
=
(
struct
lg_drv_data
*
)
hid_get_drvdata
(
hdev
);
if
((
quirks
&
LG_BAD_RELATIVE_KEYS
)
&&
usage
->
type
==
EV_KEY
&&
if
((
drv_data
->
quirks
&
LG_BAD_RELATIVE_KEYS
)
&&
usage
->
type
==
EV_KEY
&&
(
field
->
flags
&
HID_MAIN_ITEM_RELATIVE
))
(
field
->
flags
&
HID_MAIN_ITEM_RELATIVE
))
field
->
flags
&=
~
HID_MAIN_ITEM_RELATIVE
;
field
->
flags
&=
~
HID_MAIN_ITEM_RELATIVE
;
if
((
quirks
&
LG_DUPLICATE_USAGES
)
&&
(
usage
->
type
==
EV_KEY
||
if
((
drv_data
->
quirks
&
LG_DUPLICATE_USAGES
)
&&
(
usage
->
type
==
EV_KEY
||
usage
->
type
==
EV_REL
||
usage
->
type
==
EV_ABS
))
usage
->
type
==
EV_REL
||
usage
->
type
==
EV_ABS
))
clear_bit
(
usage
->
code
,
*
bit
);
clear_bit
(
usage
->
code
,
*
bit
);
...
@@ -335,9 +335,9 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
...
@@ -335,9 +335,9 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
static
int
lg_event
(
struct
hid_device
*
hdev
,
struct
hid_field
*
field
,
static
int
lg_event
(
struct
hid_device
*
hdev
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
__s32
value
)
struct
hid_usage
*
usage
,
__s32
value
)
{
{
unsigned
long
quirks
=
(
unsigned
long
)
hid_get_drvdata
(
hdev
);
struct
lg_drv_data
*
drv_data
=
(
struct
lg_drv_data
*
)
hid_get_drvdata
(
hdev
);
if
((
quirks
&
LG_INVERT_HWHEEL
)
&&
usage
->
code
==
REL_HWHEEL
)
{
if
((
drv_data
->
quirks
&
LG_INVERT_HWHEEL
)
&&
usage
->
code
==
REL_HWHEEL
)
{
input_event
(
field
->
hidinput
->
input
,
usage
->
type
,
usage
->
code
,
input_event
(
field
->
hidinput
->
input
,
usage
->
type
,
usage
->
code
,
-
value
);
-
value
);
return
1
;
return
1
;
...
@@ -348,13 +348,20 @@ static int lg_event(struct hid_device *hdev, struct hid_field *field,
...
@@ -348,13 +348,20 @@ static int lg_event(struct hid_device *hdev, struct hid_field *field,
static
int
lg_probe
(
struct
hid_device
*
hdev
,
const
struct
hid_device_id
*
id
)
static
int
lg_probe
(
struct
hid_device
*
hdev
,
const
struct
hid_device_id
*
id
)
{
{
unsigned
long
quirks
=
id
->
driver_data
;
unsigned
int
connect_mask
=
HID_CONNECT_DEFAULT
;
unsigned
int
connect_mask
=
HID_CONNECT_DEFAULT
;
struct
lg_drv_data
*
drv_data
;
int
ret
;
int
ret
;
hid_set_drvdata
(
hdev
,
(
void
*
)
quirks
);
drv_data
=
kzalloc
(
sizeof
(
struct
lg_drv_data
),
GFP_KERNEL
);
if
(
!
drv_data
)
{
hid_err
(
hdev
,
"Insufficient memory, cannot allocate driver data
\n
"
);
return
-
ENOMEM
;
}
drv_data
->
quirks
=
id
->
driver_data
;
hid_set_drvdata
(
hdev
,
(
void
*
)
drv_data
);
if
(
quirks
&
LG_NOGET
)
if
(
drv_data
->
quirks
&
LG_NOGET
)
hdev
->
quirks
|=
HID_QUIRK_NOGET
;
hdev
->
quirks
|=
HID_QUIRK_NOGET
;
ret
=
hid_parse
(
hdev
);
ret
=
hid_parse
(
hdev
);
...
@@ -363,7 +370,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
...
@@ -363,7 +370,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto
err_free
;
goto
err_free
;
}
}
if
(
quirks
&
(
LG_FF
|
LG_FF2
|
LG_FF3
|
LG_FF4
))
if
(
drv_data
->
quirks
&
(
LG_FF
|
LG_FF2
|
LG_FF3
|
LG_FF4
))
connect_mask
&=
~
HID_CONNECT_FF
;
connect_mask
&=
~
HID_CONNECT_FF
;
ret
=
hid_hw_start
(
hdev
,
connect_mask
);
ret
=
hid_hw_start
(
hdev
,
connect_mask
);
...
@@ -392,27 +399,29 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
...
@@ -392,27 +399,29 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
}
}
}
}
if
(
quirks
&
LG_FF
)
if
(
drv_data
->
quirks
&
LG_FF
)
lgff_init
(
hdev
);
lgff_init
(
hdev
);
if
(
quirks
&
LG_FF2
)
if
(
drv_data
->
quirks
&
LG_FF2
)
lg2ff_init
(
hdev
);
lg2ff_init
(
hdev
);
if
(
quirks
&
LG_FF3
)
if
(
drv_data
->
quirks
&
LG_FF3
)
lg3ff_init
(
hdev
);
lg3ff_init
(
hdev
);
if
(
quirks
&
LG_FF4
)
if
(
drv_data
->
quirks
&
LG_FF4
)
lg4ff_init
(
hdev
);
lg4ff_init
(
hdev
);
return
0
;
return
0
;
err_free:
err_free:
kfree
(
drv_data
);
return
ret
;
return
ret
;
}
}
static
void
lg_remove
(
struct
hid_device
*
hdev
)
static
void
lg_remove
(
struct
hid_device
*
hdev
)
{
{
unsigned
long
quirks
=
(
unsigned
long
)
hid_get_drvdata
(
hdev
);
struct
lg_drv_data
*
drv_data
=
(
struct
lg_drv_data
*
)
hid_get_drvdata
(
hdev
);
if
(
quirks
&
LG_FF4
)
if
(
drv_data
->
quirks
&
LG_FF4
)
lg4ff_deinit
(
hdev
);
lg4ff_deinit
(
hdev
);
hid_hw_stop
(
hdev
);
hid_hw_stop
(
hdev
);
kfree
(
drv_data
);
}
}
static
const
struct
hid_device_id
lg_devices
[]
=
{
static
const
struct
hid_device_id
lg_devices
[]
=
{
...
...
drivers/hid/hid-lg.h
浏览文件 @
b3d07e03
#ifndef __HID_LG_H
#ifndef __HID_LG_H
#define __HID_LG_H
#define __HID_LG_H
struct
lg_drv_data
{
unsigned
long
quirks
;
void
*
device_props
;
/* Device specific properties */
};
#ifdef CONFIG_LOGITECH_FF
#ifdef CONFIG_LOGITECH_FF
int
lgff_init
(
struct
hid_device
*
hdev
);
int
lgff_init
(
struct
hid_device
*
hdev
);
#else
#else
...
...
drivers/hid/hid-lg4ff.c
浏览文件 @
b3d07e03
/*
/*
* Force feedback support for Logitech
Speed Force Wireles
s
* Force feedback support for Logitech
Gaming Wheel
s
*
*
* http://wiibrew.org/wiki/Logitech_USB_steering_wheel
* Including G27, G25, DFP, DFGT, FFEX, Momo, Momo2 &
* Speed Force Wireless (WiiWheel)
*
*
* Copyright (c) 2010 Simon Wood <simon@mungewell.org>
* Copyright (c) 2010 Simon Wood <simon@mungewell.org>
*/
*/
...
@@ -51,20 +52,18 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at
...
@@ -51,20 +52,18 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at
static
DEVICE_ATTR
(
range
,
S_IRWXU
|
S_IRWXG
|
S_IRWXO
,
lg4ff_range_show
,
lg4ff_range_store
);
static
DEVICE_ATTR
(
range
,
S_IRWXU
|
S_IRWXG
|
S_IRWXO
,
lg4ff_range_show
,
lg4ff_range_store
);
static
bool
list_inited
;
struct
lg4ff_device_entry
{
struct
lg4ff_device_entry
{
char
*
device_id
;
/* Use name in respective kobject structure's address as the ID */
__u16
range
;
__u16
range
;
__u16
min_range
;
__u16
min_range
;
__u16
max_range
;
__u16
max_range
;
__u8
leds
;
#ifdef CONFIG_LEDS_CLASS
__u8
led_state
;
struct
led_classdev
*
led
[
5
];
#endif
struct
list_head
list
;
struct
list_head
list
;
void
(
*
set_range
)(
struct
hid_device
*
hid
,
u16
range
);
void
(
*
set_range
)(
struct
hid_device
*
hid
,
u16
range
);
};
};
static
struct
lg4ff_device_entry
device_list
;
static
const
signed
short
lg4ff_wheel_effects
[]
=
{
static
const
signed
short
lg4ff_wheel_effects
[]
=
{
FF_CONSTANT
,
FF_CONSTANT
,
FF_AUTOCENTER
,
FF_AUTOCENTER
,
...
@@ -285,18 +284,20 @@ static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_n
...
@@ -285,18 +284,20 @@ static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_n
/* Read current range and display it in terminal */
/* Read current range and display it in terminal */
static
ssize_t
lg4ff_range_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
static
ssize_t
lg4ff_range_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
{
struct
lg4ff_device_entry
*
uninitialized_var
(
entry
);
struct
list_head
*
h
;
struct
hid_device
*
hid
=
to_hid_device
(
dev
);
struct
hid_device
*
hid
=
to_hid_device
(
dev
);
struct
lg4ff_device_entry
*
entry
;
struct
lg_drv_data
*
drv_data
;
size_t
count
;
size_t
count
;
list_for_each
(
h
,
&
device_list
.
list
)
{
drv_data
=
hid_get_drvdata
(
hid
);
entry
=
list_entry
(
h
,
struct
lg4ff_device_entry
,
list
);
if
(
!
drv_data
)
{
if
(
strcmp
(
entry
->
device_id
,
(
&
hid
->
dev
)
->
kobj
.
name
)
==
0
)
hid_err
(
hid
,
"Private driver data not found!
\n
"
);
break
;
return
0
;
}
}
if
(
h
==
&
device_list
.
list
)
{
dbg_hid
(
"Device not found!"
);
entry
=
drv_data
->
device_props
;
if
(
!
entry
)
{
hid_err
(
hid
,
"Device properties not found!
\n
"
);
return
0
;
return
0
;
}
}
...
@@ -308,19 +309,21 @@ static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *att
...
@@ -308,19 +309,21 @@ static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *att
* according to the type of the wheel */
* according to the type of the wheel */
static
ssize_t
lg4ff_range_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
static
ssize_t
lg4ff_range_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
{
struct
lg4ff_device_entry
*
uninitialized_var
(
entry
);
struct
list_head
*
h
;
struct
hid_device
*
hid
=
to_hid_device
(
dev
);
struct
hid_device
*
hid
=
to_hid_device
(
dev
);
struct
lg4ff_device_entry
*
entry
;
struct
lg_drv_data
*
drv_data
;
__u16
range
=
simple_strtoul
(
buf
,
NULL
,
10
);
__u16
range
=
simple_strtoul
(
buf
,
NULL
,
10
);
list_for_each
(
h
,
&
device_list
.
list
)
{
drv_data
=
hid_get_drvdata
(
hid
);
entry
=
list_entry
(
h
,
struct
lg4ff_device_entry
,
list
);
if
(
!
drv_data
)
{
if
(
strcmp
(
entry
->
device_id
,
(
&
hid
->
dev
)
->
kobj
.
name
)
==
0
)
hid_err
(
hid
,
"Private driver data not found!
\n
"
);
break
;
return
0
;
}
}
if
(
h
==
&
device_list
.
list
)
{
dbg_hid
(
"Device not found!"
);
entry
=
drv_data
->
device_props
;
return
count
;
if
(
!
entry
)
{
hid_err
(
hid
,
"Device properties not found!
\n
"
);
return
0
;
}
}
if
(
range
==
0
)
if
(
range
==
0
)
...
@@ -336,6 +339,88 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at
...
@@ -336,6 +339,88 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at
return
count
;
return
count
;
}
}
#ifdef CONFIG_LEDS_CLASS
static
void
lg4ff_set_leds
(
struct
hid_device
*
hid
,
__u8
leds
)
{
struct
list_head
*
report_list
=
&
hid
->
report_enum
[
HID_OUTPUT_REPORT
].
report_list
;
struct
hid_report
*
report
=
list_entry
(
report_list
->
next
,
struct
hid_report
,
list
);
report
->
field
[
0
]
->
value
[
0
]
=
0xf8
;
report
->
field
[
0
]
->
value
[
1
]
=
0x12
;
report
->
field
[
0
]
->
value
[
2
]
=
leds
;
report
->
field
[
0
]
->
value
[
3
]
=
0x00
;
report
->
field
[
0
]
->
value
[
4
]
=
0x00
;
report
->
field
[
0
]
->
value
[
5
]
=
0x00
;
report
->
field
[
0
]
->
value
[
6
]
=
0x00
;
usbhid_submit_report
(
hid
,
report
,
USB_DIR_OUT
);
}
static
void
lg4ff_led_set_brightness
(
struct
led_classdev
*
led_cdev
,
enum
led_brightness
value
)
{
struct
device
*
dev
=
led_cdev
->
dev
->
parent
;
struct
hid_device
*
hid
=
container_of
(
dev
,
struct
hid_device
,
dev
);
struct
lg_drv_data
*
drv_data
=
(
struct
lg_drv_data
*
)
hid_get_drvdata
(
hid
);
struct
lg4ff_device_entry
*
entry
;
int
i
,
state
=
0
;
if
(
!
drv_data
)
{
hid_err
(
hid
,
"Device data not found."
);
return
;
}
entry
=
(
struct
lg4ff_device_entry
*
)
drv_data
->
device_props
;
if
(
!
entry
)
{
hid_err
(
hid
,
"Device properties not found."
);
return
;
}
for
(
i
=
0
;
i
<
5
;
i
++
)
{
if
(
led_cdev
!=
entry
->
led
[
i
])
continue
;
state
=
(
entry
->
led_state
>>
i
)
&
1
;
if
(
value
==
LED_OFF
&&
state
)
{
entry
->
led_state
&=
~
(
1
<<
i
);
lg4ff_set_leds
(
hid
,
entry
->
led_state
);
}
else
if
(
value
!=
LED_OFF
&&
!
state
)
{
entry
->
led_state
|=
1
<<
i
;
lg4ff_set_leds
(
hid
,
entry
->
led_state
);
}
break
;
}
}
static
enum
led_brightness
lg4ff_led_get_brightness
(
struct
led_classdev
*
led_cdev
)
{
struct
device
*
dev
=
led_cdev
->
dev
->
parent
;
struct
hid_device
*
hid
=
container_of
(
dev
,
struct
hid_device
,
dev
);
struct
lg_drv_data
*
drv_data
=
(
struct
lg_drv_data
*
)
hid_get_drvdata
(
hid
);
struct
lg4ff_device_entry
*
entry
;
int
i
,
value
=
0
;
if
(
!
drv_data
)
{
hid_err
(
hid
,
"Device data not found."
);
return
LED_OFF
;
}
entry
=
(
struct
lg4ff_device_entry
*
)
drv_data
->
device_props
;
if
(
!
entry
)
{
hid_err
(
hid
,
"Device properties not found."
);
return
LED_OFF
;
}
for
(
i
=
0
;
i
<
5
;
i
++
)
if
(
led_cdev
==
entry
->
led
[
i
])
{
value
=
(
entry
->
led_state
>>
i
)
&
1
;
break
;
}
return
value
?
LED_FULL
:
LED_OFF
;
}
#endif
int
lg4ff_init
(
struct
hid_device
*
hid
)
int
lg4ff_init
(
struct
hid_device
*
hid
)
{
{
struct
hid_input
*
hidinput
=
list_entry
(
hid
->
inputs
.
next
,
struct
hid_input
,
list
);
struct
hid_input
*
hidinput
=
list_entry
(
hid
->
inputs
.
next
,
struct
hid_input
,
list
);
...
@@ -344,6 +429,7 @@ int lg4ff_init(struct hid_device *hid)
...
@@ -344,6 +429,7 @@ int lg4ff_init(struct hid_device *hid)
struct
hid_report
*
report
;
struct
hid_report
*
report
;
struct
hid_field
*
field
;
struct
hid_field
*
field
;
struct
lg4ff_device_entry
*
entry
;
struct
lg4ff_device_entry
*
entry
;
struct
lg_drv_data
*
drv_data
;
struct
usb_device_descriptor
*
udesc
;
struct
usb_device_descriptor
*
udesc
;
int
error
,
i
,
j
;
int
error
,
i
,
j
;
__u16
bcdDevice
,
rev_maj
,
rev_min
;
__u16
bcdDevice
,
rev_maj
,
rev_min
;
...
@@ -423,28 +509,24 @@ int lg4ff_init(struct hid_device *hid)
...
@@ -423,28 +509,24 @@ int lg4ff_init(struct hid_device *hid)
dev
->
ff
->
set_autocenter
(
dev
,
0
);
dev
->
ff
->
set_autocenter
(
dev
,
0
);
}
}
/* Initialize device_list if this is the first device to handle by lg4ff */
/* Get private driver data */
if
(
!
list_inited
)
{
drv_data
=
hid_get_drvdata
(
hid
);
INIT_LIST_HEAD
(
&
device_list
.
list
);
if
(
!
drv_data
)
{
list_inited
=
1
;
hid_err
(
hid
,
"Cannot add device, private driver data not allocated
\n
"
);
return
-
1
;
}
}
/*
Add the device to device_list
*/
/*
Initialize device properties
*/
entry
=
kzalloc
(
sizeof
(
struct
lg4ff_device_entry
),
GFP_KERNEL
);
entry
=
kzalloc
(
sizeof
(
struct
lg4ff_device_entry
),
GFP_KERNEL
);
if
(
!
entry
)
{
if
(
!
entry
)
{
hid_err
(
hid
,
"Cannot add device, insufficient memory.
\n
"
);
hid_err
(
hid
,
"Cannot add device, insufficient memory to allocate device properties.
\n
"
);
return
-
ENOMEM
;
}
entry
->
device_id
=
kstrdup
((
&
hid
->
dev
)
->
kobj
.
name
,
GFP_KERNEL
);
if
(
!
entry
->
device_id
)
{
hid_err
(
hid
,
"Cannot set device_id, insufficient memory.
\n
"
);
kfree
(
entry
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
drv_data
->
device_props
=
entry
;
entry
->
min_range
=
lg4ff_devices
[
i
].
min_range
;
entry
->
min_range
=
lg4ff_devices
[
i
].
min_range
;
entry
->
max_range
=
lg4ff_devices
[
i
].
max_range
;
entry
->
max_range
=
lg4ff_devices
[
i
].
max_range
;
entry
->
set_range
=
lg4ff_devices
[
i
].
set_range
;
entry
->
set_range
=
lg4ff_devices
[
i
].
set_range
;
list_add
(
&
entry
->
list
,
&
device_list
.
list
);
/* Create sysfs interface */
/* Create sysfs interface */
error
=
device_create_file
(
&
hid
->
dev
,
&
dev_attr_range
);
error
=
device_create_file
(
&
hid
->
dev
,
&
dev_attr_range
);
...
@@ -457,32 +539,100 @@ int lg4ff_init(struct hid_device *hid)
...
@@ -457,32 +539,100 @@ int lg4ff_init(struct hid_device *hid)
if
(
entry
->
set_range
!=
NULL
)
if
(
entry
->
set_range
!=
NULL
)
entry
->
set_range
(
hid
,
entry
->
range
);
entry
->
set_range
(
hid
,
entry
->
range
);
hid_info
(
hid
,
"Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>
\n
"
);
#ifdef CONFIG_LEDS_CLASS
/* register led subsystem - G27 only */
entry
->
led_state
=
0
;
for
(
j
=
0
;
j
<
5
;
j
++
)
entry
->
led
[
j
]
=
NULL
;
if
(
lg4ff_devices
[
i
].
product_id
==
USB_DEVICE_ID_LOGITECH_G27_WHEEL
)
{
struct
led_classdev
*
led
;
size_t
name_sz
;
char
*
name
;
lg4ff_set_leds
(
hid
,
0
);
name_sz
=
strlen
(
dev_name
(
&
hid
->
dev
))
+
8
;
for
(
j
=
0
;
j
<
5
;
j
++
)
{
led
=
kzalloc
(
sizeof
(
struct
led_classdev
)
+
name_sz
,
GFP_KERNEL
);
if
(
!
led
)
{
hid_err
(
hid
,
"can't allocate memory for LED %d
\n
"
,
j
);
goto
err
;
}
name
=
(
void
*
)(
&
led
[
1
]);
snprintf
(
name
,
name_sz
,
"%s::RPM%d"
,
dev_name
(
&
hid
->
dev
),
j
+
1
);
led
->
name
=
name
;
led
->
brightness
=
0
;
led
->
max_brightness
=
1
;
led
->
brightness_get
=
lg4ff_led_get_brightness
;
led
->
brightness_set
=
lg4ff_led_set_brightness
;
entry
->
led
[
j
]
=
led
;
error
=
led_classdev_register
(
&
hid
->
dev
,
led
);
if
(
error
)
{
hid_err
(
hid
,
"failed to register LED %d. Aborting.
\n
"
,
j
);
err:
/* Deregister LEDs (if any) */
for
(
j
=
0
;
j
<
5
;
j
++
)
{
led
=
entry
->
led
[
j
];
entry
->
led
[
j
]
=
NULL
;
if
(
!
led
)
continue
;
led_classdev_unregister
(
led
);
kfree
(
led
);
}
goto
out
;
/* Let the driver continue without LEDs */
}
}
}
out:
#endif
hid_info
(
hid
,
"Force feedback support for Logitech Gaming Wheels
\n
"
);
return
0
;
return
0
;
}
}
int
lg4ff_deinit
(
struct
hid_device
*
hid
)
int
lg4ff_deinit
(
struct
hid_device
*
hid
)
{
{
bool
found
=
0
;
struct
lg4ff_device_entry
*
entry
;
struct
lg4ff_device_entry
*
entry
;
struct
list_head
*
h
,
*
g
;
struct
lg_drv_data
*
drv_data
;
list_for_each_safe
(
h
,
g
,
&
device_list
.
list
)
{
entry
=
list_entry
(
h
,
struct
lg4ff_device_entry
,
list
);
device_remove_file
(
&
hid
->
dev
,
&
dev_attr_range
);
if
(
strcmp
(
entry
->
device_id
,
(
&
hid
->
dev
)
->
kobj
.
name
)
==
0
)
{
list_del
(
h
);
drv_data
=
hid_get_drvdata
(
hid
);
kfree
(
entry
->
device_id
);
if
(
!
drv_data
)
{
kfree
(
entry
);
hid_err
(
hid
,
"Error while deinitializing device, no private driver data.
\n
"
);
found
=
1
;
return
-
1
;
break
;
}
}
entry
=
drv_data
->
device_props
;
if
(
!
entry
)
{
hid_err
(
hid
,
"Error while deinitializing device, no device properties data.
\n
"
);
return
-
1
;
}
}
if
(
!
found
)
{
#ifdef CONFIG_LEDS_CLASS
dbg_hid
(
"Device entry not found!
\n
"
);
{
return
-
1
;
int
j
;
struct
led_classdev
*
led
;
/* Deregister LEDs (if any) */
for
(
j
=
0
;
j
<
5
;
j
++
)
{
led
=
entry
->
led
[
j
];
entry
->
led
[
j
]
=
NULL
;
if
(
!
led
)
continue
;
led_classdev_unregister
(
led
);
kfree
(
led
);
}
}
}
#endif
/* Deallocate memory */
kfree
(
entry
);
device_remove_file
(
&
hid
->
dev
,
&
dev_attr_range
);
dbg_hid
(
"Device successfully unregistered
\n
"
);
dbg_hid
(
"Device successfully unregistered
\n
"
);
return
0
;
return
0
;
}
}
drivers/hid/hid-multitouch.c
浏览文件 @
b3d07e03
...
@@ -70,9 +70,16 @@ struct mt_class {
...
@@ -70,9 +70,16 @@ struct mt_class {
bool
is_indirect
;
/* true for touchpads */
bool
is_indirect
;
/* true for touchpads */
};
};
struct
mt_fields
{
unsigned
usages
[
HID_MAX_FIELDS
];
unsigned
int
length
;
};
struct
mt_device
{
struct
mt_device
{
struct
mt_slot
curdata
;
/* placeholder of incoming data */
struct
mt_slot
curdata
;
/* placeholder of incoming data */
struct
mt_class
mtclass
;
/* our mt device class */
struct
mt_class
mtclass
;
/* our mt device class */
struct
mt_fields
*
fields
;
/* temporary placeholder for storing the
multitouch fields */
unsigned
last_field_index
;
/* last field index of the report */
unsigned
last_field_index
;
/* last field index of the report */
unsigned
last_slot_field
;
/* the last field of a slot */
unsigned
last_slot_field
;
/* the last field of a slot */
__s8
inputmode
;
/* InputMode HID feature, -1 if non-existent */
__s8
inputmode
;
/* InputMode HID feature, -1 if non-existent */
...
@@ -278,11 +285,15 @@ static void set_abs(struct input_dev *input, unsigned int code,
...
@@ -278,11 +285,15 @@ static void set_abs(struct input_dev *input, unsigned int code,
input_set_abs_params
(
input
,
code
,
fmin
,
fmax
,
fuzz
,
0
);
input_set_abs_params
(
input
,
code
,
fmin
,
fmax
,
fuzz
,
0
);
}
}
static
void
set_last_slot
_field
(
struct
hid_usage
*
usage
,
struct
mt_device
*
td
,
static
void
mt_store
_field
(
struct
hid_usage
*
usage
,
struct
mt_device
*
td
,
struct
hid_input
*
hi
)
struct
hid_input
*
hi
)
{
{
if
(
!
test_bit
(
usage
->
hid
,
hi
->
input
->
absbit
))
struct
mt_fields
*
f
=
td
->
fields
;
td
->
last_slot_field
=
usage
->
hid
;
if
(
f
->
length
>=
HID_MAX_FIELDS
)
return
;
f
->
usages
[
f
->
length
++
]
=
usage
->
hid
;
}
}
static
int
mt_input_mapping
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
,
static
int
mt_input_mapping
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
,
...
@@ -333,7 +344,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -333,7 +344,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
cls
->
sn_move
);
cls
->
sn_move
);
/* touchscreen emulation */
/* touchscreen emulation */
set_abs
(
hi
->
input
,
ABS_X
,
field
,
cls
->
sn_move
);
set_abs
(
hi
->
input
,
ABS_X
,
field
,
cls
->
sn_move
);
set_last_slot
_field
(
usage
,
td
,
hi
);
mt_store
_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_GD_Y
:
case
HID_GD_Y
:
...
@@ -343,7 +354,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -343,7 +354,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
cls
->
sn_move
);
cls
->
sn_move
);
/* touchscreen emulation */
/* touchscreen emulation */
set_abs
(
hi
->
input
,
ABS_Y
,
field
,
cls
->
sn_move
);
set_abs
(
hi
->
input
,
ABS_Y
,
field
,
cls
->
sn_move
);
set_last_slot
_field
(
usage
,
td
,
hi
);
mt_store
_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
}
}
...
@@ -352,24 +363,24 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -352,24 +363,24 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case
HID_UP_DIGITIZER
:
case
HID_UP_DIGITIZER
:
switch
(
usage
->
hid
)
{
switch
(
usage
->
hid
)
{
case
HID_DG_INRANGE
:
case
HID_DG_INRANGE
:
set_last_slot
_field
(
usage
,
td
,
hi
);
mt_store
_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_DG_CONFIDENCE
:
case
HID_DG_CONFIDENCE
:
set_last_slot
_field
(
usage
,
td
,
hi
);
mt_store
_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_DG_TIPSWITCH
:
case
HID_DG_TIPSWITCH
:
hid_map_usage
(
hi
,
usage
,
bit
,
max
,
EV_KEY
,
BTN_TOUCH
);
hid_map_usage
(
hi
,
usage
,
bit
,
max
,
EV_KEY
,
BTN_TOUCH
);
input_set_capability
(
hi
->
input
,
EV_KEY
,
BTN_TOUCH
);
input_set_capability
(
hi
->
input
,
EV_KEY
,
BTN_TOUCH
);
set_last_slot
_field
(
usage
,
td
,
hi
);
mt_store
_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_DG_CONTACTID
:
case
HID_DG_CONTACTID
:
if
(
!
td
->
maxcontacts
)
if
(
!
td
->
maxcontacts
)
td
->
maxcontacts
=
MT_DEFAULT_MAXCONTACT
;
td
->
maxcontacts
=
MT_DEFAULT_MAXCONTACT
;
input_mt_init_slots
(
hi
->
input
,
td
->
maxcontacts
);
input_mt_init_slots
(
hi
->
input
,
td
->
maxcontacts
);
td
->
last_slot_field
=
usage
->
hid
;
mt_store_field
(
usage
,
td
,
hi
)
;
td
->
last_field_index
=
field
->
index
;
td
->
last_field_index
=
field
->
index
;
td
->
touches_by_report
++
;
td
->
touches_by_report
++
;
return
1
;
return
1
;
...
@@ -378,7 +389,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -378,7 +389,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
EV_ABS
,
ABS_MT_TOUCH_MAJOR
);
EV_ABS
,
ABS_MT_TOUCH_MAJOR
);
set_abs
(
hi
->
input
,
ABS_MT_TOUCH_MAJOR
,
field
,
set_abs
(
hi
->
input
,
ABS_MT_TOUCH_MAJOR
,
field
,
cls
->
sn_width
);
cls
->
sn_width
);
set_last_slot
_field
(
usage
,
td
,
hi
);
mt_store
_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_DG_HEIGHT
:
case
HID_DG_HEIGHT
:
...
@@ -388,7 +399,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -388,7 +399,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
cls
->
sn_height
);
cls
->
sn_height
);
input_set_abs_params
(
hi
->
input
,
input_set_abs_params
(
hi
->
input
,
ABS_MT_ORIENTATION
,
0
,
1
,
0
,
0
);
ABS_MT_ORIENTATION
,
0
,
1
,
0
,
0
);
set_last_slot
_field
(
usage
,
td
,
hi
);
mt_store
_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_DG_TIPPRESSURE
:
case
HID_DG_TIPPRESSURE
:
...
@@ -399,7 +410,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -399,7 +410,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
/* touchscreen emulation */
/* touchscreen emulation */
set_abs
(
hi
->
input
,
ABS_PRESSURE
,
field
,
set_abs
(
hi
->
input
,
ABS_PRESSURE
,
field
,
cls
->
sn_pressure
);
cls
->
sn_pressure
);
set_last_slot
_field
(
usage
,
td
,
hi
);
mt_store
_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_DG_CONTACTCOUNT
:
case
HID_DG_CONTACTCOUNT
:
...
@@ -653,6 +664,16 @@ static void mt_post_parse_default_settings(struct mt_device *td)
...
@@ -653,6 +664,16 @@ static void mt_post_parse_default_settings(struct mt_device *td)
td
->
mtclass
.
quirks
=
quirks
;
td
->
mtclass
.
quirks
=
quirks
;
}
}
static
void
mt_post_parse
(
struct
mt_device
*
td
)
{
struct
mt_fields
*
f
=
td
->
fields
;
if
(
td
->
touches_by_report
>
0
)
{
int
field_count_per_touch
=
f
->
length
/
td
->
touches_by_report
;
td
->
last_slot_field
=
f
->
usages
[
field_count_per_touch
-
1
];
}
}
static
int
mt_probe
(
struct
hid_device
*
hdev
,
const
struct
hid_device_id
*
id
)
static
int
mt_probe
(
struct
hid_device
*
hdev
,
const
struct
hid_device_id
*
id
)
{
{
int
ret
,
i
;
int
ret
,
i
;
...
@@ -683,6 +704,13 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
...
@@ -683,6 +704,13 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
td
->
maxcontact_report_id
=
-
1
;
td
->
maxcontact_report_id
=
-
1
;
hid_set_drvdata
(
hdev
,
td
);
hid_set_drvdata
(
hdev
,
td
);
td
->
fields
=
kzalloc
(
sizeof
(
struct
mt_fields
),
GFP_KERNEL
);
if
(
!
td
->
fields
)
{
dev_err
(
&
hdev
->
dev
,
"cannot allocate multitouch fields data
\n
"
);
ret
=
-
ENOMEM
;
goto
fail
;
}
ret
=
hid_parse
(
hdev
);
ret
=
hid_parse
(
hdev
);
if
(
ret
!=
0
)
if
(
ret
!=
0
)
goto
fail
;
goto
fail
;
...
@@ -691,6 +719,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
...
@@ -691,6 +719,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
if
(
ret
)
if
(
ret
)
goto
fail
;
goto
fail
;
mt_post_parse
(
td
);
if
(
id
->
vendor
==
HID_ANY_ID
&&
id
->
product
==
HID_ANY_ID
)
if
(
id
->
vendor
==
HID_ANY_ID
&&
id
->
product
==
HID_ANY_ID
)
mt_post_parse_default_settings
(
td
);
mt_post_parse_default_settings
(
td
);
...
@@ -708,9 +738,13 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
...
@@ -708,9 +738,13 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
mt_set_maxcontacts
(
hdev
);
mt_set_maxcontacts
(
hdev
);
mt_set_input_mode
(
hdev
);
mt_set_input_mode
(
hdev
);
kfree
(
td
->
fields
);
td
->
fields
=
NULL
;
return
0
;
return
0
;
fail:
fail:
kfree
(
td
->
fields
);
kfree
(
td
);
kfree
(
td
);
return
ret
;
return
ret
;
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录