Skip to content

Commit d74ea44

Browse files
committed
test-case: add new test case for check mic privacy
Add new test case to check hardware mic privacy mode enablement feature. For switching mic privacy state is using a USB relay. https://github.com/darrylb123/usbrelay Signed-off-by: Artur Wilczak <arturx.wilczak@intel.com>
1 parent 067c933 commit d74ea44

File tree

3 files changed

+283
-0
lines changed

3 files changed

+283
-0
lines changed

case-lib/relay.sh

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/bin/bash
2+
3+
# SPDX-License-Identifier: BSD-3-Clause
4+
# Copyright(c) 2021-2025 Intel Corporation. All rights reserved.
5+
6+
# needs usbrelay package: https://github.com/darrylb123/usbrelay
7+
# param1: --debug | switch name
8+
# param2: switch state
9+
usbrelay_switch()
10+
{
11+
if [[ "$1" == "--debug" ]]; then
12+
dlogi "Debug mode: Current status of all relays:"
13+
usbrelay || {
14+
die "Failed to get usbrelay status.
15+
The usbrelay hw module is not responding or no relays detected.
16+
Check hardware connection."
17+
}
18+
fi
19+
20+
# Declare a constant for the relay settle time
21+
local USBRELAY_SETTLE_TIME=0.5
22+
23+
local switch_name=$1
24+
local state=$2
25+
26+
dlogi "Setting usbrelay switch $switch_name to $state."
27+
usbrelay "$switch_name=$state" --quiet || {
28+
die "Failed to set usbrelay switch $switch_name to $state.
29+
The usbrelay hw module is not responding or no relays detected.
30+
Check hardware connection."
31+
}
32+
33+
# wait for the switch to settle
34+
sleep "$USBRELAY_SETTLE_TIME"
35+
36+
# Display current state of the switch
37+
current_state=$(usbrelay | awk -F= -v name="$switch_name" '$1 == name { print $2 }')
38+
39+
# Check if current_state is equal to the requested state
40+
[[ "$current_state" == "$state" ]] || {
41+
die "usbrelay switch $switch_name failed to set to $state (current: $current_state)"
42+
}
43+
44+
case "$current_state" in
45+
'1') dlogi "Current state of $switch_name is: on";;
46+
'0') dlogi "Current state of $switch_name is: off";;
47+
*) die "Invalid state for $switch_name: $current_state";;
48+
esac
49+
}

env-check.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ func_check_pkg aplay
8787
func_check_pkg sox
8888
func_check_pkg tinycap
8989
func_check_pkg tinyplay
90+
# MIC privacy / JACK Audio detection relay switch
91+
func_check_pkg usbrelay
9092
# JACK Audio Connection Kit
9193
func_check_pkg jackd
9294
func_check_pkg jack_iodelay

