|
@@ -1,67 +1,37 @@
|
|
Force feedback for Linux.
|
|
Force feedback for Linux.
|
|
By Johann Deneux <deneux@ifrance.com> on 2001/04/22.
|
|
By Johann Deneux <deneux@ifrance.com> on 2001/04/22.
|
|
|
|
+Updated by Anssi Hannula <anssi.hannula@gmail.com> on 2006/04/09.
|
|
You may redistribute this file. Please remember to include shape.fig and
|
|
You may redistribute this file. Please remember to include shape.fig and
|
|
interactive.fig as well.
|
|
interactive.fig as well.
|
|
----------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------
|
|
|
|
|
|
-0. Introduction
|
|
|
|
|
|
+1. Introduction
|
|
~~~~~~~~~~~~~~~
|
|
~~~~~~~~~~~~~~~
|
|
This document describes how to use force feedback devices under Linux. The
|
|
This document describes how to use force feedback devices under Linux. The
|
|
goal is not to support these devices as if they were simple input-only devices
|
|
goal is not to support these devices as if they were simple input-only devices
|
|
(as it is already the case), but to really enable the rendering of force
|
|
(as it is already the case), but to really enable the rendering of force
|
|
effects.
|
|
effects.
|
|
-At the moment, only I-Force devices are supported, and not officially. That
|
|
|
|
-means I had to find out how the protocol works on my own. Of course, the
|
|
|
|
-information I managed to grasp is far from being complete, and I can not
|
|
|
|
-guarranty that this driver will work for you.
|
|
|
|
-This document only describes the force feedback part of the driver for I-Force
|
|
|
|
-devices. Please read joystick.txt before reading further this document.
|
|
|
|
|
|
+This document only describes the force feedback part of the Linux input
|
|
|
|
+interface. Please read joystick.txt and input.txt before reading further this
|
|
|
|
+document.
|
|
|
|
|
|
2. Instructions to the user
|
|
2. Instructions to the user
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
-Here are instructions on how to compile and use the driver. In fact, this
|
|
|
|
-driver is the normal iforce, input and evdev drivers written by Vojtech
|
|
|
|
-Pavlik, plus additions to support force feedback.
|
|
|
|
|
|
+To enable force feedback, you have to:
|
|
|
|
+
|
|
|
|
+1. have your kernel configured with evdev and a driver that supports your
|
|
|
|
+ device.
|
|
|
|
+2. make sure evdev module is loaded and /dev/input/event* device files are
|
|
|
|
+ created.
|
|
|
|
|
|
Before you start, let me WARN you that some devices shake violently during the
|
|
Before you start, let me WARN you that some devices shake violently during the
|
|
initialisation phase. This happens for example with my "AVB Top Shot Pegasus".
|
|
initialisation phase. This happens for example with my "AVB Top Shot Pegasus".
|
|
To stop this annoying behaviour, move you joystick to its limits. Anyway, you
|
|
To stop this annoying behaviour, move you joystick to its limits. Anyway, you
|
|
-should keep a hand on your device, in order to avoid it to brake down if
|
|
|
|
|
|
+should keep a hand on your device, in order to avoid it to break down if
|
|
something goes wrong.
|
|
something goes wrong.
|
|
|
|
|
|
-At the kernel's compilation:
|
|
|
|
- - Enable IForce/Serial
|
|
|
|
- - Enable Event interface
|
|
|
|
-
|
|
|
|
-Compile the modules, install them.
|
|
|
|
-
|
|
|
|
-You also need inputattach.
|
|
|
|
-
|
|
|
|
-You then need to insert the modules into the following order:
|
|
|
|
-% modprobe joydev
|
|
|
|
-% modprobe serport # Only for serial
|
|
|
|
-% modprobe iforce
|
|
|
|
-% modprobe evdev
|
|
|
|
-% ./inputattach -ifor $2 & # Only for serial
|
|
|
|
-If you are using USB, you don't need the inputattach step.
|
|
|
|
-
|
|
|
|
-Please check that you have all the /dev/input entries needed:
|
|
|
|
-cd /dev
|
|
|
|
-rm js*
|
|
|
|
-mkdir input
|
|
|
|
-mknod input/js0 c 13 0
|
|
|
|
-mknod input/js1 c 13 1
|
|
|
|
-mknod input/js2 c 13 2
|
|
|
|
-mknod input/js3 c 13 3
|
|
|
|
-ln -s input/js0 js0
|
|
|
|
-ln -s input/js1 js1
|
|
|
|
-ln -s input/js2 js2
|
|
|
|
-ln -s input/js3 js3
|
|
|
|
-
|
|
|
|
-mknod input/event0 c 13 64
|
|
|
|
-mknod input/event1 c 13 65
|
|
|
|
-mknod input/event2 c 13 66
|
|
|
|
-mknod input/event3 c 13 67
|
|
|
|
|
|
+If you have a serial iforce device, you need to start inputattach. See
|
|
|
|
+joystick.txt for details.
|
|
|
|
|
|
2.1 Does it work ?
|
|
2.1 Does it work ?
|
|
~~~~~~~~~~~~~~~~~~
|
|
~~~~~~~~~~~~~~~~~~
|
|
@@ -70,9 +40,9 @@ There is an utility called fftest that will allow you to test the driver.
|
|
|
|
|
|
3. Instructions to the developper
|
|
3. Instructions to the developper
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
- All interactions are done using the event API. That is, you can use ioctl()
|
|
|
|
|
|
+All interactions are done using the event API. That is, you can use ioctl()
|
|
and write() on /dev/input/eventXX.
|
|
and write() on /dev/input/eventXX.
|
|
- This information is subject to change.
|
|
|
|
|
|
+This information is subject to change.
|
|
|
|
|
|
3.1 Querying device capabilities
|
|
3.1 Querying device capabilities
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -86,18 +56,29 @@ int ioctl(int file_descriptor, int request, unsigned long *features);
|
|
|
|
|
|
Returns the features supported by the device. features is a bitfield with the
|
|
Returns the features supported by the device. features is a bitfield with the
|
|
following bits:
|
|
following bits:
|
|
-- FF_X has an X axis (usually joysticks)
|
|
|
|
-- FF_Y has an Y axis (usually joysticks)
|
|
|
|
-- FF_WHEEL has a wheel (usually sterring wheels)
|
|
|
|
- FF_CONSTANT can render constant force effects
|
|
- FF_CONSTANT can render constant force effects
|
|
-- FF_PERIODIC can render periodic effects (sine, triangle, square...)
|
|
|
|
|
|
+- FF_PERIODIC can render periodic effects with the following waveforms:
|
|
|
|
+ - FF_SQUARE square waveform
|
|
|
|
+ - FF_TRIANGLE triangle waveform
|
|
|
|
+ - FF_SINE sine waveform
|
|
|
|
+ - FF_SAW_UP sawtooth up waveform
|
|
|
|
+ - FF_SAW_DOWN sawtooth down waveform
|
|
|
|
+ - FF_CUSTOM custom waveform
|
|
- FF_RAMP can render ramp effects
|
|
- FF_RAMP can render ramp effects
|
|
- FF_SPRING can simulate the presence of a spring
|
|
- FF_SPRING can simulate the presence of a spring
|
|
-- FF_FRICTION can simulate friction
|
|
|
|
|
|
+- FF_FRICTION can simulate friction
|
|
- FF_DAMPER can simulate damper effects
|
|
- FF_DAMPER can simulate damper effects
|
|
-- FF_RUMBLE rumble effects (normally the only effect supported by rumble
|
|
|
|
- pads)
|
|
|
|
|
|
+- FF_RUMBLE rumble effects
|
|
- FF_INERTIA can simulate inertia
|
|
- FF_INERTIA can simulate inertia
|
|
|
|
+- FF_GAIN gain is adjustable
|
|
|
|
+- FF_AUTOCENTER autocenter is adjustable
|
|
|
|
+
|
|
|
|
+Note: In most cases you should use FF_PERIODIC instead of FF_RUMBLE. All
|
|
|
|
+ devices that support FF_RUMBLE support FF_PERIODIC (square, triangle,
|
|
|
|
+ sine) and the other way around.
|
|
|
|
+
|
|
|
|
+Note: The exact syntax FF_CUSTOM is undefined for the time being as no driver
|
|
|
|
+ supports it yet.
|
|
|
|
|
|
|
|
|
|
int ioctl(int fd, EVIOCGEFFECTS, int *n);
|
|
int ioctl(int fd, EVIOCGEFFECTS, int *n);
|
|
@@ -108,7 +89,7 @@ Returns the number of effects the device can keep in its memory.
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
#include <linux/input.h>
|
|
#include <linux/input.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/ioctl.h>
|
|
-
|
|
|
|
|
|
+
|
|
int ioctl(int file_descriptor, int request, struct ff_effect *effect);
|
|
int ioctl(int file_descriptor, int request, struct ff_effect *effect);
|
|
|
|
|
|
"request" must be EVIOCSFF.
|
|
"request" must be EVIOCSFF.
|
|
@@ -120,6 +101,9 @@ to the unique id assigned by the driver. This data is required for performing
|
|
some operations (removing an effect, controlling the playback).
|
|
some operations (removing an effect, controlling the playback).
|
|
This if field must be set to -1 by the user in order to tell the driver to
|
|
This if field must be set to -1 by the user in order to tell the driver to
|
|
allocate a new effect.
|
|
allocate a new effect.
|
|
|
|
+
|
|
|
|
+Effects are file descriptor specific.
|
|
|
|
+
|
|
See <linux/input.h> for a description of the ff_effect struct. You should also
|
|
See <linux/input.h> for a description of the ff_effect struct. You should also
|
|
find help in a few sketches, contained in files shape.fig and interactive.fig.
|
|
find help in a few sketches, contained in files shape.fig and interactive.fig.
|
|
You need xfig to visualize these files.
|
|
You need xfig to visualize these files.
|
|
@@ -128,8 +112,8 @@ You need xfig to visualize these files.
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
int ioctl(int fd, EVIOCRMFF, effect.id);
|
|
int ioctl(int fd, EVIOCRMFF, effect.id);
|
|
|
|
|
|
-This makes room for new effects in the device's memory. Please note this won't
|
|
|
|
-stop the effect if it was playing.
|
|
|
|
|
|
+This makes room for new effects in the device's memory. Note that this also
|
|
|
|
+stops the effect if it was playing.
|
|
|
|
|
|
3.4 Controlling the playback of effects
|
|
3.4 Controlling the playback of effects
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -149,22 +133,21 @@ Control of playing is done with write(). Below is an example:
|
|
play.type = EV_FF;
|
|
play.type = EV_FF;
|
|
play.code = effect.id;
|
|
play.code = effect.id;
|
|
play.value = 3;
|
|
play.value = 3;
|
|
-
|
|
|
|
|
|
+
|
|
write(fd, (const void*) &play, sizeof(play));
|
|
write(fd, (const void*) &play, sizeof(play));
|
|
...
|
|
...
|
|
/* Stop an effect */
|
|
/* Stop an effect */
|
|
stop.type = EV_FF;
|
|
stop.type = EV_FF;
|
|
stop.code = effect.id;
|
|
stop.code = effect.id;
|
|
stop.value = 0;
|
|
stop.value = 0;
|
|
-
|
|
|
|
|
|
+
|
|
write(fd, (const void*) &play, sizeof(stop));
|
|
write(fd, (const void*) &play, sizeof(stop));
|
|
|
|
|
|
3.5 Setting the gain
|
|
3.5 Setting the gain
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
Not all devices have the same strength. Therefore, users should set a gain
|
|
Not all devices have the same strength. Therefore, users should set a gain
|
|
factor depending on how strong they want effects to be. This setting is
|
|
factor depending on how strong they want effects to be. This setting is
|
|
-persistent across access to the driver, so you should not care about it if
|
|
|
|
-you are writing games, as another utility probably already set this for you.
|
|
|
|
|
|
+persistent across access to the driver.
|
|
|
|
|
|
/* Set the gain of the device
|
|
/* Set the gain of the device
|
|
int gain; /* between 0 and 100 */
|
|
int gain; /* between 0 and 100 */
|
|
@@ -204,11 +187,14 @@ type of device, not all parameters can be dynamically updated. For example,
|
|
the direction of an effect cannot be updated with iforce devices. In this
|
|
the direction of an effect cannot be updated with iforce devices. In this
|
|
case, the driver stops the effect, up-load it, and restart it.
|
|
case, the driver stops the effect, up-load it, and restart it.
|
|
|
|
|
|
|
|
+Therefore it is recommended to dynamically change direction while the effect
|
|
|
|
+is playing only when it is ok to restart the effect with a replay count of 1.
|
|
|
|
|
|
3.8 Information about the status of effects
|
|
3.8 Information about the status of effects
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Every time the status of an effect is changed, an event is sent. The values
|
|
Every time the status of an effect is changed, an event is sent. The values
|
|
and meanings of the fields of the event are as follows:
|
|
and meanings of the fields of the event are as follows:
|
|
|
|
+
|
|
struct input_event {
|
|
struct input_event {
|
|
/* When the status of the effect changed */
|
|
/* When the status of the effect changed */
|
|
struct timeval time;
|
|
struct timeval time;
|
|
@@ -225,3 +211,9 @@ struct input_event {
|
|
|
|
|
|
FF_STATUS_STOPPED The effect stopped playing
|
|
FF_STATUS_STOPPED The effect stopped playing
|
|
FF_STATUS_PLAYING The effect started to play
|
|
FF_STATUS_PLAYING The effect started to play
|
|
|
|
+
|
|
|
|
+NOTE: Status feedback is only supported by iforce driver. If you have
|
|
|
|
+ a really good reason to use this, please contact
|
|
|
|
+ linux-joystick@atrey.karlin.mff.cuni.cz or anssi.hannula@gmail.com
|
|
|
|
+ so that support for it can be added to the rest of the drivers.
|
|
|
|
+
|