-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Native USB Passthrough for WSL2 over Hyper-V Sockets #13557
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Native USB Passthrough for WSL2 over Hyper-V Sockets #13557
Conversation
Implements a robust USB device passthrough solution for WSL2 that uses Hyper-V sockets instead of IP networking, eliminating issues with VPNs, network configuration changes, and gateway instability. This solution provides three main components: 1. Windows USB Service (usbservice.cpp/hpp) - Enumerates USB devices using Windows Setup API - Manages device attachment/detachment over Hyper-V socket - Forwards USB Request Blocks (URBs) between host and guest 2. Linux Kernel Module (wsl_usb.c) - Implements USB Host Controller Driver (HCD) interface - Receives USB traffic over AF_VSOCK - Emulates USB devices in Linux guest 3. WSL CLI Commands (usbclient.cpp/hpp) - wsl --usb-list: List available USB devices - wsl --usb-attach <device>: Attach USB device to WSL - wsl --usb-detach <device>: Detach USB device from WSL The implementation uses a binary protocol over Hyper-V sockets (port 0x5553422) with message types for device enumeration, attachment, detachment, and URB forwarding. This provides network-independent USB passthrough that works reliably with any host networking configuration. Benefits: - No dependency on IP networking or gateway addresses - Works with VPNs and complex network configurations - Native WSL integration, no third-party tools required - Simple user experience with intuitive CLI commands - Better performance without IP stack overhead Closes microsoft#13421 Signed-off-by: Giovanni Magliocchetti <[email protected]>
Signed-off-by: Giovanni Magliocchetti <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements a native USB passthrough solution for WSL2 that eliminates IP networking dependency by using Hyper-V sockets for communication between Windows host and Linux guest. The implementation provides a more reliable alternative to the current usbip-based solution, especially in environments with VPNs or complex network configurations.
Key changes include:
- Native USB device enumeration and management service using Windows Setup API and USB IOCTLs
- Hyper-V socket-based communication protocol for URB (USB Request Block) forwarding
- New WSL CLI commands for USB device management (--usb-list, --usb-attach, --usb-detach)
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
File | Description |
---|---|
src/windows/common/usbservice.hpp | Header file defining USB service interface, protocol structures, and message types for Hyper-V socket communication |
src/windows/common/usbservice.cpp | Implementation of USB service with device enumeration, attachment/detachment, and URB processing functionality |
src/windows/common/usbclient.hpp | Header file for USB CLI interface declarations and command parsing |
src/windows/common/usbclient.cpp | Implementation of USB CLI commands with user-friendly device management and comprehensive help system |
Signed-off-by: Giovanni Magliocchetti <[email protected]>
Signed-off-by: Giovanni Magliocchetti <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@obrobrio2000: Reading through the change, I'm seeing multiple issues (new files not added to the build system, sockets being closed while they're in use, methods like ProcessUrbRequest() added but never called)
Have you compiled and tested the change ?
…d message processing - populate CMakeLists.txt - fix sockets closed while in use - wire in ProcessUrbRequest Signed-off-by: Giovanni Magliocchetti <[email protected]>
…rieval and response handling Signed-off-by: Giovanni Magliocchetti <[email protected]>
Closes #13421
Summary
This PR implements a native USB passthrough solution for WSL2 that eliminates the dependency on IP networking. The implementation uses Hyper-V sockets (AF_HYPERV/AF_VSOCK) as the communication channel between Windows host and Linux guest, providing a solution that works regardless of network configuration, VPN status, or gateway changes.
Related Changes
Kernel changes are available at:
13421-native-usb-passthrough-hvsocket
728af7c63750507a38bb6c5b57c4f7547f9a3f8a
,d3ffc7869a9a8f448ff7feb3f2964b68c87f8169
The kernel module implementation (
wsl_usb.c
) and build configuration files must be integrated into the official kernel repository by a maintainer with write access.Problem
The current USB passthrough solution for WSL2 relies on usbip over IP networking, which has several significant limitations:
These issues make USB passthrough unreliable for many users and difficult to troubleshoot, especially in corporate environments with complex networking.
Solution
This PR introduces a native WSL USB passthrough system with three main components:
1. Windows USB Service (
usbservice.cpp/hpp
)Key APIs Used:
SetupDiGetClassDevs()
- USB device enumerationCM_Get_Device_ID()
- Device instance ID retrievalCreateFile()
- Device handle creationDeviceIoControl(IOCTL_INTERNAL_USB_SUBMIT_URB)
- URB submission to Windows USB stackGetDistributionRuntimeId()
- Retrieves VM Runtime ID for Hyper-V socket connectionsAF_HYPERV
)2. Linux Kernel Module (
wsl_usb.c
)Key Linux APIs Used:
usb_create_hcd()
/usb_add_hcd()
- HCD registrationsock_create_kern()
/kernel_connect()
- vsock connectionkernel_sendmsg()
/kernel_recvmsg()
- Protocol communicationkthread_run()
- Receiver threadusb_hcd_giveback_urb()
- URB completion3. WSL CLI Commands (
usbclient.cpp/hpp
)wsl --usb-list [--verbose]
: List all available USB deviceswsl --usb-attach <device-id> [--distribution <name>]
: Attach USB devicewsl --usb-detach <device-id> [--distribution <name>]
: Detach USB devicewsl --usb-help
: Show USB command helpFeatures:
Architecture
Communication Protocol
The implementation uses a simple binary protocol over Hyper-V sockets.
Transport Layer
0x5553422
("USB" in hex)Message Format
Header (16 bytes, little-endian):
Sequence Number Tracking
The protocol implements complete sequence number tracking to ensure correlation of requests and responses:
Implementation:
std::atomic<uint32_t> m_sequenceNumber{0}
in UsbService class for thread-safe generationGetNextSequenceNumber()
method provides atomic incrementSendUsbMessage()
accepts sequence number parameterFlow:
GetNextSequenceNumber()
to get unique ID, sends with requestReceiveUsbMessage()
Message Types
DeviceEnumeration
(0x01): List all available USB devicesDeviceAttach
(0x02): Attach a device for passthroughDeviceDetach
(0x03): Detach a deviceUrbRequest
(0x04): Forward USB Request Block to hostUrbResponse
(0x05): URB completion from hostDeviceEvent
(0x06): Hotplug notificationsError
(0xFF): Error conditionKey Benefits
Usage Examples
List USB Devices
Example output:
Attach a USB Device
Use Device in Linux
Detach a USB Device
File Structure
Created Files (13)
Modified Files (7)
Backwards Compatibility
This implementation does not affect existing usbip functionality. Users can:
Migration from usbipd-win is straightforward:
wsl --usb-attach
commandsFuture Enhancements
Potential future improvements identified:
Implementation Details
Windows Side Flow
Device Enumeration:
SetupDiGetClassDevs()
with USB device class GUIDSetupDiEnumDeviceInfo()
Device Attachment:
GetDistributionId()
orGetDefaultDistribution()
GetDistributionRuntimeId()
to get the VM Runtime IDhvsocket::Connect(runtimeId, port)
CreateFile()
URB Forwarding:
UrbRequest
from guest over hvsocket (with sequence number)DeviceIoControl(IOCTL_INTERNAL_USB_SUBMIT_URB)
UrbResponse
back to guest with matching sequence numberSequence Number Handling:
URB Implementation
The URB (USB Request Block) forwarding implementation uses Windows USB driver stack APIs with full support for all USB transfer types:
Supported URB Function Codes:
URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
- Bulk and interrupt transfers (storage, serial)URB_FUNCTION_CONTROL_TRANSFER
/URB_FUNCTION_CONTROL_TRANSFER_EX
- Control transfers (enumeration, configuration)URB_FUNCTION_ISOCH_TRANSFER
- Isochronous transfers (audio, video)URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
- Device descriptor requestsURB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE
- Interface descriptor requestsURB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT
- Endpoint descriptor requestsURB_FUNCTION_SELECT_CONFIGURATION
- Configuration selectionURB_FUNCTION_SELECT_INTERFACE
- Interface selectionURB_FUNCTION_ABORT_PIPE
/URB_FUNCTION_RESET_PIPE
- Pipe managementUSB Communication:
Key Implementation Features:
Linux Side Flow
Module Initialization:
URB Enqueue:
wsl_usb_hcd_urb_enqueue()
calledUsbUrbRequest
URB Completion:
UrbResponse
usb_hcd_giveback_urb()
VM Runtime ID vs Distribution GUID
CoCreateGuid()
)A service API was added to expose the VM Runtime ID:
Client Usage:
References