Most hardware developers using Windows have probably heard about WSL, the Windows Subsystem for Linux. WSL is a compatibility layer application that allows for the execution of Linux binaries on a Windows machine. WSL allows you to quickly jump into a Linux terminal without needing a virtual machine or dual booting your system, with the added benefit of having easy access to your Windows file system.

It’s not all fun and game. At the time of writing this, one frustrating issue with WSL is the difficulty accessing connected hardware, like USB-connected devices. In this post, I’m laying out a method I use, using the USB/IP service. There are better or more correct ways to pull this off, but this method worked for me.

Install and Setup WSL [Windows]

The first step is to install and set-up WSL with your favourite flavour of Linux, my preference is Ubuntu, so it’s what I’ll be using. The process is pretty simple, but for more information, see the Microsoft instructions here.

  1. Open a Windows PowerShell and install WSL and Ubuntu 18.04 with wsl --install -d Ubuntu-18.04

  2. From the Powershell start the Ubuntu with ubuntu and run through the configuration process

  3. Update the WSL instance wsl --update

  4. If the current WSL kernel version is 5.10.60.1 or higher, USB/IP support should already be built in. Older versions of the kernel will need to be rebuilt following the instructions from the uspipd developer page. You can check the kernel version with uname -r

Install and Setup USB/IPD Tool [Windows]

USB/IP is essentially USB communication using the TCP protocol. This means you’ll need a client (WSL) and a server (HOST). For this we’ll need to install server side applciation on the host machine.

  1. Download and run the latest .mis USBIPD installer from Github

  2. The first time a device is attached to WSL will requires elevated privileges, this will required opening a new Powershell as “Administrator”. Subsequent attachments will not require admin privileges.

  3. To list the connected devices, run the following command usbipd wsl list. For this example I’ll be connecting to my Pixel 4a.

     BUSID  VID:PID    DEVICE                                                        STATE
     1-3    090c:3350  USB Mass Storage Device                                       Not shared
     2-6    18d1:4ee1  Pixel 4a                                                      Not shared
     2-9    27c6:609c  Framework Fingerprint Reader                                  Not shared
     2-10   8087:0032  Intel(R) Wireless Bluetooth(R)                                Not shared
    
  4. Attach the device with usbipd wsl attach --busid=<BUSID>

  5. Verify the device was attached with usbipd wsl list

    BUSID  VID:PID    DEVICE                                                        STATE
    1-3    090c:3350  USB Mass Storage Device                                       Not shared
    2-6    18d1:4ee1  Pixel 4a                                                      Attached
    2-9    27c6:609c  Framework Fingerprint Reader                                  Not shared
    2-10   8087:0032  Intel(R) Wireless Bluetooth(R)                                Not shared
    
  6. Open the WSL terminal and see if the device has been connected with lsusb

    Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
    Bus 001 Device 004: ID 18d1:4ee1 Google Inc. Nexus Device (MTP)
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    

Setup USB/IPD Tool [WSL]

Up to this point, we can access the hardware from the WSL system, but if the device momentarily loses its connection, the access will go back to the host machine. To ensure the device reconnects to WSL, we’ll need to create a few helper scripts to list all devices, connect and reconnect, and disconnect the device.

  1. In the /usr/bin folder create a file called usbip-list

    #!/bin/bash
    usbip list -r $(cat /etc/resolv.conf | sed -n  's/\(.*[^0-9]\|\)\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\).*/\2/p')
    
  2. In the /usr/bin folder create a file called usbip-attach

    #!/bin/bash
    mkdir /var/spool/usbip/attach
        
    #Get the windows host IP address
    IP=$(cat /etc/resolv.conf | sed -n  's/\(.*[^0-9]\|\)\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\).*/\2/p')
    SPOOL=/var/spool/usbip/attach
        
    touch $SPOOL
        
    #while the attach folder exists try to attach the usb device
    while [[ -e $SPOOL ]]
    do
        usbip attach -r $IP -b $1 1>/dev/null 2>&1
        sleep 1
    done
        
    #If the attach folder isen't present detech the device from first port
    usbip detach -p 0
    exit 0
    
  3. In the /usr/bin folder create a file called usbip-detach

    #!/bin/bash
    rmdir /var/spool/usbip/attach
    
  4. Add the executable flag to each of the newly created file with sudo chmod +x /usr/bin/

Connect the Device [WSL]

  1. Connect your device and run sudo usbip-list the busid in this case is 2-6

    Exportable USB devices
    ======================
    - 192.168.16.1
            2-6: Google Inc. : Nexus Device (MTP) (18d1:4ee1)
            : USB\VID_18D1&PID_4EE1\0A011JEC206170
            : (Defined at Interface level) (00/00/00)
            :  0 - Imaging / Still Image Capture / Picture Transfer Protocol (PIMA 15470) (06/01/01)
    
  2. Attach the device with sudo -b usbip-attach <busid>

  3. When finished run sudo usbip-detach to stop the auto-attach script.