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

Đang mở
#7,689 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức phù hợp với người mới
35/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
c, linux
Lĩnh vực
embedded-iot, networking

Hướng nghiên cứu

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.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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.

Ngôn ngữ chính
C
Star
13.3k
Fork
5.5k
Merge trung bình
1 ngày 4 giờ
Pull request đã merge (30 ngày)
21

Chuẩn bị môi trường

Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của raspberrypi/linux

Tất cả issue của raspberrypi/linux

Issue tương tự

Thêm issue về C

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.