A utility for mapping events from Linux event devices.

Related tags

GUI evdev uinput
Overview

What is evsieve?

Evsieve (from "event sieve") is a low-level utility that can read events from Linux event devices (evdev) and write them to virtual event devices (uinput), performing simple manipulations on the events along the way. Examples of things evsieve can do are:

  • Remap certain keyboard keys to others;
  • Send some keyboard keys to one virtual device and other keyboard keys to another virtual device;
  • Turn a joystick into a virtual keyboard.

Evsieve is particularly intended to be used in conjunction with the evdev-passthrough functionality of Qemu. For other purposes, you may be better off using a higher-level utility than evsieve.

Examples of things that evsieve can achieve that are useful for evdev-passthrough are:

  • Keeping certain keys on the host while other keys are passed through to the guest;
  • Run scripts based on hotkeys even if your keyboard is passed through to the guest;
  • Remap another key to lctrl+rctrl, so you can use another key to attach/detach your keyboard to your VM;
  • Split the events over multiple virtual devices, possibly passing some of those devices to different VMs or keeping one of them on the host;
  • Remap keys on your keyboard on such a low level that even the guest OS can't tell the difference between real and mapped keys.

Evsieve is intended to make simple manipulations easy. It is not a tool for keyboard macro's or complex event manipulation. In case you want to do manipulations that are beyond the scope of evsieve, we recommend using the Python-evdev library instead.

Compilation

Compiling this program requires the Rust toolchain and the libevdev library. To install these dependencies:

  • Debian / Ubuntu: sudo apt install cargo libevdev2 libevdev-dev
  • Fedora: sudo dnf install cargo libevdev libevdev-devel
  • Arch Linux: sudo pacman -S rust libevdev

After you've installed the dependencies, you can obtain a copy of the source code and compile the program using:

wget https://github.com/KarsMulder/evsieve/archive/v1.2.0.tar.gz -O evsieve.tar.gz
tar -xzf evsieve.tar.gz && cd evsieve-1.2.0
cargo build --release

An executable binary can then be found in target/release/evsieve. You can either execute it as-is, or copy it to somewhere in your PATH for your convenience, e.g.:

sudo install -m 755 -t /usr/local/bin target/release/evsieve

The source code repository contains some files which were automatically generated. You can optionally regenerate these files before compilation. To regenerate these files, run the generate_bindings.sh script before running cargo build. This script requires the rust-bindgen tool to be installed on your system.

Usage: Basic concepts

Linux event devices are a tool the kernel uses to inform userspace applications (such as Xorg, Wayland) about input events such as keyboard presses, mouse movements. Event devices reside in /dev/input and usually have named symlinks pointed to them in /dev/input/by-id.

Event devices emit a stream of events. For example, when you press the A key on your key board, it will emit an (EV_KEY, KEY_A, 1) event, and when you release it it will emit an (EV_KEY, KEY_A, 0) event.

The quickest way to get an idea of how it works is to just look at it. You can either install the utility evtest (shipped by most major Linux distributions), run it as sudo evtest, select your keyboard/mouse/whatever and look at the events it emits, or run evsieve with the following arguments to see all events that are emitted on your computer:

sudo evsieve --input /dev/input/event* --print

Reading and writing

Evsieve is a command-line program designed to read and transform input events emitted by (real) event devices and write them to virtual event devices. It most likely needs to run as root for most features.

Assume you have a keyboard, and a symlink to its event device can be found at /dev/input/by-id/keyboard. A very basic usage of evsieve would be the following:

evsieve --input /dev/input/by-id/keyboard grab --output

In this example, evsieve will open the event device /dev/input/by-id/keyboard for exclusive read access (specified by the grab flag), read events from it, and write those same events to an unnamed virtual event device. This changes the flow of events from:

  • Keyboard → Kernel → Event Device → Xorg/Wayland → Applications

To:

  • Keyboard → Kernel → Event Device → Evsieve → Virtual Event Device → Xorg/Wayland → Applications

This has effectively accomplished nothing besides adding about 0.25ms of latency. However, if we add additional arguments to evsieve, we can use this construction to add, change, or suppress events. For example, the following script will turn the capslock into a second backspace:

evsieve --input /dev/input/by-id/keyboard grab \
        --map key:capslock key:backspace \
        --output

Since evsieve has opened your keyboard /dev/input/by-id/keyboard with exclusive access due to the grab flag, the userspace programs won't notice when you press capslock on your real keyboard. Evsieve will then read this capslock event, turn it into a backspace key event and write that to the virtual device, tricking userspace into thinking you just pressed the backspace button instead of the capslock button.

Evsieve actively maps events from the input devices to the output devices as long as evsieve runs. When evsieve exits, the virtual devices will be removed and any grabbed input devices will be released. You can exit evsieve by sending it a SIGINT or SIGTERM signal, for example by pressing Ctrl+C in the terminal where evsieve runs.

Take note that evsieve deals with events, not keys. This doesn't turn the capslock key into a backspace key, but rather turns every event associated with capslock into an event associated with backspace, e.g. a key_down for capslock is turned into a key_down for backspace, and a key_up event for capslock is turned into a key_up event for backspace. This distinction is important for some of the more advanced uses of evsieve.

Sequential event processing

The order of the arguments provided to evsieve matters. This is similar to how ImageMagick works and unlike the POSIX convention.

The --input argument reads events from the disk and generates a stream of events that will be processed by the arguments that come after. Each argument modifies the stream of events generated by previous argument. The --map arguments modify the stream of events by turning some events into other events. The --output argument consumes the events and writes them to a virtual event device.

In bash terms, you could think of all evsieve's arguments as if they were mini programs which have their outputs piped to each other. The previous script can be thought of as if it were something like the following:

# Note: this is not an actually valid evsieve script.
evsieve-input --grab /dev/input/by-id/keyboard | evsieve-map key:capslock key:backspace | evsieve-output

Due to performance concerns and some technical reasons, evsieve is not structured as a set of mini-programs but rather as a single monolithic process, but the idea is the same.

Usage: Examples

In this section we'll introduce the capabilities of evsieve through example scripts. All examples will assume that your keyboard can be found at /dev/input/by-id/keyboard and your mouse can be found at /dev/input/by-id/mouse. If you want to use these scripts, you need to replace these placeholder paths with the real paths to your keyboard and mouse.

All these scripts need to run with a certain amount of privileges. That usually means you'll need to execute them as root using sudo. If you want to put effort in making it run with more minimal permissions using ACLs, it is sufficient for most purposes to have evsieve run as a user with read/write access to /dev/uinput and all devices you try to open.

See which events are being emitted by your keyboard

evsieve --input /dev/input/by-id/keyboard --print

You can insert a --print argument at any point in your script to see which events are being processed by evsieve at that point. The events are printed the way they are seen by evsieve at that point; if you applied some maps or other transformations before the --print statement, then the events printed are the mapped events, not the original ones.

This is useful for debugging your scripts, and is also useful if you want to know what a certain key or button is called by evsieve. You can alternatively use the standard utility evtest (shipped by most major Linux distributions), which will provide a bit more detailed information using the Linux kernel's standard terminology.

Execute a script when some hotkey is pressed

evsieve --input /dev/input/by-id/keyboard \
        --hook key:leftctrl key:h exec-shell="echo Hello, world!"

You can execute a certain script when a certain key or combination of keys are pressed simultaneously using the --hook argument.

Each time the left control and the H key are pressed simultaneously, evsieve will execute the command echo Hello, world! using your OS' default POSIX shell, i.e. /bin/sh -c "echo Hello, world!". Note that the script will be executed as the same user as evsieve runs as, which may be root.

Since we did not need to modify the events and merely read them, there is no grab flag on the input device, causing evsieve to open it in nonexclusive mode. Since we didn't claim exclusive access to the device, there is no need to generate a virtual device using --output either.

In case some other program (such as Qemu) claims exclusive access to your keyboard and you still want to be able to listen to hotkeys, you can generate a virtual device and let Qemu claim access to the virtual device instead:

evsieve --input /dev/input/by-id/keyboard grab \
        --hook key:leftctrl key:h exec-shell="echo Hello, world!" \
        --output create-link=/dev/input/by-id/virtual-keyboard

This will generate a virtual device and create a link to it at /dev/input/by-id/virtual-keyboard, which you can pass to Qemu or whatever program demands exclusive access.

Remap your favourite key to lctrl+rctrl

evsieve --input /dev/input/by-id/keyboard grab \
        --map key:scrolllock key:leftctrl key:rightctrl \
        --output create-link=/dev/input/by-id/virtual-keyboard

