Page creation: 2009-11-25. Last update: 2009-11-27.
filter_evdev is a Linux C utility providing fine-grained custom sensitivity and acceleration for mice, touchpads, joysticks, or any input device. It can also remap buttons and keys such as inverting mouse buttons.
Licensed under WTFPL
The need of this program came from my experience with the RX-250 Logitech optical mouse which has firmware-level acceleration that cannot be disabled. Disliking mouse acceleration, I tried to counter this acceleration with X.org negative acceleration. That worked well enough on X.org 1.3, but X.org 1.6 seeming to support positive acceleration only I decided to act at a low level.
First, I tried to approximate the firmware algorithm with help of gnuplot. Second, I wrote a very simple user-space driver, translating accelerated evdev mouse offset events into normalized offsets.
I had learned that GNU/Linux input devices configuration is weak, so that I had to write a program to do something as simple as decelerating the mouse. That's why I transformed my simple program into a powerful input devices configuration utility and now share it with the Linux community.
Mice, keyboards, graphics tablets, joysticks, gamepads are all input devices, also known as HID devices.
Input devices can be represented as a set of buttons, keys, switches, sliders and axes. All these can be abstracted to three types of objects: Keys, relative axes and absolute axes. When the state of an object change it's perceived by the system as an event.
On 2.6 Linux kernels, input devices are exposed to user-space programs through the evdev character devices. These are device files usually stored in /dev/input/, with descriptions available in /proc/bus/input/devices.
This interface is independent of the low-level protocol such as PS/2, USB or gameport.
Evdev device files can be opened with open(2) and fixed-size event structures (16 bytes on i386) can be read from them.
An evdev structure contains four values, stored in this order.
The type of event as an integer symbolic constant:
When a continuous movement is recorded in an axis, reports are usually sent at a pre-defined rate. For example, 125 Hertz for a RX-250 Logitech mouse.
A relative integer value whose meaning depends on the event type.
Special EV_SYN events are sent after a set of events in order to indicate that they're simultaneous. Without that, a diagonal mouse displacement would appear as square stairs on screen.
This interface allows user-space programs to create evdev input devices that are exposed back to other user space programs as if it was a hardware device.
The user-space program opens the /dev/misc/uinput char device file (major 10, see /proc/misc for minor), configure it with ioctl, and then, write event structures to it.
Basically, it's a both an evdev client and an uinput client. It reads input from a specified evdev input device, creates a new input device whose name is derived from the source input device (it appends "+sensitivity" to the name) and send translated reports in the new input device.
Configuration consist of commands sent to a UNIX socket. All commands are executed for every set of simultaneous events received. Commands sent to the socket are recorded, until a "clear" command resets all configuration.
filter_evdev device socket
filter_evdev /dev/input/event8 /tmp/mouse_control
Events the physical input device are translated by filter_evdev and sent to the virtual input device. The name of the virtual input device is derived from the name of the physical input device, by appending "+sensitivity". e.g. "Logitech USB/PS/2 Optical Mouse+sensitivity".
Linefeed-terminated commands are sent to the UNIX socket to control filter_evdev translation behavior. The telfilter_evdev program does this job.
Currently, three command types are supported: Translation commands, commit command and clear command.
When sent to the socket, translation and commit commands are appended to the internal list of commands of filter_evdev, and executed everytime a set of simultaneous events is received.
Before any command is received, filter_evdev acts as a simple forwarding system. The virtual input device is a mirror of the physical input device.
REL_X REL_Y [0,5] * 2 commit REL_X remap REL_Y REL_Y remap REL_X
This multiplies by two any left, right up or down displacement less than 5 units, and swaps horizontal and vertical axes.
The commit commands is needed to make changes of the first line effective. Without it, the third and four lines commands would map the unchanged values.
command: <axis or key>* <range>? <operation>* <mapping command>* axis or key: <symbolic constant>|<type>/<code> symbolic constant: REL_* ABS_* KEY_* as defined in /usr/include/linux/input.h range: (+|-)?[ <float>?, <float>? ] operation: (+|-|*|>|<) <float> mapping command: (map|remap) <axis or key>|unmap type: integer code: integer
Every command has conditions: Axes or keys it applies to and values ranges the event values must match. Shortcut: You can use a single X or Y character instead of REL_X or REL_Y. Moreover, no whitespace is required between X and Y if both are specified.
If no sign prefix is specified for the range, it includes both the positive and negative ranges. If a range bound is not specified, it's taken as -infinity for the left bound, and +infinity for the right bound. If no range is specified, it's equivalent to [-infinity, +infinity]. If an event match a condition, its value gets the operations applied and then the mapping commands are executed on this value.
A mapping command assign a type and code to the computed value and generates the event. e.g. map REL_X map REL_Y
generates two events: One EV_REL/REL_X with the computed value, and another EV_REL/REL_Y with the same value.
By default, even without any mapping command, the axis or key is implicitly mapped to itself. The unmap command prevents this behavior.
remap <axis or key>
is equivalent to unmap map <axis or key>
.
The "commit" word appearing alone on a line.
Conditions and values used in computations are not updated until a "commit" command is met, so that, virtually, all commands in a sequence are executed at once.
The "clear" word appearing alone on a line.
This immediately resets all recorded commands, so that, the virtual input device become a simple mirror of the physical input device.
SIGINT, SIGTERM and SIGQUIT exit the program immediately. Both the physical and virtual input devices are closed.
None
None