oxysilk is a Rust tool that allows using Razer Orbweaver keypad (and other
similar devices) on Linux by re-mapping any of the keys.
It supports up to 4 layers of key bindings, just like the Windows driver.
- Multi-Layer Support: Map keys to act as layer triggers (Layer 1-3). Switch layouts on the fly by holding a designated key.
- Intelligent Fall-through: If a key isn't defined in a secondary layer, it automatically falls back to the default layer (Layer 0).
- Hot-Reloading: Modify your
oxysilk.tomland the changes take effect immediately without restarting the service. - Exclusive Hardware Grab: Uses
EVIOCGRABto ensure the original device events don't leak to the OS, preventing "double-press" issues. - Stuck-Key Prevention: A robust state engine tracks every physical-to-virtual mapping, ensuring keys are always cleanly released even if layers are swapped mid-press.
- Low Overhead: Written in idiomatic Rust with zero-cost abstractions for minimal latency.
- A Linux distribution.
- Rust toolchain (installed via rustup).
- Permissions: Access to
/dev/input/and/dev/uinputis required. You can run as root or set up udev rules.
- Clone the repository:
git clone https://github.com/karinushka/oxysilk.git cd oxysilk - Build the project:
cargo build --release
The service can be run directly from the target directory. It will attempt to auto-discover your Razer Orbweaver by default.
# Display help and usage information
./target/release/oxysilk --help
# Run with default config (oxysilk.toml) and auto-discovery
sudo ./target/release/oxysilk
# Run with a custom config and a specific device path
sudo ./target/release/oxysilk --config my_layout.toml /dev/input/by-id/usb-Razer_Razer_Orbweaver_Chroma-event-kbd
# List all valid key names for your configuration file
./target/release/oxysilk --list-keysMappings are defined in a oxysilk.toml file. You can find a full list of
supported key names by running oxysilk --list-keys.
[layers.0]
KEY_CAPSLOCK = "KEY_ESC"
KEY_1 = "KEY_F1"You can dedicate any key to act as a layer trigger.
[layers.0]
KEY_SPACE = "LAYER_1" # Hold Space to activate Layer 1
KEY_LEFTALT = "LAYER_2" # Hold LeftAlt to activate Layer 2
# While Space is held:
[layers.1]
KEY_W = "KEY_UP"
KEY_A = "KEY_LEFT"
KEY_S = "KEY_DOWN"
KEY_D = "KEY_RIGHT"
# While LeftAlt is held:
[layers.2]
KEY_1 = "KEY_PLAYPAUSE"
KEY_2 = "KEY_NEXTSONG"Note: If a key is pressed while Layer 1 is active but isn't defined in
[layers.1], oxysilk will look for it in [layers.0] before falling back to
the original key.
oxysilk is designed with testability and reliability in mind, following a
"Hexagonal Architecture" pattern.
The core logic resides in the RemapperEngine. It is decoupled from the Linux
kernel via the InputSource and OutputSink traits. This allows the entire
remapping logic, including complex layer transitions, to be unit-tested without
physical hardware.
The State module maintains a Physical -> Virtual mapping table. This is
critical for reliability:
- Physical Press: The engine determines the virtual target based on the current active layer and stores the relationship.
- Layer Change: The user releases the layer trigger, but keeps the mapped key held.
- Physical Release: The engine looks up the original virtual target in its state table and sends the release event for that specific key, preventing stuck inputs.
The service scans /dev/input/by-id for specific Razer keyboard nodes. Once
found, it issues an EVIOCGRAB to the file descriptor, giving oxysilk
exclusive access to the hardware events.
