Overview
Today I have got a crazy idea.
For a IoT project I need to control a remote usb dongle bluetooth (BLE) from a raspberry pi 4+. Why? I want to run a single program from a server that drives many devices remotely. It's possible? Yes with linux you can!
The solution is called usb2ip
The USB/IP Project aims to develop a general USB device sharing system over IP network. To share USB devices between computers with their full functionality, USB/IP encapsulates "USB I/O messages" into TCP/IP payloads and transmits them between computers. Original USB device drivers and applications can be also used for remote USB devices without any modification of them.
What do you need?
- Raspberry PI 3+
- USB Dongle BLE
- PC Linux
Server (Raspberry PI 3+)
First of all we have to check the initial state of the devices that are installated on the our raspberry pi.
Then connect via SSH to raspbian and run the following commands:
lsusb && hciconfig
As you can see lsusb show a BLE tongle identified by 0a12:0001 (this value is very important, it's called usbid, save it!)
Bus 001 Device 003: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
hciconfig instead shows the bluetooth device address of our BLE device, it is active and running.
Configure the usb2ip server
The following steps will configure the usb2ip server.
sudo su
apt-get install usbip
modprobe usbip_host
echo 'usbip_host' >> /etc/modules
nano /lib/systemd/system/usbipd.service
[Unit]
Description=usbip host daemon
After=network.target
[Service]
Type=forking
ExecStart=/usr/sbin/usbipd -D
ExecStartPost=/bin/sh -c "/usr/sbin/usbip bind --$(/usr/sbin/usbip list -p -l | grep '#usbid=0a12:0001 #' | cut '-d#' -f1)"
ExecStop=/bin/sh -c "/usr/sbin/usbip unbind --$(/usr/sbin/usbip list -p -l | grep '#usbid=0a12:0001 #' | cut '-d#' -f1); killall usbipd"
[Install]
WantedBy=multi-user.target
NB. You need to replace usbid 0a12:0001 with your usbid ble device.
sudo systemctl --system daemon-reload
sudo systemctl enable usbipd.service
sudo systemctl start usbipd.service
Client (Ubuntu 20.04+)
Before start check how many bluetooth devices are active on the client. It is possibile running hciconfig
As you can see at this moment we have only a device, called hci0, this is the built-in bluetooth.
Check now our usb devices (by running lsub):
Configure the client
sudo su
apt-get install linux-tools-generic -y
modprobe vhci-hcd
echo 'vhci-hcd' >> /etc/modules
nano /lib/systemd/system/usbip.service
[Unit]
Description=usbip client
After=network.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/sh -c "/usr/lib/linux-tools/$(uname -r)/usbip attach -r 192.168.1.148 -b $(/usr/lib/linux-tools/$(uname -r)/usbip list -r 192.168.1.148 | grep '0a12:0001 ' | cut -d: -f1)"
ExecStop=/bin/sh -c "/usr/lib/linux-tools/$(uname -r)/usbip detach --port=$(/usr/lib/linux-tools/$(uname -r)/usbip port | grep '<Port in Use>' | sed -E 's/^Port ([0-9][0-9]).*/\1/')"
[Install]
WantedBy=multi-user.target
NB. You have to replace 192.168.1.148 and 0a12:0001 with the values of the raspberry'ip and subid of the usb ble tongle.
sudo systemctl --system daemon-reload
sudo systemctl enable usbip.service
sudo systemctl start usbip.service
Thats' all!
To verify that the installation is correct you can run hciconfig on your client. You should see a new device with the bluetooth address of the ble dongle installed on the raspberry pi.
FAQ
usbip: error: open vhci_driver
If usbip service failed to start on the client:
sudo systemctl start usbip.service
sudo systemctl status usbip.service
-> libusbip: error: udev_device_new_from_subsystem_sysname failed
-> usbip: error: open vhci_driver
Rerun modprobe command
sudo su
modprobe vhci-hcd
sudo systemctl start usbip.service
What's next?
What if I want to share the main bluetooth device (/dev/serial1 -> /dev/ttyAMA0) and not an external dongle? We can try with net2ser, but this needs a new article!
Stay tuned!