From 41ff30e999a6f940483218f62b5cd5234e9af7b1 Mon Sep 17 00:00:00 2001 From: Azhar Shaikh Date: Mon, 8 Jun 2026 18:07:26 +0530 Subject: [PATCH 1/2] cleanup: Remove all trailing whitespaces No functional code change in this commit. This one only removes all trailing white spaces. Signed-off-by: Azhar Shaikh --- .../Bluetooth/BT_FW_KMD_Service/run.sh | 2 +- Runner/suites/Kernel/Baseport/BWMON/run.sh | 6 +- Runner/suites/Kernel/Baseport/Buses/run.sh | 2 +- .../Baseport/Module_Reload_Validation/run.sh | 2 +- .../Baseport/Reboot_health_check/run.sh | 10 +- Runner/suites/Kernel/Baseport/Timer/run.sh | 2 +- .../Kernel/Baseport/UserDataEncryption/run.sh | 10 +- .../suites/Kernel/Baseport/etm_trace/run.sh | 16 +- Runner/suites/Kernel/Baseport/irq/run.sh | 2 +- Runner/suites/Kernel/Baseport/smmu/run.sh | 8 +- Runner/suites/Kernel/Baseport/stm_cpu/run.sh | 39 +- Runner/suites/Kernel/DCVS/Freq_Scaling/run.sh | 4 +- .../Kernel/DEBUG/CTI-Enable-Disable/run.sh | 2 +- Runner/suites/Kernel/DEBUG/CTI-Test/run.sh | 30 +- .../Kernel/DEBUG/MultiSource-STM-ETM/run.sh | 10 +- Runner/suites/Kernel/DEBUG/Node-Access/run.sh | 4 +- .../Kernel/DEBUG/STM-HWE-PORT-SWITCH/run.sh | 14 +- .../DEBUG/STM-Source-Enable-Disable/run.sh | 8 +- .../Kernel/DEBUG/STM-Trace-Marker/run.sh | 12 +- .../DEBUG/Sink-Status-STM-Toggle/run.sh | 22 +- .../Kernel/DEBUG/TPDM-Enable-Disable/run.sh | 20 +- .../Kernel/DEBUG/TPDM-Interface-Access/run.sh | 30 +- .../Kernel/Scheduler/CPU_affinity/run.sh | 4 +- .../Multimedia/Audio/AudioPlayback/run.sh | 2 +- .../Multimedia/Audio/AudioRecord/run.sh | 16 +- .../Multimedia/Camera/Libcamera_cam/run.sh | 10 +- .../suites/Multimedia/GSTreamer/AI_ML/run.sh | 2 +- .../Audio/Audio_Record_Playback/run.sh | 74 +-- .../GSTreamer/Camera/Camera_Tests/run.sh | 272 +++++----- .../Display/Waylandsink_Playback/run.sh | 10 +- .../Video/Video_Encode_Decode/run.sh | 76 +-- Runner/suites/Performance/Geekbench/run.sh | 10 +- .../userspace-resource-manager/run.sh | 2 +- .../Virtualization/KVM/KVM_Driver/run.sh | 2 +- .../Virtualization/KVM/KVM_EL2_DTB/run.sh | 2 +- .../Virtualization/KVM/KVM_Infra/run.sh | 2 +- Runner/utils/audio_common.sh | 252 ++++----- Runner/utils/camera/lib_camera.sh | 74 +-- Runner/utils/functestlib.sh | 496 +++++++++--------- Runner/utils/lib_bluetooth.sh | 198 +++---- Runner/utils/lib_connectivity.sh | 34 +- Runner/utils/lib_display.sh | 110 ++-- Runner/utils/lib_gstreamer.sh | 76 +-- Runner/utils/lib_performance.sh | 274 +++++----- Runner/utils/lib_rt.sh | 4 +- Runner/utils/lib_sensors.sh | 6 +- Runner/utils/lib_video.sh | 110 ++-- Runner/utils/send-to-lava.sh | 3 +- 48 files changed, 1195 insertions(+), 1181 deletions(-) diff --git a/Runner/suites/Connectivity/Bluetooth/BT_FW_KMD_Service/run.sh b/Runner/suites/Connectivity/Bluetooth/BT_FW_KMD_Service/run.sh index f371d5b4..5f703a04 100755 --- a/Runner/suites/Connectivity/Bluetooth/BT_FW_KMD_Service/run.sh +++ b/Runner/suites/Connectivity/Bluetooth/BT_FW_KMD_Service/run.sh @@ -202,7 +202,7 @@ fi if [ -z "$ADAPTER" ]; then log_warn "No HCI adapter found." - + if [ "$FAIL_COUNT" -gt 0 ]; then echo "$TESTNAME FAIL" > "$RES_FILE" else diff --git a/Runner/suites/Kernel/Baseport/BWMON/run.sh b/Runner/suites/Kernel/Baseport/BWMON/run.sh index 59a3f1a4..1fbccb35 100755 --- a/Runner/suites/Kernel/Baseport/BWMON/run.sh +++ b/Runner/suites/Kernel/Baseport/BWMON/run.sh @@ -52,12 +52,12 @@ initial_votes=$(extract_votes) log_info "$initial_votes" log_info "$initial_votes" -log_info "Running bw_mem tool..." +log_info "Running bw_mem tool..." bw_mem 4000000000 frd & sleep 2 -log_info "Vote check while bw_mem tool is running:" +log_info "Vote check while bw_mem tool is running:" final_votes=$(extract_votes) log_info "$final_votes" @@ -81,7 +81,7 @@ done if $incremented; then log_pass "$TESTNAME : Test Passed" - echo "$TESTNAME PASS" > "$res_file" + echo "$TESTNAME PASS" > "$res_file" exit 0 else log_fail "$TESTNAME : Test Failed" diff --git a/Runner/suites/Kernel/Baseport/Buses/run.sh b/Runner/suites/Kernel/Baseport/Buses/run.sh index d6bc13e9..7f9f3085 100755 --- a/Runner/suites/Kernel/Baseport/Buses/run.sh +++ b/Runner/suites/Kernel/Baseport/Buses/run.sh @@ -50,5 +50,5 @@ if echo "$output" | grep -q "Reading"; then else log_fail "$TESTNAME : Test Failed" echo "$TESTNAME FAIL" > "$res_file" - exit 1 + exit 1 fi diff --git a/Runner/suites/Kernel/Baseport/Module_Reload_Validation/run.sh b/Runner/suites/Kernel/Baseport/Module_Reload_Validation/run.sh index efba6b83..cf1bceb9 100755 --- a/Runner/suites/Kernel/Baseport/Module_Reload_Validation/run.sh +++ b/Runner/suites/Kernel/Baseport/Module_Reload_Validation/run.sh @@ -73,7 +73,7 @@ cleanup() { rm -f "$PROFILE_TMP_LIST" 2>/dev/null fi } - + trap 'cleanup' EXIT INT TERM while [ $# -gt 0 ]; do diff --git a/Runner/suites/Kernel/Baseport/Reboot_health_check/run.sh b/Runner/suites/Kernel/Baseport/Reboot_health_check/run.sh index 031908e6..3c79c3b2 100755 --- a/Runner/suites/Kernel/Baseport/Reboot_health_check/run.sh +++ b/Runner/suites/Kernel/Baseport/Reboot_health_check/run.sh @@ -55,24 +55,24 @@ fi RETRY_COUNT=$(cat "$RETRY_FILE") log_info "--------------------------------------------" -log_info "Boot Health Check Started - $(date)" +log_info "Boot Health Check Started - $(date)" log_info "Current Retry Count: $RETRY_COUNT" # Health Check: You can expand this check if [ "$(whoami)" = "root" ]; then log_pass "System booted successfully and root shell obtained." log_info "Test Completed Successfully after $RETRY_COUNT retries." - + # Optional: clean retry counter after success echo "0" > "$RETRY_FILE" - + exit 0 else log_fail "Root shell not available!" - + RETRY_COUNT=$((RETRY_COUNT + 1)) echo "$RETRY_COUNT" > "$RETRY_FILE" - + if [ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]; then log_error "[ERROR] Maximum retries ($MAX_RETRIES) reached. Stopping test." exit 1 diff --git a/Runner/suites/Kernel/Baseport/Timer/run.sh b/Runner/suites/Kernel/Baseport/Timer/run.sh index 51b4ba84..41ba95dd 100755 --- a/Runner/suites/Kernel/Baseport/Timer/run.sh +++ b/Runner/suites/Kernel/Baseport/Timer/run.sh @@ -39,7 +39,7 @@ Options: Example: $0 --binary-path=/custom/path/posix_timers - $0 + $0 EOF } diff --git a/Runner/suites/Kernel/Baseport/UserDataEncryption/run.sh b/Runner/suites/Kernel/Baseport/UserDataEncryption/run.sh index 8c79fc58..d668bf3b 100755 --- a/Runner/suites/Kernel/Baseport/UserDataEncryption/run.sh +++ b/Runner/suites/Kernel/Baseport/UserDataEncryption/run.sh @@ -79,14 +79,14 @@ cleanup() { else log_info "removed key $key_id from $FS_PATH" fi - fi + fi + - if [ -n "${KEY_FILE:-}" ]; then if ! rm -f "$KEY_FILE" 2>/dev/null; then log_warn "Failed to remove key file: $KEY_FILE" fi - fi + fi scan_dmesg_errors "$test_path" "fscrypt" "" } @@ -218,7 +218,7 @@ fi log_info "Key ID: $key_id" # Step 4: Check key status -log_info "Checking key status" +log_info "Checking key status" status=$("$FSCRYPTCTL" key_status "$key_id" "$FS_PATH" 2>&1) rc=$? @@ -256,7 +256,7 @@ rc=$? if [ "$rc" -ne 0 ] || [ -z "${policy_output:-}" ]; then log_fail "fscryptctl get_policy failed for $MOUNT_DIR: $policy_output" echo "$TESTNAME FAIL" > "$res_file" - exit 0 + exit 0 fi not_encrypted=$(echo "$policy_output" | awk '/file or directory not encrypted/ {print 1}') diff --git a/Runner/suites/Kernel/Baseport/etm_trace/run.sh b/Runner/suites/Kernel/Baseport/etm_trace/run.sh index c88a12f4..c5d16f31 100755 --- a/Runner/suites/Kernel/Baseport/etm_trace/run.sh +++ b/Runner/suites/Kernel/Baseport/etm_trace/run.sh @@ -37,9 +37,9 @@ res_file="./$TESTNAME.res" log_info "-----------------------------------------------------------------------------------------" log_info "-------------------Starting $TESTNAME Testcase----------------------------" log_info "=== Test Initialization ===" - + pass=true - + # Step 1: Check required kernel config required_configs="CONFIG_CORESIGHT_SOURCE_ETM4X" check_kernel_config "$required_configs" || { @@ -47,7 +47,7 @@ check_kernel_config "$required_configs" || { echo "$TESTNAME SKIP" > "$res_file" exit 0 } - + # Step 2: Enable CoreSight sink log_info "Enabling CoreSight sink (tmc_etr0)..." echo 1 > /sys/bus/coresight/devices/tmc_etr0/enable_sink @@ -57,7 +57,7 @@ else log_fail "Failed to enable sink." pass=false fi - + # Step 3: Enable CoreSight source log_info "Enabling CoreSight source (etm0)..." echo 1 > /sys/bus/coresight/devices/etm0/enable_source @@ -67,7 +67,7 @@ else log_fail "Failed to enable source." pass=false fi - + # Step 4: Capture trace data TRACE_FILE="/tmp/qdss.bin" log_info "Capturing trace data to $TRACE_FILE..." @@ -77,7 +77,7 @@ else log_fail "Failed to capture trace data." pass=false fi - + # Step 5: Validate trace output if [ -s "$TRACE_FILE" ]; then log_info "Trace file is not empty." @@ -85,7 +85,7 @@ else log_fail "Trace file is empty." pass=false fi - + # Final result and cleanup if $pass; then log_pass "$TESTNAME : Test Passed" @@ -100,5 +100,5 @@ else log_info "-------------------Completed $TESTNAME Testcase----------------------------" exit 1 fi - + diff --git a/Runner/suites/Kernel/Baseport/irq/run.sh b/Runner/suites/Kernel/Baseport/irq/run.sh index dac022c1..5cf487b5 100755 --- a/Runner/suites/Kernel/Baseport/irq/run.sh +++ b/Runner/suites/Kernel/Baseport/irq/run.sh @@ -81,7 +81,7 @@ case "$IRQ_SKIP_ISOLATED" in esac deps_list="awk sed grep tr sleep taskset" - + log_info "Checking dependencies: $deps_list" if ! check_dependencies "$deps_list"; then log_skip "$TESTNAME SKIP - missing one or more dependencies: $deps_list" diff --git a/Runner/suites/Kernel/Baseport/smmu/run.sh b/Runner/suites/Kernel/Baseport/smmu/run.sh index e74f4022..e50d96ee 100755 --- a/Runner/suites/Kernel/Baseport/smmu/run.sh +++ b/Runner/suites/Kernel/Baseport/smmu/run.sh @@ -34,12 +34,12 @@ fi TESTNAME="smmu" test_path="$(find_test_case_by_name "$TESTNAME")" - + if [ -z "$test_path" ] || [ ! -d "$test_path" ]; then log_fail "$TESTNAME, test directory not found" exit 1 fi - + cd "$test_path" || exit 1 res_file="./$TESTNAME.res" rm -f "$res_file" @@ -80,13 +80,13 @@ else fi log_info "Checking IOMMU groups path" - + if ! wait_for_path "/sys/kernel/iommu_groups" 3; then log_fail "/sys/kernel/iommu_groups is not present" echo "$TESTNAME FAIL" > "$res_file" exit 0 fi - + log_pass "/sys/kernel/iommu_groups is present" group_count="$(find /sys/kernel/iommu_groups -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l | awk '{print $1}')" diff --git a/Runner/suites/Kernel/Baseport/stm_cpu/run.sh b/Runner/suites/Kernel/Baseport/stm_cpu/run.sh index 75f9103e..4ca18325 100755 --- a/Runner/suites/Kernel/Baseport/stm_cpu/run.sh +++ b/Runner/suites/Kernel/Baseport/stm_cpu/run.sh @@ -1,7 +1,7 @@ #!/bin/sh - + # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. -# SPDX-License-Identifier: BSD-3-Clause +# SPDX-License-Identifier: BSD-3-Clause # Robustly find and source init_env SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" INIT_ENV="" @@ -13,30 +13,30 @@ while [ "$SEARCH" != "/" ]; do fi SEARCH=$(dirname "$SEARCH") done - + if [ -z "$INIT_ENV" ]; then echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 exit 1 fi - + # Only source if not already loaded (idempotent) if [ -z "$__INIT_ENV_LOADED" ]; then # shellcheck disable=SC1090 . "$INIT_ENV" fi - + # shellcheck disable=SC1090,SC1091 . "$TOOLS/functestlib.sh" - + TESTNAME="stm_cpu" test_path=$(find_test_case_by_name "$TESTNAME") cd "$test_path" || exit 1 res_file="./$TESTNAME.res" - + log_info "-----------------------------------------------------------------------------------------" log_info "-------------------Starting $TESTNAME Testcase----------------------------" log_info "=== Test Initialization ===" - + # Step 1: Check required kernel configs individually CONFIGS="CONFIG_STM_PROTO_BASIC CONFIG_STM_PROTO_SYS_T CONFIG_STM_DUMMY CONFIG_STM_SOURCE_CONSOLE CONFIG_STM_SOURCE_HEARTBEAT" for cfg in $CONFIGS; do @@ -47,7 +47,7 @@ for cfg in $CONFIGS; do exit 1 fi done - + # Step 2: Mount configfs if not mounted if ! mountpoint -q /sys/kernel/config 2>/dev/null && [ -z "$(ls /sys/kernel/config 2>/dev/null)" ]; then mount -t configfs configfs /sys/kernel/config || { @@ -56,14 +56,14 @@ if ! mountpoint -q /sys/kernel/config 2>/dev/null && [ -z "$(ls /sys/kernel/conf exit 0 } fi - + # Step 3: Create STM policy directories mkdir -p /sys/kernel/config/stp-policy/stm0_basic.policy/default || { log_skip "$TESTNAME : Failed to create STM policy directories" echo "$TESTNAME SKIP" > "$res_file" exit 0 } - + # Step 4: Enable ETF sink only if not already enabled if [ "$(cat /sys/bus/coresight/devices/tmc_etf0/enable_sink)" != "1" ]; then echo 1 > /sys/bus/coresight/devices/tmc_etf0/enable_sink || { @@ -72,7 +72,7 @@ if [ "$(cat /sys/bus/coresight/devices/tmc_etf0/enable_sink)" != "1" ]; then exit 0 } fi - + # Step 5: Load STM modules for mod in stm_heartbeat stm_console stm_ftrace; do mod_path=$(find_kernel_module "$mod") @@ -82,10 +82,10 @@ for mod in stm_heartbeat stm_console stm_ftrace; do exit 0 } done - + # Step 6: Link STM source to ftrace echo stm0 > /sys/class/stm_source/ftrace/stm_source_link - + # Step 7: Mount debugfs if not mounted if ! mountpoint -q /sys/kernel/debug 2>/dev/null && [ -z "$(ls /sys/kernel/debug 2>/dev/null)" ]; then mount -t debugfs nodev /sys/kernel/debug || { @@ -94,24 +94,24 @@ if ! mountpoint -q /sys/kernel/debug 2>/dev/null && [ -z "$(ls /sys/kernel/debug exit 0 } fi - + # Step 8: Enable tracing echo 1 > /sys/kernel/debug/tracing/tracing_on echo 1 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable echo 1 > /sys/bus/coresight/devices/stm0/enable_source - + # Step 9: Capture trace output trace_output="/tmp/qdss_etf_stm.bin" rm -f "$trace_output" - + if [ ! -e /dev/tmc_etf0 ]; then log_skip "$TESTNAME : Trace device /dev/tmc_etf0 not found" echo "$TESTNAME SKIP" > "$res_file" exit 0 fi - + cat /dev/tmc_etf0 > "$trace_output" - + # Step 10: Validate trace output is not empty if [ -s "$trace_output" ]; then log_pass "$TESTNAME : Trace captured successfully" @@ -126,4 +126,3 @@ else log_info "------------------- Completed $TESTNAME Testcase ----------------------------" exit 1 fi - \ No newline at end of file diff --git a/Runner/suites/Kernel/DCVS/Freq_Scaling/run.sh b/Runner/suites/Kernel/DCVS/Freq_Scaling/run.sh index 4ec5b696..e408e7ac 100755 --- a/Runner/suites/Kernel/DCVS/Freq_Scaling/run.sh +++ b/Runner/suites/Kernel/DCVS/Freq_Scaling/run.sh @@ -12,12 +12,12 @@ while [ "$SEARCH" != "/" ]; do fi SEARCH=$(dirname "$SEARCH") done - + if [ -z "$INIT_ENV" ]; then echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 exit 1 fi - + # Only source if not already loaded (idempotent) if [ -z "$__INIT_ENV_LOADED" ]; then # shellcheck disable=SC1090 diff --git a/Runner/suites/Kernel/DEBUG/CTI-Enable-Disable/run.sh b/Runner/suites/Kernel/DEBUG/CTI-Enable-Disable/run.sh index 0d241c1f..48aa02d4 100755 --- a/Runner/suites/Kernel/DEBUG/CTI-Enable-Disable/run.sh +++ b/Runner/suites/Kernel/DEBUG/CTI-Enable-Disable/run.sh @@ -103,7 +103,7 @@ if [ -z "$CTI_LIST" ]; then else for cti in $CTI_LIST; do dev_path="$CS_BASE/$cti" - + if [ ! -f "$dev_path/enable" ]; then log_warn "Skipping $cti: 'enable' node not found" continue diff --git a/Runner/suites/Kernel/DEBUG/CTI-Test/run.sh b/Runner/suites/Kernel/DEBUG/CTI-Test/run.sh index 71a28bf1..404c4906 100755 --- a/Runner/suites/Kernel/DEBUG/CTI-Test/run.sh +++ b/Runner/suites/Kernel/DEBUG/CTI-Test/run.sh @@ -72,7 +72,7 @@ map_cti_trigin() { log_info "Legacy: mapping trig $trig ch $channel to $ctiname" [ -f "$cti_dev/map_trigin" ] && echo "$trig" "$channel" > "$cti_dev/map_trigin" 2>/dev/null - + trigin="" channelin="" [ -f "$cti_dev/show_trigin" ] && trigin=$(cut -b 4 "$cti_dev/show_trigin" 2>/dev/null) @@ -80,7 +80,7 @@ map_cti_trigin() { if [ -n "$trigin" ] && [ -n "$channelin" ] && [ "$trig" -eq "$trigin" ] && [ "$channel" -eq "$channelin" ] 2>/dev/null; then [ -f "$cti_dev/unmap_trigin" ] && echo "$trig" "$channel" > "$cti_dev/unmap_trigin" 2>/dev/null - + trigin="" [ -f "$cti_dev/show_trigin" ] && trigin=$(cut -b 4 "$cti_dev/show_trigin" 2>/dev/null) if [ -n "$trigin" ]; then @@ -102,21 +102,21 @@ set_trigin_attach() { [ ! -d "$cti_dev/channels" ] && return log_info "Attach trigin: trig $trig -> ch $channel on $ctiname" - + [ -f "$cti_dev/enable" ] && echo 1 > "$cti_dev/enable" 2>/dev/null [ -f "$cti_dev/channels/trigin_attach" ] && echo "$channel" "$trig" > "$cti_dev/channels/trigin_attach" 2>/dev/null [ -f "$cti_dev/channels/chan_xtrigs_sel" ] && echo "$channel" > "$cti_dev/channels/chan_xtrigs_sel" 2>/dev/null - + read_trig="" [ -f "$cti_dev/channels/chan_xtrigs_in" ] && read_trig=$(cat "$cti_dev/channels/chan_xtrigs_in" 2>/dev/null) - + if [ -n "$read_trig" ] && [ "$trig" -eq "$read_trig" ] 2>/dev/null; then [ -f "$cti_dev/channels/trigin_detach" ] && echo "$channel" "$trig" > "$cti_dev/channels/trigin_detach" 2>/dev/null [ -f "$cti_dev/channels/chan_xtrigs_sel" ] && echo "$channel" > "$cti_dev/channels/chan_xtrigs_sel" 2>/dev/null - + read_trig="" [ -f "$cti_dev/channels/chan_xtrigs_in" ] && read_trig=$(cat "$cti_dev/channels/chan_xtrigs_in" 2>/dev/null) - + if [ -n "$read_trig" ]; then log_warn "Failed to detach trigin on $ctiname" FAIL_COUNT=$((FAIL_COUNT + 1)) @@ -127,7 +127,7 @@ set_trigin_attach() { FAIL_COUNT=$((FAIL_COUNT + 1)) [ -f "$cti_dev/channels/chan_xtrigs_reset" ] && echo 1 > "$cti_dev/channels/chan_xtrigs_reset" 2>/dev/null fi - + [ -f "$cti_dev/enable" ] && echo 0 > "$cti_dev/enable" 2>/dev/null } @@ -138,21 +138,21 @@ set_trigout_attach() { [ ! -d "$cti_dev/channels" ] && return log_info "Attach trigout: trig $trig -> ch $channel on $ctiname" - + [ -f "$cti_dev/enable" ] && echo 1 > "$cti_dev/enable" 2>/dev/null [ -f "$cti_dev/channels/trigout_attach" ] && echo "$channel" "$trig" > "$cti_dev/channels/trigout_attach" 2>/dev/null [ -f "$cti_dev/channels/chan_xtrigs_sel" ] && echo "$channel" > "$cti_dev/channels/chan_xtrigs_sel" 2>/dev/null - + read_trig="" [ -f "$cti_dev/channels/chan_xtrigs_out" ] && read_trig=$(cat "$cti_dev/channels/chan_xtrigs_out" 2>/dev/null) - + if [ -n "$read_trig" ] && [ "$trig" -eq "$read_trig" ] 2>/dev/null; then [ -f "$cti_dev/channels/trigout_detach" ] && echo "$channel" "$trig" > "$cti_dev/channels/trigout_detach" 2>/dev/null [ -f "$cti_dev/channels/chan_xtrigs_sel" ] && echo "$channel" > "$cti_dev/channels/chan_xtrigs_sel" 2>/dev/null - + read_trig="" [ -f "$cti_dev/channels/chan_xtrigs_out" ] && read_trig=$(cat "$cti_dev/channels/chan_xtrigs_out" 2>/dev/null) - + if [ -n "$read_trig" ]; then log_warn "Failed to detach trigout on $ctiname" FAIL_COUNT=$((FAIL_COUNT + 1)) @@ -163,7 +163,7 @@ set_trigout_attach() { FAIL_COUNT=$((FAIL_COUNT + 1)) [ -f "$cti_dev/channels/chan_xtrigs_reset" ] && echo 1 > "$cti_dev/channels/chan_xtrigs_reset" 2>/dev/null fi - + [ -f "$cti_dev/enable" ] && echo 0 > "$cti_dev/enable" 2>/dev/null } @@ -208,7 +208,7 @@ done for cti in $CTI_DEVICES; do cti_path="$CS_BASE/$cti" - + if [ $NEW_VER -eq 1 ]; then if [ -f "$cti_path/mgmt/devid" ]; then devid=$(cat "$cti_path/mgmt/devid" 2>/dev/null) diff --git a/Runner/suites/Kernel/DEBUG/MultiSource-STM-ETM/run.sh b/Runner/suites/Kernel/DEBUG/MultiSource-STM-ETM/run.sh index 6a90a672..604f8306 100755 --- a/Runner/suites/Kernel/DEBUG/MultiSource-STM-ETM/run.sh +++ b/Runner/suites/Kernel/DEBUG/MultiSource-STM-ETM/run.sh @@ -60,10 +60,10 @@ toggle_etm_all() { state=$1 count=0 toggledcount=0 - + while [ "$count" -lt "$CORES" ]; do skip=0 - + if [ -f "${CPU_PATH}${count}/online" ]; then read -r is_online < "${CPU_PATH}${count}/online" if [ "$is_online" = "0" ]; then @@ -74,7 +74,7 @@ toggle_etm_all() { if [ "$skip" -eq 0 ]; then etm="" - + if [ -f "$cs_base/ete$count/enable_source" ]; then etm="$cs_base/ete$count/enable_source" elif [ -f "$cs_base/coresight-ete$count/enable_source" ]; then @@ -128,7 +128,7 @@ fi for sinkname in $SINKS; do log_info "Testing Sink: $sinkname" - + cs_global_reset OUTPUT_BIN="/tmp/$sinkname.bin" rm -f "$OUTPUT_BIN" @@ -166,4 +166,4 @@ for sinkname in $SINKS; do toggle_etm_all 0 done -cs_global_reset \ No newline at end of file +cs_global_reset \ No newline at end of file diff --git a/Runner/suites/Kernel/DEBUG/Node-Access/run.sh b/Runner/suites/Kernel/DEBUG/Node-Access/run.sh index 0c0adc5c..c80926db 100755 --- a/Runner/suites/Kernel/DEBUG/Node-Access/run.sh +++ b/Runner/suites/Kernel/DEBUG/Node-Access/run.sh @@ -46,12 +46,12 @@ reset_source_sink() { log_info "Dynamically finding and resetting all Coresight sources and sinks..." for _dev in "$CS_BASE"/*; do [ -e "$_dev" ] || continue - + # Disable if it's a source if [ -f "$_dev/enable_source" ]; then echo 0 > "$_dev/enable_source" 2>/dev/null || true fi - + # Disable if it's a sink if [ -f "$_dev/enable_sink" ]; then echo 0 > "$_dev/enable_sink" 2>/dev/null || true diff --git a/Runner/suites/Kernel/DEBUG/STM-HWE-PORT-SWITCH/run.sh b/Runner/suites/Kernel/DEBUG/STM-HWE-PORT-SWITCH/run.sh index d1823d02..85565b3f 100755 --- a/Runner/suites/Kernel/DEBUG/STM-HWE-PORT-SWITCH/run.sh +++ b/Runner/suites/Kernel/DEBUG/STM-HWE-PORT-SWITCH/run.sh @@ -67,7 +67,7 @@ reset_source_sink() { test_attribute() { attr_name=$1 attr_path="$stm_path/$attr_name" - + log_info "Testing Attribute: $attr_name" if [ ! -f "$attr_path" ]; then @@ -77,12 +77,12 @@ test_attribute() { for stm_state in 0 1; do echo "$stm_state" > "$stm_path/enable_source" - + for val in 0 1; do echo "$val" > "$attr_path" readback=$(cat "$attr_path") - - + + if [ "$attr_name" = "hwe_enable" ]; then if [ "$readback" -eq "$val" ]; then log_pass "STM_Src:$stm_state | $attr_name set to $val" @@ -94,7 +94,7 @@ test_attribute() { elif [ "$attr_name" = "port_enable" ]; then if [ "$val" -eq 1 ] && [ "$readback" != "0" ] && [ "$readback" != "0x0" ]; then log_pass "STM_Src:$stm_state | $attr_name set to $val" - elif [ "$val" -eq 0 ] && [ "$readback" = "0" ]; then + elif [ "$val" -eq 0 ] && [ "$readback" = "0" ]; then log_pass "STM_Src:$stm_state | $attr_name set to $val" elif [ "$val" -eq 0 ] && [ "$readback" = "0x0" ]; then log_pass "STM_Src:$stm_state | $attr_name set to $val" @@ -106,7 +106,7 @@ test_attribute() { fi done done - + echo "$TESTNAME PASS" > "$res_file" return 0 } @@ -139,4 +139,4 @@ if [ -f "$stm_path/port_enable" ]; then echo 0xffffffff > "$stm_path/port_enable" fi -log_info "-------------------$TESTNAME Testcase Finished----------------------------" \ No newline at end of file +log_info "-------------------$TESTNAME Testcase Finished----------------------------" \ No newline at end of file diff --git a/Runner/suites/Kernel/DEBUG/STM-Source-Enable-Disable/run.sh b/Runner/suites/Kernel/DEBUG/STM-Source-Enable-Disable/run.sh index 1d31537f..d251bf2a 100755 --- a/Runner/suites/Kernel/DEBUG/STM-Source-Enable-Disable/run.sh +++ b/Runner/suites/Kernel/DEBUG/STM-Source-Enable-Disable/run.sh @@ -138,10 +138,10 @@ fi count=1 while [ "$count" -le 50 ]; do - + echo 1 > "$stm_path/enable_source" 2>/dev/null val=$(cat "$stm_path/enable_source" 2>/dev/null) - + if [ "$val" != "1" ]; then log_fail "Iteration $count: Failed to enable STM source" fail=$((fail + 1)) @@ -149,7 +149,7 @@ while [ "$count" -le 50 ]; do echo 0 > "$stm_path/enable_source" 2>/dev/null val=$(cat "$stm_path/enable_source" 2>/dev/null) - + if [ "$val" != "0" ]; then log_fail "Iteration $count: Failed to disable STM source" fail=$((fail + 1)) @@ -168,4 +168,4 @@ else echo "$TESTNAME FAIL" > "$res_file" fi -log_info "-------------------$TESTNAME Testcase Finished----------------------------" \ No newline at end of file +log_info "-------------------$TESTNAME Testcase Finished----------------------------" \ No newline at end of file diff --git a/Runner/suites/Kernel/DEBUG/STM-Trace-Marker/run.sh b/Runner/suites/Kernel/DEBUG/STM-Trace-Marker/run.sh index 139b1fc4..1af00a8e 100755 --- a/Runner/suites/Kernel/DEBUG/STM-Trace-Marker/run.sh +++ b/Runner/suites/Kernel/DEBUG/STM-Trace-Marker/run.sh @@ -46,7 +46,7 @@ log_info "Checking if required tools are available" for tool in timeout stat seq; do if ! command -v "$tool" >/dev/null 2>&1; then log_skip "Required tool '$tool' not found. Skipping test." - echo "$TESTNAME SKIP" > "$res_file" + echo "$TESTNAME SKIP" > "$res_file" exit 0 fi done @@ -90,16 +90,16 @@ etf_path=$(find_first_existing_path "tmc_etf0" "tmc_etf" "tmc_etf1") cleanup_trace_marker() { log_info "Cleaning up Ftrace and STM settings..." - + [ -f "$debugfs/tracing/tracing_on" ] && echo 0 > "$debugfs/tracing/tracing_on" 2>/dev/null - + [ -f "$debugfs/tracing/events/sched/sched_switch/enable" ] && \ echo 0 > "$debugfs/tracing/events/sched/sched_switch/enable" 2>/dev/null if [ -n "$stm_path" ] && [ -f "$stm_path/enable_source" ]; then echo 0 > "$stm_path/enable_source" 2>/dev/null fi - + if [ -n "$etf_path" ] && [ -f "$etf_path/enable_sink" ]; then echo 0 > "$etf_path/enable_sink" 2>/dev/null fi @@ -187,7 +187,7 @@ fi if [ -s "$tmp_out" ]; then bin_size=$(stat -c%s "$tmp_out") log_info "Captured binary size: $bin_size bytes" - + if [ "$bin_size" -ge 65536 ]; then log_pass "Successfully captured STM trace data ($bin_size bytes)" echo "$TESTNAME PASS" > "$res_file" @@ -202,4 +202,4 @@ fi cleanup_trace_marker -log_info "-------------------$TESTNAME Testcase Finished----------------------------" \ No newline at end of file +log_info "-------------------$TESTNAME Testcase Finished----------------------------" \ No newline at end of file diff --git a/Runner/suites/Kernel/DEBUG/Sink-Status-STM-Toggle/run.sh b/Runner/suites/Kernel/DEBUG/Sink-Status-STM-Toggle/run.sh index ef0e10b2..04786a49 100755 --- a/Runner/suites/Kernel/DEBUG/Sink-Status-STM-Toggle/run.sh +++ b/Runner/suites/Kernel/DEBUG/Sink-Status-STM-Toggle/run.sh @@ -124,19 +124,19 @@ log_info "=== Phase 1: STM Only Test ===" for sink in $sink_list; do log_info "Testing Sink: $(basename "$sink")" - + reset_devices echo 1 > "$sink/enable_sink" echo 1 > "$stm_path/enable_source" sleep 1 - + if ! check_sink_status "$sink" 1 "Phase1_STM_Enable"; then fail=$((fail + 1)) fi - + echo 0 > "$stm_path/enable_source" sleep 1 - + echo 0 > "$sink/enable_sink" if ! check_sink_status "$sink" 0 "Phase1_STM_Disable"; then fail=$((fail + 1)) @@ -162,24 +162,24 @@ fi if [ "$has_etm" -eq 1 ]; then for sink in $sink_list; do log_info "Testing Sink (Multi-Source): $(basename "$sink")" - + reset_devices echo 1 > "$sink/enable_sink" - + echo 1 > "$stm_path/enable_source" echo 1 > "$etm_path/enable_source" sleep 1 - + if ! check_sink_status "$sink" 1 "Phase2_Both_Enable"; then fail=$((fail + 1)) fi - + echo 0 > "$stm_path/enable_source" - + if ! check_sink_status "$sink" 1 "Phase2_STM_Disable_ETM_Active"; then fail=$((fail + 1)) fi - + reset_devices done else @@ -196,4 +196,4 @@ else echo "$TESTNAME FAIL" > "$res_file" fi -log_info "-------------------$TESTNAME Testcase Finished----------------------------" \ No newline at end of file +log_info "-------------------$TESTNAME Testcase Finished----------------------------" \ No newline at end of file diff --git a/Runner/suites/Kernel/DEBUG/TPDM-Enable-Disable/run.sh b/Runner/suites/Kernel/DEBUG/TPDM-Enable-Disable/run.sh index 54fbef0a..808a1f5c 100755 --- a/Runner/suites/Kernel/DEBUG/TPDM-Enable-Disable/run.sh +++ b/Runner/suites/Kernel/DEBUG/TPDM-Enable-Disable/run.sh @@ -29,7 +29,7 @@ fi # shellcheck disable=SC1090,SC1091 . "$TOOLS/functestlib.sh" # shellcheck disable=SC1090,SC1091 -. "$TOOLS/coresight_helper.sh" +. "$TOOLS/coresight_helper.sh" TESTNAME="TPDM-Enable-Disable" res_file="./$TESTNAME.res" @@ -64,27 +64,27 @@ reset_devices while [ "$i" -le 50 ]; do iter_fail=0 - + for node_path in "$cs_base"/tpdm* "$cs_base"/coresight-tpdm*; do [ ! -d "$node_path" ] && continue - + node_name=$(basename "$node_path") - + if echo "$node_name" | grep -q "tpdm-turing-llm"; then continue fi - + if [ ! -f "$node_path/enable_source" ]; then continue fi - + echo 1 > "$node_path/enable_source" 2>/dev/null if [ "$(cat "$node_path/enable_source" 2>/dev/null)" != "1" ]; then iter_fail=1 log_fail "Iter $i: Failed to enable $node_name" echo "$TESTNAME FAIL" > "$res_file" fi - + echo 0 > "$node_path/enable_source" 2>/dev/null if [ "$(cat "$node_path/enable_source" 2>/dev/null)" = "1" ]; then iter_fail=1 @@ -92,14 +92,14 @@ while [ "$i" -le 50 ]; do echo "$TESTNAME FAIL" > "$res_file" fi done - + if [ "$iter_fail" -eq 0 ]; then log_info "Iteration: $i - PASS" else log_fail "Iteration: $i - FAIL" fail=1 fi - + i=$((i+1)) done @@ -114,4 +114,4 @@ else echo "$TESTNAME FAIL" > "$res_file" fi -log_info "-------------------$TESTNAME Testcase Finished----------------------------" \ No newline at end of file +log_info "-------------------$TESTNAME Testcase Finished----------------------------" \ No newline at end of file diff --git a/Runner/suites/Kernel/DEBUG/TPDM-Interface-Access/run.sh b/Runner/suites/Kernel/DEBUG/TPDM-Interface-Access/run.sh index 735e9a3c..330d3f79 100755 --- a/Runner/suites/Kernel/DEBUG/TPDM-Interface-Access/run.sh +++ b/Runner/suites/Kernel/DEBUG/TPDM-Interface-Access/run.sh @@ -59,7 +59,7 @@ dataset_map(){ mode_atrr(){ mode=$1 fail_flag=0 - + for attr_file in "$cs_base/$tpdm_device/$mode"*; do if [ -f "$attr_file" ] && [ -r "$attr_file" ]; then if ! cat "$attr_file" >/dev/null 2>&1; then @@ -95,31 +95,31 @@ for tpdm_path in "$cs_base"/tpdm* "$cs_base"/coresight-tpdm*; do [ ! -d "$tpdm_path" ] && continue tpdm_device=$(basename "$tpdm_path") tpdm_found=$((tpdm_found + 1)) - + if echo "$tpdm_device" | grep -q "tpdm-turing-llm"; then log_info "Skipping unsupported source: $tpdm_device" continue fi - + if [ ! -f "$tpdm_path/enable_source" ]; then continue fi - + log_info "Testing device: $tpdm_device" - + echo 1 > "$tpdm_path/enable_source" 2>/dev/null - + datasets=$(cat "$tpdm_path/enable_datasets" 2>/dev/null) set_mode=$(printf "%d" "0x$datasets" 2>/dev/null || echo 0) dataset_map "$set_mode" - + log_info " Default datasets: $datasets (Mode: $set_mode) -> Configurations: $mode_config" - + for mode in $mode_config; do if [ "$mode" = "none" ]; then continue fi - + mode_atrr "$mode" if mode_atrr "$mode"; then log_pass " PASS: $mode attributes" @@ -128,7 +128,7 @@ for tpdm_path in "$cs_base"/tpdm* "$cs_base"/coresight-tpdm*; do fail_count=$((fail_count + 1)) fi done - + echo 0 > "$tpdm_path/enable_source" 2>/dev/null done @@ -153,20 +153,20 @@ log_info "--- Phase 2: Readable attributes check ---" for tpdm_path in "$cs_base"/tpdm* "$cs_base"/coresight-tpdm*; do [ ! -d "$tpdm_path" ] && continue tpdm_device=$(basename "$tpdm_path") - + if echo "$tpdm_device" | grep -q "tpdm-turing-llm"; then continue fi - + if_count=0 for attr_file in "$tpdm_path"/*; do if [ -f "$attr_file" ] && [ -r "$attr_file" ]; then if_count=$((if_count + 1)) fi done - + log_info "Reading $if_count accessible nodes under $tpdm_device" - + for attr_file in "$tpdm_path"/*; do if [ -f "$attr_file" ] && [ -r "$attr_file" ]; then cat "$attr_file" >/dev/null 2>&1 @@ -188,4 +188,4 @@ else echo "$TESTNAME FAIL" > "$res_file" fi -log_info "-------------------$TESTNAME Testcase Finished----------------------------" \ No newline at end of file +log_info "-------------------$TESTNAME Testcase Finished----------------------------" \ No newline at end of file diff --git a/Runner/suites/Kernel/Scheduler/CPU_affinity/run.sh b/Runner/suites/Kernel/Scheduler/CPU_affinity/run.sh index d0f8f106..4326f722 100755 --- a/Runner/suites/Kernel/Scheduler/CPU_affinity/run.sh +++ b/Runner/suites/Kernel/Scheduler/CPU_affinity/run.sh @@ -12,12 +12,12 @@ while [ "$SEARCH" != "/" ]; do fi SEARCH=$(dirname "$SEARCH") done - + if [ -z "$INIT_ENV" ]; then echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 exit 1 fi - + # Only source if not already loaded (idempotent) if [ -z "$__INIT_ENV_LOADED" ]; then # shellcheck disable=SC1090 diff --git a/Runner/suites/Multimedia/Audio/AudioPlayback/run.sh b/Runner/suites/Multimedia/Audio/AudioPlayback/run.sh index 0f91871c..2438367e 100755 --- a/Runner/suites/Multimedia/Audio/AudioPlayback/run.sh +++ b/Runner/suites/Multimedia/Audio/AudioPlayback/run.sh @@ -934,7 +934,7 @@ else if [ -z "$clip" ]; then log_warn "[$case_name] No clip mapping for format=$fmt duration=$dur" echo "$case_name SKIP (no clip mapping)" >> "$LOGDIR/summary.txt" - skip=$((skip + 1)) + skip=$((skip + 1)) continue fi diff --git a/Runner/suites/Multimedia/Audio/AudioRecord/run.sh b/Runner/suites/Multimedia/Audio/AudioRecord/run.sh index 7196aba0..4c050c3e 100755 --- a/Runner/suites/Multimedia/Audio/AudioRecord/run.sh +++ b/Runner/suites/Multimedia/Audio/AudioRecord/run.sh @@ -517,16 +517,16 @@ esac # after creating empty files. if [ -z "$SRC_ID" ] && [ "$SRC_CHOICE" = "mic" ] && [ "$AUDIO_BACKEND" = "pipewire" ]; then log_warn "$TESTNAME: no concrete PipeWire mic source found; probing direct ALSA capture path" - + if audio_probe_alsa_capture_profile; then ALSA_CAPTURE_PROBED=1 AUDIO_BACKEND="alsa" AUDIO_SYSTEMD_MANAGED=0 export AUDIO_SYSTEMD_MANAGED - + SRC_ID="$AUDIO_ALSA_CAPTURE_DEVICE" SRC_LABEL="$SRC_ID" - + log_warn "$TESTNAME: falling back to direct ALSA capture device: $SRC_ID" else log_skip "$TESTNAME SKIP - no real capture source available; PipeWire mic source missing and ALSA capture probe failed: ${AUDIO_ALSA_CAPTURE_REASON:-capture path unavailable}" @@ -534,11 +534,11 @@ if [ -z "$SRC_ID" ] && [ "$SRC_CHOICE" = "mic" ] && [ "$AUDIO_BACKEND" = "pipewi exit 0 fi fi - + if [ -z "$SRC_ID" ] && [ "$SRC_CHOICE" = "mic" ] && [ "$AUDIO_BACKEND" != "pipewire" ]; then for b in $BACKENDS_TO_TRY; do [ "$b" = "$AUDIO_BACKEND" ] && continue - + case "$b" in pipewire) cand="$(pw_default_mic)" @@ -564,10 +564,10 @@ if [ -z "$SRC_ID" ] && [ "$SRC_CHOICE" = "mic" ] && [ "$AUDIO_BACKEND" != "pipew AUDIO_BACKEND="alsa" AUDIO_SYSTEMD_MANAGED=0 export AUDIO_SYSTEMD_MANAGED - + SRC_ID="$AUDIO_ALSA_CAPTURE_DEVICE" SRC_LABEL="$SRC_ID" - + log_info "Falling back to backend: alsa (device=$SRC_ID)" break fi @@ -575,7 +575,7 @@ if [ -z "$SRC_ID" ] && [ "$SRC_CHOICE" = "mic" ] && [ "$AUDIO_BACKEND" != "pipew esac done fi - + if [ -z "$SRC_ID" ]; then log_skip "$TESTNAME SKIP - requested source '$SRC_CHOICE' not available on any backend (${BACKENDS_TO_TRY:-unknown})" echo "$RESULT_TESTNAME SKIP" > "$RES_FILE" diff --git a/Runner/suites/Multimedia/Camera/Libcamera_cam/run.sh b/Runner/suites/Multimedia/Camera/Libcamera_cam/run.sh index dd8e5bb7..6c616f25 100755 --- a/Runner/suites/Multimedia/Camera/Libcamera_cam/run.sh +++ b/Runner/suites/Multimedia/Camera/Libcamera_cam/run.sh @@ -120,11 +120,11 @@ done # ---------- DT / platform readiness ---------- # Print both sensor and CAMSS/ISP matches if they exist; skip only if neither is present. log_info "Verifying the availability of DT nodes, this process may take some time." - + PATTERNS="sony,imx577 imx577 isp cam camss" found_any=0 missing_list="" - + for pat in $PATTERNS; do out="$(dt_confirm_node_or_compatible "$pat" 2>/dev/null || true)" if [ -n "$out" ]; then @@ -134,7 +134,7 @@ for pat in $PATTERNS; do [ -n "$missing_list" ] && missing_list="$missing_list, $pat" || missing_list="$pat" fi done - + if [ "$found_any" -eq 1 ]; then log_info "DT nodes present (see matches above)." else @@ -177,13 +177,13 @@ SENSOR_COUNT="$(libcam_list_sensors_count 2>/dev/null)" # harden: ensure numeric case "$SENSOR_COUNT" in ''|*[!0-9]*) SENSOR_COUNT=0 ;; esac log_info "[cam -l] detected ${SENSOR_COUNT} camera(s)" - + if [ "$SENSOR_COUNT" -lt 1 ]; then log_skip "No sensors reported by 'cam -l' - marking SKIP" echo "$TESTNAME SKIP" > "$RES_FILE" exit 0 fi - + # ---------- Resolve indices (supports: auto | all | 0,2,5) ---------- INDICES="$(libcam_resolve_indices "$CAM_INDEX")" diff --git a/Runner/suites/Multimedia/GSTreamer/AI_ML/run.sh b/Runner/suites/Multimedia/GSTreamer/AI_ML/run.sh index 1306899e..dd961538 100755 --- a/Runner/suites/Multimedia/GSTreamer/AI_ML/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/AI_ML/run.sh @@ -196,7 +196,7 @@ done # GStreamer pipelines # ---------------------------------------------------------------------- DETECTION_PIPELINE='filesrc location='"${test_path}"'/assets/video.mp4 ! qtdemux ! queue ! h264parse ! v4l2h264dec capture-io-mode=4 output-io-mode=4 ! queue ! tee name=split split. ! queue ! qtivcomposer name=mixer ! queue ! waylandsink sync=true fullscreen=true split. ! queue ! qtimlvconverter ! queue ! qtimltflite delegate=external external-delegate-path=libQnnTFLiteDelegate.so external-delegate-options="QNNExternalDelegate,backend_type=htp;" model='"${test_path}"'/assets/yolox_quantized.tflite ! queue ! qtimlpostprocess module=yolov8 labels='"${test_path}"'/assets/labels_ga16/labels/yolox.json settings="{\"confidence\": 50.0}" ! video/x-raw,format=BGRA,width=640,height=360 ! queue ! mixer.' -# gst-launch-1.0 -e +# gst-launch-1.0 -e CLASSIFICATION_PIPELINE='filesrc location='"${test_path}"'/assets/video.mp4 ! qtdemux ! queue ! h264parse ! v4l2h264dec capture-io-mode=4 output-io-mode=4 ! video/x-raw,format=NV12_Q08C ! queue ! tee name=split ! queue ! qtimetamux name=metamux ! queue ! qtivoverlay ! queue ! v4l2h264enc capture-io-mode=4 output-io-mode=5 ! h264parse ! queue ! mp4mux ! queue ! filesink location='"${ENCODED_VIDEO_PATH}"' split. ! queue ! qtimlvconverter ! queue ! qtimltflite delegate=external external-delegate-path=libQnnTFLiteDelegate.so external-delegate-options="QNNExternalDelegate,backend_type=htp;" model='"${test_path}"'/assets/inception_v3_quantized.tflite ! queue ! qtimlpostprocess results=5 module=mobilenet-softmax labels='"${test_path}"'/assets/labels_ga15/labels/imagenet_labels.txt settings="{\"confidence\": 31.0}" ! text/x-raw ! queue ! metamux.' # ---------------------------------------------------------------------- diff --git a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh index 515369cd..e7e7344f 100755 --- a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh @@ -234,7 +234,7 @@ while [ $# -gt 0 ]; do fi shift 2 ;; - + --clip-path) if [ $# -lt 2 ] || [ "${2#--}" != "$2" ]; then log_warn "Missing/invalid value for --clip-path" @@ -247,7 +247,7 @@ while [ $# -gt 0 ]; do fi shift 2 ;; - + --test-name) if [ $# -lt 2 ] || [ "${2#--}" != "$2" ]; then log_warn "Missing/invalid value for --test-name" @@ -469,7 +469,7 @@ run_record_test() { ext="$fmt" output_file="$RECORDED_DIR/${testname}.${ext}" test_log="$OUTDIR/${testname}.log" - + # Remove stale artifact from a previous rerun. rm -f "$output_file" @@ -625,7 +625,7 @@ run_record_pulsesrc_test() { ext="$fmt" output_file="$RECORDED_DIR/${testname}.${ext}" test_log="$OUTDIR/${testname}.log" - + # Remove stale artifact from a previous rerun. rm -f "$output_file" @@ -684,27 +684,27 @@ run_record_pulsesrc_test() { # -------------------- PulseSrc Playback test function -------------------- run_playback_pulsesrc_test() { fmt="$1" - + testname="playback_pulsesrc_${fmt}" log_info "==========================================" log_info "Running: $testname" log_info "==========================================" - + ext="$fmt" input_file="$RECORDED_DIR/record_pulsesrc_${fmt}.${ext}" - + if [ ! -f "$input_file" ]; then if [ "$testMode" = "all" ]; then log_fail "$testname: FAIL - expected recorded file is missing: $input_file (pulsesrc record testcase failed in same run)" fail_count=$((fail_count + 1)) return 1 fi - + log_warn "$testname: SKIP - recorded file not found: $input_file (run pulsesrc record first)" skip_count=$((skip_count + 1)) return 1 fi - + file_size="$(gstreamer_file_size_bytes "$input_file")" if [ "$file_size" -le 1000 ]; then if [ "$testMode" = "all" ]; then @@ -712,43 +712,43 @@ run_playback_pulsesrc_test() { fail_count=$((fail_count + 1)) return 1 fi - + log_warn "$testname: SKIP - recorded file too small: $file_size bytes (pulsesrc recording likely failed)" skip_count=$((skip_count + 1)) return 1 fi - + test_log="$OUTDIR/${testname}.log" : >"$test_log" - + # pulsesrc recordings are timeout-driven and can be longer than the nominal # AUDIO_DURATION. Keep extra headroom here so valid same-run artifacts do not # fail intermittently due to playback timeout racing EOS/finalization. playback_timeout=$((duration + 20)) pipeline="$(gstreamer_build_audio_playback_pipeline "$fmt" "$input_file")" - + if [ -z "$pipeline" ]; then log_fail "$testname: FAIL (could not build playback pipeline)" fail_count=$((fail_count + 1)) return 1 fi - + log_info "Pipeline: $pipeline" - - if gstreamer_run_gstlaunch_timeout "$playback_timeout" "$pipeline" >>"$test_log" 2>&1; then + + if gstreamer_run_gstlaunch_timeout "$playback_timeout" "$pipeline" >>"$test_log" 2>&1; then gstRc=0 else gstRc=$? fi - + log_info "$testname: playback timeout budget=${playback_timeout}s" - + if ! gstreamer_validate_log "$test_log" "$testname"; then log_fail "$testname: FAIL (GStreamer errors detected)" fail_count=$((fail_count + 1)) return 1 fi - + if [ "$gstRc" -eq 0 ]; then log_pass "$testname: PASS" pass_count=$((pass_count + 1)) @@ -762,12 +762,12 @@ run_playback_pulsesrc_test() { # -------------------- Test file playback test function (OGG/MP3) -------------------- run_playback_ogg_mp3_test() { fmt="$1" - + testname="playback_sample_${fmt}" log_info "==========================================" log_info "Running: $testname" log_info "==========================================" - + # Determine input file based on format case "$fmt" in ogg) @@ -782,13 +782,13 @@ run_playback_ogg_mp3_test() { return 1 ;; esac - + if [ ! -f "$input_file" ]; then log_warn "$testname: SKIP - Test file not found: $input_file" skip_count=$((skip_count + 1)) return 1 fi - + # Check if file has minimum content file_size="$(gstreamer_file_size_bytes "$input_file")" if [ "$file_size" -le 1000 ]; then @@ -796,36 +796,36 @@ run_playback_ogg_mp3_test() { skip_count=$((skip_count + 1)) return 1 fi - + test_log="$OUTDIR/${testname}.log" : >"$test_log" - + pipeline="$(gstreamer_build_audio_playback_pipeline "$fmt" "$input_file")" - + if [ -z "$pipeline" ]; then log_fail "$testname: FAIL (could not build playback pipeline - format not supported or elements missing)" fail_count=$((fail_count + 1)) return 1 fi - + log_info "Pipeline: $pipeline" - + # Run playback if gstreamer_run_gstlaunch_timeout "$((duration + 10))" "$pipeline" >>"$test_log" 2>&1; then gstRc=0 else gstRc=$? fi - + log_info "Playback exit code: $gstRc" - + # Check for GStreamer errors in log if ! gstreamer_validate_log "$test_log" "$testname"; then log_fail "$testname: FAIL (GStreamer errors detected)" fail_count=$((fail_count + 1)) return 1 fi - + # Check for successful completion if [ "$gstRc" -eq 0 ]; then log_pass "$testname: PASS" @@ -1012,7 +1012,7 @@ provision_test_files() { sample_ogg="$OUTDIR/sample_audio.ogg" sample_mp3="$OUTDIR/sample_audio.mp3" - + # Refresh once at each provisioning stage boundary. # This is intentional: later stages depend on the latest have_ogg/have_mp3 # values after local-path copy, URL extraction, or best-effort generation. @@ -1121,9 +1121,9 @@ if [ -n "$testName" ]; then log_info "==========================================" log_info "INDIVIDUAL TEST MODE: $testName" log_info "==========================================" - + total_tests=1 - + case "$testName" in record_wav) run_record_test "wav" || true @@ -1156,7 +1156,7 @@ if [ -n "$testName" ]; then run_playback_ogg_mp3_test "mp3" || true ;; esac - + # -------------------- Grouped Test Mode (Original) -------------------- else # Run ALL record/encode tests first (4 tests total) @@ -1184,7 +1184,7 @@ else if [ "$testMode" = "all" ] || [ "$testMode" = "playback" ]; then # Provision test files only when running playback tests provision_test_files "$OUTDIR" "$NUM_BUFFERS" "$duration" "$clipPath" "$clipUrl" "$USER_CLIP_PATH_SET" "$USER_CLIP_URL_SET" - + log_info "==========================================" log_info "PLAYBACK TESTS" log_info "==========================================" @@ -1202,7 +1202,7 @@ else total_tests=$((total_tests + 1)) run_playback_pulsesrc_test "$fmt" || true done - + # 5. Playback Test files (2 tests: ogg, mp3) log_info "Playing back Test files (OGG/MP3)..." for fmt in ogg mp3; do diff --git a/Runner/suites/Multimedia/GSTreamer/Camera/Camera_Tests/run.sh b/Runner/suites/Multimedia/GSTreamer/Camera/Camera_Tests/run.sh index 5da38175..1b17e542 100755 --- a/Runner/suites/Multimedia/GSTreamer/Camera/Camera_Tests/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/Camera/Camera_Tests/run.sh @@ -25,7 +25,7 @@ ENCODED_DIR="$OUTDIR/encoded" mkdir -p "$OUTDIR" "$DMESG_DIR" "$ENCODED_DIR" >/dev/null 2>&1 || true : >"$RES_FILE" : >"$GST_LOG" - + INIT_ENV="" SEARCH="$SCRIPT_DIR" while [ "$SEARCH" != "/" ]; do @@ -35,13 +35,13 @@ while [ "$SEARCH" != "/" ]; do fi SEARCH=$(dirname "$SEARCH") done - + if [ -z "${INIT_ENV:-}" ]; then echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 echo "$RESULT_TESTNAME SKIP" >"$RES_FILE" 2>/dev/null || true exit 0 fi - + if [ -z "${__INIT_ENV_LOADED:-}" ]; then # shellcheck disable=SC1090 . "$INIT_ENV" @@ -90,7 +90,7 @@ for param in CAMERA_DURATION CAMERA_FRAMERATE CAMERA_GST_DEBUG GST_DEBUG_LEVEL; if [ -n "$val" ]; then case "$val" in - ''|*[!0-9]*) + ''|*[!0-9]*) log_warn "$param must be numeric (got '$val')" echo "$RESULT_TESTNAME SKIP" >"$RES_FILE" exit 0 @@ -181,7 +181,7 @@ while [ $# -gt 0 ]; do fi if [ -n "$2" ]; then case "$2" in - ''|*[!0-9]*) + ''|*[!0-9]*) log_warn "Invalid --framerate '$2' (must be numeric)" echo "$RESULT_TESTNAME SKIP" >"$RES_FILE" exit 0 @@ -250,7 +250,7 @@ OVERVIEW: source plugins: - qtiqmmfsrc (Qualcomm CAMX downstream) - 12 tests - libcamerasrc (upstream) - 9 tests - + Tests run in sequence to progressively validate different camera capabilities. TEST SEQUENCES: @@ -367,11 +367,11 @@ TEST DETAILS: Fakesink (2): - fakesink_nv12 : NV12 format, 720p, no encoding - fakesink_ubwc : UBWC format, 720p, no encoding - + Preview (2): - preview_nv12_4k : NV12 format, 4K, Weston display - preview_ubwc_4k : UBWC format, 4K, Weston display - + Encode (6): - encode_nv12_720p : NV12, 1280x720, H.264 encode - encode_nv12_1080p : NV12, 1920x1080, H.264 encode @@ -379,7 +379,7 @@ TEST DETAILS: - encode_ubwc_720p : UBWC, 1280x720, H.264 encode - encode_ubwc_1080p : UBWC, 1920x1080, H.264 encode - encode_ubwc_4k : UBWC, 3840x2160, H.264 encode - + Snapshot (2): - snapshot_1080p : NV12, 1920x1080, JPEG still capture (2 images) - snapshot_4k : NV12, 3840x2160, JPEG still capture (2 images) @@ -388,16 +388,16 @@ TEST DETAILS: Fakesink (2): - libcam_720p_Fakesink : 720p, no encoding - libcam_1080p_Fakesink : 1080p, no encoding - + Preview (2): - libcam_720p_Preview : 720p, Weston display - libcam_1080p_Preview : 1080p, Weston display - + Encode (3): - libcam_720p_NV12_Encode : NV12, 1280x720, H.264 encode - libcam_1080p_NV12_Encode : NV12, 1920x1080, H.264 encode - libcam_4k_NV12_Encode : NV12, 3840x2160, H.264 encode - + Snapshot (2): - libcam_1080p_Snapshot : 1920x1080, JPEG still capture (2 images) - libcam_4k_Snapshot : 3840x2160, JPEG still capture (5 images) @@ -432,7 +432,7 @@ PREREQUISITES: - qtiqmmfsrc (Qualcomm camera source) - v4l2h264enc (V4L2 H.264 encoder, for encode) - waylandsink (Wayland display, for preview) - + For libcamerasrc (9 tests): - libcamerasrc (Upstream camera source) - videoconvert (Video format converter, required) @@ -566,10 +566,10 @@ camera_preflight_checks() { log_info "==========================================" log_info "CAMERA PRE-FLIGHT CHECKS" log_info "==========================================" - + checks_passed=0 checks_failed=0 - + # Check 1: GStreamer plugin validation (CRITICAL) log_info "[1/3] GStreamer plugin validation..." if has_element "$camera_source"; then @@ -579,7 +579,7 @@ camera_preflight_checks() { log_fail " ✗ GStreamer plugin missing: $camera_source" checks_failed=$((checks_failed + 1)) fi - + # Check 2: Required encoder plugin (only if encode tests are requested) if echo "$testModeList" | grep -q "encode"; then log_info "[2/3] H.264 encoder plugin check..." @@ -593,26 +593,26 @@ camera_preflight_checks() { log_info "[2/3] H.264 encoder plugin check... skipped (encode tests not requested)" checks_passed=$((checks_passed + 1)) fi - + # Check 3: Required snapshot plugins (only if snapshot tests are requested) if echo "$testModeList" | grep -q "snapshot"; then log_info "[3/3] Snapshot plugin checks..." snapshot_checks_failed=0 - + if has_element jpegenc; then log_pass " ✓ jpegenc available" else log_fail " ✗ jpegenc not available (required for snapshot tests)" snapshot_checks_failed=$((snapshot_checks_failed + 1)) fi - + if has_element multifilesink; then log_pass " ✓ multifilesink available" else log_fail " ✗ multifilesink not available (required for snapshot tests)" snapshot_checks_failed=$((snapshot_checks_failed + 1)) fi - + # For libcamerasrc, also check videoconvert if [ "$camera_source" = "libcamerasrc" ]; then if has_element videoconvert; then @@ -622,7 +622,7 @@ camera_preflight_checks() { snapshot_checks_failed=$((snapshot_checks_failed + 1)) fi fi - + if [ "$snapshot_checks_failed" -eq 0 ]; then checks_passed=$((checks_passed + 1)) else @@ -632,15 +632,15 @@ camera_preflight_checks() { log_info "[3/3] Snapshot plugin checks... skipped (snapshot tests not requested)" checks_passed=$((checks_passed + 1)) fi - + log_info "==========================================" log_info "Pre-flight summary: $checks_passed passed, $checks_failed failed" log_info "==========================================" - + if [ "$checks_failed" -gt 0 ]; then return 1 fi - + return 0 } @@ -648,11 +648,11 @@ camera_preflight_checks() { diagnose_camera_failure() { testname="$1" log_file="$2" - + log_info "==========================================" log_info "FAILURE DIAGNOSTICS: $testname" log_info "==========================================" - + # Check for common GStreamer errors if grep -qi "Could not open camera\|cannot open camera\|failed to open camera" "$log_file"; then log_fail "Issue: Camera device not accessible" @@ -668,7 +668,7 @@ diagnose_camera_failure() { log_info " $line" done fi - + if grep -qi "not-negotiated\|negotiation failed\|could not negotiate" "$log_file"; then log_fail "Issue: Format negotiation failed" log_info "Possible causes:" @@ -676,17 +676,17 @@ diagnose_camera_failure() { log_info " - Pipeline element incompatibility" log_info " - Missing caps filter or incorrect format string" log_info "" - + # Show what was requested if grep -q "video/x-raw" "$log_file"; then requested=$(grep -o "video/x-raw[^!]*" "$log_file" | head -1) log_info " Requested caps: $requested" fi fi - + if grep -qi "firmware" "$log_file"; then log_fail "Issue: Firmware-related error detected" - + if command -v camx_find_icp_firmware >/dev/null 2>&1; then icp_fw=$(camx_find_icp_firmware 2>/dev/null || echo "") if [ -z "$icp_fw" ]; then @@ -698,12 +698,12 @@ diagnose_camera_failure() { fi fi fi - + if grep -qi "device.*not.*found\|no such device" "$log_file"; then log_fail "Issue: Device not found" log_info "" log_info "Hardware check:" - + # Check Device Tree camera nodes if command -v camx_fdtdump_has_cam_nodes >/dev/null 2>&1; then if camx_fdtdump_has_cam_nodes >/dev/null 2>&1; then @@ -713,7 +713,7 @@ diagnose_camera_failure() { log_info " Hardware may not be properly configured" fi fi - + # Check video devices # shellcheck disable=SC2012 video_count=$(ls /dev/video* 2>/dev/null | wc -l) @@ -724,7 +724,7 @@ diagnose_camera_failure() { log_info " ✓ Video devices present: $video_count" fi fi - + if grep -qi "timeout\|timed out" "$log_file"; then log_fail "Issue: Operation timeout" log_info "Possible causes:" @@ -732,20 +732,20 @@ diagnose_camera_failure() { log_info " - Driver issue or hang" log_info " - Insufficient system resources" fi - + if grep -qi "permission denied\|access denied" "$log_file"; then log_fail "Issue: Permission denied" log_info "Solution: Add user to video group:" log_info " sudo usermod -a -G video \$USER" log_info " (logout and login required)" fi - + # Check for UBWC-specific issues if echo "$testname" | grep -q "ubwc" && grep -qi "format.*not.*supported" "$log_file"; then log_fail "Issue: UBWC format not supported" log_info "Verify pipeline includes: qtiqmmfsrc ! video/x-raw,format=NV12_Q08C" fi - + # Check kernel logs for related errors if [ -d "$DMESG_DIR" ] && [ -f "$DMESG_DIR/dmesg_errors.log" ]; then if grep -qi "camera\|video\|v4l2" "$DMESG_DIR/dmesg_errors.log"; then @@ -755,7 +755,7 @@ diagnose_camera_failure() { done fi fi - + log_info "==========================================" } @@ -771,7 +771,7 @@ if ! camera_preflight_checks; then log_fail " 2. Verify camera hardware is connected" log_fail " 3. Check camera driver is loaded" log_fail "==========================================" - + echo "$RESULT_TESTNAME SKIP" >"$RES_FILE" exit 0 fi @@ -793,48 +793,57 @@ run_camera_test() { testname="$1" pipeline="$2" output_file="${3:-}" - + restart_cam_server="${4:-no}" + log_info "=========================================="; log_info "Running: $testname"; log_info "==========================================" - + + # Restart cam-server if requested (temporary workaround for qtiqmmfsrc only) + # libcamerasrc doesn't use cam-server, so this is skipped for libcamerasrc tests + if [ "$restart_cam_server" = "yes" ] && [ "$camera_source" = "qtiqmmfsrc" ]; then + log_info "Restarting cam-server..." + systemctl restart cam-server >/dev/null 2>&1 || log_warn "Failed to restart cam-server (may not be critical)" + sleep 1 + fi + test_log="$OUTDIR/${testname}.log" : >"$test_log" - + if [ -z "$pipeline" ]; then log_warn "$testname: Failed to build pipeline"; skip_count=$((skip_count + 1)); return 1 fi - + log_info "Pipeline: gst-launch-1.0 -e $pipeline" - + # Run pipeline with timeout if gstreamer_run_gstlaunch_timeout "$((duration + 10))" "$pipeline" >>"$test_log" 2>&1; then gstRc=0; else gstRc=$?; fi - + # Validate log if ! gstreamer_validate_log "$test_log" "$testname"; then diagnose_camera_failure "$testname" "$test_log" log_fail "$testname: FAIL"; fail_count=$((fail_count + 1)); return 1 fi - + # Check for output file if encode test if [ -n "$output_file" ]; then if [ -f "$output_file" ] && [ -s "$output_file" ]; then file_size=$(gstreamer_file_size_bytes "$output_file") # Treat timeout (124) as success if file was created - test is designed to run until timeout - if [ "$file_size" -gt 1000 ] && { [ "$gstRc" -eq 0 ] || [ "$gstRc" -eq 124 ]; }; then + if [ "$file_size" -gt 1000 ] && { [ "$gstRc" -eq 0 ] || [ "$gstRc" -eq 124 ]; }; then log_info "Output file size: $file_size bytes ($(awk "BEGIN {printf \"%.2f\", $file_size/1024/1024}") MB)" log_pass "$testname: PASS"; pass_count=$((pass_count + 1)); return 0 - else + else diagnose_camera_failure "$testname" "$test_log" log_fail "$testname: FAIL (file too small or bad exit code)"; fail_count=$((fail_count + 1)); return 1 fi - else + else diagnose_camera_failure "$testname" "$test_log" log_fail "$testname: FAIL (no output)"; fail_count=$((fail_count + 1)); return 1 fi else # Non-encode test: treat timeout (124) as success - if [ "$gstRc" -eq 0 ] || [ "$gstRc" -eq 124 ]; then + if [ "$gstRc" -eq 0 ] || [ "$gstRc" -eq 124 ]; then log_pass "$testname: PASS"; pass_count=$((pass_count + 1)); return 0 - else + else diagnose_camera_failure "$testname" "$test_log" log_fail "$testname: FAIL (rc=$gstRc)"; fail_count=$((fail_count + 1)); return 1 fi @@ -844,16 +853,16 @@ run_camera_test() { # qtiqmmfsrc Fakesink test run_qtiqmmf_fakesink_test() { format="$1" - + case "$format" in nv12) format_name="NV12" ;; ubwc) format_name="UBWC" ;; *) log_warn "Unknown format: $format"; skip_count=$((skip_count + 1)); return 1 ;; esac - + testname="fakesink_${format}" log_info "Format: $format_name" - + pipeline=$(camera_build_qtiqmmfsrc_fakesink_pipeline "$cameraId" "$format" 1280 720 "$framerate") run_camera_test "$testname" "$pipeline" } @@ -861,21 +870,21 @@ run_qtiqmmf_fakesink_test() { # qtiqmmfsrc Preview test run_qtiqmmf_preview_test() { format="$1" - + case "$format" in nv12) format_name="NV12" ;; ubwc) format_name="UBWC" ;; *) log_warn "Unknown format: $format"; skip_count=$((skip_count + 1)); return 1 ;; esac - + if ! has_element waylandsink; then log_warn "waylandsink not available, skipping preview test" skip_count=$((skip_count + 1)); return 1 fi - + testname="preview_${format}_4k" log_info "Format: $format_name" - + pipeline=$(camera_build_qtiqmmfsrc_preview_pipeline "$cameraId" "$format" 3840 2160 "$framerate") run_camera_test "$testname" "$pipeline" } @@ -886,24 +895,24 @@ run_qtiqmmf_encode_test() { resolution="$2" width="$3" height="$4" - + case "$format" in nv12) format_name="NV12" ;; ubwc) format_name="UBWC" ;; *) log_warn "Unknown format: $format"; skip_count=$((skip_count + 1)); return 1 ;; esac - + if ! has_element v4l2h264enc; then log_warn "v4l2h264enc not available, skipping encode test" skip_count=$((skip_count + 1)); return 1 fi - + testname="encode_${format}_${resolution}" output_file="$ENCODED_DIR/${testname}.mp4" - + log_info "Format: $format_name" log_info "Resolution: $resolution (${width}x${height})" - + pipeline=$(camera_build_qtiqmmfsrc_encode_pipeline "$cameraId" "$format" "$width" "$height" "$framerate" "$output_file") run_camera_test "$testname" "$pipeline" "$output_file" } @@ -914,69 +923,74 @@ run_qtiqmmf_snapshot_test() { width="$2" height="$3" max_files="${4:-2}" - + if ! has_element jpegenc; then log_fail "jpegenc not available - required for snapshot test" fail_count=$((fail_count + 1)); return 1 fi - + if ! has_element multifilesink; then log_fail "multifilesink not available - required for snapshot test" fail_count=$((fail_count + 1)); return 1 fi - + testname="snapshot_${resolution}" output_pattern="$ENCODED_DIR/camera${cameraId}_${resolution}_image%d.jpg" - + log_info "Resolution: $resolution (${width}x${height})" log_info "Max snapshots: $max_files" - + # Clean up old snapshot files from previous runs to avoid false positives if ls "$ENCODED_DIR"/camera"${cameraId}"_"${resolution}"_image*.jpg >/dev/null 2>&1; then log_info "Cleaning up old snapshot files..." rm -f "$ENCODED_DIR"/camera"${cameraId}"_"${resolution}"_image*.jpg fi - + pipeline=$(camera_build_qtiqmmfsrc_snapshot_pipeline "$cameraId" "$width" "$height" "$framerate" "$output_pattern" "$max_files") - + # For snapshot tests, we check if at least one snapshot file was created # Run the test with a shorter timeout since we're only capturing a few frames snapshot_timeout=$((max_files + 5)) - + log_info "=========================================="; log_info "Running: $testname"; log_info "==========================================" - + + # Restart cam-server before snapshot test (qtiqmmfsrc only) + log_info "Restarting cam-server..." + systemctl restart cam-server >/dev/null 2>&1 || log_warn "Failed to restart cam-server (may not be critical)" + sleep 1 + test_log="$OUTDIR/${testname}.log" : >"$test_log" - + if [ -z "$pipeline" ]; then log_warn "$testname: Failed to build pipeline"; skip_count=$((skip_count + 1)); return 1 fi - + log_info "Pipeline: gst-launch-1.0 -e $pipeline" - + # Run pipeline with timeout gstreamer_run_gstlaunch_timeout "$snapshot_timeout" "$pipeline" >>"$test_log" 2>&1 - + # Wait for filesystem to sync sleep 5 - + # Validate log if ! gstreamer_validate_log "$test_log" "$testname"; then diagnose_camera_failure "$testname" "$test_log" log_fail "$testname: FAIL"; fail_count=$((fail_count + 1)); return 1 fi - + # Check if at least one snapshot file was created (any number, not just 0) # multifilesink may continue numbering from previous runs snapshot_files=$(find "$ENCODED_DIR" -name "camera${cameraId}_${resolution}_image*.jpg" -type f 2>/dev/null) snapshot_count=$(printf '%s\n' "$snapshot_files" | grep -c .) - + if [ "$snapshot_count" -gt 0 ]; then # Get the first file found (any number) first_snapshot=$(printf '%s\n' "$snapshot_files" | head -n 1) file_size=$(gstreamer_file_size_bytes "$first_snapshot") log_info "Found snapshot file: $(basename "$first_snapshot")" - + # Check if file size is reasonable for a JPEG if [ "$file_size" -gt "$SNAPSHOT_MIN_BYTES" ]; then log_info "Snapshots created: $snapshot_count (file size: $file_size bytes)" @@ -995,7 +1009,7 @@ run_qtiqmmf_snapshot_test() { run_libcam_fakesink_test() { width="$1" height="$2" - + # Determine test name based on resolution if [ "$width" -eq 0 ] 2>/dev/null || [ "$height" -eq 0 ] 2>/dev/null; then testname="libcam_Default_Fakesink" @@ -1004,9 +1018,9 @@ run_libcam_fakesink_test() { testname="libcam_${width}x${height}_Fakesink" res_name="${width}x${height}" fi - + log_info "Resolution: $res_name" - + pipeline=$(camera_build_libcamera_fakesink_pipeline "$width" "$height" "$framerate") run_camera_test "$testname" "$pipeline" } @@ -1015,17 +1029,17 @@ run_libcam_fakesink_test() { run_libcam_preview_test() { width="$1" height="$2" - + if ! has_element waylandsink; then log_warn "waylandsink not available, skipping libcam preview test" skip_count=$((skip_count + 1)); return 1 fi - + if ! has_element videoconvert; then log_warn "videoconvert not available, skipping libcam preview test" skip_count=$((skip_count + 1)); return 1 fi - + # Determine test name based on resolution if [ "$width" -eq 0 ] 2>/dev/null || [ "$height" -eq 0 ] 2>/dev/null; then testname="libcam_Default_Preview" @@ -1040,9 +1054,9 @@ run_libcam_preview_test() { testname="libcam_${width}x${height}_Preview" res_name="${width}x${height}" fi - + log_info "Resolution: $res_name" - + pipeline=$(camera_build_libcamera_preview_pipeline "$width" "$height" "$framerate") run_camera_test "$testname" "$pipeline" } @@ -1052,22 +1066,22 @@ run_libcam_encode_test() { width="$1" height="$2" resolution_name="$3" - + if ! has_element v4l2h264enc; then log_warn "v4l2h264enc not available, skipping libcam encode test" skip_count=$((skip_count + 1)); return 1 fi - + if ! has_element videoconvert; then log_warn "videoconvert not available, skipping libcam encode test" skip_count=$((skip_count + 1)); return 1 fi - + testname="libcam_${resolution_name}_NV12_Encode" output_file="$ENCODED_DIR/sample_${resolution_name}.mp4" - + log_info "Resolution: $resolution_name (${width}x${height})" - + pipeline=$(camera_build_libcamera_encode_pipeline "$width" "$height" "$output_file" "$framerate") run_camera_test "$testname" "$pipeline" "$output_file" } @@ -1078,74 +1092,74 @@ run_libcam_snapshot_test() { height="$2" resolution_name="$3" max_files="${4:-5}" - + if ! has_element videoconvert; then log_fail "videoconvert not available - required for snapshot test" fail_count=$((fail_count + 1)); return 1 fi - + if ! has_element jpegenc; then log_fail "jpegenc not available - required for snapshot test" fail_count=$((fail_count + 1)); return 1 fi - + if ! has_element multifilesink; then log_fail "multifilesink not available - required for snapshot test" fail_count=$((fail_count + 1)); return 1 fi - + testname="libcam_${resolution_name}_Snapshot" output_pattern="$ENCODED_DIR/snapshot_${resolution_name}_%d.jpg" - + log_info "Resolution: $resolution_name (${width}x${height})" log_info "Max snapshots: $max_files" - + # Clean up old snapshot files from previous runs to avoid false positives if ls "$ENCODED_DIR"/snapshot_"${resolution_name}"_*.jpg >/dev/null 2>&1; then log_info "Cleaning up old snapshot files..." rm -f "$ENCODED_DIR"/snapshot_"${resolution_name}"_*.jpg fi - + pipeline=$(camera_build_libcamera_snapshot_pipeline "$width" "$height" "$output_pattern" "$max_files") - + # For snapshot tests, we check if at least one snapshot file was created # Run the test with a shorter timeout since we're only capturing a few frames snapshot_timeout=$((max_files + 5)) - + log_info "=========================================="; log_info "Running: $testname"; log_info "==========================================" - + test_log="$OUTDIR/${testname}.log" : >"$test_log" - + if [ -z "$pipeline" ]; then log_warn "$testname: Failed to build pipeline"; skip_count=$((skip_count + 1)); return 1 fi - + log_info "Pipeline: gst-launch-1.0 -e $pipeline" - + # Run pipeline with timeout gstreamer_run_gstlaunch_timeout "$snapshot_timeout" "$pipeline" >>"$test_log" 2>&1 - + # Wait for filesystem to sync sleep 5 - + # Validate log if ! gstreamer_validate_log "$test_log" "$testname"; then diagnose_camera_failure "$testname" "$test_log" log_fail "$testname: FAIL"; fail_count=$((fail_count + 1)); return 1 fi - + # Check if at least one snapshot file was created (any number, not just 0) # multifilesink may continue numbering from previous runs snapshot_files=$(find "$ENCODED_DIR" -name "snapshot_${resolution_name}_*.jpg" -type f 2>/dev/null) snapshot_count=$(printf '%s\n' "$snapshot_files" | grep -c .) - + if [ "$snapshot_count" -gt 0 ]; then # Get the first file found (any number) first_snapshot=$(printf '%s\n' "$snapshot_files" | head -n 1) file_size=$(gstreamer_file_size_bytes "$first_snapshot") log_info "Found snapshot file: $(basename "$first_snapshot")" - + # Check if file size is reasonable for a JPEG if [ "$file_size" -gt "$SNAPSHOT_MIN_BYTES" ]; then log_info "Snapshots created: $snapshot_count (file size: $file_size bytes)" @@ -1161,19 +1175,19 @@ run_libcam_snapshot_test() { # -------------------- Main test execution -------------------- if [ "$camera_source" = "libcamerasrc" ]; then log_info "Starting libcamerasrc tests: fakesink -> preview -> encode -> snapshot" - + # Parse test modes and resolutions for libcamerasrc test_modes=$(printf '%s' "$testModeList" | tr ',' ' ') resolutions=$(printf '%s' "$resolutionList" | tr ',' ' ') - + # Wayland/Weston environment setup for libcamerasrc preview tests log_info "==========================================" log_info "LIBCAMERA - WAYLAND SETUP" log_info "==========================================" - + wayland_ready=0 camera_setup_wayland_environment "Libcamera_Tests" - + # Run tests based on test modes filter for mode in $test_modes; do case "$mode" in @@ -1181,7 +1195,7 @@ if [ "$camera_source" = "libcamerasrc" ]; then log_info "==========================================" log_info "LIBCAMERA FAKESINK TESTS" log_info "==========================================" - + # Run fakesink tests based on resolution filter (only 720p and 1080p supported) for res in $resolutions; do case "$res" in @@ -1200,14 +1214,14 @@ if [ "$camera_source" = "libcamerasrc" ]; then esac done ;; - + preview) # Preview tests - require Wayland if [ "$wayland_ready" -eq 1 ]; then log_info "==========================================" log_info "LIBCAMERA PREVIEW TESTS" log_info "==========================================" - + # Run preview tests based on resolution filter (only 720p and 1080p supported) for res in $resolutions; do case "$res" in @@ -1239,12 +1253,12 @@ if [ "$camera_source" = "libcamerasrc" ]; then done fi ;; - + encode) log_info "==========================================" log_info "LIBCAMERA ENCODE TESTS" log_info "==========================================" - + # Run encode tests based on resolution filter for res in $resolutions; do case "$res" in @@ -1266,12 +1280,12 @@ if [ "$camera_source" = "libcamerasrc" ]; then esac done ;; - + snapshot) log_info "==========================================" log_info "LIBCAMERA SNAPSHOT TESTS" log_info "==========================================" - + # Run snapshot tests for 1080p and 4K only for res in $resolutions; do case "$res" in @@ -1290,21 +1304,21 @@ if [ "$camera_source" = "libcamerasrc" ]; then esac done ;; - + *) log_warn "Unknown test mode for libcamerasrc: $mode" ;; esac done - + else # qtiqmmfsrc tests log_info "Starting camera tests in sequence: fakesink -> preview -> encode -> snapshot" - + test_modes=$(printf '%s' "$testModeList" | tr ',' ' ') formats=$(printf '%s' "$formatList" | tr ',' ' ') resolutions=$(printf '%s' "$resolutionList" | tr ',' ' ') - + for mode in $test_modes; do case "$mode" in fakesink) @@ -1320,11 +1334,11 @@ else log_info "==========================================" log_info "PREVIEW TESTS - WAYLAND SETUP" log_info "==========================================" - + # Wayland/Weston environment setup for preview tests wayland_ready=0 camera_setup_wayland_environment "Camera_Preview" - + # Run preview tests if Wayland is ready if [ "$wayland_ready" -eq 1 ]; then log_info "==========================================" @@ -1365,7 +1379,7 @@ else log_info "==========================================" log_info "QTIQMMFSRC SNAPSHOT TESTS" log_info "==========================================" - + # Run snapshot tests for 1080p and 4K only for res in $resolutions; do case "$res" in diff --git a/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/run.sh b/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/run.sh index 435b2091..e2f6afc9 100755 --- a/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/run.sh @@ -27,7 +27,7 @@ SCRIPT_DIR="$( cd "$(dirname "$0")" || exit 1 pwd )" - + INIT_ENV="" SEARCH="$SCRIPT_DIR" while [ "$SEARCH" != "/" ]; do @@ -37,13 +37,13 @@ while [ "$SEARCH" != "/" ]; do fi SEARCH=$(dirname "$SEARCH") done - + if [ -z "${INIT_ENV:-}" ]; then echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 echo "$TESTNAME SKIP" >"$RES_FILE" 2>/dev/null || true exit 0 fi - + if [ -z "${__INIT_ENV_LOADED:-}" ]; then # shellcheck disable=SC1090 . "$INIT_ENV" @@ -118,10 +118,10 @@ while [ $# -gt 0 ]; do echo "$TESTNAME SKIP" >"$RES_FILE" exit 0 fi - + width="${2%%x*}" height="${2#*x}" - + # Validate both width and height are numeric if ! echo "$width" | grep -q "^[0-9]\+$" || ! echo "$height" | grep -q "^[0-9]\+$"; then log_warn "Width and height must be numeric values (got width='$width', height='$height')" diff --git a/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh b/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh index a0e556ee..4f3485bf 100755 --- a/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh @@ -19,7 +19,7 @@ LOG_DIR="${SCRIPT_DIR}/logs" OUTDIR="$LOG_DIR/$TESTNAME" GST_LOG="$OUTDIR/gst.log" DMESG_DIR="$OUTDIR/dmesg" - + INIT_ENV="" SEARCH="$SCRIPT_DIR" while [ "$SEARCH" != "/" ]; do @@ -29,13 +29,13 @@ while [ "$SEARCH" != "/" ]; do fi SEARCH=$(dirname "$SEARCH") done - + if [ -z "${INIT_ENV:-}" ]; then echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 echo "$RESULT_TESTNAME SKIP" >"$RES_FILE" 2>/dev/null || true exit 0 fi - + if [ -z "${__INIT_ENV_LOADED:-}" ]; then # shellcheck disable=SC1090 . "$INIT_ENV" @@ -102,7 +102,7 @@ for param in VIDEO_DURATION RUNTIMESEC VIDEO_FRAMERATE VIDEO_GST_DEBUG GST_DEBUG if [ -n "$val" ]; then case "$val" in - ''|*[!0-9]*) + ''|*[!0-9]*) log_warn "$param must be numeric (got '$val')" echo "$RESULT_TESTNAME SKIP" >"$RES_FILE" exit 0 @@ -193,7 +193,7 @@ while [ $# -gt 0 ]; do fi if [ -n "$2" ]; then case "$2" in - ''|*[!0-9]*) + ''|*[!0-9]*) log_warn "Invalid --framerate '$2' (must be numeric)" echo "$RESULT_TESTNAME SKIP" >"$RES_FILE" exit 0 @@ -369,7 +369,7 @@ case "$gstDebugLevel" in 1|2|3|4|5|6|7|8|9) : ;; *) esac case "$duration" in - ''|*[!0-9]*) + ''|*[!0-9]*) log_warn "Invalid duration '$duration' (must be numeric)" echo "$RESULT_TESTNAME SKIP" >"$RES_FILE" exit 0 @@ -384,7 +384,7 @@ case "$duration" in esac case "$framerate" in - ''|*[!0-9]*) + ''|*[!0-9]*) log_warn "Invalid framerate '$framerate' (must be numeric)" echo "$RESULT_TESTNAME SKIP" >"$RES_FILE" exit 0 @@ -447,12 +447,12 @@ run_encode_test() { resolution="$2" width="$3" height="$4" - + testname="encode_${codec}_${resolution}" log_info "==========================================" log_info "Running: $testname" log_info "==========================================" - + # Check if encoder is available encoder=$(gstreamer_v4l2_encoder_for_codec "$codec") if [ -z "$encoder" ]; then @@ -460,48 +460,48 @@ run_encode_test() { skip_count=$((skip_count + 1)) return 1 fi - + ext=$(gstreamer_container_ext_for_codec "$codec") output_file="$ENCODED_DIR/${testname}.${ext}" test_log="$OUTDIR/${testname}.log" - + : >"$test_log" - + # Calculate bitrate based on resolution bitrate=$(gstreamer_bitrate_for_resolution "$width" "$height") - + # Build pipeline using library function pipeline=$(gstreamer_build_v4l2_encode_pipeline "$codec" "$width" "$height" "$duration" "$framerate" "$bitrate" "$output_file" "$detected_stack") - + if [ -z "$pipeline" ]; then log_fail "$testname: FAIL (could not build pipeline)" fail_count=$((fail_count + 1)) return 1 fi - + log_info "Pipeline: $pipeline" - + # Run encoding if gstreamer_run_gstlaunch_timeout "$((duration + 10))" "$pipeline" >>"$test_log" 2>&1; then gstRc=0 else gstRc=$? fi - + log_info "Encode exit code: $gstRc" - + # Check for GStreamer errors in log if ! gstreamer_validate_log "$test_log" "$testname"; then log_fail "$testname: FAIL (GStreamer errors detected)" fail_count=$((fail_count + 1)) return 1 fi - + # Check if output file was created and has content if [ -f "$output_file" ] && [ -s "$output_file" ]; then file_size=$(gstreamer_file_size_bytes "$output_file") log_info "Encoded file: $output_file (size: $file_size bytes)" - + if [ "$file_size" -gt 1000 ]; then log_pass "$testname: PASS" pass_count=$((pass_count + 1)) @@ -522,12 +522,12 @@ run_encode_test() { run_decode_test() { codec="$1" resolution="$2" - + testname="decode_${codec}_${resolution}" log_info "==========================================" log_info "Running: $testname" log_info "==========================================" - + # Check if decoder is available decoder=$(gstreamer_v4l2_decoder_for_codec "$codec") if [ -z "$decoder" ]; then @@ -535,9 +535,9 @@ run_decode_test() { skip_count=$((skip_count + 1)) return 1 fi - + ext=$(gstreamer_container_ext_for_codec "$codec") - + # For VP9, use WebM clip directly; for others, use encoded file if [ "$codec" = "vp9" ]; then input_file="$OUTDIR/VP9_640x480_10s.webm" @@ -554,37 +554,37 @@ run_decode_test() { return 1 fi fi - + test_log="$OUTDIR/${testname}.log" : >"$test_log" - + # Build pipeline using library function pipeline=$(gstreamer_build_v4l2_decode_pipeline "$codec" "$input_file" "$detected_stack") - + if [ -z "$pipeline" ]; then log_fail "$testname: FAIL (could not build pipeline)" fail_count=$((fail_count + 1)) return 1 fi - + log_info "Pipeline: $pipeline" - + # Run decoding if gstreamer_run_gstlaunch_timeout "$((duration + 10))" "$pipeline" >>"$test_log" 2>&1; then gstRc=0 else gstRc=$? fi - + log_info "Decode exit code: $gstRc" - + # Check for GStreamer errors in log if ! gstreamer_validate_log "$test_log" "$testname"; then log_fail "$testname: FAIL (GStreamer errors detected)" fail_count=$((fail_count + 1)) return 1 fi - + # Check for successful completion if [ "$gstRc" -eq 0 ]; then log_pass "$testname: PASS" @@ -619,9 +619,9 @@ if [ "$need_vp9_clip" -eq 1 ] && [ "$testMode" != "encode" ]; then log_info "==========================================" log_info "VP9 CLIP PREP" log_info "==========================================" - + vp9_clip_webm="$OUTDIR/VP9_640x480_10s.webm" - + # Check if WebM file already exists if [ -f "$vp9_clip_webm" ]; then log_info "VP9 WebM clip already exists: $vp9_clip_webm" @@ -660,14 +660,14 @@ if [ "$testMode" = "all" ] || [ "$testMode" = "encode" ]; then log_info "==========================================" log_info "ENCODE TESTS" log_info "==========================================" - + for codec in $codecs; do # Skip VP9 for encode tests (no v4l2vp9enc support in this test) if [ "$codec" = "vp9" ]; then log_info "Skipping VP9 encode (not supported)" continue fi - + for res in $resolutions; do params=$(gstreamer_resolution_to_wh "$res") @@ -689,7 +689,7 @@ if [ "$testMode" = "all" ] || [ "$testMode" = "decode" ]; then log_info "==========================================" log_info "DECODE TESTS" log_info "==========================================" - + for codec in $codecs; do if [ "$codec" = "vp9" ]; then total_tests=$((total_tests + 1)) @@ -714,7 +714,7 @@ exclude_regex="dummy regulator|supply [^ ]+ not found|using dummy regulator" if command -v scan_dmesg_errors >/dev/null 2>&1; then scan_dmesg_errors "$DMESG_DIR" "$module_regex" "$exclude_regex" || true - + if [ -s "$DMESG_DIR/dmesg_errors.log" ]; then log_warn "dmesg scan found video-related warnings or errors in $DMESG_DIR/dmesg_errors.log" else diff --git a/Runner/suites/Performance/Geekbench/run.sh b/Runner/suites/Performance/Geekbench/run.sh index 095c4078..69484897 100755 --- a/Runner/suites/Performance/Geekbench/run.sh +++ b/Runner/suites/Performance/Geekbench/run.sh @@ -90,7 +90,7 @@ GEEKBENCH_ARGS="${GEEKBENCH_ARGS:-}" usage() { cat < overall SKIP (everything skipped) if [ "$FAIL" -gt 0 ]; then echo "$TESTNAME FAIL" >"$RES_FILE" - exit 1 + exit 1 fi if [ "$PASS" -gt 0 ]; then echo "$TESTNAME PASS" >"$RES_FILE" diff --git a/Runner/suites/Virtualization/KVM/KVM_Driver/run.sh b/Runner/suites/Virtualization/KVM/KVM_Driver/run.sh index d63850c0..a75ee04e 100755 --- a/Runner/suites/Virtualization/KVM/KVM_Driver/run.sh +++ b/Runner/suites/Virtualization/KVM/KVM_Driver/run.sh @@ -142,7 +142,7 @@ log_info "=== KVM Driver Dmesg Advisory Scan ===" if ! kvm_check_boot_dmesg_errors "$DMESG_DIR"; then log_warn "$TESTNAME WARN - KVM/EL2 dmesg issues detected; not failing due to possible CI dmesg flooding" fi - + log_pass "$TESTNAME PASS - KVM kernel config, /dev/kvm, and ioctl API are valid" echo "$TESTNAME PASS" >"$res_file" diff --git a/Runner/suites/Virtualization/KVM/KVM_EL2_DTB/run.sh b/Runner/suites/Virtualization/KVM/KVM_EL2_DTB/run.sh index 973485ff..b6068df6 100755 --- a/Runner/suites/Virtualization/KVM/KVM_EL2_DTB/run.sh +++ b/Runner/suites/Virtualization/KVM/KVM_EL2_DTB/run.sh @@ -124,7 +124,7 @@ log_info "=== EL2/KVM Dmesg Advisory Scan ===" if ! kvm_check_boot_dmesg_errors "$DMESG_DIR"; then log_warn "$TESTNAME WARN - KVM/EL2 dmesg issues detected; not failing due to possible CI dmesg flooding" fi - + log_pass "$TESTNAME PASS - dynamic EL2-DTB evidence is valid" echo "$TESTNAME PASS" >"$res_file" diff --git a/Runner/suites/Virtualization/KVM/KVM_Infra/run.sh b/Runner/suites/Virtualization/KVM/KVM_Infra/run.sh index 7a09ae20..f802273d 100755 --- a/Runner/suites/Virtualization/KVM/KVM_Infra/run.sh +++ b/Runner/suites/Virtualization/KVM/KVM_Infra/run.sh @@ -138,7 +138,7 @@ log_info "=== KVM/QEMU Dmesg Advisory Scan ===" if ! kvm_check_boot_dmesg_errors "$DMESG_DIR"; then log_warn "$TESTNAME WARN - KVM/EL2 dmesg issues detected; not failing due to possible CI dmesg flooding" fi - + log_pass "$TESTNAME PASS - QEMU/KVM host infrastructure is available" echo "$TESTNAME PASS" >"$res_file" diff --git a/Runner/utils/audio_common.sh b/Runner/utils/audio_common.sh index 50417481..813534d3 100755 --- a/Runner/utils/audio_common.sh +++ b/Runner/utils/audio_common.sh @@ -57,7 +57,7 @@ check_audio_daemon() { resolve_clip() { fmt="$1"; dur="$2" base="${AUDIO_CLIPS_BASE_DIR:-AudioClips}" - + case "$fmt:$dur" in wav:short|wav:medium|wav:long) # Try hardcoded clip first (backward compatibility) @@ -66,7 +66,7 @@ resolve_clip() { printf '%s\n' "$clip" return 0 fi - + # Fallback: discover first available clip first_clip="$(find "$base" -maxdepth 1 -name "*.wav" -type f 2>/dev/null | head -n1)" if [ -n "$first_clip" ] && [ -f "$first_clip" ]; then @@ -74,7 +74,7 @@ resolve_clip() { printf '%s\n' "$first_clip" return 0 fi - + # No clips available log_error "No audio clips found in $base" >&2 printf '%s\n' "" @@ -298,7 +298,7 @@ dump_mixers() { else echo "(wpctl not found)" fi - + echo "---- pactl list ----" if command -v pactl >/dev/null 2>&1; then audio_exec_with_timeout 3s pactl list 2>&1 || echo "(pactl list failed/timeout)" @@ -314,10 +314,10 @@ dump_mixers() { # Returns child's exit code. For the fallback-kill path, returns 143 on timeout. audio_timeout_run() { tmo="$1"; shift - + # 0/empty => run without a watchdog (do NOT background/kill) case "$tmo" in ""|0|"0s"|"0S") "$@"; return $? ;; esac - + # Use project-provided wrappers if available if command -v run_with_timeout >/dev/null 2>&1; then run_with_timeout "$tmo" "$@"; return $? @@ -328,14 +328,14 @@ audio_timeout_run() { if command -v timeout >/dev/null 2>&1; then timeout "$tmo" "$@"; return $? fi - + # Last-resort busybox-safe watchdog # Normalize "15s" -> 15 sec="$(printf '%s' "$tmo" | sed 's/[sS]$//')" [ -z "$sec" ] && sec="$tmo" # If parsing failed for some reason, just run directly case "$sec" in ''|*[!0-9]* ) "$@"; return $? ;; esac - + "$@" & pid=$! t=0 @@ -353,29 +353,29 @@ audio_timeout_run() { audio_restart_services_best_effort() { uid="$(id -u 2>/dev/null || echo 0)" rt="${XDG_RUNTIME_DIR:-/run/user/$uid}" - + # Ensure runtime dir exists (some LAVA/minimal images may not have it) if [ ! -d "$rt" ] && [ -n "$rt" ]; then mkdir -p "$rt" 2>/dev/null || true chmod 700 "$rt" 2>/dev/null || true fi [ -d "$rt" ] && export XDG_RUNTIME_DIR="$rt" - + # systemd user + system (best effort, bounded time) if command -v systemctl >/dev/null 2>&1; then # optional reloads (some images need this after overlay / unit changes) audio_exec_with_timeout 10s systemctl --user daemon-reload >/dev/null 2>&1 || true audio_exec_with_timeout 10s systemctl daemon-reload >/dev/null 2>&1 || true - + audio_exec_with_timeout 10s systemctl --user restart pipewire pipewire-pulse wireplumber pulseaudio >/dev/null 2>&1 || true audio_exec_with_timeout 10s systemctl restart pipewire pipewire-pulse wireplumber pulseaudio >/dev/null 2>&1 || true fi - + # If control-plane is OK already, stop here (accept PW or PA) if audio_pw_ctl_ok 2>/dev/null || audio_pa_ctl_ok 2>/dev/null; then return 0 fi - + # hard reset (works without systemd/user session) if command -v pkill >/dev/null 2>&1; then pkill -x wireplumber >/dev/null 2>&1 || true @@ -385,9 +385,9 @@ audio_restart_services_best_effort() { elif command -v killall >/dev/null 2>&1; then killall -q wireplumber pipewire-pulse pipewire pulseaudio 2>/dev/null || true fi - + sleep 1 - + # stale sockets/locks if [ -n "${XDG_RUNTIME_DIR:-}" ] && [ -d "$XDG_RUNTIME_DIR" ]; then rm -f "$XDG_RUNTIME_DIR/pipewire-0" \ @@ -397,26 +397,26 @@ audio_restart_services_best_effort() { "$XDG_RUNTIME_DIR/pulse/cookie" \ 2>/dev/null || true fi - + # respawn (best effort, ShellCheck-clean) if command -v pipewire >/dev/null 2>&1; then pipewire >/dev/null 2>&1 & fi - + if command -v wireplumber >/dev/null 2>&1; then wireplumber >/dev/null 2>&1 & elif command -v pipewire-media-session >/dev/null 2>&1; then pipewire-media-session >/dev/null 2>&1 & fi - + if command -v pipewire-pulse >/dev/null 2>&1; then pipewire-pulse >/dev/null 2>&1 & fi - + if command -v pulseaudio >/dev/null 2>&1; then pulseaudio --start >/dev/null 2>&1 || true fi - + return 0 } @@ -505,30 +505,30 @@ audio_restart_pipewire_service() { # and does not restart PipeWire, so distro regressions are not hidden by tests. setup_overlay_audio_environment() { PIPEWIRE_READY_TIMEOUT="${PIPEWIRE_READY_TIMEOUT:-120}" - + if ! command -v lsmod >/dev/null 2>&1; then log_fail "lsmod command not available, cannot detect overlay audio modules" return 1 fi - + audio_modules="$(lsmod 2>/dev/null)" || { log_fail "lsmod failed, cannot detect overlay audio modules" return 1 } - + if ! printf '%s\n' "$audio_modules" | awk '$1 ~ /^audioreach/ { found=1; exit } END { exit !found }'; then log_info "Base build detected, no audioreach modules, skipping overlay setup" return 0 fi - + log_info "Overlay build detected, validating distro-provided audio prerequisites" - + if [ ! -e /dev/dma_heap/system ]; then log_fail "/dev/dma_heap/system is missing" log_fail "Distro should provide dma_heap system node for overlay audio" return 1 fi - + if command -v stat >/dev/null 2>&1; then dma_heap_mode="$(stat -c '%a' /dev/dma_heap/system 2>/dev/null || echo unknown)" dma_heap_owner="$(stat -c '%U:%G' /dev/dma_heap/system 2>/dev/null || echo unknown)" @@ -536,7 +536,7 @@ setup_overlay_audio_environment() { else log_info "stat command not available, skipping /dev/dma_heap/system mode and owner dump" fi - + if [ -r /dev/dma_heap/system ] && [ -w /dev/dma_heap/system ]; then log_pass "/dev/dma_heap/system is accessible" else @@ -544,7 +544,7 @@ setup_overlay_audio_environment() { log_fail "Distro should provide correct dma_heap permissions, test will not chmod it" return 1 fi - + log_info "Waiting for PipeWire readiness, timeout ${PIPEWIRE_READY_TIMEOUT}s" if audio_wait_audio_ready "$PIPEWIRE_READY_TIMEOUT" pipewire; then log_pass "PipeWire is ready" @@ -553,7 +553,7 @@ setup_overlay_audio_environment() { log_fail "Distro should start PipeWire correctly, test will not restart it during overlay setup" return 1 fi - + log_pass "Overlay audio prerequisites are ready" return 0 } @@ -570,7 +570,7 @@ pwctl_inspect_safe() { # ---------- PipeWire: sinks (playback) ---------- pw_default_speakers() { st="$(pwctl_status_safe 2>/dev/null)" || { printf '%s\n' ""; return 0; } - + _block="$(printf '%s\n' "$st" | sed -n '/Sinks:/,/Sources:/p')" _id="$(printf '%s\n' "$_block" \ | grep -i -E 'speaker|headphone' \ @@ -629,7 +629,7 @@ pw_set_default_sink() { # ---------- PipeWire: sources (record) ---------- pw_default_mic() { st="$(pwctl_status_safe 2>/dev/null)" || { printf '%s\n' ""; return 0; } - + blk="$(printf '%s\n' "$st" | sed -n '/Sources:/,/^$/p')" id="$(printf '%s\n' "$blk" | grep -i 'mic' | sed -n 's/^[^0-9]*\([0-9][0-9]*\)\..*/\1/p' | head -n1)" [ -n "$id" ] || id="$(printf '%s\n' "$blk" | sed -n 's/^[^0-9]*\([0-9][0-9]*\)\..*/\1/p' | head -n1)" @@ -638,7 +638,7 @@ pw_default_mic() { pw_default_null_source() { st="$(pwctl_status_safe 2>/dev/null)" || { printf '%s\n' ""; return 0; } - + blk="$(printf '%s\n' "$st" | sed -n '/Sources:/,/^$/p')" id="$(printf '%s\n' "$blk" | grep -i 'null\|dummy' | sed -n 's/^[^0-9]*\([0-9][0-9]*\)\..*/\1/p' | head -n1)" printf '%s\n' "$id" @@ -754,7 +754,7 @@ audio_evidence_pw_streaming() { fi echo 0 } - + # 2) PulseAudio streaming - safe when PA is absent (returns 0 without forcing FAIL) #Return 1 if PulseAudio is actively streaming (sink-inputs, source-outputs, or RUNNING sink), # else 0. Works even when the PA daemon is a different user by trying sockets + cookies. @@ -767,7 +767,7 @@ audio_evidence_pa_streaming() { fi echo 0; return } - + # build candidate socket + cookie pairs cand="" # per-user runtime dir sockets @@ -790,7 +790,7 @@ audio_evidence_pa_streaming() { done # also try current env (no explicit socket) cand="$cand|::env::|" - + # try pactl first with cookie if available if command -v pactl >/dev/null 2>&1; then IFS='|' read -r _ sock cookie rest </dev/null 2>&1; then IFS='|' read -r _ sock cookie rest </dev/null; then echo 1; return fi - + # Many QCS boards expose lots of Playback/Capture endpoints; if any of them say "On", mark active dapm_pc_files="$(grep -RIl --binary-files=text -E '/dapm/.*(Playback|Capture)$' "$base"/*/dapm 2>/dev/null)" if [ -n "$dapm_pc_files" ]; then echo "$dapm_pc_files" | xargs -r grep -I -q -E ':\s*On(\s|$)' 2>/dev/null && { echo 1; return; } fi - + # Some kernels only flip bias level when any path is active if grep -RIlq --binary-files=text '/dapm/bias_level$' "$base"/*/dapm 2>/dev/null; then grep -RIl --binary-files=text '/dapm/bias_level$' "$base"/*/dapm 2>/dev/null \ | xargs -r grep -I -q -E 'On|Standby' 2>/dev/null && { echo 1; return; } fi - + # Fallback heuristic: if ALSA says a PCM substream is RUNNING, assume DAPM is up if audio_evidence_alsa_running_any 2>/dev/null | grep -qx 1; then echo 1; return fi - + echo 0 } # 5) PW log evidence (optional, from AUDIO_LOGCTX) @@ -991,7 +991,7 @@ audio_parse_secs() { # --- Local watchdog that always honors the first argument (e.g. "15" or "15s") --- audio_exec_with_timeout() { dur="$1"; shift - + # normalize: allow "15" or "15s" case "$dur" in ""|"0") dur_norm=0 ;; @@ -999,20 +999,20 @@ audio_exec_with_timeout() { *) dur_norm="$dur" ;; esac case "$dur_norm" in *[!0-9]*|"") dur_norm=0 ;; esac - + # no watchdog if [ "$dur_norm" -le 0 ] 2>/dev/null; then "$@" return $? fi - + # Run in background and enforce our own bounded timeout (don't rely on external timeout) "$@" & pid=$! - + start="$(date +%s 2>/dev/null || echo 0)" deadline=$((start + dur_norm)) - + # Wait until exit or deadline while kill -0 "$pid" 2>/dev/null; do now="$(date +%s 2>/dev/null || echo 0)" @@ -1021,31 +1021,31 @@ audio_exec_with_timeout() { fi sleep 1 done - + # Timed out: try terminate/kill, but never block forever if kill -0 "$pid" 2>/dev/null; then kill -TERM "$pid" 2>/dev/null || true sleep 1 kill -KILL "$pid" 2>/dev/null || true - + # bounded grace wait (handles normal killable cases) grace=0 while kill -0 "$pid" 2>/dev/null && [ "$grace" -lt 3 ]; do sleep 1 grace=$((grace + 1)) done - + # Still alive -> likely D-state. Do NOT wait forever. if kill -0 "$pid" 2>/dev/null; then return 124 fi - + wait "$pid" 2>/dev/null rc=$? [ "$rc" -eq 143 ] 2>/dev/null && rc=124 return "$rc" fi - + # Exited naturally before timeout wait "$pid" 2>/dev/null return $? @@ -1116,7 +1116,7 @@ pwctl_status_safe() { [ "$rc" -eq 0 ] || return 1 printf '%s\n' "$out" } - + audio_pw_ctl_ok() { pwctl_status_safe >/dev/null 2>&1 } @@ -1153,15 +1153,15 @@ file_size_bytes() { # Returns: 0=success, 1=unable to parse duration extract_clip_duration() { filename="$1" - + # Extract duration field from pattern: _RATE_DURATIONs_BITS_CHANNELS.wav # Use sed to match the exact 4-field structure duration_str="$(printf '%s' "$filename" | sed -n 's/.*_[0-9.][0-9.]*KHz_\([0-9][0-9]*\)s_[0-9][0-9]*b_[0-9][0-9]*ch\.wav$/\1/p')" - + if [ -z "$duration_str" ]; then return 1 fi - + printf '%s\n' "$duration_str" return 0 } @@ -1263,7 +1263,7 @@ audio_check_clips_available() { # Returns descriptive test case name for given config map_config_to_testcase() { config="$1" - + # Extract config number if using playback_config format config_num="" case "$config" in @@ -1290,7 +1290,7 @@ map_config_to_testcase() { config_num="$config" ;; esac - + # Map config number to test case name case "$config_num" in 1) printf 'play_8KHz_8b_1ch\n' ;; @@ -1314,22 +1314,22 @@ map_config_to_testcase() { # Exit codes: 0=success, 1=directory not found or no clips discover_audio_clips() { clips_dir="${AUDIO_CLIPS_BASE_DIR:-AudioClips}" - + # Check directory exists if [ ! -d "$clips_dir" ]; then log_error "Clips directory not found: $clips_dir" >&2 return 1 fi - + # Find .wav files (only in top level, not recursive) clips="$(find "$clips_dir" -maxdepth 1 -name "*.wav" -type f 2>/dev/null | sort)" - + # Check if any clips found if [ -z "$clips" ]; then log_error "No .wav files found in $clips_dir" >&2 return 1 fi - + # Output basenames only to stdout for clip in $clips; do basename "$clip" @@ -1343,29 +1343,29 @@ discover_audio_clips() { # Returns: 0=success, 1=parse failure parse_clip_metadata() { filename="$1" - + # Extract rate, bits, and channels in one sed call # Pattern matches exact 4-field structure from end: _RATE_DURATIONs_BITS_CHANNELS.wav # Anchored to .wav extension to ensure we're matching the correct fields metadata="$(printf '%s' "$filename" | sed -n 's/.*_\([0-9.][0-9.]*KHz\)_\([0-9][0-9]*s\)_\([0-9][0-9]*b\)_\([0-9][0-9]*ch\)\.wav$/\1 \3 \4/p')" - + # Validate extraction succeeded if [ -z "$metadata" ]; then log_warn "Cannot parse metadata from: $filename (skipping)" return 1 fi - + # Split extracted fields (rate bits channels) # shellcheck disable=SC2086 # Intentional field splitting of generated key=value triplet. set -- $metadata rate="$1"; bits="$2"; channels="$3" - + # Validate all components present if [ -z "$rate" ] || [ -z "$bits" ] || [ -z "$channels" ]; then log_warn "Cannot parse metadata from: $filename (skipping)" return 1 fi - + printf 'rate=%s bits=%s channels=%s\n' "$rate" "$bits" "$channels" return 0 } @@ -1376,17 +1376,17 @@ parse_clip_metadata() { # Returns: 0=success, 1=parse failure generate_clip_testcase_name() { filename="$1" - + # Parse metadata (returns "rate=48KHz bits=16b channels=2ch") metadata="$(parse_clip_metadata "$filename")" || return 1 - + # Extract values using positional parameters and prefix stripping # shellcheck disable=SC2086 # Intentional field splitting of generated key=value triplet. set -- $metadata rate="${1#rate=}" bits="${2#bits=}" channels="${3#channels=}" - + # Generate test case name printf 'play_%s_%s_%s\n' "$rate" "$bits" "$channels" return 0 @@ -1399,7 +1399,7 @@ generate_clip_testcase_name() { resolve_clip_by_name() { name="$1" clips_dir="${AUDIO_CLIPS_BASE_DIR:-AudioClips}" - + # If name already looks like a filename, try direct path if printf '%s' "$name" | grep -F -q -- '.wav'; then clip_path="$clips_dir/$name" @@ -1408,22 +1408,22 @@ resolve_clip_by_name() { return 0 fi fi - + # Strip "play_" prefix if present search_name="$(printf '%s' "$name" | sed 's/^play_//')" - + # Search for matching clip using literal string matching for clip_file in "$clips_dir"/*.wav; do [ -f "$clip_file" ] || continue clip_basename="$(basename "$clip_file")" - + # Check if clip contains the search pattern (literal string match) if printf '%s' "$clip_basename" | grep -F -q -- "$search_name"; then printf '%s\n' "$clip_file" return 0 fi done - + return 1 } @@ -1435,7 +1435,7 @@ resolve_clip_by_name() { validate_clip_name() { requested_name="$1" available_clips="$2" - + # Check if requested_name is a generic config name (playback_config1, Config1, etc.) # Support both formats for backward compatibility config_num="" @@ -1447,20 +1447,20 @@ validate_clip_name() { config_num="$(printf '%s' "$requested_name" | sed -n 's/^[Cc]onfig\([0-9][0-9]*\)$/\1/p')" ;; esac - + if [ -n "$config_num" ]; then # Generic config name - map to clip by index (1-based) # Count total clips first using POSIX-compliant approach # shellcheck disable=SC2086 # Intentional field splitting of generated key=value triplet. set -- $available_clips idx=$# - + # Validate config number is positive and within range if [ "$config_num" -le 0 ] 2>/dev/null || [ "$config_num" -gt "$idx" ] 2>/dev/null; then log_error "Invalid config number: $requested_name. Available range: Config1 to Config$idx. Please check again." >&2 return 1 fi - + # Get clip by index (1-based) using POSIX-compliant approach current_idx=0 for clip in $available_clips; do @@ -1470,12 +1470,12 @@ validate_clip_name() { return 0 fi done - + # This shouldn't happen, but just in case log_error "Invalid config number: $requested_name. Available range: Config1 to Config$idx. Please check again." >&2 return 1 fi - + # Try exact match for specific clip names (play_48KHz_16b_2ch format) for clip in $available_clips; do test_name="$(generate_clip_testcase_name "$clip" 2>/dev/null)" || continue @@ -1484,12 +1484,12 @@ validate_clip_name() { return 0 fi done - + # No match found - count available clips for helpful message using POSIX-compliant approach # shellcheck disable=SC2086 # Intentional field splitting of space-separated clip list. set -- $available_clips idx=$# - + # No match found - provide helpful error message with range log_error "Wrong clip name: '$requested_name'. Available range: playback_config1 to playback_config$idx. Please check again." >&2 return 1 @@ -1501,13 +1501,13 @@ validate_clip_name() { apply_clip_filter() { filter="$1" available_clips="$2" - + # If no filter, return all clips if [ -z "$filter" ]; then printf '%s\n' "$available_clips" return 0 fi - + # Apply filter filtered="" for clip in $available_clips; do @@ -1520,10 +1520,10 @@ apply_clip_filter() { fi done done - + # Remove leading space filtered="$(printf '%s' "$filtered" | sed 's/^ //')" - + # Check if filter matched anything if [ -z "$filtered" ]; then log_error "Filter '$filter' matched no clips" >&2 @@ -1533,7 +1533,7 @@ apply_clip_filter() { done return 1 fi - + printf '%s\n' "$filtered" return 0 } @@ -1543,26 +1543,26 @@ apply_clip_filter() { # Returns: 0=valid, 1=invalid validate_clip_file() { clip_path="$1" - + # Check exists if [ ! -f "$clip_path" ]; then log_error "Clip file not found: $clip_path" return 1 fi - + # Check readable if [ ! -r "$clip_path" ]; then log_error "Clip file not readable: $clip_path" return 1 fi - + # Check not empty using portable file size helper size="$(file_size_bytes "$clip_path")" if [ -z "$size" ] || [ "$size" -le 0 ] 2>/dev/null; then log_error "Clip file is empty: $clip_path" return 1 fi - + return 0 } @@ -1574,18 +1574,18 @@ validate_clip_file() { discover_and_filter_clips() { clip_names="$1" clip_filter="$2" - + # Discover all available clips (logs go to stderr automatically) available_clips="$(discover_audio_clips)" || { log_error "Failed to discover audio clips" >&2 return 1 } - + # If explicit clip names provided, validate and use them if [ -n "$clip_names" ]; then validated="" failed_names="" - + for name in $clip_names; do # Validate clip name - let error messages display to stderr if clip="$(validate_clip_name "$name" "$available_clips")"; then @@ -1594,24 +1594,24 @@ discover_and_filter_clips() { failed_names="$failed_names $name" fi done - + validated="$(printf '%s' "$validated" | sed 's/^ //')" failed_names="$(printf '%s' "$failed_names" | sed 's/^ //')" - + if [ -z "$validated" ]; then # Don't repeat the error - validate_clip_name already showed it return 1 fi - + # Warn about any failed names (only if there are some valid ones) if [ -n "$failed_names" ]; then log_warn "Invalid clip/config names skipped: $failed_names" >&2 fi - + printf '%s\n' "$validated" return 0 fi - + # Apply filter if provided if [ -n "$clip_filter" ]; then filtered="$(apply_clip_filter "$clip_filter" "$available_clips" 2>/dev/null)" || { @@ -1621,7 +1621,7 @@ discover_and_filter_clips() { printf '%s\n' "$filtered" return 0 fi - + # No filter - return all clips printf '%s\n' "$available_clips" return 0 @@ -1643,7 +1643,7 @@ discover_record_configs() { # Returns: 0=success, 1=invalid config get_record_config_params() { config_name="$1" - + # Normalize config name to handle both formats (record_config1 and record_config01) normalized_name="$config_name" case "$config_name" in @@ -1657,7 +1657,7 @@ get_record_config_params() { # If config_num is empty, normalized_name stays as original config_name ;; esac - + case "$normalized_name" in record_config1|record_8KHz_1ch) printf '%s\n' "8000 1" ;; record_config2|record_16KHz_1ch) printf '%s\n' "16000 1" ;; @@ -1680,7 +1680,7 @@ get_record_config_params() { # Returns: 0=success, 1=invalid config generate_record_testcase_name() { config_name="$1" - + # Normalize config name to handle both formats (record_config1 and record_config01) normalized_name="$config_name" case "$config_name" in @@ -1690,7 +1690,7 @@ generate_record_testcase_name() { normalized_name="record_config$config_num" ;; esac - + case "$normalized_name" in record_config1) printf '%s\n' "record_8KHz_1ch" ;; record_config2) printf '%s\n' "record_16KHz_1ch" ;; @@ -1715,7 +1715,7 @@ generate_record_filename() { testcase_base="$1" rate="$2" channels="$3" - + # Convert rate to KHz format rate_khz="$rate" case "$rate" in @@ -1734,7 +1734,7 @@ generate_record_filename() { 384000) rate_khz="384KHz" ;; *) rate_khz="${rate}Hz" ;; # Fallback for unknown rates esac - + printf '%s_%s_%sch.wav\n' "$testcase_base" "$rate_khz" "$channels" return 0 } @@ -1744,13 +1744,13 @@ generate_record_filename() { # Returns: 0=valid, 1=invalid (with helpful error message) validate_record_config_name() { requested_name="$1" - + # Validate by checking if get_record_config_params() supports it # This eliminates redundant pattern matching that could be misleading if get_record_config_params "$requested_name" >/dev/null 2>&1; then return 0 fi - + log_error "Invalid record config name: $requested_name" >&2 log_error "Available configs: record_config1-record_config10, record_8KHz_1ch, record_16KHz_1ch, record_16KHz_2ch, record_24KHz_1ch, record_32KHz_2ch, record_44.1KHz_2ch, record_48KHz_2ch, record_48KHz_6ch, record_96KHz_2ch, record_96KHz_6ch" >&2 return 1 @@ -1763,19 +1763,19 @@ validate_record_config_name() { apply_record_config_filter() { filter="$1" available_configs="$2" - + # If no filter, return all configs if [ -z "$filter" ]; then printf '%s\n' "$available_configs" return 0 fi - + # Apply filter filtered="" for config in $available_configs; do # Generate descriptive name for matching desc_name="$(generate_record_testcase_name "$config" 2>/dev/null)" || continue - + for pattern in $filter; do # Match against config name or descriptive name if printf '%s %s' "$config" "$desc_name" | grep -F -q -- "$pattern"; then @@ -1784,17 +1784,17 @@ apply_record_config_filter() { fi done done - + # Remove leading space filtered="$(printf '%s' "$filtered" | sed 's/^ //')" - + # Check if filter matched anything if [ -z "$filtered" ]; then log_error "Filter '$filter' matched no record configs" >&2 log_info "Available configs: record_config1 to record_config10" >&2 return 1 fi - + printf '%s\n' "$filtered" return 0 } @@ -1807,15 +1807,15 @@ apply_record_config_filter() { discover_and_filter_record_configs() { config_names="$1" config_filter="$2" - + # Get all available configs available_configs="$(discover_record_configs)" - + # If explicit config names provided, validate and use them if [ -n "$config_names" ]; then validated="" failed_names="" - + for name in $config_names; do if validate_record_config_name "$name"; then validated="$validated $name" @@ -1823,30 +1823,30 @@ discover_and_filter_record_configs() { failed_names="$failed_names $name" fi done - + validated="$(printf '%s' "$validated" | sed 's/^ //')" failed_names="$(printf '%s' "$failed_names" | sed 's/^ //')" - + if [ -z "$validated" ]; then return 1 fi - + # Warn about any failed names (only if there are some valid ones) if [ -n "$failed_names" ]; then log_warn "Invalid record config names skipped: $failed_names" >&2 fi - + printf '%s\n' "$validated" return 0 fi - + # Apply filter if provided if [ -n "$config_filter" ]; then filtered="$(apply_record_config_filter "$config_filter" "$available_configs")" || return 1 printf '%s\n' "$filtered" return 0 fi - + # No filter - return all configs printf '%s\n' "$available_configs" return 0 diff --git a/Runner/utils/camera/lib_camera.sh b/Runner/utils/camera/lib_camera.sh index 0c286200..245f79d8 100755 --- a/Runner/utils/camera/lib_camera.sh +++ b/Runner/utils/camera/lib_camera.sh @@ -111,7 +111,7 @@ libcam_file_list_and_seq() { # Usage: libcam_sample_uniques "" "" libcam_sample_uniques() { f="$1"; n="$2" - + # Prefer BusyBox-compatible od -b if command -v od >/dev/null 2>&1; then dd if="$f" bs=1 count="$n" status=none 2>/dev/null \ @@ -129,7 +129,7 @@ libcam_sample_uniques() { ' return fi - + # Fallback: hexdump (some BusyBox builds lack -e) if command -v hexdump >/dev/null 2>&1; then dd if="$f" bs=1 count="$n" status=none 2>/dev/null \ @@ -149,7 +149,7 @@ libcam_sample_uniques() { ' return fi - + # Last-chance optimistic fallback echo 256 } @@ -176,7 +176,7 @@ libcam_files_and_seq() { dir="$1"; strict="$2" MAP="$dir/.file_seq_map.txt" : > "$MAP" - + for f in "$dir"/frame-*.bin "$dir"/frame-*.ppm; do [ -e "$f" ] || continue base="${f##*/}" @@ -184,7 +184,7 @@ libcam_files_and_seq() { seq="${seq##*-}" printf '%s %s\n' "$f" "$seq" >> "$MAP" done - + if [ "$strict" = "yes" ]; then awk '{print $2+0}' "$MAP" | sort -n | libcam_check_contiguous >/dev/null 2>&1 || { log_warn "non-contiguous sequences in files" @@ -261,13 +261,13 @@ EOF # Returns: 0 = OK, 1 = problems found libcam_validate_bin() { dir="$1"; run_log="$2"; bin_sample_bytes="$3"; BIN_TOL_PCT="$4"; DUP_MAX_RATIO="$5" - + BAD=0 - + # Extract bytesused lines from the run log (may be 0 lines; that's fine) BU_TXT="$dir/.bytesused.txt" sed -n 's/.*bytesused:[[:space:]]*\([0-9][0-9]*\).*/\1/p' "$run_log" > "$BU_TXT" 2>/dev/null || : - + # List BIN files & sizes (BusyBox-compatible: no -printf) SIZES_TXT="$dir/.bin_sizes.txt" : > "$SIZES_TXT" @@ -276,14 +276,14 @@ libcam_validate_bin() { sz="$(stat -c %s "$f" 2>/dev/null || stat -f %z "$f" 2>/dev/null || wc -c <"$f")" printf '%s %s\n' "$f" "$sz" >> "$SIZES_TXT" done - + # Size tolerance check vs. closest bytesused if [ -s "$BU_TXT" ] && [ -s "$SIZES_TXT" ]; then while IFS= read -r line; do f=$(printf '%s\n' "$line" | cut -d' ' -f1) sz=$(printf '%s\n' "$line" | cut -d' ' -f2) [ -n "$sz" ] || continue - + target=$( sort -n "$BU_TXT" 2>/dev/null \ | awk -v S="$sz" ' @@ -301,7 +301,7 @@ libcam_validate_bin() { fi done < "$SIZES_TXT" fi - + # Content entropy quick check: sample first N bytes, count unique byte values. # On BusyBox, avoid 'od -A'; use plain 'od' or 'hexdump' fallback. if [ -s "$SIZES_TXT" ]; then @@ -324,14 +324,14 @@ libcam_validate_bin() { fi done < "$SIZES_TXT" fi - + # Duplicate detection by hash (optional, best-effort) if [ -s "$SIZES_TXT" ]; then hash_cmd="" if command -v sha256sum >/dev/null 2>&1; then hash_cmd="sha256sum" elif command -v md5sum >/dev/null 2>&1; then hash_cmd="md5sum" fi - + if [ -n "$hash_cmd" ]; then DUPS_TXT="$dir/.hashes.txt" : > "$DUPS_TXT" @@ -341,11 +341,11 @@ libcam_validate_bin() { done < "$SORTED" 2>/dev/null || cp "$DUPS_TXT" "$SORTED" - + total=$(wc -l <"$SORTED" 2>/dev/null | tr -d ' ') maxdup=$(awk ' { cnt[$1]++ } @@ -353,7 +353,7 @@ EOF_HASHLIST m=0; for (k in cnt) if (cnt[k]>m) m=cnt[k]; print m+0 }' "$SORTED") - + if [ "${total:-0}" -gt 0 ] && [ "${maxdup:-0}" -gt 0 ]; then ratio=$(awk -v m="$maxdup" -v t="$total" 'BEGIN{ if(t==0) print "0"; else printf "%.3f", m/t }') if awk -v r="$ratio" -v lim="$DUP_MAX_RATIO" 'BEGIN{ exit !(r>lim) }'; then @@ -364,7 +364,7 @@ EOF_HASHLIST fi fi fi - + [ "$BAD" -eq 0 ] } @@ -386,9 +386,9 @@ libcam_validate_content() { libcam_scan_errors() { run_log="$1" strict="$2" - + [ "$strict" = "yes" ] || { log_info "[scan] ERR_STRICT=no; skipping fatal scan"; return 0; } - + # Build a filtered view that removes known-benign noise we see on imx577 / simple pipeline. # We keep this BusyBox/grep-basic-friendly (no PCRE features). tmpf="$(mktemp)" || return 1 @@ -400,7 +400,7 @@ libcam_scan_errors() { grep -viE \ 'CameraSensor|PixelArray|ActiveAreas|crop rectangle|Rotation control|No sensor delays|CameraSensorProperties|IPAProxy|configuration file.*yaml|SoftwareIsp|IPASoft|SimplePipeline' \ "$run_log" >"$tmpf" || true - + # Fatal patterns: keep simple & portable; focus on truly bad states. # (No generic "error" catch-all here.) if grep -Eiq \ @@ -410,7 +410,7 @@ libcam_scan_errors() { rm -f "$tmpf" return 1 fi - + log_info "[scan] No fatal errors after noise suppression" rm -f "$tmpf" return 0 @@ -426,11 +426,11 @@ libcam_scan_errors() { # Prefer /sys/devices/soc0/soc_id. Normalize to lowercase and trim. camx_read_soc_id() { soc="" - + if [ -r /sys/devices/soc0/soc_id ]; then soc="$(tr -d '\r\n[:space:]' /dev/null | tr '[:upper:]' '[:lower:]')" fi - + [ -n "$soc" ] || return 1 echo "$soc" return 0 @@ -445,7 +445,7 @@ camx_find_icp_firmware() { token_list="" token="" cand="" - + if [ -r /proc/device-tree/compatible ]; then token_list="$( tr '\0' '\n' /dev/null \ @@ -454,7 +454,7 @@ camx_find_icp_firmware() { | sort -u )" fi - + for token in $token_list; do if [ -d "/lib/firmware/qcom/$token" ]; then for cand in \ @@ -466,7 +466,7 @@ camx_find_icp_firmware() { return 0 fi done - + cand="$( find "/lib/firmware/qcom/$token" -maxdepth 1 -type f \ \( -name 'CAMERA_ICP*.mbn' -o -name 'CAMERA_ICP*.elf' \) \ @@ -478,7 +478,7 @@ camx_find_icp_firmware() { fi fi done - + cand="$( find /lib/firmware/qcom -type f \ \( -name 'CAMERA_ICP.mbn' -o -name 'CAMERA_ICP.elf' -o -name 'CAMERA_ICP*.mbn' -o -name 'CAMERA_ICP*.elf' \) \ @@ -488,7 +488,7 @@ camx_find_icp_firmware() { printf '%s\n' "$cand" return 0 fi - + cand="$( find /lib/firmware -type f \ \( -name 'CAMERA_ICP.mbn' -o -name 'CAMERA_ICP.elf' -o -name 'CAMERA_ICP*.mbn' -o -name 'CAMERA_ICP*.elf' \) \ @@ -498,7 +498,7 @@ camx_find_icp_firmware() { printf '%s\n' "$cand" return 0 fi - + return 1 } # ----------------------------------------------------------------------------- @@ -506,28 +506,28 @@ camx_find_icp_firmware() { # ----------------------------------------------------------------------------- camx_opkg_list_camx() { out="" - + if command -v opkg >/dev/null 2>&1; then out="$(opkg list-installed 2>/dev/null | grep -i '^camx' || true)" [ -n "$out" ] || return 1 printf '%s\n' "$out" return 0 fi - + if command -v dnf >/dev/null 2>&1; then out="$(dnf list installed 2>/dev/null | grep -i '^camx' || true)" [ -n "$out" ] || return 1 printf '%s\n' "$out" return 0 fi - + if command -v rpm >/dev/null 2>&1; then out="$(rpm -qa 2>/dev/null | grep -i '^camx' || true)" [ -n "$out" ] || return 1 printf '%s\n' "$out" return 0 fi - + return 1 } @@ -856,15 +856,15 @@ run_cmd_live_to_log() { camx_pick_camera_module() { compat_list="" model_str="" - + if [ -r /proc/device-tree/compatible ]; then compat_list="$(tr '\0' '\n' /dev/null | tr '[:upper:]' '[:lower:]')" fi - + if [ -r /proc/device-tree/model ]; then model_str="$(tr '[:upper:]' '[:lower:]' /dev/null)" fi - + case "$compat_list $model_str" in *rb3gen2*|*qcm6490*|*qcs6490*) @@ -880,7 +880,7 @@ $model_str" in return 0 ;; esac - + return 1 } diff --git a/Runner/utils/functestlib.sh b/Runner/utils/functestlib.sh index 05243a9e..6d952850 100755 --- a/Runner/utils/functestlib.sh +++ b/Runner/utils/functestlib.sh @@ -650,7 +650,7 @@ check_dt_nodes() { found=true fi done - + if [ "$found" = true ]; then return 0 else @@ -695,20 +695,20 @@ detect_runner_root() { # Function is to check for network connectivity status check_network_status() { echo "[INFO] Checking network connectivity..." - + # Prefer the egress/source IP chosen by the routing table (most accurate). ip_addr=$(ip -4 route get 1.1.1.1 2>/dev/null \ | awk 'NR==1{for(i=1;i<=NF;i++) if($i=="src"){print $(i+1); exit}}') - + # Fallback: first global IPv4 on any UP interface (works even without a default route). if [ -z "$ip_addr" ]; then ip_addr=$(ip -o -4 addr show scope global up 2>/dev/null \ | awk 'NR==1{split($4,a,"/"); print a[1]}') fi - + if [ -n "$ip_addr" ]; then echo "[PASS] Network is active. IP address: $ip_addr" - + # Quick reachability probe (single ICMP). BusyBox-compatible flags. if ping -c 1 -W 2 8.8.8.8 >/dev/null 2>&1; then echo "[PASS] Internet is reachable." @@ -728,14 +728,14 @@ ensure_reasonable_clock() { now="$(date +%s 2>/dev/null || echo 0)" cutoff="$(date -d '2020-01-01 UTC' +%s 2>/dev/null || echo 1577836800)" [ -z "$cutoff" ] && cutoff=1577836800 - + [ "$now" -ge "$cutoff" ] 2>/dev/null && return 0 - + log_warn "System clock looks invalid (epoch=$now). Trying local time sources (no network)..." - + # Optional diagnostics file (caller may set this, e.g. CLOCK_DIAG_FILE="$OUT_DIR/clock_diag.txt") diag_file="${CLOCK_DIAG_FILE:-}" - + # ---- Diagnostics (only when invalid clock) ---- if [ -n "$diag_file" ]; then { @@ -745,7 +745,7 @@ ensure_reasonable_clock() { echo } >>"$diag_file" 2>/dev/null || true fi - + # Log minimal summaries to stdout; write full outputs to diag file. # date summary date_out="$(date 2>&1 || true)" @@ -757,7 +757,7 @@ ensure_reasonable_clock() { } >>"$diag_file" 2>/dev/null || true fi log_info "date: $(printf '%s' "$date_out" | head -n 1)" - + # timedatectl summaries + full dump if command -v timedatectl >/dev/null 2>&1; then td_status="$(timedatectl status 2>&1 || true)" @@ -768,18 +768,18 @@ ensure_reasonable_clock() { echo } >>"$diag_file" 2>/dev/null || true fi - + # minimal, stable-ish summaries td_local="$(printf '%s\n' "$td_status" | sed -n 's/^[[:space:]]*Local time:[[:space:]]*//p' | head -n 1)" td_sync="$(printf '%s\n' "$td_status" | sed -n 's/^[[:space:]]*System clock synchronized:[[:space:]]*//p' | head -n 1)" td_ntp="$(printf '%s\n' "$td_status" | sed -n 's/^[[:space:]]*NTP service:[[:space:]]*//p' | head -n 1)" td_rtc="$(printf '%s\n' "$td_status" | sed -n 's/^[[:space:]]*RTC time:[[:space:]]*//p' | head -n 1)" - + [ -n "$td_local" ] && log_info "timedatectl: Local time: $td_local" [ -n "$td_rtc" ] && log_info "timedatectl: RTC time: $td_rtc" [ -n "$td_sync" ] && log_info "timedatectl: System clock synchronized: $td_sync" [ -n "$td_ntp" ] && log_info "timedatectl: NTP service: $td_ntp" - + td_show="$(timedatectl show-timesync --all 2>&1 || true)" if [ -n "$diag_file" ]; then { @@ -788,12 +788,12 @@ ensure_reasonable_clock() { echo } >>"$diag_file" 2>/dev/null || true fi - + td_server="$(printf '%s\n' "$td_show" | sed -n 's/^ServerName=//p' | head -n 1)" td_addr="$(printf '%s\n' "$td_show" | sed -n 's/^ServerAddress=//p' | head -n 1)" td_sysntp="$(printf '%s\n' "$td_show" | sed -n 's/^SystemNTPServers=//p' | head -n 1)" td_fallback="$(printf '%s\n' "$td_show" | sed -n 's/^FallbackNTPServers=//p' | head -n 1)" - + if [ -n "$td_server" ] || [ -n "$td_addr" ]; then log_info "timesync: server=${td_server:-NA} addr=${td_addr:-NA}" fi @@ -805,7 +805,7 @@ ensure_reasonable_clock() { short_fb="$(printf '%s' "$td_fallback" | awk '{print $1" "$2" "$3" "$4}')" log_info "timesync: FallbackNTPServers: ${short_fb:-NA}" fi - + td_ts="$(timedatectl timesync-status 2>&1 || true)" if [ -n "$diag_file" ]; then { @@ -814,7 +814,7 @@ ensure_reasonable_clock() { echo } >>"$diag_file" 2>/dev/null || true fi - + td_pkt="$(printf '%s\n' "$td_ts" | sed -n 's/^[[:space:]]*Packet count:[[:space:]]*//p' | head -n 1)" td_srvline="$(printf '%s\n' "$td_ts" | sed -n 's/^[[:space:]]*Server:[[:space:]]*//p' | head -n 1)" [ -n "$td_srvline" ] && log_info "timesync-status: Server: $td_srvline" @@ -825,7 +825,7 @@ ensure_reasonable_clock() { echo "timedatectl: not available" >>"$diag_file" 2>/dev/null || true fi fi - + # systemctl status summaries + full dump if command -v systemctl >/dev/null 2>&1; then sdts="$(systemctl status systemd-timesyncd --no-pager --full 2>&1 || true)" @@ -836,7 +836,7 @@ ensure_reasonable_clock() { echo } >>"$diag_file" 2>/dev/null || true fi - + sd_active="$(printf '%s\n' "$sdts" | sed -n 's/^[[:space:]]*Active:[[:space:]]*//p' | head -n 1)" sd_pid="$(printf '%s\n' "$sdts" | sed -n 's/^[[:space:]]*Main PID:[[:space:]]*//p' | head -n 1)" [ -n "$sd_active" ] && log_info "systemd-timesyncd: Active: $sd_active" @@ -847,7 +847,7 @@ ensure_reasonable_clock() { echo "systemctl: not available" >>"$diag_file" 2>/dev/null || true fi fi - + # 1) Try RTC (if it is sane) if command -v hwclock >/dev/null 2>&1 && [ -e /dev/rtc0 ]; then hwclock -s 2>/dev/null || true @@ -856,7 +856,7 @@ ensure_reasonable_clock() { log_pass "Clock restored from RTC." return 0 fi - + if [ -r /sys/class/rtc/rtc0/since_epoch ]; then rtc_epoch="$(tr -cd 0-9 < /sys/class/rtc/rtc0/since_epoch 2>/dev/null)" if [ -n "$rtc_epoch" ]; then @@ -882,7 +882,7 @@ ensure_reasonable_clock() { echo "RTC: hwclock or /dev/rtc0 not available" >>"$diag_file" 2>/dev/null || true fi fi - + # 2) Try kernel build timestamp from /proc/version or uname -v kb="$(uname -v 2>/dev/null || cat /proc/version 2>/dev/null || true)" if [ -n "$diag_file" ]; then @@ -892,11 +892,11 @@ ensure_reasonable_clock() { echo } >>"$diag_file" 2>/dev/null || true fi - + kb_date="$(printf '%s\n' "$kb" | sed -n \ 's/.*\([A-Z][a-z][a-z] [A-Z][a-z][a-z] [ 0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [A-Z][A-Za-z0-9+:-]* [0-9][0-9][0-9][0-9]\).*/\1/p' \ | head -n 1)" - + if [ -n "$kb_date" ]; then log_info "kernel-build-time: parsed='$kb_date'" kb_epoch="$(date -d "$kb_date" +%s 2>/dev/null || echo 0)" @@ -911,7 +911,7 @@ ensure_reasonable_clock() { else log_info "kernel-build-time: could not parse from uname -v / /proc/version" fi - + log_warn "Clock still invalid; continuing (timestamps may be epoch)." return 1 } @@ -921,7 +921,7 @@ extract_tar_from_url() { url="$1" outdir="${LOG_DIR:-.}" mkdir -p "$outdir" 2>/dev/null || true - + case "$url" in /*) tarfile="$url" @@ -935,13 +935,13 @@ extract_tar_from_url() { esac markfile="${tarfile}.extracted" skip_sentinel="${outdir}/.asset_fetch_skipped" - + # If a previous run already marked "assets unavailable", honor it and SKIP. if [ -f "$skip_sentinel" ]; then log_info "Previous run marked assets unavailable on this system (${skip_sentinel}); skipping download." return 2 fi - + tar_already_extracted() { tf="$1" od="$2" @@ -970,7 +970,7 @@ extract_tar_from_url() { fi return 1 } - + if command -v check_tar_file >/dev/null 2>&1; then check_tar_file "$url" status=$? @@ -985,12 +985,12 @@ extract_tar_from_url() { status=1 fi fi - + ensure_reasonable_clock || { log_warn "Proceeding in limited-network mode." limited_net=1 } - + is_busybox_wget() { if command -v wget >/dev/null 2>&1; then if wget --help 2>&1 | head -n 1 | grep -qi busybox; then @@ -999,7 +999,7 @@ extract_tar_from_url() { fi return 1 } - + tls_capable_fetcher_available() { scheme_https=0 case "$url" in @@ -1028,13 +1028,13 @@ extract_tar_from_url() { fi return 1 } - + try_download() { src="$1" dst="$2" part="${dst}.part.$$" ca="" - + for cand in \ /etc/ssl/certs/ca-certificates.crt \ /etc/ssl/cert.pem \ @@ -1045,7 +1045,7 @@ extract_tar_from_url() { break fi done - + if command -v curl >/dev/null 2>&1; then if [ -n "$ca" ]; then curl -4 -L --fail --retry 3 --retry-delay 2 --connect-timeout 10 \ @@ -1066,7 +1066,7 @@ extract_tar_from_url() { ;; esac fi - + if command -v aria2c >/dev/null 2>&1; then aria2c -x4 -s4 -m3 --connect-timeout=10 \ -o "$(basename "$part")" --dir="$(dirname "$part")" "$src" @@ -1077,7 +1077,7 @@ extract_tar_from_url() { fi rm -f "$part" 2>/dev/null || true fi - + if command -v wget >/dev/null 2>&1; then if is_busybox_wget; then wget -O "$part" -T 15 "$src" @@ -1117,15 +1117,15 @@ extract_tar_from_url() { return $rc fi fi - + return 127 } - + if [ "$status" -eq 0 ]; then log_info "Already extracted. Skipping download." return 0 fi - + if [ "$status" -eq 2 ]; then log_info "File exists and is valid, but not yet extracted. Proceeding to extract." else @@ -1143,7 +1143,7 @@ extract_tar_from_url() { if [ -n "${VIDEO_ASSET_DIR:-}" ]; then prestage_dirs="$prestage_dirs $VIDEO_ASSET_DIR"; fi if [ -n "${AUDIO_ASSET_DIR:-}" ]; then prestage_dirs="$prestage_dirs $AUDIO_ASSET_DIR"; fi prestage_dirs="$prestage_dirs . $outdir ${ROOT_DIR:-} ${ROOT_DIR:-}/cache /var/Runner /var/Runner/cache" - + for d in $prestage_dirs; do if [ -d "$d" ] && [ -f "$d/$(basename "$tarfile")" ]; then log_info "Using pre-staged tarball: $d/$(basename "$tarfile")" @@ -1151,7 +1151,7 @@ extract_tar_from_url() { break fi done - + if [ ! -s "$tarfile" ]; then for top in /mnt /media; do if [ -d "$top" ]; then @@ -1166,21 +1166,21 @@ extract_tar_from_url() { done fi fi - + if [ ! -s "$tarfile" ]; then if [ -n "$limited_net" ]; then log_warn "Limited network, cannot fetch media bundle. Marking SKIP for callers." : > "$skip_sentinel" 2>/dev/null || true return 2 fi - + if ! tls_capable_fetcher_available; then log_warn "No TLS-capable downloader available on this minimal build, cannot fetch: $url" log_warn "Pre-stage $(basename "$url") locally or use a file:// URL." : > "$skip_sentinel" 2>/dev/null || true return 2 fi - + log_info "Downloading $url -> $tarfile" if ! try_download "$url" "$tarfile"; then rc=$? @@ -1196,7 +1196,7 @@ extract_tar_from_url() { ;; esac fi - + log_info "Extracting $(basename "$tarfile")..." if tar -xvf "$tarfile"; then : > "$markfile" 2>/dev/null || true @@ -1204,7 +1204,7 @@ extract_tar_from_url() { if [ -f "$skip_sentinel" ]; then rm -f "$skip_sentinel" 2>/dev/null || true fi - + first_entry="$(tar -tf "$tarfile" 2>/dev/null | head -n 1 | sed 's#/$##')" if [ -n "$first_entry" ]; then if [ -e "$first_entry" ] || [ -e "$outdir/$first_entry" ]; then @@ -1215,7 +1215,7 @@ extract_tar_from_url() { log_warn "Extraction finished but couldn't verify entries. Assuming success." return 0 fi - + log_fail "Failed to extract $(basename "$tarfile")" return 1 } @@ -1226,14 +1226,14 @@ check_tar_file() { url="$1" outdir="${LOG_DIR:-.}" mkdir -p "$outdir" 2>/dev/null || true - + case "$url" in /*) tarfile="$url" ;; file://*) tarfile="${url#file://}" ;; *) tarfile="$outdir/$(basename "$url")" ;; esac markfile="${tarfile}.extracted" - + # 1) Existence & basic validity if [ ! -f "$tarfile" ]; then log_info "File $(basename "$tarfile") does not exist in $outdir." @@ -1247,13 +1247,13 @@ check_tar_file() { log_warn "File $(basename "$tarfile") is not a valid tar archive." return 1 fi - + # 2) Already extracted? (marker first) if [ -f "$markfile" ]; then log_pass "$(basename "$tarfile") has already been extracted (marker present)." return 0 fi - + # 3) Heuristic: check multiple entries from the tar exist on disk tmp_list="${outdir}/.tar_ls.$$" if tar -tf "$tarfile" 2>/dev/null | head -n 20 >"$tmp_list"; then @@ -1268,14 +1268,14 @@ check_tar_file() { fi done < "$tmp_list" rm -f "$tmp_list" 2>/dev/null || true - + # If we find a reasonable portion of entries, assume it's extracted if [ "$present" -ge 3 ] || { [ "$total" -gt 0 ] && [ $((present * 100 / total)) -ge 50 ]; }; then log_pass "$(basename "$tarfile") already extracted ($present/$total entries found)." return 0 fi fi - + # 4) Exists and valid, but not yet extracted log_info "$(basename "$tarfile") exists and is valid, but not yet extracted." return 2 @@ -1471,12 +1471,12 @@ overlay_start_weston_drm() { break fi done - + if [ -n "$EGL_JSON" ]; then export __EGL_VENDOR_LIBRARY_FILENAMES="$EGL_JSON" log_info "Overlay EGL: using vendor JSON: $EGL_JSON" fi - + RUNTIME_DIR="/dev/socket/weston" if ! mkdir -p "$RUNTIME_DIR"; then log_warn "Failed to create runtime dir $RUNTIME_DIR; falling back to /run/user/0" @@ -1484,23 +1484,23 @@ overlay_start_weston_drm() { mkdir -p "$RUNTIME_DIR" || true fi chmod 700 "$RUNTIME_DIR" 2>/dev/null || true - + XDG_RUNTIME_DIR="$RUNTIME_DIR" export XDG_RUNTIME_DIR - + # Do NOT force a specific WAYLAND_DISPLAY; let Weston decide. unset WAYLAND_DISPLAY - + log_dir=${1:-$PWD} WESTON_LOG="$log_dir/weston.log" log_info "Overlay Weston start: XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR (WAYLAND_DISPLAY=)" log_info "Weston log: $WESTON_LOG" - + # Start Weston in the background; we intentionally do not track the PID # here to avoid killing it while clients are still using the socket. weston --continue-without-input --idle-time=0 --log="$WESTON_LOG" \ >/dev/null 2>&1 & - + # Best-effort check: see if ANY wayland-* socket appears, but do not kill Weston. i=0 sock_found="" @@ -1514,13 +1514,13 @@ overlay_start_weston_drm() { sleep 1 i=$((i + 1)) done - + if [ -n "$sock_found" ]; then log_info "Overlay Weston created Wayland socket at $sock_found" # Caller can discover/adopt env via discover_wayland_socket_anywhere + adopt_wayland_env_from_socket. return 0 fi - + log_warn "Overlay Weston did not create a Wayland socket under $XDG_RUNTIME_DIR (see $WESTON_LOG)" return 1 } @@ -1691,18 +1691,18 @@ wayland_can_connect() { weston_pick_env_or_start() { ctx="${1:-weston_pick_env_or_start}" sock="" - + # Honor WESTON_LOG_DIR for any Weston logs that helpers might write log_dir="${WESTON_LOG_DIR:-/tmp}" log_info "$ctx: Weston logs (if any) will be under: $log_dir" - + # 0) If env already points to a valid socket, keep it. if [ -n "${XDG_RUNTIME_DIR:-}" ] && [ -n "${WAYLAND_DISPLAY:-}" ] \ && [ -S "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" ]; then log_info "$ctx: Using existing Wayland env: $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" return 0 fi - + # 1) Try to discover any existing Wayland socket first. if command -v discover_wayland_socket_anywhere >/dev/null 2>&1; then sock="$(discover_wayland_socket_anywhere 2>/dev/null | head -n 1)" @@ -1721,7 +1721,7 @@ weston_pick_env_or_start() { fi done fi - + if [ -n "$sock" ]; then if adopt_wayland_env_from_socket "$sock"; then log_info "$ctx: Selected existing Wayland socket: $sock" @@ -1730,7 +1730,7 @@ weston_pick_env_or_start() { log_warn "$ctx: Failed to adopt env from existing socket: $sock" return 1 fi - + # 2) No socket found → restart Weston and wait for a new one. if weston_is_running; then log_info "$ctx: Weston is running but no socket found; stopping..." @@ -1741,9 +1741,9 @@ weston_pick_env_or_start() { sleep 1 done fi - + uid="$(id -u 2>/dev/null || echo 0)" - + # Ensure XDG_RUNTIME_DIR before starting Weston (manual mkdir, no external helpers). if [ -z "${XDG_RUNTIME_DIR:-}" ]; then if mkdir -p "/run/user/$uid" 2>/dev/null; then @@ -1760,13 +1760,13 @@ weston_pick_env_or_start() { chmod 700 "$XDG_RUNTIME_DIR" 2>/dev/null || true log_info "$ctx: Using existing XDG_RUNTIME_DIR='$XDG_RUNTIME_DIR' before starting Weston" fi - + # Never pre-set WAYLAND_DISPLAY; let Weston choose. unset WAYLAND_DISPLAY - + log_info "$ctx: Starting Weston..." weston_start - + # 3) Wait up to ~10 seconds for any Wayland socket to appear. i=0 sock="" @@ -1782,17 +1782,17 @@ weston_pick_env_or_start() { sleep 1 i=$((i + 1)) done - + if [ -z "$sock" ]; then log_fail "$ctx: Could not find Wayland socket after starting Weston." return 1 fi - + if ! adopt_wayland_env_from_socket "$sock"; then log_fail "$ctx: Failed to adopt env from socket: $sock" return 1 fi - + log_info "$ctx: Weston started; socket: $sock" return 0 } @@ -1801,12 +1801,12 @@ weston_pick_env_or_start() { # Prints absolute socket paths, one per line, most-preferred first. find_wayland_sockets() { uid="$(id -u 2>/dev/null || echo 0)" - + if [ -n "${XDG_RUNTIME_DIR:-}" ] && [ -n "${WAYLAND_DISPLAY:-}" ] && [ -S "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" ]; then echo "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" fi - + # Current uid for f in "/run/user/$uid/wayland-0" "/run/user/$uid/wayland-1" "/run/user/$uid/wayland-2"; do [ -S "$f" ] && echo "$f" @@ -1814,7 +1814,7 @@ find_wayland_sockets() { for f in /run/user/"$uid"/wayland-*; do [ -S "$f" ] && echo "$f" done 2>/dev/null - + # Any other user under /run/user (covers weston as uid 100, 1000, etc.) for d in /run/user/*; do [ -d "$d" ] || continue @@ -1823,11 +1823,11 @@ find_wayland_sockets() { [ -S "$f" ] && echo "$f" done done 2>/dev/null - + for f in /dev/socket/weston/wayland-*; do [ -S "$f" ] && echo "$f" done 2>/dev/null - + for f in /tmp/wayland-*; do [ -S "$f" ] && echo "$f" done 2>/dev/null @@ -1868,7 +1868,7 @@ ensure_wayland_runtime_dir_perms() { # Also enforces/fixes XDG_RUNTIME_DIR permissions so clients won’t reject it. wayland_connection_ok() { sock="" - + # Sanity-check the socket path first. if [ -z "$XDG_RUNTIME_DIR" ] || [ -z "$WAYLAND_DISPLAY" ]; then log_warn "wayland_connection_ok: XDG_RUNTIME_DIR or WAYLAND_DISPLAY not set" @@ -1880,7 +1880,7 @@ wayland_connection_ok() { fi log_info "wayland_connection_ok: using socket $sock" fi - + if command -v wayland-info >/dev/null 2>&1; then log_info "Probing Wayland with: wayland-info" wayland-info >/dev/null 2>&1 @@ -1891,7 +1891,7 @@ wayland_connection_ok() { [ "$rc" -eq 124 ] && return 0 return 1 fi - + if command -v weston-info >/dev/null 2>&1; then log_info "Probing Wayland with: weston-info" weston-info >/dev/null 2>&1 @@ -1901,7 +1901,7 @@ wayland_connection_ok() { [ "$rc" -eq 124 ] && return 0 return 1 fi - + if command -v weston-simple-egl >/dev/null 2>&1; then log_info "Probing Wayland by briefly starting weston-simple-egl" ( @@ -1910,26 +1910,26 @@ wayland_connection_ok() { ) pid="$(cat "/tmp/.wsegl.$$" 2>/dev/null || echo '')" rm -f "/tmp/.wsegl.$$" 2>/dev/null || true - + i=0 while [ "$i" -lt 2 ]; do sleep 1 i=$((i + 1)) done - + if [ -n "$pid" ]; then kill "$pid" 2>/dev/null || true fi # If it started at all, consider the connection OK (best effort). return 0 fi - + # Last resort: trust socket existence alone. if [ -n "$sock" ] && [ -S "$sock" ]; then log_info "No probe tools present; accepting socket existence as OK." return 0 fi - + return 1 } # Very verbose snapshot for debugging (processes, sockets, env, perms). @@ -1937,7 +1937,7 @@ wayland_debug_snapshot() { label="$1" [ -n "$label" ] || label="snapshot" log_info "----- Wayland/Weston debug snapshot: $label -----" - + # Processes wpids="$(weston_pids)" if [ -n "$wpids" ]; then @@ -1953,23 +1953,23 @@ wayland_debug_snapshot() { else log_info "weston PIDs: (none)" fi - + # Sockets (meta) — use stat instead of ls (SC2012) for s in $(find_wayland_sockets | sort -u); do log_info "socket: $s" stat -c '[stat] %n -> owner=%U:%G mode=%A size=%s mtime=%y' "$s" 2>/dev/null || true done - + # Current env log_info "Env now: XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-} WAYLAND_DISPLAY=${WAYLAND_DISPLAY:-}" if [ -n "${XDG_RUNTIME_DIR:-}" ]; then stat -c '[stat] %n -> owner=%U:%G mode=%A size=%s mtime=%y' "$XDG_RUNTIME_DIR" 2>/dev/null || true fi - + log_info "Suggested export (current env):" log_info " export XDG_RUNTIME_DIR='${XDG_RUNTIME_DIR:-}'" log_info " export WAYLAND_DISPLAY='${WAYLAND_DISPLAY:-}'" - + log_info "----- End snapshot: $label -----" } @@ -2004,25 +2004,25 @@ print_path_meta() { display_connector_cur_mode() { full="$1" [ -n "$full" ] || { echo "-"; return; } - + card="${full%%-*}" # card0 con="${full#*-}" # HDMI-A-1 idx="${card#card}" # 0 - + state="/sys/kernel/debug/dri/${idx}/state" - + # debugfs may not be mounted; best-effort mount (ignore failures) if [ ! -r "$state" ] && [ -r /proc/mounts ] && command -v mount >/dev/null 2>&1; then if ! grep -q " /sys/kernel/debug " /proc/mounts 2>/dev/null; then mount -t debugfs debugfs /sys/kernel/debug 2>/dev/null || true fi fi - + [ -r "$state" ] || { echo "-"; return; } - + awk -v CON="$con" ' BEGIN { crtc=""; in_conn=0; in_crtc=0; mode=""; vr=""; active="" } - + # Connector block -> capture bound CRTC id $0 ~ /^connector/ { in_conn=0 @@ -2032,7 +2032,7 @@ display_connector_cur_mode() { if (match($0, /[0-9]+/, m)) crtc=m[0] } in_conn && $0 ~ /^$/ { in_conn=0 } - + # CRTC block -> capture active + mode + refresh crtc != "" && $0 ~ /^crtc/ { in_crtc=0 @@ -2048,7 +2048,7 @@ display_connector_cur_mode() { if (match($0, /[0-9]+(\.[0-9]+)?/, m)) vr=m[0] } in_crtc && $0 ~ /^$/ { in_crtc=0 } - + END { if (crtc == "" || mode == "" || active != "1") { print "-"; exit } if (vr != "") print mode "@" vr @@ -2065,19 +2065,19 @@ display_list_connectors() { [ -f "$d/status" ] || continue name="$(basename "$d")" status="$(tr -d '\r\n' <"$d/status" 2>/dev/null)" - + # enabled (best-effort; may not exist on some kernels) enabled="unknown" if [ -f "$d/enabled" ]; then enabled="$(tr -d '\r\n' <"$d/enabled" 2>/dev/null)" [ -z "$enabled" ] && enabled="unknown" fi - + # Derive connector type from name: cardX--N typ="$(printf '%s' "$name" \ | sed -n 's/^card[0-9]\+-\([A-Za-z0-9+]\+\(-[A-Za-z0-9+]\+\)*\)-[0-9]\+/\1/p')" [ -z "$typ" ] && typ="unknown" - + # Modes modes_file="$d/modes" if [ -f "$modes_file" ]; then @@ -2089,11 +2089,11 @@ display_list_connectors() { mc=0 fm="" fi - + # Current mode (best-effort via debugfs helper) cur="$(display_connector_cur_mode "$name")" [ -z "$cur" ] && cur="-" - + # NOTE: 7 columns: name status enabled typ mc fm cur printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \ "$name" "$status" "$enabled" "$typ" "$mc" "$fm" "$cur" @@ -2183,7 +2183,7 @@ display_debug_snapshot() { ctx="$1" [ -z "$ctx" ] && ctx="display-snapshot" log_info "----- Display snapshot: $ctx -----" - + have=0 while IFS="$(printf '\t')" read -r name status enabled typ mc fm cur; do [ -n "$name" ] || continue @@ -2195,7 +2195,7 @@ display_debug_snapshot() { $(display_list_connectors 2>/dev/null || true) EOF [ "$have" -eq 1 ] || log_warn "No DRM connectors in /sys/class/drm." - + log_info "----- End display snapshot: $ctx -----" } @@ -2313,7 +2313,7 @@ runWithTimeoutIfSet() { t=0 ;; esac - + if [ "$t" -gt 0 ] && command -v run_with_timeout >/dev/null 2>&1; then # Correct signature: run_with_timeout [args...] run_with_timeout "$t" "$@" @@ -2355,16 +2355,16 @@ run_dhcp_client() { try_dhcp_client_safe() { iface=$1 timeout=${2:-10} - + [ -n "$iface" ] || return 1 - + # Debug breadcrumb: track which path we took dhcp_path="unknown" dhcp_note="" - + # Ensure interface is up (best-effort) ip link set "$iface" up >/dev/null 2>&1 || true - + # If link is down/no cable, don't try DHCP if command -v is_link_up >/dev/null 2>&1; then if ! is_link_up "$iface"; then @@ -2377,7 +2377,7 @@ try_dhcp_client_safe() { return 1 fi fi - + current_ip=$(get_ip_address "$iface") if [ -n "$current_ip" ] && ! echo "$current_ip" | grep -q '^169\.254'; then dhcp_path="skip_existing_ip" @@ -2385,7 +2385,7 @@ try_dhcp_client_safe() { log_info "$iface already has valid IP: $current_ip. Skipping DHCP." return 0 fi - + # If NetworkManager/systemd-networkd is active, avoid fighting it: # just wait for IP to appear. if command -v systemctl >/dev/null 2>&1; then @@ -2410,13 +2410,13 @@ try_dhcp_client_safe() { return 1 fi fi - + # Minimal/kernel-only builds might not have udhcpc. Try other clients first if needed. if ! command -v udhcpc >/dev/null 2>&1; then log_warn "udhcpc not found (kernel/minimal build). Trying fallback DHCP clients..." dhcp_path="fallback_clients" log_info "$iface DHCP path: ${dhcp_path} (trying dhclient/dhcpcd)" - + if command -v dhclient >/dev/null 2>&1; then dhcp_note="dhclient" log_info "$iface DHCP path: ${dhcp_path}/${dhcp_note} (timeout=${timeout}s)" @@ -2426,14 +2426,14 @@ try_dhcp_client_safe() { else dhclient -1 -v "$iface" >/dev/null 2>&1 || true fi - + current_ip=$(get_ip_address "$iface") if [ -n "$current_ip" ] && ! echo "$current_ip" | grep -q '^169\.254'; then log_info "$iface DHCP path: ${dhcp_path}/${dhcp_note} success (ip=${current_ip})" return 0 fi fi - + if command -v dhcpcd >/dev/null 2>&1; then dhcp_note="dhcpcd" log_info "$iface DHCP path: ${dhcp_path}/${dhcp_note} (timeout=${timeout}s)" @@ -2445,18 +2445,18 @@ try_dhcp_client_safe() { fi # Avoid leaving daemon running if it spawned dhcpcd -k "$iface" >/dev/null 2>&1 || true - + current_ip=$(get_ip_address "$iface") if [ -n "$current_ip" ] && ! echo "$current_ip" | grep -q '^169\.254'; then log_info "$iface DHCP path: ${dhcp_path}/${dhcp_note} success (ip=${current_ip})" return 0 fi fi - + log_warn "$iface DHCP path: ${dhcp_path} failed (no client succeeded)" return 1 fi - + # Safe udhcpc script: # - Avoid aggressive flushes # - Remove only link-local (169.254/16) if present @@ -2502,7 +2502,7 @@ mask_to_prefix() { ;; esac } - + case "$1" in bound|renew) # Drop link-local if present @@ -2511,7 +2511,7 @@ case "$1" in [ -n "$cidr" ] || continue ip addr del "$cidr" dev "$interface" >/dev/null 2>&1 || true done - + # Add/replace address (best-effort) if [ -n "$ip" ]; then pfx="" @@ -2524,7 +2524,7 @@ case "$1" in ip addr add "$ip" dev "$interface" >/dev/null 2>&1 || true fi fi - + # Default route if [ -n "$router" ]; then ip route replace default via "$router" dev "$interface" >/dev/null 2>&1 || true @@ -2541,7 +2541,7 @@ case "$1" in esac EOF chmod +x "$safe_dhcp_script" - + dhcp_path="udhcpc_safe_script" log_info "$iface DHCP path: ${dhcp_path} (timeout=${timeout}s)" log_info "Attempting DHCP on $iface (udhcpc) for up to ${timeout}s..." @@ -2551,9 +2551,9 @@ EOF # Best-effort bounded retries if run_with_timeout isn't available udhcpc -i "$iface" -n -q -t 3 -T 3 -s "$safe_dhcp_script" >/dev/null 2>&1 || true fi - + rm -f "$safe_dhcp_script" >/dev/null 2>&1 || true - + # Verify outcome current_ip=$(get_ip_address "$iface") if [ -n "$current_ip" ] && ! echo "$current_ip" | grep -q '^169\.254'; then @@ -2561,7 +2561,7 @@ EOF log_info "$iface DHCP path: ${dhcp_path} success (ip=${current_ip})" return 0 fi - + log_warn "$iface still has no valid IP after DHCP attempt" log_warn "$iface DHCP path: ${dhcp_path} failed (no valid IP after attempt)" return 1 @@ -2582,9 +2582,9 @@ ethIsLinkUp() { carrier="" st="" ld="" - + [ -n "$iface" ] || return 1 - + # 1) If carrier says 1, we are good. # Some drivers return EINVAL while MAC/PHY attach is broken or incomplete. # Suppress stderr to avoid noisy LAVA stdout. @@ -2592,30 +2592,30 @@ ethIsLinkUp() { carrier="$(cat "/sys/class/net/$iface/carrier" 2>/dev/null || true)" [ "$carrier" = "1" ] && return 0 fi - + # 2) If helper exists and says up, accept it. if command -v is_link_up >/dev/null 2>&1; then is_link_up "$iface" >/dev/null 2>&1 && return 0 fi - + # 3) operstate can sometimes reflect link sooner than carrier. if [ -r "/sys/class/net/$iface/operstate" ]; then st="$(cat "/sys/class/net/$iface/operstate" 2>/dev/null || true)" [ "$st" = "up" ] && return 0 fi - + # 4) ip link LOWER_UP is a useful physical-link signal. if command -v ip >/dev/null 2>&1; then ip link show "$iface" 2>/dev/null | grep -qw "LOWER_UP" && return 0 fi - + # 5) Last resort: ethtool parse. if command -v ethtool >/dev/null 2>&1; then ld="$(ethtool "$iface" 2>/dev/null | awk -F': ' '/^[[:space:]]*Link detected:/ {print $2; exit 0}' || true)" [ "$ld" = "yes" ] && return 0 fi - + return 1 } @@ -2623,10 +2623,10 @@ ethWaitLinkUp() { iface=$1 timeout_s=$2 i=0 - + [ -n "$iface" ] || return 1 [ -n "$timeout_s" ] || timeout_s=5 - + while [ "$i" -lt "$timeout_s" ]; do if ethIsLinkUp "$iface"; then return 0 @@ -2634,7 +2634,7 @@ ethWaitLinkUp() { i=$((i + 1)) sleep 1 done - + return 1 } @@ -2687,11 +2687,11 @@ ethRestartAutoneg() { ethForceSpeedMbps() { iface=$1 mbps=$2 - + [ -n "$iface" ] || return 1 command -v ethtool >/dev/null 2>&1 || return 1 case "$mbps" in ""|*[!0-9]*) return 1 ;; esac - + ethtool -s "$iface" speed "$mbps" duplex full autoneg off >/dev/null 2>&1 || return 1 return 0 } @@ -2709,11 +2709,11 @@ ethEnableAutoneg() { ethSupportsSpeedMbps() { iface=$1 mbps=$2 - + [ -n "$iface" ] || return 1 case "$mbps" in ""|*[!0-9]*) return 1 ;; esac command -v ethtool >/dev/null 2>&1 || return 1 - + ethtool "$iface" 2>/dev/null | grep -Eq "[[:space:]]${mbps}baseT/Full|[[:space:]]${mbps}baseT1/Full|[[:space:]]${mbps}baseX/Full" } @@ -2767,7 +2767,7 @@ ethEnsureLinkUpWithFallback() { [ -n "$iface" ] || return 1 [ -n "$timeout_s" ] || timeout_s=5 init_autoneg=$(ethGetAutonegState "$iface" 2>/dev/null || echo "unknown") - + # Bring interface up using existing helper (admin-up) if command -v bringup_interface >/dev/null 2>&1; then bringup_interface "$iface" 3 2 >/dev/null 2>&1 || true @@ -2775,18 +2775,18 @@ ethEnsureLinkUpWithFallback() { ip link set "$iface" up >/dev/null 2>&1 || true sleep 1 fi - + # Let PHY settle a bit after admin-up sleep 1 - + # 1) Wait for normal autoneg link if ethWaitLinkUp "$iface" "$timeout_s"; then return 0 fi - + # If no ethtool, we cannot do fallback forcing command -v ethtool >/dev/null 2>&1 || return 1 - + # 2) Try restarting autoneg once if ethRestartAutoneg "$iface"; then # Give retrain a moment before polling @@ -2795,18 +2795,18 @@ ethEnsureLinkUpWithFallback() { return 0 fi fi - + # 3) Force speeds (smart order: may try 100 first for 100M-only setups) force_order=$(ethPickForceOrder "$iface" 2>/dev/null || echo "1000 100") for sp in $force_order; do if ethForceSpeedMbps "$iface" "$sp"; then # After forcing speed, some PHYs need a short settle window sleep 1 - + # Best-effort retrain ethtool -r "$iface" >/dev/null 2>&1 || true sleep 1 - + if ethWaitLinkUp "$iface" "$timeout_s"; then # IMPORTANT: Do NOT restore autoneg here. # If we had to force speed (autoneg off), keeping it avoids regression @@ -2815,7 +2815,7 @@ ethEnsureLinkUpWithFallback() { fi fi done - + # Bring-up failed: # If autoneg was originally on, restore it (best-effort) so we don't leave user in forced mode. if [ "$init_autoneg" = "on" ]; then @@ -2833,7 +2833,7 @@ ethEnsureLinkUpWithFallback() { get_remoteproc_by_firmware() { fw="$1" out="$2" # optional: filepath to append results - list_all="$3" # set to "all" to continue past first match + list_all="$3" # set to "all" to continue past first match [ -n "$fw" ] || return 3 # misuse if no firmware provided @@ -2884,35 +2884,35 @@ get_remoteproc_by_firmware() { dt_has_remoteproc_fw() { fw="$1" [ -n "$fw" ] || return 3 - + base="/proc/device-tree" [ -d "$base" ] || return 1 - + # lower-case match key fw_lc=$(printf '%s\n' "$fw" | tr '[:upper:]' '[:lower:]') - + # new fast-path (any smp2p-* or remoteproc-* directory) found=0 for d in "$base"/smp2p-"$fw"* "$base"/remoteproc-"$fw"*; do [ -d "$d" ] && found=1 && break done [ "$found" -eq 1 ] && return 0 - + # 2) Shallow find (/dev/null | grep -q .; then return 0 fi - + # 3) Grep soc@0 and aliases for a first match if grep -Iq -m1 -F "$fw_lc" "$base/soc@0" "$base/aliases" 2>/dev/null; then return 0 fi - + # 4) Fallback: grep entire DT tree if grep -Iq -m1 -F "$fw_lc" "$base" 2>/dev/null; then return 0 fi - + return 1 } @@ -2923,14 +2923,14 @@ dt_has_remoteproc_fw() { # - Subtract 1 → remoteproc index → /sys/class/remoteproc/remoteproc${idx} get_remoteproc_path_by_firmware() { name=$1 - + [ -n "$name" ] || return 1 [ -d /sys/class/remoteproc ] || return 1 - + for fw in /sys/class/remoteproc/remoteproc*/firmware; do # Skip if glob didn't match any file [ -f "$fw" ] || continue - + # Read first line from firmware file without using cat if IFS= read -r fwname <"$fw"; then case "$fwname" in @@ -2945,7 +2945,7 @@ get_remoteproc_path_by_firmware() { esac fi done - + return 1 } @@ -2953,12 +2953,12 @@ get_remoteproc_path_by_firmware() { get_remoteproc_state() { rp="$1" [ -z "$rp" ] && { printf '\n'; return 1; } - + case "$rp" in /sys/*) rpath="$rp" ;; *) rpath="/sys/class/remoteproc/$rp" ;; esac - + state_file="$rpath/state" if [ -r "$state_file" ]; then IFS= read -r state < "$state_file" || state="" @@ -2972,17 +2972,17 @@ get_remoteproc_state() { # wait_remoteproc_state wait_remoteproc_state() { rp="$1"; want="$2"; to=${3:-10}; poll=${4:-1} - + case "$rp" in /sys/*) rpath="$rp" ;; *) rpath="/sys/class/remoteproc/$rp" ;; esac - + start_ts=$(date +%s) while :; do cur=$(get_remoteproc_state "$rpath") [ "$cur" = "$want" ] && return 0 - + now_ts=$(date +%s) [ $((now_ts - start_ts)) -ge "$to" ] && { log_info "Waiting for state='$want' timed out (got='$cur')..." @@ -2995,40 +2995,40 @@ wait_remoteproc_state() { # Stop remoteproc stop_remoteproc() { rproc_path="$1" - + # Resolve to a real sysfs dir if only a name was given case "$rproc_path" in /sys/*) path="$rproc_path" ;; remoteproc*) path="/sys/class/remoteproc/$rproc_path" ;; *) path="$rproc_path" ;; # last resort, assume caller passed full path esac - + statef="$path/state" if [ ! -w "$statef" ]; then log_warn "stop_remoteproc: state file not found/writable: $statef" return 1 fi - + printf 'stop\n' >"$statef" 2>/dev/null || return 1 wait_remoteproc_state "$path" offline 6 } - + # Start remoteproc start_remoteproc() { rproc_path="$1" - + case "$rproc_path" in /sys/*) path="$rproc_path" ;; remoteproc*) path="/sys/class/remoteproc/$rproc_path" ;; *) path="$rproc_path" ;; esac - + statef="$path/state" if [ ! -w "$statef" ]; then log_warn "start_remoteproc: state file not found/writable: $statef" return 1 fi - + printf 'start\n' >"$statef" 2>/dev/null || return 1 wait_remoteproc_state "$path" running 6 } @@ -3205,21 +3205,21 @@ rpmsg_create_ep_generic() { name="${2:-gen-test}" # generic endpoint name src="${3:-0}" dst="${4:-0}" - + create_file="$(readlink -f "$ctrl_sys")/create" [ -w "$create_file" ] || return 1 - + # Request endpoint creation printf '%s %s %s\n' "$name" "$src" "$dst" >"$create_file" 2>/dev/null || return 1 - + # Pick the newest rpmsg* sysfs node without using 'ls -t' (SC2012) new_sys=$( find -L /sys/class/rpmsg -maxdepth 1 -type l -name 'rpmsg[0-9]*' \ -printf '%T@ %p\n' 2>/dev/null | sort -nr | awk 'NR==1{print $2}' ) - + [ -n "$new_sys" ] || return 1 - + rpmsg_sys_to_dev "$new_sys" } @@ -4079,19 +4079,19 @@ $val" ;; configure_pipeline_block() { MEDIA_NODE="$1" USER_FORMAT="$2" - + # Reset graph if ! media-ctl -d "$MEDIA_NODE" reset >/dev/null 2>&1; then media-ctl -d "$MEDIA_NODE" -r >/dev/null 2>&1 || true fi - + # Apply pad formats (MBUS, never *P). Also strip 'field:*'. printf "%s\n" "$MEDIA_CTL_V_LIST" | while IFS= read -r vline || [ -n "$vline" ]; do [ -z "$vline" ] && continue - + curfmt="$(printf "%s" "$vline" | sed -n 's/.*fmt:\([^/]*\)\/.*/\1/p')" newfmt="$curfmt" - + if [ -n "$USER_FORMAT" ]; then case "$USER_FORMAT" in *P) newfmt="${USER_FORMAT%P}" ;; @@ -4103,18 +4103,18 @@ configure_pipeline_block() { *) newfmt="$curfmt" ;; esac fi - + vline_new="$(printf "%s" "$vline" | sed -E "s/fmt:[^/]+/fmt:${newfmt}/")" vline_new="$(printf "%s" "$vline_new" | sed -E 's/ field:[^]]*//g')" - + if [ -n "$YAVTA_W" ] && [ -n "$YAVTA_H" ]; then vline_new="$(printf "%s" "$vline_new" \ | sed -E "s/(fmt:[^/]+\/)[0-9]+x[0-9]+/\1${YAVTA_W}x${YAVTA_H}/")" fi - + media-ctl -d "$MEDIA_NODE" -V "$vline_new" >/dev/null 2>&1 done - + # Apply ONLY the two links (no fragile case patterns; avoids ShellCheck parse issues). printf "%s\n" "$MEDIA_CTL_L_LIST" | while IFS= read -r lline || [ -n "$lline" ]; do [ -z "$lline" ] && continue @@ -4127,10 +4127,10 @@ configure_pipeline_block() { : # ignore others fi done - + sleep 0.15 } - + # Executes yavta capture with the same semantics as your manual call. # Return codes: # 0: PASS (>=1 frame captured) @@ -4212,13 +4212,13 @@ execute_capture_block() { print_planned_commands() { media_node="$1" pixfmt="$2" - + # Pads should use MBUS code (strip trailing 'P' if present) padfmt="$(printf '%s' "$pixfmt" | sed 's/P$//')" - + log_info "[CI] Planned sequence:" log_info " media-ctl -d $media_node --reset" - + # Pad formats: show MBUS (non-P) on -V lines if [ -n "$MEDIA_CTL_V_LIST" ]; then printf '%s\n' "$MEDIA_CTL_V_LIST" | while IFS= read -r vline; do @@ -4227,7 +4227,7 @@ print_planned_commands() { log_info " media-ctl -d $media_node -V '$vline_out'" done fi - + # Links unchanged if [ -n "$MEDIA_CTL_L_LIST" ]; then printf '%s\n' "$MEDIA_CTL_L_LIST" | while IFS= read -r lline; do @@ -4235,7 +4235,7 @@ print_planned_commands() { log_info " media-ctl -d $media_node -l '$lline'" done fi - + # Any pre/post yavta register writes (unchanged) if [ -n "$YAVTA_CTRL_PRE_LIST" ]; then printf '%s\n' "$YAVTA_CTRL_PRE_LIST" | while IFS= read -r ctrl; do @@ -4247,7 +4247,7 @@ print_planned_commands() { log_info " yavta --no-query -w '$reg $val' $dev" done fi - + size_arg="" if [ -n "$YAVTA_W" ] && [ -n "$YAVTA_H" ]; then size_arg="-s ${YAVTA_W}x${YAVTA_H}" @@ -4256,7 +4256,7 @@ print_planned_commands() { # Show pixel format (SRGGB10P) only on the video node log_info " yavta -B capture-mplane -c -I -n $FRAMES -f $pixfmt $size_arg -F $YAVTA_DEV --capture=$FRAMES --file='frame-#.bin'" fi - + if [ -n "$YAVTA_CTRL_POST_LIST" ]; then printf '%s\n' "$YAVTA_CTRL_POST_LIST" | while IFS= read -r ctrl; do [ -z "$ctrl" ] && continue @@ -4294,33 +4294,33 @@ detect_platform() { PLATFORM_ARCH="$(uname -m 2>/dev/null)" PLATFORM_UNAME_S="$(uname -s 2>/dev/null)" PLATFORM_HOSTNAME="$(hostname 2>/dev/null)" - + # --- soc0 details --- if [ -r /sys/devices/soc0/machine ]; then PLATFORM_SOC_MACHINE="$(cat /sys/devices/soc0/machine 2>/dev/null)" else PLATFORM_SOC_MACHINE="" fi - + if [ -r /sys/devices/soc0/soc_id ]; then PLATFORM_SOC_ID="$(cat /sys/devices/soc0/soc_id 2>/dev/null)" else PLATFORM_SOC_ID="" fi - + if [ -r /sys/devices/soc0/family ]; then PLATFORM_SOC_FAMILY="$(cat /sys/devices/soc0/family 2>/dev/null)" else PLATFORM_SOC_FAMILY="" fi - + # --- Device Tree model / compatible (strip NULs) --- if [ -r /proc/device-tree/model ]; then PLATFORM_DT_MODEL="$(tr -d '\000' /dev/null | head -n 1)" else PLATFORM_DT_MODEL="" fi - + PLATFORM_DT_COMPAT="" if [ -d /proc/device-tree ]; then for f in /proc/device-tree/compatible /proc/device-tree/*/compatible; do @@ -4330,7 +4330,7 @@ detect_platform() { fi done fi - + # --- OS (parse, do not source /etc/os-release) --- PLATFORM_OS_LIKE="" PLATFORM_OS_NAME="" @@ -4347,11 +4347,11 @@ detect_platform() { awk -F= '$1=="PRETTY_NAME"{gsub(/"/,"",$2); print $2}' /etc/os-release 2>/dev/null )" fi - + # --- Target guess (mutually-exclusive; generic names only) --- lc_compat="$(printf '%s %s' "$PLATFORM_DT_MODEL" "$PLATFORM_DT_COMPAT" \ | tr '[:upper:]' '[:lower:]')" - + case "$lc_compat" in # Kodiak: qcs6490 / RB3 Gen2 *qcs6490*|*kodiak*|*rb3gen2*|*rb3-gen2*|*rb3*gen2*) @@ -4377,7 +4377,7 @@ detect_platform() { PLATFORM_TARGET="unknown" ;; esac - + # --- Human-friendly machine name --- if [ -n "$PLATFORM_DT_MODEL" ]; then PLATFORM_MACHINE="$PLATFORM_DT_MODEL" @@ -4388,14 +4388,14 @@ detect_platform() { PLATFORM_MACHINE="$PLATFORM_HOSTNAME" fi fi - + # Export for callers (and to silence SC2034 in this file) export \ PLATFORM_KERNEL PLATFORM_ARCH PLATFORM_UNAME_S PLATFORM_HOSTNAME \ PLATFORM_SOC_MACHINE PLATFORM_SOC_ID PLATFORM_SOC_FAMILY \ PLATFORM_DT_MODEL PLATFORM_DT_COMPAT PLATFORM_OS_LIKE PLATFORM_OS_NAME \ PLATFORM_TARGET PLATFORM_MACHINE - + return 0 } @@ -4435,9 +4435,9 @@ tryremountrw() { # FASTRPC_AUTOREMOUNT_RO=yes|no (default: yes) remount ro after linking ensure_usr_lib_dsp_symlinks() { [ "${FASTRPC_DSP_AUTOLINK:-yes}" = "yes" ] || { log_info "DSP autolink disabled"; return 0; } - + dsptgt="/usr/lib/dsp" - + # If already populated, skip if [ -d "$dsptgt" ]; then if find "$dsptgt" -mindepth 1 -maxdepth 1 -print -quit 2>/dev/null | grep -q .; then @@ -4445,7 +4445,7 @@ ensure_usr_lib_dsp_symlinks() { return 0 fi fi - + # Choose source: explicit env wins, else discover if [ -n "${FASTRPC_DSP_SRC:-}" ] && [ -d "$FASTRPC_DSP_SRC" ]; then dspsrc="$FASTRPC_DSP_SRC" @@ -4455,7 +4455,7 @@ ensure_usr_lib_dsp_symlinks() { hintstr="$(printf '%s %s %s %s' \ "${PLATFORM_SOC_ID:-}" "${PLATFORM_DT_MODEL:-}" "${PLATFORM_DT_COMPAT:-}" "${PLATFORM_TARGET:-}" \ | tr '[:upper:]' '[:lower:]')" - + candidateslist="$(find /usr/share/qcom -maxdepth 6 -type d -name dsp 2>/dev/null | sort)" best=""; bestscore=-1; bestcount=-1 IFS=' @@ -4479,18 +4479,18 @@ ensure_usr_lib_dsp_symlinks() { unset IFS dspsrc="$best" fi - + if [ -z "$dspsrc" ]; then log_warn "No DSP skeleton source found under /usr/share/qcom, skipping autolink." return 0 fi - + # Must be root on Yocto (no sudo). If not root, skip safely. if ! isroot; then log_warn "Not root; cannot write to $dsptgt on Yocto (no sudo). Skipping DSP autolink." return 0 fi - + # Ensure target dir exists; handle read-only rootfs if requested remounted="" mountpt="" @@ -4513,7 +4513,7 @@ ensure_usr_lib_dsp_symlinks() { return 0 fi fi - + # If something appeared meanwhile, stop (idempotent) if find "$dsptgt" -mindepth 1 -maxdepth 1 -print -quit 2>/dev/null | grep -q .; then log_info "$dsptgt now contains entries, not linking from $dspsrc" @@ -4522,7 +4522,7 @@ ensure_usr_lib_dsp_symlinks() { fi return 0 fi - + # Link both files and directories; don't clobber existing names log_info "Linking DSP artifacts from: $dspsrc → $dsptgt" linked=0 @@ -4537,7 +4537,7 @@ ensure_usr_lib_dsp_symlinks() { fi fi done - + # Final visibility + sanity if find "$dsptgt" -mindepth 1 -maxdepth 1 -print -quit 2>/dev/null | grep -q .; then log_info "DSP autolink complete ($linked link(s))" @@ -4550,7 +4550,7 @@ ensure_usr_lib_dsp_symlinks() { else log_warn "DSP autolink finished but $dsptgt is still empty, source may contain only nested content or FS is RO." fi - + # Optionally restore read-only if [ -n "$remounted" ] && [ -n "$mountpt" ] && [ "${FASTRPC_AUTOREMOUNT_RO:-yes}" = "yes" ]; then mount -o remount,ro "$mountpt" 2>/dev/null || true @@ -4894,11 +4894,11 @@ sanitize_pid() { get_pids_by_name() { name="$1" - + if [ -z "$name" ]; then return 1 fi - + # Print one PID per line (sanitized), for all processes whose basename matches $name ps -ef 2>/dev/null | awk -v n="$name" ' NR==1 { next } @@ -4913,7 +4913,7 @@ get_pids_by_name() { fi done } - + # get_one_pid_by_name [all] # # Without 'all': prints the lowest (oldest) matching PID, returns 1 if none found. @@ -4925,29 +4925,29 @@ get_one_pid_by_name() { gopn_mode="${2:-}" gopn_pids="" gopn_first_pid="" - + for gopn_d in /proc/[0-9]*; do [ -r "$gopn_d/comm" ] || continue gopn_comm=$(tr -d '\r\n' <"$gopn_d/comm" 2>/dev/null) [ "$gopn_comm" = "$gopn_name" ] || continue - + gopn_pid=${gopn_d#/proc/} gopn_pid=$(sanitize_pid "$gopn_pid") [ -n "$gopn_pid" ] || continue - + if [ -z "$gopn_first_pid" ] || [ "$gopn_pid" -lt "$gopn_first_pid" ]; then gopn_first_pid="$gopn_pid" fi - + if [ -z "$gopn_pids" ]; then gopn_pids="$gopn_pid" else gopn_pids="$gopn_pids $gopn_pid" fi done - + [ -n "$gopn_pids" ] || return 1 - + if [ "$gopn_mode" = "all" ]; then printf '%s\n' "$gopn_pids" else @@ -4959,14 +4959,14 @@ get_one_pid_by_name() { wait_pid_alive() { pid="$1" timeout="${2:-10}" - + pid=$(sanitize_pid "$pid") case "$pid" in ''|*[!0-9]*) return 1 ;; esac - + i=0 while [ "$i" -lt "$timeout" ]; do if kill -0 "$pid" 2>/dev/null; then @@ -4984,40 +4984,40 @@ kill_process() { KILL_TERM_GRACE="${KILL_TERM_GRACE:-5}" KILL_KILL_GRACE="${KILL_KILL_GRACE:-5}" SELF_PID="$$" - + case "$PID" in ''|*[!0-9]*) log_warn "Refusing to kill non-numeric PID '$PID'" return 1 ;; esac - + # Safety checks if [ "$PID" -eq 1 ] || [ "$PID" -eq "$SELF_PID" ]; then log_warn "Refusing to kill PID $PID (init or self)" return 1 fi - + if ! kill -0 "$PID" 2>/dev/null; then log_info "Process $PID not running" return 0 fi - + log_info "Sending SIGTERM to PID $PID" kill -TERM "$PID" 2>/dev/null sleep "$KILL_TERM_GRACE" - + if kill -0 "$PID" 2>/dev/null; then log_info "Sending SIGKILL to PID $PID" kill -KILL "$PID" 2>/dev/null sleep "$KILL_KILL_GRACE" fi - + if kill -0 "$PID" 2>/dev/null; then log_warn "Failed to kill process $PID" return 1 fi - + log_info "Process $PID terminated successfully" return 0 } @@ -5034,38 +5034,38 @@ kill_process() { # - If multiple instances exist, logs the PID list as a summary. is_process_running() { ipr_name="$1" - + ipr_pids=$(get_one_pid_by_name "$ipr_name" all 2>/dev/null) || { log_info "Process '$ipr_name' is not running." return 1 } - + log_info "Process '$ipr_name' is running." - + # Extra summary only if multiple instances exist case "$ipr_pids" in *" "*) log_info "Process '$ipr_name' instances: $ipr_pids" ;; esac - + # Always print PID -> cmdline/comm for CI debug (single or multiple) # ShellCheck-safe iteration: split spaces to newlines. printf '%s\n' "$ipr_pids" | tr ' ' '\n' | while IFS= read -r ipr_pid; do ipr_pid=$(sanitize_pid "$ipr_pid") [ -n "$ipr_pid" ] || continue - + # PID may have exited between collection and inspection if [ ! -d "/proc/$ipr_pid" ]; then log_info "Process '$ipr_name' PID $ipr_pid is no longer present in /proc" continue fi - + ipr_cmd="" if [ -r "/proc/$ipr_pid/cmdline" ]; then ipr_cmd=$(tr '\000' ' ' <"/proc/$ipr_pid/cmdline" 2>/dev/null) fi - + if [ -n "$ipr_cmd" ]; then log_info "Process '$ipr_name' PID $ipr_pid cmdline: $ipr_cmd" else @@ -5076,7 +5076,7 @@ is_process_running() { log_info "Process '$ipr_name' PID $ipr_pid comm: ${ipr_comm:-unknown}" fi done - + return 0 } diff --git a/Runner/utils/lib_bluetooth.sh b/Runner/utils/lib_bluetooth.sh index d65e574e..4606def6 100755 --- a/Runner/utils/lib_bluetooth.sh +++ b/Runner/utils/lib_bluetooth.sh @@ -136,22 +136,22 @@ bt_scan_devices_expect() { duration="${SCAN_SECONDS:-10}" mac_id="${MAC_ID:-}" [ -z "${mac_id}" ] && [ -n "${1:-}" ] && mac_id="$1" # allow positional MAC - + # Detect adapter; hciconfig prints "hci0:"; strip trailing colon. if [ -z "${adapter}" ]; then adapter="$(hciconfig 2>/dev/null | awk '/^hci[0-9]+/ {print $1}' | head -n1)" fi adapter="${adapter%:}" - + if [ -z "${adapter}" ]; then log_error "No Bluetooth adapter found" return 1 fi - + log_info "Using Bluetooth adapter: ${adapter}" hciconfig "${adapter}" up 2>/dev/null || true sleep 1 - + # Expect flow (prompt-tolerant, in-memory capture) scan_raw="$(expect -c " log_user 1 @@ -175,10 +175,10 @@ expect -re {#|\\\[.*\\\]#} {} send \"quit\\r\" expect { timeout {} eof {} } " 2>&1)" - + log_info "scan_raw size: $(printf '%s' "${scan_raw}" | wc -c) bytes" printf '%s\n' "${scan_raw}" | head -n 3 | sed 's/^/[RAW] /' >&2 - + # Clean CRs; sanity check for "Device " lines scan_clean="$(printf '%s' "${scan_raw}" | tr -d '\r')" if ! printf '%s' "${scan_clean}" | grep -q 'Device '; then @@ -187,7 +187,7 @@ expect { timeout {} eof {} } fi log_info "scan_clean size: $(printf '%s' "${scan_clean}" | wc -c) bytes" printf '%s\n' "${scan_clean}" | head -n 3 | sed 's/^/[CLN] /' >&2 - + # Build unique "MAC NAME" lines (BusyBox-safe MAC check) found_lines="$( printf '%s\n' "${scan_clean}" | @@ -222,12 +222,12 @@ expect { timeout {} eof {} } } ' | sort -u )" - + if [ -z "${found_lines}" ]; then log_warn "Parsed 0 devices (format/parser issue?)." return 1 fi - + if [ -n "${mac_id}" ]; then if match_line="$(printf '%s\n' "${found_lines}" | awk -v t="${mac_id}" 'BEGIN{IGNORECASE=1} $1==t {print; exit 0} END{exit 1}')"; then printf '%s\n' "${match_line}" @@ -236,7 +236,7 @@ expect { timeout {} eof {} } log_warn "MAC_ID not found: ${mac_id}" return 1 fi - + printf '%s\n' "${found_lines}" return 0 } @@ -600,9 +600,9 @@ bt_pair_with_mac() { log_error "Usage: bt_pair_with_mac [adapter]" return 1 fi - + mac=$1 - + # Optional second arg: adapter; otherwise use default helper or hci0 if [ $# -ge 2 ]; then adapter=$2 @@ -613,17 +613,17 @@ bt_pair_with_mac() { adapter="hci0" fi fi - + if ! command -v bluetoothctl >/dev/null 2>&1; then log_error "bt_pair_with_mac: bluetoothctl not found in PATH" return 1 fi - + # Safe logfile name: MAC with ':' -> '_' (same pattern as your last working snapshot) safe_mac=$(printf '%s\n' "$mac" | tr '[:lower:]' '[:upper:]' | tr ':' '_') ts=$(date +%Y%m%d_%H%M%S 2>/dev/null || date +%s) logfile="bt_pair_${safe_mac}_${ts}.log" - + log_info "Ensuring controller is powered on before pairing (adapter=${adapter})..." if command -v btpower >/dev/null 2>&1; then btpower "$adapter" on >>"$logfile" 2>&1 || \ @@ -631,21 +631,21 @@ bt_pair_with_mac() { else log_warn "bt_pair_with_mac: 'btpower' helper not found; assuming adapter is powered." fi - + # ---------------- First attempt: no internal scan ---------------- log_info "Attempting bluetoothctl 'pair $mac' (no internal scan)..." bluetoothctl --timeout 20 pair "$mac" >>"$logfile" 2>&1 || true - + # Success = explicit "Pairing successful" only (no 'Paired: yes' check) if grep -qi 'Pairing successful' "$logfile"; then log_info "bt_pair_with_mac: successfully paired with $mac" return 0 fi - + # ---------------- Fallback: only if device was "not available" ---------------- if grep -qi 'not available' "$logfile"; then log_warn "bt_pair_with_mac: device not available; running short scan+retry for $mac" - + if command -v bt_scan_devices >/dev/null 2>&1; then # Append scan logs to the same file for full context bt_scan_devices "$mac" >>"$logfile" 2>&1 || \ @@ -653,17 +653,17 @@ bt_pair_with_mac() { else log_warn "bt_pair_with_mac: bt_scan_devices helper not found; skipping scan retry." fi - + log_info "Retrying bluetoothctl 'pair $mac' after scan..." bluetoothctl --timeout 20 pair "$mac" >>"$logfile" 2>&1 || true - + if grep -qi 'Pairing successful' "$logfile"; then log_info "bt_pair_with_mac: successfully paired with $mac after scan retry" return 0 fi fi # ----------------------------------------------------------------- - + log_warn "bt_pair_with_mac: bluetoothctl did not report successful pairing for $mac (see $logfile)" return 1 } @@ -778,7 +778,7 @@ bt_post_pair_connect() { sanitized_mac=$(echo "$target_mac" | tr ':' '_') timestamp=$(date '+%Y%m%d_%H%M%S') base_logfile="bt_connect_${sanitized_mac}_${timestamp}" - + # Already connected? (like when pair leaves us connected) if bluetoothctl info "$target_mac" 2>/dev/null \ | sanitize_bt_output \ @@ -788,20 +788,20 @@ bt_post_pair_connect() { log_pass "Post-pair connection successful" return 0 fi - + max_attempts=3 attempt=1 while [ "$attempt" -le "$max_attempts" ]; do logfile="${base_logfile}_attempt${attempt}.log" log_info "Attempting bluetoothctl connect (try $attempt/$max_attempts) to $target_mac" - + bluetoothctl <"$logfile" 2>&1 power on trust $target_mac connect $target_mac quit EOF - + if bluetoothctl info "$target_mac" 2>/dev/null \ | sanitize_bt_output \ | grep -q 'Connected:[[:space:]]*yes' @@ -809,17 +809,17 @@ EOF log_pass "Post-pair connection successful to $target_mac (see $logfile)" return 0 fi - + if grep -q "Failed to connect" "$logfile"; then log_warn "bluetoothctl reported connect failure for $target_mac (see $logfile)" else log_warn "No 'Connected: yes' for $target_mac after attempt $attempt (see $logfile)" fi - + attempt=$((attempt + 1)) sleep 2 done - + # Final fallback: l2ping (this is what the test ultimately cares about) if command -v l2ping >/dev/null 2>&1; then l2ping_log="${base_logfile}_l2ping.log" @@ -835,7 +835,7 @@ EOF else log_warn "l2ping not available, skipping connectivity fallback for $target_mac" fi - + log_fail "Post-pair connection failed for $target_mac" return 1 } @@ -859,18 +859,18 @@ bt_remove_all_paired_devices() { bt_l2ping_check() { target_mac="$1" logfile="$2" - + if ! command -v l2ping >/dev/null 2>&1; then log_warn "l2ping command not available - skipping" return 1 fi - + # Small grace period after connect so the remote side can settle sleep 2 - + attempts=2 i=1 - + while [ "$i" -le "$attempts" ]; do log_info "Running l2ping test for $target_mac (attempt $i/$attempts)" if l2ping -c 3 -t 5 "$target_mac" >>"$logfile" 2>&1; then @@ -881,7 +881,7 @@ bt_l2ping_check() { i=$((i + 1)) sleep 2 done - + log_warn "l2ping to $target_mac failed after $attempts attempts" return 1 } @@ -1307,7 +1307,7 @@ findhcisysfs() { # ret: 0=ok, 1=not found btgetbdaddr() { dev="${1:-}" - + if command -v hciconfig >/dev/null 2>&1; then if [ -n "$dev" ]; then addr="$(hciconfig -a "$dev" 2>/dev/null | awk '/BD Address:/ {print $3; exit}')" @@ -1320,7 +1320,7 @@ btgetbdaddr() { return 0 fi fi - + # No logging here either, caller will log if needed. return 1 } @@ -1385,31 +1385,31 @@ bt_controller_visible() { # 2 = could not read BD address btensurepublicaddr() { dev="${1:-}" - + # Already visible: nothing to do. if btcontrollerpresent || bt_controller_visible "$dev"; then log_info "controller already visible via bluetoothctl, skip public-addr" return 0 fi - + mac="$( btgetbdaddr "$dev" 2>/dev/null \ | head -n 1 \ | awk '{print $NF}' )" - + if [ -z "$mac" ]; then log_warn "could not read bd address ${dev:+for $dev} public-addr cannot be applied" return 2 fi - + log_info "applying bluetoothctl public-addr $mac" - + btctl_script "menu mgmt public-addr $mac back quit" >/dev/null 2>&1 || true - + # Poll for controller visibility (BlueZ can be async) i=0 max_wait=15 # was 5; 15 is still small but avoids flakiness @@ -1421,7 +1421,7 @@ quit" >/dev/null 2>&1 || true sleep 1 i=$((i + 1)) done - + log_warn "controller still not visible after public-addr $mac (after ${max_wait}s)" return 1 } @@ -1433,12 +1433,12 @@ btcontrollervisible() { # btcontrollervisible 00:11:22:33:44:55 # # Returns: 0 if controller visible to bluetoothctl, else 1 - + arg="${1:-}" addr="" dev="" out="" - + # Normalize arg case "$arg" in hci[0-9]*) @@ -1453,7 +1453,7 @@ btcontrollervisible() { *) ;; esac - + btctlrun() { if command -v timeout >/dev/null 2>&1; then timeout 2 bluetoothctl "$@" 2>/dev/null || true @@ -1461,7 +1461,7 @@ btcontrollervisible() { bluetoothctl "$@" 2>/dev/null || true fi } - + # bluetoothctl list out="$(btctlrun list)" if [ -n "$out" ]; then @@ -1470,7 +1470,7 @@ btcontrollervisible() { fi printf '%s\n' "$out" | grep -q '^Controller ' && return 0 fi - + # bluetoothctl show out="$(btctlrun show)" if [ -n "$out" ]; then @@ -1479,7 +1479,7 @@ btcontrollervisible() { fi printf '%s\n' "$out" | grep -q '^Controller ' && return 0 fi - + return 1 } @@ -1493,19 +1493,19 @@ btcontrollervisible() { # 1 = still no controller visible bt_ensure_controller_visible() { adapter="${1:-}" - + # Fast path: already visible if btcontrollerpresent || bt_controller_visible "$adapter"; then return 0 fi - + # Try to guess adapter from sysfs if not provided if [ -z "$adapter" ]; then if findhcisysfs >/dev/null 2>&1; then adapter="$(findhcisysfs 2>/dev/null || true)" fi fi - + if [ -n "$adapter" ]; then log_info "Using adapter for public-addr/bootstrap: $adapter" btensurepublicaddr "$adapter" || \ @@ -1513,12 +1513,12 @@ bt_ensure_controller_visible() { else log_warn "No HCI adapter found in sysfs; cannot apply public-addr." fi - + # Final controller visibility check if btcontrollerpresent || bt_controller_visible "$adapter"; then return 0 fi - + return 1 } @@ -1794,7 +1794,7 @@ bt_pair_once() { # Prints one of: yes | no | unknown bt_get_discovering() { out="$(bluetoothctl show 2>/dev/null | sanitize_bt_output | tr -d '\r')" - + case "$out" in *"Discovering: yes"*) echo "yes" @@ -1884,7 +1884,7 @@ bt_scan_validate() { adapter="$1" target_mac="$2" # may be empty fail=0 - + # --- Ensure power ON --- initial_power="$(btgetpower "$adapter" 2>/dev/null || echo "unknown")" if [ "$initial_power" != "yes" ]; then @@ -1897,29 +1897,29 @@ bt_scan_validate() { else log_pass "Power ON verified before scan." fi - + if [ -n "$target_mac" ]; then log_info "Target MAC provided for BT_SCAN: $target_mac" else log_info "No target MAC provided, BT_SCAN will just verify that some devices are visible." fi - + # --- Scan ON phase --- log_info "Testing scan ON..." if ! bt_set_scan on; then log_warn "bt_set_scan(on) reported immediate failure; will still poll Discovering/devices." fi - + # Wait for Discovering=yes (best-effort) if bt_wait_discovering yes 10 2; then log_info "Observed Discovering=yes during scan ON window." else log_warn "Never observed Discovering=yes during scan ON polling window (may indicate stack/timing issue)." fi - + # Give a small extra window for devices to accumulate sleep 2 - + dev_out="$(bt_list_devices_raw)" if [ -n "$dev_out" ]; then log_info "Devices seen by bluetoothctl after scan ON:" @@ -1930,7 +1930,7 @@ bt_scan_validate() { else log_info "Devices seen by bluetoothctl after scan ON: (none)" fi - + if ! bt_devices_seen "$target_mac"; then if [ -n "$target_mac" ]; then log_fail "Target MAC $target_mac not found in 'bluetoothctl devices' after scan ON window." @@ -1946,19 +1946,19 @@ bt_scan_validate() { fi fail=0 fi - + # --- Scan OFF phase --- log_info "Testing scan OFF..." if ! bt_set_scan off; then log_warn "bt_set_scan(off) reported immediate failure; will still poll Discovering." fi - + if bt_wait_discovering no 10 2; then log_pass "Discovering=no observed after scan OFF polling." else log_warn "Did not observe Discovering=no within timeout after scan OFF." fi - + return "$fail" } @@ -2016,7 +2016,7 @@ btgetpower() { dev="${1-}" state="" mac="" - + # If a specific adapter is provided (e.g. hci0), resolve to BDADDR and use "show " # because "select hci0" is unreliable on some minimal/ramdisk setups. if [ -n "$dev" ]; then @@ -2026,7 +2026,7 @@ btgetpower() { | awk '{print $NF}' )" fi - + if [ -n "$mac" ]; then out="$( { @@ -2044,7 +2044,7 @@ btgetpower() { } | bluetoothctl 2>/dev/null | sanitize_bt_output || true )" fi - + state="$(printf '%s\n' "$out" \ | awk -F':[[:space:]]*' ' /^[[:space:]]*Powered:/ { @@ -2055,7 +2055,7 @@ btgetpower() { exit } ')" - + # Fallback: try default controller if adapter-specific attempt didn’t yield Powered: if [ -z "$state" ]; then out="$( @@ -2076,14 +2076,14 @@ btgetpower() { } ')" fi - + [ -n "$state" ] || return 2 - + if [ "$state" = "yes" ] || [ "$state" = "no" ]; then printf '%s\n' "$state" return 0 fi - + return 2 } # Usage: btpower hci0 on|off @@ -2094,7 +2094,7 @@ btgetpower() { btpower() { dev="${1:-}" want="${2:-}" - + case "$want" in on|off) ;; @@ -2103,45 +2103,45 @@ btpower() { return 1 ;; esac - + cur_state="$(btgetpower "$dev" 2>/dev/null || true)" [ -z "$cur_state" ] && cur_state="unknown" - + if [ "$want" = "on" ] && [ "$cur_state" = "yes" ]; then log_info "btpower: $dev already Powered=yes; skipping 'power on'." return 0 fi - + if [ "$want" = "off" ] && [ "$cur_state" = "no" ]; then log_info "btpower: $dev already Powered=no; skipping 'power off'." return 0 fi - + log_info "btpower: requesting '$want' on $dev (current=$cur_state)" - + # Drive bluetoothctl interactively (works on ramdisk where non-interactive list/show may be empty) # Do NOT use "select hci0" (it can say "Controller hci0 not available" even when controller exists). btctl_script "power $want" "quit" >/dev/null 2>&1 || true - + i=0 max_tries=10 state="" pstate="" - + while [ "$i" -lt "$max_tries" ]; do # Read Powered via btgetpower (must be interactive-based implementation) state="$(btgetpower "$dev" 2>/dev/null || true)" - + if [ "$want" = "on" ] && [ "$state" = "yes" ]; then log_info "btpower: $dev Powered=yes after request." return 0 fi - + if [ "$want" = "off" ] && [ "$state" = "no" ]; then log_info "btpower: $dev Powered=no after request." return 0 fi - + # If Powered line is not available yet, try to parse PowerState as an informational fallback # (Some stacks lag on Powered; PowerState can show transitions like off-enabling/on-disabling.) out="$( @@ -2151,7 +2151,7 @@ btpower() { printf 'quit\n' } | bluetoothctl 2>/dev/null | sanitize_bt_output || true )" - + pstate="$(printf '%s\n' "$out" \ | awk -F':[[:space:]]*' ' /^[[:space:]]*PowerState:/ { @@ -2161,18 +2161,18 @@ btpower() { print v; exit }')" - + # If Powered was empty but PowerState suggests we reached a stable end state, # keep waiting a little more for Powered to update (do not treat pstate as PASS alone). sleep 1 i=$((i + 1)) done - + if [ -z "$state" ]; then log_warn "btpower: unable to read Powered state for $dev after request. (PowerState last='$pstate')" return 2 fi - + log_warn "btpower: $dev state after request is '$state' (wanted $want). (PowerState last='$pstate')" return 1 } @@ -2181,10 +2181,10 @@ btfwpresent() { dir="" pattern="" file="" - + for d in /lib/firmware/qca /usr/lib/firmware/qca /lib/firmware /usr/lib/firmware; do [ -d "$d" ] || continue - + for pattern in \ "msbtfw*.mbn" \ "msbtfw*.tlv" \ @@ -2207,7 +2207,7 @@ btfwpresent() { done done done - + return 1 } @@ -2216,14 +2216,14 @@ bt_wait_ready() { sleep_step="${2:-2}" waited=0 started_service=0 - + if [ -z "$max_wait" ]; then max_wait=60 fi if [ -z "$sleep_step" ]; then sleep_step=2 fi - + case "$max_wait" in ''|*[!0-9]*) max_wait=60 @@ -2234,20 +2234,20 @@ bt_wait_ready() { sleep_step=2 ;; esac - + if [ "$max_wait" -le 0 ] 2>/dev/null; then max_wait=60 fi if [ "$sleep_step" -le 0 ] 2>/dev/null; then sleep_step=2 fi - + while [ "$waited" -lt "$max_wait" ]; do if btsvcactive && bthcipresent; then log_info "Bluetooth runtime became ready after ${waited}s." return 0 fi - + if [ "$started_service" -eq 0 ]; then if command -v systemctl >/dev/null 2>&1; then if ! btsvcactive; then @@ -2257,11 +2257,11 @@ bt_wait_ready() { fi started_service=1 fi - + sleep "$sleep_step" waited=$((waited + sleep_step)) done - + log_warn "Bluetooth runtime did not become ready within ${max_wait}s." return 1 } @@ -2435,7 +2435,7 @@ bt_scan_poll_on() { if [ "$disc_state" = "yes" ]; then seen_disc_yes=1 fi - + devices_out="$(bt_list_devices_raw || true)" devices_snapshot="$devices_out" diff --git a/Runner/utils/lib_connectivity.sh b/Runner/utils/lib_connectivity.sh index d657cbd2..106424ae 100755 --- a/Runner/utils/lib_connectivity.sh +++ b/Runner/utils/lib_connectivity.sh @@ -20,27 +20,27 @@ wait_for_wifi_interface() { waited=0 iface="" settle_done=0 - + case "$max_wait" in ''|*[!0-9]*) max_wait=60 ;; esac - + case "$sleep_step" in ''|*[!0-9]*) sleep_step=2 ;; esac - + if [ "$max_wait" -le 0 ] 2>/dev/null; then max_wait=60 fi - + if [ "$sleep_step" -le 0 ] 2>/dev/null; then sleep_step=2 fi - + # Keep stdout reserved only for the detected interface name because callers # commonly use command substitution: # wifi_iface="$(wait_for_wifi_interface ...)" @@ -48,24 +48,24 @@ wait_for_wifi_interface() { # All diagnostics must go to stderr to avoid contaminating the returned # interface name. log_info "Waiting up to ${max_wait}s for WiFi interface creation" >&2 - + while [ "$waited" -lt "$max_wait" ]; do wifi_unblock_rfkill - + iface="$(get_wifi_interface 2>/dev/null || true)" if [ -n "$iface" ]; then printf '%s\n' "$iface" return 0 fi - + if [ "$settle_done" -eq 0 ]; then settle_done=1 - + if command -v udevadm >/dev/null 2>&1; then log_info "No WiFi interface yet; triggering net add uevents and waiting for udev settle" >&2 udevadm trigger --action=add --subsystem-match=net >/dev/null 2>&1 || true udevadm settle --timeout=5 >/dev/null 2>&1 || true - + iface="$(get_wifi_interface 2>/dev/null || true)" if [ -n "$iface" ]; then printf '%s\n' "$iface" @@ -73,15 +73,15 @@ wait_for_wifi_interface() { fi fi fi - + sleep "$sleep_step" waited=$((waited + sleep_step)) - + if [ "$waited" -gt 0 ] && [ $((waited % 10)) -eq 0 ]; then log_info "Still waiting for WiFi interface... waited=${waited}s/${max_wait}s" >&2 fi done - + return 1 } @@ -96,16 +96,16 @@ wifi_dt_present() { wifi_log_module_info() { mod="" mod_path="" - + for mod in "$@"; do [ -n "$mod" ] || continue - + if is_module_loaded "$mod"; then log_pass "Module loaded: $mod" else log_info "Module not loaded: $mod" fi - + mod_path="$(find_kernel_module "$mod" 2>/dev/null | awk '/^\// { print; exit }' || true)" if [ -n "$mod_path" ]; then log_info "[module-path] $mod -> $mod_path" @@ -492,7 +492,7 @@ wifi_firmware_loaded() { return 1 ;; esac - + matches="$(get_kernel_log 2>/dev/null | grep -Ei "$pattern" | \ grep -Eiv 'failed|failure|error|timeout|unable|crash|fatal|Modules linked in' | tail -n 40 || true)" diff --git a/Runner/utils/lib_display.sh b/Runner/utils/lib_display.sh index dff2cfad..a04a0bf1 100755 --- a/Runner/utils/lib_display.sh +++ b/Runner/utils/lib_display.sh @@ -86,7 +86,7 @@ display__debugfs_mode_for_crtc_name() { crtc_name="$2" [ -r "$st" ] || return 1 [ -n "$crtc_name" ] || return 1 - + awk -v want="$crtc_name" ' function is_hz(x){ v=x+0.0; return (v>=20.0 && v<=240.0) } $0 ~ /^crtc\[[0-9]+\]:/ { @@ -264,11 +264,11 @@ display_connected_summary() { display_debug_snapshot() { ds_tag="$1" [ -n "$ds_tag" ] || ds_tag="snapshot" - + log_info "----- Display snapshot: $ds_tag -----" - + debugfs_try_mount >/dev/null 2>&1 || true - + if [ -d /dev/dri ]; then ds_nodes="" set -- /dev/dri/* @@ -282,27 +282,27 @@ display_debug_snapshot() { else log_warn "/dev/dri not present" fi - + ds_base="/sys/class/drm" if [ -d "$ds_base" ]; then for ds_path in "$ds_base"/card*-*; do [ -e "$ds_path" ] || continue ds_name=$(basename "$ds_path") - + case "$ds_name" in renderD*|card[0-9]) continue ;; esac - + ds_status="unknown" if [ -r "$ds_path/status" ]; then ds_status=$(tr -d '[:space:]' 2>/dev/null <"$ds_path/status") fi - + ds_enabled="unknown" if [ -r "$ds_path/enabled" ]; then ds_enabled=$(tr -d '[:space:]' 2>/dev/null <"$ds_path/enabled") fi - + ds_ctype="Other" case "$ds_name" in *HDMI*) ds_ctype="HDMI-A" ;; @@ -310,7 +310,7 @@ display_debug_snapshot() { *DP*) ds_ctype="DP" ;; *LVDS*) ds_ctype="LVDS" ;; esac - + ds_nmodes=0 ds_first_mode="" if [ -r "$ds_path/modes" ]; then @@ -319,19 +319,19 @@ display_debug_snapshot() { [ -n "$ds_first_mode" ] || ds_first_mode="" [ -n "$ds_nmodes" ] || ds_nmodes=0 fi - + ds_cur="$(display_connector_cur_mode "$ds_name" 2>/dev/null || true)" [ -n "$ds_cur" ] || ds_cur="-" - + log_info "DRM: $ds_name status=$ds_status enabled=$ds_enabled type=$ds_ctype modes=$ds_nmodes first=$ds_first_mode cur=$ds_cur" done else log_warn "display_debug_snapshot: $ds_base not found" fi - + ds_summary=$(display_connected_summary) log_info "Connected summary (sysfs): $ds_summary" - + log_info "----- End display snapshot: $ds_tag -----" return 0 } @@ -769,27 +769,27 @@ weston_wait_ready() { # Starts socket/service first, then falls back to weston_start, and waits until ready. weston_restore_runtime() { timeout="${1:-15}" - + if command -v weston_is_running >/dev/null 2>&1; then if weston_is_running >/dev/null 2>&1 && weston_runtime_socket_exists; then return 0 fi fi - + if command -v systemctl >/dev/null 2>&1; then systemctl start weston.socket >/dev/null 2>&1 || true systemctl start weston.service >/dev/null 2>&1 || \ systemctl start weston@root.service >/dev/null 2>&1 || true fi - + if weston_wait_ready 3; then return 0 fi - + if command -v weston_start >/dev/null 2>&1; then weston_start >/dev/null 2>&1 || true fi - + weston_wait_ready "$timeout" } @@ -916,43 +916,43 @@ weston_ini_force_primary_1080p60_if_not_60() { weston_get_primary_refresh_hz() { primary_sysfs=$(display_select_primary_connector 2>/dev/null || true) [ -n "$primary_sysfs" ] || return 1 - + mode=$(display_connector_cur_mode "$primary_sysfs" 2>/dev/null || true) [ -n "$mode" ] || return 1 - + hz=$(printf '%s\n' "$mode" | awk -F@ 'NF>=2{print $2; exit 0}') [ -n "$hz" ] || return 1 - + printf '%s\n' "$hz" } display_cur_size_from_state_msm() { state="$(display_find_dri_state_file 2>/dev/null || true)" - + if [ -z "$state" ] || [ ! -r "$state" ]; then echo "-" return 0 fi - + awk ' BEGIN { good=0; crtc=0; fb=0; sz=""; } - + /^plane\[/ { good=0; crtc=0; fb=0; sz=""; next } - + /allocated by[[:space:]]*=/ { good=1; next } - + /^[[:space:]]*crtc=crtc-/ { if ($0 !~ /\(null\)/) crtc=1 next } - + /^[[:space:]]*fb=/ { s=$0 sub(/^[[:space:]]*fb=/, "", s) fb = s + 0 next } - + /^[[:space:]]*size=/ { s=$0 sub(/^[[:space:]]*size=/, "", s) @@ -961,7 +961,7 @@ display_cur_size_from_state_msm() { if (good && crtc && fb > 0 && sz != "") { print sz; exit 0 } next } - + /^[[:space:]]*dst\[0\]=/ { s=$0 sub(/^[[:space:]]*dst\[0\]=/, "", s) @@ -971,32 +971,32 @@ display_cur_size_from_state_msm() { } next } - + END { if (sz != "") print sz; else print "-"; }' "$state" 2>/dev/null } - + display_connector_cur_mode() { sysfs_name="$1" [ -n "$sysfs_name" ] || { echo "-"; return 0; } - + debugfs_try_mount >/dev/null 2>&1 || true - + idx=$(printf '%s\n' "$sysfs_name" | sed -n 's/^card\([0-9][0-9]*\)-.*/\1/p') case "$idx" in ""|*[!0-9]*) echo "-"; return 0 ;; esac - + st="/sys/kernel/debug/dri/$idx/state" if [ ! -r "$st" ]; then echo "-" return 0 fi - + prefix="card${idx}-" cname=${sysfs_name#"$prefix"} [ -n "$cname" ] || { echo "-"; return 0; } - + awk -v want="$cname" ' function first_hz(line, i, v) { for (i=1; i<=NF; i++) { @@ -1007,44 +1007,44 @@ display_connector_cur_mode() { } return "" } - + BEGIN { cur_crtc_id=""; cur_crtc_name=""; in_crtc=0; in_conn=0; target_crtc_name=""; target_crtc_id=""; } - + # -------- CRTC blocks (come earlier in your file) -------- /^[[:space:]]*crtc\[[0-9]+\]:/ { in_crtc=1 - + line=$0 sub(/^[[:space:]]*crtc\[/, "", line) cur_crtc_id=line sub(/\].*$/, "", cur_crtc_id) - + cur_crtc_name=$0 sub(/^[[:space:]]*crtc\[[0-9]+\]:[[:space:]]*/, "", cur_crtc_name) next } - + in_crtc && $1=="mode:" { res=$2 gsub(/"/, "", res) sub(/:$/, "", res) hz=first_hz($0) - + if (res ~ /^[0-9]+x[0-9]+$/ && hz != "") { mode_by_id[cur_crtc_id] = res "@" hz mode_by_name[cur_crtc_name] = res "@" hz } next } - + # stop CRTC block when next top-level block starts in_crtc && /^[[:space:]]*[A-Za-z_]+\[[0-9]+\]:/ && $0 !~ /^[[:space:]]*crtc\[/ { in_crtc=0 } - + # -------- Connector blocks -------- /^[[:space:]]*connector\[[0-9]+\]:/ { in_conn=0 @@ -1053,7 +1053,7 @@ display_connector_cur_mode() { if (conn_name == want) in_conn=1 next } - + in_conn { # your format: "crtc=crtc-0" or "crtc=(null)" if ($0 ~ /^[[:space:]]*crtc=/) { @@ -1065,7 +1065,7 @@ display_connector_cur_mode() { } next } - + END { if (target_crtc_name != "" && (target_crtc_name in mode_by_name)) { print mode_by_name[target_crtc_name] @@ -1269,18 +1269,18 @@ egli_glvnd_icd_from_json() { # Prints the value (e.g., libEGL_adreno.so.1) or empty on failure. f="$1" [ -r "$f" ] || { printf '%s\n' ""; return 0; } - + # Match a line containing "library_path" : "...." # Keep it resilient to whitespace. sed -n 's/.*"library_path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$f" | head -n 1 } - + egli_derive_driver_name() { # Best-effort for log readability only. # Inputs: gl_vendor gl_renderer v="$1" r="$2" - + # Qualcomm/Adreno path if printf '%s %s\n' "$v" "$r" | grep -Eqi '(qualcomm|adreno)'; then icd="" @@ -1294,7 +1294,7 @@ egli_derive_driver_name() { printf '%s\n' "adreno" return 0 fi - + # Mesa path if printf '%s %s\n' "$v" "$r" | grep -Eqi '(mesa|llvmpipe|softpipe|swrast|lavapipe)'; then icd="" @@ -1308,7 +1308,7 @@ egli_derive_driver_name() { printf '%s\n' "mesa" return 0 fi - + printf '%s\n' "unknown" return 0 } @@ -1396,7 +1396,7 @@ egli_classify_pipeline() { egli_wayland_socket_ok() { wd="${WAYLAND_DISPLAY:-}" [ -n "$wd" ] || return 1 - + case "$wd" in /*) [ -S "$wd" ] && return 0 @@ -1408,12 +1408,12 @@ egli_wayland_socket_ok() { [ -S "$xrd/$wd" ] && return 0 return 1 fi - + # Fallbacks when XDG_RUNTIME_DIR is unset (common in minimal shells) [ -S "/run/user/0/$wd" ] && return 0 [ -S "/run/user/1000/$wd" ] && return 0 [ -S "/run/$wd" ] && return 0 - + return 1 ;; esac diff --git a/Runner/utils/lib_gstreamer.sh b/Runner/utils/lib_gstreamer.sh index d852bbf4..18c7df12 100755 --- a/Runner/utils/lib_gstreamer.sh +++ b/Runner/utils/lib_gstreamer.sh @@ -74,7 +74,7 @@ gstreamer_shared_artifact_dir() { gstreamer_shared_encoded_dir() { script_dir="$1" outdir="$2" - + gstreamer_shared_artifact_dir "VIDEO_SHARED_ENCODE_DIR" "video-encode-decode" "encoded" "$script_dir" "$outdir" } @@ -88,7 +88,7 @@ gstreamer_shared_encoded_dir() { gstreamer_shared_recorded_dir() { script_dir="$1" outdir="$2" - + gstreamer_shared_artifact_dir "AUDIO_SHARED_RECORDED_DIR" "audio-record-playback" "recorded" "$script_dir" "$outdir" } # -------------------- Element check -------------------- @@ -835,10 +835,10 @@ gstreamer_resolution_to_wh() { printf '%s %s\n' "640" "480" # Default resolution if none provided return 0 } - + # Convert to lowercase for case-insensitive matching res=$(printf '%s' "$res" | tr '[:upper:]' '[:lower:]') - + case "$res" in 480p) printf '%s %s\n' "640" "480" @@ -933,7 +933,7 @@ gstreamer_v4l2_decoder_for_codec() { # This standardizes container format selection across encode/decode operations: # - H.264/H.265: mp4 container (ISO BMFF/MP4) - encode & decode supported # - VP9: webm container (WebM) - decode-only -# +# # The encode pipeline builders (gstreamer_build_v4l2_encode_pipeline) use # appropriate muxers (mp4mux for H.264/H.265). VP9 encoding is not supported. # The decode pipeline builders (gstreamer_build_v4l2_decode_pipeline) use @@ -965,7 +965,7 @@ gstreamer_container_ext_for_codec() { gstreamer_bitrate_for_resolution() { width="$1" height="$2" - + # Default bitrate calculation bitrate=8000000 if [ "$width" -le 640 ]; then @@ -975,7 +975,7 @@ gstreamer_bitrate_for_resolution() { elif [ "$width" -le 1920 ]; then bitrate=4000000 fi - + printf '%s\n' "$bitrate" } @@ -984,9 +984,9 @@ gstreamer_bitrate_for_resolution() { # Prints: file size in bytes or 0 if file doesn't exist gstreamer_file_size_bytes() { filepath="$1" - + [ -f "$filepath" ] || { printf '%s\n' "0"; return 1; } - + # Try BSD stat first, then GNU stat file_size=$(stat -f%z "$filepath" 2>/dev/null || stat -c%s "$filepath" 2>/dev/null || echo 0) printf '%s\n' "$file_size" @@ -1005,22 +1005,22 @@ gstreamer_build_v4l2_encode_pipeline() { bitrate="$6" output_file="$7" video_stack="${8:-upstream}" - + # Validate numeric parameters case "$duration" in ''|*[!0-9]*) duration=30 ;; # Default 30s for invalid/non-numeric duration esac - + case "$framerate" in ''|*[!0-9]*) framerate=30 ;; # Default 30fps for invalid/non-numeric framerate esac - + encoder=$(gstreamer_v4l2_encoder_for_codec "$codec") if [ -z "$encoder" ]; then printf '%s\n' "" return 1 fi - + # Determine parser based on codec case "$codec" in h264) @@ -1033,13 +1033,13 @@ gstreamer_build_v4l2_encode_pipeline() { parser="" ;; esac - + # Build encoder parameters encoder_params="extra-controls=\"controls,video_bitrate=${bitrate}\"" if [ "$video_stack" = "downstream" ]; then encoder_params="${encoder_params} capture-io-mode=4 output-io-mode=4" fi - + # Calculate total frames with numeric safety total_frames=0 if [ "$duration" -gt 0 ] 2>/dev/null && [ "$framerate" -gt 0 ] 2>/dev/null; then @@ -1054,7 +1054,7 @@ gstreamer_build_v4l2_encode_pipeline() { else printf '%s\n' "videotestsrc num-buffers=${total_frames} pattern=smpte ! video/x-raw,width=${width},height=${height},format=NV12,framerate=${framerate}/1 ! ${encoder} ${encoder_params} ! mp4mux ! filesink location=${output_file}" fi - + return 0 } @@ -1066,13 +1066,13 @@ gstreamer_build_v4l2_decode_pipeline() { codec="$1" input_file="$2" video_stack="${3:-upstream}" - + decoder=$(gstreamer_v4l2_decoder_for_codec "$codec") if [ -z "$decoder" ]; then printf '%s\n' "" return 1 fi - + # Determine parser and container based on codec case "$codec" in h264) @@ -1093,13 +1093,13 @@ gstreamer_build_v4l2_decode_pipeline() { container="matroskademux" ;; esac - + # Build decoder parameters decoder_params="" if [ "$video_stack" = "downstream" ]; then decoder_params="capture-io-mode=4 output-io-mode=4" fi - + # Build pipeline based on parser availability # All supported formats (h264, h265, vp9) have containers (MP4 or WebM) if [ -n "$parser" ]; then @@ -1117,7 +1117,7 @@ gstreamer_build_v4l2_decode_pipeline() { printf '%s\n' "filesrc location=${input_file} ! ${container} ! ${decoder} ! videoconvert ! fakesink" fi fi - + return 0 } @@ -1462,10 +1462,10 @@ camera_build_qtiqmmfsrc_fakesink_pipeline() { width="$3" height="$4" framerate="$5" - + gst_format=$(camera_format_to_gst_string "$format") [ -z "$gst_format" ] && return 1 - + if [ "$format" = "ubwc" ]; then printf '%s\n' "qtiqmmfsrc camera=${camera_id} name=camsrc ! video/x-raw,format=${gst_format},width=${width},height=${height},framerate=${framerate}/1,interlace-mode=progressive,colorimetry=bt601 ! queue ! fakesink" else @@ -1482,10 +1482,10 @@ camera_build_qtiqmmfsrc_preview_pipeline() { width="$3" height="$4" framerate="$5" - + gst_format=$(camera_format_to_gst_string "$format") [ -z "$gst_format" ] && return 1 - + if [ "$format" = "ubwc" ]; then printf '%s\n' "qtiqmmfsrc camera=${camera_id} name=camsrc ! video/x-raw,format=${gst_format},width=${width},height=${height},framerate=${framerate}/1 ! waylandsink fullscreen=true async=true sync=false" else @@ -1503,10 +1503,10 @@ camera_build_qtiqmmfsrc_encode_pipeline() { height="$4" framerate="$5" output_file="$6" - + gst_format=$(camera_format_to_gst_string "$format") [ -z "$gst_format" ] && return 1 - + if [ "$format" = "ubwc" ]; then printf '%s\n' "qtiqmmfsrc camera=${camera_id} name=camsrc ! video/x-raw,format=${gst_format},width=${width},height=${height},framerate=${framerate}/1,interlace-mode=progressive,colorimetry=bt601 ! queue ! v4l2h264enc capture-io-mode=4 output-io-mode=5 ! h264parse ! mp4mux ! queue ! filesink location=${output_file}" else @@ -1532,7 +1532,7 @@ camera_build_qtiqmmfsrc_snapshot_pipeline() { framerate="$4" output_location="$5" max_files="${6:-2}" - + printf '%s\n' "qtiqmmfsrc camera=${camera_id} name=camsrc ! capsfilter caps=\"video/x-raw,format=NV12,width=${width},height=${height},framerate=${framerate}/1\" ! jpegenc ! multifilesink location=\"${output_location}\" max-files=${max_files}" } @@ -1548,7 +1548,7 @@ camera_build_libcamera_fakesink_pipeline() { width="$1" height="$2" framerate="${3:-30}" - + # If width/height are 0 or empty, build pipeline without caps filter if [ -z "$width" ] || [ -z "$height" ] || [ "$width" -eq 0 ] 2>/dev/null || [ "$height" -eq 0 ] 2>/dev/null; then printf '%s\n' "libcamerasrc ! fakesink" @@ -1568,7 +1568,7 @@ camera_build_libcamera_preview_pipeline() { width="$1" height="$2" framerate="${3:-30}" - + # If width/height are 0 or empty, build pipeline without caps filter if [ -z "$width" ] || [ -z "$height" ] || [ "$width" -eq 0 ] 2>/dev/null || [ "$height" -eq 0 ] 2>/dev/null; then printf '%s\n' "libcamerasrc ! videoconvert ! waylandsink fullscreen=true" @@ -1590,7 +1590,7 @@ camera_build_libcamera_encode_pipeline() { height="$2" output_file="$3" framerate="${4:-30}" - + printf '%s\n' "libcamerasrc ! videoconvert ! video/x-raw,format=NV12,width=${width},height=${height},framerate=${framerate}/1 ! v4l2h264enc capture-io-mode=4 output-io-mode=4 ! h264parse ! mp4mux ! filesink location=${output_file}" } @@ -1608,7 +1608,7 @@ camera_build_libcamera_snapshot_pipeline() { height="$2" output_location="$3" max_files="${4:-5}" - + printf '%s\n' "libcamerasrc name=camsrc src_1::stream-role=still-capture ! video/x-raw,width=${width},height=${height} ! videoconvert ! jpegenc ! multifilesink location=\"${output_location}\" max-files=${max_files}" } @@ -1621,10 +1621,10 @@ camera_build_libcamera_snapshot_pipeline() { # Returns: 0 if Wayland is ready, 1 otherwise camera_setup_wayland_environment() { test_name="${1:-Camera_Test}" - + wayland_ready=0 sock="" - + # Try to find existing Wayland socket if command -v discover_wayland_socket_anywhere >/dev/null 2>&1; then sock=$(discover_wayland_socket_anywhere | head -n 1 || true) @@ -1638,7 +1638,7 @@ camera_setup_wayland_environment() { fi fi fi - + # Try starting Weston if no socket found if [ "$wayland_ready" -eq 0 ] && [ -z "$sock" ]; then if command -v weston_pick_env_or_start >/dev/null 2>&1; then @@ -1659,7 +1659,7 @@ camera_setup_wayland_environment() { fi fi fi - + # Verify Wayland connection if [ "$wayland_ready" -eq 1 ] || [ -n "${WAYLAND_DISPLAY:-}" ]; then if command -v wayland_connection_ok >/dev/null 2>&1; then @@ -1676,9 +1676,9 @@ camera_setup_wayland_environment() { log_info "Wayland environment set (WAYLAND_DISPLAY=${WAYLAND_DISPLAY})" fi fi - + # Export wayland_ready for caller export wayland_ready - + return $((1 - wayland_ready)) } diff --git a/Runner/utils/lib_performance.sh b/Runner/utils/lib_performance.sh index 456efe56..f0d18fc5 100755 --- a/Runner/utils/lib_performance.sh +++ b/Runner/utils/lib_performance.sh @@ -951,18 +951,18 @@ perf_baseline_get() { key=$1 file=$2 [ -f "$file" ] || { echo ""; return 0; } - + awk -v k="$key" ' { line=$0 sub(/^[ \t]*/, "", line) - + # exact prefix match on key (string compare, not regex) kl = length(k) if (substr(line, 1, kl) != k) next - + rest = substr(line, kl + 1) - + # allow optional spaces then ":" or "=" then optional spaces if (rest ~ /^[ \t]*[=:][ \t]*/) { sub(/^[ \t]*[=:][ \t]*/, "", rest) @@ -1088,7 +1088,7 @@ run_sysbench_case() { sysbench_mib_to_mb() { v=$1 [ -z "$v" ] && { echo ""; return 0; } - + if command -v perf_f_mul >/dev/null 2>&1; then perf_f_mul "$v" "1.048576" else @@ -1486,11 +1486,11 @@ perf_sysbench_csv_append() { perf_baseline_get_value() { f=$1 key=$2 - + [ -n "$f" ] || return 0 [ -f "$f" ] || return 0 [ -n "$key" ] || return 0 - + awk -v k="$key" ' /^[[:space:]]*#/ {next} /^[[:space:]]*$/ {next} @@ -1548,12 +1548,12 @@ perf_f_le() { awk -v a="$1" -v b="$2" 'BEGIN{exit !((a+0) <= (b+0))}'; } # - time_sec: lower is better perf_metric_direction() { m=$1 - + # Lower is better only for explicit time metrics case "$m" in *time_sec*) echo "lower"; return 0 ;; esac - + # Everything else (mem_mbps, fileio_*_mbps, etc.) is higher-is-better echo "higher" return 0 @@ -1566,12 +1566,12 @@ perf_metric_direction() { perf_sysbench_baseline_get() { file=$1 key=$2 - + [ -f "$file" ] || { printf '%s' ""; return 0; } [ -n "$key" ] || { printf '%s' ""; return 0; } - + key_esc=$(perf_sed_escape_bre "$key") - + # Match "key = value" (value is first token-ish number) v=$( sed -n \ @@ -1608,30 +1608,30 @@ perf_sysbench_gate_eval() { metric=$4 value=$5 delta=$6 - + PERF_GATE_KEY="${case_name}_${metric}.t${threads}" PERF_GATE_OP="" PERF_GATE_BASELINE="" PERF_GATE_GOAL="" PERF_GATE_SCORE_PCT="" PERF_GATE_STATUS="SKIP" - + # Export for external consumers (run.sh) → fixes SC2034 export PERF_GATE_KEY PERF_GATE_OP PERF_GATE_BASELINE PERF_GATE_GOAL PERF_GATE_SCORE_PCT PERF_GATE_STATUS - + [ -f "$file" ] || return 2 [ -n "$case_name" ] || return 2 [ -n "$threads" ] || return 2 [ -n "$metric" ] || return 2 [ -n "$value" ] || return 2 [ -n "$delta" ] || delta=0 - + base=$(perf_sysbench_baseline_get "$file" "$PERF_GATE_KEY") [ -n "$base" ] || return 2 - + PERF_GATE_BASELINE="$base" export PERF_GATE_BASELINE - + # Decide direction: # - Throughput (mem_mbps): higher is better # - time_sec: lower is better @@ -1639,7 +1639,7 @@ perf_sysbench_gate_eval() { if [ "$metric" = "mem_mbps" ] || echo "$metric" | grep -q "mbps"; then higher_is_better=1 fi - + if [ "$higher_is_better" -eq 1 ]; then PERF_GATE_OP=">=" goal=$(awk -v b="$base" -v d="$delta" 'BEGIN{printf "%.6f", (b*(1-d))}') @@ -1647,7 +1647,7 @@ perf_sysbench_gate_eval() { score=$(awk -v b="$base" -v v="$value" 'BEGIN{ if (b==0) print ""; else printf "%.2f", (v/b*100) }') PERF_GATE_SCORE_PCT="$score" export PERF_GATE_OP PERF_GATE_GOAL PERF_GATE_SCORE_PCT - + pass=$(awk -v v="$value" -v g="$goal" 'BEGIN{print (v+0 >= g+0) ? 1 : 0}') else PERF_GATE_OP="<=" @@ -1657,16 +1657,16 @@ perf_sysbench_gate_eval() { score=$(awk -v b="$base" -v v="$value" 'BEGIN{ if (v==0) print ""; else printf "%.2f", (b/v*100) }') PERF_GATE_SCORE_PCT="$score" export PERF_GATE_OP PERF_GATE_GOAL PERF_GATE_SCORE_PCT - + pass=$(awk -v v="$value" -v g="$goal" 'BEGIN{print (v+0 <= g+0) ? 1 : 0}') fi - + if [ "$pass" -eq 1 ]; then PERF_GATE_STATUS="PASS" export PERF_GATE_STATUS return 0 fi - + PERF_GATE_STATUS="FAIL" export PERF_GATE_STATUS return 1 @@ -1705,21 +1705,21 @@ perf_sysbench_gate_eval_line() { metric=$4 avg=$5 delta=$6 - + if [ -z "$avg" ]; then echo "status=NO_AVG baseline=NA goal=NA op=NA score_pct=NA key=NA" return 2 fi - + key=$(perf_sysbench_baseline_key "$sb_case" "$metric" "$thr") base=$(perf_baseline_get_value "$f" "$key") if [ -z "$base" ]; then echo "status=NO_BASELINE baseline=NA goal=NA op=NA score_pct=NA key=$key" return 2 fi - + dir=$(perf_metric_direction "$metric") - + if [ "$dir" = "higher" ]; then one_minus=$(perf_f_sub "1.0" "$delta") goal=$(perf_f_mul "$base" "$one_minus") @@ -1731,7 +1731,7 @@ perf_sysbench_gate_eval_line() { echo "status=FAIL baseline=$base goal=$goal op=>= score_pct=${score:-NA} key=$key" return 1 fi - + # lower-is-better one_plus=$(perf_f_add "1.0" "$delta") goal=$(perf_f_mul "$base" "$one_plus") @@ -1821,30 +1821,30 @@ perf_sysbench_fileio_prepare() { iomode=$7 extra=$8 out_log=$9 - + [ -n "$dir" ] || return 1 mkdir -p "$dir" 2>/dev/null || true - + ( cd "$dir" 2>/dev/null || exit 1 - + set -- sysbench --rand-seed="$seed" --threads="$threads" fileio \ --file-total-size="$total" \ --file-num="$num" \ --file-block-size="$blksz" \ --file-io-mode="$iomode" \ --file-test-mode=seqwr - + if [ -n "$extra" ]; then # shellcheck disable=SC2086 set -- "$@" $extra fi - + set -- "$@" prepare perf_run_cmd_tee "$out_log" "$@" ) } - + perf_sysbench_fileio_cleanup() { dir=$1 total=$2 @@ -1852,30 +1852,30 @@ perf_sysbench_fileio_cleanup() { blksz=$4 iomode=$5 extra=$6 - + [ -n "$dir" ] || return 0 - + ( cd "$dir" 2>/dev/null || exit 0 - + set -- sysbench fileio \ --file-total-size="$total" \ --file-num="$num" \ --file-block-size="$blksz" \ --file-io-mode="$iomode" \ --file-test-mode=seqwr - + if [ -n "$extra" ]; then # shellcheck disable=SC2086 set -- "$@" $extra fi - + set -- "$@" cleanup "$@" >/dev/null 2>&1 || true ) return 0 } - + # Runs one fileio mode and prints one line of kv tokens: # mode=seqwr mibps=0.40 gbps=0.0004 perf_sysbench_fileio_run_mode() { @@ -1890,28 +1890,28 @@ perf_sysbench_fileio_run_mode() { extra=$9 mode=${10} out_log=${11} - + [ -n "$dir" ] || { echo ""; return 1; } - + ( cd "$dir" 2>/dev/null || exit 1 - + set -- sysbench --time="$time" --rand-seed="$seed" --threads="$threads" fileio \ --file-total-size="$total" \ --file-num="$num" \ --file-block-size="$blksz" \ --file-io-mode="$iomode" \ --file-test-mode="$mode" - + if [ -n "$extra" ]; then # shellcheck disable=SC2086 set -- "$@" $extra fi - + set -- "$@" run perf_run_cmd_tee "$out_log" "$@" ) || true - + case "$mode" in seqrd) r=$(perf_sysbench_parse_fileio_read_mibps "$out_log") @@ -2100,7 +2100,7 @@ tiotest_extract_mbps() { # Args: (ex: "Write" or "Read") logf=$1 lbl=$2 - + awk -v lbl="$lbl" ' BEGIN{v=""} /^[[:space:]]*\|/ && $0 ~ lbl { @@ -2146,13 +2146,13 @@ tiotest_extract_iops() { tiotest_extract_latency_block() { logf=$1 item=$2 # "Write" / "Read" / "Random Write" / "Random Read" - + awk -v item="$item" ' BEGIN { inblk=0; la=""; lm=""; p2=""; p10="" } - + /^Tiotest latency results/ { inblk=1; next } inblk==1 && /^`/ { inblk=0 } # end of ascii table (best-effort) - + # Match the latency row for the requested item inblk==1 && $0 ~ /^\|/ && $0 ~ ("|[[:space:]]*" item "[[:space:]]*\\|") { # Extract numbers that appear *after* the item label. @@ -2170,7 +2170,7 @@ tiotest_extract_latency_block() { } } } - + END { # Print only numeric fields; empty means "not found" printf "%s\t%s\t%s\t%s\n", la, lm, p2, p10 @@ -2185,14 +2185,14 @@ tiotest_metrics_append() { } # ---------------- perf helpers: normalize/validate numeric metrics ---------------- - + perf_norm_metric() { case "${1:-}" in ""|"unknown"|"UNKNOWN"|"NA"|"N/A"|"n/a") printf "%s" "NA" ;; *) printf "%s" "$1" ;; esac } - + perf_is_number() { # integer or decimal (e.g., 10, 10.5, 0.000) echo "${1:-}" | awk ' @@ -2200,7 +2200,7 @@ perf_is_number() { { exit 1 } ' } - + perf_append_if_number() { # $1=file $2=value if perf_is_number "${2:-}"; then @@ -2248,20 +2248,20 @@ perf_tiotest_run_seq_pair() { hide_lat=$7; terse=$8; wphase=$9; syncw=${10}; cons=${11}; dbg=${12} offmb=${13}; ofirst=${14} logf=${15}; metrics=${16} - + : >"$logf" 2>/dev/null || true - + common=$(tiotest_build_common_args "$tt" "$dir" "$use_raw" "$bs" "$fmb" "" \ "$hide_lat" "$terse" "$wphase" "$syncw" "$cons" "$dbg" "$offmb" "$ofirst") - + log_info "RUN: $bin $common -k 1 -k 3" # shellcheck disable=SC2086 "$bin" $common -k 1 -k 3 >>"$logf" 2>&1 || true - + # ---------------- MB/s ---------------- seqwr_mbps=$(tiotest_extract_mbps "$logf" "Write" 2>/dev/null || true) seqrd_mbps=$(tiotest_extract_mbps "$logf" "Read" 2>/dev/null || true) - + # ---------------- IOPS estimate ---------------- seqwr_iops="" seqrd_iops="" @@ -2273,7 +2273,7 @@ perf_tiotest_run_seq_pair() { seqrd_iops=$(awk -v mbps="$seqrd_mbps" -v b="$bs" 'BEGIN{ if (b>0) printf "%.0f", (mbps*1024*1024)/b }' 2>/dev/null) fi fi - + # ---------------- Latency (best-effort) ---------------- # Strictly parse numeric columns from: # | Write | ms | ms | | | @@ -2281,7 +2281,7 @@ perf_tiotest_run_seq_pair() { # Ensures we never output "Write"/"|" into metrics.tsv. seqwr_latavg=""; seqwr_latmax=""; seqwr_pct2=""; seqwr_pct10="" seqrd_latavg=""; seqrd_latmax=""; seqrd_pct2=""; seqrd_pct10="" - + row=$(awk ' BEGIN { inlat=0; la=""; lm=""; p2=""; p10="" } /^Tiotest latency results/ { inlat=1; next } @@ -2302,7 +2302,7 @@ perf_tiotest_run_seq_pair() { printf "%s\t%s\t%s\t%s\n", la, lm, p2, p10 } ' "$logf" 2>/dev/null || true) - + if [ -n "$row" ]; then # split by tabs seqwr_latavg=$(printf '%s' "$row" | awk -F'\t' '{print $1}') @@ -2310,7 +2310,7 @@ perf_tiotest_run_seq_pair() { seqwr_pct2=$(printf '%s' "$row" | awk -F'\t' '{print $3}') seqwr_pct10=$(printf '%s' "$row" | awk -F'\t' '{print $4}') fi - + row=$(awk ' BEGIN { inlat=0; la=""; lm=""; p2=""; p10="" } /^Tiotest latency results/ { inlat=1; next } @@ -2331,21 +2331,21 @@ perf_tiotest_run_seq_pair() { printf "%s\t%s\t%s\t%s\n", la, lm, p2, p10 } ' "$logf" 2>/dev/null || true) - + if [ -n "$row" ]; then seqrd_latavg=$(printf '%s' "$row" | awk -F'\t' '{print $1}') seqrd_latmax=$(printf '%s' "$row" | awk -F'\t' '{print $2}') seqrd_pct2=$(printf '%s' "$row" | awk -F'\t' '{print $3}') seqrd_pct10=$(printf '%s' "$row" | awk -F'\t' '{print $4}') fi - + # ---------------- Emit metrics (8 columns) ---------------- tiotest_metrics_append "$metrics" "seqwr" "$tt" "$seqwr_mbps" "$seqwr_iops" \ "$seqwr_latavg" "$seqwr_latmax" "$seqwr_pct2" "$seqwr_pct10" - + tiotest_metrics_append "$metrics" "seqrd" "$tt" "$seqrd_mbps" "$seqrd_iops" \ "$seqrd_latavg" "$seqrd_latmax" "$seqrd_pct2" "$seqrd_pct10" - + if [ -z "$seqwr_mbps" ] && [ -z "$seqrd_mbps" ]; then return 1 fi @@ -2364,31 +2364,31 @@ perf_tiotest_run_rnd_pair() { hide_lat=$8; terse=$9; wphase=${10}; syncw=${11}; cons=${12}; dbg=${13} offmb=${14}; ofirst=${15} logf=${16}; metrics=${17} - + : >"$logf" 2>/dev/null || true - + common=$(tiotest_build_common_args "$tt" "$dir" "$use_raw" "$bs" "$fmb" "$rops" \ "$hide_lat" "$terse" "$wphase" "$syncw" "$cons" "$dbg" "$offmb" "$ofirst") - + tmp_both="${logf}.rndboth.tmp" tmp_wr="${logf}.rndwr.tmp" tmp_rd="${logf}.rndrd.tmp" : >"$tmp_both" 2>/dev/null || true : >"$tmp_wr" 2>/dev/null || true : >"$tmp_rd" 2>/dev/null || true - + rndwr_mbps=""; rndwr_iops=""; rndwr_latavg=""; rndwr_latmax=""; rndwr_pct2=""; rndwr_pct10="" rndrd_mbps=""; rndrd_iops=""; rndrd_latavg=""; rndrd_latmax=""; rndrd_pct2=""; rndrd_pct10="" - + # ---------------- Primary: BOTH random write + random read ---------------- log_info "RUN (rnd both): $bin $common -k 1 -k 3" # shellcheck disable=SC2086 "$bin" $common -k 1 -k 3 >"$tmp_both" 2>&1 || true cat "$tmp_both" >>"$logf" 2>/dev/null || true - + rndwr_mbps=$(tiotest_extract_mbps "$tmp_both" "Write" 2>/dev/null || true) rndrd_mbps=$(tiotest_extract_mbps "$tmp_both" "Read" 2>/dev/null || true) - + # Latency parsing (best-effort): strict match "| Write |" and "| Read |" row=$(awk ' BEGIN { inlat=0; la=""; lm=""; p2=""; p10="" } @@ -2416,7 +2416,7 @@ perf_tiotest_run_rnd_pair() { rndwr_pct2=$(printf '%s' "$row" | awk -F'\t' '{print $3}') rndwr_pct10=$(printf '%s' "$row" | awk -F'\t' '{print $4}') fi - + row=$(awk ' BEGIN { inlat=0; la=""; lm=""; p2=""; p10="" } /^Tiotest latency results/ { inlat=1; next } @@ -2443,28 +2443,28 @@ perf_tiotest_run_rnd_pair() { rndrd_pct2=$(printf '%s' "$row" | awk -F'\t' '{print $3}') rndrd_pct10=$(printf '%s' "$row" | awk -F'\t' '{print $4}') fi - + # If Read missing, fallback to legacy probing if [ -z "$rndrd_mbps" ]; then log_info "rndrd missing in primary run; falling back to legacy probing" - + # Phase 1: try to collect write log_info "RUN (rndwr fallback): $bin $common -k 0 -k 2 -k 3" # shellcheck disable=SC2086 "$bin" $common -k 0 -k 2 -k 3 >"$tmp_wr" 2>&1 || true cat "$tmp_wr" >>"$logf" 2>/dev/null || true [ -z "$rndwr_mbps" ] && rndwr_mbps=$(tiotest_extract_mbps "$tmp_wr" "Write" 2>/dev/null || true) - + # Phase 2: prep + attempt read (best-effort) log_info "RUN (rndrd+prep fallback): $bin -t $tt -d $dir -b $bs -f $fmb -k 1 -k 2 -k 3 ; then $bin $common -k 0 -k 1 -k 2" "$bin" -t "$tt" -d "$dir" -b "$bs" -f "$fmb" -k 1 -k 2 -k 3 >>"$tmp_rd" 2>&1 || true # shellcheck disable=SC2086 "$bin" $common -k 0 -k 1 -k 2 >>"$tmp_rd" 2>&1 || true cat "$tmp_rd" >>"$logf" 2>/dev/null || true - + [ -z "$rndwr_mbps" ] && rndwr_mbps=$(tiotest_extract_mbps "$tmp_rd" "Write" 2>/dev/null || true) rndrd_mbps=$(tiotest_extract_mbps "$tmp_rd" "Read" 2>/dev/null || true) - + # Latency from fallback read log (if any) if [ -z "$rndwr_latavg" ]; then row=$(awk ' @@ -2491,7 +2491,7 @@ perf_tiotest_run_rnd_pair() { rndwr_pct10=$(printf '%s' "$row" | awk -F'\t' '{print $4}') fi fi - + if [ -z "$rndrd_latavg" ]; then row=$(awk ' BEGIN { inlat=0; la=""; lm=""; p2=""; p10="" } @@ -2518,7 +2518,7 @@ perf_tiotest_run_rnd_pair() { fi fi fi - + # ---------------- IOPS estimation ---------------- if [ -n "$bs" ] && [ "$bs" -gt 0 ] 2>/dev/null; then if [ -n "$rndwr_mbps" ]; then @@ -2528,16 +2528,16 @@ perf_tiotest_run_rnd_pair() { rndrd_iops=$(awk -v mbps="$rndrd_mbps" -v b="$bs" 'BEGIN{ if (b>0) printf "%.0f", (mbps*1024*1024)/b }' 2>/dev/null) fi fi - + # ---------------- Emit metrics (8 columns) ---------------- tiotest_metrics_append "$metrics" "rndwr" "$tt" "$rndwr_mbps" "$rndwr_iops" \ "$rndwr_latavg" "$rndwr_latmax" "$rndwr_pct2" "$rndwr_pct10" - + tiotest_metrics_append "$metrics" "rndrd" "$tt" "$rndrd_mbps" "$rndrd_iops" \ "$rndrd_latavg" "$rndrd_latmax" "$rndrd_pct2" "$rndrd_pct10" - + rm -f "$tmp_both" "$tmp_wr" "$tmp_rd" 2>/dev/null || true - + # Success if we got rndwr or rndrd [ -n "$rndwr_mbps" ] && return 0 [ -n "$rndrd_mbps" ] && return 0 @@ -2766,24 +2766,24 @@ perf_run_cmd_with_progress() { heartbeat_secs=$3 label=$4 shift 4 - + mkdir -p "${outdir:-.}" 2>/dev/null || true : >"$run_log" 2>/dev/null || true - + case "${heartbeat_secs:-}" in ""|*[!0-9]*) heartbeat_secs=15 ;; esac if [ "$heartbeat_secs" -lt 1 ] 2>/dev/null; then heartbeat_secs=15 fi - + if [ "${1:-}" != "--" ]; then log_warn "perf_run_cmd_with_progress: missing -- separator, falling back to tee" perf_run_cmd_tee_safe "$run_log" -- "$@" return $? fi shift - + tmpdir=$(mktemp -d "$outdir/.perftmp.XXXXXX" 2>/dev/null) if [ -z "${tmpdir:-}" ] || [ ! -d "$tmpdir" ]; then tmpdir=$(mktemp -d 2>/dev/null) @@ -2793,29 +2793,29 @@ perf_run_cmd_with_progress() { perf_run_cmd_tee_safe "$run_log" -- "$@" return $? fi - + fifo="$tmpdir/fifo" status_file="$tmpdir/status" : >"$status_file" 2>/dev/null || true - + if ! mkfifo "$fifo" 2>/dev/null; then rm -rf "$tmpdir" 2>/dev/null || true log_warn "perf_run_cmd_with_progress: mkfifo failed, falling back to tee" perf_run_cmd_tee_safe "$run_log" -- "$@" return $? fi - + log_info "Progress, $label, started" log_info "Progress, command, $*" printf "%s\n" "$label, invoked, waiting for output" >"$status_file" 2>/dev/null || true - + if command -v stdbuf >/dev/null 2>&1; then (stdbuf -oL -eL "$@" >"$fifo" 2>&1) & else ("$@" >"$fifo" 2>&1) & fi pid=$! - + ( while kill -0 "$pid" 2>/dev/null; do sleep "$heartbeat_secs" 2>/dev/null || break @@ -2828,15 +2828,15 @@ perf_run_cmd_with_progress() { done ) & hbpid=$! - + mode="" sc=0 mc=0 - + while IFS= read -r line; do printf "%s\n" "$line" printf "%s\n" "$line" >>"$run_log" 2>/dev/null || true - + case "$line" in "Single-Core") mode="Single-Core" @@ -2868,7 +2868,7 @@ perf_run_cmd_with_progress() { continue ;; esac - + if [ -n "$mode" ]; then name=$( printf "%s\n" "$line" | @@ -2892,7 +2892,7 @@ perf_run_cmd_with_progress() { } ' 2>/dev/null ) - + if [ -n "${name:-}" ]; then if [ "$mode" = "Single-Core" ]; then sc=$((sc + 1)) @@ -2906,21 +2906,21 @@ perf_run_cmd_with_progress() { fi fi done <"$fifo" - + wait "$pid" rc=$? - + kill "$hbpid" 2>/dev/null || true wait "$hbpid" 2>/dev/null || true - + rm -rf "$tmpdir" 2>/dev/null || true - + if [ "$rc" -eq 0 ]; then log_info "Progress, $label, completed, rc, 0" else log_warn "Progress, $label, completed, rc, $rc" fi - + return "$rc" } @@ -2934,7 +2934,7 @@ perf_parse_geekbench_summary_scores() { logfile=$1 [ -n "$logfile" ] || return 1 [ -f "$logfile" ] || return 1 - + awk ' function clean(line) { gsub(/\r/, "", line) @@ -2951,25 +2951,25 @@ perf_parse_geekbench_summary_scores() { } return "" } - + BEGIN{ in_summary=0 cur="" st=""; si=""; sf="" mt=""; mi=""; mf="" } - + { $0 = clean($0) } - + # Start summary (allow indentation) /^[[:space:]]*Benchmark Summary[[:space:]]*$/ { in_summary=1; cur=""; next } - + in_summary==1 { # If a new big header begins, stop if ($0 ~ /^[[:space:]]*System Information[[:space:]]*$/) { in_summary=0; next } if ($0 ~ /^[[:space:]]*CPU Information[[:space:]]*$/) { in_summary=0; next } if ($0 ~ /^[[:space:]]*Memory Information[[:space:]]*$/) { in_summary=0; next } - + if (index($0, "Single-Core Score") > 0) { v = last_int($0) if (v != "") { st=v; cur="single" } @@ -2980,7 +2980,7 @@ perf_parse_geekbench_summary_scores() { if (v != "") { mt=v; cur="multi" } next } - + if (index($0, "Integer Score") > 0) { v = last_int($0) if (v != "") { @@ -2999,7 +2999,7 @@ perf_parse_geekbench_summary_scores() { } next } - + END{ if (st!="" || mt!="") { printf "%s|%s|%s|%s|%s|%s\n", st, si, sf, mt, mi, mf @@ -3093,11 +3093,11 @@ perf_geekbench_write_iter_summary_txt() { st=$1; si=$2; sf=$3 mt=$4; mi=$5; mf=$6 outfile=$7 - + [ -n "$outfile" ] || return 1 - + : >"$outfile" 2>/dev/null || true - + if [ -n "${st:-}" ]; then echo "Benchmark Summary" >>"$outfile" echo " Single-Core Score: ${st}" >>"$outfile" @@ -3105,7 +3105,7 @@ perf_geekbench_write_iter_summary_txt() { [ -n "${sf:-}" ] && echo " Floating Point Score: ${sf}" >>"$outfile" echo "" >>"$outfile" fi - + if [ -n "${mt:-}" ]; then echo "Benchmark Summary" >>"$outfile" echo " Multi-Core Score: ${mt}" >>"$outfile" @@ -3113,11 +3113,11 @@ perf_geekbench_write_iter_summary_txt() { [ -n "${mf:-}" ] && echo " Floating Point Score: ${mf}" >>"$outfile" echo "" >>"$outfile" fi - + if [ -z "${st:-}" ] && [ -z "${mt:-}" ]; then echo "Benchmark Summary present but totals could not be parsed." >>"$outfile" fi - + return 0 } @@ -3183,7 +3183,7 @@ perf_geekbench_write_iter_subscores_txt() { perf_geekbench_scores_to_vars() { s=$1 [ -n "$s" ] || return 1 - + # Split without relying on bash arrays st=$(printf '%s' "$s" | awk -F'|' '{print $1}') si=$(printf '%s' "$s" | awk -F'|' '{print $2}') @@ -3191,7 +3191,7 @@ perf_geekbench_scores_to_vars() { mt=$(printf '%s' "$s" | awk -F'|' '{print $4}') mi=$(printf '%s' "$s" | awk -F'|' '{print $5}') mf=$(printf '%s' "$s" | awk -F'|' '{print $6}') - + # Quote values safely for eval. Values are numeric/empty, but keep it robust. printf "st='%s'\n" "$(printf '%s' "$st" | sed "s/'/'\\\\''/g")" printf "si='%s'\n" "$(printf '%s' "$si" | sed "s/'/'\\\\''/g")" @@ -3264,11 +3264,11 @@ perf_geekbench_pick_bin() { # Optional override: can be a directory or a file or a command name # Backward compatible: if not given, uses $GEEKBENCH_BIN then PATH. spec=$1 - + if [ -z "${spec:-}" ]; then spec=${GEEKBENCH_BIN:-} fi - + # If user provided a directory, pick executable inside it and fix +x if [ -n "${spec:-}" ] && [ -d "$spec" ]; then # try common names inside bundle @@ -3292,7 +3292,7 @@ perf_geekbench_pick_bin() { echo "" return 1 fi - + # If user provided a file path, chmod +x if needed if [ -n "${spec:-}" ] && [ -f "$spec" ]; then if [ ! -x "$spec" ]; then @@ -3305,7 +3305,7 @@ perf_geekbench_pick_bin() { echo "" return 1 fi - + # If user provided a command name present in PATH if [ -n "${spec:-}" ] && command -v "$spec" >/dev/null 2>&1; then p=$(command -v "$spec" 2>/dev/null) @@ -3318,7 +3318,7 @@ perf_geekbench_pick_bin() { return 0 fi fi - + # Default PATH lookup if command -v geekbench_aarch64 >/dev/null 2>&1; then p=$(command -v geekbench_aarch64 2>/dev/null) @@ -3330,7 +3330,7 @@ perf_geekbench_pick_bin() { return 0 fi fi - + if command -v geekbench >/dev/null 2>&1; then p=$(command -v geekbench 2>/dev/null) if [ -n "${p:-}" ] && [ -f "$p" ] && [ ! -x "$p" ]; then @@ -3341,7 +3341,7 @@ perf_geekbench_pick_bin() { return 0 fi fi - + echo "" return 1 } @@ -3353,7 +3353,7 @@ perf_geekbench_fix_exec_perms_dir() { d=$1 [ -n "$d" ] || return 1 [ -d "$d" ] || return 1 - + # Best effort: known names in Geekbench bundles for f in \ "$d/geekbench_aarch64" \ @@ -3367,13 +3367,13 @@ perf_geekbench_fix_exec_perms_dir() { done return 0 } - + # perf_geekbench_resolve_bin_and_fix_perms REQUESTED # - REQUESTED can be: empty, command, file path, or directory path # - Prints resolved executable path to stdout perf_geekbench_resolve_bin_and_fix_perms() { req=$1 - + # empty -> try PATH candidates if [ -z "${req:-}" ]; then if command -v geekbench_aarch64 >/dev/null 2>&1; then @@ -3386,11 +3386,11 @@ perf_geekbench_resolve_bin_and_fix_perms() { fi return 1 fi - + # directory provided if [ -d "$req" ]; then perf_geekbench_fix_exec_perms_dir "$req" 2>/dev/null || true - + if [ -f "$req/geekbench_aarch64" ]; then [ -x "$req/geekbench_aarch64" ] || chmod +x "$req/geekbench_aarch64" 2>/dev/null || true echo "$req/geekbench_aarch64" @@ -3401,7 +3401,7 @@ perf_geekbench_resolve_bin_and_fix_perms() { echo "$req/geekbench" return 0 fi - + # last resort: pick first file matching geekbench* for f in "$req"/geekbench* "$req"/Geekbench*; do [ -f "$f" ] || continue @@ -3411,14 +3411,14 @@ perf_geekbench_resolve_bin_and_fix_perms() { done return 1 fi - + # file provided if [ -f "$req" ]; then [ -x "$req" ] || chmod +x "$req" 2>/dev/null || true echo "$req" return 0 fi - + # command provided if command -v "$req" >/dev/null 2>&1; then p=$(command -v "$req" 2>/dev/null) @@ -3426,7 +3426,7 @@ perf_geekbench_resolve_bin_and_fix_perms() { echo "$p" return 0 fi - + return 1 } diff --git a/Runner/utils/lib_rt.sh b/Runner/utils/lib_rt.sh index bbc53513..f17c930d 100755 --- a/Runner/utils/lib_rt.sh +++ b/Runner/utils/lib_rt.sh @@ -1039,11 +1039,11 @@ rt_stop_heartbeat() { kill "$RT_HEARTBEAT_PID" 2>/dev/null || true wait "$RT_HEARTBEAT_PID" 2>/dev/null || true fi - + if [ "${RT_HEARTBEAT_INLINE:-0}" -eq 1 ] 2>/dev/null && [ -n "${RT_HEARTBEAT_TTY:-}" ]; then printf '\n' >"$RT_HEARTBEAT_TTY" fi - + RT_HEARTBEAT_PID="" RT_HEARTBEAT_INLINE=0 RT_HEARTBEAT_TTY="" diff --git a/Runner/utils/lib_sensors.sh b/Runner/utils/lib_sensors.sh index a76ee0cc..c1ae55d6 100755 --- a/Runner/utils/lib_sensors.sh +++ b/Runner/utils/lib_sensors.sh @@ -194,18 +194,18 @@ sensors_run_cmd_with_progress() { sensors_see_workhorse_passed() { logf="$1" [ -r "$logf" ] || return 1 - + # Decide verdict by the *last* PASS/FAIL marker in the log. # This handles duplicate PASS lines and any earlier noise. last="$(grep -E '^(PASS|FAIL)[[:space:]]+see_workhorse' "$logf" 2>/dev/null | tail -n 1 | awk '{print $1}')" - + if [ "$last" = "PASS" ]; then return 0 fi if [ "$last" = "FAIL" ]; then return 1 fi - + # Fallback if no explicit markers found: # consider non-empty log as "likely ran", but you can make this stricter if needed. [ -s "$logf" ] && return 0 diff --git a/Runner/utils/lib_video.sh b/Runner/utils/lib_video.sh index c51b2a76..d66d0d61 100755 --- a/Runner/utils/lib_video.sh +++ b/Runner/utils/lib_video.sh @@ -344,11 +344,11 @@ video_find_module_file() { # Prefers: modinfo -n, then .../updates/, then general search (and KO_DIRS/KO_TREE if provided). m="$1" kr="$(uname -r 2>/dev/null)" - + if [ -z "$kr" ]; then kr="$(find /lib/modules -mindepth 1 -maxdepth 1 -type d -printf '%f\n' 2>/dev/null | head -n 1)" fi - + if video_exist_cmd modinfo; then p="$(modinfo -n "$m" 2>/dev/null)" if [ -n "$p" ] && [ -f "$p" ]; then @@ -357,11 +357,11 @@ video_find_module_file() { return 0 fi fi - + m_us="$m" m_hy="$(printf '%s' "$m" | tr '_' '-')" m_alt="$(printf '%s' "$m" | tr '-' '_')" - + # Helper to scan KO_DIRS (bounded search) scan_ko_dirs() { modbase="$1" # without .ko* @@ -386,7 +386,7 @@ video_find_module_file() { IFS="$OLD_IFS" return 1 } - + # Optional order: prefer KO_DIRS first if requested if [ "$KO_PREFER_CUSTOM" -eq 1 ] 2>/dev/null; then for pat in "$m_us" "$m_hy" "$m_alt"; do @@ -395,7 +395,7 @@ video_find_module_file() { fi done fi - + # Optional altroot tree (KO_TREE) first, if provided if [ -n "$KO_TREE" ] && [ -d "$KO_TREE" ]; then for pat in "$m_us" "$m_hy" "$m_alt"; do @@ -407,7 +407,7 @@ video_find_module_file() { fi done fi - + for pat in "$m_us" "$m_hy" "$m_alt"; do p="$(find "/lib/modules/$kr/updates" -type f -name "${pat}.ko*" 2>/dev/null | head -n 1)" if [ -n "$p" ]; then @@ -416,7 +416,7 @@ video_find_module_file() { return 0 fi done - + for pat in "$m_us" "$m_hy" "$m_alt"; do p="$(find "/lib/modules/$kr" -type f -name "${pat}.ko*" 2>/dev/null | head -n 1)" if [ -n "$p" ]; then @@ -425,7 +425,7 @@ video_find_module_file() { return 0 fi done - + # If not preferred-first, still try KO_DIRS at the end if [ "$KO_PREFER_CUSTOM" -ne 1 ] 2>/dev/null; then for pat in "$m_us" "$m_hy" "$m_alt"; do @@ -434,7 +434,7 @@ video_find_module_file() { fi done fi - + return 1 } @@ -668,41 +668,41 @@ video_normalize_stack() { video_detect_platform() { model="" compat="" - + if [ -r /proc/device-tree/model ]; then model=$(tr -d '\000' /dev/null) fi - + if [ -r /proc/device-tree/compatible ]; then compat=$(tr -d '\000' /dev/null) fi - + s=$(printf '%s\n%s\n' "$model" "$compat" | tr '[:upper:]' '[:lower:]') - + # Monaco: qcs8300-ride, iq-8275-evk, qcs8275, generic qcs8300, or ride-sx+8300 monaco_pat='qcs8300-ride|iq-8275-evk|qcs8275|qcs8300|ride-sx.*8300|8300.*ride-sx' - + # LeMans: qcs9100-ride, qcs9075, generic qcs9100, or ride-sx+9100 lemans_pat='qcs9100-ride|qcs9075|qcs9100|ride-sx.*9100|9100.*ride-sx' - + # Kodiak: qcs6490, qcm6490, or rb3+6490 kodiak_pat='qcs6490|qcm6490|rb3.*6490|6490.*rb3' - + if printf '%s' "$s" | grep -Eq "$lemans_pat"; then printf '%s\n' "lemans" return 0 fi - + if printf '%s' "$s" | grep -Eq "$monaco_pat"; then printf '%s\n' "monaco" return 0 fi - + if printf '%s' "$s" | grep -Eq "$kodiak_pat"; then printf '%s\n' "kodiak" return 0 fi - + printf '%s\n' "unknown" } @@ -711,11 +711,11 @@ video_detect_platform() { # ----------------------------------------------------------------------------- video_validate_upstream_loaded() { plat="$1" - + if [ -z "$plat" ]; then plat="$(video_detect_platform)" fi - + case "$plat" in lemans|monaco) # Any upstream build has qcom_iris present @@ -724,21 +724,21 @@ video_validate_upstream_loaded() { fi return 1 ;; - + kodiak) # Upstream valid if Venus trio present OR pure qcom_iris-only present if video_has_module_loaded venus_core && video_has_module_loaded venus_dec && video_has_module_loaded venus_enc; then return 0 fi - + if video_has_module_loaded qcom_iris && ! video_has_module_loaded iris_vpu; then return 0 fi - + return 1 ;; esac - + return 1 } @@ -811,11 +811,11 @@ video_assert_stack() { video_stack_status() { plat="$1" - + if [ -z "$plat" ]; then plat="$(video_detect_platform)" fi - + case "$plat" in lemans|monaco) # Upstream accepted if: @@ -825,19 +825,19 @@ video_stack_status() { printf '%s\n' "upstream" return 0 fi - + if video_has_module_loaded qcom_iris && video_has_module_loaded iris_vpu; then printf '%s\n' "upstream" return 0 fi - + # Downstream if only iris_vpu is present (no qcom_iris) if video_has_module_loaded iris_vpu && ! video_has_module_loaded qcom_iris; then printf '%s\n' "downstream" return 0 fi ;; - + kodiak) # Upstream accepted if: # - Venus trio present (canonical upstream on Kodiak), OR @@ -846,12 +846,12 @@ video_stack_status() { printf '%s\n' "upstream" return 0 fi - + if video_has_module_loaded qcom_iris && ! video_has_module_loaded iris_vpu; then printf '%s\n' "upstream" return 0 fi - + # Downstream if iris_vpu present and Venus core not loaded if video_has_module_loaded iris_vpu && ! video_has_module_loaded venus_core; then printf '%s\n' "downstream" @@ -859,7 +859,7 @@ video_stack_status() { fi ;; esac - + printf '%s\n' "unknown" return 1 } @@ -1006,13 +1006,13 @@ video_hot_switch_modules() { video_ensure_stack() { want_raw="$1" # upstream|downstream|auto|base|overlay|up|down plat="$2" - + if [ -z "$plat" ]; then plat="$(video_detect_platform)" fi - + want="$(video_normalize_stack "$want_raw")" - + if [ "$want" = "auto" ]; then pref="$(video_auto_preference_from_blacklist "$plat")" if [ "$pref" != "unknown" ]; then @@ -1027,7 +1027,7 @@ video_ensure_stack() { fi log_info "AUTO stack selection => $want" fi - + # ---------------------------------------------------------------------- # Early no-op: if current state already equals desired, do NOT hot switch. # This covers: @@ -1037,7 +1037,7 @@ video_ensure_stack() { # Still allow Kodiak downstream FW swap without touching modules. # ---------------------------------------------------------------------- cur_state="$(video_stack_status "$plat")" - + if [ "$cur_state" = "$want" ]; then if [ "$plat" = "kodiak" ] && [ "$want" = "downstream" ] && [ -n "$VIDEO_FW_DS" ] && [ -f "$VIDEO_FW_DS" ]; then log_info "Kodiak: downstream already active; applying FW swap + live reload without hot switch." @@ -1046,7 +1046,7 @@ video_ensure_stack() { printf '%s\n' "$cur_state" return 0 fi - + # Fast paths (retain existing logic; these also help when cur_state was unknown) case "$want" in upstream|up|base) @@ -1084,20 +1084,20 @@ video_ensure_stack() { fi ;; esac - + # Only reach here if a switch is actually required. video_apply_blacklist_for_stack "$plat" "$want" || return 1 video_usleep "${MOD_SETTLE_SLEEP}" - + video_hot_switch_modules "$plat" "$want" || true - + if [ "$plat" = "kodiak" ] && [ "$want" = "downstream" ] && [ -n "$VIDEO_FW_DS" ] && [ -f "$VIDEO_FW_DS" ]; then if video_validate_downstream_loaded "$plat"; then log_info "Kodiak: downstream active and FW override detected — ensuring FW swap + live reload." video_kodiak_swap_and_reload "$VIDEO_FW_DS" || log_warn "Kodiak: post-switch FW swap/reload failed (continuing)" fi fi - + if [ "$want" = "upstream" ]; then if video_validate_upstream_loaded "$plat"; then printf '%s\n' "upstream" @@ -1109,7 +1109,7 @@ video_ensure_stack() { return 0 fi fi - + printf '%s\n' "unknown" return 1 } @@ -1144,12 +1144,12 @@ video_clean_and_refresh_v4l() { udevadm trigger --subsystem-match=media --action=change 2>/dev/null || true udevadm settle 2>/dev/null || true fi - + # Recreate missing /dev nodes using /sys/dev/char mapping. # Additive-only: never modify existing nodes (no chmod/chgrp on existing). for sysdev in /sys/dev/char/*; do [ -e "$sysdev" ] || continue - + majmin=$(basename "$sysdev") case "$majmin" in *:*) @@ -1160,42 +1160,42 @@ video_clean_and_refresh_v4l() { continue ;; esac - + case "$major" in ''|*[!0-9]*) continue ;; esac case "$minor" in ''|*[!0-9]*) continue ;; esac - + tgt=$(readlink -f "$sysdev" 2>/dev/null || true) [ -n "$tgt" ] || continue - + # Media controller nodes case "$tgt" in */media[0-9]*) bn=$(basename "$tgt") # e.g. media0 devnode="/dev/$bn" - + # Never touch if it already exists if [ -e "$devnode" ]; then continue fi - + log_info "Recreating missing node: $devnode (c $major $minor)" mknod "$devnode" c "$major" "$minor" 2>/dev/null || true chgrp video "$devnode" 2>/dev/null || true chmod 660 "$devnode" 2>/dev/null || true ;; esac - + # V4L2 video nodes case "$tgt" in */video4linux/video[0-9]*) bn=$(basename "$tgt") # e.g. video0 devnode="/dev/$bn" - + # Never touch if it already exists if [ -e "$devnode" ]; then continue fi - + log_info "Recreating missing node: $devnode (c $major $minor)" mknod "$devnode" c "$major" "$minor" 2>/dev/null || true chgrp video "$devnode" 2>/dev/null || true diff --git a/Runner/utils/send-to-lava.sh b/Runner/utils/send-to-lava.sh index 10c7d99a..be763e92 100755 --- a/Runner/utils/send-to-lava.sh +++ b/Runner/utils/send-to-lava.sh @@ -172,7 +172,8 @@ if [ -s "$SIGNAL_FILE" ]; then while IFS= read -r signal_line || [ -n "$signal_line" ]; do [ -n "$signal_line" ] || continue - save_and_quiet_kernel_console + # Blank lines help if previous console output did not end cleanly. + # The signal itself is still emitted only once. printf '\n%s\n\n' "$signal_line" restore_kernel_console done < "$SIGNAL_FILE" From 080d61c363a44954c2d12ce2c070c47b9db248e5 Mon Sep 17 00:00:00 2001 From: Azhar Shaikh Date: Mon, 8 Jun 2026 18:08:20 +0530 Subject: [PATCH 2/2] ci: Add a pre-check to detect whitespace Add a pre-merge check to detect any whitespace and fail the pre-merge if any detected. Signed-off-by: Azhar Shaikh --- .github/workflows/shellcheck.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index da51942a..334ba175 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -114,3 +114,27 @@ jobs: exit "$rc" ' sh < "$files_list" + - name: Check for trailing whitespace in .sh files (pull_request) + if: github.event_name == 'pull_request' + env: + BASE_BRANCH: ${{ github.base_ref }} + run: | + set -eu + + if [ -z "$BASE_BRANCH" ]; then + echo "BASE_BRANCH is empty" + exit 1 + fi + + if ! git check-ref-format --branch "$BASE_BRANCH" >/dev/null 2>&1; then + echo "Invalid base branch name: $BASE_BRANCH" + exit 1 + fi + + git fetch --no-tags origin "+refs/heads/${BASE_BRANCH}:refs/remotes/origin/${BASE_BRANCH}" + + MERGE_BASE="$(git merge-base HEAD "refs/remotes/origin/${BASE_BRANCH}")" + + git diff --check "${MERGE_BASE}"...HEAD \ + && echo "No trailing whitespace found." \ + || { echo "ERROR: Trailing whitespace or space/tab conflict found!"; exit 1; }