Skip to content

About

This set of scripts encodes an xbox controller from a linux machine to a windows machine on the same local LAN network. Sender is for the linux machine, receiver is for windows.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LAN Xbox Controller Forwarder

Forward a physical controller connected to a Linux host into a Windows VM over LAN, where it appears as a virtual Xbox 360 controller through ViGEmBus.

Pop!_OS / Linux host
  physical controller -> /dev/input/js*
  C++ sender -> UDP packets

Windows VM
  C# receiver -> ViGEmBus
  virtual Xbox 360 controller

Status

Working end to end:

  • Linux sender reads a selected /dev/input/js* controller.
  • Sender maps the Linux controller state into Xbox-style packets.
  • Sender streams fixed-size UDP packets at a configurable tick rate.
  • Windows receiver decodes those packets.
  • Receiver updates a ViGEmBus virtual Xbox 360 controller.
  • Receiver releases all inputs if packets stop for about 250 ms.
  • Both sender and receiver support silent mode.

Disclaimer

This project is not affiliated with Microsoft, Xbox, ViGEmBus, Nefarius Software Solutions, or any game publisher/platform. ViGEmBus is a separate dependency and is not bundled with this repository.

Use this only on networks and systems you control. The receiver accepts unauthenticated UDP packets on the configured port.

Requirements

Linux host:

  • bash
  • g++
  • make
  • a controller exposed as /dev/input/js*

Windows VM:

  • ViGEmBus installed and running
  • .NET 8 SDK/runtime for development, or the published standalone .exe
  • inbound UDP allowed for the selected port, default 26760

Check ViGEmBus on Windows:

Get-Service ViGEmBus

Quick Start

Start the Windows receiver first:

cd <repo>\XboxControllerForwarder\Receiver\XboxForwarderReceiver
dotnet restore
dotnet run -- --port 26760

Find the Windows VM IP:

ipconfig

Start the Linux sender:

cd XboxControllerForwarder/Sender
./XboxForwarder.sh --host <WINDOWS_VM_IP> --port 26760

The sender prompts for a controller on first run and stores the selection locally.

Silent mode:

./XboxForwarder.sh --host <WINDOWS_VM_IP> --port 26760 --silent
dotnet run -- --port 26760 --silent

Windows Standalone EXE

To publish a Windows .exe from Linux:

cd XboxControllerForwarder
./Receiver/PublishWindowsReceiver.sh

Output:

dist/windows-receiver/XboxForwarderReceiver.exe

Generated files under dist/ are release artifacts. Do not commit them to git; attach them to a GitHub Release or copy them directly to the Windows VM.

Copy dist/windows-receiver/ to the Windows VM, then run:

.\XboxForwarderReceiver.exe --port 26760

Silent mode:

.\XboxForwarderReceiver.exe --port 26760 --silent

To publish an executable that defaults to silent mode:

./Receiver/PublishWindowsReceiverSilent.sh

Output:

dist/windows-receiver-silent/XboxForwarderReceiverSilent.exe

Run:

.\XboxForwarderReceiverSilent.exe --port 26760

Linux Sender Commands

Normal run:

cd XboxControllerForwarder/Sender
./XboxForwarder.sh --host <WINDOWS_VM_IP> --port 26760

Choose a different controller:

./XboxForwarder.sh --select --host <WINDOWS_VM_IP> --port 26760

Bypass stored selection:

./XboxForwarder.sh --device /dev/input/js0 --host <WINDOWS_VM_IP> --port 26760

Useful sender flags:

--device /dev/input/js0
--host <ip-or-hostname>
--port 26760
--hz 125
--config controller.yaml
--axis-layout default
--axis-layout legacy
--axis-map lx,ly,rx,ry,lt,rt,dpx,dpy
--silent

The launcher automatically loads Sender/controller.yaml. It maps semantic controls to stable Linux input identities rather than fragile /dev/input/js* positions:

axes:
  left_stick_x: ABS_X
  left_stick_y: ABS_Y
  right_stick_x: ABS_RX
  right_stick_y: ABS_RY
  left_trigger: ABS_Z
  right_trigger: ABS_RZ
  dpad_x: ABS_HAT0X
  dpad_y: ABS_HAT0Y

You can edit that file to rearrange controls, or select another config explicitly:

./XboxForwarder.sh --host <WINDOWS_VM_IP> --config my-controller.yaml

At connection time the sender asks the Linux joystick API which numeric position each identity occupies. It resolves the mapping again after reconnecting, so a changed enumeration does not cross sticks and triggers.

The older fixed numeric layouts remain available as compatibility overrides:

./XboxForwarder.sh --host <WINDOWS_VM_IP> --axis-layout legacy
./XboxForwarder.sh --host <WINDOWS_VM_IP> --axis-map 0,1,3,4,2,5,6,7

Receiver Commands

Development run:

cd <repo>\XboxControllerForwarder\Receiver\XboxForwarderReceiver
dotnet restore
dotnet run -- --port 26760

Run an existing build:

dotnet .\bin\Debug\net8.0\XboxForwarderReceiver.dll --port 26760

Run the published executable:

.\XboxForwarderReceiver.exe --port 26760

Receiver flags:

--port 26760
--silent

Local Packet Test

Use this to test the sender without Windows.

Terminal 1:

cd XboxControllerForwarder/Sender
./PacketInspector.sh --port 26760

Terminal 2:

cd XboxControllerForwarder/Sender
./XboxForwarder.sh --host 127.0.0.1 --port 26760

The inspector prints decoded packet state.

Troubleshooting

Windows receiver gets no packets:

  • Use the Windows VM IP, not localhost, from the Linux sender.
  • Allow inbound UDP on port 26760 in Windows Firewall.
  • Confirm the VM network mode allows host-to-guest traffic.
  • Test the sender locally with PacketInspector.sh.

Virtual controller does not appear:

  • Confirm ViGEmBus is installed and running:

    Get-Service ViGEmBus
  • Restart the receiver after installing ViGEmBus.

  • Try running the receiver from an elevated PowerShell.

Linux sender cannot open the controller:

ls /dev/input/js*
./XboxForwarder.sh --select --host <WINDOWS_VM_IP>

Controls are mapped incorrectly:

  • Check the sender's Last: Axis map: line to see the identities Linux reported.

  • Edit Sender/controller.yaml so each semantic control points to the intended ABS_* identity, then restart the sender.

  • For a device that does not expose useful Linux identities, use the fixed numeric compatibility map:

    ./XboxForwarder.sh --host <WINDOWS_VM_IP> --axis-map 0,1,3,4,2,5,6,7

Project Layout

XboxControllerForwarder/
  Sender/                         Linux C++ sender
  Receiver/XboxForwarderReceiver/ Windows C# receiver
  Receiver/PublishWindowsReceiver.sh
  Receiver/PublishWindowsReceiverSilent.sh
  LICENSE
  README.md

License

MIT. See LICENSE.

About

This set of scripts encodes an xbox controller from a linux machine to a windows machine on the same local LAN network. Sender is for the linux machine, receiver is for windows.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages