uinput-mapper
uinput-mapper is a program that can clone and remap (in clones) input devices to other (newly created) input devices (locally or over the network). It also offers a nice API to both the /dev/input/* and /dev/uinput devices in Python.
For any questions regarding a HGB project see: Contact
Quick Links:
Source: http://github.com/MerlijnWajer/uinput-mapper
Motivation
Initially we wrote this program to create two virtual joysticks from a single keyboard, which was really just two real arcade joysticks exposed over a keyboard. To be able to use these joysticks separately and to have SDL recognise them, I wrote a program with uinput to create two joystick devices. The program quickly evolved into uinput-mapper, a generalisation of the concept. The result is a set of command line utilities and python modules that allow you to remap all kind of input devices to new input devices. You can split and merge input devices, as well as write programs using the python modules to create "programmable" input devices.
uinput-mapper in distributions and other projects
uinput-mapper is available for Maemo 5 (for the N900 smartphone): http://maemo.org/packages/view/uinput-mapper/
uinput-mapper is available for Gentoo in the GrandTree overlay
uinput-mapper may soon be used by the xbian distribution for modifying their touchscreen inputs (http://forum.xbian.org/thread-832-page-7.html)
Source: http://github.com/MerlijnWajer/uinput-mapper
Features
- Clone input devices (create a new input device)
- Partially clone and remap input devices (to a new input device)
- Programmable configuration (in Python)
- Networked input (cloning/remapping) supported (requires openssh for secure networked input)
Usage
This section will discuss how to use uinput-mapper to easily create input devices from existing devices as input using the two uinput-mapper tools:
input-read: Read events from an input device
input-create: Create an input device and pass through events received from input-read
The idea in a nutshell:
input-read will read one (or several) input-devices to stdout. input-create will read from stdin and create a clone (or mapping) of the input presented.
input-read
input-read reads events from input devices. These usually reside in /dev/input/. input-read can read input events from any amount of input devices.
If you want to pass along events to input-create; start input-read with the -D flag and pipe the output to input-create; input-read will automagically detect the configuration of the passed input devices and pass those along to input-create as well. More on this later; at the input-create section.
To grab a device, pass the -G flag, followed by an input device. Grabbing a device is useful if you do not want other programs to interact / read from the input device.
Important: The order in which you pass input devices to input-read matters to input-create! Furthermore, any device passed with -G will be put after all the other input devices. Therefore, it is best to always put the input devices that you want to grab as the final arguments, like so:
input-read /dev/input/event1 /dev/input/event4 -G /dev/input/event2
Finally, the -C flag will marshall the events in such a way that is more compatible with other versions of python. It is only to be used with the -D option, but may be advisable if you run into problems.
$ input-read --help Usage: input-read /dev/input/event<0> ... /dev/input/event<N> Read input devices. Options: --version show program's version number and exit -h, --help show this help message and exit -D, --dump Dump will marshall all the events to stdout -v, --verbose Enable verbose mode (do not combine with -D) -G GRAB, --grab=GRAB -C, --compat Enable compatibility mode; for Python < 2.7
input-create
input-create reads events from stdin; typically events from input-read (with the -D flag). input-create will also recieve the initial device configuration from input-create. input-read reads all the keys that exported by all the input devices (and possible other properties) and passes these over stdout to input-create. By default, input-create will use this configuration, but it is very simple to modify the configuration.
A very basic example, simply cloning an input device:
1 ./input-read -D /dev/input/event3 | ./input-create
See uinput-mapper/Config for an detailed explanation of the configuration. Here we will only discuss the input-create options.
input-create by default takes no arguments, but if you wish to pass a configuration file, simply add it to the arguments.
If you used -C on input-read, you must also use -C on input-create. For the effect of -C, see the input-read section.
The -S flag will make input-create send synchronisation events to all newly created input-devices. This is particularly useful if you are creating multiple input devices from a single input device. If you run into problems where input-create is magically not sending events, use -S.
Usage: python create.py /path/to/config1 ... /path/to/configN Create input devices. Options: --version show program's version number and exit -h, --help show this help message and exit -C, --compat Enable compatibility mode; for Python < 2.7 -S, --sync Synchronise all events on an synchronise event -v, --verbose Enable verbose mode
Configuration
The configuration is done in Python, it is mostly a large dictionary but can be extended with function. The configuration can be quite simple, but it can also grow quite complex. See the config page for a full explanation on the configuration. For some quick examples, have a look at Use Cases with Configurations for possible configurations and use cases.
Troubleshooting
TODO: Add a lot more here. (Permission problems, sync problems, etc)
No events seem to be passed over the network.
Solution: Pass the compatibility flag to both input-read and input-create. (-C)
Future plans
- Document the pickle format; change it to JSON?
- Document the configuration in a better way, more than just examples.
- Improve configuration format for more functionality:
- Allow mapping one button to multiple buttons, based on a function result.
- Allow changing more than just the value of an event.
- Improve multiple input device support to allow reading from a set of
- devices rather than from each device explicitly.
- Extra list of keys(+type) that need to be exported? (Without a clear mapping)
- Think about callbacks, injection of events without a key being pressed?
- (This is currently possible, just not with configuration)
- Support for reading devices using the HID-API?
- Ignoring events
- Event Queue (Flush on Sync, etc) (Partially done)
- Implement/add a USB (gadgetfs) hid sink
Implement more high level classes for input and uinput
Support mapping of keys (Basic)
Support reading device info and events from stdin.
Support networked input
Support configuration (Basic)
Re-add Multiple input device support
Re-add Map to multiple devices support
Grab mode
Grab mode using the command line (Use -G /dev/input/eventX)
ABS properties
Add recording possiblity for input-read (to be used with input-replay)
Replaying(?) → input-replay (BETA)
Implementation in Python
Implementation of uinput-mapper in Python.
API: TODO: Document this properly
Linux input
Low level Python interface to Linux' "input.h".
Required for reading input event as well as the creation of aforementioned.
Features:
- Most useful IOCTL constants exported
- Most, if not all key constants exported.
- ctypes structures for input_event and input_id
Linux uinput
- Most useful IOCTL constants exported
- ctypes structure for user_input_dev
cinput
cinput combines the input and uinput modules and provides a higher level api.
Currently it exposes two classes:
InputDevice (For reading devices from /dev/input/)
- UInputDevice (For creating devices in /dev/input/ )
Screenshots
TODO: Screenshots of the new program