}sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget/translations/zh_CN/input/ffmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/zh_TW/input/ffmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/it_IT/input/ffmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/ja_JP/input/ffmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/ko_KR/input/ffmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/sp_SP/input/ffmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhsection)}(hhh](htitle)}(hForce feedback for Linuxh]hForce feedback for Linux}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhh6/var/lib/git/docbuild/linux/Documentation/input/ff.rsthKubh field_list)}(hhh](hfield)}(hhh](h field_name)}(hAuthorh]hAuthor}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhKubh field_body)}(h6Johann Deneux on 2001/04/22.h]h paragraph)}(hhh](hJohann Deneux <}(hhhhhNhNubh reference)}(hjohann.deneux@gmail.comh]hjohann.deneux@gmail.com}(hhhhhNhNubah}(h]h ]h"]h$]h&]refurimailto:johann.deneux@gmail.comuh1hhhubh> on 2001/04/22.}(hhhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhhubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(hUpdatedh]hUpdated}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhKubh)}(h7Anssi Hannula on 2006/04/09. h]h)}(h6Anssi Hannula on 2006/04/09.h](hAnssi Hannula <}(hjhhhNhNubh)}(hanssi.hannula@gmail.comh]hanssi.hannula@gmail.com}(hj%hhhNhNubah}(h]h ]h"]h$]h&]refurimailto:anssi.hannula@gmail.comuh1hhjubh> on 2006/04/09.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubeh}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh)}(haYou may redistribute this file. Please remember to include shape.svg and interactive.svg as well.h]haYou may redistribute this file. Please remember to include shape.svg and interactive.svg as well.}(hjQhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(h Introductionh]h Introduction}(hjbhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj_hhhhhK ubh)}(hXThis 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 joydev/joystick.rst and input.rst before reading further this document.h]hXThis 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 joydev/joystick.rst and input.rst before reading further this document.}(hjphhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj_hhubeh}(h] introductionah ]h"] introductionah$]h&]uh1hhhhhhhhK ubh)}(hhh](h)}(hInstructions to the userh]hInstructions to the user}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKubh)}(h&To enable force feedback, you have to:h]h&To enable force feedback, you have to:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubhenumerated_list)}(hhh](h list_item)}(hNhave your kernel configured with evdev and a driver that supports your device.h]h)}(hNhave your kernel configured with evdev and a driver that supports your device.h]hNhave your kernel configured with evdev and a driver that supports your device.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(hQmake sure evdev module is loaded and /dev/input/event* device files are created. h]h)}(hPmake sure evdev module is loaded and /dev/input/event* device files are created.h]hPmake sure evdev module is loaded and /dev/input/event* device files are created.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubeh}(h]h ]h"]h$]h&]enumtypearabicprefixhsuffix.uh1jhjhhhhhKubh)}(hXKBefore 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.h]hXOBefore 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hjhhubh)}(hgIf you have a serial iforce device, you need to start inputattach. See joydev/joystick.rst for details.h]hgIf you have a serial iforce device, you need to start inputattach. See joydev/joystick.rst for details.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK&hjhhubh)}(hhh](h)}(hDoes it work ?h]hDoes it work ?}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhK*ubh)}(hJThere is an utility called fftest that will allow you to test the driver::h]hIThere is an utility called fftest that will allow you to test the driver:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK,hjhhubh literal_block)}(h% fftest /dev/input/eventXXh]h% fftest /dev/input/eventXX}hj$sbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1j"hhhK.hjhhubeh}(h] does-it-workah ]h"]does it work ?ah$]h&]uh1hhjhhhhhK*ubeh}(h]instructions-to-the-userah ]h"]instructions to the userah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hInstructions to the developerh]hInstructions to the developer}(hjGhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjDhhhhhK1ubh)}(hAll 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.h]hAll 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.}(hjUhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK3hjDhhubh)}(hhh](h)}(hQuerying device capabilitiesh]hQuerying device capabilities}(hjfhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjchhhhhK8ubj#)}(hX#include #include #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);h]hX#include #include #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);}hjtsbah}(h]h ]h"]h$]h&]j2j3uh1j"hhhK #include int ioctl(int file_descriptor, int request, struct ff_effect *effect);h]hw#include #include int ioctl(int file_descriptor, int request, struct ff_effect *effect);}hjsbah}(h]h ]h"]h$]h&]j2j3uh1j"hhhKphjhhubh)}(h"request" must be EVIOCSFF.h]h“request” must be EVIOCSFF.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKuhjhhubh)}(hX"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.h]hX“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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKwhjhhubh)}(h%Effects are file descriptor specific.h]h%Effects are file descriptor specific.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hSee 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:h]hSee 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:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubkfigure kernel_figure)}(hhh]hfigure)}(hhh](himage)}(h(.. kernel-figure:: shape.svg Shape h]h}(h]h ]h"]h$]h&]uriinput/shape.svg candidates}*jsuh1jhjhhhKubhcaption)}(hShapeh]hShape}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhhhKhjubeh}(h]id1ah ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(hhh]j)}(hhh](j)}(h5.. kernel-figure:: interactive.svg Interactive h]h}(h]h ]h"]h$]h&]uriinput/interactive.svgj}jj1suh1jhj#hhhKubj)}(h Interactiveh]h Interactive}(hj3hhhNhNubah}(h]h ]h"]h$]h&]uh1jhhhKhj#ubeh}(h]id2ah ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubeh}(h]uploading-effects-to-the-deviceah ]h"]uploading effects to the deviceah$]h&]uh1hhjDhhhhhKlubh)}(hhh](h)}(h"Removing an effect from the deviceh]h"Removing an effect from the device}(hjYhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjVhhhhhKubj#)}(h(int ioctl(int fd, EVIOCRMFF, effect.id);h]h(int ioctl(int fd, EVIOCRMFF, effect.id);}hjgsbah}(h]h ]h"]h$]h&]j2j3uh1j"hhhKhjVhhubh)}(hoThis makes room for new effects in the device's memory. Note that this also stops the effect if it was playing.h]hqThis makes room for new effects in the device’s memory. Note that this also stops the effect if it was playing.}(hjuhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjVhhubeh}(h]"removing-an-effect-from-the-deviceah ]h"]"removing an effect from the deviceah$]h&]uh1hhjDhhhhhKubh)}(hhh](h)}(h#Controlling the playback of effectsh]h#Controlling the playback of effects}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKubh)}(h=Control of playing is done with write(). Below is an example:h]h=Control of playing is done with write(). Below is an example:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj#)}(hX #include #include 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));h]hX #include #include 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));}hjsbah}(h]h ]h"]h$]h&]j2j3uh1j"hhhKhjhhubeh}(h]#controlling-the-playback-of-effectsah ]h"]#controlling the playback of effectsah$]h&]uh1hhjDhhhhhKubh)}(hhh](h)}(hSetting the gainh]hSetting the gain}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKubh)}(hNot 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.h]hNot 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj#)}(hX/* 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");h]hX/* 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");}hjsbah}(h]h ]h"]h$]h&]j2j3uh1j"hhhKhjhhubeh}(h]setting-the-gainah ]h"]setting the gainah$]h&]uh1hhjDhhhhhKubh)}(hhh](h)}(hEnabling/Disabling autocenterh]hEnabling/Disabling autocenter}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKubh)}(hThe 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.h]hThe 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj#)}(hint 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");h]hint 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");}hjsbah}(h]h ]h"]h$]h&]j2j3uh1j"hhhKhjhhubh)}(h$A value of 0 means "no auto-center".h]h(A value of 0 means “no auto-center”.}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubeh}(h]enabling-disabling-autocenterah ]h"]enabling/disabling autocenterah$]h&]uh1hhjDhhhhhKubh)}(hhh](h)}(hDynamic update of an effecth]hDynamic update of an effect}(hj;hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj8hhhhhKubh)}(hXProceed 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.h]hXProceed 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.}(hjIhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj8hhubh)}(hTherefore 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.h]hTherefore 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.}(hjWhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj8hhubeh}(h]dynamic-update-of-an-effectah ]h"]dynamic update of an effectah$]h&]uh1hhjDhhhhhKubh)}(hhh](h)}(h'Information about the status of effectsh]h'Information about the status of effects}(hjphhhNhNubah}(h]h ]h"]h$]h&]uh1hhjmhhhhhKubh)}(hEvery 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::h]hEvery 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:}(hj~hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjmhhubj#)}(hXqstruct 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 playh]hXqstruct 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}hjsbah}(h]h ]h"]h$]h&]j2j3uh1j"hhhKhjmhhubj()}(h- 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.h]j)}(hhh]j)}(hStatus 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.h]h)}(hStatus 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.h](hqStatus feedback is only supported by iforce driver. If you have a really good reason to use this, please contact }(hjhhhNhNubh)}(h'linux-joystick@atrey.karlin.mff.cuni.czh]h'linux-joystick@atrey.karlin.mff.cuni.cz}(hjhhhNhNubah}(h]h ]h"]h$]h&]refuri.mailto:linux-joystick@atrey.karlin.mff.cuni.czuh1hhjubh or }(hjhhhNhNubh)}(hanssi.hannula@gmail.comh]hanssi.hannula@gmail.com}(hjhhhNhNubah}(h]h ]h"]h$]h&]refurimailto:anssi.hannula@gmail.comuh1hhjubh@ so that support for it can be added to the rest of the drivers.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]j`jauh1jhhhMhjubah}(h]h ]h"]h$]h&]uh1j'hjmhhhNhNubeh}(h]'information-about-the-status-of-effectsah ]h"]'information about the status of effectsah$]h&]uh1hhjDhhhhhKubeh}(h]instructions-to-the-developerah ]h"]instructions to the developerah$]h&]uh1hhhhhhhhK1ubeh}(h]force-feedback-for-linuxah ]h"]force feedback for linuxah$]h&]uh1hhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerj(error_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(jjjjjAj>j9j6jjjjjSjPjjjjjjj5j2jjjgjju nametypes}(jjjAj9jjjSjjjj5jjjuh}(jhjj_j>jj6jjjDjjcjPjjjVjjjjj2jjgj8jjmjjjCj#u footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}j6KsRparse_messages]transform_messages] transformerN include_log] decorationNhhub.