From c9f5490f91b27108c19ee049729b60c0572f5082 Mon Sep 17 00:00:00 2001 From: Srikanth Muppandam Date: Tue, 12 May 2026 06:23:50 +0530 Subject: [PATCH 1/3] bluetooth: harden bt_scan_devices discovery logic Update bt_scan_devices() to make Bluetooth scanning more robust on minimal and CI images. The helper now parses both live bluetoothctl scan output and cached bluetoothctl devices output across multiple scan attempts. This avoids false failures where advertisements are visible during scan but BlueZ does not immediately populate the devices cache. Also accept MAC-only discovery because name resolution can be delayed or unavailable on minimal images. This keeps the existing bt_scan_devices() API and avoids adding another parallel scan helper. Signed-off-by: Srikanth Muppandam --- Runner/utils/lib_bluetooth.sh | 330 ++++++++++++++++++++++++---------- 1 file changed, 238 insertions(+), 92 deletions(-) diff --git a/Runner/utils/lib_bluetooth.sh b/Runner/utils/lib_bluetooth.sh index 4bee53ef..76b3c267 100755 --- a/Runner/utils/lib_bluetooth.sh +++ b/Runner/utils/lib_bluetooth.sh @@ -241,31 +241,85 @@ expect { timeout {} eof {} } return 0 } -# Scan for nearby BT devices using bluetoothctl (no expect). +# Scan for nearby BT devices using bluetoothctl. +# # Env: -# BT_ADAPTER : adapter (e.g. hci0); auto-detected if unset -# SCAN_SECONDS : total scan window (default 10) -# MAC_ID : optional AA:BB:CC:DD:EE:FF; if set, succeed only if seen +# BT_ADAPTER : adapter, for example hci0; auto-detected if unset +# SCAN_SECONDS : scan window per attempt, default 10 +# SCAN_ATTEMPTS : scan attempts, default 3 +# SCAN_RETRY_DELAY : delay between attempts, default 2 +# MAC_ID : optional AA:BB:CC:DD:EE:FF; if set, succeed only if seen +# SCAN_RESULT : optional file to store parsed scan result lines +# # Usage: -# bt_scan_devices # list all devices (prints "MAC NAME" lines) -# bt_scan_devices AA:..:FF # success only if that MAC is seen +# bt_scan_devices # generic scan, succeeds if any valid MAC is seen +# bt_scan_devices AA:..:FF # target scan, succeeds only if target MAC is seen +# +# Output: +# MAC NAME +# # Return: -# 0 on success, 1 on failure (no devices / MAC not found) +# 0 on success +# 1 on failure +# +# Notes: +# - Reuses existing helper name; do not add a parallel scan helper. +# - Parses live bluetoothctl scan output and cached bluetoothctl devices output. +# - Accepts MAC-only discovery because name resolution can be delayed. +# - Keeps positional MAC support for existing callers. # shellcheck disable=SC2120 bt_scan_devices() { adapter="${BT_ADAPTER:-}" scan_window="${SCAN_SECONDS:-10}" + scan_attempts="${SCAN_ATTEMPTS:-3}" + scan_retry_delay="${SCAN_RETRY_DELAY:-2}" mac_id="${MAC_ID:-}" - # Allow positional MAC as first arg if MAC_ID not set if [ -z "$mac_id" ] && [ -n "${1:-}" ]; then mac_id="$1" fi - # Detect adapter (hci0, hci1, ...) + case "$scan_window" in + ""|*[!0-9]*) + scan_window=10 + ;; + esac + + case "$scan_attempts" in + ""|*[!0-9]*) + scan_attempts=3 + ;; + esac + + case "$scan_retry_delay" in + ""|*[!0-9]*) + scan_retry_delay=2 + ;; + esac + + if [ "$scan_window" -le 0 ] 2>/dev/null; then + scan_window=10 + fi + + if [ "$scan_attempts" -le 0 ] 2>/dev/null; then + scan_attempts=3 + fi + + if [ "$scan_retry_delay" -lt 0 ] 2>/dev/null; then + scan_retry_delay=2 + fi + + if [ -z "$adapter" ] && command -v findhcisysfs >/dev/null 2>&1; then + adapter="$(findhcisysfs 2>/dev/null || true)" + fi + if [ -z "$adapter" ] && command -v hciconfig >/dev/null 2>&1; then - adapter="$(hciconfig 2>/dev/null | awk '/^hci[0-9]+:/ {print $1}' | head -n1)" + adapter="$( + hciconfig 2>/dev/null \ + | awk '/^hci[0-9]+:/ { print $1; exit }' + )" fi + adapter="${adapter%:}" if [ -z "$adapter" ]; then @@ -273,112 +327,204 @@ bt_scan_devices() { return 1 fi - log_info "bt_scan_devices: using adapter $adapter (window=${scan_window}s)" + mac_id_up="" + if [ -n "$mac_id" ]; then + mac_id_up="$(printf '%s\n' "$mac_id" | tr '[:lower:]' '[:upper:]')" + fi + + log_info "bt_scan_devices: using adapter $adapter" + log_info "bt_scan_devices: scan_window=${scan_window}s attempts=${scan_attempts} retry_delay=${scan_retry_delay}s" - # Make sure adapter is powered on (best-effort) if command -v btpower >/dev/null 2>&1; then if ! btpower "$adapter" on; then - log_warn "bt_scan_devices: btpower($adapter on) did not report success; continuing anyway" + log_warn "bt_scan_devices: btpower($adapter on) did not report success; continuing" fi else - log_info "bt_scan_devices: btpower helper missing, assuming adapter is already powered." + bluetoothctl power on >/dev/null 2>&1 || true fi - # Start scan using CLI helper (non-expect) - if ! bt_set_scan on; then - log_warn "bt_scan_devices: bt_set_scan(on) reported failure; will still poll 'devices'." - fi - - start_ts=$(date +%s 2>/dev/null || printf '%s\n' 0) - [ "$scan_window" -le 0 ] 2>/dev/null && scan_window=10 + bluetoothctl select "$adapter" >/dev/null 2>&1 || true + attempt=1 found_lines="" - seen_target=0 - # Poll 'bluetoothctl devices' for up to scan_window seconds - while :; do - devices_out="$( - bluetoothctl devices 2>/dev/null | sanitize_bt_output || true + while [ "$attempt" -le "$scan_attempts" ]; do + log_info "bt_scan_devices: scan attempt ${attempt}/${scan_attempts}" + + live_out="$( + { + bluetoothctl select "$adapter" 2>/dev/null || true + bluetoothctl power on 2>/dev/null || true + bluetoothctl --timeout "$scan_window" scan on 2>&1 || true + } | sanitize_bt_output )" - if [ -n "$devices_out" ]; then - # Convert "Device MAC NAME..." → "MAC NAME" lines, unique - found_lines="$( - printf '%s\n' "$devices_out" | awk ' - function is_hex_pair(s, c1,c2) { - if (length(s)!=2) return 0 - c1=substr(s,1,1); c2=substr(s,2,1) - return index("0123456789ABCDEFabcdef", c1) && index("0123456789ABCDEFabcdef", c2) - } - function is_mac(m, a,n,i) { - n = split(m, a, ":"); if (n!=6) return 0 - for (i=1;i<=6;i++) if (!is_hex_pair(a[i])) return 0 - return 1 - } - /^Device[[:space:]]/ { - mac=$2 - if (!is_mac(mac)) next - name="" - for (i=3;i<=NF;i++) name = name (i==3?"":" ") $i - sub(/[[:space:]]+$/,"",name) - if (name=="") next - print mac, name - } - ' | sort -u + if command -v bt_set_scan >/dev/null 2>&1; then + if ! bt_set_scan off "$adapter"; then + log_warn "bt_scan_devices: bt_set_scan(off) reported failure after attempt $attempt" + fi + else + bluetoothctl scan off >/dev/null 2>&1 || true + fi + + if command -v bt_list_devices_raw >/dev/null 2>&1; then + cache_out="$( + bt_list_devices_raw 2>/dev/null \ + | sanitize_bt_output || true )" + else + cache_out="$( + bluetoothctl devices 2>/dev/null \ + | sanitize_bt_output || true + )" + fi + + found_lines="$( + { + printf '%s\n' "$live_out" + printf '%s\n' "$cache_out" + } | awk ' + function is_hex_pair(s) { + return s ~ /^[0-9A-Fa-f][0-9A-Fa-f]$/ + } + + function is_mac(m, a,n,i) { + n = split(m, a, ":") + if (n != 6) { + return 0 + } + + for (i = 1; i <= 6; i++) { + if (!is_hex_pair(a[i])) { + return 0 + } + } + + return 1 + } - if [ -n "$found_lines" ]; then - if [ -n "$mac_id" ]; then - if printf '%s\n' "$found_lines" \ - | awk -v t="$mac_id" 'BEGIN{IGNORECASE=1} $1==t {exit 0} END{exit 1}' - then - seen_target=1 - break - fi - else - # Any device is enough if no MAC_ID filter - seen_target=1 - break + function is_property_token(s) { + return s ~ /^(RSSI|UUIDs:|TxPower|ManufacturerData|ManufacturerData\.|Paired|Connected|Advertising|Flags:|ServiceData|Alias:|Class:|Icon:|Modalias:|Services)/ + } + + function emit_device(mac, name) { + mac = toupper(mac) + + if (name == "") { + name = "" + } + + if (!(mac in seen)) { + seen[mac] = name + order[++count] = mac + } else if (seen[mac] == "" && name != "") { + seen[mac] = name + } + } + + { + mac = "" + start = 0 + + for (i = 1; i <= NF; i++) { + if ($i == "Device" && (i + 1) <= NF && is_mac($(i + 1))) { + mac = $(i + 1) + start = i + 2 + break + } + } + + if (mac == "") { + next + } + + name = "" + for (i = start; i <= NF; i++) { + if (is_property_token($i)) { + break + } + + if ($i == "") { + continue + } + + name = name (name == "" ? "" : " ") $i + } + + sub(/[[:space:]]+$/, "", name) + + if (name ~ /^[0-9A-Fa-f][0-9A-Fa-f]-[0-9A-Fa-f][0-9A-Fa-f]-[0-9A-Fa-f][0-9A-Fa-f]-[0-9A-Fa-f][0-9A-Fa-f]-[0-9A-Fa-f][0-9A-Fa-f]-[0-9A-Fa-f][0-9A-Fa-f]$/) { + name = "" + } + + emit_device(mac, name) + } + + END { + for (i = 1; i <= count; i++) { + mac = order[i] + print mac, seen[mac] + } + } + ' + )" + + if [ -n "$found_lines" ]; then + log_info "bt_scan_devices: devices seen during attempt $attempt" + printf '%s\n' "$found_lines" | while IFS= read -r line; do + if [ -n "$line" ]; then + log_info " $line" fi + done + + if [ -n "${SCAN_RESULT:-}" ]; then + printf '%s\n' "$found_lines" > "$SCAN_RESULT" fi - fi - # Check timeout - now_ts=$(date +%s 2>/dev/null || printf '%s\n' "$scan_window") - elapsed=$((now_ts - start_ts)) - if [ "$elapsed" -ge "$scan_window" ]; then - break + if [ -n "$mac_id_up" ]; then + match_line="$( + printf '%s\n' "$found_lines" \ + | awk -v target="$mac_id_up" ' + toupper($1) == target { + print + found = 1 + exit + } + + END { + if (found != 1) { + exit 1 + } + } + ' + )" + + if [ -n "$match_line" ]; then + return 0 + fi + + log_warn "bt_scan_devices: target MAC not seen in attempt $attempt: $mac_id" + else + return 0 + fi + else + log_warn "bt_scan_devices: no devices parsed in attempt $attempt" fi - sleep 1 - done - # Stop scan (best-effort) - if ! bt_set_scan off; then - log_warn "bt_scan_devices: bt_set_scan(off) reported failure" - fi + attempt=$((attempt + 1)) - if [ -z "$found_lines" ]; then - log_warn "bt_scan_devices: no devices parsed from 'bluetoothctl devices'" - return 1 - fi + if [ "$attempt" -le "$scan_attempts" ]; then + sleep "$scan_retry_delay" + fi + done if [ -n "$mac_id" ]; then - # Print only the matching line if available - match_line="$( - printf '%s\n' "$found_lines" \ - | awk -v t="$mac_id" 'BEGIN{IGNORECASE=1} $1==t {print; exit}' - )" - if [ -n "$match_line" ]; then - printf '%s\n' "$match_line" - return 0 - fi - log_warn "bt_scan_devices: MAC_ID not found: $mac_id" - return 1 + log_warn "bt_scan_devices: MAC_ID not found after ${scan_attempts} attempts: $mac_id" + else + log_warn "bt_scan_devices: no devices found after ${scan_attempts} attempts" fi - # No filter: print all MAC/NAME pairs - printf '%s\n' "$found_lines" - return 0 + return 1 } # Pair with Bluetooth device using MAC (with retries and timestamped logs) From e77f6e1da289f6fa4dc5eec34d647656cc5caf62 Mon Sep 17 00:00:00 2001 From: Srikanth Muppandam Date: Tue, 12 May 2026 06:24:12 +0530 Subject: [PATCH 2/3] bt-scan: use common robust scan helper Update BT_SCAN/run.sh to use the common bt_scan_devices() helper instead of open-coding a single scan window followed by one bluetoothctl devices cache check. Add scan tuning knobs for CI stability: - BT_SCAN_SECONDS - BT_SCAN_RETRIES - BT_SCAN_RETRY_DELAY Also add matching CLI options: - --scan-seconds - --scan-retries - --scan-retry-delay This keeps generic scan mode unchanged while making it less flaky when BlueZ cache updates are delayed. Signed-off-by: Srikanth Muppandam --- .../Connectivity/Bluetooth/BT_SCAN/run.sh | 82 +++++++++++-------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/Runner/suites/Connectivity/Bluetooth/BT_SCAN/run.sh b/Runner/suites/Connectivity/Bluetooth/BT_SCAN/run.sh index 45aaa0de..de5cdc55 100755 --- a/Runner/suites/Connectivity/Bluetooth/BT_SCAN/run.sh +++ b/Runner/suites/Connectivity/Bluetooth/BT_SCAN/run.sh @@ -39,6 +39,9 @@ fi BT_ADAPTER="${BT_ADAPTER-}" BT_SCAN_TARGET_MAC="${BT_SCAN_TARGET_MAC-}" BT_TARGET_MAC="${BT_TARGET_MAC-}" +BT_SCAN_SECONDS="${BT_SCAN_SECONDS:-15}" +BT_SCAN_RETRIES="${BT_SCAN_RETRIES:-3}" +BT_SCAN_RETRY_DELAY="${BT_SCAN_RETRY_DELAY:-2}" while [ "$#" -gt 0 ]; do case "$1" in @@ -50,6 +53,18 @@ while [ "$#" -gt 0 ]; do BT_TARGET_MAC="$2" shift 2 ;; + --scan-seconds) + BT_SCAN_SECONDS="$2" + shift 2 + ;; + --scan-retries) + BT_SCAN_RETRIES="$2" + shift 2 + ;; + --scan-retry-delay) + BT_SCAN_RETRY_DELAY="$2" + shift 2 + ;; *) log_warn "Unknown argument ignored: $1" shift 1 @@ -158,52 +173,46 @@ else fi # ----------------------------- -# 6. Scan ON via helper +# 6. Scan using common Bluetooth helper # ----------------------------- -log_info "Testing scan ON..." -if ! bt_set_scan on "$ADAPTER"; then - log_warn "bt_set_scan(on) returned non-zero will still inspect devices list." -fi +log_info "Testing Bluetooth scan..." +log_info "Scan config: BT_SCAN_SECONDS=${BT_SCAN_SECONDS} BT_SCAN_RETRIES=${BT_SCAN_RETRIES} BT_SCAN_RETRY_DELAY=${BT_SCAN_RETRY_DELAY}" -# Optional: single Discovering snapshot after scan-on window -dstate_on="$(bt_get_discovering 2>/dev/null || true)" -[ -z "$dstate_on" ] && dstate_on="unknown" -log_info "Discovering state after scan ON window: $dstate_on" +SCAN_SECONDS="$BT_SCAN_SECONDS" +SCAN_ATTEMPTS="$BT_SCAN_RETRIES" +SCAN_RETRY_DELAY="$BT_SCAN_RETRY_DELAY" +MAC_ID="$TARGET_MAC" +BT_ADAPTER="$ADAPTER" -# ----------------------------- -# 7. Get devices list after scan ON -# - Try non-interactive bluetoothctl first -# - If empty/flaky, fallback to btctl_script "devices" "quit" -# ----------------------------- -devices_out="$( - bt_list_devices_raw 2>/dev/null \ - | grep '^Device ' || true -)" +export SCAN_SECONDS +export SCAN_ATTEMPTS +export SCAN_RETRY_DELAY +export MAC_ID +export BT_ADAPTER -if [ -n "$TARGET_MAC" ]; then - mac_up=$(printf '%s\n' "$TARGET_MAC" | tr '[:lower:]' '[:upper:]') - if printf '%s\n' "$devices_out" \ - | awk '/^Device /{print toupper($2)}' \ - | grep -q "$mac_up" - then +if bt_scan_devices "$TARGET_MAC"; then + dstate_on="$(bt_get_discovering 2>/dev/null || true)" + [ -z "$dstate_on" ] && dstate_on="unknown" + log_info "Discovering state after scan attempts: $dstate_on" + + if [ -n "$TARGET_MAC" ]; then log_pass "Target MAC $TARGET_MAC detected." else - log_fail "Target MAC $TARGET_MAC missing after scan ON window." - echo "$TESTNAME FAIL" > "$res_file" - exit 0 + log_pass "At least one Bluetooth device discovered." fi else - if [ -n "$devices_out" ]; then - log_info "Devices seen by bluetoothctl after scan ON:" - printf '%s\n' "$devices_out" | while IFS= read -r line; do - [ -n "$line" ] && log_info " $line" - done - log_pass "At least one device discovered." + dstate_on="$(bt_get_discovering 2>/dev/null || true)" + [ -z "$dstate_on" ] && dstate_on="unknown" + log_info "Discovering state after failed scan attempts: $dstate_on" + + if [ -n "$TARGET_MAC" ]; then + log_fail "Target MAC $TARGET_MAC missing after scan attempts." else - log_fail "No devices discovered in bluetoothctl devices after scan ON." - echo "$TESTNAME FAIL" > "$res_file" - exit 0 + log_fail "No Bluetooth devices discovered after scan attempts." fi + + echo "$TESTNAME FAIL" > "$res_file" + exit 0 fi # ----------------------------- @@ -226,3 +235,4 @@ fi echo "$TESTNAME PASS" > "$res_file" exit 0 + From a782fe61474029f23f3cde08a394101ec3f26ed7 Mon Sep 17 00:00:00 2001 From: Srikanth Muppandam Date: Tue, 12 May 2026 06:24:38 +0530 Subject: [PATCH 3/3] bt-scan: add README with usage and tuning details Add README.md for BT_SCAN covering generic scan mode, target MAC mode, adapter selection, scan retry tuning, result handling, LAVA usage, and debugging steps. Signed-off-by: Srikanth Muppandam --- .../Bluetooth/BT_SCAN/BT_SCAN_README.md | 388 ++++++++++++++++++ 1 file changed, 388 insertions(+) create mode 100644 Runner/suites/Connectivity/Bluetooth/BT_SCAN/BT_SCAN_README.md diff --git a/Runner/suites/Connectivity/Bluetooth/BT_SCAN/BT_SCAN_README.md b/Runner/suites/Connectivity/Bluetooth/BT_SCAN/BT_SCAN_README.md new file mode 100644 index 00000000..6c2e0039 --- /dev/null +++ b/Runner/suites/Connectivity/Bluetooth/BT_SCAN/BT_SCAN_README.md @@ -0,0 +1,388 @@ +# BT_SCAN + +## Overview + +`BT_SCAN` validates Bluetooth scan functionality on a Linux target. + +The test verifies that: + +1. `bluetoothd` is running. +2. A Bluetooth HCI adapter is available. +3. The adapter is visible to `bluetoothctl`. +4. The adapter can be powered on. +5. Bluetooth scan can discover nearby devices. + +The test supports two modes: + +- Generic scan mode: pass if any valid Bluetooth device is discovered. +- Target MAC mode: pass only if the requested target MAC address is discovered. + +This test uses common Bluetooth helpers from: + +```text +Runner/utils/lib_bluetooth.sh +``` + +## Test location + +```text +Runner/suites/Connectivity/Bluetooth/BT_SCAN/ +``` + +## Files + +```text +BT_SCAN/ +├── BT_SCAN.yaml +├── README.md +└── run.sh +``` + +## Dependencies + +Required tools: + +```text +bluetoothctl +pgrep +``` + +Required service: + +```text +bluetoothd +``` + +Required runtime support: + +```text +/sys/class/bluetooth/hci* +``` + +The test automatically skips if no HCI adapter is found. + +## Basic usage + +Run from the test directory: + +```sh +./run.sh +``` + +Run from anywhere inside the testkit repository: + +```sh +Runner/suites/Connectivity/Bluetooth/BT_SCAN/run.sh +``` + +## Generic scan mode + +When no target MAC is provided, the test checks generic device visibility. + +```sh +./run.sh +``` + +Expected behavior: + +```text +PASS: at least one valid Bluetooth device MAC is discovered. +FAIL: no valid Bluetooth device is discovered after scan attempts. +SKIP: no adapter/controller is available. +``` + +This mode is useful for basic scan sanity validation, but it depends on at least one discoverable or advertising Bluetooth device being nearby. + +## Target MAC mode + +To validate discovery of a specific Bluetooth device: + +```sh +./run.sh --target-mac AA:BB:CC:DD:EE:FF +``` + +Or using environment variables: + +```sh +BT_SCAN_TARGET_MAC=AA:BB:CC:DD:EE:FF ./run.sh +``` + +Alternative supported variable: + +```sh +BT_TARGET_MAC=AA:BB:CC:DD:EE:FF ./run.sh +``` + +Priority: + +```text +BT_SCAN_TARGET_MAC > BT_TARGET_MAC +``` + +Expected behavior: + +```text +PASS: requested MAC is discovered. +FAIL: requested MAC is not discovered after scan attempts. +``` + +## Adapter selection + +By default, the test auto-detects the adapter using Bluetooth helper logic. + +To force a specific adapter: + +```sh +./run.sh --adapter hci0 +``` + +Or: + +```sh +BT_ADAPTER=hci0 ./run.sh +``` + +## Scan tuning + +The updated scan flow supports retries to reduce CI flakiness. + +Default values: + +```text +BT_SCAN_SECONDS=15 +BT_SCAN_RETRIES=3 +BT_SCAN_RETRY_DELAY=2 +``` + +These values mean: + +```text +Run up to 3 scan attempts. +Each scan attempt lasts 15 seconds. +Wait 2 seconds between attempts. +``` + +### Environment tuning + +```sh +BT_SCAN_SECONDS=20 BT_SCAN_RETRIES=5 BT_SCAN_RETRY_DELAY=3 ./run.sh +``` + +### CLI tuning + +```sh +./run.sh --scan-seconds 20 --scan-retries 5 --scan-retry-delay 3 +``` + +## Supported options + +```text +--adapter + Select Bluetooth adapter manually. + Example: --adapter hci0 + +--target-mac + Validate that a specific target MAC is discovered. + Example: --target-mac AA:BB:CC:DD:EE:FF + +--scan-seconds + Scan duration per attempt in seconds. + Default: 15 + +--scan-retries + Number of scan attempts before failing. + Default: 3 + +--scan-retry-delay + Delay between scan attempts in seconds. + Default: 2 +``` + +## Supported environment variables + +```text +BT_ADAPTER + Bluetooth adapter to use. + Example: hci0 + +BT_SCAN_TARGET_MAC + Target MAC for scan validation. + Highest priority target MAC variable. + +BT_TARGET_MAC + Alternative target MAC variable. + +BT_SCAN_SECONDS + Scan window per attempt. + Default: 15 + +BT_SCAN_RETRIES + Number of scan attempts. + Default: 3 + +BT_SCAN_RETRY_DELAY + Delay between scan attempts. + Default: 2 +``` + +## Result file + +The test writes: + +```text +BT_SCAN.res +``` + +Possible contents: + +```text +BT_SCAN PASS +BT_SCAN FAIL +BT_SCAN SKIP +``` + +LAVA consumes this result file through: + +```sh +$REPO_PATH/Runner/utils/send-to-lava.sh BT_SCAN.res +``` + +## PASS criteria + +### Generic scan mode + +The test passes if any valid Bluetooth MAC address is discovered during scan attempts. + +Examples of acceptable discovery: + +```text +AA:BB:CC:DD:EE:FF DeviceName +AA:BB:CC:DD:EE:FF +``` + +A MAC-only discovery is accepted because name resolution can be delayed or unavailable on minimal images. + +### Target MAC mode + +The test passes only if the requested target MAC is discovered. + +Matching is case-insensitive: + +```text +aa:bb:cc:dd:ee:ff +AA:BB:CC:DD:EE:FF +``` + +Both are treated as the same MAC. + +## FAIL criteria + +The test fails if: + +- `bluetoothd` is not running after retries. +- Adapter power-on fails. +- Target MAC is provided but not discovered. +- No Bluetooth device is discovered in generic mode after all scan attempts. + +## SKIP criteria + +The test skips if: + +- Required dependencies are missing. +- No HCI adapter is found. +- Adapter is not visible to `bluetoothctl`. + +## LAVA usage + +Current YAML runs the test with defaults: + +```yaml +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Connectivity/Bluetooth/BT_SCAN/ + - ./run.sh || true + - $REPO_PATH/Runner/utils/send-to-lava.sh BT_SCAN.res +``` + +No YAML change is required for the default retry behavior. + +## LAVA usage with target MAC + +If a board has a known nearby Bluetooth peer, YAML can optionally export a target MAC: + +```yaml +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Connectivity/Bluetooth/BT_SCAN/ + - BT_SCAN_TARGET_MAC=AA:BB:CC:DD:EE:FF ./run.sh || true + - $REPO_PATH/Runner/utils/send-to-lava.sh BT_SCAN.res +``` + +## LAVA usage with scan tuning + +Optional tuning example: + +```yaml +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Connectivity/Bluetooth/BT_SCAN/ + - BT_SCAN_SECONDS=20 BT_SCAN_RETRIES=5 BT_SCAN_RETRY_DELAY=3 ./run.sh || true + - $REPO_PATH/Runner/utils/send-to-lava.sh BT_SCAN.res +``` + +## Debugging + +### Check adapter + +```sh +ls /sys/class/bluetooth +``` + +Expected: + +```text +hci0 +``` + +### Check bluetoothd + +```sh +pgrep bluetoothd +``` + +### Check controller visibility + +```sh +bluetoothctl list +``` + +On some minimal images, non-interactive `bluetoothctl list` may return no controllers even when interactive `bluetoothctl` works. The test handles this using helper logic. + +### Manual scan + +```sh +bluetoothctl +power on +scan on +devices +scan off +quit +``` + +### Non-interactive scan + +```sh +bluetoothctl --timeout 15 scan on +bluetoothctl devices +bluetoothctl scan off +``` + +## Notes + +- Generic scan mode is useful for sanity testing, but it depends on nearby Bluetooth advertisements. +- Target MAC mode is more deterministic for CI. +- Some devices advertise without a resolved name. The test accepts MAC-only discovery. +- BlueZ device cache can be delayed. The updated scan helper checks both live scan output and cached device output across retries.