Finders, Keepers
Tutorial – USB/IP
The Linux kernel has many interesting but unknown services. USB/IP, in particular, is one that you'll probably wonder why you have never encountered. USB/IP lets you use USB devices connected to other machines on your network as if they were plugged directly into your computer.
This happened to me recently: I have an oldish Brother multifunction printer/scanner/fax machine. It is an okay thing to have and quite useful, but it is as dumb as brick and has no network capabilities at all. This means you must have a computer plugged into it directly if you need to use it. If you want to share it over a network, which of course you do, you have to make the computer a server and have it manage the network side of things.
Brother supplies some drivers for Linux, but they are closed source. This means that, if something doesn't work, you face a familiar conundrum: Firstly, Brother will not assign an engineer to sort out a problem for a system used by a minority of desktop users and a machine that is at least seven years old. Secondly, you can't solve things yourself because the drivers are closed source.
Unfortunately for me, something doesn't work.
Brother's scanner driver refuses to play ball with SANE's network printing protocol. That means, if I want to scan without lifting my laptop off the table, walking into the living room, unplugging it from the server, and attaching my computer directly to the lunk, I have to proceed as follows:
- Open an SSH session from my laptop to the server.
- Scan from the command line with
scanimage
. - Copy the file that
scanimage
creates over to my laptop usingscp
, and open it in an image visualizing program. - Make sure that the scan is the correct in size, color, contrast, and alignment.
- If not, get up and adjust the piece of paper and the
scanimage
flags - Start all over again.
This is less than ideal, especially when you have graphical utilities, like, say, XSane [1], a comprehensive graphical application for all your scanning needs.
Is there a way to make the process less cumbersome? Thankfully, there is. It's called USB/IP (read: USB over IP); it is a set of modules and tools that comes with all modern kernels from 3.17 onwards. USB/IP allows you to set up a USB server on one machine (e.g., on your printer/scanner server) and share it with the rest of your network as if it were connected directly to the client machine.
USB/IP in Practice
This may sound like a godsend, but USB/IP, precisely because not very many people use it, is a bit finicky. All distributions provide the modules, as they are a standard part of modern kernels. The suitability of the tools you need for setting up the server and sharing to the client, however, is a different matter. The combination that worked for me was to use an up-to-date Debian as a server, and machines loaded with Ubuntu and KDE neon (which is currently based on Ubuntu 16.04) as clients. If you try anything else, the steps you follow should be very similar, but your mileage may vary.
Although the USB/IP modules (usbip-core
, usb-host
, and vhci-hcd
) are standard, you will have to install the tools that allow you to set up a server and start a client. In Debian, the package you need is called simply usbip
, but Ubuntu's usbip
package contains out-dated and flawed versions of the software. I have no idea why this exists – very confusing. If you have installed the usbip package before reading this, purge it now. What you are looking for is a package called linux-tools-generic
. Install that.
Once you have everything installed on your server and clients, connect to the machine that will act as the USB/IP server and load two modules into the kernel:
su -c "modprobe usbip-core; modprobe usbip-host"
Then to start the server; still as root, do:
su -c "usbipd"
By starting the server like this, you will be able to see what it is doing. Your computer will display the machines that try to connect and show whether they are successful. This will help you troubleshoot during the first few runs. Once you are confident everything works as it should, you may want to run the server with the -D
flag:
su -c "usbipd -D"
This will push usbipd
to the background and have it run as a daemon.
You can now check what USB devices you can share. To do this, use the instruction shown in Listing 1, line 1. The list
command is, as its name implies, for listing devices. The -l
flag tells usbip
to list the devices connected "locally." As you will see later, you use a similar instruction to find out which devices are available on the server from the client.
Listing 1
Shareable Devices
$ su - c "usbip list -l" - busid 1-1 (0474:025f) Sanyo Electric Co., Ltd : unknown product (0474:025f) - busid 1-2 (04f9:01eb) Brother Industries, Ltd : MFC-7320 (04f9:01eb) - busid 1-4 (8087:0a2a) Intel Corp. : unknown product (8087:0a2a)
As Listing 1 shows, there seems to be three devices you can share, but really there are only two: The last one (busid 1-4
) is the machine's internal USB hub doohickey (pretty sure that's its technical name). The two devices you can share are busid 1-1
, a Sanyo webcam, and busid 1-2
, the multifunction printer/scanner/fax machine I mentioned earlier.
Notice that, in the case of the webcam, the server has no idea what the device is. But, then again, it doesn't have to: The task of figuring out what a device is and how to use it falls to the client.
The next step is binding a device to the server, so it can be shared. To bind a device, you have to pass the device's bus ID to the server:
su -c "usbip bind -b 1-1"
The -b
stands for "bus ID," and, as per Listing 1, the instruction above shares the Sanyo video camera.
To share the printer/scanner, you should do this:
su -c "usbip bind -b 1-2"
To stop sharing a device, you should use the unbind
command. The command:
su -c "usbip unbind -b 1-2"
disconnects the printer/scanner from the server, for example.
Client Side
To get the Ubuntu/neon client set up (see the "Ubuntu Paths" box), load the modules you need into the kernel:
sudo modprobe usbip-core sudo modprobe vhci-hcd
To query the server and see what devices it has on offer, use another variant of the list
instruction:
sudo usbip list -r <server>
where <server>
is the name or IP address of the USB/IP server. Listing 2 shows what querying the server looks like.
Listing 2
Querying the Server
$ sudo usbip list -r 192.168.1.24 Exportable USB devices ====================== - 192.168.1.24 1-2: Brother Industries, Ltd : MFC-7320 (04f9:01eb) : /sys/devices/pci0000:00/0000:00:14.0/usb1/1-2 : (Defined at Interface level) (00/00/00) 1-1: Sanyo Electric Co., Ltd : unknown product (0474:025f) : /sys/devices/pci0000:00/0000:00:14.0/usb1/1-1 : Miscellaneous Device / ? / Interface Association (ef/02/01)
Ubuntu Paths
Ubuntu saves the USB/IP tools in a weird place that is not in your $PATH
. This makes calling usbip
cumbersome, since you have to prepend the whole path (/usr/lib/linux-tools-<version number>/
) each time you want to use it.
This gets boring quickly, so you may want to make a soft link to the tool somewhere in your path. As it is a command you should issue only with root privileges, you can do:
sudo ln -s /usr/lib/flfl linux-tools-<version number>/usbip /usr/sbin/
For the rest of the article, I'll assume you have done that.
The listing gives you the two devices, the printer/scanner and the webcam, that the server is sharing.
To start using a device, you have to first attach
it
:
sudo usbip attach -r <server> -b <bus ID>
As before, <server>
is your server machine's name or IP (-r
stands for "remote") and <bus ID>
is the bus ID of the device, as shown using the list
command in Listing 2.
To attach the Sanyo webcam shown in Listing 2, for example, you should do this:
sudo usbip attach -r 192.168.1.24 -b 1-1
Note that some versions of usbip
use -h
(for "host") instead of -r
.
If everything goes well, the device should now show up on your system as if it were plugged directly into one of your USB ports. Listing 3 shows what the list of USB devices looks like on the client. Figure 1 shows what it looks like to see yourself from your laptop's webcam and from a webcam connected to the USB server several feet away.
Listing 3
Client USB Devices
$ lsusb <Bus 003 Device 004: ID 0474:025f Sanyo Electric Co., Ltd> Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 003: ID 058f:d102 Alcor Micro Corp. Bus 001 Device 002: ID 8087:0a2a Intel Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Attaching the printer/scanner had the interesting effect of providing the client with two printers: one network printer via CUPS and one virtual USB-connected printer (Figure 2), even though both are the same physical machine.
Just to show how the client sees the printers differently, take a look at Figure 3. On the left is what you get if you tell the CUPS network printer to print a test page – it is the server that sends the test page to the printer, hence the Debian/CUPS logos. By contrast, on the right is the test page from the virtual USB/IP printer. As the machine "thinks" the printer is connected locally to one of its USB ports, it sends its own, internal test page.
With a bit of fiddling (and by "a bit" I mean "hours of hair-wrenching frustration") you can get even the most stubborn scanner to work as it should (Figure 4).
Detaching
Devices that are attached to a client via USB/IP are blocked for the rest of the network, so at some point, you will want to detach them and let others use them.
To detach a device, first you need to know to which virtual port each device is attached. Listing 4 shows an example from a client with the printer/scanner and webcam attached. If you are not sure which device is which, look at the vendor/product line and compare the numbers in brackets with what you get from lsusb
.
Listing 4
Connected Ports
$ sudo usbip port Imported USB devices ==================== Port 00: <Port in Use> at High Speed(480Mbps) unknown vendor : unknown product (0474:025f) 8-1 -> usbip://192.168.1.24:3240/1-1 -> remote bus/dev 001/002 Port 01: <Port in Use> at Full Speed(12Mbps) unknown vendor : unknown product (04f9:01eb) 8-2 -> usbip://192.168.1.24:3240/1-2 -> remote bus/dev 001/004
Armed with the port number, you can detach a device with:
sudo usbip detach -p <port number>
So, to detach the printer/scanner ( in Listing 4), do:
sudo usbip detach -p 01
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
AlmaLinux 10.0 Beta Released
The AlmaLinux OS Foundation has announced the availability of AlmaLinux 10.0 Beta ("Purple Lion") for all supported devices with significant changes.
-
Gnome 47.2 Now Available
Gnome 47.2 is now available for general use but don't expect much in the way of newness, as this is all about improvements and bug fixes.
-
Latest Cinnamon Desktop Releases with a Bold New Look
Just in time for the holidays, the developer of the Cinnamon desktop has shipped a new release to help spice up your eggnog with new features and a new look.
-
Armbian 24.11 Released with Expanded Hardware Support
If you've been waiting for Armbian to support OrangePi 5 Max and Radxa ROCK 5B+, the wait is over.
-
SUSE Renames Several Products for Better Name Recognition
SUSE has been a very powerful player in the European market, but it knows it must branch out to gain serious traction. Will a name change do the trick?
-
ESET Discovers New Linux Malware
WolfsBane is an all-in-one malware that has hit the Linux operating system and includes a dropper, a launcher, and a backdoor.
-
New Linux Kernel Patch Allows Forcing a CPU Mitigation
Even when CPU mitigations can consume precious CPU cycles, it might not be a bad idea to allow users to enable them, even if your machine isn't vulnerable.
-
Red Hat Enterprise Linux 9.5 Released
Notify your friends, loved ones, and colleagues that the latest version of RHEL is available with plenty of enhancements.
-
Linux Sees Massive Performance Increase from a Single Line of Code
With one line of code, Intel was able to increase the performance of the Linux kernel by 4,000 percent.
-
Fedora KDE Approved as an Official Spin
If you prefer the Plasma desktop environment and the Fedora distribution, you're in luck because there's now an official spin that is listed on the same level as the Fedora Workstation edition.