BCM43455: BLE scan responses nearly disappear on 2.4 GHz Wi-Fi with power saving off

Abierto
#7,689 1 comentario 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
35/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
c, linux

Línea de trabajo

Start with the BCM43455 coexistence report and compare the supplied captures: the issue links the brcmfmac vendor ABI and implementation in drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.h and vendor.c. The measurements show scan responses return when btc_params[51] changes from 0x190 to 0x1f0, but the cause and supported values are unresolved. A fix needs investigation into driver or firmware behavior and confirmation that active BLE scan responses work reliably with 2.4 GHz Wi-Fi power saving off.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Describe the bug

On a Raspberry Pi 4 Model B running a fresh Raspberry Pi OS Lite 64-bit image, BLE scan responses almost disappear when 2.4 GHz Wi-Fi is connected and Wi-Fi power saving is disabled. Ordinary advertisements still arrive. I reproduced this using BlueZ tools, without pairing, GATT or a sensor application.

With the installed Wi-Fi firmware 7.45.265 and btc_params[51]=0x190, I measured:

Wi-Fi power_save SCAN_RSP reports in three 10-second captures
5 GHz on (stock default) 441, 463, 482
5 GHz off 453, 524, 512
2.4 GHz on 173, 166, 254
2.4 GHz off 0, 0, 0

These are report counts, not success rates. The rows were collected in separate runs. On 2.4 GHz, an on → off → on comparison without reassociating Wi-Fi gave 65, 183, 259 → 0, 0, 0 → 243, 434, 352 SCAN_RSP reports. ADV_IND reports during the off phase were 604, 608 and 626.

Keeping 2.4 GHz and power saving off, I then changed only btc_params[51] in RAM:

btc_params[51] SCAN_RSP reports in three 10-second captures
0x190, before 0, 1, 0
0x1f0, temporary 440, 461, 500
0x190, restored 0, 0, 1

No firmware, CLM, NVRAM or kernel replacement was made during these tests. HCI scan commands returned success (0x00) in every capture.

This points to Wi-Fi/Bluetooth coexistence, but I cannot tell from host-side captures whether scan requests are not transmitted, responses are missed, or reports are lost inside the controller.

Steps to reproduce the behaviour

Use onboard Bluetooth and a nearby BLE device that returns scan responses. First confirm that SCAN_RSP reports appear on 5 GHz or with Wi-Fi power saving on.

  1. Connect to a 2.4 GHz Wi-Fi network. Note the original Wi-Fi power-saving, Bluetooth and rfkill states, then prepare a raw scan:
iw dev wlan0 link
iw dev wlan0 get power_save
systemctl is-active bluetooth.service
rfkill list bluetooth
sudo systemctl stop bluetooth.service
sudo rfkill unblock bluetooth
sudo hciconfig hci0 up
sudo iw dev wlan0 set power_save off
sleep 5
  1. In terminal A, record HCI traffic:
sudo btmon -i 0 -w scan.btsnoop

In terminal B, scan for 10 seconds:

sudo timeout --signal=INT --kill-after=3s 10s hcitool -i hci0 lescan --duplicates

Stop btmon with Ctrl+C, then count reports:

btmon -r scan.btsnoop | grep 'Event type:' | sort | uniq -c
  1. Repeat with sudo iw dev wlan0 set power_save on, then off, then on again, waiting 5 seconds after each change. Use a new filename for each capture. I took three captures per condition. Repeat on 5 GHz as a control.

  2. To reproduce the separate parameter comparison, keep 2.4 GHz and power_save off. Save the helper in Additional context as btc51.py, and capture after each command:

sudo python3 btc51.py                         # original readback: 0x190
sudo python3 btc51.py --set 0x1f0 --expect 0x190
sudo python3 btc51.py --set 0x190 --expect 0x1f0

The helper verifies each write by reading the value back. After testing, restore the original Wi-Fi, power-saving and Bluetooth/rfkill states. The parameter change above is an experiment, not a recommendation for permanent use.

Device (s)

Raspberry Pi 4 Mod. B

System

Raspberry Pi 4 Model B Rev 1.5, onboard BCM43455. Fresh Raspberry Pi OS Lite 64-bit, reference 2026-10-06; no package upgrades.

uname -a:
Linux ble-test-pi4 6.18.50+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.18.50-1+rpt1 (2026-09-11) aarch64 GNU/Linux

/etc/os-release:
Debian GNU/Linux 13 (trixie), DEBIAN_VERSION_FULL=13.7

/etc/rpi-issue:
Raspberry Pi reference 2026-10-06
Generated using pi-gen, https://github.com/RPi-Distro/pi-gen,
b2cd98a9ee08a31ef7d0110ed09f2492bbd972ec, stage2

vcgencmd version:
Sep 14 2026 14:49:30
version a86983925695a7e63166327d7c002d64040ed31d (clean) (release) (start)

