Skip to content

defconxt/ArchJoyHide

Repository files navigation

ArchJoyHide

ArchJoy Linux equivalent of HidHide — hide USB and Bluetooth input devices (HOTAS, rudder pedals, flight sticks, gamepads) from games at the kernel level using eBPF LSM.

Problem: Your HOTAS shows up as a game controller in every game. Playing Elden Ring with rudder pedals plugged in causes menu scrolling. A Bluetooth gamepad connected for one game interferes with another. On Windows, HidHide solves this. On Linux, nothing existed — until now.

Solution: ArchJoyHide uses eBPF LSM to intercept device access at the kernel level. Per-device rules let you whitelist or blacklist specific games. A background process watcher automatically detects game launches (including Wine/Proton) and manages access. Works with both USB and Bluetooth input devices.

Features

  • Kernel-level device hiding via eBPF LSM (file_open hook)
  • USB and Bluetooth support — discovers and manages both transport types
  • Per-device rules — whitelist or blacklist mode for each device
  • Multiple identical controllers — each physical device is tracked separately by unique ID (BT MAC address or USB serial/bus path), so two of the same gamepad get independent rules
  • Wine/Proton support — automatically detects game process trees including winedevice.exe
  • GUI (PyQt6) — device list with toggles, app management, system tray
  • CLI — full control from the terminal
  • Persistent rules — saved to config, auto-applied on boot via systemd
  • Process watcher — monitors game launches by exe path, adds entire process trees to allow/deny maps
  • No kernel module needed — pure eBPF, works on any kernel with BPF LSM enabled

How It Works

┌───────────────────────────────────────┐
│  GUI (PyQt6) / CLI                    │
│  Configure per-device rules           │
│  Process watcher detects game launches│
└──────────────┬────────────────────────┘
               │
┌──────────────▼────────────────────────┐
│  Loader (C + libbpf)                  │
│  Loads eBPF programs at boot          │
│  Pins maps to /run/archjh/            │
└──────────────┬────────────────────────┘
               │
┌──────────────▼────────────────────────┐
│  eBPF Programs                        │
│  lsm/file_open    — gate device access│
│  sched_process_fork — inherit PIDs    │
│  sched_process_exit — cleanup PIDs    │
└───────────────────────────────────────┘

Modes

Mode Behavior Empty app list
Off No rules. Device visible to everything.
Whitelist Device hidden from everything EXCEPT listed apps. Hidden from everything.
Blacklist Device visible to everything EXCEPT listed apps. Same as Off.

Wine/Proton Games

When you add a game exe path (e.g. /mnt/gaming/.../DCS.exe), the process watcher:

  1. Polls /proc for processes whose cmdline contains the path
  2. Walks up the process tree to find the Wine/Proton root
  3. Adds the entire process tree (including winedevice.exe) to the BPF allow/deny map
  4. The BPF fork tracepoint propagates access to any new child processes

This means Wine's shared winedevice.exe (which actually reads input devices) gets the correct access, even though it's a sibling of the game process, not a child.

Requirements

  • Linux kernel with BPF LSM enabled (CONFIG_BPF_LSM=y, bpf in LSM list)
  • CachyOS, Arch, and most modern distros have this by default
  • clang, bpftool, libbpf
  • Python 3.10+, python-yaml, python-pyqt6

Check kernel support

zcat /proc/config.gz | grep BPF_LSM
# CONFIG_BPF_LSM=y

cat /sys/kernel/security/lsm
# should contain "bpf"

Install

AUR (recommended for Arch/CachyOS)

yay -S archjh
sudo systemctl enable --now archjh

Updates automatically with yay -Syu.

From source

# Install dependencies
sudo pacman -S clang bpf libbpf python-yaml python-pyqt6

# Clone and install
git clone https://github.com/defconxt/ArchJoyHide.git
cd ArchJoyHide
sudo ./install.sh

Update with git pull && sudo ./install.sh.

Post-install

# Enable the BPF loader service (runs at boot, auto-applies saved rules)
sudo systemctl enable --now archjh

# Launch the GUI
archjh

Usage

GUI (primary)

Launch from your app menu or run:

archjh
  1. Find your device in the list
  2. Set mode to Whitelist or Blacklist
  3. Click + Add App and browse to the game's .exe
  4. Click Apply Rules
  5. Launch your game — rules must be active before the game starts

The GUI minimizes to the system tray. The process watcher runs in the background.

CLI

archjh status                                            # Show rules and BPF status
archjh devices                                           # List detected input devices
archjh whitelist 231d:011f:SER123 /path/to/DCS.exe       # Whitelist device for DCS
archjh blacklist 054c:05c4:aa:bb:cc:dd:ee:ff /path/to/game.exe  # Blacklist by device ID
archjh disable 231d:011f:SER123                          # Disable rules for device
archjh run -- /path/to/app                               # Run app with device access
archjh watch                                             # Run process watcher standalone

Device IDs use the format vid:pid:uniq where uniq is the Bluetooth MAC address or USB serial/bus path. Run archjh devices to see the full device IDs for your hardware.

Service management

sudo systemctl status archjh    # Check service status
sudo systemctl restart archjh   # Restart (reloads BPF + applies rules)
sudo systemctl stop archjh      # Stop (removes all hiding)

Configuration

Rules are saved to ~/.config/archjh/config.yaml:

devices:
  "231d:011f:A02B2515W08":
    name: "VKBSim T-Rudder"
    mode: whitelist
    apps:
      - /mnt/gaming/dcs-world/drive_c/Program Files/Eagle Dynamics/DCS World/bin-mt/DCS.exe
      - /mnt/gaming/star-citizen/drive_c/Program Files/StarCitizen/LIVE/StarCitizen.exe
  "054c:05c4:1c:a0:b8:ff:22:a3":
    name: "Wireless Controller"
    mode: whitelist
    transport: bluetooth
    apps:
      - SO2R.exe
  "054c:05c4:aa:bb:cc:dd:ee:ff":
    name: "Wireless Controller"
    mode: "off"
    transport: bluetooth
    apps: []

Device keys use the format vid:pid:uniq — the unique identifier is a Bluetooth MAC address, USB serial number, or USB bus path. This allows multiple identical controllers (same model) to have independent rules.

Upgrading from v1.1.0 or earlier? Old configs with vid:pid keys are automatically migrated to the new format when your devices are connected. No manual editing needed.

Uninstall

sudo ./uninstall.sh

Config at ~/.config/archjh/ is preserved.

How It Differs from Windows HidHide

Windows HidHide ArchJoyHide
Mechanism Kernel-mode filter driver eBPF LSM
Install DKMS/driver signing No kernel module needed
Kernel updates May break Portable via CO-RE
Per-process filtering By exe path By exe path + process tree detection
Wine/Proton N/A Full support with automatic process tree walking

License

GPL-2.0

About

Linux equivalent of HidHide - hide USB input devices from games at the kernel level using eBPF LSM

Resources

Stars

Watchers

Forks

Sponsor this project

  •  

Packages

 
 
 

Contributors