First appearing in 2005 in Takahiro Hirofuchi's kickass paper, there are much better guides on USB/IP, like Linux Magazine's, Ridgerun's, etc. From 2009 USB/IP was accepted into mainline Linux kernel and up-to-date documentation on it tends to get lost in the Linux haystack. The wrinkle here is USB/IP running on Slackware 14.2-current as of July 2019. Unlike Debian/Ubuntu you cannot usually seamlessly install USB/IP (or most other things) on Slackware. A little DIY is in order.
I know that is cold comfort compared to Debian's 'apt install'. Indeed, Slackware too has its (a little rickety) SlackBuild scripts. But in USB/IP case there is no SlackBuild as it was already included in the kernel. Well, after a fashion.
But take heart: in 30 years of Slackware I seldom fail to install the things I want. This is a chance to poke a little into the innards of Linux. You have the source code in all its glory. And it is built beautifully - I say this as one who has seen Microsoft Windows NT source code [shudder].
And the experience will prove useful in the rare instances Debian's installs fail, like the time I installed the Java development kit and could no longer log into my desktop. This means when things fail the same methods work: paste the error into google and look for the patches and workarounds. But I digress; back to USB/IP.
I should test my Acer aspireM3's USB webcam before the install breaks things:
# mplayer tv:// -tv driver=v4l2:width=640:height=480 -vo xv -tv device=/dev/video1
Let's verify that my Slackware kernel actuall has USB/IP:
root@aspireM3:~# ls -lR /usr/src/linux/ | grep -i usbip
-rw-r--r-- 1 root root 1172 Jan 26 2019 sysfs-platform-usbip-vudc
-rw-r--r-- 1 root root 23365 Jan 26 2019 usbip_protocol.txt
drwxr-xr-x 2 root root 4096 Jan 26 2019 usbip/
/usr/src/linux/drivers/usb/usbip:
-rw-r--r-- 1 root root 18694 Jan 26 2019 usbip_common.c
-rw-r--r-- 1 root root 10117 Jan 26 2019 usbip_common.h
-rw-r--r-- 1 root root 3969 Jan 26 2019 usbip_event.c
drwxr-xr-x 3 root root 4096 Jan 27 2019 usbip/
Looks good. A look at the kernel's config file shows that the binary has not been left out at compile time:
root@aspireM3:~# grep -i usbip /usr/src/linux/.config
CONFIG_USBIP_CORE=m
CONFIG_USBIP_VHCI_HCD=m
CONFIG_USBIP_VHCI_HC_PORTS=8
CONFIG_USBIP_VHCI_NR_HCS=1
CONFIG_USBIP_HOST=m
# CONFIG_USBIP_DEBUG is not set
And finally, locate the kernel modules (ie device drivers) themselves:
# ls -l /lib/modules/4.19.18/kernel/drivers/usb/usbip
total 128
-rw-r--r-- 1 root root 22576 Jan 27 2019 usbip-core.ko
-rw-r--r-- 1 root root 42480 Jan 27 2019 usbip-host.ko
-rw-r--r-- 1 root root 58016 Jan 27 2019 vhci-hcd.ko
And it runs OK:
# modprobe -v usbip-core
insmod /lib/modules/4.19.18/kernel/drivers/usb/usbip/usbip-core.ko
Let's launch the USB/IP server daemon:
# usbipd -D
-su: usbipd: command not found
Oops. The userspace binaries are not installed. Let's see if my Slackware installation has the userspace source code:
# ls -l /usr/src/linux/tools/usb/usbip/src
total 96
-rw-r--r-- 1 root root 440 Jan 26 2019 Makefile.am
-rw-r--r-- 1 root root 4406 Jan 26 2019 usbip.c
-rw-r--r-- 1 root root 1292 Jan 26 2019 usbip.h
-rw-r--r-- 1 root root 5404 Jan 26 2019 usbip_attach.c
-rw-r--r-- 1 root root 5169 Jan 26 2019 usbip_bind.c
-rw-r--r-- 1 root root 2922 Jan 26 2019 usbip_detach.c
-rw-r--r-- 1 root root 9713 Jan 26 2019 usbip_list.c
-rw-r--r-- 1 root root 6179 Jan 26 2019 usbip_network.c
-rw-r--r-- 1 root root 5295 Jan 26 2019 usbip_network.h
-rw-r--r-- 1 root root 1536 Jan 26 2019 usbip_port.c
-rw-r--r-- 1 root root 3494 Jan 26 2019 usbip_unbind.c
-rw-r--r-- 1 root root 15083 Jan 26 2019 usbipd.c
-rw-r--r-- 1 root root 1630 Jan 26 2019 utils.c
-rw-r--r-- 1 root root 863 Jan 26 2019 utils.h
Yes, I do. I just need to compile it but it fails:
/usr/src/linux/tools/usb/usbip# ./autogen.sh
/usr/src/linux/tools/usb/usbip# ./configure
/usr/src/linux/tools/usb/usbip# make
make all-recursive
make[1]: Entering directory '/usr/src/linux-4.19.18/tools/usb/usbip'
Making all in libsrc
make[2]: Entering directory '/usr/src/linux-4.19.18/tools/usb/usbip/libsrc'
CC libusbip_la-usbip_device_driver.lo
usbip_device_driver.c: In function �..read_usb_vudc_device�..:
usbip_device_driver.c:106:2: error: �..strncpy�.. specified bound 256 equals destination size [Werror=stringop-truncation]
strncpy(dev->path, path, SYSFS_PATH_MAX);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
usbip_device_driver.c:125:2: error: �..strncpy�.. specified bound 32 equals dest
ination size [-Werror=stringop-truncation]
strncpy(dev->busid, name, SYSFS_BUS_ID_SIZE);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[2]: *** [Makefile:471: libusbip_la-usbip_device_driver.lo] Error 1
make[2]: Leaving directory '/usr/src/linux-4.19.18/tools/usb/usbip/libsrc'
make[1]: *** [Makefile:497: all-recursive] Error 1
make[1]: Leaving directory '/usr/src/linux-4.19.18/tools/usb/usbip'
make: *** [Makefile:365: all] Error 2
It does not look serious. What used to be a compiler warning has now been classified as an error so the compiler obligingly stops. A quick google comes up with a patch:
https://patchwork.kernel.org/project/linux-usb/patch/20180721021232.GR14131@deca
dent.org.uk/
> +++ b/tools/usb/usbip/libsrc/usbip_common.c
> @@ -226,8 +226,8 @@ int read_usb_device(struct udev_device *
> path = udev_device_get_syspath(sdev);
> name = udev_device_get_sysname(sdev);
>
> - strncpy(udev->path, path, SYSFS_PATH_MAX);
> - strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE);
> + snprintf(udev->path, SYSFS_PATH_MAX, "%s", path);
> + snprintf(udev->busid, SYSFS_BUS_ID_SIZE, "%s", name);
So I just edit usbip_device_driver.c:
# vi libsrc/usbip_device_driver.c
And at line 106
strncpy(dev->path, path, SYSFS_PATH_MAX);
Is changed to
// strncpy(dev->path, path, SYSFS_PATH_MAX); cmheong 2021-03-27
snprintf(dev->path, SYSFS_PATH_MAX, "%s", path);
At line 125:
strncpy(dev->busid, name, SYSFS_BUS_ID_SIZE);
Became
snprintf(dev->busid, SYSFS_BUS_ID_SIZE, "%s", name);
Anow for the file usbip_common.c line 230:
// strncpy(udev->path, path, SYSFS_PATH_MAX); // cmheong 2021-03-27
// strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE);
Becomes
snprintf(udev->path, SYSFS_PATH_MAX, "%s", path);
snprintf(udev->busid, SYSFS_BUS_ID_SIZE, "%s", name);
Now some Slackware versions, depending on the date of your install, you might get an additional error:
CC usbip_network.o
usbip_network.c: In function âusbip_net_pack_usb_deviceâ:
usbip_network.c:91:32: error: taking address of packed member of âstruct usbip_
usb_deviceâ may result in an unaligned pointer value [-Werror=address-of-packed
-member]
91 | usbip_net_pack_uint32_t(pack, &udev->busnum);
| ^~~~~~~~~~~~~
We just need to tell the compiler not to freak out and treat the warning as an error. This can be done by changing line 12174 of the 'configure' file:
/usr/src/linux/tools/usb/usbip$vi configure
EXTRA_CFLAGS="-Wall -Wno-error=address-of-packed-member -Werror -Wextra -std=gnu
99"
After which the compile completes successfully:
# make
make all-recursive
make[1]: Entering directory '/usr/src/linux-4.19.18/tools/usb/usbip'
Making all in libsrc
make[2]: Entering directory '/usr/src/linux-4.19.18/tools/usb/usbip/libsrc'
CC libusbip_la-usbip_common.lo
CC libusbip_la-usbip_host_common.lo
CC libusbip_la-vhci_driver.lo
CC libusbip_la-sysfs_utils.lo
CCLD libusbip.la
make[2]: Leaving directory '/usr/src/linux-4.19.18/tools/usb/usbip/libsrc'
Making all in src
make[2]: Entering directory '/usr/src/linux-4.19.18/tools/usb/usbip/src'
CC usbip.o
CC utils.o
CC usbip_network.o
CC usbip_attach.o
CC usbip_detach.o
CC usbip_list.o
CC usbip_bind.o
CC usbip_unbind.o
CC usbip_port.o
CCLD usbip
CC usbipd.o
CCLD usbipd
make[2]: Leaving directory '/usr/src/linux-4.19.18/tools/usb/usbip/src'
make[2]: Entering directory '/usr/src/linux-4.19.18/tools/usb/usbip'
make[2]: Leaving directory '/usr/src/linux-4.19.18/tools/usb/usbip'
make[1]: Leaving directory '/usr/src/linux-4.19.18/tools/usb/usbip'
Now the server daemon runs:
# /usr/src/linux/tools/usb/usbip/src/usbipd -D
A quick check:
/usr/src/linux/tools/usb/usbip# ps -ef | grep -e usbip
root 23597 2 0 14:57 ? 00:00:00 [usbip_event]
root 23608 1 0 19:53 ? 00:00:00 /usr/src/linux/tools/usb/usbip/src/.libs/lt-usbipd -D
root 23835 1533 0 19:54 pts/0 00:00:00 grep -e usbip
Next we list the USB devices available to the server:
/usr/src/linux/tools/usb/usbip# /usr/src/linux/tools/usb/usbip/src/usbip list --local
- busid 1-3.1 (0835:8501)
Action Star Enterprise Co., Ltd : unknown product (0835:8501)
- busid 1-3.2 (046d:c077)
Logitech, Inc. : M105 Optical Mouse (046d:c077)
- busid 1-3.3 (13ba:0017)
PCPlay : PS/2 Keyboard+Mouse Adapter (13ba:0017)
- busid 1-3.4 (10c4:ea60)
Cygnal Integrated Products, Inc. : CP2102/CP2109 UART Bridge Controller [CP21
0x family] (10c4:ea60)
- busid 1-3.5.1 (0835:8502)
Action Star Enterprise Co., Ltd : unknown product (0835:8502)
- busid 1-3.5.2 (046d:0829)
Logitech, Inc. : unknown product (046d:0829)
- busid 1-3.5.4 (0c45:62f1)
Microdia : unknown product (0c45:62f1)
- busid 2-1.3 (04f2:b300)
Chicony Electronics Co., Ltd : unknown product (04f2:b300)
- busid 2-1.4 (04ca:3006)
Lite-On Technology Corp. : unknown product (04ca:3006)
Using the displayed busis, we use 'lsusb -v' to zero in on the webcam:
Bus 002 Device 003: ID 04f2:b300 Chicony Electronics Co., Ltd
iManufacturer 1 Chicony Electronics Co., Ltd.
iProduct 2 HD WebCam
iSerial 3 SN0001
- busid 2-1.3 (04f2:b300)
Now I need to launch another kernel module:
# modprobe -v usbip-host
insmod /lib/modules/4.19.18/kernel/drivers/usb/usbip/usbip-host.ko
We now have the USB/IP server grab the webcam:
/usr/src/linux/tools/usb/usbip# /usr/src/linux/tools/usb/usbip/src/usbip bind --busid=2-1.3
usbip: info: bind device on busid 2-1.3: complete
Now we move over to the other (ie client) computer, and repeat the process of installing USB/IP. We then launch the USB/IP kernel client modules:
/usr/src/linux/tools/usb/usbip$modprobe -v vhci-hcd
insmod /lib/modules/4.19.62/kernel/drivers/usb/usbip/usbip-core.ko
insmod /lib/modules/4.19.62/kernel/drivers/usb/usbip/vhci-hcd.ko
Let's say the server's IP address is 12.34.56.78. We can see what USB device on the server is available over IP:
/usr/src/linux/tools/usb/usbip$src/usbip list --remote=12.34.56.78
Exportable USB devices
======================
- 12.34.56.78
2-1.3: Chicony Electronics Co., Ltd : unknown product (04f2:b300)
: /sys/devices/pci0000:00/0000:00:1a.0/usb2/2-1/2-1.3
: Miscellaneous Device / ? / Interface Association (ef/02/01).
Ah it is a webcam ;7) We attach to it:
/usr/src/linux/tools/usb/usbip# /usr/src/linux/tools/usb/usbip/src/usbip attach -debug --remote=12.34.56.78 --busid=2-1.3
And we play the remote (ie server) webcam by using mplayer:
/usr/src/linux/tools/usb/usbip$ mplayer -cache 128 -tv device=/dev/video2:driver=v4l2:width=640:height=480:outfmt=i420 -vo xv tv://
Note that here I access /dev/video2, since my client laptop also has a webcam at /dev/video1, and the USB/IP attach made a new one at /dev/video2. Also the server webcam resolution is 1080 x 720 but that seemed to mave maxed out my old 100Mbps fiber link. Dropping the resolution down to 640 x 480 worked out well.
You can see your attached USB device using:
/usr/src/linux/tools/usb/usbip$src/usbip port --remote=12.34.56.78
Imported USB devices
====================
Port 00: <Port in Use> at High Speed(480Mbps)
Chicony Electronics Co., Ltd : unknown product (04f2:b300)
3-1 -> usbip://192.168.1.4:3240/3-1.3
-> remote bus/dev 003/003
Notice the port number 00. We will be needing it. Lastly once you are through with the webcam you release it so another computer can use it:
/usr/src/linux/tools/usb/usbip$src/usbip detach --port=00
usbip: info: Port 0 is now detached!
There you have it. USB/IP comes standard with Linux, and lets you access USB devices remotely. I had great fun spending an afternoon doing this to the
boogie blues. Here's a video of Daisy tapping her feet to it:
Happy Trails.
No comments:
Post a Comment