I started working on this project in the year 2007 as an employee of the company Conemis AG in Karlsruhe.
The primary goal was to share USB devices over ethernet. At this point in time it works fine with Linux, but not Windows, because you need a kernel module providing you the ability to emulate an USB host controller, which i wrote for Linux. I just started to play around with the Windows kernel a few weeks ago.
The user space part is written in C# and runs on Mono and MS.NET. It consists of some libraries and two executables (server and client).
Look at this file. It contains a self-explaining picture.
Download and read the source code.
You can download it here.
Or clone the git repositories:
# linux kernel module:
git clone git://188.8.131.52/pub/scm/git/vhci_hcd.git
# user space tools:
git clone git://184.108.40.206/pub/scm/git/Vhci.git
Requires: binutils, gcc >= ~3.x.x, gnumake, linux kernel sources >= ~2.6.18.x, ... (in short: the ability to build kernel modules)
Requires: Mono >= 2.0.1 or MS.NET >= 2.0, gnumake or Monodevelop >= 2.0 or MS Visual Studio >= 2005
Open the Solution (Vhci.sln) and just click on the "Build all" button with your preferred pointing device.
Make sure the kernel module is loaded (as root):
udev should create the character device node /dev/vhci-ctrl. You can change its mode to 666 if you like. (If you don't change it you have to run the following commands as root.)
Check if usbfs is mounted on /proc/bus/usb:
Now, choose the USB device you want to plug into your (not yet created) virtual host controller. Maybe you want to try your mouse if it is connected via USB. Make sure the device is connected. Then enter the following command to list all connected devices:
The output should look like this:
5 [RootHub of bus 5]
5.0 [Mass Storage (address: 7)]
5.1 [unconnected port]
5.2 [unconnected port]
5.3 [unconnected port]
5.4 [unconnected port]
5.5 [unconnected port]
5.6 [unconnected port]
5.7 [unconnected port]
4 [RootHub of bus 4]
4.0 [unconnected port]
4.1 [unconnected port]
3 [RootHub of bus 3]
3.0 [unconnected port]
3.1 [unconnected port]
2 [RootHub of bus 2]
2.0 [HID (address: 8)]
2.1 [HID (address: 6)]
1 [RootHub of bus 1]
1.0 [unconnected port]
1.1 [unconnected port]
In this example there are two human interface devices (HID). Actually the
first one is my mouse, the other is my keyboard. You can enter
cat /proc/bus/usb/devices' to get more information about the
Every device is identified by a few numbers (2.0 for the mouse in this example). The first number (2) is the bus number. The second number (0) represents the index of the USB port of the root hub of this bus. If you have a hub connected to your computer there may be devices with three (or even more) numbers in front of them. In such a case the second number is the index of the USB port of the root hub to which the hub is connected. And (you may have figured it out by yourself now) the third number is the index of the USB port of the hub to which the device is connected. (I think you can repeat this for four, five and six numbers on your own.) It is the physical path to the device or one branch in the tree of hubs.
The following command will create a new virtual USB host controller and will plug in the selected device.
vhciclient 2.0 # replace 2.0 with the identifier of your
This will not do any network stuff. It just forwards packets from the virtual device to the real device. (Both on the same host.)
You can enter '
vhciclient -l' or
cat /proc/bus/usb/devices' on another terminal to see the
virtual host controller with the device attached to it.
Press CTRL-C (on the terminal which runs vhciclient) to remove the virtual
hardware. The device (your mouse) will stop working. This is because your OS
does not automatically reattach the driver (usbhid) to the device after we've
freed it. Just pull the plug and put it in again. Advanched users could try to
pipe the sysfs id of the device's interface into /sys/bus/usb/drivers_probe. In
this example the command would be
echo "2-1:1.0" >/sys/bus/usb/drivers_probe'.
If everything worked as expected you can try to forward the device over ethernet now. But first you need to understand the client/server concept behind it.
The server creates the virtual host controller and listens on a tcp port for connections from clients. A client connects to the server and provides a device which is virtually plugged into the servers virtual host controller. Summarized: The device is physically connected to the client but the server speaks with the device.
Let's start the server on the host on which you want to use the device: (If you want you can run both, client and server, on the same machine, of course.)
vhciserver 4 1138
The first argument (4) means we want to create a virtual host controller with
four virtual USB ports. Therefore up to four clients can connect to this server
and plug in their devices. The second argument (1138) is the tcp port on which
this server listens for incoming connection requests. You can enter
vhciclient -l' or '
on another terminal to see the virtual host controller with no devices attached
Now, start the client on the host to which the device is physically connected:
vhciclient 2.0 bob:1138
I'm sure you can guess the meaning of the arguments. ("Take device 2.0 and give it to bob on port 1138.")