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
nexedi
linux
Commits
90b9b0d5
Commit
90b9b0d5
authored
Jun 29, 2019
by
Dmitry Torokhov
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'iforce' into next
Bring in improvements to driver for I-Force devices.
parents
002cdb95
11518370
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
424 additions
and
410 deletions
+424
-410
drivers/input/joystick/iforce/Kconfig
drivers/input/joystick/iforce/Kconfig
+4
-4
drivers/input/joystick/iforce/Makefile
drivers/input/joystick/iforce/Makefile
+3
-4
drivers/input/joystick/iforce/iforce-ff.c
drivers/input/joystick/iforce/iforce-ff.c
+9
-9
drivers/input/joystick/iforce/iforce-main.c
drivers/input/joystick/iforce/iforce-main.c
+57
-121
drivers/input/joystick/iforce/iforce-packets.c
drivers/input/joystick/iforce/iforce-packets.c
+70
-145
drivers/input/joystick/iforce/iforce-serio.c
drivers/input/joystick/iforce/iforce-serio.c
+124
-37
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/joystick/iforce/iforce-usb.c
+135
-57
drivers/input/joystick/iforce/iforce.h
drivers/input/joystick/iforce/iforce.h
+22
-33
No files found.
drivers/input/joystick/iforce/Kconfig
View file @
90b9b0d5
...
...
@@ -13,15 +13,15 @@ config JOYSTICK_IFORCE
module will be called iforce.
config JOYSTICK_IFORCE_USB
bool
"I-Force USB joysticks and wheels"
depends on JOYSTICK_IFORCE &&
(JOYSTICK_IFORCE=m || USB=y) &&
USB
tristate
"I-Force USB joysticks and wheels"
depends on JOYSTICK_IFORCE && USB
help
Say Y here if you have an I-Force joystick or steering wheel
connected to your USB port.
config JOYSTICK_IFORCE_232
bool
"I-Force Serial joysticks and wheels"
depends on JOYSTICK_IFORCE &&
(JOYSTICK_IFORCE=m || SERIO=y) &&
SERIO
tristate
"I-Force Serial joysticks and wheels"
depends on JOYSTICK_IFORCE && SERIO
help
Say Y here if you have an I-Force joystick or steering wheel
connected to your serial (COM) port.
...
...
drivers/input/joystick/iforce/Makefile
View file @
90b9b0d5
...
...
@@ -4,8 +4,7 @@
# By Johann Deneux <johann.deneux@gmail.com>
#
obj-$(CONFIG_JOYSTICK_IFORCE)
+=
iforce.o
obj-$(CONFIG_JOYSTICK_IFORCE)
+=
iforce.o
iforce-y
:=
iforce-ff.o iforce-main.o iforce-packets.o
iforce
-$(CONFIG_JOYSTICK_IFORCE_232)
+=
iforce-serio.o
iforce
-$(CONFIG_JOYSTICK_IFORCE_USB)
+=
iforce-usb.o
obj
-$(CONFIG_JOYSTICK_IFORCE_232)
+=
iforce-serio.o
obj
-$(CONFIG_JOYSTICK_IFORCE_USB)
+=
iforce-usb.o
drivers/input/joystick/iforce/iforce-ff.c
View file @
90b9b0d5
...
...
@@ -384,12 +384,12 @@ int iforce_upload_periodic(struct iforce *iforce, struct ff_effect *effect, stru
}
switch
(
effect
->
u
.
periodic
.
waveform
)
{
case
FF_SQUARE
:
wave_code
=
0x20
;
break
;
case
FF_TRIANGLE
:
wave_code
=
0x21
;
break
;
case
FF_SINE
:
wave_code
=
0x22
;
break
;
case
FF_SAW_UP
:
wave_code
=
0x23
;
break
;
case
FF_SAW_DOWN
:
wave_code
=
0x24
;
break
;
default:
wave_code
=
0x20
;
break
;
case
FF_SQUARE
:
wave_code
=
0x20
;
break
;
case
FF_TRIANGLE
:
wave_code
=
0x21
;
break
;
case
FF_SINE
:
wave_code
=
0x22
;
break
;
case
FF_SAW_UP
:
wave_code
=
0x23
;
break
;
case
FF_SAW_DOWN
:
wave_code
=
0x24
;
break
;
default:
wave_code
=
0x20
;
break
;
}
if
(
!
old
||
need_core
(
old
,
effect
))
{
...
...
@@ -488,9 +488,9 @@ int iforce_upload_condition(struct iforce *iforce, struct ff_effect *effect, str
int
core_err
=
0
;
switch
(
effect
->
type
)
{
case
FF_SPRING
:
type
=
0x40
;
break
;
case
FF_DAMPER
:
type
=
0x41
;
break
;
default:
return
-
1
;
case
FF_SPRING
:
type
=
0x40
;
break
;
case
FF_DAMPER
:
type
=
0x41
;
break
;
default:
return
-
1
;
}
if
(
!
old
||
need_condition_modifier
(
iforce
,
old
,
effect
))
{
...
...
drivers/input/joystick/iforce/iforce-main.c
View file @
90b9b0d5
...
...
@@ -21,10 +21,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <asm/unaligned.h>
#include "iforce.h"
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>"
);
MODULE_DESCRIPTION
(
"
USB/RS232
I-Force joysticks and wheels driver"
);
MODULE_DESCRIPTION
(
"
Core
I-Force joysticks and wheels driver"
);
MODULE_LICENSE
(
"GPL"
);
static
signed
short
btn_joystick
[]
=
...
...
@@ -67,6 +68,7 @@ static struct iforce_device iforce_device[] = {
{
0x05ef
,
0x8888
,
"AVB Top Shot Force Feedback Racing Wheel"
,
btn_wheel
,
abs_wheel
,
ff_iforce
},
//?
{
0x061c
,
0xc0a4
,
"ACT LABS Force RS"
,
btn_wheel
,
abs_wheel
,
ff_iforce
},
//?
{
0x061c
,
0xc084
,
"ACT LABS Force RS"
,
btn_wheel
,
abs_wheel
,
ff_iforce
},
{
0x06a3
,
0xff04
,
"Saitek R440 Force Wheel"
,
btn_wheel
,
abs_wheel
,
ff_iforce
},
//?
{
0x06f8
,
0x0001
,
"Guillemot Race Leader Force Feedback"
,
btn_wheel
,
abs_wheel
,
ff_iforce
},
//?
{
0x06f8
,
0x0001
,
"Guillemot Jet Leader Force Feedback"
,
btn_joystick
,
abs_joystick_rudder
,
ff_iforce
},
{
0x06f8
,
0x0004
,
"Guillemot Force Feedback Racing Wheel"
,
btn_wheel
,
abs_wheel
,
ff_iforce
},
//?
...
...
@@ -132,22 +134,21 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect,
* Upload the effect
*/
switch
(
effect
->
type
)
{
case
FF_PERIODIC
:
ret
=
iforce_upload_periodic
(
iforce
,
effect
,
old
);
break
;
case
FF_PERIODIC
:
ret
=
iforce_upload_periodic
(
iforce
,
effect
,
old
);
break
;
case
FF_CONSTANT
:
ret
=
iforce_upload_constant
(
iforce
,
effect
,
old
);
break
;
case
FF_CONSTANT
:
ret
=
iforce_upload_constant
(
iforce
,
effect
,
old
);
break
;
case
FF_SPRING
:
case
FF_DAMPER
:
ret
=
iforce_upload_condition
(
iforce
,
effect
,
old
);
break
;
case
FF_SPRING
:
case
FF_DAMPER
:
ret
=
iforce_upload_condition
(
iforce
,
effect
,
old
);
break
;
default:
return
-
EINVAL
;
default:
return
-
EINVAL
;
}
if
(
ret
==
0
)
{
...
...
@@ -185,15 +186,7 @@ static int iforce_open(struct input_dev *dev)
{
struct
iforce
*
iforce
=
input_get_drvdata
(
dev
);
switch
(
iforce
->
bus
)
{
#ifdef CONFIG_JOYSTICK_IFORCE_USB
case
IFORCE_USB
:
iforce
->
irq
->
dev
=
iforce
->
usbdev
;
if
(
usb_submit_urb
(
iforce
->
irq
,
GFP_KERNEL
))
return
-
EIO
;
break
;
#endif
}
iforce
->
xport_ops
->
start_io
(
iforce
);
if
(
test_bit
(
EV_FF
,
dev
->
evbit
))
{
/* Enable force feedback */
...
...
@@ -226,27 +219,17 @@ static void iforce_close(struct input_dev *dev)
!
test_bit
(
IFORCE_XMIT_RUNNING
,
iforce
->
xmit_flags
));
}
switch
(
iforce
->
bus
)
{
#ifdef CONFIG_JOYSTICK_IFORCE_USB
case
IFORCE_USB
:
usb_kill_urb
(
iforce
->
irq
);
usb_kill_urb
(
iforce
->
out
);
usb_kill_urb
(
iforce
->
ctrl
);
break
;
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_232
case
IFORCE_232
:
//TODO: Wait for the last packets to be sent
break
;
#endif
}
iforce
->
xport_ops
->
stop_io
(
iforce
);
}
int
iforce_init_device
(
struct
iforce
*
iforce
)
int
iforce_init_device
(
struct
device
*
parent
,
u16
bustype
,
struct
iforce
*
iforce
)
{
struct
input_dev
*
input_dev
;
struct
ff_device
*
ff
;
unsigned
char
c
[]
=
"CEOV"
;
u8
c
[]
=
"CEOV"
;
u8
buf
[
IFORCE_MAX_LENGTH
];
size_t
len
;
int
i
,
error
;
int
ff_effects
=
0
;
...
...
@@ -264,20 +247,8 @@ int iforce_init_device(struct iforce *iforce)
* Input device fields.
*/
switch
(
iforce
->
bus
)
{
#ifdef CONFIG_JOYSTICK_IFORCE_USB
case
IFORCE_USB
:
input_dev
->
id
.
bustype
=
BUS_USB
;
input_dev
->
dev
.
parent
=
&
iforce
->
usbdev
->
dev
;
break
;
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_232
case
IFORCE_232
:
input_dev
->
id
.
bustype
=
BUS_RS232
;
input_dev
->
dev
.
parent
=
&
iforce
->
serio
->
dev
;
break
;
#endif
}
input_dev
->
id
.
bustype
=
bustype
;
input_dev
->
dev
.
parent
=
parent
;
input_set_drvdata
(
input_dev
,
iforce
);
...
...
@@ -302,7 +273,7 @@ int iforce_init_device(struct iforce *iforce)
*/
for
(
i
=
0
;
i
<
20
;
i
++
)
if
(
!
iforce_get_id_packet
(
iforce
,
"O"
))
if
(
!
iforce_get_id_packet
(
iforce
,
'O'
,
buf
,
&
len
))
break
;
if
(
i
==
20
)
{
/* 5 seconds */
...
...
@@ -316,23 +287,23 @@ int iforce_init_device(struct iforce *iforce)
* Get device info.
*/
if
(
!
iforce_get_id_packet
(
iforce
,
"M"
)
)
input_dev
->
id
.
vendor
=
(
iforce
->
edata
[
2
]
<<
8
)
|
iforce
->
edata
[
1
]
;
if
(
!
iforce_get_id_packet
(
iforce
,
'M'
,
buf
,
&
len
)
||
len
<
3
)
input_dev
->
id
.
vendor
=
get_unaligned_le16
(
buf
+
1
)
;
else
dev_warn
(
&
iforce
->
dev
->
dev
,
"Device does not respond to id packet M
\n
"
);
if
(
!
iforce_get_id_packet
(
iforce
,
"P"
)
)
input_dev
->
id
.
product
=
(
iforce
->
edata
[
2
]
<<
8
)
|
iforce
->
edata
[
1
]
;
if
(
!
iforce_get_id_packet
(
iforce
,
'P'
,
buf
,
&
len
)
||
len
<
3
)
input_dev
->
id
.
product
=
get_unaligned_le16
(
buf
+
1
)
;
else
dev_warn
(
&
iforce
->
dev
->
dev
,
"Device does not respond to id packet P
\n
"
);
if
(
!
iforce_get_id_packet
(
iforce
,
"B"
)
)
iforce
->
device_memory
.
end
=
(
iforce
->
edata
[
2
]
<<
8
)
|
iforce
->
edata
[
1
]
;
if
(
!
iforce_get_id_packet
(
iforce
,
'B'
,
buf
,
&
len
)
||
len
<
3
)
iforce
->
device_memory
.
end
=
get_unaligned_le16
(
buf
+
1
)
;
else
dev_warn
(
&
iforce
->
dev
->
dev
,
"Device does not respond to id packet B
\n
"
);
if
(
!
iforce_get_id_packet
(
iforce
,
"N"
)
)
ff_effects
=
iforce
->
edata
[
1
];
if
(
!
iforce_get_id_packet
(
iforce
,
'N'
,
buf
,
&
len
)
||
len
<
2
)
ff_effects
=
buf
[
1
];
else
dev_warn
(
&
iforce
->
dev
->
dev
,
"Device does not respond to id packet N
\n
"
);
...
...
@@ -348,8 +319,9 @@ int iforce_init_device(struct iforce *iforce)
*/
for
(
i
=
0
;
c
[
i
];
i
++
)
if
(
!
iforce_get_id_packet
(
iforce
,
c
+
i
))
iforce_dump_packet
(
iforce
,
"info"
,
iforce
->
ecmd
,
iforce
->
edata
);
if
(
!
iforce_get_id_packet
(
iforce
,
c
[
i
],
buf
,
&
len
))
iforce_dump_packet
(
iforce
,
"info"
,
(
FF_CMD_QUERY
&
0xff00
)
|
len
,
buf
);
/*
* Disable spring, enable force feedback.
...
...
@@ -383,34 +355,29 @@ int iforce_init_device(struct iforce *iforce)
signed
short
t
=
iforce
->
type
->
abs
[
i
];
switch
(
t
)
{
case
ABS_X
:
case
ABS_Y
:
case
ABS_WHEEL
:
input_set_abs_params
(
input_dev
,
t
,
-
1920
,
1920
,
16
,
128
);
set_bit
(
t
,
input_dev
->
ffbit
);
break
;
case
ABS_X
:
case
ABS_Y
:
case
ABS_WHEEL
:
input_set_abs_params
(
input_dev
,
t
,
-
1920
,
1920
,
16
,
128
);
set_bit
(
t
,
input_dev
->
ffbit
);
break
;
case
ABS_THROTTLE
:
case
ABS_GAS
:
case
ABS_BRAKE
:
input_set_abs_params
(
input_dev
,
t
,
0
,
255
,
0
,
0
);
break
;
case
ABS_RUDDER
:
input_set_abs_params
(
input_dev
,
t
,
-
128
,
127
,
0
,
0
);
break
;
case
ABS_THROTTLE
:
case
ABS_GAS
:
case
ABS_BRAKE
:
input_set_abs_params
(
input_dev
,
t
,
0
,
255
,
0
,
0
);
break
;
case
ABS_HAT0X
:
case
ABS_HAT0Y
:
case
ABS_HAT1X
:
case
ABS_HAT1Y
:
case
ABS_RUDDER
:
input_set_abs_params
(
input_dev
,
t
,
-
128
,
127
,
0
,
0
);
break
;
input_set_abs_params
(
input_dev
,
t
,
-
1
,
1
,
0
,
0
);
break
;
case
ABS_HAT0X
:
case
ABS_HAT0Y
:
case
ABS_HAT1X
:
case
ABS_HAT1Y
:
input_set_abs_params
(
input_dev
,
t
,
-
1
,
1
,
0
,
0
);
break
;
}
}
...
...
@@ -443,35 +410,4 @@ int iforce_init_device(struct iforce *iforce)
fail:
input_free_device
(
input_dev
);
return
error
;
}
static
int
__init
iforce_init
(
void
)
{
int
err
=
0
;
#ifdef CONFIG_JOYSTICK_IFORCE_USB
err
=
usb_register
(
&
iforce_usb_driver
);
if
(
err
)
return
err
;
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_232
err
=
serio_register_driver
(
&
iforce_serio_drv
);
#ifdef CONFIG_JOYSTICK_IFORCE_USB
if
(
err
)
usb_deregister
(
&
iforce_usb_driver
);
#endif
#endif
return
err
;
}
static
void
__exit
iforce_exit
(
void
)
{
#ifdef CONFIG_JOYSTICK_IFORCE_USB
usb_deregister
(
&
iforce_usb_driver
);
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_232
serio_unregister_driver
(
&
iforce_serio_drv
);
#endif
}
module_init
(
iforce_init
);
module_exit
(
iforce_exit
);
EXPORT_SYMBOL
(
iforce_init_device
);
drivers/input/joystick/iforce/iforce-packets.c
View file @
90b9b0d5
...
...
@@ -21,6 +21,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <asm/unaligned.h>
#include "iforce.h"
static
struct
{
...
...
@@ -91,27 +92,12 @@ int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data)
/*
* If necessary, start the transmission
*/
switch
(
iforce
->
bus
)
{
if
(
empty
)
iforce
->
xport_ops
->
xmit
(
iforce
);
#ifdef CONFIG_JOYSTICK_IFORCE_232
case
IFORCE_232
:
if
(
empty
)
iforce_serial_xmit
(
iforce
);
break
;
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_USB
case
IFORCE_USB
:
if
(
iforce
->
usbdev
&&
empty
&&
!
test_and_set_bit
(
IFORCE_XMIT_RUNNING
,
iforce
->
xmit_flags
))
{
iforce_usb_xmit
(
iforce
);
}
break
;
#endif
}
return
0
;
}
EXPORT_SYMBOL
(
iforce_send_packet
);
/* Start or stop an effect */
int
iforce_control_playback
(
struct
iforce
*
iforce
,
u16
id
,
unsigned
int
value
)
...
...
@@ -145,157 +131,96 @@ static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
return
-
1
;
}
void
iforce_process_packet
(
struct
iforce
*
iforce
,
u16
cmd
,
unsigned
char
*
data
)
static
void
iforce_report_hats_buttons
(
struct
iforce
*
iforce
,
u8
*
data
)
{
struct
input_dev
*
dev
=
iforce
->
dev
;
int
i
;
static
int
being_used
=
0
;
if
(
being_used
)
dev_warn
(
&
iforce
->
dev
->
dev
,
"re-entrant call to iforce_process %d
\n
"
,
being_used
);
being_used
++
;
#ifdef CONFIG_JOYSTICK_IFORCE_232
if
(
HI
(
iforce
->
expect_packet
)
==
HI
(
cmd
))
{
iforce
->
expect_packet
=
0
;
iforce
->
ecmd
=
cmd
;
memcpy
(
iforce
->
edata
,
data
,
IFORCE_MAX_LENGTH
);
}
#endif
wake_up
(
&
iforce
->
wait
);
input_report_abs
(
dev
,
ABS_HAT0X
,
iforce_hat_to_axis
[
data
[
6
]
>>
4
].
x
);
input_report_abs
(
dev
,
ABS_HAT0Y
,
iforce_hat_to_axis
[
data
[
6
]
>>
4
].
y
);
if
(
!
iforce
->
type
)
{
being_used
--
;
return
;
}
switch
(
HI
(
cmd
))
{
case
0x01
:
/* joystick position data */
case
0x03
:
/* wheel position data */
if
(
HI
(
cmd
)
==
1
)
{
input_report_abs
(
dev
,
ABS_X
,
(
__s16
)
(((
__s16
)
data
[
1
]
<<
8
)
|
data
[
0
]));
input_report_abs
(
dev
,
ABS_Y
,
(
__s16
)
(((
__s16
)
data
[
3
]
<<
8
)
|
data
[
2
]));
input_report_abs
(
dev
,
ABS_THROTTLE
,
255
-
data
[
4
]);
if
(
LO
(
cmd
)
>=
8
&&
test_bit
(
ABS_RUDDER
,
dev
->
absbit
))
input_report_abs
(
dev
,
ABS_RUDDER
,
(
__s8
)
data
[
7
]);
}
else
{
input_report_abs
(
dev
,
ABS_WHEEL
,
(
__s16
)
(((
__s16
)
data
[
1
]
<<
8
)
|
data
[
0
]));
input_report_abs
(
dev
,
ABS_GAS
,
255
-
data
[
2
]);
input_report_abs
(
dev
,
ABS_BRAKE
,
255
-
data
[
3
]);
}
for
(
i
=
0
;
iforce
->
type
->
btn
[
i
]
>=
0
;
i
++
)
input_report_key
(
dev
,
iforce
->
type
->
btn
[
i
],
data
[(
i
>>
3
)
+
5
]
&
(
1
<<
(
i
&
7
)));
input_report_abs
(
dev
,
ABS_HAT0X
,
iforce_hat_to_axis
[
data
[
6
]
>>
4
].
x
);
input_report_abs
(
dev
,
ABS_HAT0Y
,
iforce_hat_to_axis
[
data
[
6
]
>>
4
].
y
);
for
(
i
=
0
;
iforce
->
type
->
btn
[
i
]
>=
0
;
i
++
)
input_report_key
(
dev
,
iforce
->
type
->
btn
[
i
],
data
[(
i
>>
3
)
+
5
]
&
(
1
<<
(
i
&
7
)));
/* If there are untouched bits left, interpret them as the second hat */
if
(
i
<=
8
)
{
int
btns
=
data
[
6
];
if
(
test_bit
(
ABS_HAT1X
,
dev
->
absbit
))
{
if
(
btns
&
8
)
input_report_abs
(
dev
,
ABS_HAT1X
,
-
1
);
else
if
(
btns
&
2
)
input_report_abs
(
dev
,
ABS_HAT1X
,
1
);
else
input_report_abs
(
dev
,
ABS_HAT1X
,
0
);
}
if
(
test_bit
(
ABS_HAT1Y
,
dev
->
absbit
))
{
if
(
btns
&
1
)
input_report_abs
(
dev
,
ABS_HAT1Y
,
-
1
);
else
if
(
btns
&
4
)
input_report_abs
(
dev
,
ABS_HAT1Y
,
1
);
else
input_report_abs
(
dev
,
ABS_HAT1Y
,
0
);
}
}
/* If there are untouched bits left, interpret them as the second hat */
if
(
i
<=
8
)
{
u8
btns
=
data
[
6
];
input_sync
(
dev
);
break
;
case
0x02
:
/* status report */
input_report_key
(
dev
,
BTN_DEAD
,
data
[
0
]
&
0x02
);
input_sync
(
dev
);
if
(
test_bit
(
ABS_HAT1X
,
dev
->
absbit
))
{
if
(
btns
&
BIT
(
3
))
input_report_abs
(
dev
,
ABS_HAT1X
,
-
1
);
else
if
(
btns
&
BIT
(
1
))
input_report_abs
(
dev
,
ABS_HAT1X
,
1
);
else
input_report_abs
(
dev
,
ABS_HAT1X
,
0
);
}
/* Check if an effect was just started or stopped */
i
=
data
[
1
]
&
0x7f
;
if
(
data
[
1
]
&
0x80
)
{
if
(
!
test_and_set_bit
(
FF_CORE_IS_PLAYED
,
iforce
->
core_effects
[
i
].
flags
))
{
/* Report play event */
input_report_ff_status
(
dev
,
i
,
FF_STATUS_PLAYING
);
}
}
else
if
(
test_and_clear_bit
(
FF_CORE_IS_PLAYED
,
iforce
->
core_effects
[
i
].
flags
))
{
/* Report stop event */
input_report_ff_status
(
dev
,
i
,
FF_STATUS_STOPPED
);
}
if
(
LO
(
cmd
)
>
3
)
{
int
j
;
for
(
j
=
3
;
j
<
LO
(
cmd
);
j
+=
2
)
mark_core_as_ready
(
iforce
,
data
[
j
]
|
(
data
[
j
+
1
]
<<
8
));
}
break
;
if
(
test_bit
(
ABS_HAT1Y
,
dev
->
absbit
))
{
if
(
btns
&
BIT
(
0
))
input_report_abs
(
dev
,
ABS_HAT1Y
,
-
1
);
else
if
(
btns
&
BIT
(
2
))
input_report_abs
(
dev
,
ABS_HAT1Y
,
1
);
else
input_report_abs
(
dev
,
ABS_HAT1Y
,
0
);
}
}
being_used
--
;
}
int
iforce_get_id_packet
(
struct
iforce
*
iforce
,
char
*
packet
)
void
iforce_process_packet
(
struct
iforce
*
iforce
,
u8
packet_id
,
u8
*
data
,
size_t
len
)
{
switch
(
iforce
->
bus
)
{
struct
input_dev
*
dev
=
iforce
->
dev
;
int
i
,
j
;
case
IFORCE_USB
:
{
#ifdef CONFIG_JOYSTICK_IFORCE_USB
int
status
;
switch
(
packet_id
)
{
iforce
->
cr
.
bRequest
=
packet
[
0
];
iforce
->
ctrl
->
dev
=
iforce
->
usbdev
;
case
0x01
:
/* joystick position data */
input_report_abs
(
dev
,
ABS_X
,
(
__s16
)
get_unaligned_le16
(
data
));
input_report_abs
(
dev
,
ABS_Y
,
(
__s16
)
get_unaligned_le16
(
data
+
2
));
input_report_abs
(
dev
,
ABS_THROTTLE
,
255
-
data
[
4
]);
status
=
usb_submit_urb
(
iforce
->
ctrl
,
GFP_KERNEL
);
if
(
status
)
{
dev_err
(
&
iforce
->
intf
->
dev
,
"usb_submit_urb failed %d
\n
"
,
status
);
return
-
1
;
}
if
(
len
>=
8
&&
test_bit
(
ABS_RUDDER
,
dev
->
absbit
))
input_report_abs
(
dev
,
ABS_RUDDER
,
(
__s8
)
data
[
7
]);
wait_event_interruptible_timeout
(
iforce
->
wait
,
iforce
->
ctrl
->
status
!=
-
EINPROGRESS
,
HZ
);
iforce_report_hats_buttons
(
iforce
,
data
);
if
(
iforce
->
ctrl
->
status
)
{
dev_dbg
(
&
iforce
->
intf
->
dev
,
"iforce->ctrl->status = %d
\n
"
,
iforce
->
ctrl
->
status
);
usb_unlink_urb
(
iforce
->
ctrl
);
return
-
1
;
}
#else
printk
(
KERN_DEBUG
"iforce_get_id_packet: iforce->bus = USB!
\n
"
);
#endif
}
input_sync
(
dev
);
break
;
case
IFORCE_232
:
case
0x03
:
/* wheel position data */
input_report_abs
(
dev
,
ABS_WHEEL
,
(
__s16
)
get_unaligned_le16
(
data
));
input_report_abs
(
dev
,
ABS_GAS
,
255
-
data
[
2
]);
input_report_abs
(
dev
,
ABS_BRAKE
,
255
-
data
[
3
]);
#ifdef CONFIG_JOYSTICK_IFORCE_232
iforce
->
expect_packet
=
FF_CMD_QUERY
;
iforce_send_packet
(
iforce
,
FF_CMD_QUERY
,
packet
);
iforce_report_hats_buttons
(
iforce
,
data
);
wait_event_interruptible_timeout
(
iforce
->
wait
,
!
iforce
->
expect_packet
,
HZ
);
input_sync
(
dev
);
break
;
case
0x02
:
/* status report */
input_report_key
(
dev
,
BTN_DEAD
,
data
[
0
]
&
0x02
);
input_sync
(
dev
);
if
(
iforce
->
expect_packet
)
{
iforce
->
expect_packet
=
0
;
return
-
1
;
/* Check if an effect was just started or stopped */
i
=
data
[
1
]
&
0x7f
;
if
(
data
[
1
]
&
0x80
)
{
if
(
!
test_and_set_bit
(
FF_CORE_IS_PLAYED
,
iforce
->
core_effects
[
i
].
flags
))
{
/* Report play event */
input_report_ff_status
(
dev
,
i
,
FF_STATUS_PLAYING
);
}
}
else
if
(
test_and_clear_bit
(
FF_CORE_IS_PLAYED
,
iforce
->
core_effects
[
i
].
flags
))
{
/* Report stop event */
input_report_ff_status
(
dev
,
i
,
FF_STATUS_STOPPED
);
}
#else
dev_err
(
&
iforce
->
dev
->
dev
,
"iforce_get_id_packet: iforce->bus = SERIO!
\n
"
);
#endif
break
;
default:
dev_err
(
&
iforce
->
dev
->
dev
,
"iforce_get_id_packet: iforce->bus = %d
\n
"
,
iforce
->
bus
);
for
(
j
=
3
;
j
<
len
;
j
+=
2
)
mark_core_as_ready
(
iforce
,
get_unaligned_le16
(
data
+
j
));
break
;
}
return
-
(
iforce
->
edata
[
0
]
!=
packet
[
0
]);
}
EXPORT_SYMBOL
(
iforce_process_packet
);
drivers/input/joystick/iforce/iforce-serio.c
View file @
90b9b0d5
...
...
@@ -21,10 +21,26 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/serio.h>
#include "iforce.h"
void
iforce_serial_xmit
(
struct
iforce
*
iforce
)
struct
iforce_serio
{
struct
iforce
iforce
;
struct
serio
*
serio
;
int
idx
,
pkt
,
len
,
id
;
u8
csum
;
u8
expect_packet
;
u8
cmd_response
[
IFORCE_MAX_LENGTH
];
u8
cmd_response_len
;
u8
data_in
[
IFORCE_MAX_LENGTH
];
};
static
void
iforce_serio_xmit
(
struct
iforce
*
iforce
)
{
struct
iforce_serio
*
iforce_serio
=
container_of
(
iforce
,
struct
iforce_serio
,
iforce
);
unsigned
char
cs
;
int
i
;
unsigned
long
flags
;
...
...
@@ -45,19 +61,20 @@ void iforce_serial_xmit(struct iforce *iforce)
cs
=
0x2b
;
serio_write
(
iforce
->
serio
,
0x2b
);
serio_write
(
iforce
_serio
->
serio
,
0x2b
);
serio_write
(
iforce
->
serio
,
iforce
->
xmit
.
buf
[
iforce
->
xmit
.
tail
]);
serio_write
(
iforce
_serio
->
serio
,
iforce
->
xmit
.
buf
[
iforce
->
xmit
.
tail
]);
cs
^=
iforce
->
xmit
.
buf
[
iforce
->
xmit
.
tail
];
XMIT_INC
(
iforce
->
xmit
.
tail
,
1
);
for
(
i
=
iforce
->
xmit
.
buf
[
iforce
->
xmit
.
tail
];
i
>=
0
;
--
i
)
{
serio_write
(
iforce
->
serio
,
iforce
->
xmit
.
buf
[
iforce
->
xmit
.
tail
]);
serio_write
(
iforce_serio
->
serio
,
iforce
->
xmit
.
buf
[
iforce
->
xmit
.
tail
]);
cs
^=
iforce
->
xmit
.
buf
[
iforce
->
xmit
.
tail
];
XMIT_INC
(
iforce
->
xmit
.
tail
,
1
);
}
serio_write
(
iforce
->
serio
,
cs
);
serio_write
(
iforce
_serio
->
serio
,
cs
);
if
(
test_and_clear_bit
(
IFORCE_XMIT_AGAIN
,
iforce
->
xmit_flags
))
goto
again
;
...
...
@@ -67,54 +84,118 @@ void iforce_serial_xmit(struct iforce *iforce)
spin_unlock_irqrestore
(
&
iforce
->
xmit_lock
,
flags
);
}
static
int
iforce_serio_get_id
(
struct
iforce
*
iforce
,
u8
id
,
u8
*
response_data
,
size_t
*
response_len
)
{
struct
iforce_serio
*
iforce_serio
=
container_of
(
iforce
,
struct
iforce_serio
,
iforce
);
iforce_serio
->
expect_packet
=
HI
(
FF_CMD_QUERY
);
iforce_serio
->
cmd_response_len
=
0
;
iforce_send_packet
(
iforce
,
FF_CMD_QUERY
,
&
id
);
wait_event_interruptible_timeout
(
iforce
->
wait
,
!
iforce_serio
->
expect_packet
,
HZ
);
if
(
iforce_serio
->
expect_packet
)
{
iforce_serio
->
expect_packet
=
0
;
return
-
ETIMEDOUT
;
}
if
(
iforce_serio
->
cmd_response
[
0
]
!=
id
)
return
-
EIO
;
memcpy
(
response_data
,
iforce_serio
->
cmd_response
,
iforce_serio
->
cmd_response_len
);
*
response_len
=
iforce_serio
->
cmd_response_len
;
return
0
;
}
static
int
iforce_serio_start_io
(
struct
iforce
*
iforce
)
{
/* No special handling required */
return
0
;
}
static
void
iforce_serio_stop_io
(
struct
iforce
*
iforce
)
{
//TODO: Wait for the last packets to be sent
}
static
const
struct
iforce_xport_ops
iforce_serio_xport_ops
=
{
.
xmit
=
iforce_serio_xmit
,
.
get_id
=
iforce_serio_get_id
,
.
start_io
=
iforce_serio_start_io
,
.
stop_io
=
iforce_serio_stop_io
,
};
static
void
iforce_serio_write_wakeup
(
struct
serio
*
serio
)
{
struct
iforce
*
iforce
=
serio_get_drvdata
(
serio
);
iforce_seri
al
_xmit
(
iforce
);
iforce_seri
o
_xmit
(
iforce
);
}
static
irqreturn_t
iforce_serio_irq
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
flags
)
unsigned
char
data
,
unsigned
int
flags
)
{
struct
iforce
*
iforce
=
serio_get_drvdata
(
serio
);
struct
iforce_serio
*
iforce_serio
=
serio_get_drvdata
(
serio
);
struct
iforce
*
iforce
=
&
iforce_serio
->
iforce
;
if
(
!
iforce
->
pkt
)
{
if
(
!
iforce
_serio
->
pkt
)
{
if
(
data
==
0x2b
)
iforce
->
pkt
=
1
;
iforce
_serio
->
pkt
=
1
;
goto
out
;
}
if
(
!
iforce
->
id
)
{
if
(
!
iforce
_serio
->
id
)
{
if
(
data
>
3
&&
data
!=
0xff
)
iforce
->
pkt
=
0
;
iforce
_serio
->
pkt
=
0
;
else
iforce
->
id
=
data
;
iforce
_serio
->
id
=
data
;
goto
out
;
}
if
(
!
iforce
->
len
)
{
if
(
!
iforce
_serio
->
len
)
{
if
(
data
>
IFORCE_MAX_LENGTH
)
{
iforce
->
pkt
=
0
;
iforce
->
id
=
0
;
iforce
_serio
->
pkt
=
0
;
iforce
_serio
->
id
=
0
;
}
else
{
iforce
->
len
=
data
;
iforce
_serio
->
len
=
data
;
}
goto
out
;
}
if
(
iforce
->
idx
<
iforce
->
len
)
{
iforce
->
csum
+=
iforce
->
data
[
iforce
->
idx
++
]
=
data
;
if
(
iforce_serio
->
idx
<
iforce_serio
->
len
)
{
iforce_serio
->
data_in
[
iforce_serio
->
idx
++
]
=
data
;
iforce_serio
->
csum
+=
data
;
goto
out
;
}
if
(
iforce
->
idx
==
iforce
->
len
)
{
iforce_process_packet
(
iforce
,
(
iforce
->
id
<<
8
)
|
iforce
->
idx
,
iforce
->
data
);
iforce
->
pkt
=
0
;
iforce
->
id
=
0
;
iforce
->
len
=
0
;
iforce
->
idx
=
0
;
iforce
->
csum
=
0
;
if
(
iforce_serio
->
idx
==
iforce_serio
->
len
)
{
/* Handle command completion */
if
(
iforce_serio
->
expect_packet
==
iforce_serio
->
id
)
{
iforce_serio
->
expect_packet
=
0
;
memcpy
(
iforce_serio
->
cmd_response
,
iforce_serio
->
data_in
,
IFORCE_MAX_LENGTH
);
iforce_serio
->
cmd_response_len
=
iforce_serio
->
len
;
/* Signal that command is done */
wake_up
(
&
iforce
->
wait
);
}
else
if
(
likely
(
iforce
->
type
))
{
iforce_process_packet
(
iforce
,
iforce_serio
->
id
,
iforce_serio
->
data_in
,
iforce_serio
->
len
);
}
iforce_serio
->
pkt
=
0
;
iforce_serio
->
id
=
0
;
iforce_serio
->
len
=
0
;
iforce_serio
->
idx
=
0
;
iforce_serio
->
csum
=
0
;
}
out:
return
IRQ_HANDLED
;
...
...
@@ -122,23 +203,23 @@ static irqreturn_t iforce_serio_irq(struct serio *serio,
static
int
iforce_serio_connect
(
struct
serio
*
serio
,
struct
serio_driver
*
drv
)
{
struct
iforce
*
iforce
;
struct
iforce
_serio
*
iforce_serio
;
int
err
;
iforce
=
kzalloc
(
sizeof
(
struct
iforce
),
GFP_KERNEL
);
if
(
!
iforce
)
iforce
_serio
=
kzalloc
(
sizeof
(
*
iforce_serio
),
GFP_KERNEL
);
if
(
!
iforce
_serio
)
return
-
ENOMEM
;
iforce
->
bus
=
IFORCE_232
;
iforce
->
serio
=
serio
;
iforce_serio
->
iforce
.
xport_ops
=
&
iforce_serio_xport_ops
;
serio_set_drvdata
(
serio
,
iforce
);
iforce_serio
->
serio
=
serio
;
serio_set_drvdata
(
serio
,
iforce_serio
);
err
=
serio_open
(
serio
,
drv
);
if
(
err
)
goto
fail1
;
err
=
iforce_init_device
(
iforce
);
err
=
iforce_init_device
(
&
serio
->
dev
,
BUS_RS232
,
&
iforce_serio
->
iforce
);
if
(
err
)
goto
fail2
;
...
...
@@ -146,18 +227,18 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
fail2:
serio_close
(
serio
);
fail1:
serio_set_drvdata
(
serio
,
NULL
);
kfree
(
iforce
);
kfree
(
iforce
_serio
);
return
err
;
}
static
void
iforce_serio_disconnect
(
struct
serio
*
serio
)
{
struct
iforce
*
iforce
=
serio_get_drvdata
(
serio
);
struct
iforce
_serio
*
iforce_serio
=
serio_get_drvdata
(
serio
);
input_unregister_device
(
iforce
->
dev
);
input_unregister_device
(
iforce
_serio
->
iforce
.
dev
);
serio_close
(
serio
);
serio_set_drvdata
(
serio
,
NULL
);
kfree
(
iforce
);
kfree
(
iforce
_serio
);
}
static
const
struct
serio_device_id
iforce_serio_ids
[]
=
{
...
...
@@ -183,3 +264,9 @@ struct serio_driver iforce_serio_drv = {
.
connect
=
iforce_serio_connect
,
.
disconnect
=
iforce_serio_disconnect
,
};
module_serio_driver
(
iforce_serio_drv
);
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>"
);
MODULE_DESCRIPTION
(
"RS232 I-Force joysticks and wheels driver"
);
MODULE_LICENSE
(
"GPL"
);
drivers/input/joystick/iforce/iforce-usb.c
View file @
90b9b0d5
...
...
@@ -21,10 +21,24 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/usb.h>
#include "iforce.h"
void
iforce_usb_xmit
(
struct
iforce
*
iforce
)
struct
iforce_usb
{
struct
iforce
iforce
;
struct
usb_device
*
usbdev
;
struct
usb_interface
*
intf
;
struct
urb
*
irq
,
*
out
;
u8
data_in
[
IFORCE_MAX_LENGTH
]
____cacheline_aligned
;
u8
data_out
[
IFORCE_MAX_LENGTH
]
____cacheline_aligned
;
};
static
void
__iforce_usb_xmit
(
struct
iforce
*
iforce
)
{
struct
iforce_usb
*
iforce_usb
=
container_of
(
iforce
,
struct
iforce_usb
,
iforce
);
int
n
,
c
;
unsigned
long
flags
;
...
...
@@ -36,31 +50,32 @@ void iforce_usb_xmit(struct iforce *iforce)
return
;
}
((
char
*
)
iforce
->
out
->
transfer_buffer
)[
0
]
=
iforce
->
xmit
.
buf
[
iforce
->
xmit
.
tail
];
((
char
*
)
iforce
_usb
->
out
->
transfer_buffer
)[
0
]
=
iforce
->
xmit
.
buf
[
iforce
->
xmit
.
tail
];
XMIT_INC
(
iforce
->
xmit
.
tail
,
1
);
n
=
iforce
->
xmit
.
buf
[
iforce
->
xmit
.
tail
];
XMIT_INC
(
iforce
->
xmit
.
tail
,
1
);
iforce
->
out
->
transfer_buffer_length
=
n
+
1
;
iforce
->
out
->
dev
=
iforce
->
usbdev
;
iforce
_usb
->
out
->
transfer_buffer_length
=
n
+
1
;
iforce
_usb
->
out
->
dev
=
iforce_usb
->
usbdev
;
/* Copy rest of data then */
c
=
CIRC_CNT_TO_END
(
iforce
->
xmit
.
head
,
iforce
->
xmit
.
tail
,
XMIT_SIZE
);
if
(
n
<
c
)
c
=
n
;
memcpy
(
iforce
->
out
->
transfer_buffer
+
1
,
memcpy
(
iforce
_usb
->
out
->
transfer_buffer
+
1
,
&
iforce
->
xmit
.
buf
[
iforce
->
xmit
.
tail
],
c
);
if
(
n
!=
c
)
{
memcpy
(
iforce
->
out
->
transfer_buffer
+
1
+
c
,
memcpy
(
iforce
_usb
->
out
->
transfer_buffer
+
1
+
c
,
&
iforce
->
xmit
.
buf
[
0
],
n
-
c
);
}
XMIT_INC
(
iforce
->
xmit
.
tail
,
n
);
if
(
(
n
=
usb_submit_urb
(
iforce
->
out
,
GFP_ATOMIC
))
)
{
if
(
(
n
=
usb_submit_urb
(
iforce
_usb
->
out
,
GFP_ATOMIC
))
)
{
clear_bit
(
IFORCE_XMIT_RUNNING
,
iforce
->
xmit_flags
);
dev_warn
(
&
iforce
->
intf
->
dev
,
"usb_submit_urb failed %d
\n
"
,
n
);
dev_warn
(
&
iforce_usb
->
intf
->
dev
,
"usb_submit_urb failed %d
\n
"
,
n
);
}
/* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
...
...
@@ -69,10 +84,77 @@ void iforce_usb_xmit(struct iforce *iforce)
spin_unlock_irqrestore
(
&
iforce
->
xmit_lock
,
flags
);
}
static
void
iforce_usb_xmit
(
struct
iforce
*
iforce
)
{
if
(
!
test_and_set_bit
(
IFORCE_XMIT_RUNNING
,
iforce
->
xmit_flags
))
__iforce_usb_xmit
(
iforce
);
}
static
int
iforce_usb_get_id
(
struct
iforce
*
iforce
,
u8
id
,
u8
*
response_data
,
size_t
*
response_len
)
{
struct
iforce_usb
*
iforce_usb
=
container_of
(
iforce
,
struct
iforce_usb
,
iforce
);
u8
*
buf
;
int
status
;
buf
=
kmalloc
(
IFORCE_MAX_LENGTH
,
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
status
=
usb_control_msg
(
iforce_usb
->
usbdev
,
usb_rcvctrlpipe
(
iforce_usb
->
usbdev
,
0
),
id
,
USB_TYPE_VENDOR
|
USB_DIR_IN
|
USB_RECIP_INTERFACE
,
0
,
0
,
buf
,
IFORCE_MAX_LENGTH
,
HZ
);
if
(
status
<
0
)
{
dev_err
(
&
iforce_usb
->
intf
->
dev
,
"usb_submit_urb failed: %d
\n
"
,
status
);
}
else
if
(
buf
[
0
]
!=
id
)
{
status
=
-
EIO
;
}
else
{
memcpy
(
response_data
,
buf
,
status
);
*
response_len
=
status
;
status
=
0
;
}
kfree
(
buf
);
return
status
;
}
static
int
iforce_usb_start_io
(
struct
iforce
*
iforce
)
{
struct
iforce_usb
*
iforce_usb
=
container_of
(
iforce
,
struct
iforce_usb
,
iforce
);
if
(
usb_submit_urb
(
iforce_usb
->
irq
,
GFP_KERNEL
))
return
-
EIO
;
return
0
;
}
static
void
iforce_usb_stop_io
(
struct
iforce
*
iforce
)
{
struct
iforce_usb
*
iforce_usb
=
container_of
(
iforce
,
struct
iforce_usb
,
iforce
);
usb_kill_urb
(
iforce_usb
->
irq
);
usb_kill_urb
(
iforce_usb
->
out
);
}
static
const
struct
iforce_xport_ops
iforce_usb_xport_ops
=
{
.
xmit
=
iforce_usb_xmit
,
.
get_id
=
iforce_usb_get_id
,
.
start_io
=
iforce_usb_start_io
,
.
stop_io
=
iforce_usb_stop_io
,
};
static
void
iforce_usb_irq
(
struct
urb
*
urb
)
{
struct
iforce
*
iforce
=
urb
->
context
;
struct
device
*
dev
=
&
iforce
->
intf
->
dev
;
struct
iforce_usb
*
iforce_usb
=
urb
->
context
;
struct
iforce
*
iforce
=
&
iforce_usb
->
iforce
;
struct
device
*
dev
=
&
iforce_usb
->
intf
->
dev
;
int
status
;
switch
(
urb
->
status
)
{
...
...
@@ -92,11 +174,11 @@ static void iforce_usb_irq(struct urb *urb)
goto
exit
;
}
iforce_process_packet
(
iforce
,
(
iforce
->
data
[
0
]
<<
8
)
|
(
urb
->
actual_length
-
1
),
iforce
->
data
+
1
);
iforce_process_packet
(
iforce
,
iforce_usb
->
data_in
[
0
],
iforce_usb
->
data_in
+
1
,
urb
->
actual_length
-
1
);
exit:
status
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
status
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
if
(
status
)
dev_err
(
dev
,
"%s - usb_submit_urb failed with result %d
\n
"
,
__func__
,
status
);
...
...
@@ -104,35 +186,28 @@ static void iforce_usb_irq(struct urb *urb)
static
void
iforce_usb_out
(
struct
urb
*
urb
)
{
struct
iforce
*
iforce
=
urb
->
context
;
struct
iforce_usb
*
iforce_usb
=
urb
->
context
;
struct
iforce
*
iforce
=
&
iforce_usb
->
iforce
;
if
(
urb
->
status
)
{
clear_bit
(
IFORCE_XMIT_RUNNING
,
iforce
->
xmit_flags
);
dev_dbg
(
&
iforce
->
intf
->
dev
,
"urb->status %d, exiting
\n
"
,
dev_dbg
(
&
iforce
_usb
->
intf
->
dev
,
"urb->status %d, exiting
\n
"
,
urb
->
status
);
return
;
}
iforce_usb_xmit
(
iforce
);
__
iforce_usb_xmit
(
iforce
);
wake_up
(
&
iforce
->
wait
);
}
static
void
iforce_usb_ctrl
(
struct
urb
*
urb
)
{
struct
iforce
*
iforce
=
urb
->
context
;
if
(
urb
->
status
)
return
;
iforce
->
ecmd
=
0xff00
|
urb
->
actual_length
;
wake_up
(
&
iforce
->
wait
);
}
static
int
iforce_usb_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
struct
usb_device
*
dev
=
interface_to_usbdev
(
intf
);
struct
usb_host_interface
*
interface
;
struct
usb_endpoint_descriptor
*
epirq
,
*
epout
;
struct
iforce
*
iforce
;
struct
iforce
_usb
*
iforce_usb
;
int
err
=
-
ENOMEM
;
interface
=
intf
->
cur_altsetting
;
...
...
@@ -143,48 +218,45 @@ static int iforce_usb_probe(struct usb_interface *intf,
epirq
=
&
interface
->
endpoint
[
0
].
desc
;
epout
=
&
interface
->
endpoint
[
1
].
desc
;
if
(
!
(
iforce
=
kzalloc
(
sizeof
(
struct
iforce
)
+
32
,
GFP_KERNEL
)))
goto
fail
;
if
(
!
(
iforce
->
irq
=
usb_alloc_urb
(
0
,
GFP_KERNEL
)))
iforce_usb
=
kzalloc
(
sizeof
(
*
iforce_usb
),
GFP_KERNEL
);
if
(
!
iforce_usb
)
goto
fail
;
if
(
!
(
iforce
->
out
=
usb_alloc_urb
(
0
,
GFP_KERNEL
)))
iforce_usb
->
irq
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
iforce_usb
->
irq
)
goto
fail
;
if
(
!
(
iforce
->
ctrl
=
usb_alloc_urb
(
0
,
GFP_KERNEL
)))
iforce_usb
->
out
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
iforce_usb
->
out
)
goto
fail
;
iforce
->
bus
=
IFORCE_USB
;
iforce
->
usbdev
=
dev
;
iforce
->
intf
=
intf
;
iforce
->
cr
.
bRequestType
=
USB_TYPE_VENDOR
|
USB_DIR_IN
|
USB_RECIP_INTERFACE
;
iforce
->
cr
.
wIndex
=
0
;
iforce
->
cr
.
wLength
=
cpu_to_le16
(
16
);
iforce_usb
->
iforce
.
xport_ops
=
&
iforce_usb_xport_ops
;
usb_fill_int_urb
(
iforce
->
irq
,
dev
,
usb_rcvintpipe
(
dev
,
epirq
->
bEndpointAddress
),
iforce
->
data
,
16
,
iforce_usb_irq
,
iforce
,
epirq
->
bInterval
)
;
iforce_usb
->
usbdev
=
dev
;
iforce_usb
->
intf
=
intf
;
usb_fill_int_urb
(
iforce
->
out
,
dev
,
usb_sndintpipe
(
dev
,
epout
->
bEndpointAddress
),
iforce
+
1
,
32
,
iforce_usb_out
,
iforce
,
epout
->
bInterval
);
usb_fill_int_urb
(
iforce_usb
->
irq
,
dev
,
usb_rcvintpipe
(
dev
,
epirq
->
bEndpointAddress
),
iforce_usb
->
data_in
,
sizeof
(
iforce_usb
->
data_in
),
iforce_usb_irq
,
iforce_usb
,
epirq
->
bInterval
);
usb_fill_control_urb
(
iforce
->
ctrl
,
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
(
void
*
)
&
iforce
->
cr
,
iforce
->
edata
,
16
,
iforce_usb_ctrl
,
iforce
);
usb_fill_int_urb
(
iforce_usb
->
out
,
dev
,
usb_sndintpipe
(
dev
,
epout
->
bEndpointAddress
),
iforce_usb
->
data_out
,
sizeof
(
iforce_usb
->
data_out
),
iforce_usb_out
,
iforce_usb
,
epout
->
bInterval
);
err
=
iforce_init_device
(
iforce
);
err
=
iforce_init_device
(
&
intf
->
dev
,
BUS_USB
,
&
iforce_usb
->
iforce
);
if
(
err
)
goto
fail
;
usb_set_intfdata
(
intf
,
iforce
);
usb_set_intfdata
(
intf
,
iforce
_usb
);
return
0
;
fail:
if
(
iforce
)
{
usb_free_urb
(
iforce
->
irq
);
usb_free_urb
(
iforce
->
out
);
usb_free_urb
(
iforce
->
ctrl
);
kfree
(
iforce
);
if
(
iforce_usb
)
{
usb_free_urb
(
iforce_usb
->
irq
);
usb_free_urb
(
iforce_usb
->
out
);
kfree
(
iforce_usb
);
}
return
err
;
...
...
@@ -192,17 +264,16 @@ static int iforce_usb_probe(struct usb_interface *intf,
static
void
iforce_usb_disconnect
(
struct
usb_interface
*
intf
)
{
struct
iforce
*
iforce
=
usb_get_intfdata
(
intf
);
struct
iforce
_usb
*
iforce_usb
=
usb_get_intfdata
(
intf
);
usb_set_intfdata
(
intf
,
NULL
);
input_unregister_device
(
iforce
->
dev
);
input_unregister_device
(
iforce
_usb
->
iforce
.
dev
);
usb_free_urb
(
iforce
->
irq
);
usb_free_urb
(
iforce
->
out
);
usb_free_urb
(
iforce
->
ctrl
);
usb_free_urb
(
iforce_usb
->
irq
);
usb_free_urb
(
iforce_usb
->
out
);
kfree
(
iforce
);
kfree
(
iforce
_usb
);
}
static
const
struct
usb_device_id
iforce_usb_ids
[]
=
{
...
...
@@ -214,6 +285,7 @@ static const struct usb_device_id iforce_usb_ids[] = {
{
USB_DEVICE
(
0x05ef
,
0x8888
)
},
/* AVB Top Shot FFB Racing Wheel */
{
USB_DEVICE
(
0x061c
,
0xc0a4
)
},
/* ACT LABS Force RS */
{
USB_DEVICE
(
0x061c
,
0xc084
)
},
/* ACT LABS Force RS */
{
USB_DEVICE
(
0x06a3
,
0xff04
)
},
/* Saitek R440 Force Wheel */
{
USB_DEVICE
(
0x06f8
,
0x0001
)
},
/* Guillemot Race Leader Force Feedback */
{
USB_DEVICE
(
0x06f8
,
0x0003
)
},
/* Guillemot Jet Leader Force Feedback */
{
USB_DEVICE
(
0x06f8
,
0x0004
)
},
/* Guillemot Force Feedback Racing Wheel */
...
...
@@ -229,3 +301,9 @@ struct usb_driver iforce_usb_driver = {
.
disconnect
=
iforce_usb_disconnect
,
.
id_table
=
iforce_usb_ids
,
};
module_usb_driver
(
iforce_usb_driver
);
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>"
);
MODULE_DESCRIPTION
(
"USB I-Force joysticks and wheels driver"
);
MODULE_LICENSE
(
"GPL"
);
drivers/input/joystick/iforce/iforce.h
View file @
90b9b0d5
...
...
@@ -26,8 +26,6 @@
#include <linux/input.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/serio.h>
#include <linux/circ_buf.h>
#include <linux/mutex.h>
...
...
@@ -40,10 +38,6 @@
#define IFORCE_MAX_LENGTH 16
/* iforce::bus */
#define IFORCE_232 1
#define IFORCE_USB 2
#define IFORCE_EFFECTS_MAX 32
/* Each force feedback effect is made of one core effect, which can be
...
...
@@ -93,27 +87,21 @@ struct iforce_device {
signed
short
*
ff
;
};
struct
iforce
;
struct
iforce_xport_ops
{
void
(
*
xmit
)(
struct
iforce
*
iforce
);
int
(
*
get_id
)(
struct
iforce
*
iforce
,
u8
id
,
u8
*
response_data
,
size_t
*
response_len
);
int
(
*
start_io
)(
struct
iforce
*
iforce
);
void
(
*
stop_io
)(
struct
iforce
*
iforce
);
};
struct
iforce
{
struct
input_dev
*
dev
;
/* Input device interface */
struct
iforce_device
*
type
;
int
bus
;
unsigned
char
data
[
IFORCE_MAX_LENGTH
];
unsigned
char
edata
[
IFORCE_MAX_LENGTH
];
u16
ecmd
;
u16
expect_packet
;
#ifdef CONFIG_JOYSTICK_IFORCE_232
struct
serio
*
serio
;
/* RS232 transfer */
int
idx
,
pkt
,
len
,
id
;
unsigned
char
csum
;
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_USB
struct
usb_device
*
usbdev
;
/* USB transfer */
struct
usb_interface
*
intf
;
struct
urb
*
irq
,
*
out
,
*
ctrl
;
struct
usb_ctrlrequest
cr
;
#endif
const
struct
iforce_xport_ops
*
xport_ops
;
spinlock_t
xmit_lock
;
/* Buffer used for asynchronous sending of bytes to the device */
struct
circ_buf
xmit
;
...
...
@@ -139,23 +127,24 @@ struct iforce {
/* Encode a time value */
#define TIME_SCALE(a) (a)
static
inline
int
iforce_get_id_packet
(
struct
iforce
*
iforce
,
u8
id
,
u8
*
response_data
,
size_t
*
response_len
)
{
return
iforce
->
xport_ops
->
get_id
(
iforce
,
id
,
response_data
,
response_len
);
}
/* Public functions */
/* iforce-serio.c */
void
iforce_serial_xmit
(
struct
iforce
*
iforce
);
/* iforce-usb.c */
void
iforce_usb_xmit
(
struct
iforce
*
iforce
);
/* iforce-main.c */
int
iforce_init_device
(
struct
iforce
*
iforce
);
int
iforce_init_device
(
struct
device
*
parent
,
u16
bustype
,
struct
iforce
*
iforce
);
/* iforce-packets.c */
int
iforce_control_playback
(
struct
iforce
*
,
u16
id
,
unsigned
int
);
void
iforce_process_packet
(
struct
iforce
*
iforce
,
u16
cmd
,
unsigned
char
*
data
);
void
iforce_process_packet
(
struct
iforce
*
iforce
,
u8
packet_id
,
u8
*
data
,
size_t
len
);
int
iforce_send_packet
(
struct
iforce
*
iforce
,
u16
cmd
,
unsigned
char
*
data
);
void
iforce_dump_packet
(
struct
iforce
*
iforce
,
char
*
msg
,
u16
cmd
,
unsigned
char
*
data
);
int
iforce_get_id_packet
(
struct
iforce
*
iforce
,
char
*
packet
);
/* iforce-ff.c */
int
iforce_upload_periodic
(
struct
iforce
*
,
struct
ff_effect
*
,
struct
ff_effect
*
);
...
...
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