Mirror a Windows USB or Bluetooth game controller into WSL2 as a Linux joystick.
Project description
wsljoy
wsljoy mirrors a controller connected to Windows over USB or Bluetooth into WSL2 as a normal Linux joystick device.
Python
Use Python 3.10. The project is pinned to Python 3.10 because the Windows controller dependencies have the most reliable wheel support there.
Installation From Released Package
Windows Host
Install the Windows host package on Windows with the windows extra. This extra installs hidapi and pygame for controller access.
With pip:
py -3.10 -m venv .venv
.venv\Scripts\activate.bat
python -m pip install --upgrade pip
python -m pip install "wsljoy[windows]"
python -m wsljoy list
python -m wsljoy host
With uv pip:
uv venv --python 3.10
.venv\Scripts\activate.bat
uv pip install "wsljoy[windows]"
python -m wsljoy list
python -m wsljoy host
WSL2 Guest
Install the WSL2 guest package inside WSL2 Ubuntu. The linux extra is available for symmetry, but currently has no third-party dependencies.
With pip:
python3.10 -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install "wsljoy[linux]"
python -m wsljoy setup-uinput
python -m wsljoy guest
With uv pip:
uv venv --python 3.10
. .venv/bin/activate
uv pip install "wsljoy[linux]"
python -m wsljoy setup-uinput
python -m wsljoy guest
Installation From Source
Use these commands when developing from a cloned checkout.
Windows Host
With uv:
uv python install 3.10
uv sync --extra windows
uv run python -m wsljoy list
uv run python -m wsljoy host
With standard venv and pip:
py -3.10 -m venv .venv
.venv\Scripts\activate.bat
python -m pip install --upgrade pip
python -m pip install -e ".[windows]"
python -m wsljoy list
python -m wsljoy host
WSL2 Guest
With uv:
uv sync --extra linux
uv run python -m wsljoy setup-uinput
uv run python -m wsljoy guest
With standard venv and pip:
python3.10 -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[linux]"
python -m wsljoy setup-uinput
python -m wsljoy guest
setup-uinput first checks whether /dev/uinput is already writable. It only asks for sudo when your user needs to be added to the input group; after that, start a new WSL shell or run newgrp input, then run the guest without sudo.
It creates a virtual Linux input device through /dev/uinput using the Linux uinput API. The /dev/input/event* device appears after the guest receives the first packet from Windows. The /dev/input/js* device appears when the Linux joydev module is available and loaded.
Check the guest side:
ls -l /dev/uinput
groups
python -m wsljoy guest
In a second WSL terminal, after the Windows host is running:
ls -l /dev/input/event* /dev/input/js*
If event* exists but js* does not, try:
sudo modprobe joydev
Network Setup
By default the Windows host targets WSL2. On Windows, wsljoy resolves the current WSL2 IP by running wsl.exe hostname -I.
With uv:
uv run python -m wsljoy host
uv run python -m wsljoy guest --listen 0.0.0.0 --port 27414
With an activated venv:
python -m wsljoy host
python -m wsljoy guest --listen 0.0.0.0 --port 27414
If you have multiple WSL distros, name the one running the guest:
python -m wsljoy host --wsl-distro Ubuntu-22.04
To bypass WSL auto-resolution, pass an explicit IP address:
python -m wsljoy host --target 172.25.121.7
Controller Support
The Windows host has two reader backends:
ds4-hid: exact DualShock 4 HID parser for USB and Bluetooth, preferred automatically for DS4 devices.sdl: generic SDL/pygame joystick reader, used for common Xbox, PlayStation, 8BitDo, Nintendo, Logitech, PowerA, Razer, and compatible controllers.
If the same controller is visible through both APIs, list shows the exact backend and hides the duplicate SDL entry. host --backend auto prefers ds4-hid; use host --backend sdl to force SDL.
Auto detection is the default:
python -m wsljoy list
python -m wsljoy host --backend auto
Force the generic backend:
python -m wsljoy host --backend sdl
The exact DS4 path supports:
- Sony vendor ID
054c - Product IDs
05c4and09cc - USB reports and Bluetooth reports
The SDL path covers many usual-suspect controllers but depends on the mapping SDL exposes for that device. The WSL side creates a virtual Linux gamepad with the detected vendor/product IDs when available and Linux-style axes/buttons available through /dev/input/event* and /dev/input/js*.
Development
With uv:
uv python install 3.10
uv sync --all-extras --dev
uv run pytest
With standard venv and pip:
python3.10 -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
python -m pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wsljoy-0.1.2.tar.gz.
File metadata
- Download URL: wsljoy-0.1.2.tar.gz
- Upload date:
- Size: 19.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eca0ef7e112448d4beef968c6166c92569e8623c6595b0e5d1bd2628da9453e2
|
|
| MD5 |
2aa8efb8bbe93377aa19e00755895348
|
|
| BLAKE2b-256 |
7cd3f713b9a7ad45624851f4589d405627bc6164ee59568a46309416783e317d
|
File details
Details for the file wsljoy-0.1.2-py3-none-any.whl.
File metadata
- Download URL: wsljoy-0.1.2-py3-none-any.whl
- Upload date:
- Size: 17.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
15bbdedc4aebb9ad8ba48f597e3391bafb33840e6c327409586f2646a7c7211f
|
|
| MD5 |
271f4b251845c6b89a53c0a20793ef8e
|
|
| BLAKE2b-256 |
e0a25c15e8fbfb1e1d049bcd4e365fc5ee6f72210be8cc66bd7c1dd6f5a7ed3c
|