Skip to content

Instantly share code, notes, and snippets.

@jennifersmith
Last active December 3, 2023 12:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jennifersmith/9ad98084037c8006777fa5115a3c2dd9 to your computer and use it in GitHub Desktop.
Save jennifersmith/9ad98084037c8006777fa5115a3c2dd9 to your computer and use it in GitHub Desktop.
Bluetooth + Bumble + Socat fun

Getting Bumble - Python Bluetooth Stack going on Mac and Linux with QEMU + UTM

I tried to follow the example here: (https://github.com/google/bumble/blob/main/examples/README.md#running-run_controllerpy-with-a-bluez-host-running-on-linux) but it may need updating to change the order of running stuff and some of the params to the example file (or I need to read it more carefully).

Step 0: Prep

Anyway, I had a freshly installed QEMU based VM running Debian Bookworm - got this started via the UTM app which was new to me and handy for this quick hack. Also useful for quick hacks, I used the default networking offerd by the UTM inteface (host networking or whatever it is called) to avoid having to deal with ports and routing. Installed a few bits, most relevantly bluez and socat.

On my host machine (mac) I cloned the Bumble repo, venv-ed, pipped and so on so I could run the example code.

(I am sure I ever knew why, but seemed to run ok after I ran pip inside my activated venv as : pip install -e . )

Step 1: Run example

In the examples directory:

 python run_controller.py F2:F3:F4:F5:F6:F7  device1.json udp:0.0.0.0:22333,VIRTUAL_MACHINE_IP:22333

(maybe it would have worked with the hostname not IP but I didn't try)

Also I cut this down to make it a bit easier to follow - only creates the one controller - see my copy

Step 2: Socat to hook up pty and udp

On the virtual machine in user home dir:

 socat -d -d -x PTY,link=./hci_pty,rawer UDP-SENDTO:HOST_MACHINE_IP:22333,bind=:22333

This creates a pseudo terminal that socat conveniently symlinks for us to ./hci_pty. The -d -d and -x parts are there to give us nice debug output of what is going through socat. It also create a socket on local port 22333 communicating with host port 22333 (I don't think they need to be the same port number- just should agree with whatever the previous command specified). Then it creates a bidirectional stream between the pty and the udp socket. Somehow (and I don't know how yet), that means stuff that comes thru the pty magically gets converted into datagrams and vice versa. Not entirely sure how socat knows when to send a datagram - must be some kind of additional signal on the pty or something?

Step 3: Fire up some monitors

As the run_controller script is emitting lots of nice-controller side output, get some host-side outputs by running btmon

sudo btmon 

(has to be sudo - something like permissions to open the management socket or something - probably fixable I guess)

Step 4: Create hci connection/device

In the home dir again on the vm:

sudo btattach -P h4 -B hci_pty

Where -B is --bredr (aka bluetooth classic) -P H4 is protocol type (this may go some way to answer my question about conversion to datagrams) and hci_pty is the link created by socat.

Step 5: Watch the aftermath

Should be able to see both host side (btmon) and controller side (run_controller.py) with lots of messages suggesting they are talking to each other. For extra fun, run hcitool commands - most of them wont work but will show some trace of the message exchange.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment