There is often the task of connecting a USB device to a remote PC over a local network. Below is a narrative of my search in this area, and the path to a ready solution based on an open-source project. with a description of the various obstacles lovingly installed by different people along the way, as well as ways to circumvent them.
Part one, historical
If the machine is virtual, all of this is not difficult. The USB passthrough functionality from host to virtual machine appeared back in VMWare 4.1. But in my case, the protection key, recognized as WIBU-KEY, needed to be connected at different times to different machines, not just virtual ones.
The first round of my search in the distant 2009 led me to a device called
Pros:
- sometimes even works
Cons:
- does not always work. For instance, the Guardant Stealth II protection key does not start through it, complaining with an error "the device cannot be started."
- The management software (or rather, the software for mounting and unmounting USB devices) is extremely poor. Command line keys, automation—no, they haven't heard of it. Everything is done manually. A nightmare.
- The management software searches for the device in the network through broadcasting, which means it only works within one broadcast segment of the network. You cannot manually specify the IP address of the device. Is the device in another subnet? Then you have a problem.
- The developers have abandoned the device; sending bug reports is useless.
The second round occurred in more recent times and led me to the topic of this article— . It attracts due to its openness, especially since the folks at signed a driver for Windows for it, so now even on x64 everything works without any hacks like test mode. Huge thanks to the ReactOS team! It all sounds great; let's see if it holds up in reality? Unfortunately, the project itself is also somewhat abandoned, and support shouldn’t be expected—but where there’s a will, there’s a way; the source code is available, we will figure it out!
Part two, server-linux
The USB/IP server, which shares USB devices over the network, can only be set up in a Linux-based OS. Well, Linux it is, we install Debian 8 on a virtual machine in minimal configuration; a standard procedure:
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install usbipWe've installed it. Next, the internet suggests that we need to load the usbip module, but — hello, here comes the first hurdle. There is no such module. This is all because most guides on the network refer to an older branch 0.1.x, while in the latest 0.2.0, the usbip modules have different names.
Therefore:
sudo modprobe usbip-core
sudo modprobe usbip-host
sudo lsmod | grep usbipNow let's add these lines to /etc/modules to load them automatically at system startup:
usbip-core
usbip-host
vhci-hcdLet's start the usbip server:
sudo usbipd -DNext, the collective intelligence tells us that with usbip come scripts that allow us to manage the server — to show which device it will share over the network, check the status, and so on. Another hurdle awaits us here — these scripts in the 0.2.x branch have again been renamed. We can get a list of commands using
sudo usbipAfter reading the command descriptions, it becomes clear that to share the desired USB device, usbip wants to know its Bus ID. Dear viewers, here comes hurdle number three: the Bus ID that will be given to us lsusb (it seems to be the most obvious way) — is not suitable! The thing is that hardware like USB hubs is ignored by usbip. So, let's 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: here and in the listings below, I will describe everything using my specific USB key as an example. The names of your hardware and the VID:PID pair may 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: completeHooray, 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 has shared the device over the network, and we can connect it! Now we just need to add the auto-start for the usbip daemon in /etc/rc.local
usbipd -DPart three, the client side and confusing
I immediately tried to connect the shared device over the network to a machine running Debian on the same server, and everything connected perfectly:
sudo usbip attach --remote=localhost --busid=1-1Now, let's move on to Windows. In my case, it was Windows Server 2008R2 Standard Edition. The official guide asks to first install the driver. The procedure is well described in the readme attached to the Windows client, we follow the instructions, and everything works out. It also works on XP without any issues.
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 deviceOh no. Something went wrong. Let's use our Google skills. There are scattered mentions that something is off with the constants; the developers changed the protocol version in the server part when moving to version 0.2.0, but in the Windows client, they forgot to do that. The suggested solution is to change the constant in the source code and recompile the client.
But I really don't want to download Visual Studio for this procedure. However, I have the good old Hiew. In the source, the constant is declared as a double word. Let's search in the file 0x00000106, replacing it with 0x00000111. Don’t forget, the byte order is reversed. Result — two matches, we patch:
[usbip.exe]
00000CBC: 06 11
00000E0A: 06 11And yes!
C:Program FilesUSB-IP>usbip -a %server-ip% 1-1
new usb device attached to usbvbus port 1At this point, I could wrap up the description, but the music didn't play for long. After restarting the server, I found that the device wouldn't mount on the client!
C:Program FilesUSB-IP>usbip -a %server-ip% 1-1
usbip err: usbip_windows.c: 829 (attach_device) cannot find deviceAnd that’s it. Even the all-knowing Google couldn't answer this for me. Meanwhile, the command to display available devices on the server works perfectly — there it is, the key, ready to be mounted. I try to mount it from Linux — it works! But what if I try from Windows now? Oh horror — it works!
Final stumbling block: something in the server code isn't fully implemented. When sharing the device, it doesn’t read the number of USB descriptors. However, when mounting the device from Linux, this field gets filled. Unfortunately, my experience with Linux development is at the level of 'make && make install'. So, the problem was solved with a rather dirty hack — adding to /etc/rc.local
usbip attach --remote=localhost --busid=1-1
usbip port
usbip detach --port=00Final part
After some trials and tribulations, it works. The desired outcome has been achieved, and now the key can be mounted on any PC (and of course unmounted too), including beyond the broadcast segment of the network. If desired, this can be done with a shell script. The best part is that it's completely free of charge.
I hope my experience helps fellow Hubrazhitel to avoid the pitfalls that have left their mark on me. Thank you for your attention!
Source: habr.com
