kjscal - A Linux kernel module that provides automatic joystick calibration Contents: 1. Introduction 2. Setup 2.1. Compilation 2.2. Installation 2.3. Use 2.3.1. Module options 3. Internals 4. License 5. Authors 1. Introduction kjscal is a simple Linux kernel module that is based on the Linux kernel 2.6 input system. For each attached joystick, or joystick-like device, it creates a virtual joystick device with automatically calibrated axis. To achieve this, it uses the events it receives from the "real" joystick to determine what are the limits of its movement and then rescales the values it receives to provide full-scale movement for the software. Since it supports runtime recalibration, it can be used with unstable devices for which a fixed jscal command (e.g. in the boot/hotplug scripts) is just not sufficient. 2. Setup 2.1. Compilation To compile kjscal you need the configured sources of your kernel. In most cases the build process will detect them automatically and a simple call to `make' is all you need: # make If your kernel source tree was not detected, you have to set the KDIR Makefile variable. To build for a different kernel version you can set the KVER variable to your target kernel version. Note that write access to your kernel source tree may be needed to complete the compilation. To turn on additional debugging code you have to set DEBUG to 1 in the kjscal.c file and recompile kjscal. Note that this produces quite a bit of syslog output so it is not recommended for normal builds. 2.2. Installation The Makefile installs the kjscal module to the misc/ subdirectory of the default kernel modules directory, i.e. to: /lib/modules/$(KVER)/misc To change this you may specify the IDIR Makefile variable. Then give # make install as root to install the kernel module. Of course you can always copy the module by hand, but don't forget to run depmod afterwards. 2.3. Use To use kjscal, you have to load it on your running kernel. This can be done by typing (as root): # modprobe kjscal To have it automatically loaded on boot, you can insert the above command in your boot scripts. In some systems there is a file somewhere in /etc where the administrator can specify modules to be loaded on boot. Unfortunately there is no standard way to do this yet. If you wish to use any module options for kjscal, you will probably have to edit your /etc/modprobe.conf file to avoid specifying them in the modprobe command line. See the modprobe.conf(5) manual page to see how to do this. As soon as it is loaded, kjscal will dynamically attach to any joystick that is connected to the system. It will also detect any new joysticks at the moment they are plugged in and detach from unplugged devices. For every joystick it will create a new virtual joystick device with exactly the same features as the real one. The only difference is that the virtul joystick will have the events on each axis processed and normalised to the full value range. If you use the joydev/evdev interfaces (which you probably do use) you will probably have to look at /proc/bus/input/devices to find out which device is the virtual joystick and what device nodes it uses. If you have multiple joysticks then there is probably no other way to determine this information. In most Linux systems it is possible to create a hotplug/udev script which will automatically create symlinks (e.g. /dev/vjs0 -> /dev/js1) to make the use of the virtual joysticks easier. 2.3.1. Module options The following options can be used to tune kjscal's operation: - verbose=N (positive integer) This sets the verbosity level of the kjscal code. Higher values result in more output to the system logs. It defaults to 1 in debug builds. - ignore=N (positive integer) This instructs kjscal to completely ignore the first N events on each axis. It may be useful with devices that give out random values when plugged-in. The ignored events are not passed to the virtual device. The number of events to ignore will have to be determined with some experimentation, since each device produces events at different rates. Use this option only when necessary. - recal=N (positive integer) This enables the kjscal recalibration code, which causes kjscal to only use the last N events to determine the actual device range. Note that the recalibration process happens every N events, and not continuously. This option can be used with devices whose values drift through time causing the initial calculated range to become outdated. Note that smaller N values will case more frequent recalibration, but they may also result in kjscal not having the correct actual range of the device. Larger values are probably safer in this regard, but they may leave kjscal vulnerable to any drift effects of the hardware. Trial and error is probably the only way to determine a value for this option. Use this option only when necessary. - minrange=N (positive integer) This instructs kjscal to require at least 1/minrange coverage of the device's reported range to perform any normalisation and recalibration operations. This means that it will wait until the actual (received) range is at least 1/minrange of the reported device range before performing value normalisation. It will also delay the recalibration (when the recal option is used) if the new range does not satisfy this condition. The most common use of this option would be with joysticks that jump around values even when idle, which could cause the normalised values to jump all over the reported range and the recalibration routines to regularly reset the received range to incorrect values. Note that specifying minrange=1 is probably not useful, since it would require the actual range of the joystick to be equal to its reported one, which suggests a perfectly calibrated piece of hardware. - noskip=N (positive integer) This instructs kjscal to ignore events that differ from the last received value more than 1/noskip of the reported device range. It can be used to compensate partly for devices that every once in a while give out random values, confusing the calibration algorithms. Values around 10 or 12 should probably be enough, but your mileage may vary. noskip=1 is a no-op, unless your joystick returns events outside its reported range - there certainly is enough brain-damaged hardware out there. Note that noskip is applied only on axis with absolute range greater than skiprange (see below). Use this option only when necessary. - skiprange=N (positive integer) This option sets the maximum axis absolute range for which noskip will not be applied. It defaults to 2 to keep noskip from killing any hats on the joystick - hat axis move from -1 to 0 to +1, a 50% range movement that would normally trigger the noskip code. Please inform the kjscal author if you have to change this default for any reason. 3. Internals In short, kjscal assumes the place of both an input event handler and an input device driver. Then, for each joystick attached on the system, it will create a corresponding virtual device that will be regarded by both the kernel and the userspace as a regular joystick. All input events, apart from axis (ABS) ones, are passed through to the virtual device without change. The values of the ABS events, though, are used to compute the actual range of the joystick and are afterwards altered to cover its full reported range. In most cases the result will resemble a properly calibrated joystick. Currently a one-piece linear algorith is used to calculate the replacement values: (report_max - report_min) * (old_value - receive_min) new_value = ----------------------------------------------------- + report_min (receive_max - receive_min) For more details you can always read the kjscal source code, but you need some knowledge on the Linux input system to understand what happens in some parts. 4. License kjscal is released under the GNU General Public License version 2. The full text of the GPL is in the COPYING file that should be included in the kjscal distribution. 5. Authors Original author: Theodoros V. Kalamatianos