firmware-brcm80211 1:20260519-1~bpo13+1+rpt1
bluez 5.82-1.1+rpt2
iw 6.9-1+b1

Wi-Fi frequencies: 2412 and 5180 MHz. btc_mode=1; initial btc_params[51]=0x190 and power_save on. Baseline vcgencmd get_throttled: throttled=0x0.

Logs
brcmfmac: brcmf_c_preinit_dcmds: Firmware: BCM4345/6 wl0: Aug 29 2023 01:47:08 version 7.45.265 (28bca26 CY) FWID 01-b677b91b
Bluetooth: hci0: BCM4345C0 (003.001.025) build 0382

The captures show active scanning, a 10 ms interval/window, public own-address type, accept-all policy and duplicate filtering disabled. Scan-parameter, scan-enable and scan-disable commands all completed with 0x00.

The zip contains two original btsnoop captures from the parameter comparison: both use 2.4 GHz Wi-Fi with power saving off. The 0x190 capture has 556 ADV_IND and 0 SCAN_RSP reports; the 0x1f0 capture has 534 ADV_IND and 440 SCAN_RSP reports.

Installed Wi-Fi firmware and CLM SHA-256 (unchanged):

d608f866582519c0a28d86db43040f4f1b98dd1d153e72e9752586546b4a36c3  cyfmac43455-sdio-standard.bin
9823842cae9fb9a5dd1e5fb31f595516ec7deee341354bef30bb3026eee29cc1  cyfmac43455-sdio.clm_blob

bcm43455-scan-response-comparison.zip

Additional context
Reading and writing btc_params[51]

I used Python 3 and the distribution's iw 6.9, not the proprietary wl utility. The helper below uses brcmfmac's vendor/DCMD interface: OUI 0x001018, subcommand 1, GET_VAR 262 and SET_VAR 263.

btc51.py — self-contained helper used for parameter access
#!/usr/bin/env python3
"""Small reproducer for the brcmfmac DCMD transport used in the original tests.

Read by default. Writes are limited to btc_params[51], require --expect,
and are followed by readback. No firmware, CLM, or NVRAM files are touched.
"""
import argparse
import struct
import subprocess


def dcmd(interface, setting=None):
    payload = b"btc_params\0" + struct.pack("<I", 51)
    writing = setting is not None
    if writing:
        payload += struct.pack("<I", setting)
    header = struct.pack("<IIIII", 263 if writing else 262,
                         len(payload) if writing else 64, 20, int(writing), 0)
    proc = subprocess.run(
        ["iw", "dev", interface, "vendor", "recvbin", "0x001018", "0x1",
         *[f"0x{byte:02x}" for byte in header + payload]],
        capture_output=True, timeout=5, check=True,
    )
    if writing:
        return
    offset = 0
    while offset + 4 <= len(proc.stdout):
        length, kind = struct.unpack_from("<HH", proc.stdout, offset)
        if length < 4 or offset + length > len(proc.stdout):
            raise RuntimeError("Malformed netlink response")
        if kind & 0x3fff == 2 and length >= 8:
            return struct.unpack_from("<I", proc.stdout, offset + 4)[0]
        offset += (length + 3) & ~3
    raise RuntimeError("No BRCMF_NLATTR_DATA in response")


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--interface", default="wlan0")
    parser.add_argument("--set", type=lambda value: int(value, 0))
    parser.add_argument("--expect", type=lambda value: int(value, 0))
    args = parser.parse_args()
    before = dcmd(args.interface)
    if args.set is None:
        print(hex(before))
        return
    if not 0 <= args.set <= 0xffffffff:
        parser.error("--set must fit in an unsigned 32-bit integer")
    if args.expect is None or before != args.expect:
        parser.error(f"Current value is {before:#x}; supply matching --expect")
    dcmd(args.interface, args.set)
    after = dcmd(args.interface)
    if after != args.set:
        raise RuntimeError(f"Readback mismatch: requested {args.set:#x}, got {after:#x}")
    print(f"{before:#x} -> {after:#x}")


if __name__ == "__main__":
    main()

I found this while testing a Raspberry Pi-based IoT gateway with BLE sensors; its existing configuration had Wi-Fi power saving disabled. This could affect other gateways using active BLE scans in that configuration.

Is there a supported firmware or driver fix for this behavior? I would also appreciate clarification on whether 0x1f0 is a supported value for btc_params[51] on BCM43455.

Related: RPi-Distro/bluez-firmware#13, agherzan/meta-raspberrypi#1637.

Thank you for looking into this.

Lenguaje dominante
C
Estrellas
13.3k
Forks
5.5k
Merge medio
1 d 4 h
PR fusionados (30 d)
21

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de raspberrypi/linux

Todos los issues de raspberrypi/linux

Issues similares

Más issues de C

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.