| ======================== | 
 | Force feedback for Linux | 
 | ======================== | 
 |  | 
 | :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.svg and | 
 | interactive.svg as well. | 
 |  | 
 | 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. | 
 | 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. | 
 |  | 
 | Instructions to the user | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | 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 your joystick to its limits. Anyway, you | 
 | should keep a hand on your device, in order to avoid it to break down if | 
 | something goes wrong. | 
 |  | 
 | If you have a serial iforce device, you need to start inputattach. See | 
 | joystick.txt for details. | 
 |  | 
 | Does it work ? | 
 | -------------- | 
 |  | 
 | There is an utility called fftest that will allow you to test the driver:: | 
 |  | 
 |     % fftest /dev/input/eventXX | 
 |  | 
 | Instructions to the developer | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | 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. | 
 |  | 
 | 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)]; | 
 |     int ioctl(int file_descriptor, int request, unsigned long *features); | 
 |  | 
 | "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 | 
 | following bits: | 
 |  | 
 | - FF_CONSTANT	can render constant force effects | 
 | - 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_DAMPER	can simulate damper effects | 
 | - 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. | 
 |  | 
 |     - The exact syntax FF_CUSTOM is undefined for the time being as no driver | 
 |       supports it yet. | 
 |  | 
 | :: | 
 |  | 
 |     int ioctl(int fd, EVIOCGEFFECTS, int *n); | 
 |  | 
 | Returns the number of effects the device can keep in its memory. | 
 |  | 
 | Uploading effects to the device | 
 | ------------------------------- | 
 |  | 
 | :: | 
 |  | 
 |     #include <linux/input.h> | 
 |     #include <sys/ioctl.h> | 
 |  | 
 |     int ioctl(int file_descriptor, int request, struct ff_effect *effect); | 
 |  | 
 | "request" must be EVIOCSFF. | 
 |  | 
 | "effect" points to a structure describing the effect to upload. The effect is | 
 | uploaded, but not played. | 
 | The content of effect may be modified. In particular, its field "id" is set | 
 | to the unique id assigned by the driver. This data is required for performing | 
 | some operations (removing an effect, controlling the playback). | 
 | The "id" 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 <uapi/linux/input.h> for a description of the ff_effect struct.  You | 
 | should also find help in a few sketches, contained in files shape.svg | 
 | and interactive.svg: | 
 |  | 
 | .. kernel-figure:: shape.svg | 
 |  | 
 |     Shape | 
 |  | 
 | .. kernel-figure:: interactive.svg | 
 |  | 
 |     Interactive | 
 |  | 
 |  | 
 | Removing an effect from the device | 
 | ---------------------------------- | 
 |  | 
 | :: | 
 |  | 
 |     int ioctl(int fd, EVIOCRMFF, effect.id); | 
 |  | 
 | This makes room for new effects in the device's memory. Note that this also | 
 | stops the effect if it was playing. | 
 |  | 
 | Controlling the playback of effects | 
 | ----------------------------------- | 
 |  | 
 | Control of playing is done with write(). Below is an example: | 
 |  | 
 | :: | 
 |  | 
 |     #include <linux/input.h> | 
 |     #include <unistd.h> | 
 |  | 
 | 	struct input_event play; | 
 | 	struct input_event stop; | 
 | 	struct ff_effect effect; | 
 | 	int fd; | 
 |    ... | 
 | 	fd = open("/dev/input/eventXX", O_RDWR); | 
 |    ... | 
 | 	/* Play three times */ | 
 | 	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*) &stop, sizeof(stop)); | 
 |  | 
 | 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. | 
 |  | 
 | :: | 
 |  | 
 |     /* 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; | 
 |     ie.code = FF_GAIN; | 
 |     ie.value = 0xFFFFUL * gain / 100; | 
 |  | 
 |     if (write(fd, &ie, sizeof(ie)) == -1) | 
 | 	perror("set gain"); | 
 |  | 
 | Enabling/Disabling autocenter | 
 | ----------------------------- | 
 |  | 
 | 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 | 
 | type. But you can enable it if you want. | 
 |  | 
 | :: | 
 |  | 
 |     int autocenter;		/* between 0 and 100 */ | 
 |     struct input_event ie; | 
 |  | 
 |     ie.type = EV_FF; | 
 |     ie.code = FF_AUTOCENTER; | 
 |     ie.value = 0xFFFFUL * autocenter / 100; | 
 |  | 
 |     if (write(fd, &ie, sizeof(ie)) == -1) | 
 | 	perror("set auto-center"); | 
 |  | 
 | A value of 0 means "no auto-center". | 
 |  | 
 | Dynamic update of an effect | 
 | --------------------------- | 
 |  | 
 | 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. | 
 | Normally, the effect is not stopped and restarted. However, depending on the | 
 | 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. | 
 |  | 
 | 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; | 
 |  | 
 |     /* Set to EV_FF_STATUS */ | 
 | 	    unsigned short type; | 
 |  | 
 |     /* Contains the id of the effect */ | 
 | 	    unsigned short code; | 
 |  | 
 |     /* Indicates the status */ | 
 | 	    unsigned int value; | 
 |     }; | 
 |  | 
 |     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. |