Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
f0fab8e0
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看板
提交
f0fab8e0
编写于
4月 04, 2008
作者:
D
Dmitry Torokhov
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'xbox'
上级
5550fbae
6eae9b0a
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
187 addition
and
24 deletion
+187
-24
drivers/input/joystick/xpad.c
drivers/input/joystick/xpad.c
+187
-24
未找到文件。
drivers/input/joystick/xpad.c
浏览文件 @
f0fab8e0
/*
* X-Box gamepad
- v0.0.6
* X-Box gamepad
driver
*
* Copyright (c) 2002 Marko Friedemann <mfr@bmx-chemnitz.de>
* 2004 Oliver Schwartz <Oliver.Schwartz@gmx.de>,
...
...
@@ -68,6 +68,8 @@
* - dance pads will map D-PAD to buttons, not axes
* - pass the module paramater 'dpad_to_buttons' to force
* the D-PAD to map to buttons if your pad is not detected
*
* Later changes can be tracked in SCM.
*/
#include <linux/kernel.h>
...
...
@@ -77,7 +79,6 @@
#include <linux/module.h>
#include <linux/usb/input.h>
#define DRIVER_VERSION "v0.0.6"
#define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>"
#define DRIVER_DESC "X-Box pad driver"
...
...
@@ -87,10 +88,12 @@
but we map them to axes when possible to simplify things */
#define MAP_DPAD_TO_BUTTONS 0
#define MAP_DPAD_TO_AXES 1
#define MAP_DPAD_UNKNOWN
-1
#define MAP_DPAD_UNKNOWN
2
#define XTYPE_XBOX 0
#define XTYPE_XBOX360 1
#define XTYPE_XBOX360W 2
#define XTYPE_UNKNOWN 3
static
int
dpad_to_buttons
;
module_param
(
dpad_to_buttons
,
bool
,
S_IRUGO
);
...
...
@@ -107,8 +110,10 @@ static const struct xpad_device {
{
0x045e
,
0x0289
,
"Microsoft X-Box pad v2 (US)"
,
MAP_DPAD_TO_AXES
,
XTYPE_XBOX
},
{
0x045e
,
0x0285
,
"Microsoft X-Box pad (Japan)"
,
MAP_DPAD_TO_AXES
,
XTYPE_XBOX
},
{
0x045e
,
0x0287
,
"Microsoft Xbox Controller S"
,
MAP_DPAD_TO_AXES
,
XTYPE_XBOX
},
{
0x045e
,
0x0719
,
"Xbox 360 Wireless Receiver"
,
MAP_DPAD_TO_BUTTONS
,
XTYPE_XBOX360W
},
{
0x0c12
,
0x8809
,
"RedOctane Xbox Dance Pad"
,
MAP_DPAD_TO_BUTTONS
,
XTYPE_XBOX
},
{
0x044f
,
0x0f07
,
"Thrustmaster, Inc. Controller"
,
MAP_DPAD_TO_AXES
,
XTYPE_XBOX
},
{
0x046d
,
0xc242
,
"Logitech Chillstream Controller"
,
MAP_DPAD_TO_AXES
,
XTYPE_XBOX360
},
{
0x046d
,
0xca84
,
"Logitech Xbox Cordless Controller"
,
MAP_DPAD_TO_AXES
,
XTYPE_XBOX
},
{
0x046d
,
0xca88
,
"Logitech Compact Controller for Xbox"
,
MAP_DPAD_TO_AXES
,
XTYPE_XBOX
},
{
0x05fd
,
0x1007
,
"Mad Catz Controller (unverified)"
,
MAP_DPAD_TO_AXES
,
XTYPE_XBOX
},
...
...
@@ -135,18 +140,26 @@ static const struct xpad_device {
{
0x0f30
,
0x8888
,
"BigBen XBMiniPad Controller"
,
MAP_DPAD_TO_AXES
,
XTYPE_XBOX
},
{
0x102c
,
0xff0c
,
"Joytech Wireless Advanced Controller"
,
MAP_DPAD_TO_AXES
,
XTYPE_XBOX
},
{
0x12ab
,
0x8809
,
"Xbox DDR dancepad"
,
MAP_DPAD_TO_BUTTONS
,
XTYPE_XBOX
},
{
0x1430
,
0x4748
,
"RedOctane Guitar Hero X-plorer"
,
MAP_DPAD_TO_AXES
,
XTYPE_XBOX360
},
{
0x1430
,
0x8888
,
"TX6500+ Dance Pad (first generation)"
,
MAP_DPAD_TO_BUTTONS
,
XTYPE_XBOX
},
{
0x045e
,
0x028e
,
"Microsoft X-Box 360 pad"
,
MAP_DPAD_TO_AXES
,
XTYPE_XBOX360
},
{
0xffff
,
0xffff
,
"Chinese-made Xbox Controller"
,
MAP_DPAD_TO_AXES
,
XTYPE_XBOX
},
{
0x0000
,
0x0000
,
"Generic X-Box pad"
,
MAP_DPAD_UNKNOWN
,
XTYPE_
XBOX
}
{
0x0000
,
0x0000
,
"Generic X-Box pad"
,
MAP_DPAD_UNKNOWN
,
XTYPE_
UNKNOWN
}
};
static
const
signed
short
xpad_btn
[]
=
{
BTN_A
,
BTN_B
,
BTN_C
,
BTN_X
,
BTN_Y
,
BTN_Z
,
/* "analog" buttons */
/* buttons shared with xbox and xbox360 */
static
const
signed
short
xpad_common_btn
[]
=
{
BTN_A
,
BTN_B
,
BTN_X
,
BTN_Y
,
/* "analog" buttons */
BTN_START
,
BTN_BACK
,
BTN_THUMBL
,
BTN_THUMBR
,
/* start/back/sticks */
-
1
/* terminating entry */
};
/* original xbox controllers only */
static
const
signed
short
xpad_btn
[]
=
{
BTN_C
,
BTN_Z
,
/* "analog" buttons */
-
1
/* terminating entry */
};
/* only used if MAP_DPAD_TO_BUTTONS */
static
const
signed
short
xpad_btn_pad
[]
=
{
BTN_LEFT
,
BTN_RIGHT
,
/* d-pad left, right */
...
...
@@ -173,12 +186,27 @@ static const signed short xpad_abs_pad[] = {
-
1
/* terminating entry */
};
/* Xbox 360 has a vendor-specific (sub)class, so we cannot match it with only
* USB_INTERFACE_INFO, more to that this device has 4 InterfaceProtocols,
* but we need only one of them. */
/* Xbox 360 has a vendor-specific class, so we cannot match it with only
* USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
* match against vendor id as well. Wired Xbox 360 devices have protocol 1,
* wireless controllers have protocol 129. */
#define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \
.match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
.idVendor = (vend), \
.bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
.bInterfaceSubClass = 93, \
.bInterfaceProtocol = (pr)
#define XPAD_XBOX360_VENDOR(vend) \
{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \
{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) }
static
struct
usb_device_id
xpad_table
[]
=
{
{
USB_INTERFACE_INFO
(
'X'
,
'B'
,
0
)
},
/* X-Box USB-IF not approved class */
{
USB_DEVICE_INTERFACE_PROTOCOL
(
0x045e
,
0x028e
,
1
)
},
/* X-Box 360 controller */
XPAD_XBOX360_VENDOR
(
0x045e
),
/* Microsoft X-Box 360 controllers */
XPAD_XBOX360_VENDOR
(
0x046d
),
/* Logitech X-Box 360 style controllers */
XPAD_XBOX360_VENDOR
(
0x0738
),
/* Mad Catz X-Box 360 controllers */
XPAD_XBOX360_VENDOR
(
0x0e6f
),
/* 0x0e6f X-Box 360 controllers */
XPAD_XBOX360_VENDOR
(
0x1430
),
/* RedOctane X-Box 360 controllers */
{
}
};
...
...
@@ -188,10 +216,15 @@ struct usb_xpad {
struct
input_dev
*
dev
;
/* input device interface */
struct
usb_device
*
udev
;
/* usb device */
int
pad_present
;
struct
urb
*
irq_in
;
/* urb for interrupt in report */
unsigned
char
*
idata
;
/* input data */
dma_addr_t
idata_dma
;
struct
urb
*
bulk_out
;
unsigned
char
*
bdata
;
#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
struct
urb
*
irq_out
;
/* urb for interrupt out report */
unsigned
char
*
odata
;
/* output data */
...
...
@@ -227,13 +260,13 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
input_report_abs
(
dev
,
ABS_X
,
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
12
)));
input_report_abs
(
dev
,
ABS_Y
,
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
14
)));
~
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
14
)));
/* right stick */
input_report_abs
(
dev
,
ABS_RX
,
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
16
)));
input_report_abs
(
dev
,
ABS_RY
,
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
18
)));
~
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
18
)));
/* triggers left/right */
input_report_abs
(
dev
,
ABS_Z
,
data
[
10
]);
...
...
@@ -321,13 +354,13 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
input_report_abs
(
dev
,
ABS_X
,
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
6
)));
input_report_abs
(
dev
,
ABS_Y
,
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
8
)));
~
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
8
)));
/* right stick */
input_report_abs
(
dev
,
ABS_RX
,
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
10
)));
input_report_abs
(
dev
,
ABS_RY
,
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
12
)));
~
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
12
)));
/* triggers left/right */
input_report_abs
(
dev
,
ABS_Z
,
data
[
4
]);
...
...
@@ -336,6 +369,39 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
input_sync
(
dev
);
}
/*
* xpad360w_process_packet
*
* Completes a request by converting the data into events for the
* input subsystem. It is version for xbox 360 wireless controller.
*
* Byte.Bit
* 00.1 - Status change: The controller or headset has connected/disconnected
* Bits 01.7 and 01.6 are valid
* 01.7 - Controller present
* 01.6 - Headset present
* 01.1 - Pad state (Bytes 4+) valid
*
*/
static
void
xpad360w_process_packet
(
struct
usb_xpad
*
xpad
,
u16
cmd
,
unsigned
char
*
data
)
{
/* Presence change */
if
(
data
[
0
]
&
0x08
)
{
if
(
data
[
1
]
&
0x80
)
{
xpad
->
pad_present
=
1
;
usb_submit_urb
(
xpad
->
bulk_out
,
GFP_ATOMIC
);
}
else
xpad
->
pad_present
=
0
;
}
/* Valid pad data */
if
(
!
(
data
[
1
]
&
0x1
))
return
;
xpad360_process_packet
(
xpad
,
cmd
,
&
data
[
4
]);
}
static
void
xpad_irq_in
(
struct
urb
*
urb
)
{
struct
usb_xpad
*
xpad
=
urb
->
context
;
...
...
@@ -358,10 +424,16 @@ static void xpad_irq_in(struct urb *urb)
goto
exit
;
}
if
(
xpad
->
xtype
==
XTYPE_XBOX360
)
switch
(
xpad
->
xtype
)
{
case
XTYPE_XBOX360
:
xpad360_process_packet
(
xpad
,
0
,
xpad
->
idata
);
else
break
;
case
XTYPE_XBOX360W
:
xpad360w_process_packet
(
xpad
,
0
,
xpad
->
idata
);
break
;
default:
xpad_process_packet
(
xpad
,
0
,
xpad
->
idata
);
}
exit:
retval
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
...
...
@@ -399,6 +471,23 @@ static void xpad_irq_out(struct urb *urb)
__FUNCTION__
,
retval
);
}
static
void
xpad_bulk_out
(
struct
urb
*
urb
)
{
switch
(
urb
->
status
)
{
case
0
:
/* success */
break
;
case
-
ECONNRESET
:
case
-
ENOENT
:
case
-
ESHUTDOWN
:
/* this urb is terminated, clean up */
dbg
(
"%s - urb shutting down with status: %d"
,
__FUNCTION__
,
urb
->
status
);
break
;
default:
dbg
(
"%s - nonzero urb status received: %d"
,
__FUNCTION__
,
urb
->
status
);
}
}
static
int
xpad_init_output
(
struct
usb_interface
*
intf
,
struct
usb_xpad
*
xpad
)
{
struct
usb_endpoint_descriptor
*
ep_irq_out
;
...
...
@@ -408,7 +497,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
return
0
;
xpad
->
odata
=
usb_buffer_alloc
(
xpad
->
udev
,
XPAD_PKT_LEN
,
GFP_
ATOMIC
,
&
xpad
->
odata_dma
);
GFP_
KERNEL
,
&
xpad
->
odata_dma
);
if
(
!
xpad
->
odata
)
goto
fail1
;
...
...
@@ -477,6 +566,9 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
static
int
xpad_init_ff
(
struct
usb_xpad
*
xpad
)
{
if
(
xpad
->
xtype
!=
XTYPE_XBOX360
)
return
0
;
input_set_capability
(
xpad
->
dev
,
EV_FF
,
FF_RUMBLE
);
return
input_ff_create_memless
(
xpad
->
dev
,
NULL
,
xpad_play_effect
);
...
...
@@ -574,6 +666,10 @@ static int xpad_open(struct input_dev *dev)
{
struct
usb_xpad
*
xpad
=
input_get_drvdata
(
dev
);
/* URB was submitted in probe */
if
(
xpad
->
xtype
==
XTYPE_XBOX360W
)
return
0
;
xpad
->
irq_in
->
dev
=
xpad
->
udev
;
if
(
usb_submit_urb
(
xpad
->
irq_in
,
GFP_KERNEL
))
return
-
EIO
;
...
...
@@ -585,7 +681,8 @@ static void xpad_close(struct input_dev *dev)
{
struct
usb_xpad
*
xpad
=
input_get_drvdata
(
dev
);
usb_kill_urb
(
xpad
->
irq_in
);
if
(
xpad
->
xtype
!=
XTYPE_XBOX360W
)
usb_kill_urb
(
xpad
->
irq_in
);
xpad_stop_output
(
xpad
);
}
...
...
@@ -632,7 +729,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
goto
fail1
;
xpad
->
idata
=
usb_buffer_alloc
(
udev
,
XPAD_PKT_LEN
,
GFP_
ATOMIC
,
&
xpad
->
idata_dma
);
GFP_
KERNEL
,
&
xpad
->
idata_dma
);
if
(
!
xpad
->
idata
)
goto
fail1
;
...
...
@@ -644,7 +741,16 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad
->
dpad_mapping
=
xpad_device
[
i
].
dpad_mapping
;
xpad
->
xtype
=
xpad_device
[
i
].
xtype
;
if
(
xpad
->
dpad_mapping
==
MAP_DPAD_UNKNOWN
)
xpad
->
dpad_mapping
=
dpad_to_buttons
;
xpad
->
dpad_mapping
=
!
dpad_to_buttons
;
if
(
xpad
->
xtype
==
XTYPE_UNKNOWN
)
{
if
(
intf
->
cur_altsetting
->
desc
.
bInterfaceClass
==
USB_CLASS_VENDOR_SPEC
)
{
if
(
intf
->
cur_altsetting
->
desc
.
bInterfaceProtocol
==
129
)
xpad
->
xtype
=
XTYPE_XBOX360W
;
else
xpad
->
xtype
=
XTYPE_XBOX360
;
}
else
xpad
->
xtype
=
XTYPE_XBOX
;
}
xpad
->
dev
=
input_dev
;
usb_make_path
(
udev
,
xpad
->
phys
,
sizeof
(
xpad
->
phys
));
strlcat
(
xpad
->
phys
,
"/input0"
,
sizeof
(
xpad
->
phys
));
...
...
@@ -662,11 +768,14 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
input_dev
->
evbit
[
0
]
=
BIT_MASK
(
EV_KEY
)
|
BIT_MASK
(
EV_ABS
);
/* set up buttons */
for
(
i
=
0
;
xpad_btn
[
i
]
>=
0
;
i
++
)
set_bit
(
xpad_btn
[
i
],
input_dev
->
keybit
);
if
(
xpad
->
xtype
==
XTYPE_XBOX360
)
for
(
i
=
0
;
xpad_
common_
btn
[
i
]
>=
0
;
i
++
)
set_bit
(
xpad_
common_
btn
[
i
],
input_dev
->
keybit
);
if
(
(
xpad
->
xtype
==
XTYPE_XBOX360
)
||
(
xpad
->
xtype
==
XTYPE_XBOX360W
)
)
for
(
i
=
0
;
xpad360_btn
[
i
]
>=
0
;
i
++
)
set_bit
(
xpad360_btn
[
i
],
input_dev
->
keybit
);
else
for
(
i
=
0
;
xpad_btn
[
i
]
>=
0
;
i
++
)
set_bit
(
xpad_btn
[
i
],
input_dev
->
keybit
);
if
(
xpad
->
dpad_mapping
==
MAP_DPAD_TO_BUTTONS
)
for
(
i
=
0
;
xpad_btn_pad
[
i
]
>=
0
;
i
++
)
set_bit
(
xpad_btn_pad
[
i
],
input_dev
->
keybit
);
...
...
@@ -703,8 +812,57 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
goto
fail4
;
usb_set_intfdata
(
intf
,
xpad
);
/*
* Submit the int URB immediatly rather than waiting for open
* because we get status messages from the device whether
* or not any controllers are attached. In fact, it's
* exactly the message that a controller has arrived that
* we're waiting for.
*/
if
(
xpad
->
xtype
==
XTYPE_XBOX360W
)
{
xpad
->
irq_in
->
dev
=
xpad
->
udev
;
error
=
usb_submit_urb
(
xpad
->
irq_in
,
GFP_KERNEL
);
if
(
error
)
goto
fail4
;
/*
* Setup the message to set the LEDs on the
* controller when it shows up
*/
xpad
->
bulk_out
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
xpad
->
bulk_out
)
goto
fail5
;
xpad
->
bdata
=
kzalloc
(
XPAD_PKT_LEN
,
GFP_KERNEL
);
if
(
!
xpad
->
bdata
)
goto
fail6
;
xpad
->
bdata
[
2
]
=
0x08
;
switch
(
intf
->
cur_altsetting
->
desc
.
bInterfaceNumber
)
{
case
0
:
xpad
->
bdata
[
3
]
=
0x42
;
break
;
case
2
:
xpad
->
bdata
[
3
]
=
0x43
;
break
;
case
4
:
xpad
->
bdata
[
3
]
=
0x44
;
break
;
case
6
:
xpad
->
bdata
[
3
]
=
0x45
;
}
ep_irq_in
=
&
intf
->
cur_altsetting
->
endpoint
[
1
].
desc
;
usb_fill_bulk_urb
(
xpad
->
bulk_out
,
udev
,
usb_sndbulkpipe
(
udev
,
ep_irq_in
->
bEndpointAddress
),
xpad
->
bdata
,
XPAD_PKT_LEN
,
xpad_bulk_out
,
xpad
);
}
return
0
;
fail6:
usb_free_urb
(
xpad
->
bulk_out
);
fail5:
usb_kill_urb
(
xpad
->
irq_in
);
fail4:
usb_free_urb
(
xpad
->
irq_in
);
fail3:
xpad_deinit_output
(
xpad
);
fail2:
usb_buffer_free
(
udev
,
XPAD_PKT_LEN
,
xpad
->
idata
,
xpad
->
idata_dma
);
...
...
@@ -723,6 +881,11 @@ static void xpad_disconnect(struct usb_interface *intf)
xpad_led_disconnect
(
xpad
);
input_unregister_device
(
xpad
->
dev
);
xpad_deinit_output
(
xpad
);
if
(
xpad
->
xtype
==
XTYPE_XBOX360W
)
{
usb_kill_urb
(
xpad
->
bulk_out
);
usb_free_urb
(
xpad
->
bulk_out
);
usb_kill_urb
(
xpad
->
irq_in
);
}
usb_free_urb
(
xpad
->
irq_in
);
usb_buffer_free
(
xpad
->
udev
,
XPAD_PKT_LEN
,
xpad
->
idata
,
xpad
->
idata_dma
);
...
...
@@ -741,7 +904,7 @@ static int __init usb_xpad_init(void)
{
int
result
=
usb_register
(
&
xpad_driver
);
if
(
result
==
0
)
info
(
DRIVER_DESC
":"
DRIVER_VERSION
);
info
(
DRIVER_DESC
);
return
result
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录