here is my how-to, thus far:
started from scratch (fresh slackware 10 installation, default 2.4.26 kernel);
notes:
i did this all as root.
if you have a 2.6.x kernel this is probably unnecessary, can probably just do steps 10 onwards.
*** *** *** *** *** *** *** *** *** ***
***1. download these two files:
http://user.it.uu.se/~johannd/projec...dalone.tar.bz2
http://user.it.uu.se/~johannd/projec...-utils.tar.bz2
***2. uncompress each (i did this the easy way by right-clicking in KDE).
***3. navigate into the modules directory.
e.g. $ cd /root/wheel_stuff/ff-standalone-module/
and then do;
$ ./configure
$ make
***4. run lsmod and have a look at the output for any mentions of modules; input, evdev, iforce.
***5. if any of the three modules appear on the list, remove them by typing;
$ rmmod module
where 'module' is whichever of input/evdev/iforce was shown from lsmod. i managed to do this even to the input module, and my keyboard & mosue kept working fine (but mine are both PS/2, not sure if USB ones would manage this. advised by Johann that USB should probably be fine too). if none of the modules appeared then skip to step 6.
***6. insert the new modules like this:
$ insmod input.o
$ insmod evdev.o
$ insmod iforce.o
hopefully they all go in fine. if not, or it complains about some of them already being loaded, then have another look at step 4, or try removing the offending modules from /etc/rc.d/rc.modules & reboot.
***7. backup the three new modules;
$ cp input.o new_input.o
$ cp evdev.o new_evdev.o
$ cp iforce.o new_iforce.o
then gzip them;
$ gzip input.o
$ gzip evdev.o
$ gzip iforce.o
***8. move the original three kernel modules into a backup folder (don't just rename them in their original folder);
$ mkdir /root/wheel/ff-standalone-modules/old_modules/
$ cd old_modules
$ mv /lib/modules/2.4.26/kernel/drivers/input/input.o.gz .
$ mv /lib/modules/2.4.26/kernel/drivers/input/evdev.o.gz .
$ mv /lib/modules/2.4.26/kernel/drivers/char/joystick/iforce.o.gz .
$ cd ..
***9. replace the old modules with the new ones;
$ cp input.o.gz /lib/modules/2.4.26/kernel/drivers/input/
$ cp evdev.o.gz /lib/modules/2.4.26/kernel/drivers/input/
$ cp iforce.o.gz /lib/modules/2.4.26/kernel/drivers/char/joystick/
***10. enable the three modules in /etc/rc.d/rc.modules by uncommenting or creating the following lines;
/sbin/modprobe joydev
/sbin/modprobe input
/sbin/modprobe evdev
/sbin/modprobe iforce
the first line isn't needed to get purely force feedback going, but i needed it to actually use the wheel later.
PS: i also use a joystick with the lines;
/sbin/modporbe joydev
/sbin/modprobe analog
/sbin/modprobe emu10k1-gp
these conflict with the wheel drivers, so i make sure to only have one set loaded at a time. i do it via editing the rc.modules for one set & rebooting, but there's probably a non-reboot method too.
***11. reboot or manaully type the above lines.
***12. test the force playback using the ff-itils:
e.g. $ cd /root/wheel/ff-utils
$ ./fftest /dev/input/eventX
where X must be replaced by the right number (you may have to try, starting from 0 until you get the right one, i.e your wheel, not the keyboard or the mouse or another input device). once into the program, try 0,1,2,3 (4 & 5 are gamepad rumble effects, not for steering wheels). i liked to test each separately, i.e. close and restart the util after each.
***13. i did all of the above as root. now need to make /dev/input/event0 writable to a user group (i.e. 'games', which my main user belongs to). to do this in KDE; as root, right click on the file and set 'Group: Can Read & Write', and change the group to 'games' down at the bottom. now the normal user will be able to run the fftest utility.
*** *** *** *** *** *** *** *** *** ***
that's it. force feedback works. i installed wine(20040914) and installed Live for Speed S1, and the wheel worked... but only as non-force feedback. this issue is a wine and/or LFS issue, which i'll let Johann sum up;
"Yes, what now? That's how far I can get you. For applications actually making use of FF, you have to ask their developers. I don't know if any linux application available out there makes use of the driver. I have received several mails from people doing their own in-house software, but I don't know of any publicly available usable game taking advantage of force-feedback. I would be glad to hear about them if you know any."
i got great help from Johann Deneux via the e-mailing list (
http://lists.sourceforge.net/lists/l...o/libff-kernel &
libff-kernel@lists.sourceforge.net).
*** *** *** *** *** *** *** *** *** ***
understanding that no games (that i know of) use force feedback yet, i wanted to at least enable the spring and damping conditions when using it. to do this i played around with the utils in;
http://user.it.uu.se/~johannd/projec...-utils.tar.bz2
using fftest.c as my starting point i tried various ideas:
1. a background program that runs in a periodic loop to repeatedly run the spring & damping functions so that even if the controller is 'reset' by the program when it starts each race or exiting/entering pits or messing around with the in-game controls menu, the spring & damper function kick in within a few seconds.
2. a program which runs once, maybe give it a shortcut keyset to run from within whatever game I'm playing, to enable the spring & damper for infinity timescale (0).
i think option 1 is the ideal, and i maybe managed it at one stage, but i lost the code :O(. I couldn't figure out how to make shortcut keys in KDE so gave up on program 2. skipping to another terminal via CTRL+F2 (get back to game with CTRL+F7) and running program 2 worked. i then found that the racing game i play only resets the controller during startup & if i mess around in the controller menu. what i ended up with is having a program run with a 15 second delay to activation, which is enough time for me to get into the game, and learnt not to mess around in the controls menu. crude, but it worked. here's how i do it:
***1. after extracting ff-utils.tar.bz2 go into its directory and backup the fftest.c file, thus:
$ cp fftest.c original_fftest.c
***2. open fftest with a text editor, and delete its contents and put in the following code (which i just edited from Johanns original fftest.c anyway):
Code:
/*
* $id$
*
* Tests the force feedback driver
* Copyright 2001-2002 Johann Deneux <deneux@ifrance.com>
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* You can contact the author by email at this address:
* Johann Deneux <deneux@ifrance.com>
*/
// Quick fix for #define mess
#define uint16_t unsigned short
#define uint32_t unsigned short
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/input.h>
#define BITS_PER_LONG (sizeof(long) * 8)
#define OFF(x) ((x)%BITS_PER_LONG)
#define BIT(x) (1UL<<OFF(x))
#define LONG(x) ((x)/BITS_PER_LONG)
#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
#define N_EFFECTS 2
char* effect_names[] = {
"Spring Condition",
"Damping Condition"
};
int main(int argc, char** argv)
{
struct ff_effect effects[N_EFFECTS];
struct input_event play, stop;
int fd;
char device_file_name[64];
unsigned long features[4];
int n_effects; /* Number of effects the device can play at the same time */
int i;
printf("Force feedback test program.\n");
printf("HOLD FIRMLY YOUR WHEEL OR JOYSTICK TO PREVENT DAMAGES\n\n");
system("sleep 15");
strncpy(device_file_name, "/dev/input/event0", 64);
for (i=1; i<argc; ++i) {
if (strncmp(argv[i], "--help", 64) == 0) {
printf("Usage: %s /dev/input/eventXX\n", argv[0]);
printf("Tests the force feedback driver\n");
exit(1);
}
else {
strncpy(device_file_name, argv[i], 64);
}
}
/* Open device */
fd = open(device_file_name, O_RDWR);
if (fd == -1) {
perror("Open device file");
exit(1);
}
printf("Device %s opened\n", device_file_name);
/* Query device */
if (ioctl(fd, EVIOCGBIT(EV_FF, sizeof(unsigned long) * 4), features) == -1) {
perror("Ioctl query");
exit(1);
}
printf("Axes query: ");
if (test_bit(ABS_X, features)) printf("Axis X ");
if (test_bit(ABS_Y, features)) printf("Axis Y ");
if (test_bit(ABS_WHEEL, features)) printf("Wheel ");
printf("\nEffects: ");
if (test_bit(FF_SPRING, features)) printf("Spring ");
if (test_bit(FF_DAMPER, features)) printf("Damper ");
printf("\nNumber of simultaneous effects: ");
if (ioctl(fd, EVIOCGEFFECTS, &n_effects) == -1) {
perror("Ioctl number of effects");
}
printf("%d\n", n_effects);
/* download an condition spring effect */
effects[0].type = FF_SPRING;
effects[0].id = -1;
effects[0].u.condition[0].right_saturation = 0x7fff;
effects[0].u.condition[0].left_saturation = 0x7fff;
effects[0].u.condition[0].right_coeff = 0x2000;
effects[0].u.condition[0].left_coeff = 0x2000;
effects[0].u.condition[0].deadband = 0x0;
effects[0].u.condition[0].center = 0x0;
effects[0].u.condition[1] = effects[0].u.condition[0];
effects[0].trigger.button = 0;
effects[0].trigger.interval = 0;
effects[0].replay.length = 0; /* infinite seconds */
effects[0].replay.delay = 0;
if (ioctl(fd, EVIOCSFF, &effects[0]) == -1) {
perror("Upload effects[0]");
}
/* download an condition damper effect */
effects[1].type = FF_DAMPER;
effects[1].id = -1;
effects[1].u.condition[0].right_saturation = 0x7fff;
effects[1].u.condition[0].left_saturation = 0x7fff;
effects[1].u.condition[0].right_coeff = 0x2000;
effects[1].u.condition[0].left_coeff = 0x2000;
effects[1].u.condition[0].deadband = 0x0;
effects[1].u.condition[0].center = 0x0;
effects[1].u.condition[1] = effects[1].u.condition[0];
effects[1].trigger.button = 0;
effects[1].trigger.interval = 0;
effects[1].replay.length = 0; /* infinite seconds */
effects[1].replay.delay = 0;
if (ioctl(fd, EVIOCSFF, &effects[1]) == -1) {
perror("Upload effects[1]");
}
i=0;
play.type = EV_FF;
play.code = effects[i].id;
play.value = 1;
if (write(fd, (const void*) &play, sizeof(play)) == -1) {
perror("Play effect");
exit(1);
}
printf("Now Playing: %s\n", effect_names[i]);
play.type = EV_FF;
play.code = effects[i+1].id;
play.value = 1;
if (write(fd, (const void*) &play, sizeof(play)) == -1) {
perror("Play effect");
exit(1);
}
printf("Now Playing: %s\n", effect_names[i+1]);
/*
printf("Press CTRL + Z to exit\n");
*/
exit(0);}
***3. exit & save the new fftest.c.
***4. need to compile/make it now:
$ make
it gives some errors, but they dont seem to stop if from working. oh, i can't program by the way. i've done a bit of pascal at uni, but noting as complicated as whats in this file. but it seems to work. ;O)
***5. run it (see also step 12 above):
$ ./fftest
***6. run whatever racing game you like. the fftest program is on a 15 seconds delay you should notice it kick in. if this isn't enough time for your game or computer, just edit the line "system("sleep 15");" in the above source code and 'make' it again.
I'd like to make the centering force a bit stronger, but haven't got round to looking into that yet. also there's bit of a deadzone in the middle of my wheel; either the wheel is knackered or the centreing force needs to be greater. i'll probably try and do more with this once LFS S2 comes out.
the above method worked for me, i just wanted to pass it on.