Skip to main content

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.

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 05c4 and 09cc
  • 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wsljoy-0.1.1.tar.gz (19.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wsljoy-0.1.1-py3-none-any.whl (16.9 kB view details)

Uploaded Python 3

File details

Details for the file wsljoy-0.1.1.tar.gz.

File metadata

  • Download URL: wsljoy-0.1.1.tar.gz
  • Upload date:
  • Size: 19.5 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

Hashes for wsljoy-0.1.1.tar.gz
Algorithm Hash digest
SHA256 eadd2fddfab53bd9e1d5184cd6a49df4e609d5b8d9a787cbe52ee9ba2109920d
MD5 96991c5d91bbc5dbea4a374c44f08948
BLAKE2b-256 f9e7a383111ffd80b9fa3114aad68762bbe53d4c758959e4cecbeed77c064c25

See more details on using hashes here.

File details

Details for the file wsljoy-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: wsljoy-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 16.9 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

Hashes for wsljoy-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 24fce07485af728c0e2b897e0a546156f29f5e7edd4fa92c075308bec4f7f627
MD5 e8cd24cfdc249935922b05bc1da36ab3
BLAKE2b-256 efe545f1b0a7042dc26ce5935b7c8c7d23f0c1ad24ef919138fa87fd35a86c2f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page