Share a USB dongle bluetooth (BLE) over IP using usb2ip

2021-05-17T20:00Z


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!