In case you want to use Qemu evdev passthrough and use some other key than lctrl+rctrl to switch between guest and host, this is the second-easiest solution. (The easiest solution, of course, is using Qemu's built-in functionality for this purpose.)

Swap the control and the shift keys

evsieve --input /dev/input/by-id/keyboard grab    \
        --map yield key:leftctrl   key:leftshift  \
        --map yield key:leftshift  key:leftctrl   \
        --map yield key:rightctrl  key:rightshift \
        --map yield key:rightshift key:rightctrl  \
        --output

In previous examples, we mapped a single key using --map. In this example we do the same, except this time we also pass the yield flag to the --map arguments.

Remember that the output events of one argument are input events for the next argument. The --input argument emits a constant stream of events that are processed by all the maps until they encounter an --output event.

A first map like --map key:leftctrl key:leftshift could turn a control key event into a shift key event without problem. However, if the next argument were to naively be --map key:leftshift key:leftctrl, then the second map would turn the shift key event back into a control key—undoing the effect of the first map.

There are use cases where this behaviour is useful. For cases where it isn't, the --map argument accepts a yield flag. All events that are generated by a --map yield are considered "yielded" and will not trigger any further maps, nor any other arguments except for the --output argument. This prevents the shift event generated by the first map from getting turned back to a ctrl event by later maps.

Process two devices simultaneously

evsieve --input /dev/input/by-id/keyboard grab \
        --output                               \
        --input /dev/input/by-id/mouse grab    \
        --output

Evsieve is not restricted to a single input or output, and is also not restricted to only keyboards.

This results into two virtual devices, one virtual device for the keyboard event (created by the first --output) and a virtual device for all mouse events (created by the second --output). The keyboard arguments are not sent to the virtual mouse because no event in the event processing stream gets past the first --output argument.

It is also possible to map both the keyboard and the mouse to a single virtual hybrid key-mouse device in the following way.:

evsieve --input /dev/input/by-id/keyboard grab \
        --input /dev/input/by-id/mouse grab    \
        --output

Keeping certain keyboard keys on the host after passing a keyboard to the guest

evsieve --input /dev/input/by-id/keyboard grab \
        --output key:f9 key:f10 key:f11 key:f12 \
        --output create-link=/dev/input/by-id/virtual-keyboard

This example is useful for those who wish to do evdev passthrough using Qemu.

It is possible to specify event filters on --output arguments. By default an --output argument will take all events and write them to an output device, but if one or more filters are specified, then only events that match at least one of those filters will be written to that output device.

In this example, the first --output argument creates an unnamed virtual device, and writes all events related to the F9–F12 keys to it. Those events are then removed from the processing stream.

All events that were not removed by the first --output argument encounter the second --output argument, which applies to all events and sends them to a second virtual device which is linked to at /dev/input/by-id/virtual-keyboard.

You can then pass the latter device /dev/input/by-id/virtual-keyboard through to your virtual machine using evdev passthrough and keep the former unnamed device on the host. Now your host will still be able to receive the F9–F12 keys from the real keyboard while the majority of your keys are send to your VM through the latter keyboard.

Toggle events between two virtual devices

evsieve --input  /dev/input/by-id/keyboard domain=kb grab \
        --input  /dev/input/by-id/mouse    domain=ms grab \
        --hook   key:scrolllock toggle   \
        --map    key:scrolllock @host-kb \
        --toggle @kb @guest-kb @host-kb  \
        --toggle @ms @guest-ms @host-ms  \
        --output @host-kb create-link=/dev/input/by-id/host-keyboard   \
        --output @host-ms create-link=/dev/input/by-id/host-mouse      \
        --output @guest-kb create-link=/dev/input/by-id/guest-keyboard \
        --output @guest-ms create-link=/dev/input/by-id/guest-mouse

A somewhat more involved solution that's primarily useful for switching your input between the host and guest when doing evdev passthrough. This script reads your real keyboard and mouse, and creates two virtual devices for each of them.

By default, all events will be written to the guest-* devices, but by pressing the scrolllock key, you can change that to send write all of them to the host-* devices instead. Pressing scrolllock again with switch them back to the guest-* devices.

If you then pass the guest-* devices through to your virtual machine and leave the host-* devices on your host, then you can switch your input between your host and guest by pressing the scrolllock key. The scrolllock key is always sent to the host using --map so the LED indicator works properly.

You could also do something like passing both of the devices through to two different virtual machines, so you can toggle between both of the machines instead of toggling between host and guest. Of course, it is also possible to create more than two virtual devices per real device: just add more @something domains to the --toggles along with corresponding --outputs.

Explanation

Two new features are introduced in this script: the --toggle argument, and the concept of domains. A toggle is like a map, except that only one of the output keys is active at a time, and the active output key is switched every time a --hook toggle is triggered. An argument like --toggle key:a key:b key:c will by default map all A key events to B key events, but when a --hook toggle is triggered, it will start mapping them to C key events instead. Triggering a --hook toggle again will make the toggle go back to turning them into B key events.

In this script, we do not match events by type or code such as key:a, but instead by domains. In evsieve logic, all events have a domain attached to them. A domain is a string of text without any intrinsic meaning; they are not something that exists in the evdev protocol, but they are useful for writing evsieve scripts. Because the domain=kb clause was set on an input device, all events read from that device will have the domain kb attached to it.

A filter like @kb matches all events which have domain kb, just like a filter key:a matches all events with type EV_KEY and code KEY_A. The argument --toggle @kb @guest-kb @host-kb will take all events with domain kb and change their domain to guest-kb. When the --hook toggle is triggered, it will start changing their domain to host-kb instead.

Next, the output devices also filter by domain. There is one virtual output which will write all events with domain guest-kb to it, and another output which will write all events with domain host-kb to it. Thus, by changing the domains of events, this --toggle effectively decides to which virtual device the events will be written.

Advanced variations

In case you want a set/reset behaviour instead of toggle behaviour, i.e. one key that always switches to host and one key that always switches to guest, you can specify an index for the toggle, for example:

evsieve --input  /dev/input/by-id/keyboard domain=kb grab \
        --input  /dev/input/by-id/mouse    domain=ms grab \
        --hook   key:kpenter toggle=:1  \
        --hook   key:kpdot   toggle=:2  \
        --block  key:kpenter key:kpdot  \
        --toggle @kb @guest-kb @host-kb \
        --toggle @ms @guest-ms @host-ms \
        --output @host-kb create-link=/dev/input/by-id/host-keyboard   \
        --output @host-ms create-link=/dev/input/by-id/host-mouse      \
        --output @guest-kb create-link=/dev/input/by-id/guest-keyboard \
        --output @guest-ms create-link=/dev/input/by-id/guest-mouse

This uses the numpad's enter key to switch to the guest and the numpad's dot key to switch to the host. The --block argument drops all events matching one of the keys specified, so the numpad enter/dot are sent to neither host or guest.

You can go further and specify some exec=shell= clause on the hooks to execute a certain script whenever the input target changes. For example, if your monitor supports the DDC2 protocol, you may be able to use the ddcutil utility to change its input source every time you switch between host and guest:

evsieve --input  /dev/input/by-id/keyboard domain=kb grab \
        --input  /dev/input/by-id/mouse    domain=ms grab \
        --hook   key:kpenter toggle=:1 exec-shell="ddcutil setvcp 60 0x11" \
        --hook   key:kpdot   toggle=:2 exec-shell="ddcutil setvcp 60 0x0f" \
        --block  key:kpenter key:kpdot  \
        --toggle @kb @guest-kb @host-kb \
        --toggle @ms @guest-ms @host-ms \
        --output @host-kb create-link=/dev/input/by-id/host-keyboard   \
        --output @host-ms create-link=/dev/input/by-id/host-mouse      \
        --output @guest-kb create-link=/dev/input/by-id/guest-keyboard \
        --output @guest-ms create-link=/dev/input/by-id/guest-mouse

You may need to adjust the numbers involved depending on your monitor. Not all monitors have proper support for the DDC2 protocol and/or may refuse to listen to commands that do not come from its active input. Read the ddcutil manual for more information.

Control your mouse using your keyboard

evsieve --input /dev/input/by-id/keyboard \
        --input /dev/input/by-id/mouse grab domain=mouse \
        --map key:left:1~2      rel:x:-20@mouse \
        --map key:right:1~2     rel:x:20@mouse  \
        --map key:up:1~2        rel:y:-20@mouse \
        --map key:down:1~2      rel:y:20@mouse  \
        --map key:enter:0~1     btn:left@mouse  \
        --map key:backslash:0~1 btn:right@mouse \
        --output @mouse

This script will create a virtual mouse that moves with every key_down or key_repeat event on the arrow keys, and can left/right click with the enter/backslash keys. Keyboard to mouse mapping is not what evsieve was intended to be used for, but it works anyway to some extent.

A new feature in this script is value mapping. In previous scripts, when we saw an argument like --map key:a key:b it meant "turn any event of type EV_KEY, code KEY_A, any value, into an event of type EV_KEY, code KEY_B, with the same value". In this script, we're not only mapping the event type and code, but also the value.

The key rel:x:-20 means "an event with type EV_REL, code REL_X, value -20". The key key:left:1~ means "an event with type EV_KEY, code KEY_LEFT, value between 1 and 2", where the ~ denotes a range. Thus the map --map key:left:1~2 rel:x:-20 maps any event of type EV_KEY, code KEY_LEFT, value 1 or 2 to an event of type EV_REL, code REL_X, value -20. This effectively makes any key down (value 1) or key repeat (value 2) event on the left arrow key change the mouse's X axis with -20.

In the later map --map key:enter:0~1 btn:left you may notice that no value is specified for the output event. This means that it's value is taken to be the same as the input event, which conveniently maps a key down event (value 1) to a click event, and a key up event (value 0) to a release event.

Finally, all events with the domain mouse are written to a virtual device. This are all events generated by the real mouse and all events that were created by a map. Events generated by your real keyboard that didn't match any map will not be written to this virtual device. Note that there is no grab flag provided to the keyboard input, so evsieve will open the keyboard in nonexclusive mode, allowing other programs to read from it as well.

Map a controller to a virtual keyboard

If an application does not support controllers or joysticks but you want to control them with a controller or joystick anyway, you can use evsieve to turn your controller/joystick into a virtual keyboard.

Controllers are seen as joysticks by the Linux kernel. The good news is that they have event devices just like keyboards and can be processed by evsieve. The bad news is that the buttons on them do not tend to have sensible names or event codes, so the commands you need to map them tend to be cryptic and dependent on what controller you use.

Below are example scripts that create a virtual keyboard based on a DualSense or Xbox One controller. You can change which keyboard keys the controller buttons get mapped to as you please.

If you want to write a mapping script for some other controller or joystick, we recommend using the --print argument or the Linux utility evtest to discover which event codes are associated with the buttons on your controller.

DualSense controller:

evsieve --input /dev/input/by-id/usb-Sony_Interactive_Entertainment_Wireless_Controller-if03-event-joystick \
                                                \
        `# Directional pad`                     \
        --copy abs:hat0x:-1      key:left:1@kb  \
        --copy abs:hat0x:-1..0~  key:left:0@kb  \
        --copy abs:hat0x:1       key:right:1@kb \
        --copy abs:hat0x:1..~0   key:right:0@kb \
        --copy abs:hat0y:-1      key:up:1@kb    \
        --copy abs:hat0y:-1..0~  key:up:0@kb    \
        --copy abs:hat0y:1       key:down:1@kb  \
        --copy abs:hat0y:1..~0   key:down:0@kb  \
                                                \
        `# Shape buttons: circle, cross, square, triangle` \
        --copy btn:c             key:z@kb       \
        --copy btn:east          key:x@kb       \
        --copy btn:south         key:c@kb       \
        --copy btn:north         key:v@kb       \
                                                \
        `# Left pad`                            \
        --copy abs:z:38~..~37    key:j:1@kb     \
        --copy abs:z:~37..38~    key:j:0@kb     \
        --copy abs:z:~216..217~  key:l:1@kb     \
        --copy abs:z:217~..~216  key:l:0@kb     \
        --copy abs:rz:38~..~37   key:i:1@kb     \
        --copy abs:rz:~37..38~   key:i:0@kb     \
        --copy abs:rz:~216..217~ key:k:1@kb     \
        --copy abs:rz:217~..~216 key:k:0@kb     \
                                                \
        `# Right pad`                           \
        --copy abs:x:38~..~37    key:a:1@kb     \
        --copy abs:x:~37..38~    key:a:0@kb     \
        --copy abs:x:~216..217~  key:d:1@kb     \
        --copy abs:x:217~..~216  key:d:0@kb     \
        --copy abs:y:38~..~37    key:w:1@kb     \
        --copy abs:y:~37..38~    key:w:0@kb     \
        --copy abs:y:~216..217~  key:s:1@kb     \
        --copy abs:y:217~..~216  key:s:0@kb     \
                                                \
        `# Press left pad, press right pad`     \
        --copy btn:select        key:t@kb       \
        --copy btn:start         key:g@kb       \
                                                \
        `# Back buttons: LB, RB, LT, RT`        \
        --copy btn:west         key:q@kb        \
        --copy btn:z            key:e@kb        \
        --copy abs:rx:~50..51~  key:u:1@kb      \
        --copy abs:rx:51~..~50  key:u:0@kb      \
        --copy abs:ry:~50..51~  key:o:1@kb      \
        --copy abs:ry:51~..~50  key:o:0@kb      \
                                                \
        `# Special buttons: create, start, PlayStation, touch pad, microphone` \
        --copy btn:tl2           key:y@kb       \
        --copy btn:tr2           key:enter@kb   \
        --copy btn:mode          key:esc@kb     \
        --copy btn:thumbl        key:n@kb       \
        --copy btn:thumbr        key:m@kb       \
                                                \
        --output @kb repeat

Xbox One controller:

evsieve --input /dev/input/by-id/usb-Microsoft_Controller_*-event-joystick \
                                                      \
        `# Directional pad`                           \
        --copy abs:hat0y:-1            key:up:1@kb    \
        --copy abs:hat0y:-1..0~        key:up:0@kb    \
        --copy abs:hat0y:1             key:down:1@kb  \
        --copy abs:hat0y:1..~0         key:down:0@kb  \
        --copy abs:hat0x:-1            key:left:1@kb  \
        --copy abs:hat0x:-1..0~        key:left:0@kb  \
        --copy abs:hat0x:1             key:right:1@kb \
        --copy abs:hat0x:1..~0         key:right:0@kb \
                                                      \
        `# Letter buttons: A, B, X, Y`                \
        --copy btn:south               key:z@kb       \
        --copy btn:east                key:x@kb       \
        --copy btn:north               key:c@kb       \
        --copy btn:west                key:v@kb       \
                                                      \
        `# Left pad`                                  \
        --copy abs:x:~23169..23170~    key:d:1@kb     \
        --copy abs:x:23170~..~23169    key:d:0@kb     \
        --copy abs:x:-23169~..~-23170  key:a:1@kb     \
        --copy abs:x:~-23170..-23169~  key:a:0@kb     \
        --copy abs:y:~23169..23170~    key:s:1@kb     \
        --copy abs:y:23170~..~23169    key:s:0@kb     \
        --copy abs:y:-23169~..~-23170  key:w:1@kb     \
        --copy abs:y:~-23170..-23169~  key:w:0@kb     \
                                                      \
        `# Right pad`                                 \
        --copy abs:rx:~23169..23170~   key:l:1@kb     \
        --copy abs:rx:23170~..~23169   key:l:0@kb     \
        --copy abs:rx:-23169~..~-23170 key:j:1@kb     \
        --copy abs:rx:~-23170..-23169~ key:j:0@kb     \
        --copy abs:ry:~23169..23170~   key:k:1@kb     \
        --copy abs:ry:23170~..~23169   key:k:0@kb     \
        --copy abs:ry:-23169~..~-23170 key:i:1@kb     \
        --copy abs:ry:~-23170..-23169~ key:i:0@kb     \
                                                      \
        `# Press left pad, press right pad`           \
        --copy btn:thumbl              key:t@kb       \
        --copy btn:thumbr              key:g@kb       \
                                                      \
        `# Back buttons: LB, RB, LT, RT`              \
        --copy btn:tl                  key:q@kb       \
        --copy btn:tr                  key:e@kb       \
        --copy abs:z:~203..204~        key:u:1@kb     \
        --copy abs:z:204~..~203        key:u:0@kb     \
        --copy abs:rz:~203..204~       key:o:1@kb     \
        --copy abs:rz:204~..~203       key:o:0@kb     \
                                                      \
        `# Special buttons: start, select, Xbox button` \
        --copy btn:start               key:enter@kb   \
        --copy btn:select              key:space@kb   \
        --copy btn:mode                key:esc@kb     \
                                                      \
        --output @kb repeat

The major new feature used in these scripts are transitions: a transition like ~216..217~ matches an event with a value of 217 or greater, provided that the last event with the same type and code had a value of 216 or less. These transitions are useful for detecting when an absolute axis event goes over or under a certain threshold.

The chosen thresholds determine how far you need to move a stick or trigger to make them cause a keyboard event. You can adjust them to make the maps more or less sensitive to small movements.

You may further notice that these scripts use the --copy argument instead of --map. The --copy and --map arguments are identical with one difference: source events matching a --map are removed from the processing stream, but those matching --copy are not. In these scripts --copy is used because it might be theoretically possible that e.g. a abs:hat0x:-1 event gets followed up by a abs:hat0x:1 event, which should simultaneously release the left key and press the right key.

The repeat flag makes the virtual keyboard emit key repeat events if a button is held down, like a keyboard does, even though the controllers do not emit repeat events themselves. Since most applications that read event devices ignore repeat events anyway, this clause isn't very important.

Change your keyboard layout on an evdev level

It is probably better to change your keyboard layout by changing your OS settings, but if that isn't possible for some reason, it is possible to use evsieve to map every key to its corresponding key on your favourite keyboard layout. For example, the following script will map the Qwerty keys to Colemak:

evsieve --input /dev/input/by-id/keyboard grab \
        --map yield key:e key:f \
        --map yield key:r key:p \
        --map yield key:t key:g \
        --map yield key:y key:j \
        --map yield key:u key:l \
        --map yield key:i key:u \
        --map yield key:o key:y \
        --map yield key:s key:r \
        --map yield key:d key:s \
        --map yield key:f key:t \
        --map yield key:g key:d \
        --map yield key:j key:n \
        --map yield key:k key:e \
        --map yield key:l key:i \
        --map yield key:n key:k \
        --map yield key:p key:semicolon \
        --map yield key:semicolon key:o \
        --map yield key:capslock key:backspace \
        --output

Usage: In detail

In this section, we'll provide comprehensive documentation about all the arguments evsieve accepts.

Maps

The --map and --copy arguments have the following basic syntax:

    --map  SOURCE_EVENT [TARGET_EVENT...] [yield]
    --copy SOURCE_EVENT [TARGET_EVENT...] [yield]

A map triggers every time an event matching the SOURCE_EVENT is generated by a physical device, and then generates event(s) matching all TARGET_EVENT(s) specified.

When a source event triggers a --map, it is removed from the processing stream and will not trigger any further arguments. The --copy argument has the same syntax and semantics as --map with the single difference being that source events that trigger --copy are not removed from the processing stream.

If a target event is not fully specified (e.g. it specifies a keycode but not a value), all missing details of the target event shall be taken to be the same as those of the source event. If zero target events are specified on a --map, then the source event is removed from the processing stream and no new events are added.

Key format

Keys can be provided to the --map arguments. They use the same form for both the input event and output events. They have the form

    event_type:event_code:event_value@domain

For more information about the "@domain" part, see the "Domains" section below. We will first talk about the type, code, and value.

Most parts are optional. If formal format, all parts between [] are optional:

    [event_type:event_code[:event_value]][@domain]

Any part that is not specified will be interpreted to mean "any" for source events. For example:

    ""              # The empty string matches any event
    key:a           # Matches any event with type EV_KEY, code KEY_A
    key:a:1         # Matches any event with type EV_KEY, code KEY_A, value 1 (down)
    key:a@keyboard  # Matches any event with type EV_KEY, code KEY_A with domain "keyboard"
    @keyboard       # Matches any event with domain "keyboard"   

For output events, any part that is not specified will be interpreted as "same as the source event". For example:

    --map key:a   key:b    # Will map any EV_KEY, KEY_A event to a EV_KEY, KEY_B event with the same event value.
    --map key:a:1 key:b:0  # Will map any EV_KEY, KEY_A, value=1 event to a EV_KEY, KEY_B, value=0 event.
    --map key:a   ""       # Will map any EV_KEY, KEY_A event to an identical event.

The value for input events may also be expressed as an (optionally bounded) range. For example:

    key:a:1~2        # Matches any event with type EV_KEY, code KEY_A, a value of 1 (down) or 2 (repeat)
    abs:x:10~50      # Matches any event with type EV_ABS, code ABS_X, a value between 10 and 50
    abs:x:51~        # Matches any event with type EV_ABS, code ABS_X, a value of 51 or higher

No ranges may be specified for the values of the output events, they can only be concrete values such as "1" or be left unspecified.

Furthermore, when matching an input event, it is possible to specify a transition of values. If a transition is specified, then a certain event only matches if its value lies in the specified range and the value of the previous event with the same type and code from the same input device also lies within a certain range. For example:

    key:a:1..2       # Matches an A key event with value 2 (repeat),
                     # if the last A key event had value 1 (down).
    abs:x:~50..51~   # Matches an X axis event with a value of 51 or greater,
                     # provided that the previous X axis value was 50 or less.

Ranges and transitions are particularly useful for mapping absolute events to key events. For example, the following maps will press the A key when the X axis goes over 200, and releases the key when it goes under it:

    --map abs:x:~199..200~ key:a:1
    --map abs:x:200~..~199 key:a:0

Key names

All names that evsieve uses for events are derived from the names used by the Linux kernel for such events, using a fairly systematic way that's understood most quickly by looking at the following examples:

    EV_KEY, KEY_A -> key:a
    EV_REL, REL_X -> rel:x
    EV_ABS, ABS_X -> abs:x
    EV_KEY, KEY_LEFTCTRL -> key:leftctrl
    EV_REL, REL_WHEEL_HI_RES -> rel:wheel_hi_res

In case you're wondering what the kernel calls a certain button on your device, we recommend using the third-party program evtest, which is probably shipped by your favourite distribution.

There is one notable exceptions to the above scheme. There are events with type EV_KEY and a code of form BTN_*. These are called btn:something by evsieve even though though there is no EV_BTN event type. For example:

    EV_KEY, BTN_RIGHT -> btn:right
    EV_KEY, BTN_NORTH -> btn:north

Domains

Domains are not something that exists according to the evdev protocol, they are merely a tool invented by evsieve to help you write advanced maps. Domains are strings of text. Any event being processed by evsieve has a domain attached to it. This domain can be specified using the domain= clause on an --input argument, otherwise the domain of an event is set to the path to the input device that emitted said event.

You can specify a domain on a map source or target by adding @domain after the rest of the key. For example, a source of key:a@my-domain means "any event with type EV_KEY, code KEY_A and domain my-domain". If no domain is specified on a source, it will be interpreted as "any domain". If a domain is specified on a target, then the generated event will have that domain. If no domain is specified on a target, the generated event will have the same domain as the source event.

If the part before the @ is empty, then it will be interpreted as "any event with this domain", for example --map @foo @bar will turn any event with domain foo into the same event with domain bar. This is particularly handy for output devices: --output @foo will write all events with domain foo to a virtual device and leave the other events untouched.

The yield flag

It is possible to add the yield flag to an --map or --copy argument, for example:

    --map yield key:a key:b

The position of the yield flag does not matter. All events generated by a --map yield or --copy yield will not be processed by any further maps, copies, hooks, toggles, blocks, or any other kind of argument except for --output. For example, the following arguments will transpose the A and B keys:

    --map yield key:a key:b \
    --map yield key:b key:a \

If yield was not provided here, then the second map would turn any B-key events generated by the first map back into A-key events.

If a yield flag is provided to a --copy argument, then source events matching the --copy argument are not yielded, only the generated events are. For example, the following arguments will turn the A key into a B+C key.

    --copy yield key:a key:b \
    --map key:a key:c \
    --map key:b key:d \

The --block argument

The --block arguments have the form:

    --block [SOURCE_EVENT...]

The --block argument takes a list of event filters with the same format as the source events for --maps. All events that match one of the filters provided will be removed from the processing stream. For example, the following argument will drop all events related to the A or B keys:

    --block key:a key:b

Using --block is equivalent to using maps that generate zero output events; the above argument would have the same effect as --map key:a --map key:b.

If no source events are specified, the --block argument will drop all events from the processing stream.

Toggles

The --toggle argument has the following basic syntax:

    --toggle SOURCE_EVENT TARGET_EVENT... [id=ID] [mode=consistent|passive]

Toggles work the same way as --maps do, with one difference: a --map will map each source event to all of its target events, whereas a --toggle will map each source events to only one of its target events. The target event it gets mapped to is called the "active target".

The first target listed becomes the active target when the program starts. The active target can be changed using a --hook with a toggle clause. For more information, see the "Toggles" subsection under the "Hooks" section.

An optional id= clause can be specified to give this --toggle a name. This ID can be used to modify specific toggles in the --hook toggle= clause. No two toggles may have the same ID.

Modes

There are two modes of operation for toggles: consistent and passive. The mode of operation can be chosen by supplying a mode= clause to a --toggle argument. If no mode is specified, then "consistent" will be chosen by default.

The easiest mode to understand is "passive". If mode=passive is specified on a toggle, then all source events will be mapped to the currently active target event, no exceptions. However, this mode of operation can introduce some unexpected issues. For example, consider the following argument:

    --toggle key:a key:b key:c mode=passive \
    --hook key:z toggle

Suppose the user presses the A key. Then a B key down event will be generated. Now suppose the user presses the Z key before releasing the A key. When the user releases the A key, the A key up event will be mapped to a C key up event, which results in the B key being stuck in a key_down state.

To address this problem, mode=consistent exists. If a toggle operates in consistent mode, then for every key it will remember which target was active when it received a key_down event of that key, and and will then map all events related to that key to that target until a key_up event of that key is received, even if the active target changed in the meanwhile. In the above example, this ensures that an A key up event is mapped to a B key up event event if the active target was changed.

Hooks

The --hook argument has the following basic syntax:

    --hook KEY... [exec-shell=COMMAND]... [toggle[=[ID][:INDEX]]]...

Hooks take actions upon events, but do not modify events. An example of such an action is executing a certain script. The following hook will print "Hello, world!" every time lctrl+A is pressed:

    --hook key:a key:leftcontrol exec-shell="echo Hello, world!"

One or more KEYs can be specified. The syntax for specifying the keys that trigger the hook is the same as the one used to match events for maps, but the semantics are different. The simple explanation of KEYs is that the hook will trigger whenever all those keys are held down simultaneously, and that is probably all you need to remember about them.

In detail: key format

As said, the syntax is the same as the syntax used for maps, but the semantics are different. These semantics are intended to facilitate writing hooks that trigger when a certain combination of keys such as lctrl+A is pressed. First, if no event value is specified for a key, then the value is interpreted to be "1~". Thus, the above example is equivalent to:

    --hook key:a:1~ key:leftcontrol:1~ exec-shell="echo Hello, world!"

Formally said, the hook triggers when (1) an event is received that matches one of the KEYs specified, (2) the last event whose type, code and domain matched that same KEY did not have a value matching that KEY, and (3) for all other KEYs, the last event whose type, code and domain matched those KEYs had a value matching those KEYs.

It is not possible to specify transitions in these KEYs, e.g. --hook key:a:1..0 will throw an error.

Exec-shell

If an exec-shell clause is specified, then a certain command will be executed using the system's default POSIX shell (/bin/sh). Thus, if exec-shell="echo Hello, world!" is specified, the following will be executed:

    /bin/sh -c "echo Hello, world!"

This will be executed as the same user that evsieve is running as, which may be root. If you want to run it as another user, you can make sudo -u $USER part of the command.

The command is executed asynchronously, which means that the processing of events will not halt until the command's execution has completed. In case the command takes sufficiently long to complete and the user presses keys sufficiently fast, it may be possible to trigger the hook again before the command's execution has finished, which will lead to multiple copies of the command being executed simultaneously.

Any processes spawned by exec-shell that are still running when evsieve exits will be sent a SIGTERM signal. This is may change in future versions of evsieve.

Toggles

Hooks are capable of modifying the active target of --toggle arguments specified elsewhere in the script. Any hook can modify any toggle, it doesn't matter whether the --hook or the --toggle argument was specified first, e.g. the following two orders are functionally identical:

    # Order 1
    --hook key:leftctrl toggle \
    --toggle @source @target-1 @target-2

    # Order 2, functionally identical to Order 1
    --toggle @source @target-1 @target-2 \
    --hook key:leftctrl toggle

If a toggle flag is specified on a hook, then all toggles specified anywhere in the script will have their active target moved to the next one, wrapping around. The above example maps all events with domain source to domain target-1 by default. Once the lctrl key is pressed, they will start mapping the events to target-2 instead. By pressing lctrl again, they will start mapping the events to target-1 again.

It is also possible to specify a toggle clause, using the syntax:

    --hook toggle=[ID][:TARGET]

Both the ID and the TARGET are optional. If an ID is specified, then only the --toggle with the matching ID will be affected. For example, the following hook will affect the first toggle but not the second:

    --toggle @source-1 @target-1 @target-2 id=first-toggle \
    --toggle @source-2 @target-1 @target-2 id=second-toggle \
    --hook key:leftctrl toggle=first-toggle

By default, the active target is always moved to the next one in the list. It is also possible to move the active target to a specific one by providing a numerical index for TARGET, for example:

    --toggle @source-1 @target-1 @target-2 id=first-toggle \
    --toggle @source-2 @target-1 @target-2 id=second-toggle \
    --hook key:leftctrl toggle=first-toggle:1 \
    --hook key:rightctrl toggle=:2 \

This will move the active target to the first one (@target-1) for first-toggle when lctrl is pressed, and move the active target to the second one (@target-2) for all toggles when rctrl is pressed.

Inputs

The --input argument has the following basic syntax:

    --input PATH [PATH...] [domain=DOMAIN] [grab[=auto|force]]

At least one path to a device to open is mandatory, everything else is optional. All paths must be represented in absolute form, i.e. starting with a "/" character. It is possible to provide more than one path, in which case multiple devices will be opened with a single argument.

If the domain= clause is provided, then all events read from this input device will have the specified domain attached to them, otherwise the domain of those events shall be equal to the path of said input device. Domains have no intrinsic meaning, but are useful for writing maps. See the "Key format" section under "In detail: Maps" for more information.

Grab modes

Using the grab clause, it is possible to "grab" an input device, by which evsieve will claim exclusive reading access to said device and prevent other programs from reading from that device. This will prevent the X server and similar programs from acting upon the events generated by said device.

Evsieve has two different modes of grabbing a device, auto and force. If merely the grab flag is specified, it will be interpreted as grab=auto. If no grab flag or clause is specified, the input device will not be grabbed.

The two modes differ only in when the input device is grabbed. Under the force mode, evsieve will immediately grab the event device as soon as evsieve starts. Under the auto mode, evsieve will not grab the device until no keys are in the "down" state.

Depending on your use case, there may be an annoying issue with the force mode: if you start evsieve from a terminal by typing in a command or scriptname and then press enter, evsieve will probably grab your device before you release the enter key, causing the terminal/X server to not see you release the enter key and treat it as stuck in the key_down state. The auto mode solves this by not actually grabbing your device until the enter key (and all other keys) are released.

The auto mode is considered the default mode because it has the least potential for surprises. However, if evsieve does refuses to grab your device because some key is permanently stuck in the down state for some reason, you may want to specify grab=force.

There are some questions left surrounding the design of the auto mode, so it is possible that its behaviour will change in future versions of evsieve.

Outputs

The basic syntax for the --output argument is:

    --output [EVENTS...] [create-link=PATH] [name=NAME] [repeat[=enable|disable|passive]]

The --output argument creates a virtual event device and sends events to it. If the --output argument is specified multiple times, a different virtual device will be created for each argument.

By default, all events that reach the --output argument will be sent to its virtual device, but it is possible to specify a filter to send only some of the events events that reach it. Any event that get sends to an output device is removed from the evsieve processing stream, e.g. in the following example:

evsieve --input /dev/input/by-id/keyboard \
        --output \
        --output

All events generated by the --input argument will be written to a virtual device created by the first --output argument. No events will reach the second output argument because all events have already been consumed by the first.

It is possible to create a filter upon which events to send to an output device by specifying the EVENTS part. The syntax used for matching these EVENTS is the same as the one used by the --map argument, see the "Maps" section above. If zero EVENTS are specified, all events will be written to the output device. If one or more EVENTS are specified, only events matching at least one of the EVENTS are written to the output device. For example:

evsieve --input /dev/input/by-id/keyboard \
        --output key:a key:b \
        --output

This script will write all events relating to the A or B keys to the first output device, and all other events to the second output device.

Symlinks

It is possible to ask evsieve to create a symlink to the device created by an --output by specifying the --create-link= part. For example, --output create-link=/dev/input/by-id/my-virtual-device will create a symlink at /dev/input/by-id/my-virtual-device that points to the actual event device node. The actual event device node will probably have an unpredictable name of /dev/input/event__ where __ is an arbitrary number.

It is customary for links to event devices to reside in /dev/input/by-id/, but this is by no means a requirement. You can create a link anywhere you want (as long as evsieve has write permission to the directory where you put it). Note that putting links in /dev/input/by-id/ requires root privileges on most distributions, so if you want to run evsieve with less privileges, you may want to put your links elsewhere.

Evsieve will create the link when it starts, and try to remove the link when it exits. Note that there are circumstances under which evsieve may be unable to clean up the link it created, such as when evsieve is SIGKILL'd or in case of unexpected power loss. In such cases you may end up with a dangling symlink on your filesystem.

In case a symlink already exists at the path you provided to create-link=, evsieve will overwrite that link. This behaviour has been chosen to not make any scripts involving evsieve mysteriously break after an unexpected power loss.

Names

A name for the device can be specified using the name= clause, e.g.:

    --output name="My keyboard"

If no name is specified, then Evsieve Virtual Device is chosen by default. The device name is usually of little consequence, but some third-party tools may care about it. For example, the evtest utility is able to display the device name.

Repeats

Some devices, like most keyboards, will send repeat events when a key or button is held down. These are events with type EV_KEY and value 2. Most applications ignore these repeat events and use their own internal logic to detect keys that are held down, but for correctness' sake, evsieve is capable of handling them.

Repeat events are read from input devices if input devices emit them and processed just like any other event. There are three things an output device can do when it receives repeat events:

  • If repeat=passive is set on an --output device, then all repeat events that reach this --output argument will be written to this device;
  • If repeat=disable is set on an --output device, then all repeat events that reach this --output argument will be dropped;
  • If repeat=enable is set on an --output device, then all repeat events that reach this --output argument will be dropped, but the kernel will be asked to automatically generate repeat events for this device.

If no repeat= clause is specified, then repeat=passive will be chosen by default. If a repeat flag is specified without a mode, then repeat=enable is chosen.

Prints

The basic syntax for the --print argument is:

    --print [EVENTS...] [format=default|direct]

The --print arguments prints all events in the event processing stream to stdout. It does not modify the event processing stream. This is mostly useful for debugging your scripts and for discovering what evsieve calls certain events.

It prints the events the way they are seen by evsieve at the point where the --print argument is placed. For example, the following script will print key:b events when the A key is pressed:

evsieve --input /dev/input/by-id/keyboard \
        --map key:a key:b \
        --print

The optional EVENTS can be a filter for events that you want to print, similar to the EVENTS in the --output argument. For example, --print @foo will only print events that have domain foo. If no filter is specified, all events are printed.

Formats

The format= clause can specify how the events should be printed, and can choose between format=default and format=direct. If no format= clause is specified, format=default shall be assumed.

The default formatter prints events in a human-readable way, for example:

Event:  type:code = key:a          value = 1 (down)    domain = /dev/input/by-id/keyboard

If you specify format=direct, then it will print the events using evsieve's standard key format that's also used for maps and other arguments, for example:

key:a:1@/dev/input/by-id/keyboard

Beware: --print is intended for human readers, not for scripts. Even if format=<something> is specified, evsieve makes absolutely no guarantees about how the events are printed. Future versions of evsieve may change the format of the printed events without warning. It is not recommended to attempt to programmatically parse the output of evsieve.

License

Most of the content on this repository is licensed under the GPLv2 or later, though the repository does contain some files derived from third-party content with a different license, including some content indirectly derived from Linux kernel headers which, depending on legal interpretation, may or may not effectively render the program GPLv2 only. To the extent of our knowledge, all content on this repository is compatible with the GPLv2. See the COPYING file for more information.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

Comments
  • Cross Build evsieve for Alpine

    Cross Build evsieve for Alpine

    I attempted to cross build evsieve for Alpine but I get this error instead.

    These are the steps that I did for the build.

    1. apt-get install -y --no-install-recommends libevdev2 libevdev-dev wget musl-tools make g++ libc6-dev
    2. wget https://github.com/KarsMulder/evsieve/archive/v1.3.1.tar.gz -O evsieve-1.3.1.tar.gz
    3. tar -xzf evsieve-1.3.1.tar.gz && cd /evsieve-1.3.1
    4. rustup target add arm-unknown-linux-musleabihf
    5. cargo build -vv --target arm-unknown-linux-musleabihf --release

    Here are the build logs. Error message is at the end

     Downloading crates ...
      Downloaded lazy_static v1.4.0
      Downloaded libc v0.2.82
       Compiling libc v0.2.82
       Compiling evsieve v1.3.1 (/evsieve-1.3.1)
       Compiling lazy_static v1.4.0
         Running `CARGO=/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/bin/cargo CARGO_CRATE_NAME=build_script_build CARGO_MANIFEST_DIR=/usr/local/cargo/registry/src/github.com-1285ae84e5963aae/libc-0.2.82 CARGO_PKG_AUTHORS='The Rust Project Developers' CARGO_PKG_DESCRIPTION='Raw FFI bindings to platform libraries like libc.
    ' CARGO_PKG_HOMEPAGE='https://github.com/rust-lang/libc' CARGO_PKG_LICENSE='MIT OR Apache-2.0' CARGO_PKG_LICENSE_FILE='' CARGO_PKG_NAME=libc CARGO_PKG_REPOSITORY='https://github.com/rust-lang/libc' CARGO_PKG_VERSION=0.2.82 CARGO_PKG_VERSION_MAJOR=0 CARGO_PKG_VERSION_MINOR=2 CARGO_PKG_VERSION_PATCH=82 CARGO_PKG_VERSION_PRE='' LD_LIBRARY_PATH='/evsieve-1.3.1/target/release/deps:/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib:/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib' rustc --crate-name build_script_build /usr/local/cargo/registry/src/github.com-1285ae84e5963aae/libc-0.2.82/build.rs --error-format=json --json=diagnostic-rendered-ansi,future-incompat --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debug-assertions=off --cfg 'feature="default"' --cfg 'feature="std"' -C metadata=1e8fe370016abd8d -C extra-filename=-1e8fe370016abd8d --out-dir /evsieve-1.3.1/target/release/build/libc-1e8fe370016abd8d -L dependency=/evsieve-1.3.1/target/release/deps --cap-lints warn`
         Running `CARGO=/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/bin/cargo CARGO_CRATE_NAME=lazy_static CARGO_MANIFEST_DIR=/usr/local/cargo/registry/src/github.com-1285ae84e5963aae/lazy_static-1.4.0 CARGO_PKG_AUTHORS='Marvin Löbel <[email protected]>' CARGO_PKG_DESCRIPTION='A macro for declaring lazily evaluated statics in Rust.' CARGO_PKG_HOMEPAGE='' CARGO_PKG_LICENSE=MIT/Apache-2.0 CARGO_PKG_LICENSE_FILE='' CARGO_PKG_NAME=lazy_static CARGO_PKG_REPOSITORY='https://github.com/rust-lang-nursery/lazy-static.rs' CARGO_PKG_VERSION=1.4.0 CARGO_PKG_VERSION_MAJOR=1 CARGO_PKG_VERSION_MINOR=4 CARGO_PKG_VERSION_PATCH=0 CARGO_PKG_VERSION_PRE='' LD_LIBRARY_PATH='/evsieve-1.3.1/target/release/deps:/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib:/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib' rustc --crate-name lazy_static /usr/local/cargo/registry/src/github.com-1285ae84e5963aae/lazy_static-1.4.0/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,future-incompat --crate-type lib --emit=dep-info,metadata,link -C opt-level=3 -C linker-plugin-lto -C metadata=3d9ce34e1f2a1704 -C extra-filename=-3d9ce34e1f2a1704 --out-dir /evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps --target arm-unknown-linux-musleabihf -L dependency=/evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps -L dependency=/evsieve-1.3.1/target/release/deps --cap-lints warn`
         Running `CARGO=/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/bin/cargo CARGO_CRATE_NAME=build_script_build CARGO_MANIFEST_DIR=/evsieve-1.3.1 CARGO_PKG_AUTHORS='Kars Mulder <[email protected]>' CARGO_PKG_DESCRIPTION='' CARGO_PKG_HOMEPAGE='' CARGO_PKG_LICENSE='GPL-2.0-or-later AND MIT AND GPL-2.0-only WITH Linux-syscall-note' CARGO_PKG_LICENSE_FILE='' CARGO_PKG_NAME=evsieve CARGO_PKG_REPOSITORY='' CARGO_PKG_VERSION=1.3.1 CARGO_PKG_VERSION_MAJOR=1 CARGO_PKG_VERSION_MINOR=3 CARGO_PKG_VERSION_PATCH=1 CARGO_PKG_VERSION_PRE='' CARGO_PRIMARY_PACKAGE=1 LD_LIBRARY_PATH='/evsieve-1.3.1/target/release/deps:/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib:/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib' rustc --crate-name build_script_build --edition=2018 build.rs --error-format=json --json=diagnostic-rendered-ansi,future-incompat --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debug-assertions=off -C metadata=22c4863004204d9f -C extra-filename=-22c4863004204d9f --out-dir /evsieve-1.3.1/target/release/build/evsieve-22c4863004204d9f -L dependency=/evsieve-1.3.1/target/release/deps`
         Running `/evsieve-1.3.1/target/release/build/evsieve-22c4863004204d9f/build-script-build`
    [evsieve 1.3.1] cargo:rustc-link-lib=dylib=evdev
         Running `/evsieve-1.3.1/target/release/build/libc-1e8fe370016abd8d/build-script-build`
    [libc 0.2.82] cargo:rustc-cfg=freebsd11
    [libc 0.2.82] cargo:rustc-cfg=libc_priv_mod_use
    [libc 0.2.82] cargo:rustc-cfg=libc_union
    [libc 0.2.82] cargo:rustc-cfg=libc_const_size_of
    [libc 0.2.82] cargo:rustc-cfg=libc_align
    [libc 0.2.82] cargo:rustc-cfg=libc_core_cvoid
    [libc 0.2.82] cargo:rustc-cfg=libc_packedN
    [libc 0.2.82] cargo:rustc-cfg=libc_cfg_target_vendor
         Running `CARGO=/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/bin/cargo CARGO_CRATE_NAME=libc CARGO_MANIFEST_DIR=/usr/local/cargo/registry/src/github.com-1285ae84e5963aae/libc-0.2.82 CARGO_PKG_AUTHORS='The Rust Project Developers' CARGO_PKG_DESCRIPTION='Raw FFI bindings to platform libraries like libc.
    ' CARGO_PKG_HOMEPAGE='https://github.com/rust-lang/libc' CARGO_PKG_LICENSE='MIT OR Apache-2.0' CARGO_PKG_LICENSE_FILE='' CARGO_PKG_NAME=libc CARGO_PKG_REPOSITORY='https://github.com/rust-lang/libc' CARGO_PKG_VERSION=0.2.82 CARGO_PKG_VERSION_MAJOR=0 CARGO_PKG_VERSION_MINOR=2 CARGO_PKG_VERSION_PATCH=82 CARGO_PKG_VERSION_PRE='' LD_LIBRARY_PATH='/evsieve-1.3.1/target/release/deps:/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib:/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib' OUT_DIR=/evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/build/libc-f2c09ad6e5d550cb/out rustc --crate-name libc /usr/local/cargo/registry/src/github.com-1285ae84e5963aae/libc-0.2.82/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,future-incompat --crate-type lib --emit=dep-info,metadata,link -C opt-level=3 -C linker-plugin-lto --cfg 'feature="default"' --cfg 'feature="std"' -C metadata=30c486c1ef1c22c6 -C extra-filename=-30c486c1ef1c22c6 --out-dir /evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps --target arm-unknown-linux-musleabihf -L dependency=/evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps -L dependency=/evsieve-1.3.1/target/release/deps --cap-lints warn --cfg freebsd11 --cfg libc_priv_mod_use --cfg libc_union --cfg libc_const_size_of --cfg libc_align --cfg libc_core_cvoid --cfg libc_packedN --cfg libc_cfg_target_vendor`
         Running `CARGO=/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/bin/cargo CARGO_BIN_NAME=evsieve CARGO_CRATE_NAME=evsieve CARGO_MANIFEST_DIR=/evsieve-1.3.1 CARGO_PKG_AUTHORS='Kars Mulder <[email protected]>' CARGO_PKG_DESCRIPTION='' CARGO_PKG_HOMEPAGE='' CARGO_PKG_LICENSE='GPL-2.0-or-later AND MIT AND GPL-2.0-only WITH Linux-syscall-note' CARGO_PKG_LICENSE_FILE='' CARGO_PKG_NAME=evsieve CARGO_PKG_REPOSITORY='' CARGO_PKG_VERSION=1.3.1 CARGO_PKG_VERSION_MAJOR=1 CARGO_PKG_VERSION_MINOR=3 CARGO_PKG_VERSION_PATCH=1 CARGO_PKG_VERSION_PRE='' CARGO_PRIMARY_PACKAGE=1 LD_LIBRARY_PATH='/evsieve-1.3.1/target/release/deps:/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib:/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib' OUT_DIR=/evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/build/evsieve-726638333db86f48/out rustc --crate-name evsieve --edition=2018 src/main.rs --error-format=json --json=diagnostic-rendered-ansi,future-incompat --crate-type bin --emit=dep-info,link -C opt-level=3 -C lto -C metadata=c790f64dca250c82 -C extra-filename=-c790f64dca250c82 --out-dir /evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps --target arm-unknown-linux-musleabihf -L dependency=/evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps -L dependency=/evsieve-1.3.1/target/release/deps --extern lazy_static=/evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps/liblazy_static-3d9ce34e1f2a1704.rlib --extern libc=/evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps/liblibc-30c486c1ef1c22c6.rlib -l dylib=evdev`
    error: linking with `cc` failed: exit status: 1
      |
      = note: "cc" "/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib/rustlib/arm-unknown-linux-musleabihf/lib/self-contained/crt1.o" "/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib/rustlib/arm-unknown-linux-musleabihf/lib/self-contained/crti.o" "/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib/rustlib/arm-unknown-linux-musleabihf/lib/self-contained/crtbegin.o" "/evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps/evsieve-c790f64dca250c82.evsieve.4fac1677-cgu.3.rcgu.o" "-Wl,--as-needed" "-L" "/evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps" "-L" "/evsieve-1.3.1/target/release/deps" "-L" "/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib/rustlib/arm-unknown-linux-musleabihf/lib" "-levdev" "-Wl,--start-group" "-Wl,-Bstatic" "-lunwind" "-lc" "-Wl,--end-group" "/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib/rustlib/arm-unknown-linux-musleabihf/lib/libcompiler_builtins-b85afa065dacb413.rlib" "-Wl,-Bdynamic" "-Wl,--eh-frame-hdr" "-Wl,-znoexecstack" "-nostartfiles" "-L" "/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib/rustlib/arm-unknown-linux-musleabihf/lib" "-L" "/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib/rustlib/arm-unknown-linux-musleabihf/lib/self-contained" "-o" "/evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps/evsieve-c790f64dca250c82" "-Wl,--gc-sections" "-static" "-no-pie" "-Wl,-zrelro,-znow" "-Wl,-O1" "-nodefaultlibs" "/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib/rustlib/arm-unknown-linux-musleabihf/lib/self-contained/crtend.o" "/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib/rustlib/arm-unknown-linux-musleabihf/lib/self-contained/crtn.o"
      = note: /usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/8/../../../arm-linux-gnueabihf/libevdev.a(libevdev-uinput.o): in function `fetch_device_node':
              (.text.fetch_device_node+0x5e): undefined reference to `__asprintf_chk'
              /usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/8/../../../arm-linux-gnueabihf/libevdev.a(libevdev-uinput.o): in function `libevdev_uinput_create_from_device':
              (.text.libevdev_uinput_create_from_device+0x226): undefined reference to `__snprintf_chk'
              /usr/bin/ld: (.text.libevdev_uinput_create_from_device+0x266): undefined reference to `__snprintf_chk'
              /usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/8/../../../arm-linux-gnueabihf/libevdev.a(libevdev.o): in function `libevdev_dflt_log_func':
              (.text.libevdev_dflt_log_func+0x36): undefined reference to `__fprintf_chk'
              /usr/bin/ld: (.text.libevdev_dflt_log_func+0x44): undefined reference to `__fprintf_chk'
              /usr/bin/ld: (.text.libevdev_dflt_log_func+0x66): undefined reference to `__fprintf_chk'
              /usr/bin/ld: (.text.libevdev_dflt_log_func+0x7e): undefined reference to `__fprintf_chk'
              /usr/bin/ld: (.text.libevdev_dflt_log_func+0x8e): undefined reference to `__fprintf_chk'
              /usr/bin/ld: (.text.libevdev_dflt_log_func+0x56): undefined reference to `__vfprintf_chk'
              collect2: error: ld returned 1 exit status
    
      = help: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
      = note: use the `-l` flag to specify native libraries to link
      = note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
    
    error: could not compile `evsieve` due to previous error
    
    Caused by:
      process didn't exit successfully: `CARGO=/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/bin/cargo CARGO_BIN_NAME=evsieve CARGO_CRATE_NAME=evsieve CARGO_MANIFEST_DIR=/evsieve-1.3.1 CARGO_PKG_AUTHORS='Kars Mulder <[email protected]>' CARGO_PKG_DESCRIPTION='' CARGO_PKG_HOMEPAGE='' CARGO_PKG_LICENSE='GPL-2.0-or-later AND MIT AND GPL-2.0-only WITH Linux-syscall-note' CARGO_PKG_LICENSE_FILE='' CARGO_PKG_NAME=evsieve CARGO_PKG_REPOSITORY='' CARGO_PKG_VERSION=1.3.1 CARGO_PKG_VERSION_MAJOR=1 CARGO_PKG_VERSION_MINOR=3 CARGO_PKG_VERSION_PATCH=1 CARGO_PKG_VERSION_PRE='' CARGO_PRIMARY_PACKAGE=1 LD_LIBRARY_PATH='/evsieve-1.3.1/target/release/deps:/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib:/usr/local/rustup/toolchains/1.59.0-armv7-unknown-linux-gnueabihf/lib' OUT_DIR=/evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/build/evsieve-726638333db86f48/out rustc --crate-name evsieve --edition=2018 src/main.rs --error-format=json --json=diagnostic-rendered-ansi,future-incompat --crate-type bin --emit=dep-info,link -C opt-level=3 -C lto -C metadata=c790f64dca250c82 -C extra-filename=-c790f64dca250c82 --out-dir /evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps --target arm-unknown-linux-musleabihf -L dependency=/evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps -L dependency=/evsieve-1.3.1/target/release/deps --extern lazy_static=/evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps/liblazy_static-3d9ce34e1f2a1704.rlib --extern libc=/evsieve-1.3.1/target/arm-unknown-linux-musleabihf/release/deps/liblibc-30c486c1ef1c22c6.rlib -l dylib=evdev` (exit status: 1)```
    
    What did i miss?
    opened by aggo15 13
  • caps2esc behaviour possible?

    caps2esc behaviour possible?

    Thank you for this awesome software, been using it for setting keybinds for all my VM inputs at once.
    Is caps2esc behaviour possible using esieve, or is it a job for python evdev lib?

    in caps2esc: CtrlDown CtrlUp --> Esc CtrlDown d CtrlUp --> Ctrl-d Esc --> grave

    question 
    opened by fhill2 11
  • Remap combo of mouse wheel and keyboard modifier

    Remap combo of mouse wheel and keyboard modifier

    I am trying to do a remapping of event like alt + wheel up to ctrl + wheel up. I did the following:

    $ sudo evsieve --input /dev/input/event8 grab --input /dev/input/event5 grab \
        --toggle rel:wheel @alt-up @alt-down id=alt \
        --hook   key:leftalt:1 toggle=alt:2 \
        --hook   key:leftalt:0 toggle=alt:1 \
        --map    rel:wheel@alt-down key:leftctrl:1 key:leftctrl:2 rel:wheel key:leftctrl:0 \
        --print  @alt-down @alt-up \
        --output create-link=/dev/input/by-id/merged-virtual-KM name="merged virtual KM"
    
    

    /dev/input/event8 is my keyboard, /dev/input/event5 is my mouse. I combined them into hybrid keyboard+mouse virtual device. I used the idea from #9 to combine several source events.

    And as far as I can tell from the printed events, the remapping is done correctly. But still the KDE does not react properly. I.e. I press and hold the alt, then scroll wheel up, then release alt. And I expect the text to be zoomed in (i.e. ctrl + wheel up). But it does not happen.

    I also tried replacing rel:wheel with rel:wheel_hi_res. Also tried with key:leftalt:0 because I thought it may be in pressed state with the combo output, resulting in ctrl + alt + wheel up. Also tried even --block key:leftalt. Nothing helped.

    Can you suggest what I am doing wrong? Also, see the question that requires this solution.

    opened by Ashark 9
  • Missing Event Codes between BTN_BASE6 and BTN_DEAD?

    Missing Event Codes between BTN_BASE6 and BTN_DEAD?

    Hi I have found evsieve very useful to create a virtual device merging a joystick and throttle (HOTAS) for use with older games that can only handle one joystick.

    However, both the joystick and throttle have buttons whose event_codes show as '?' in evtest, with numeric values for the codes from 300 to 302.

    Looking at linux/input-event-codes.h I can see there is a gap from BTN_BASE6, 0x12b (299) to BTN_DEAD, 0x12f (303).

    If these points will not have codes assigned to them is there a way to permit providing the actual code value instead (whether in hex or decimal)? Thank you.

    opened by Karnith-Sylass 5
  • Invert ABS values when min greater than max

    Invert ABS values when min greater than max

    uinput runs validation on event definitions to ensure min is less than max. This means uinput can't clone devices like the "ADC attached joystick" driver which says:

    If min > max, it is left to userspace to treat the axis as inverted.

    https://www.kernel.org/doc/Documentation/devicetree/bindings/input/adc-joystick.yaml

    So we need something which inverts everything in user-space. That's what this commit does.

    opened by puffnfresh 4
  • Possibility to associate scripts with toggles

    Possibility to associate scripts with toggles

    I would like to be able to use ddcutil with my current KVM setup. I know that currently evsieve can allow associating a command to a hook. But as it stands now, this requires using two different keys as described in the "Toggle events between two virtual devices - Advanced Variations" section. It would be nice if we could map a shell command to a toggle target. This way one can use a single key combination to both switch between inputs.

    opened by acama 4
  • 2 instances working simultaneously

    2 instances working simultaneously

    Hi, I want to implement key remapping with layouts. Basically if dev_layout is active, keys would be remapped c -> ctrl+c, v -> ctrl+v, l -> ctrl+alt+l, etc. If another layout is active, different mapping works.

    The best way to implement this that I can think of is to have a "control switcher" instance that always running and on the press of special keys (like "f8", 'f10") executes bash script. Bash script would kill the previous instance of evsieve and run another one with a different layout (set of arguments).

    The problem is there always gonna be two instances running: "control switcher" and "layout handler". Does evsieve take exclusive control when running thus one of the two instances will just stop working? Maybe there is a better simpler way to implement such functionality?

    question 
    opened by positiveway 4
  • Unknown event code mapping/copy issue

    Unknown event code mapping/copy issue

    I believe there is an issue when trying to process arbitrary event codes. I have a joystick controller which is sending a 1:300 (key:300) event, and I believe because 300 is not a standard event code, issues are arising:

    Full script:

    sudo evsieve --input /dev/input/by-id/usb-GGG_GPWiz49-2-event-joystick grab=force persist=reopen \
            --input /dev/input/by-id/usb-GGG_GPWiz49-event-joystick grab=force persist=reopen \
            --map "key:300" "key:up" \
            --print \
            --output name="joysticks" \
    
    
    While parsing the arguments "--map key:300 key:up":
        While parsing the key "key:300"
            invalid argument: unknown event code "300"
    

    evtest output:

    Event: time 1669313468.400824, type 4 (EV_MSC), code 4 (MSC_SCAN), value 9000d
    Event: time 1669313468.400824, type 1 (EV_KEY), code 300 (?), value 0
    

    Any ideas for workarounds?

    opened by jettdc 2
  • How to filter Volume Up and Volume Down?

    How to filter Volume Up and Volume Down?

    I've tried evtest and evsieve with the --print argument to figure out what the key names are; I see KEY_VOLUMEUP and KEY_VOLUMEDOWN as the name, but if I try key:volumeup,volup,volume_up,volup - none of them work (same for down).
    Is there a way to filter out these keys from a virtual keyboard? Mute, play/pause and such seem to work just fine.

    Thanks. Any thoughts are welcome, and appreciate your time and effort.

    Edit: I have a Logitech G810 Keyboard in case that matters. [Don't buy, the [[physical]] key caps are crap.] All regular keyboard events are detected on /dev/input/by-id/usb-Logitech_Gaming_Keyboard_G810_036B364F3537-event-kbd,
    while media keys (and I think only media keys) are detected on /dev/input/by-id/usb-Logitech_Gaming_Keyboard_G810_036B364F3537-if01-event-kbd

    opened by oitos 2
  • Use just one key to switch between layouts

    Use just one key to switch between layouts

    Hi! So I have two layouts, Del key is used to activate the first one and Ins to activate the second one. Is it possible to use just one (Del) key to "rotate" between layouts?

    evsieve --input /dev/input/by-id/usb-Logitech_USB_Receiver-if02-event-mouse grab \
            --hook key:insert  toggle=:1 \
            --hook key:delete  toggle=:2 \
            --block key:insert key:delete \
            --toggle "" @norm_layout @dev_layout \
            --map key:c@dev_layout key:leftctrl key:c \
            --map key:v@dev_layout key:leftctrl key:v \
            --map key:x@dev_layout key:leftctrl key:x \
            --map key:z@dev_layout key:leftctrl key:z \
            --map key:f@dev_layout key:leftctrl key:f \
            --map key:w@dev_layout key:leftctrl key:w \
            --map key:l@dev_layout key:leftctrl key:leftalt key:l \
            --output
    
    question 
    opened by positiveway 2
  • Keyboard doesn't work in VM

    Keyboard doesn't work in VM

    Hello,

    I tried to pass my keyboard to VM like this:

    evsieve --input /dev/input/by-id/usb-Razer_Razer_BlackWidow_Chroma_V2-if01-event-kbd grab \
    	--map key:scrolllock key:leftctrl key:rightctrl \
            --output key:grave \
            --output create-link=/dev/input/by-id/guest-keyboard &
    

    problem is that my VM starts and my mouse works in VM too, but my keyboard doesn't work, my keyboard is locked in host, I tried LCTRL+RCTRL and Scroll Lock too and didn't help.

    This is how I passed keyboard to VM:

    <input type="evdev">
      <source dev="/dev/input/by-id/guest-keyboard" grab="all" repeat="on"/>
    </input>
    
    opened by t0msk 1
  • Multi-touch finger count

    Multi-touch finger count

    How does one filter for 3 finger multi-touch events? I wanted to convert a three finger multi-touch motion into a mouse drag. (Like in macOS)

    --print doesn't seem to provide info on number of fingers

    opened by icedman 1
  • Possible to block regular key output while pressing a hook keyboard combo?

    Possible to block regular key output while pressing a hook keyboard combo?

    I like to use the super key in combination the F row keys for executing scripts. This works fine with evsieve, but with the minor downside that whatever other key gets pressed will also be registered by any open application. For example, if I press Super+F1, then the help menu will (typically) pop up or for Super+F9, it will open the help menu in byobu. Is there some way to suppress regular key output while the keyboard combo is pressed, without losing previous function?

    opened by oitos 4
  • Question re switching 1 kbd between multiple VMs

    Question re switching 1 kbd between multiple VMs

    Apologies if there is a better place to put basic questions, I didn't see one when looking.

    I'm curious if evsieve can support a workflow I'm trying to build.

    I have a system where the host (Proxmox as a hypervisor) is running headless. I'd still like to be able to use the same keyboard on the host in emergencies but will need it there far less than 1% of the time.

    I'm running multiple VFIO (passthrough) VMs via a couple of GPUs.

    I'd like to be able to:

    • switch input between 2 different VMs (ie, something like pressing control+control but have it switch to a different VM instead of the host)
    • use the same input on multiple VMs (not simultaneously, rather, when I shut down 1 VM, another can spin up and use the same input that would have gone to to the prior VM)
    • (optional) run a command-line argument during VM startup (qemu hookscript) that focuses the keyboard on a spun up VM
    1. Is there a way to cycle multiple VM inputs using a hotkey?

    2. If yes, can the host cycle hotkey be different than the VM switching hotkey?


    To explain the workflow differently:

    I'd be setting a VM up to run on Proxmox boot up. Only 1 VM would be running at this point. I'd like to focus evsieve to immediately control that VM (using hookscript most likely). I could spin up a second VM and use a hotkey to switch input to it. Later I might shut down one of the VMs to spin up a different one, but still have ability to switch to it.

    In the case of some weird emergency I'd have a different hotkey that would always focus the inputs back to the Proxmox host.

    question 
    opened by Jahfry 2
  • revert mouse

    revert mouse

    not sure it is already possible or not. i don't find how.

    is it possible to revert an axis ? basically, map abs:x to abs:-x (because with my device, the x axis is reverted compared to my needs)

    enhancement 
    opened by nadenislamarre 6
  • Using evsieve with barrier

    Using evsieve with barrier

    Hi, This is not an "issue" per se but I don't know where else to ask this question. Sorry for spamming you with issues. I would like to be able to use evsieve with barrier (the keyboard and mouse sharing tool). My current setup is that I have a VFIO setup where I am using evsieve to switch keyboard and mouse between guest and host and also switch the display back and forth using ddcutil with "exec-shell" command. It is working pretty well and I have no issues with that. However, recently I have added a mac machine to my setup (a physical machine) and the way I am sharing the keyboard and mouse with that machine is by using 'barrier'. The question is then, how can I use evsieve together with barrier and add all that to my current setup ? I have started implementing a solution but I am missing some pieces in order to make it work fully. I have modified barrier so that I can switch the kbd/ms between the main (linux) machine and the macos machine by issuing a command (think barrierctl switchtoa/switchtob). Currently my evsieve command is the following:

    	--input  /dev/input/by-id/usb-SteelSeries_SteelSeries_Aerox_3_Wireless-event-mouse    persist=reopen domain=ms grab \
            --toggle @kb @guest-kb @host-kb  \
            --toggle @ms @guest-ms @host-ms  \
            --hook   key:leftalt@host-kb key:rightalt@host-kb toggle   exec-shell="sudo ddcutil --display=1 setvcp 60 0x0f"\
            --hook   key:leftalt@guest-kb key:rightalt@guest-kb toggle  exec-shell="sudo ddcutil --display=1 setvcp 60 0x13" \
            --output @host-kb create-link=/dev/input/by-id/host-kbd   \
            --output @host-ms create-link=/dev/input/by-id/host-mouse      \
            --output @guest-kb create-link=/dev/input/by-id/guest-kbd \
    	--output @guest-ms create-link=/dev/input/by-id/guest-mouse
    

    This is switching between guest and host when I press leftalt+rightalt. Is there anyway I could add switching to the macos machine to this somehow in a way that wouldn't result in some inconsistencies in my setup ? For instance using leftshit+rightshift to switch back and forth between the macos machine and the host machine using a combination of the barrierctl command and ddcutil.

    opened by acama 1
  • Issue When Mapping Single Key to Output Combination Key

    Issue When Mapping Single Key to Output Combination Key

    I'm trying to use evsieve to map a single key and generate a combination key. For example, when I press F12 key, I want evsieve to output Ctrl+C key to my device.

    Here is the command I use

    evsieve --input /dev/input/event0 --map key:f12 key:leftctrl key:c --print --output
    

    However, this command will not generate Ctrl+C key consistently. On the monitor of my device, it some time will output ^C as expected, but most of the time I get [24~ instead.

    Did I miss anything? Is there a way to achieve what I want?

    opened by aggo15 9
Releases(v1.3.1)
  • v1.3.1(Jan 1, 2022)

    Changelog

    Bugfix:

    • Fixed a bug that could unnecessarily cause virtual output devices to get recreated if an input that is capable of EV_ABS-type events gets reopened using the persist=reopen clause.
    Source code(tar.gz)
    Source code(zip)
  • v1.3.0(Dec 27, 2021)

    Changelog

    New feature: partial persistence support Input devices now accept a persist=reopen clause. If this clause is specified and the input device becomes unavailable (e.g. because some USB cable got disconnected), evsieve will wait until the device becomes available again and then try to reopen it.

    The main reason that this persist=reopen clause is not enabled by default is for backwards compatibility.

    New feature: optional systemd integration When evsieve is ran as a systemd service of Type=notify, evsieve will notify systemd when it has created its virtual output devices and is ready to start listening for events. This can be used in combination with the systemd-run tool to conveniently start evsieve in the background from shell scripts. An example shell script is in the README.

    Maps can operate on an event type Mapping all events of a certain type is now possible, e.g. --map key key:space will map all keyboard keys to the spacebar. Mapping events to a certain type like --map key rel is still not possible because it has the potential to create invalid (type, code) pairs.

    New argument: --merge The --merge argument flattens stacked KEY_UP and KEY_DOWN events and is possibly handy if you want to map mulple keys to a single key. For example: if --map key key:space --merge is used to map an entire keyboard to a spacebar and multiple keys are pressed simultaneously, the --merge argument will ensure that only a single KEY_DOWN event for the spacebar is generated and the corresponding KEY_UP event is generated only after all keys are released.

    Maps can map to relative values To facilitate mapping abs to rel events, a special value d (short for "delta" or "difference") has been added, which represents the difference between an input event's value and its previous value. It can also scale the difference by an optional factor, for example:

    # If an abs:x:10 event gets followed up by a abs:x:50 event, then the latter one gets mapped to rel:x:40.
    --map abs:x rel:x:d
    
    # If an abs:y:10 event gets followed up by a abs:y:50 event, then the latter one gets mapped to rel:y:8.
    --map abs:y rel:y:0.2d
    
    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Jan 29, 2021)

    Changelog

    Improvements:

    • Evsieve will now print more helpful error messages in many situations.

    Bugfix:

    • Constructing a value range where the lower bound is greater than the upper bound will now throw an error, e.g. trying to map key:a:1~0 will throw an error because 1 is greater than 0.
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Jan 20, 2021)

    Changelog

    New feature:

    • The --output argument now accepts a name= clause.

    Behaviour changed / bugfix:

    • --toggle arguments operating in consistent mode now lock active targets for pressed keys based on (keycode, domain) pairs, rather than on keycode alone;
    • --toggle arguments operating in consistent mode will no longer receive interference from events that do not match its source event.

    Toggle arguments operating in consistent mode have received some technically breaking changes. These changes only show up in rare cases; very few scripts will be affected by it. For the scripts that are affected, the new behaviour is in most likelihood the correct/intended behaviour.

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Jan 17, 2021)

    This is the first official release of evsieve. The core functionality has been implemented and evsieve has reached a point where it may be useful to others.

    Source code(tar.gz)
    Source code(zip)
Owner
Kars Mulder
Kars Mulder
SixtyFPS is a toolkit to efficiently develop fluid graphical user interfaces for any display: embedded devices and desktop applications. We support multiple programming languages, such as Rust, C++ or JavaScript.

SixtyFPS is a toolkit to efficiently develop fluid graphical user interfaces for any display: embedded devices and desktop applications. We support multiple programming languages, such as Rust, C++ or JavaScript.

SixtyFPS 5.5k Jan 1, 2023
OS-native file dialogs on Linux, OS X and Windows

nfd-rs nfd-rs is a Rust binding to the library nativefiledialog, that provides a convenient cross-platform interface to opening file dialogs on Linux,

Saurav Sachidanand 152 Nov 9, 2022
Arch Linux Security Update Notifications

arch-audit-gtk Show an indicator if there are any security updates missing for your Arch Linux system. Install git clone https://aur.archlinux.org/arc

null 48 Nov 28, 2022
OS native dialogs for Windows, MacOS, and Linux

?? nfd2 nfd2 is a Rust binding to the nativefiledialog library, that provides a convenient cross-platform interface to opening file dialogs on Windows

Embark 33 May 15, 2022
A GUI for NordVPN on Linux that maintains feature parity with the official clients, written with Rust and GTK.

Viking for NordVPN This project aims to provide a fully usable and feature-complete graphical interface for NordVPN on Linux. While it attempts to clo

Jacob Birkett 2 Oct 23, 2022
A cross-platform Mod Manager for RimWorld intended to work with macOS, linux and Windows

TODOs are available here. Discussions, PRs and Issues are open for anyone who is willing to contribute. rrm Inspired by Spoons rmm. This is a cross-pl

Alejandro Osornio 7 Sep 5, 2022
Unofficial Linux QQ client, based on GTK4 and libadwaita, developed with Rust and Relm4.

GTK QQ (WIP) Unofficial Linux QQ client, based on GTK4 and libadwaita, developed with Rust and Relm4. Screenshots Light Dark Note The two screenshots

Lomírus 198 Dec 24, 2022
Access German-language public broadcasting live streams and archives on the Linux Desktop

Deutsche Version Televido Televido (“Television” in Esperanto) lets you livestream, search, play and download media from German-language public televi

David C. 10 Nov 4, 2023
Easy c̵̰͠r̵̛̠ö̴̪s̶̩̒s̵̭̀-t̶̲͝h̶̯̚r̵̺͐e̷̖̽ḁ̴̍d̶̖̔ ȓ̵͙ė̶͎ḟ̴͙e̸̖͛r̶̖͗ë̶̱́ṉ̵̒ĉ̷̥e̷͚̍ s̷̹͌h̷̲̉a̵̭͋r̷̫̊ḭ̵̊n̷̬͂g̵̦̃ f̶̻̊ơ̵̜ṟ̸̈́ R̵̞̋ù̵̺s̷̖̅ţ̸͗!̸̼͋

Rust S̵̓i̸̓n̵̉ I̴n̴f̶e̸r̵n̷a̴l mutability! Howdy, friendly Rust developer! Ever had a value get m̵̯̅ð̶͊v̴̮̾ê̴̼͘d away right under your nose just when

null 294 Dec 23, 2022
A toy event store and event messaging system.

RDeeBee Follow this blog series for more details on this project. This system is inspired by Martin Kleppman's arguments that Event Sourcing system an

null 4 Nov 6, 2022
An implementation of a Windows Event Collector server running on GNU/Linux.

OpenWEC OpenWEC is a free and open source (GPLv3) implementation of a Windows Event Collector server running on GNU/Linux and written in Rust. OpenWEC

CEA IT Security 15 Jun 15, 2023
LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values.

LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values. Authors: Sanjay Ghem

Google 31.5k Jan 1, 2023
bevy-hikari is an implementation of voxel cone tracing global illumination with anisotropic mip-mapping in Bevy

Bevy Voxel Cone Tracing bevy-hikari is an implementation of voxel cone tracing global illumination with anisotropic mip-mapping in Bevy. Bevy Version

研究社交 208 Dec 27, 2022
Functions for mapping plaintexts to a u64 while preserving sort order

ore_encoding.rs This is a companion package to ore.rs that can generate and manipulate u64 plaintexts before they are encrypted by ore.rs. Being able

CipherStash 2 Dec 14, 2022
Parallax mapping shaders (relief and POM) for the bevy game engine

Bevy parallax mapping parallax mapping is a graphical effect adding the impression of depth to simple 2d textures by moving the texture's pixel around

Nicola Papale 10 Dec 28, 2022
A vcf parser that use memory mapping to get high performance.

biommap An efficient bioinformatics file parser based on memory mapping of file. WARNING: biommap work only on uncompressed seekable file biommap is t

Pierre Marijon 2 Dec 15, 2022
Omi - Object Mapping Intelligently

Omi - Object Mapping Intelligently A library that maps object structures to relational databases and provides interfaces for common queries and update

Amphitheatre 6 Dec 28, 2022
Executable memory allocator with support for dual mapping and W^X protection

jit-allocator A simple memory allocator for executable code. Use JitAllocator type to allocate/release memory and virtual_memory module functions to e

playX 5 Jul 5, 2023
A collection of mapping suites and useful algorithms, implemented in pure Rust

Unstable API Note that this crate is in early development, breaking API changes are to be expected. Usage Add this to your Cargo.toml: [dependencies]

Emily Matheys 7 Aug 31, 2023
Simple utility to backup/sync data between devices to the cloud

RSink Simple utility to backup/sync data between devices to the cloud Features ?? Blazingly Fast ⛽ Lightweight ?? Cross-platform, runs everywhere ?? S

Abdulrahman Salah 4 Sep 3, 2022