test-case/test-mic-privacy.sh

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
#!/bin/bash
2+
3+
# SPDX-License-Identifier: BSD-3-Clause
4+
# Copyright(c) 2025 Intel Corporation. All rights reserved.
5+
6+
##
7+
## Case Name: test-mic-privacy
8+
##
9+
## Preconditions:
10+
## HW managed mode (Only for DMIC PCH and SNDW interfaces).
11+
## This test case requires physical loopback between playback and capture.
12+
## playback <=====> capture
13+
## USB relay switch is connected. The usbrelay app is installed.
14+
## Instruction: https://github.com/darrylb123/usbrelay
15+
##
16+
## Description:
17+
## Run alsabat process perform both playback and capture.
18+
## Enable MIC privacy.
19+
## Run alsabat process perform both playback and capture again.
20+
##
21+
## Case step:
22+
## 1. Specify the pcm IDs for playback and capture
23+
## 2. Check if usbrelay is installed and connected properly.
24+
## 3. Run alsabat process perform both playback and capture.
25+
## 4. Switch relay 1 to enable MIC privacy.
26+
## 5. Run alsabat process perform both playback and capture.
27+
##
28+
## Expect result:
29+
## After step 3 the return value is 0.
30+
## After step 5 the return value is -1001 (no peak be detected).
31+
32+
TESTDIR=$(realpath -e "$(dirname "${BASH_SOURCE[0]}")/..")
33+
TESTLIB="${TESTDIR}/case-lib"
34+
35+
# shellcheck disable=SC1091 source=case-lib/lib.sh
36+
source "${TESTLIB}/lib.sh"
37+
# shellcheck disable=SC1091 source=case-lib/relay.sh
38+
source "${TESTLIB}/relay.sh"
39+
40+
# remove the existing alsabat wav files
41+
ALSABAT_WAV_FILES="/tmp/mc.wav.*"
42+
rm -f "$ALSABAT_WAV_FILES"
43+
44+
DSP_SETTLE_TIME=2
45+
46+
OPT_NAME['p']='pcm_p' OPT_DESC['p']='pcm for playback. Example: hw:0,0'
47+
OPT_HAS_ARG['p']=1 OPT_VAL['p']='hw:0,0'
48+
49+
OPT_NAME['N']='channel_p' OPT_DESC['N']='channel number for playback.'
50+
OPT_HAS_ARG['N']=1 OPT_VAL['N']='2'
51+
52+
OPT_NAME['c']='pcm_c' OPT_DESC['c']='pcm for capture. Example: hw:0,1'
53+
OPT_HAS_ARG['c']=1 OPT_VAL['c']='hw:0,1'
54+
55+
OPT_NAME['C']='channel_c' OPT_DESC['C']='channel number for capture.'
56+
OPT_HAS_ARG['C']=1 OPT_VAL['C']='2'
57+
58+
OPT_NAME['s']='sof-logger' OPT_DESC['s']="Open sof-logger trace the data will store at $LOG_ROOT"
59+
OPT_HAS_ARG['s']=0 OPT_VAL['s']=1
60+
61+
OPT_NAME['r']='rate' OPT_DESC['r']='sample rate'
62+
OPT_HAS_ARG['r']=1 OPT_VAL['r']=48000
63+
64+
OPT_NAME['u']='relay' OPT_DESC['u']='name of usbrelay switch, default value is HURTM_1'
65+
OPT_HAS_ARG['u']=1 OPT_VAL['u']='HURTM_1'
66+
67+
func_opt_parse_option "$@"
68+
69+
pcm_p=${OPT_VAL['p']}
70+
pcm_c=${OPT_VAL['c']}
71+
channel_c=${OPT_VAL['C']}
72+
channel_p=${OPT_VAL['N']}
73+
rate=${OPT_VAL['r']}
74+
relay=${OPT_VAL['u']}
75+
76+
dlogi "Params: pcm_p=$pcm_p, pcm_c=$pcm_c, channel_c=$channel_c, channel_p=$channel_p, rate=$rate, LOG_ROOT=$LOG_ROOT"
77+
78+
__upload_wav_files()
79+
{
80+
# upload the alsabat wav file
81+
for file in $ALSABAT_WAV_FILES; do
82+
# alsabat has a bug where it creates an empty record in playback mode
83+
if test -s "$file"; then
84+
cp -v "$file" "$LOG_ROOT/"
85+
fi
86+
done
87+
}
88+
89+
check_playback_capture()
90+
{
91+
# check if capture and playback work
92+
dlogc "alsabat -P$pcm_p -C$pcm_c -c 2 -r $rate"
93+
alsabat -P"$pcm_p" -C"$pcm_c" -c 2 -r "$rate" || {
94+
# upload failed wav file
95+
__upload_wav_files
96+
die "check_playback_capture() failed - check if a loopback is connected."
97+
}
98+
}
99+
100+
handle_alsabat_result()
101+
{
102+
case "$alsabat_status" in
103+
23)
104+
# alsabat returns 23 if no peak detected (expected for MIC privacy)
105+
if grep -q -e "Amplitude: 0.0; Percentage: \[0\]" -e "Return value is -1001" "$alsabat_output"; then
106+
dlogi "Alsabat output indicates zero signal as expected (MIC privacy works)."
107+
else
108+
dloge "alsabat failed with status $alsabat_status, but signal is not zero."
109+
__upload_wav_files
110+
die "alsabat failed with: $(cat "$alsabat_output")."
111+
fi
112+
;;
113+
0)
114+
dloge "The alsabat command was unexpectedly successful."
115+
__upload_wav_files
116+
die "MIC privacy doesn't work. alsabat output: $(cat "$alsabat_output")"
117+
;;
118+
*)
119+
dloge "The alsabat command failed with unexpected status $alsabat_status."
120+
__upload_wav_files
121+
die "alsabat failed with: $(cat "$alsabat_output")."
122+
;;
123+
esac
124+
}
125+
126+
show_control_state()
127+
{
128+
dlogi "Current state of the mic privacy control:"
129+
amixer -c 0 contents | awk '
130+
/^numid=/ {
131+
n=$0
132+
show = tolower($0) ~ /capture/
133+
found = 0
134+
}
135+
/type=BOOLEAN/ {
136+
t = $0
137+
if (show) found = 1
138+
}
139+
/: values=/ && found {
140+
print n
141+
print t
142+
print $0
143+
found = 0
144+
}'
145+
}
146+
147+
main()
148+
{
149+
setup_kernel_check_point
150+
151+
start_test
152+
153+
logger_disabled || func_lib_start_log_collect
154+
155+
if [ -z "$pcm_p" ] || [ -z "$pcm_c" ]; then
156+
skip_test "No playback or capture PCM is specified. Skip the $0 test."
157+
fi
158+
159+
# check if usbrelay tool is installed
160+
command -v usbrelay || {
161+
skip_test "usbrelay command not found. Please install usbrelay to control the mic privacy switch."
162+
}
163+
164+
dlogi "Current DSP status is $(sof-dump-status.py --dsp_status 0)" || {
165+
skip_test "platform doesn't support runtime pm, skip test case"
166+
}
167+
168+
dlogi "Starting preconditions check"
169+
170+
# display current status of relays
171+
usbrelay "--debug"
172+
173+
check_locale_for_alsabat
174+
175+
set_alsa
176+
177+
dlogi "Reset - Turn off the mic privacy"
178+
usbrelay_switch "$relay" 0
179+
180+
show_control_state
181+
182+
# wait for the switch to settle
183+
sleep "$DSP_SETTLE_TIME"
184+
185+
# check the PCMs before mic privacy test
186+
dlogi "Check playback/capture before mic privacy test"
187+
check_playback_capture
188+
189+
# select the first card
190+
first_card_name=$(aplay -l | awk '/^card ([0-9]+)/ {print $3; exit}')
191+
# dump amixer contents always.
192+
# good case amixer settings is for reference, bad case for debugging.
193+
amixer -c "${first_card_name}" contents > "$LOG_ROOT"/amixer_settings.txt
194+
195+
check_playback_capture
196+
197+
dlogi "Preconditions are met, starting mic privacy test"
198+
199+
sleep "$DSP_SETTLE_TIME"
200+
201+
dlogi "===== Testing: MIC privacy ====="
202+
dlogi "Turn on the mic privacy switch"
203+
usbrelay_switch "$relay" 1
204+
205+
# wait for the switch to settle
206+
sleep "$DSP_SETTLE_TIME"
207+
208+
alsabat_output=$(mktemp)
209+
dlogc "alsabat -P$pcm_p -C$pcm_c -c 2 -r $rate"
210+
# run alsabat and capture both output and exit status
211+
alsabat_status=0
212+
alsabat -P"$pcm_p" -C"$pcm_c" -c 2 -r "$rate" > "$alsabat_output" 2>&1 || {
213+
alsabat_status=$?
214+
}
215+
216+
handle_alsabat_result
217+
218+
dlogi "Turn off the mic privacy switch."
219+
usbrelay_switch "$relay" 0
220+
221+
check_playback_capture
222+
223+
sof-kernel-log-check.sh "$KERNEL_CHECKPOINT"
224+
225+
dlogi "===== Test completed successfully. ====="
226+
227+
rm -rf "$alsabat_output"
228+
}
229+
230+
{
231+
main "$@"; exit "$?"
232+
}

0 commit comments

Comments
 (0)