mirror of https://gitee.com/openkylin/linux.git
Input: convert force feedback documentation into ReST format
This file require minimum adjustments to be a valid ReST file. Do it, in order to be able to parse it with Sphinx. Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
parent
acbdca8bf1
commit
3057d50980
|
@ -1,12 +1,16 @@
|
||||||
Force feedback for Linux.
|
========================
|
||||||
By Johann Deneux <johann.deneux@gmail.com> on 2001/04/22.
|
Force feedback for Linux
|
||||||
Updated by Anssi Hannula <anssi.hannula@gmail.com> on 2006/04/09.
|
========================
|
||||||
|
|
||||||
|
:Author: Johann Deneux <johann.deneux@gmail.com> on 2001/04/22.
|
||||||
|
:Updated: 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.
|
||||||
----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
1. Introduction
|
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
|
||||||
|
@ -15,8 +19,9 @@ This document only describes the force feedback part of the Linux input
|
||||||
interface. Please read joystick.txt and input.txt before reading further this
|
interface. Please read joystick.txt and input.txt before reading further this
|
||||||
document.
|
document.
|
||||||
|
|
||||||
2. Instructions to the user
|
Instructions to the user
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
To enable force feedback, you have to:
|
To enable force feedback, you have to:
|
||||||
|
|
||||||
1. have your kernel configured with evdev and a driver that supports your
|
1. have your kernel configured with evdev and a driver that supports your
|
||||||
|
@ -33,39 +38,48 @@ something goes wrong.
|
||||||
If you have a serial iforce device, you need to start inputattach. See
|
If you have a serial iforce device, you need to start inputattach. See
|
||||||
joystick.txt for details.
|
joystick.txt for details.
|
||||||
|
|
||||||
2.1 Does it work ?
|
Does it work ?
|
||||||
~~~~~~~~~~~~~~~~~~
|
--------------
|
||||||
There is an utility called fftest that will allow you to test the driver.
|
|
||||||
% fftest /dev/input/eventXX
|
There is an utility called fftest that will allow you to test the driver::
|
||||||
|
|
||||||
|
% fftest /dev/input/eventXX
|
||||||
|
|
||||||
|
Instructions to the developer
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
3. Instructions to the developer
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
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
|
Querying device capabilities
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
----------------------------
|
||||||
#include <linux/input.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
|
|
||||||
#define BITS_TO_LONGS(x) \
|
::
|
||||||
(((x) + 8 * sizeof (unsigned long) - 1) / (8 * sizeof (unsigned long)))
|
|
||||||
unsigned long features[BITS_TO_LONGS(FF_CNT)];
|
#include <linux/input.h>
|
||||||
int ioctl(int file_descriptor, int request, unsigned long *features);
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#define BITS_TO_LONGS(x) \
|
||||||
|
(((x) + 8 * sizeof (unsigned long) - 1) / (8 * sizeof (unsigned long)))
|
||||||
|
unsigned long features[BITS_TO_LONGS(FF_CNT)];
|
||||||
|
int ioctl(int file_descriptor, int request, unsigned long *features);
|
||||||
|
|
||||||
"request" must be EVIOCGBIT(EV_FF, size of features array in bytes )
|
"request" must be EVIOCGBIT(EV_FF, size of features array in bytes )
|
||||||
|
|
||||||
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_CONSTANT can render constant force effects
|
- FF_CONSTANT can render constant force effects
|
||||||
- FF_PERIODIC can render periodic effects with the following waveforms:
|
- FF_PERIODIC can render periodic effects with the following waveforms:
|
||||||
|
|
||||||
- FF_SQUARE square waveform
|
- FF_SQUARE square waveform
|
||||||
- FF_TRIANGLE triangle waveform
|
- FF_TRIANGLE triangle waveform
|
||||||
- FF_SINE sine waveform
|
- FF_SINE sine waveform
|
||||||
- FF_SAW_UP sawtooth up waveform
|
- FF_SAW_UP sawtooth up waveform
|
||||||
- FF_SAW_DOWN sawtooth down waveform
|
- FF_SAW_DOWN sawtooth down waveform
|
||||||
- FF_CUSTOM custom 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
|
||||||
|
@ -75,24 +89,30 @@ following bits:
|
||||||
- FF_GAIN gain is adjustable
|
- FF_GAIN gain is adjustable
|
||||||
- FF_AUTOCENTER autocenter is adjustable
|
- FF_AUTOCENTER autocenter is adjustable
|
||||||
|
|
||||||
Note: In most cases you should use FF_PERIODIC instead of FF_RUMBLE. All
|
.. note::
|
||||||
|
|
||||||
|
- In most cases you should use FF_PERIODIC instead of FF_RUMBLE. All
|
||||||
devices that support FF_RUMBLE support FF_PERIODIC (square, triangle,
|
devices that support FF_RUMBLE support FF_PERIODIC (square, triangle,
|
||||||
sine) and the other way around.
|
sine) and the other way around.
|
||||||
|
|
||||||
Note: The exact syntax FF_CUSTOM is undefined for the time being as no driver
|
- The exact syntax FF_CUSTOM is undefined for the time being as no driver
|
||||||
supports it yet.
|
supports it yet.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
int ioctl(int fd, EVIOCGEFFECTS, int *n);
|
int ioctl(int fd, EVIOCGEFFECTS, int *n);
|
||||||
|
|
||||||
Returns the number of effects the device can keep in its memory.
|
Returns the number of effects the device can keep in its memory.
|
||||||
|
|
||||||
3.2 Uploading effects to the device
|
Uploading effects to the device
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
-------------------------------
|
||||||
#include <linux/input.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
|
|
||||||
int ioctl(int file_descriptor, int request, struct ff_effect *effect);
|
::
|
||||||
|
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
int ioctl(int file_descriptor, int request, struct ff_effect *effect);
|
||||||
|
|
||||||
"request" must be EVIOCSFF.
|
"request" must be EVIOCSFF.
|
||||||
|
|
||||||
|
@ -110,34 +130,41 @@ 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.
|
||||||
|
|
||||||
3.3 Removing an effect from the device
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
Removing an effect from the device
|
||||||
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. Note that this also
|
This makes room for new effects in the device's memory. Note that this also
|
||||||
stops the effect if it was playing.
|
stops the effect if it was playing.
|
||||||
|
|
||||||
3.4 Controlling the playback of effects
|
Controlling the playback of effects
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
-----------------------------------
|
||||||
|
|
||||||
Control of playing is done with write(). Below is an example:
|
Control of playing is done with write(). Below is an example:
|
||||||
|
|
||||||
#include <linux/input.h>
|
::
|
||||||
#include <unistd.h>
|
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
struct input_event play;
|
struct input_event play;
|
||||||
struct input_event stop;
|
struct input_event stop;
|
||||||
struct ff_effect effect;
|
struct ff_effect effect;
|
||||||
int fd;
|
int fd;
|
||||||
...
|
...
|
||||||
fd = open("/dev/input/eventXX", O_RDWR);
|
fd = open("/dev/input/eventXX", O_RDWR);
|
||||||
...
|
...
|
||||||
/* Play three times */
|
/* Play three times */
|
||||||
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;
|
||||||
|
@ -145,43 +172,50 @@ Control of playing is done with write(). Below is an example:
|
||||||
|
|
||||||
write(fd, (const void*) &play, sizeof(stop));
|
write(fd, (const void*) &play, sizeof(stop));
|
||||||
|
|
||||||
3.5 Setting the gain
|
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.
|
persistent across access to the driver.
|
||||||
|
|
||||||
/* Set the gain of the device
|
::
|
||||||
int gain; /* between 0 and 100 */
|
|
||||||
struct input_event ie; /* structure used to communicate with the driver */
|
|
||||||
|
|
||||||
ie.type = EV_FF;
|
/* Set the gain of the device
|
||||||
ie.code = FF_GAIN;
|
int gain; /* between 0 and 100 */
|
||||||
ie.value = 0xFFFFUL * gain / 100;
|
struct input_event ie; /* structure used to communicate with the driver */
|
||||||
|
|
||||||
if (write(fd, &ie, sizeof(ie)) == -1)
|
ie.type = EV_FF;
|
||||||
|
ie.code = FF_GAIN;
|
||||||
|
ie.value = 0xFFFFUL * gain / 100;
|
||||||
|
|
||||||
|
if (write(fd, &ie, sizeof(ie)) == -1)
|
||||||
perror("set gain");
|
perror("set gain");
|
||||||
|
|
||||||
3.6 Enabling/Disabling autocenter
|
Enabling/Disabling autocenter
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
-----------------------------
|
||||||
|
|
||||||
The autocenter feature quite disturbs the rendering of effects in my opinion,
|
The autocenter feature quite disturbs the rendering of effects in my opinion,
|
||||||
and I think it should be an effect, which computation depends on the game
|
and I think it should be an effect, which computation depends on the game
|
||||||
type. But you can enable it if you want.
|
type. But you can enable it if you want.
|
||||||
|
|
||||||
int autocenter; /* between 0 and 100 */
|
::
|
||||||
struct input_event ie;
|
|
||||||
|
|
||||||
ie.type = EV_FF;
|
int autocenter; /* between 0 and 100 */
|
||||||
ie.code = FF_AUTOCENTER;
|
struct input_event ie;
|
||||||
ie.value = 0xFFFFUL * autocenter / 100;
|
|
||||||
|
|
||||||
if (write(fd, &ie, sizeof(ie)) == -1)
|
ie.type = EV_FF;
|
||||||
|
ie.code = FF_AUTOCENTER;
|
||||||
|
ie.value = 0xFFFFUL * autocenter / 100;
|
||||||
|
|
||||||
|
if (write(fd, &ie, sizeof(ie)) == -1)
|
||||||
perror("set auto-center");
|
perror("set auto-center");
|
||||||
|
|
||||||
A value of 0 means "no auto-center".
|
A value of 0 means "no auto-center".
|
||||||
|
|
||||||
3.7 Dynamic update of an effect
|
Dynamic update of an effect
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
---------------------------
|
||||||
|
|
||||||
Proceed as if you wanted to upload a new effect, except that instead of
|
Proceed as if you wanted to upload a new effect, except that instead of
|
||||||
setting the id field to -1, you set it to the wanted effect id.
|
setting the id field to -1, you set it to the wanted effect id.
|
||||||
Normally, the effect is not stopped and restarted. However, depending on the
|
Normally, the effect is not stopped and restarted. However, depending on the
|
||||||
|
@ -192,30 +226,32 @@ case, the driver stops the effect, up-load it, and restart it.
|
||||||
Therefore it is recommended to dynamically change direction while the effect
|
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.
|
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
|
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;
|
||||||
|
|
||||||
/* Set to EV_FF_STATUS */
|
/* Set to EV_FF_STATUS */
|
||||||
unsigned short type;
|
unsigned short type;
|
||||||
|
|
||||||
/* Contains the id of the effect */
|
/* Contains the id of the effect */
|
||||||
unsigned short code;
|
unsigned short code;
|
||||||
|
|
||||||
/* Indicates the status */
|
/* Indicates the status */
|
||||||
unsigned int value;
|
unsigned int value;
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
.. note::
|
||||||
|
|
||||||
|
- Status feedback is only supported by iforce driver. If you have
|
||||||
a really good reason to use this, please contact
|
a really good reason to use this, please contact
|
||||||
linux-joystick@atrey.karlin.mff.cuni.cz or anssi.hannula@gmail.com
|
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.
|
so that support for it can be added to the rest of the drivers.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue