Raspberry Pi 4 bluetooth, audio

I installed NixOS on a 4Gb Raspberry Pi 4 and can’t get bluetooth and audio (that’s two issues, not a single issue about a bluetooth audio device). Had no issues running another system so no reason to suspect any kind of hardware fault.

For the install, I basically followed this, execept that I fetch the master branch from git.

Bluetooth

Did add in system configuration.nix:

    hardware.bluetooth.enable = true;
    services.blueman.enable = true;

A few command outputs:

# bluetoothctl
Agent registered
[bluetooth]# power on
No default controller available
[bluetooth]# devices
No default controller available

# rfkill
ID TYPE DEVICE      SOFT      HARD
 0 wlan phy0   unblocked unblocked

# lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 046d:c315 Logitech, Inc. Classic Keyboard 200
Bus 001 Device 003: ID 046d:c00f Logitech, Inc. MouseMan Traveler/Mobile
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

# lspci
00:00.0 PCI bridge: Broadcom Inc. and subsidiaries BCM2711 PCIe Bridge (rev 10)
01:00.0 USB controller: VIA Technologies, Inc. VL805/806 xHCI USB 3.0 Controller (rev 01)

# dmesg | grep -i blue
[   10.708661] Bluetooth: Core ver 2.22
[   10.708726] Bluetooth: HCI device and connection manager initialized
[   10.708742] Bluetooth: HCI socket layer initialized
[   10.708749] Bluetooth: L2CAP socket layer initialized
[   10.708761] Bluetooth: SCO socket layer initialized

# lsmod | grep blue
bluetooth             667648  1 btsdio
ecdh_generic           16384  1 bluetooth
rfkill                 45056  5 bluetooth,cfg80211

# lsmod | grep bt
btsdio                 20480  0
bluetooth             667648  1 btsdio

Audio

Tried a bunch of things in configuration.nix, I don’t notice any difference whether the firmwareConfig line is there or not:

  sound.enable = true;
  hardware.pulseaudio.enable = true;
  boot.loader.raspberryPi.firmwareConfig = ''
    dtparam=audio=on
    hdmi_drive=2
  '';

I only get a single bar in alsamixer. Only sound card it shows is default. I’m not very aware of sound issues, let me know what kind of ouput I can provide.

See NixOS on Raspberry Pi 4 Model B | bluetoothctl issue: No default controller available · Issue #123725 · NixOS/nixpkgs · GitHub

I’ve tried including the configuration from the linked issue, it does allow the bluetooth device to be found by rfkill and dmesg got more talkative. I still don’t have anything in bluetoothctl.

$ rfkill
ID TYPE      DEVICE      SOFT      HARD
 0 bluetooth hci0   unblocked unblocked
 1 wlan      phy0   unblocked unblocked

$ dmesg | grep -i blue
[   11.750176] Bluetooth: Core ver 2.22
[   11.750320] Bluetooth: HCI device and connection manager initialized
[   11.750355] Bluetooth: HCI socket layer initialized
[   11.750367] Bluetooth: L2CAP socket layer initialized
[   11.750386] Bluetooth: SCO socket layer initialized
[   11.782035] Bluetooth: HCI UART driver ver 2.3
[   11.782051] Bluetooth: HCI UART protocol H4 registered
[   11.782055] Bluetooth: HCI UART protocol BCSP registered
[   11.782121] Bluetooth: HCI UART protocol LL registered
[   11.782154] Bluetooth: HCI UART protocol Three-wire (H5) registered
[   11.782314] Bluetooth: HCI UART protocol Broadcom registered
[   12.378992] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[   12.379004] Bluetooth: BNEP filters: protocol multicast
[   12.379022] Bluetooth: BNEP socket layer initialized
[   13.822576] Bluetooth: hci0: command 0x0c03 tx timeout
[   21.982562] Bluetooth: hci0: BCM: Reset failed (-110)

If I’m understanding correctly what’s said in the issue, the problem is from recent kernels, but I have downgraded to this commit and this one, and none seemed to display a different behaviour.

Here is how I downgraded kernels, it seemed to work but I not really sure of what I’m doing:

{ config, pkgs, lib, ... }:
let
  old_linux_pkgs = import
    (builtins.fetchGit {
      name = "my-old-revision";
      url = "https://github.com/nixos/nixpkgs/";
      ref = "refs/heads/nixpkgs-unstable";
      rev = "0b2043f7b63fb7f57014eada5224c2f6ced4680c";
    })
    { };
  myLinuxPkg = old_linux_pkgs.linux_rpi4;
in
{
  imports = [
    "${fetchTarball "https://github.com/NixOS/nixos-hardware/archive/master.tar.gz" }/raspberry-pi/4"
  ];

  boot = {
    kernelPackages = pkgs.linuxPackages_rpi4;
  };

  nixpkgs.config.packageOverrides = pkgs: {
    linux_rpi4 = myLinuxPkg;
  };

  hardware = {
    enableRedistributableFirmware = true;
    pulseaudio = {
      enable = true;
      support32Bit = true;
      extraModules = [ pkgs.pulseaudio-modules-bt ];
      package = pkgs.pulseaudioFull;
      extraConfig = ''
        load-module module-switch-on-connect
      '';
    };
    bluetooth.enable = true;
  };

  services.blueman.enable = true;

  systemd.services = {
    btattach = {
      before = [ "bluetooth.service" ];
      after = [ "dev-ttyAMA0.device" ];
      wantedBy = [ "multi-user.target" ];
      serviceConfig = {
        ExecStart = "${pkgs.bluez}/bin/btattach -B /dev/ttyAMA0 -P bcm -S 3000000";
      };
    };
  };

  services.blueman.enable = true;
}

Has anyone found a solution to this that doesn’t involve taking the kernel and bootloader from a working raspbian image?

The firmware does some manipulation before passing the device tree to the kernel. One thing it does is configure bluetooth flow control pins. So, I have fixed the bluetooth issue in the past by creating an overlay that mimics the firmware manipulation. Something like:

// Configure uart0 pins so that bluetooth works
/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2835";

    fragment@0 {
        target = <&uart0_pins>;
        __overlay__ {
                brcm,pins = <30 31 32 33>;
                brcm,pull = <2 0 0 2>;
        };
    };
};

It is tedious and error prone to maintain these patches. So, more recently I have pursued using the device tree that the firmware provides (using u-boot’s CONFIG_OF_BOARD option) rather than trying to mimic the manipulation. This approach has worked well for me.

I packaged up this approach here and an example with working bluetooth can be found here.

1 Like