mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 21:33:00 +00:00
Input: update the force feedback documentation
Signed-off-by: Anssi Hannula <anssi.hannula@gmail.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
parent
bb3caf7f43
commit
8b8277a174
@ -1,67 +1,37 @@
|
||||
Force feedback for Linux.
|
||||
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
|
||||
interactive.fig as well.
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
0. Introduction
|
||||
1. Introduction
|
||||
~~~~~~~~~~~~~~~
|
||||
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
|
||||
(as it is already the case), but to really enable the rendering of force
|
||||
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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
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 ?
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
@ -70,9 +40,9 @@ There is an utility called fftest that will allow you to test the driver.
|
||||
|
||||
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.
|
||||
This information is subject to change.
|
||||
This information is subject to change.
|
||||
|
||||
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
|
||||
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_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_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_RUMBLE rumble effects (normally the only effect supported by rumble
|
||||
pads)
|
||||
- FF_RUMBLE rumble effects
|
||||
- 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);
|
||||
@ -108,7 +89,7 @@ Returns the number of effects the device can keep in its memory.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
#include <linux/input.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
|
||||
int ioctl(int file_descriptor, int request, struct ff_effect *effect);
|
||||
|
||||
"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).
|
||||
This if field must be set to -1 by the user in order to tell the driver to
|
||||
allocate a new effect.
|
||||
|
||||
Effects are file descriptor specific.
|
||||
|
||||
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.
|
||||
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);
|
||||
|
||||
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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -149,22 +133,21 @@ Control of playing is done with write(). Below is an example:
|
||||
play.type = EV_FF;
|
||||
play.code = effect.id;
|
||||
play.value = 3;
|
||||
|
||||
|
||||
write(fd, (const void*) &play, sizeof(play));
|
||||
...
|
||||
/* Stop an effect */
|
||||
stop.type = EV_FF;
|
||||
stop.code = effect.id;
|
||||
stop.value = 0;
|
||||
|
||||
|
||||
write(fd, (const void*) &play, sizeof(stop));
|
||||
|
||||
3.5 Setting the 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
|
||||
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
|
||||
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
|
||||
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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
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:
|
||||
|
||||
struct input_event {
|
||||
/* When the status of the effect changed */
|
||||
struct timeval time;
|
||||
@ -225,3 +211,9 @@ struct input_event {
|
||||
|
||||
FF_STATUS_STOPPED The effect stopped playing
|
||||
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.
|
||||
|
||||
|
@ -667,98 +667,167 @@ struct input_absinfo {
|
||||
|
||||
/*
|
||||
* Structures used in ioctls to upload effects to a device
|
||||
* The first structures are not passed directly by using ioctls.
|
||||
* They are sub-structures of the actually sent structure (called ff_effect)
|
||||
* They are pieces of a bigger structure (called ff_effect)
|
||||
*/
|
||||
|
||||
/*
|
||||
* All duration values are expressed in ms. Values above 32767 ms (0x7fff)
|
||||
* should not be used and have unspecified results.
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct ff_replay - defines scheduling of the effect
|
||||
* @length: duration of the effect
|
||||
* @delay: delay before effect should start playing
|
||||
*/
|
||||
struct ff_replay {
|
||||
__u16 length; /* Duration of an effect in ms. All other times are also expressed in ms */
|
||||
__u16 delay; /* Time to wait before to start playing an effect */
|
||||
__u16 length;
|
||||
__u16 delay;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ff_trigger - defines what triggers the effect
|
||||
* @button: number of the button triggering the effect
|
||||
* @interval: controls how soon the effect can be re-triggered
|
||||
*/
|
||||
struct ff_trigger {
|
||||
__u16 button; /* Number of button triggering an effect */
|
||||
__u16 interval; /* Time to wait before an effect can be re-triggered (ms) */
|
||||
__u16 button;
|
||||
__u16 interval;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ff_envelope - generic effect envelope
|
||||
* @attack_length: duration of the attack (ms)
|
||||
* @attack_level: level at the beginning of the attack
|
||||
* @fade_length: duration of fade (ms)
|
||||
* @fade_level: level at the end of fade
|
||||
*
|
||||
* The @attack_level and @fade_level are absolute values; when applying
|
||||
* envelope force-feedback core will convert to positive/negative
|
||||
* value based on polarity of the default level of the effect.
|
||||
* Valid range for the attack and fade levels is 0x0000 - 0x7fff
|
||||
*/
|
||||
struct ff_envelope {
|
||||
__u16 attack_length; /* Duration of attack (ms) */
|
||||
__u16 attack_level; /* Level at beginning of attack */
|
||||
__u16 fade_length; /* Duration of fade (ms) */
|
||||
__u16 fade_level; /* Level at end of fade */
|
||||
__u16 attack_length;
|
||||
__u16 attack_level;
|
||||
__u16 fade_length;
|
||||
__u16 fade_level;
|
||||
};
|
||||
|
||||
/* FF_CONSTANT */
|
||||
/**
|
||||
* struct ff_constant_effect - defines parameters of a constant effect
|
||||
* @level: strength of the effect; may be negative
|
||||
* @envelope: envelope data
|
||||
*/
|
||||
struct ff_constant_effect {
|
||||
__s16 level; /* Strength of effect. Negative values are OK */
|
||||
__s16 level;
|
||||
struct ff_envelope envelope;
|
||||
};
|
||||
|
||||
/* FF_RAMP */
|
||||
/**
|
||||
* struct ff_ramp_effect - defines parameters of a ramp effect
|
||||
* @start_level: beginning strength of the effect; may be negative
|
||||
* @end_level: final strength of the effect; may be negative
|
||||
* @envelope: envelope data
|
||||
*/
|
||||
struct ff_ramp_effect {
|
||||
__s16 start_level;
|
||||
__s16 end_level;
|
||||
struct ff_envelope envelope;
|
||||
};
|
||||
|
||||
/* FF_SPRING of FF_FRICTION */
|
||||
/**
|
||||
* struct ff_condition_effect - defines a spring or friction effect
|
||||
* @right_saturation: maximum level when joystick moved all way to the right
|
||||
* @left_saturation: same for the left side
|
||||
* @right_coeff: controls how fast the force grows when the joystick moves
|
||||
* to the right
|
||||
* @left_coeff: same for the left side
|
||||
* @deadband: size of the dead zone, where no force is produced
|
||||
* @center: position of the dead zone
|
||||
*/
|
||||
struct ff_condition_effect {
|
||||
__u16 right_saturation; /* Max level when joystick is on the right */
|
||||
__u16 left_saturation; /* Max level when joystick in on the left */
|
||||
__u16 right_saturation;
|
||||
__u16 left_saturation;
|
||||
|
||||
__s16 right_coeff; /* Indicates how fast the force grows when the
|
||||
joystick moves to the right */
|
||||
__s16 left_coeff; /* Same for left side */
|
||||
|
||||
__u16 deadband; /* Size of area where no force is produced */
|
||||
__s16 center; /* Position of dead zone */
|
||||
__s16 right_coeff;
|
||||
__s16 left_coeff;
|
||||
|
||||
__u16 deadband;
|
||||
__s16 center;
|
||||
};
|
||||
|
||||
/* FF_PERIODIC */
|
||||
/**
|
||||
* struct ff_periodic_effect - defines parameters of a periodic effect
|
||||
* @waveform: kind of the effect (wave)
|
||||
* @period: period of the wave (ms)
|
||||
* @magnitude: peak value
|
||||
* @offset: mean value of the wave (roughly)
|
||||
* @phase: 'horizontal' shift
|
||||
* @envelope: envelope data
|
||||
* @custom_len: number of samples (FF_CUSTOM only)
|
||||
* @custom_data: buffer of samples (FF_CUSTOM only)
|
||||
*
|
||||
* Known waveforms - FF_SQUARE, FF_TRIANGLE, FF_SINE, FF_SAW_UP,
|
||||
* FF_SAW_DOWN, FF_CUSTOM. The exact syntax FF_CUSTOM is undefined
|
||||
* for the time being as no driver supports it yet.
|
||||
*
|
||||
* Note: the data pointed by custom_data is copied by the driver.
|
||||
* You can therefore dispose of the memory after the upload/update.
|
||||
*/
|
||||
struct ff_periodic_effect {
|
||||
__u16 waveform; /* Kind of wave (sine, square...) */
|
||||
__u16 period; /* in ms */
|
||||
__s16 magnitude; /* Peak value */
|
||||
__s16 offset; /* Mean value of wave (roughly) */
|
||||
__u16 phase; /* 'Horizontal' shift */
|
||||
__u16 waveform;
|
||||
__u16 period;
|
||||
__s16 magnitude;
|
||||
__s16 offset;
|
||||
__u16 phase;
|
||||
|
||||
struct ff_envelope envelope;
|
||||
|
||||
/* Only used if waveform == FF_CUSTOM */
|
||||
__u32 custom_len; /* Number of samples */
|
||||
__s16 *custom_data; /* Buffer of samples */
|
||||
/* Note: the data pointed by custom_data is copied by the driver. You can
|
||||
* therefore dispose of the memory after the upload/update */
|
||||
__u32 custom_len;
|
||||
__s16 *custom_data;
|
||||
};
|
||||
|
||||
/* FF_RUMBLE */
|
||||
/* Some rumble pads have two motors of different weight.
|
||||
strong_magnitude represents the magnitude of the vibration generated
|
||||
by the heavy motor.
|
||||
*/
|
||||
/**
|
||||
* struct ff_rumble_effect - defines parameters of a periodic effect
|
||||
* @strong_magnitude: magnitude of the heavy motor
|
||||
* @weak_magnitude: magnitude of the light one
|
||||
*
|
||||
* Some rumble pads have two motors of different weight. Strong_magnitude
|
||||
* represents the magnitude of the vibration generated by the heavy one.
|
||||
*/
|
||||
struct ff_rumble_effect {
|
||||
__u16 strong_magnitude; /* Magnitude of the heavy motor */
|
||||
__u16 weak_magnitude; /* Magnitude of the light one */
|
||||
__u16 strong_magnitude;
|
||||
__u16 weak_magnitude;
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure sent through ioctl from the application to the driver
|
||||
/**
|
||||
* struct ff_effect - defines force feedback effect
|
||||
* @type: type of the effect (FF_CONSTANT, FF_PERIODIC, FF_RAMP, FF_SPRING,
|
||||
* FF_FRICTION, FF_DAMPER, FF_RUMBLE, FF_INERTIA, or FF_CUSTOM)
|
||||
* @id: an unique id assigned to an effect
|
||||
* @direction: direction of the effect
|
||||
* @trigger: trigger conditions (struct ff_trigger)
|
||||
* @replay: scheduling of the effect (struct ff_replay)
|
||||
* @u: effect-specific structure (one of ff_constant_effect, ff_ramp_effect,
|
||||
* ff_periodic_effect, ff_condition_effect, ff_rumble_effect) further
|
||||
* defining effect parameters
|
||||
*
|
||||
* This structure is sent through ioctl from the application to the driver.
|
||||
* To create a new effect aplication should set its @id to -1; the kernel
|
||||
* will return assigned @id which can later be used to update or delete
|
||||
* this effect.
|
||||
*
|
||||
* Direction of the effect is encoded as follows:
|
||||
* 0 deg -> 0x0000 (down)
|
||||
* 90 deg -> 0x4000 (left)
|
||||
* 180 deg -> 0x8000 (up)
|
||||
* 270 deg -> 0xC000 (right)
|
||||
*/
|
||||
struct ff_effect {
|
||||
__u16 type;
|
||||
/* Following field denotes the unique id assigned to an effect.
|
||||
* If user sets if to -1, a new effect is created, and its id is returned in the same field
|
||||
* Else, the user sets it to the effect id it wants to update.
|
||||
*/
|
||||
__s16 id;
|
||||
|
||||
__u16 direction; /* Direction. 0 deg -> 0x0000 (down)
|
||||
90 deg -> 0x4000 (left)
|
||||
180 deg -> 0x8000 (up)
|
||||
270 deg -> 0xC000 (right)
|
||||
*/
|
||||
|
||||
__u16 direction;
|
||||
struct ff_trigger trigger;
|
||||
struct ff_replay replay;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user