/funkeymonkey

FunKeyMonkey is an efficient evdev/uinput wrangler with a plugin architecture

Primary LanguageC++BSD 2-Clause "Simplified" LicenseBSD-2-Clause

FunKeyMonkey

An efficient evdev/uinput wrangler with a plugin architecture.

Install

Standard CMake stuff:

mkdir build
cd build
cmake ..
make

Usage

  ./funkeymonkey [OPTION...] - A evdev/uinput wrangler

  -i, --device PATH            Input device to read from, eg.
                               /dev/input/event0, multiple can be provided
  -m, --match-devices PATTERN  Regular expression to match device strings
                               (format: ',,,')
                               with, matching will be read, multiple can be
                               provided
  -r, --roles ROLES            A comma-separated list of role numbers. Roles
                               will be assigned to devices in order of
                               definition, path-based first. Devices matching a
                               match-devices get one role.
  -p, --plugin PATH            Path to plugin
  -g, --grab                   Grab the input device, preventing others from
                               accessing it
  -v, --verbose                Print extra runtime information
  -d, --daemonize              Daemonize process
  -l, --list-devices           List available devices
  -X, --plugin-parameter ARG   Plugin parameter
  -h, --help                   Print help

Basics

FunKeyMonkey reads one or more evdev devices (basically any input device on a typical Linux setup) and relays their events to a plugin. Plugins are compiled separately and are provided to FunKeyMonkey on execution.

A plugin often creates one or more virtual input devices using uinput. The plugin then typically reacts to the real input events and generates virtual ones based them.

When running FunKeyMonkey, you may decide to "grab" the input device(s) to prevent any other program from reading them. This way, only the virtual input is visible.

Example use-cases

  • Implementing an Fn-key on non-full keyboards
  • Creating low-level keyboard macros
  • Faking device-specific input, like integrated control devices for development
  • Customizing keyboard controls for applications without built-in settings to do so

General advice

List available input devices with funkeymonkey -l:

# funkeymonkey -l
/dev/input/event0: 0,1,0,Power Button
...
/dev/input/event14: 1235,ab12,110,NES30              NES30 Joystick

You can test the desired device with with the libtestmodule.so to echo any input to the terminal:

# sudo ./funkeymonkey -g -i /dev/input/event14 -p libtestmodule.so
Successfully added device '/dev/input/event14'.
Init!
Event! 3 0 128 
...

Using the -g option ensures no other applications can listen directly to the chosen input device.

To match a device by metadata instead of a file path, use -m, for example -m keyboard would match any devices with "keyboard" in their name.

Device roles are used to differentiate between event sources inside a plugin. For example, you could want to have two separate keyboard inputs to your plugin. Specify your role number list with -r, for example -r 1,2 would give the first matched device role 1 and second matched device role 2. Devices are sorted with those given using -i first, those with -m second. For example, if you had -r 1,2,3 -m foo -i /dev/input/event0 -m bar, event0 would get role 1, any devices matching "foo" role 2 and any devices matching "bar" role 3. By default all devices have role 0.

Plugins can receive command line parameters through the -X option. They are used for example for specifying configuration files. These should be documented by plugins.

Notice you may need additional privileges in order to create uinput devices. Any modules that generate input events need this. Check your distribution documentation for details or run with root privileges. Your call.

To try if you have sufficient privileges for creating uinput devices, use libtoymodule.so with a keyboard (or other device that generates key events) as an input device. It creates a virtual keyboard that inserts "k" key presses after every keyboard key up event. It's annoying but very easy to notice.