Skip to content

Repository files navigation

Mini-Keyboard Macro Listener

A lightweight, zero-dependency, cross-platform Python background utility to capture raw input events (keypresses and knob rotations) from a specific USB macro keyboard with Vendor ID 1189 and Product ID 8890 (commonly presenting as an Acer spoofed device). I'm using this one: https://www.aliexpress.us/item/3256809632264925.html

Example of the keyboard

This tool maps keyboard events to custom user-defined shell commands based on a configuration file. It supports hot-reloading of configurations and runs as a background service on Ubuntu (Linux), Windows 11, and macOS.

the original windows software from the manufacturer is here (untested by me): https://drive.google.com/file/d/1k3Ees_tiSThPaRT059_yOJrZMBprVJfB/view?usp=sharing


Features

  • Zero External Dependencies: Implemented using pure Python standard libraries (struct, select, ctypes, etc.).
  • Asynchronous Execution: Triggers commands via subprocess.Popen to ensure the input polling loop remains highly responsive.
  • Platform-Specific Backends:
    • Linux: Low-level event reading from /dev/input/event* using select polling and raw structure unpacking.
    • Windows: Hidden Win32 message-only window and standard Raw Input API (WM_INPUT) via ctypes.
    • macOS: Native HID event listener using IOHIDManager and CoreFoundation via ctypes to ensure exclusive device control and macro execution.
  • Hot-Reloading: Automatically detects edits to config.json and applies them on the next key press/knob turn.

Configuration (config.json)

Configure your keyboard shortcuts and commands in config.json. The file separates mappings by platform so you can use the same file across dual-boots:

{
  "linux": {
    "key_46": "echo 'Key 46 pressed on Linux!'",
    "knob_cw": "echo 'Knob CW rotated on Linux!'",
    "knob_ccw": "echo 'Knob CCW rotated on Linux!'"
  },
  "windows": {
    "key_67": "echo Key 67 pressed on Windows!",
    "knob_cw": "echo Knob CW rotated on Windows!",
    "knob_ccw": "echo Knob CCW rotated on Windows!"
  },
  "darwin": {
    "key_110": "key 110 pressed on macOS",
    "key_104": "key 104 pressed on macOS",
    "key_105": "key 105 pressed on macOS",
    "knob_cw": "knob CW rotated on macOS",
    "knob_ccw": "knob CCW rotated on macOS"
  }
}

Note

Finding Keycodes: When running the listener in a console/log environment, pressing any button or turning the knob will print the event name (e.g. key_46 or knob_cw) if no mapping is found. Use this output to copy key names and add mappings to your configuration.


Ubuntu / Linux Setup

Prerequisites

Since reading /dev/input/event* requires read permissions, ensure your user belongs to the input group:

sudo usermod -aG input $USER

Note: You must log out and log back in, or reboot your machine, for this group change to take effect.

Running Manually

To run the listener manually in your terminal:

python3 listener.py

Autostart via systemd (User Service)

To configure the utility to run automatically in the background on startup:

  1. Copy or link the service file mini-keyboard.service to your user systemd directory:

    mkdir -p ~/.config/systemd/user/
    cp mini-keyboard.service ~/.config/systemd/user/
  2. Open the copied file ~/.config/systemd/user/mini-keyboard.service in a text editor and update the paths (ExecStart and WorkingDirectory) from the generic /path/to/mini-keyboard placeholder to the absolute path of your cloned repository.

  3. Reload the user daemon, enable the service, and start it:

    systemctl --user daemon-reload
    systemctl --user enable mini-keyboard.service
    systemctl --user start mini-keyboard.service
  4. Check the service status and logs:

    systemctl --user status mini-keyboard.service
    journalctl --user -u mini-keyboard.service -f

Windows 11 Setup

Running Manually (for Debugging)

Double-click start_listener.bat to run the listener in a visible command window. This is highly recommended when initially configuring your key maps so you can see stdout logs.

IMPORTANT - To control VLC on Windows when it is in the background, you must enable its built-in HTTP Web interface:

Open VLC, go to Tools -> Preferences. At the bottom-left, under Show settings, click All. Navigate to Interface -> Main interfaces, and check Web. Expand Main interfaces in the tree, click on Lua, and set a password (e.g. vlc) under Lua HTTP. Click Save and restart VLC.

Running Invisibly on Login

To have the script run completely silently in the background:

  1. Press Win + R, type shell:startup, and press Enter. This opens your Windows Startup folder.
  2. Create a shortcut to start_listener.vbs and paste it inside the Startup folder.
  3. On your next login, the VBScript will execute listener.py in the background with no terminal window visible. You can stop it via Task Manager under "Python".

macOS Setup

