Introduction
Bluetooth on FreeBSD is a topic that’s fraught with some difficulty to say the least. Many modern system bluetooth chipsets are not supported ‘out of the box’ by FreeBSD drivers and the pairing / connectivity software leaves a bit to be desired.
With all that said, it is possible to get Bluetooth working with an audio headset. I have not tried to connect any other devices since my primary use case for bluetooth on FreeBSD is listening to background music while I work at my laptop.
For awhile, I used my smartphone as a primary music source and connected headphones via bluetooth to it. Eventually, I found the phone way too distracting. I like working in a focused development environment where I’m able to put my head down and work on a one thing at a time without looking up too often. Jumping from vim to musikcube and back via tmux is a tiny brain interrupt compared to looking at my phone, unlocking it, attempting to navigate the (terrible) music app and then going back to the laptop.
First off, I found this forum post immensely helpful to me when connecting my headphones: Bluetooth audio and how to connect and use bluetooth headphones on freebsd
My Lenovo T480 laptop has an Intel bluetooth chipset that’s supported by FreeBSD. However, if you do not have a supported chipset, I have personally tested an inexpensive bluetooth dongle from Amazon (Broadcom BCM20702A0) that works very well.
Installation
If you’re using the bluetooth dongle such as the one I linked to above, you can
skip the firmware and devd bits and move on to install Virtual OSS
.
Because I have a supported Intel bluetooth chipset, I have to install the intel
firmware binary blob, iwmbt-firmware
:
|
|
After installing the firmware, restart devd
to enable it:
|
|
Now install Virtual OSS
which is required for bluetooth audio to work on
FreeBSD:
|
|
Virtual OSS requires the user space character device driver (CUSE) to be loaded. Load it manually and enable loading for every boot:
|
|
Start Bluetooth Stack
The next step is to start the bluetooth stack your system.
This is an odd service start because usually I have to start the service two to three times before it will actually start.
Start the hcsecd before bluetooth (I’ll explain this service a little later):
|
|
Now start the bluetooth ubt0
device with the bluetooth service. This will
likely need to be run several times.
|
|
|
|
grumble… grumble… didn’t work…
Second time works, however. Like I said, it rarely works on the first try. I am unsure why.
|
|
Pair Headphones
If all has gone well, you should have a functional bluetooth stack. A little more work is involved in getting an audio device connected.
First, put your headphones in pairing mode. Then run an inquiry on the bluetooth stack
|
|
|
|
If your headphones are the only bluetooth enabled devices close to your system and they’re in pairing mode, there is a good chance the BD_ADDR from the inquiry are your headphones.
You can ask the BD_ADDR what it’s name is:
|
|
|
|
Oops, that’s a computer, not headphones! You can request remote name down the list of devices returned by the inquiry to find your headphones.
Once you’ve found your headphones, you’ll want to edit a couple of files to
make your life a bit easier. Remember the hcsecd
service? It runs a daemon
that listens for key requests from bluetooth devices. My headphones don’t
require a key or pin so I add nokey and 0000 as the pin. Like this:
/etc/bluetooth/hcsecd.conf
|
|
Like the /etc/hosts file, /etc/bluetooth/hosts allows you to alias BD_ADDR addresses to names. MUCH easier to remember.
/etc/bluetooth/hosts
|
|
Now restart hcsecd
. (I’m not sure if this is required)
|
|
Because we have an alias in /etc/bluetooth/hosts
, we can substitute
headphones
for the BD_ADDR in hccontrol
commands. Now it’s time to connect
your headphones to the computer via bluetooth! Make sure the headphones are in
pairing mode and execute:
|
|
|
|
For my headphones to work, I have to enable write_authentication on the HCI node. I’m not sure why this is required but my headphones do not work without it.
|
|
Now the part where the headphones actually pair. Running the following virtual_oss command creates the audio channel to my headphones and allows audio packets to flow from my laptop, into the headphone speakers and finally into my head. :)
|
|
That’s it! You should now have another DSP device listed in /dev/sndstat
|
|
|
|
Firefox
If you have pulseaudio installed and running, firefox will use it by default. Your bluetooth headphones are using OSS, not pulseaudio. There are a couple of ways to fix that.
First, configure firefox to use OSS instead of pulseaudio (FreeBSD devs compile
in OSS support with the default package.) Open up firefox and put
about:config
in the URL line. Then add the following entry:
|
|
Second, if you MUST have pulseaudio output, you can follow redirect all OSS output into pulseaudio. It adds latency to the audio but works. I’m sure there’s a better way to do this!
|
|
Embarrassing Script
I setup a script in my $HOME/bin directory called
do_bluetooth.sh
and I often have to run it several times to get it to work.
I know this is a hacky as heck but I don’t care. It’s easy to run and debug.
|
|
Blued
FreeBSD has a new bluetooth daemon called blued that’s supposed to make much of this easier (maybe). I’ll report on it once I get a chance to play with it.
UPDATE 9-6-22 I documented my blued install here