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
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.
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 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!