Taming USB/IP

The task of connecting a USB device to a remote PC via a local network regularly arises. Under the cut, the history of my searches in this direction is set out, and the path to a ready-made solution based on an open-source project USB/IP with a description of the obstacles carefully set by various people on this path, as well as ways to bypass them.

Part One, Historical

If the machine is virtual - all this is easy. The functionality of USB forwarding from a host to a virtual machine appeared in VMWare 4.1. But in my case, the security key, recognizable as WIBU-KEY, had to be connected at different times to different machines, and not only virtual ones.
The first round of search in the distant 2009 led me to a piece of iron called TrendNet TU2-NU4
Pros:

  • sometimes it even works

Cons:

  • does not always work. Suppose the Guardant Stealth II protection key does not start through it, swearing with the error β€œdevice cannot be started”.
  • Management software (read - mounting and unmounting USB devices) is pathetic to the extreme. Command line switches, automation - no, have not heard. Everything is just by hand. Nightmare.
  • the control software searches for the piece of iron itself in the network by broadcasting, so this only works within one broadcast network segment. You cannot specify the IP address of the piece of iron by hand. A piece of iron in other subnet? Then you have a problem.
  • developers scored on the device, it is useless to send bug reports.

The second round happened in times not so distant, and led me to the topic of the article - USB/IP project. Attracts with openness, especially since the guys from ReactOS they signed a driver for Windows, so now everything works even on x64 without any crutches like a test mode. For which many thanks to the ReactOS team! Everything sounds beautiful, let's try to feel it, is it really so? Unfortunately, the project itself is also abandoned, and you can’t count on support - but where ours didn’t disappear, the source is there, we’ll figure it out!

Part two, server-linux

A USB/IP server that shares USB devices over a network can only be set up on a Linux-based OS. Well, Linux is Linux, so install on the Debian 8 virtual machine in the minimum configuration, standard hand movement:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install usbip

Settled. Further, the Internet suggests that you would need to download the usbip module, but - hello, the first rake. There is no such module. And all because most of the manuals on the network refer to the older branch 0.1.x, and in the latest 0.2.0 the usbip modules have different names.

Therefore:

sudo modprobe usbip-core
sudo modprobe usbip-host
sudo lsmod | grep usbip

Well, let's add the following lines to /etc/modules to load them automatically at system startup:

usbip-core
usbip-host
vhci-hcd

Let's start the usbip server:

sudo usbipd -D

Further, the universal mind tells us that usbip comes with scripts that allow us to manage the server - show which device it will share over the network, see the status, and so on. Here another garden tool awaits us - these scripts in the 0.2.x branch, again, have been renamed. You can get a list of commands with

sudo usbip

After reading the description of the commands, it becomes clear that in order to share the required USB device, usbip wants to know its Bus ID. Dear viewers, rake number three is in the arena: the Bus ID that will give us lsusb (it would seem the most obvious way) - it does not suit her! The fact is that usbip ignores hardware like USB hubs. Therefore, we will use the built-in command:

user@usb-server:~$ sudo usbip list -l
 - busid 1-1 (064f:0bd7)
   WIBU-Systems AG : BOX/U (064f:0bd7)

Note: hereinafter in the listings I will describe everything using the example of my specific USB key. Your hardware name and VID:PID pair can and will differ. Mine is called Wibu-Systems AG: BOX/U, VID 064F, PID 0BD7.

Now we can share our device:

user@usb-server:~$ sudo usbip bind --busid=1-1
usbip: info: bind device on busid 1-1: complete

Cheers, comrades!

user@usb-server:~$ sudo usbip list -r localhost
Exportable USB devices
======================
 - localhost
        1-1: WIBU-Systems AG : BOX/U (064f:0bd7)
           : /sys/devices/pci0000:00/0000:00:11.0/0000:02:00.0/usb1/1-1
           : Vendor Specific Class / unknown subclass / unknown protocol (ff/00/ff)

Three cheers, comrades! The server shared the piece of iron over the network, and we can connect it! It remains only to add the autostart of the usbip daemon to /etc/rc.local

usbipd -D

Part three, client-side and confusing

I tried connecting the shared device over the network to a Debian machine right away on the same server, and everything connected fine:

sudo usbip attach --remote=localhost --busid=1-1

Let's move on to Windows. In my case it was Windows Server 2008R2 Standard Edition. The official guide asks you to install the driver first. The procedure is perfectly described in the readme attached to the windows client, we do everything as it is written, everything works out. On XP it also works without any problems.

After unpacking the client, we try to mount our key:

C:Program FilesUSB-IP>usbip -a %server-ip% 1-1
usbip err: usbip_network.c: 121 (usbip_recv_op_common) recv op_common, -1
usbip err: usbip_windows.c: 756 (query_interface0) recv op_common
usbip err: usbip_windows.c: 829 (attach_device) cannot find device

Oh oh. Something went wrong. We use the skill of Google. There are fragmentary mentions that something is wrong with the constants; in the server part, the developers changed the protocol version when switching to version 0.2.0, but they forgot to do this in the Win client. The proposed solution is to change the constant in the source code and rebuild the client.

But I really don’t want to download Visual Studio for the sake of this procedure. But I have a good old Hiew. In the source code, the constant is declared as a double word. Let's look in the file for 0x00000106, replacing it with 0x00000111. Remember, byte order is reversed. The result is two matches, patch:

[usbip.exe]
00000CBC: 06 11
00000E0A: 06 11

Eeeee... yes!

C:Program FilesUSB-IP>usbip -a %server-ip% 1-1
new usb device attached to usbvbus port 1

This could have ended the presentation, but the music did not play for long. After rebooting the server, I found that the device on the client is not mounted!

C:Program FilesUSB-IP>usbip -a %server-ip% 1-1
usbip err: usbip_windows.c: 829 (attach_device) cannot find device

And that's it. Even all-knowing Google could not answer this for me. And at the same time, the command to display devices available on the server quite correctly shows - here it is, the key, you can mount it. I try to mount from under Linux - it works! And if now try from under Windows? Oh shit - it works!

The last rake: something is not added in the server code. When sharing a device, it does not read the number of USB descriptors from it. And when mounting the device from under Linux, this field is filled. Unfortunately, I am familiar with development under Linux at the β€œmake && make install” level. Therefore, the problem is solved with a rather dirty hack - adding to /etc/rc.local

usbip attach --remote=localhost --busid=1-1
usbip port
usbip detach --port=00

Part final

After some fiddling, it works. The desired result has been obtained, now the key can be mounted to any PC (and unmounted, of course, too), including those outside the broadcast network segment. If you want, you can do it using a shell script. What is nice - the pleasure is absolutely free.
I hope that my experience will help habrazhiteli to get around the rake that imprinted on my forehead. Thank you for your attention!

Source: habr.com

Add a comment