Problem :
I have a USB joystick (Saitek Cyborg 3D) which shows up on my recently installed Ubuntu 9.04 box as /dev/input/js0
, and jstest
is showing values in the range +-32767 as I would expect. I just dug up a copy of FreeSpace Open, a game which uses SDL and worked with no problems on a previous Ubuntu install about a year ago, and the joystick seems very mis-calibrated. All axes (X, Y, twist, throttle) seem at least 20% off-center. The X and Y axes at least definitely aren’t reaching their end points.
A relevant message on the SDL mailing list in January 2009 received no concrete answers.
Here is joy-unix.cpp from the project source. I’m not quite running trunk, but as you can see from the revision log there, no actual code changes have happened to that file for over 3 years.
Solution :
I noticed the problem in d2x (a Descent port), which also uses SDL, so I went digging in SDL. testjoystick
from the SDL source showed the problem as well. Looking at the SDL linux joystick driver, the problem is mentioned. Search for joydev_pattern
in that file and you’ll see what they’re doing; search for calibrate
and they do mention this problem. Basically they use /dev/input/event6
(or whichever) in preference to /dev/input/js0
, unless compiled with --disable-input-events
, even knowing the event device can’t be calibrated (i.e. the calibration set on js0
will be ignored).
Having found all that, Google searches involving that configure
option reveal that hidden away in the comments to a Linux howto for fs2_open
, someone has actually had this problem already.
I have reported this bug to Ubuntu. To work around, pick any one of:
- Set
SDL_JOYSTICK_DEVICE=/dev/input/js0
(you could put this in/etc/environment
and reboot to apply it everywhere). Edit: SDL will still have theevdev
device as a second joystick, so in games liked2x
that respond to the second joystick as well by default, visit the options screen and remove those extra bindings. - Recompile libSDL with
--disable-input-events
. rmmod evdev
(quite likely to lose any unusual input devices you have).
Sounds like the game needs to be provided with the min/max/center axis values from the joystick. The default values might be 0/32768/65536 rather than -32676/0/32760 you’re seeing? That’s more obviously a lot more than 20% off, so maybe it’s trying to auto-calibrate at some point. It also looks like the joytest2
console command can show in-game values which might provide some added insight.
From joy_init()
:
// Fake a calibration
if (joy_num_sticks > 0) {
for (i=0; i<JOY_NUM_AXES; i++) {
joystick.axis_center[i] = 32768;
joystick.axis_min[i] = 0;
joystick.axis_max[i] = 65536;
}
}
I see a calibration function (joy_cheap_cal()
at joy.cpp:454
) but it’s not immediately obvious where that’s called from, or if there are other methods within the game for re-calibrating the axis values. I love Freespace, so when I get home I’ll download the code and poke around a bit. You might also try running jscal
just for good measure?