1 |
1275 |
phoenix |
Force feedback for Linux.
|
2 |
|
|
By Johann Deneux on 2001/04/22.
|
3 |
|
|
|
4 |
|
|
----------------------------------------------------------------------------
|
5 |
|
|
|
6 |
|
|
0. Introduction
|
7 |
|
|
~~~~~~~~~~~~~~~
|
8 |
|
|
This document describes how to use force feedback devices under Linux. The
|
9 |
|
|
goal is not to support these devices as if they were simple input-only devices
|
10 |
|
|
(as it is already the case), but to really enable the rendering of force
|
11 |
|
|
effects.
|
12 |
|
|
At the moment, only I-Force devices are supported, and not officially. That
|
13 |
|
|
means I had to find out how the protocol works on my own. Of course, the
|
14 |
|
|
information I managed to grasp is far from being complete, and I can not
|
15 |
|
|
guarranty that this driver will work for you.
|
16 |
|
|
This document only describes the force feedback part of the driver for I-Force
|
17 |
|
|
devices. Please read joystick.txt before reading further this document.
|
18 |
|
|
|
19 |
|
|
2. Instructions to the user
|
20 |
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
21 |
|
|
Here are instructions on how to compile and use the driver. In fact, this
|
22 |
|
|
driver is the normal iforce.o, input.o and evdev.o drivers written by Vojtech
|
23 |
|
|
Pavlik, plus additions to support force feedback.
|
24 |
|
|
|
25 |
|
|
Before you start, let me WARN you that some devices shake violently during the
|
26 |
|
|
initialisation phase. This happens for example with my "AVB Top Shot Pegasus".
|
27 |
|
|
To stop this annoying behaviour, move you joystick to its limits. Anyway, you
|
28 |
|
|
should keep a hand on your device, in order to avoid it to brake down if
|
29 |
|
|
something goes wrong.
|
30 |
|
|
|
31 |
|
|
At the kernel's compilation:
|
32 |
|
|
- Enable IForce/Serial
|
33 |
|
|
- Enable Event interface
|
34 |
|
|
|
35 |
|
|
Compile the modules, install them.
|
36 |
|
|
|
37 |
|
|
You also need inputattach.
|
38 |
|
|
|
39 |
|
|
You then need to insert the modules into the following order:
|
40 |
|
|
% modprobe joydev
|
41 |
|
|
% modprobe serport
|
42 |
|
|
% modprobe iforce
|
43 |
|
|
% modprobe evdev
|
44 |
|
|
% ./inputattach -ifor $2 & # Only for serial
|
45 |
|
|
For convenience, you may use the shell script named "ff" available from
|
46 |
|
|
the cvs tree of the Linux Console Project at sourceforge. You can also
|
47 |
|
|
retrieve it from http://www.esil.univ-mrs.fr/~jdeneux/projects/ff/.
|
48 |
|
|
If you are using USB, you don't need the inputattach step.
|
49 |
|
|
|
50 |
|
|
Please check that you have all the /dev/input entries needed:
|
51 |
|
|
cd /dev
|
52 |
|
|
rm js*
|
53 |
|
|
mkdir input
|
54 |
|
|
mknod input/js0 c 13 0
|
55 |
|
|
mknod input/js1 c 13 1
|
56 |
|
|
mknod input/js2 c 13 2
|
57 |
|
|
mknod input/js3 c 13 3
|
58 |
|
|
ln -s input/js0 js0
|
59 |
|
|
ln -s input/js1 js1
|
60 |
|
|
ln -s input/js2 js2
|
61 |
|
|
ln -s input/js3 js3
|
62 |
|
|
|
63 |
|
|
mknod input/event0 c 13 64
|
64 |
|
|
mknod input/event1 c 13 65
|
65 |
|
|
mknod input/event2 c 13 66
|
66 |
|
|
mknod input/event3 c 13 67
|
67 |
|
|
|
68 |
|
|
2.1 Does it work ?
|
69 |
|
|
~~~~~~~~~~~~~~~~~~
|
70 |
|
|
There is an utility called fftest that will allow you to test the driver.
|
71 |
|
|
% fftest /dev/eventXX
|
72 |
|
|
|
73 |
|
|
3. Instructions to the developper
|
74 |
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
75 |
|
|
All interactions are done using the event API. That is, you can use ioctl()
|
76 |
|
|
and write() on /dev/input/eventXX.
|
77 |
|
|
This information is subject to change.
|
78 |
|
|
|
79 |
|
|
3.1 Querying device capabilities
|
80 |
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
81 |
|
|
#include
|
82 |
|
|
#include
|
83 |
|
|
|
84 |
|
|
int ioctl(int file_descriptor, int request, unsigned long *features);
|
85 |
|
|
|
86 |
|
|
"request" must be EVIOCGBIT(EV_FF, sizeof(unsigned long))
|
87 |
|
|
|
88 |
|
|
Returns the features supported by the device. features is a bitfield with the
|
89 |
|
|
following bits:
|
90 |
|
|
- FF_X has an X axis (should allways be the case)
|
91 |
|
|
- FF_Y has an Y axis (usually not the case for wheels)
|
92 |
|
|
- FF_CONSTANT can render constant force effects
|
93 |
|
|
- FF_PERIODIC can render periodic effects (sine, ramp, square...)
|
94 |
|
|
- FF_SPRING can simulate the presence of a spring
|
95 |
|
|
- FF_FRICTION can simulate friction (aka drag, damper effect...)
|
96 |
|
|
- FF_RUMBLE rumble effects (normally the only effect supported by rumble
|
97 |
|
|
pads)
|
98 |
|
|
- 8 bits from FF_N_EFFECTS_0 containing the number of effects that can be
|
99 |
|
|
simultaneously played.
|
100 |
|
|
|
101 |
|
|
3.2 Uploading effects to the device
|
102 |
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
103 |
|
|
#include
|
104 |
|
|
#include
|
105 |
|
|
|
106 |
|
|
int ioctl(int file_descriptor, int request, struct ff_effect *effect);
|
107 |
|
|
|
108 |
|
|
"request" must be EVIOCSFF.
|
109 |
|
|
|
110 |
|
|
"effect" points to a structure describing the effect to upload. The effect is
|
111 |
|
|
uploaded, but not played.
|
112 |
|
|
The content of effect may be modified. In particular, its field "id" is set
|
113 |
|
|
to the unique id assigned by the driver. This data is required for performing
|
114 |
|
|
some operations (removing an effect, controlling the playback).
|
115 |
|
|
See for a description of the ff_effect stuct.
|
116 |
|
|
|
117 |
|
|
3.3 Removing an effect from the device
|
118 |
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
119 |
|
|
int ioctl(int fd, EVIOCRMFF, effect.id);
|
120 |
|
|
|
121 |
|
|
This makes room for new effects in the device's memory. Please note this won't
|
122 |
|
|
stop the effect if it was playing.
|
123 |
|
|
|
124 |
|
|
3.4 Controlling the playback of effects
|
125 |
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
126 |
|
|
Control of playing is done with write(). Below is an example:
|
127 |
|
|
|
128 |
|
|
#include
|
129 |
|
|
#include
|
130 |
|
|
|
131 |
|
|
struct input_event play;
|
132 |
|
|
struct input_event stop;
|
133 |
|
|
struct ff_effect effect;
|
134 |
|
|
int fd;
|
135 |
|
|
...
|
136 |
|
|
fd = open("/dev/input/eventXX", O_RDWR);
|
137 |
|
|
...
|
138 |
|
|
/* Play three times */
|
139 |
|
|
play.type = EV_FF;
|
140 |
|
|
play.code = effect.id;
|
141 |
|
|
play.value = 3;
|
142 |
|
|
|
143 |
|
|
write(fd, (const void*) &play, sizeof(play));
|
144 |
|
|
...
|
145 |
|
|
/* Stop an effect */
|
146 |
|
|
stop.type = EV_FF;
|
147 |
|
|
stop.code = effect.id;
|
148 |
|
|
stop.value = 0;
|
149 |
|
|
|
150 |
|
|
write(fd, (const void*) &play, sizeof(stop));
|
151 |
|
|
|
152 |
|
|
3.5 Setting the gain
|
153 |
|
|
~~~~~~~~~~~~~~~~~~~~
|
154 |
|
|
Not all devices have the same strength. Therefore, users should set a gain
|
155 |
|
|
factor depending on how strong they want effects to be. This setting is
|
156 |
|
|
persistent accross access to the driver, so you should not care about it if
|
157 |
|
|
you are writing games, as another utility probably already set this for you.
|
158 |
|
|
|
159 |
|
|
/* Set the gain of the device
|
160 |
|
|
int gain; /* between 0 and 100 */
|
161 |
|
|
struct input_event ie; /* structure used to communicate with the driver */
|
162 |
|
|
|
163 |
|
|
ie.type = EV_FF;
|
164 |
|
|
ie.code = FF_GAIN;
|
165 |
|
|
ie.value = 0xFFFFUL * gain / 100;
|
166 |
|
|
|
167 |
|
|
if (write(fd, &ie, sizeof(ie)) == -1)
|
168 |
|
|
perror("set gain");
|
169 |
|
|
|
170 |
|
|
3.6 Enabling/Disabling autocenter
|
171 |
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
172 |
|
|
The autocenter feature quite disturbs the rendering of effects in my opinion,
|
173 |
|
|
and I think it should be an effect, which computation depends on the game
|
174 |
|
|
type. But you can enable it if you want.
|
175 |
|
|
|
176 |
|
|
int autocenter; /* between 0 and 100 */
|
177 |
|
|
struct input_event ie;
|
178 |
|
|
|
179 |
|
|
ie.type = EV_FF;
|
180 |
|
|
ie.code = FF_AUTOCENTER;
|
181 |
|
|
ie.value = 0xFFFFUL * autocenter / 100;
|
182 |
|
|
|
183 |
|
|
if (write(fd, &ie, sizeof(ie)) == -1)
|
184 |
|
|
perror("set auto-center");
|
185 |
|
|
|
186 |
|
|
A value of 0 means "no auto-center".
|
187 |
|
|
|
188 |
|
|
3.7 Dynamic update of an effect
|
189 |
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
190 |
|
|
This consists in changing some parameters of an effect while it's playing. The
|
191 |
|
|
driver currently does not support that. You still have the brute-force method,
|
192 |
|
|
which consists in erasing the effect and uploading the updated version. It
|
193 |
|
|
actually works pretty well. You don't need to stop-and-start the effect.
|
194 |
|
|
|