Prerequisites & Permissions

Since the utility uses macOS IOHIDManager to capture raw input events at a system level and seize the device exclusively, the application running the listener needs Input Monitoring permissions:

  1. Launch Terminal or your preferred terminal app.
  2. Run the script manually (see below).
  3. If macOS prompts you for permissions, allow it. Alternatively, open System Settings -> Privacy & Security -> Input Monitoring and ensure your terminal application is enabled.

VLC Control Configuration

Similar to Windows, macOS uses the Lua HTTP API to control VLC when in the background.

  1. Open VLC, go to Preferences.
  2. Click Show All settings at the bottom-left corner.
  3. Navigate to Interface -> Main interfaces and check the box for Web.
  4. Expand the Main interfaces submenu on the left, click on Lua, and set a password (e.g., vlc) under Lua HTTP.
  5. Click Save and restart VLC.

Running Manually

python3 listener.py

Running in Background on Login

You can create a LaunchAgent to run the utility silently in the background on login:

  1. Create a file named com.user.minikeyboard.plist in ~/Library/LaunchAgents/ with the following contents (adjust /path/to/mini-keyboard and /path/to/python3 accordingly):

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>com.user.minikeyboard</string>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/bin/python3</string>
            <string>/path/to/mini-keyboard/listener.py</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>KeepAlive</key>
        <true/>
        <key>WorkingDirectory</key>
        <string>/path/to/mini-keyboard</string>
        <key>StandardOutPath</key>
        <string>/tmp/mini-keyboard.out.log</string>
        <key>StandardErrorPath</key>
        <string>/tmp/mini-keyboard.err.log</string>
    </dict>
    </plist>
  2. Load and start the LaunchAgent:

    launchctl load ~/Library/LaunchAgents/com.user.minikeyboard.plist

Programming the Physical Hardware

Factory default macro keyboards of this style usually send the letter c (KEY 46 / virtual key 67 / macOS key 110) for all physical buttons and knob directions.

For the listener utility to distinguish between your buttons and knob rotation/presses, you must program the keyboard's onboard EEPROM/memory to send unique codes first (typically mapping buttons to function keys F13 through F24). Because standard keyboards do not have F13–F24 keys, these mappings will not conflict with normal system keys (e.g., F5 reloading a webpage). Once programmed, these mappings are retained on the hardware.

It's recommended to use the open-source CLI utility ch57x-keyboard-tool.

1. Installation & Setup by OS

Linux (Ubuntu/Debian)

  1. Install the Rust compiler and Cargo toolchain:
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  2. Install the utility via Cargo:
    cargo install ch57x-keyboard-tool
  3. Configure udev permissions so that you can communicate with the USB device without root privileges (sudo):
    echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1189", ATTR{idProduct}=="8890", MODE="0666"' | sudo tee /etc/udev/rules.d/99-ch57x-macropad.rules
    sudo udevadm control --reload-rules && sudo udevadm trigger

macOS

  1. Install Homebrew (if not already installed) from brew.sh.
  2. Install the libusb dependency:
    brew install libusb
  3. Install the Rust compiler and Cargo toolchain:
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  4. Install the utility via Cargo:
    cargo install ch57x-keyboard-tool

Windows

  1. Download and install the latest .msi driver release of USBDK from daynix/UsbDk Releases (necessary for USB communication).
  2. Install Rust and Cargo by downloading and running rustup-init.exe from rustup.rs.
  3. Install the utility via Cargo:
    cargo install ch57x-keyboard-tool

2. How to Program the Keyboard Mappings

  1. Create a Configuration YAML File: Create a configuration file (e.g., keyboard-config.yaml) defining your layout. You can use the provided template in dev/keyboard-config.yaml:

    orientation: normal
    rows: 2
    columns: 3
    knobs: 1
    
    layers:
      - buttons:
          - ["f13", "f14", "f15"]
          - ["f16", "f17", "f18"]
        knobs:
          - ccw: "wheelup"
            press: "f19"
            cw: "wheeldown"
  2. Connect the Keyboard via USB: Ensure the device is connected directly via a USB cable. Flashing mappings cannot be performed over Bluetooth.

  3. Validate the Configuration: Before uploading, check the YAML file for syntax errors or invalid keycodes:

    ch57x-keyboard-tool validate < keyboard-config.yaml
  4. Upload the Configuration: Flash the mappings to the device's hardware:

    ch57x-keyboard-tool upload < keyboard-config.yaml

    (Note: If permission errors occur on Linux and you did not configure the udev rules, run the command with sudo)

  5. View Supported Key Names: To see a full list of all modifier and key names recognized by the programmer:

    ch57x-keyboard-tool show-keys

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages