diff --git a/overlay/etc/skel/.config/JS8Call.ini b/overlay/etc/skel/.config/JS8Call.ini
index 30e6484..f918f2b 100644
--- a/overlay/etc/skel/.config/JS8Call.ini
+++ b/overlay/etc/skel/.config/JS8Call.ini
@@ -17,7 +17,7 @@ Miles=true
MyCall=N0CALL
MyGrid=DM33
MyGroups=@@TTP,@@TTPNET
-MyInfo=ETC R3
+MyInfo=ETC R5
Polling=1
PSKReporter=false
PTTMethod=@Variant(\0\0\0\x7f\0\0\0\x1eTransceiverFactory::PTTMethod\0\0\0\0\xfPTT_method_CAT\0)
diff --git a/overlay/etc/skel/.fldigi/fldigi_def.xml b/overlay/etc/skel/.fldigi/fldigi_def.xml
new file mode 100644
index 0000000..0472d43
--- /dev/null
+++ b/overlay/etc/skel/.fldigi/fldigi_def.xml
@@ -0,0 +1,3457 @@
+
+
+
+1
+
+
+1
+
+
+5
+
+
+1
+
+
+0
+
+
+20
+
+
+0
+
+
+5
+
+
+200
+
+
+1
+
+
+1
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+,
+
+
+CW,BPSK-31,RTTY,,
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+1
+
+
+-60
+
+
+-6
+
+
+-3
+
+
+0
+
+
+0
+
+
+60
+
+
+1
+
+
+1
+
+
+8
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+0
+
+
+3000
+
+
+1500
+
+
+1500
+
+
+1500
+
+
+1
+
+
+100
+
+
+1
+
+
+0
+
+
+1
+
+
+0
+
+
+1
+
+
+0
+
+
+0
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+42
+
+
+
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+
+<FREQ>
+
+
+
+4
+
+
+0
+
+
+0
+
+
+0
+
+
+1
+
+
+50
+
+
+0
+
+
+-30
+
+
+9
+
+
+0
+
+
+1
+
+
+15
+
+
+0
+
+
+50
+
+
+1500
+
+
+25
+
+
+9
+
+
+1
+
+
+1
+
+
+3
+
+
+450
+
+
+68
+
+
+0
+
+
+1.25
+
+
+0
+
+
+0
+
+
+0
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+1
+
+
+72
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+
+
+
+0
+
+
+0
+
+
+0
+
+
+1
+
+
+0
+
+
+200
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+18
+
+
+15
+
+
+0
+
+
+15
+
+
+0
+
+
+24
+
+
+150
+
+
+2
+
+
+0.4
+
+
+0.6
+
+
+100
+
+
+1
+
+
+0
+
+
+0
+
+
+10
+
+
+5
+
+
+50
+
+
+1
+
+
+1
+
+
+3
+
+
+0
+
+
+1
+
+
+0
+
+
+2000
+
+
+4
+
+
+0.8
+
+
+4
+
+
+0
+
+
+18
+
+
+CW,,
+
+
+0
+
+
+0
+
+
+0
+
+
+4
+
+
+4
+
+
+0
+
+
+100
+
+
+0
+
+
+0
+
+
+=~<>%+&{}
+
+
+0
+
+
+20
+
+
+1
+
+
+0
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+0
+
+
+1
+
+
+0
+
+
+1
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+1
+
+
+245
+
+
+245
+
+
+30
+
+
+1225
+
+
+2205
+
+
+250
+
+
+120
+
+
+450
+
+
+2
+
+
+20
+
+
+0
+
+
+0
+
+
+1
+
+
+0
+
+
+1
+
+
+2
+
+
+2
+
+
+2
+
+
+8
+
+
+4
+
+
+0
+
+
+1
+
+
+1
+
+
+2
+
+
+2
+
+
+8
+
+
+4
+
+
+1
+
+
+0
+
+
+1
+
+
+2
+
+
+1
+
+
+K
+
+
+5
+
+
+4
+
+
+0
+
+
+1
+
+
+1
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+
+
+
+2
+
+
+K
+
+
+1
+
+
+0
+
+
+5
+
+
+0
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+4
+
+
+0
+
+
+0
+
+
+4
+
+
+2
+
+
+4.5
+
+
+3
+
+
+0
+
+
+0
+
+
+1
+
+
+cq cq cq de nocall
+
+
+0
+
+
+0
+
+
+0
+
+
+6
+
+
+10
+
+
+1
+
+
+fsq_heard_log.txt
+
+
+1
+
+
+fsq_audit_log.txt
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+ifkp_heard_log.txt
+
+
+1
+
+
+ifkp_audit_log.txt
+
+
+1
+
+
+1
+
+
+1
+
+
+
+
+
+32
+
+
+1
+
+
+1
+
+
+8
+
+
+1
+
+
+1
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+4
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+CQ
+
+
+2
+
+
+0
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+CW,BPSK-31,RTTY,,
+
+
+1
+
+
+125
+
+
+1
+
+
+1
+
+
+0
+
+
+
+
+
+
+
+
+1
+
+
+0
+
+
+1
+
+
+0
+
+
+1
+
+
+,
+
+
+1
+
+
+1
+
+
+0
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+/usr/local/bin/flmsg
+
+
+dinner_bell
+
+
+8
+
+
+0
+
+
+dinner_bell
+
+
+8
+
+
+0
+
+
+2
+
+
+phone
+
+
+7
+
+
+0
+
+
+beeboo
+
+
+6
+
+
+0
+
+
+phone
+
+
+7
+
+
+0
+
+
+rtty_bell
+
+
+9
+
+
+50
+
+
+0
+
+
+0
+
+
+1
+
+
+0
+
+
+1
+
+
+25
+
+
+50
+
+
+0
+
+
+500
+
+
+1500
+
+
+1250
+
+
+1750
+
+
+0
+
+
+/home/gaston/.fldigi/
+
+
+0
+
+
+0
+
+
+0
+
+
+https://www.hamcall.net/
+
+
+https://www.hamqth.com/
+
+
+http://www.qrz.com/
+
+
+https://callook.info/
+
+
+0
+
+
+
+
+
+
+
+
+
+
+
+0
+
+
+1
+
+
+http://www.eqsl.cc/qslcard/importADIF.cfm?ADIFdata=
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0
+
+
+0
+
+
+1
+
+
+0
+
+
+1
+
+
+
+
+
+
+
+
+1
+
+
+1
+
+
+
+
+
+15
+
+
+127.0.0.1
+
+
+9876
+
+
+0
+
+
+0
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+1
+
+
+maclogger_udp_strings.txt
+
+
+127.0.0.1
+
+
+1100
+
+
+1
+
+
+0
+
+
+0
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+1
+
+
+0
+
+
+0
+
+
+/dev/ttyS0
+
+
+localhost:4532
+
+
+
+
+
+2
+
+
+
+
+
+1
+
+
+2
+
+
+250
+
+
+1
+
+
+0
+
+
+0
+
+
+200
+
+
+/home/gaston/.fldigi/rig-not-assigned.xml
+
+
+/dev/ttyS0
+
+
+1
+
+
+2
+
+
+0
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+NONE
+
+
+0
+
+
+GPIO-3
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+2
+
+
+10
+
+
+50
+
+
+200
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+2
+
+
+200
+
+
+5
+
+
+0
+
+
+0
+
+
+NONE
+
+
+0
+
+
+1
+
+
+6
+
+
+50
+
+
+18
+
+
+0
+
+
+0
+
+
+1
+
+
+24
+
+
+0
+
+
+0
+
+
+2125
+
+
+2
+
+
+NONE
+
+
+NONE
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+{{ET_CALLSIGN}}
+
+
+
+
+
+
+
+
+{{ET_GRID}}
+
+
+
+
+
+
+
+
+1
+
+
+
+
+
+
+
+
+{{ET_PORTAUDIO_DEVICE}}
+
+
+{{ET_PORTAUDIO_INDEX}}
+
+
+{{ET_PORTAUDIO_DEVICE}}
+
+
+{{ET_PORTAUDIO_INDEX}}
+
+
+default
+
+
+19
+
+
+0
+
+
+
+
+
+1
+
+
+1
+
+
+0
+
+
+0
+
+
+-1
+
+
+1
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+/home/gaston/.fldigi/logs/logbook.adif
+
+
+0
+
+
+1
+
+
+1
+
+
+0
+
+
+1
+
+
+88
+
+
+63
+
+
+55
+
+
+53
+
+
+216
+
+
+1
+
+
+1
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+120
+
+
+1
+
+
+3
+
+
+*,-.;
+
+
+
+
+
+
+
+
+1
+
+
+1
+
+
+20
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5
+
+
+
+
+
+
+
+
+
+
+
+0
+
+
+0
+
+
+CALL if (RSTr), if (LOCATOR), NAME, QTH
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+127.0.0.1
+
+
+20001
+
+
+
+
+
+w3nr.ddns.net:7300::|dx.n8noe.us:7373::|w0mw.dynip.com:23::|
+
+
+sans
+
+
+0
+
+
+14
+
+
+sans
+
+
+0
+
+
+14
+
+
+
+
+
+
+
+
+
+
+
+Show DX
+
+
+SH/DX
+
+
+dxcm 2
+
+
+
+
+
+dxcm 3
+
+
+
+
+
+dxcm 4
+
+
+
+
+
+dxcm 5
+
+
+
+
+
+dxcm 6
+
+
+
+
+
+dxcm 7
+
+
+
+
+
+dxcm 8
+
+
+
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+1
+
+
+0.5
+
+
+1
+
+
+1
+
+
+0
+
+
+1
+
+
+0
+
+
+0
+
+
+-3
+
+
+0.2
+
+
+default.pal
+
+
+1
+
+
+UTF-8
+
+
+0
+
+
+16
+
+
+1
+
+
+sans
+
+
+0
+
+
+16
+
+
+sans
+
+
+0
+
+
+12
+
+
+1
+
+
+sans
+
+
+0
+
+
+16
+
+
+sans
+
+
+0
+
+
+12
+
+
+sans
+
+
+0
+
+
+12
+
+
+sans
+
+
+0
+
+
+12
+
+
+sans
+
+
+0
+
+
+gtk+
+
+
+0
+
+
+1
+
+
+4
+
+
+1
+
+
+1
+
+
+0
+
+
+0
+
+
+1
+
+
+2
+
+
+30
+
+
+25
+
+
+15
+
+
+sans
+
+
+0
+
+
+14
+
+
+0
+
+
+127.0.0.1
+
+
+8421
+
+
+0
+
+
+127.0.0.1
+
+
+7362
+
+
+127.0.0.1
+
+
+7322
+
+
+127.0.0.1
+
+
+7342
+
+
+7343
+
+
+0
+
+
+1
+
+
+0
+
+
+0
+
+
+3
+
+
+0
+
+
+2
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+63
+
+
+10
+
+
+50
+
+
+15
+
+
+100
+
+
+10
+
+
+0
+
+
+3
+
+
+15
+
+
+15
+
+
+0
+
+
+127.0.0.1
+
+
+12345
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+report.pskreporter.info
+
+
+4739
+
+
+0
+
+
+
+
+
+
+
+
+0
+
+
+1
+
+
+1
+
+
+800
+
+
+1900
+
+
+4000
+
+
+1
+
+
+5
+
+
+0.05
+
+
+15
+
+
+0
+
+
+30
+
+
+500
+
+
+10
+
+
+3
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+http://tgftp.nws.noaa.gov/data/observations/metar/decoded/
+
+
+Connection: close
+
+
+KMDQ
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
+0
+
+
+/home/gaston/.fldigi/kml/
+
+
+
+
+
+10000
+
+
+0
+
+
+120
+
+
+2
+
+
+60
+
+
+100
+
+
+0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+22
+
+
+0
+
+
+0
+
+
+sans
+
+
+0
+
+
+0
+
+
+16
+
+
+0
+
+
+0
+
+
+0
+
+
+60
+
+
+100
+
+
+2000
+
+
+4000
+
+
+500
+
+
+1
+
+
+1
+
+
+5
+
+
+1
+
+
+1
+
+
+3
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+4
+
+
+20
+
+
+0
+
+
+0
+
+
+4
+
+
+0.95
+
+
+0
+
+
+10
+
+
+0
+
+
+1
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+0
+
+
+1
+
+
+0
+
+
+2
+
+
+1
+
+
+1
+
+
+1
+
+
+1
+
+
diff --git a/overlay/etc/udev/rules.d/89-et-bg2fx-fx4cr.rules b/overlay/etc/udev/rules.d/89-et-bg2fx-fx4cr.rules
new file mode 100644
index 0000000..c7d6817
--- /dev/null
+++ b/overlay/etc/udev/rules.d/89-et-bg2fx-fx4cr.rules
@@ -0,0 +1,23 @@
+# Author : Gaston Gonzalez
+# Date : 18 September 2025
+# Purpose : udev rules for the FX-4CR by BG2FX
+#
+# Preconditions:
+# 1. FX-4CR connected via USB cable
+#
+# Postconditions:
+# 1. /dev/et-cat created
+# 2. rigctld is started
+# 3. /dev/et-audio created
+
+SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", ENV{ET_DEVICE}=="", \
+ ACTION=="add", \
+ ENV{ET_DEVICE}="FX-4CR", ENV{ET_SUBDEVICE}="CAT", GROUP="dialout", MODE="0660", SYMLINK+="et-cat", \
+ RUN+="/usr/bin/systemctl start rigctld"
+
+# PROGRAM="/opt/emcomm-tools/sbin/udev-tester.sh digirig-mobile", \
+SUBSYSTEM=="sound", ATTRS{idVendor}=="4c4a", ATTRS{idProduct}=="4155", \
+ ACTION=="add", \
+ ENV{ET_DEVICE}="FX-4CR", \
+ ATTR{id}="ET_AUDIO", \
+ ENV{ET_SUBDEVICE}="AUDIO", GROUP="audio", MODE="0660", SYMLINK+="et-audio"
diff --git a/overlay/opt/emcomm-tools/bin/et-audio b/overlay/opt/emcomm-tools/bin/et-audio
index dc33bde..b7a4e05 100755
--- a/overlay/opt/emcomm-tools/bin/et-audio
+++ b/overlay/opt/emcomm-tools/bin/et-audio
@@ -2,14 +2,14 @@
#
# Author : Gaston Gonzalez
# Date : 31 October 2024
-# Updated : 31 May 2024
+# Updated : 26 September 2025
# Purpose : Configures ET audio device with sane defaults
#
# Preconditions
# 1. Supported audio interface is connected and properly detected
#
# Postconditions
-# 1. ASLA settings set on ET audio device
+# 1. ALSA settings set on ET audio device
usage() {
echo "usage: $(basename $0) "
@@ -50,6 +50,8 @@ update-config () {
case ${ET_DEVICE_NAME} in
"DIGIRIG_MOBILE")
+ # TODO: 92% is needed for the TX-500MP. Revisit approach for setting speaker
+ # out differently across radios definitions.
# Unmute Speaker a set volume. Adjust if remote station can't decode you. Your TX controls.
amixer -q -c ${AUDIO_CARD} sset Speaker Playback Switch 42% unmute
# Unmute Mic
@@ -97,6 +99,19 @@ update-config () {
et-log "Applied amixer settings for ${ET_DEVICE_NAME}"
;;
+ "FX-4CR")
+ # Unmute the PCM and set the volume to 21% to get the full output power. This value is
+ # dependent on the settings defined for the FX-4CR in the et-radio notes.
+ amixer -q -c ${AUDIO_CARD} sset 'PCM' 31% unmute
+
+ # Set "L/R Capture" to 55%. Adjust if you can't decode received audio.
+ amixer -q -c ${AUDIO_CARD} sset 'Mic' 67% unmute
+
+ # Disable Auto Gain Control
+ amixer -q -c ${AUDIO_CARD} sset 'Auto Gain Control' mute
+
+ et-log "Applied amixer settings for ${ET_DEVICE_NAME}"
+ ;;
*)
et-log "No ALSA configuration specified for this ET_DEVICE."
;;
diff --git a/overlay/opt/emcomm-tools/bin/et-fldigi b/overlay/opt/emcomm-tools/bin/et-fldigi
new file mode 100755
index 0000000..70d0e52
--- /dev/null
+++ b/overlay/opt/emcomm-tools/bin/et-fldigi
@@ -0,0 +1,201 @@
+#!/bin/bash
+#
+# Author : Gaston Gonzalez
+# Date : 2 October 2025
+# Purpose : Wrapper script for starting fldigi with PnP support
+#
+# Preconditions
+# 1. Supported radio and audio interface are connected and properly detected
+#
+# Postconditions
+# 1. Stop all running EmComm Tools modes
+# 2. fldigi core settings updated (e.g., CAT, audio, user config and ETC defaults)
+# 3. fldigi started
+
+usage() {
+ echo "usage: $(basename $0) "
+ echo " start - Update config and start fldigi"
+ echo " update-config - Update config"
+}
+
+if [[ $# -ne 1 ]]; then
+ usage
+ exit 1
+fi
+
+notify_user() {
+ notify-send \
+ -t 5000 \
+ --app-name="EmComm Tools" \
+ "$1"
+}
+
+start() {
+ /opt/emcomm-tools/bin/et-kill-all && update-config && /usr/local/bin/fldigi &
+}
+
+update-config () {
+
+ # 1. Check if the audio device symlink was created by the udev rules
+ if [[ -e /dev/et-audio ]]; then
+
+ # 2. Check that this device was properly tagged with the ET_AUDIO env variable
+ APLAY_OUT=$(arecord -l | grep ET_AUDIO)
+ if [[ $? -eq 0 ]]; then
+
+ ## Configure ALSA settings for sound card
+ /opt/emcomm-tools/bin/et-audio update-config
+
+ else
+ et-log "No ET_AUDIO device detected."
+ notify_user "Can't start fldigi. No ET_AUDIO device detected."
+ exit 1
+ fi
+ else
+ et-log "No ET_AUDIO device plugged in."
+ notify_user "Can't start fldigi. No supported audio device plugged in."
+ exit 1
+ fi
+
+ PORT_AUDIO_CONF=/tmp/conf.tmp
+ GEO_CONF=/tmp/geo.tmp
+ FLDIGI_CONF_DIR="${HOME}/.fldigi"
+ FLDIGI_CONF_FILE="${FLDIGI_CONF_DIR}/fldigi_def.xml"
+
+ if [[ ! -e ${FLDIGI_CONF_DIR} ]]; then
+ et-log "${FLDIGI_CONF_DIR} does not exist. Creating it from template."
+ mkdir -v ${FLDIGI_CONF_DIR}
+ cp -v /etc/skel/.fldigi/fldigi_def.xml ${FLDIGI_CONF_DIR}
+ fi
+
+ [ -z "$ET_USER_CONFIG" ] && ET_USER_CONFIG="${HOME}/.config/emcomm-tools/user.json"
+
+ # clean up temporary config that may exist
+ [[ -e ${PORT_AUDIO_CONF} ]] && rm ${PORT_AUDIO_CONF}
+
+ et-portaudio 2>/dev/null > ${PORT_AUDIO_CONF}
+
+ if [[ $? -ne 0 ]]; then
+ et-log "No supported ET_AUDIO device found"
+ exit 1
+ fi
+
+ DEVICE=$(jq -r -e '.device' ${PORT_AUDIO_CONF})
+ if [[ $? -ne 0 ]]; then
+ et-log "Error getting PulseAudio device name for ET_AUDIO device"
+ exit 1
+ fi
+
+ INDEX=$(jq -r -e '.index' ${PORT_AUDIO_CONF})
+ if [[ $? -ne 0 ]]; then
+ et-log "Error getting PulseAudio device index for ET_AUDIO device"
+ exit 1
+ fi
+
+ ##############################################
+ # Map ALSA ET_AUDIO device to PortAudio device
+ ##############################################
+ et-log "Updating PortAudio device configuration..."
+
+ sed -i "s|^.*|1|" ${FLDIGI_CONF_FILE}
+
+ sed -i "s|^.*|${DEVICE}|" ${FLDIGI_CONF_FILE}
+ sed -i "s|^.*|${INDEX}|" ${FLDIGI_CONF_FILE}
+
+ sed -i "s|^.*|${DEVICE}|" ${FLDIGI_CONF_FILE}
+ sed -i "s|^.*|${INDEX}|" ${FLDIGI_CONF_FILE}
+
+ et-log "Using device '${DEVICE}' and device index '${INDEX}' for PortAudio configuration"
+
+
+ #################
+ # Update callsign
+ #################
+ et-log "Updating callsign configuration..."
+ CALLSIGN=$(jq -r -e '.callsign' ${ET_USER_CONFIG})
+
+ if [[ "${CALLSIGN}" = "N0CALL" ]]; then
+ et-log "Exiting early. No callsign set. Run: et-user."
+ exit 1
+ fi
+
+ et-log "Using callsign '${CALLSIGN}'"
+ sed -i "s|^.*|${CALLSIGN}|" ${FLDIGI_CONF_FILE}
+
+
+ ###############################################
+ # Update grid based on ETC geolocation services
+ ###############################################
+ et-log "Updating your grid square..."
+ curl -f -s "http://localhost:1981/api/geo/position" > ${GEO_CONF}
+
+ if [[ $? -eq 0 ]]; then
+ GRID=$(jq -r -e '.position.gridSquare' ${GEO_CONF})
+ if [[ $? -eq 0 ]]; then
+ et-log "Using grid square '${GRID}' for your location"
+ sed -i "s|^.*|${GRID}|" ${FLDIGI_CONF_FILE}
+ fi
+ fi
+
+ [[ -e ${GEO_CONF} ]] && rm ${GEO_CONF}
+
+
+ #####################################################################
+ # Configure CAT interface using Hamlib's rig control daemon (rigctld)
+ #####################################################################
+ et-log "Updating CAT control configuration..."
+
+ sed -i "s|^.*|1|" ${FLDIGI_CONF_FILE}
+ sed -i "s|^.*|2|" ${FLDIGI_CONF_FILE}
+ sed -i "s|^.*|1|" ${FLDIGI_CONF_FILE}
+ sed -i "s|^.*|localhost:4532|" ${FLDIGI_CONF_FILE}
+
+
+ ######################################
+ # Enable Reed Soloman ID for RX and TX
+ ######################################
+ et-log "Enabling Reed Soloman ID for RX/TX..."
+
+ sed -i "s|^.*|1|" ${FLDIGI_CONF_FILE}
+ sed -i "s|^.*|1|" ${FLDIGI_CONF_FILE}
+
+
+ ###########################
+ # Modem configuration: MT63
+ ###########################
+ et-log "Updating MT63 modem configuration..."
+
+ sed -i "s|^.*|1|" ${FLDIGI_CONF_FILE}
+
+
+ ########################
+ # Repeater configuration
+ ########################
+ et-log "Updating settings for linked repeater systems..."
+
+ # Key up for 2 seconds before transmitting tone. Needed for linked repeater systems.
+ sed -i "s|^.*|2|" ${FLDIGI_CONF_FILE}
+
+
+ #####################
+ # NBEMS configuration
+ #####################
+ et-log "Updating settings for NBEMS..."
+
+ sed -i "s|^.*|1|" ${FLDIGI_CONF_FILE}
+ sed -i "s|^.*|/usr/local/bin/flmsg|" ${FLDIGI_CONF_FILE}
+}
+
+case $1 in
+ start)
+ start
+ ;;
+ update-config)
+ update-config
+ ;;
+ *)
+ echo "Invalid command."
+ usage
+ exit 1
+ ;;
+esac
diff --git a/overlay/opt/emcomm-tools/bin/et-kill-all b/overlay/opt/emcomm-tools/bin/et-kill-all
index b08e594..ed0b8b3 100755
--- a/overlay/opt/emcomm-tools/bin/et-kill-all
+++ b/overlay/opt/emcomm-tools/bin/et-kill-all
@@ -2,7 +2,7 @@
#
# Author : Gaston Gonzalez
# Date : 12 November 2024
-# Updated : 7 February 2025
+# Updated : 2 October 2025
# Purpose : Stops all EmComm Tools sound-based services (i.e. modems) and
# amatuer radio applications to ensure a clean start for the next mode.
diff --git a/overlay/opt/emcomm-tools/conf/radios.d/bg2fx-fx4cr.json b/overlay/opt/emcomm-tools/conf/radios.d/bg2fx-fx4cr.json
new file mode 100644
index 0000000..6c39035
--- /dev/null
+++ b/overlay/opt/emcomm-tools/conf/radios.d/bg2fx-fx4cr.json
@@ -0,0 +1,28 @@
+{
+ "id": "bg2fx-fx4cr",
+ "vendor": "BG2FX",
+ "model": "FX-4CR",
+ "rigctrl": {
+ "id": "2031",
+ "baud": "115200",
+ "ptt": "RIG",
+ "conf": "data_bits=8,serial_handshake=None,stop_bits=1,rts_state=OFF",
+ "pttOnly": "false"
+ },
+ "notes": [
+ "Short press [PWR], then rotate AF knob until POW = 5.0",
+ "Toggle [SSB] button until both USB and DIG appear",
+ "Short press [M. V] until VFOA is displayed",
+ "Long press [MENU], rotate AF to BLUETOOTH, rotate TUNE and set to 0",
+ "Set radio volume to 50",
+ "Set mic gain to 50",
+ "Set alsamixer PCM to 21",
+ "Set alsamixer Mic to 55",
+ "Set alsamixer AGC to mm"
+ ],
+ "fieldNotes": [
+ "Tested with FX-4CR firmware version: 1.7.3 (2025/09/01)",
+ "You must force the RTS control line to low for audio output to work with the PTT",
+ "This is handled with rts_state=OFF using the --set-conf argument of rigctld"
+ ]
+}
diff --git a/overlay/opt/emcomm-tools/conf/radios.d/lab599-tx500mp.json b/overlay/opt/emcomm-tools/conf/radios.d/lab599-tx500mp.json
new file mode 100644
index 0000000..63331ac
--- /dev/null
+++ b/overlay/opt/emcomm-tools/conf/radios.d/lab599-tx500mp.json
@@ -0,0 +1,20 @@
+{
+ "id": "lab599-tx500mp",
+ "vendor": "Lab599",
+ "model": "TX-500MP (DigiRig Mobile)",
+ "rigctrl": {
+ "id": "2014",
+ "baud": "9600",
+ "ptt": "RTS",
+ "pttOnly": "false"
+ },
+ "notes": [
+ "1. Set MENU 36 CAT PROTOCOL = TS2000",
+ "2. Set MODE = DIGI",
+ "",
+ "Do not enable VOX on radio"
+
+ ],
+ "fieldNotes": [
+ ]
+}
diff --git a/overlay/opt/emcomm-tools/sbin/udev-tester.sh b/overlay/opt/emcomm-tools/sbin/udev-tester.sh
index 9f60211..02fb7f9 100755
--- a/overlay/opt/emcomm-tools/sbin/udev-tester.sh
+++ b/overlay/opt/emcomm-tools/sbin/udev-tester.sh
@@ -1,7 +1,7 @@
#!/bin/bash
# Author : Gaston Gonzalez
# Date : 11 October 2024
-# Updated : 21 May 2025
+# Updated : 13 September 2025
# Purpose : Perform tests that can be used by the udev subsystem to aid
# in rule development. This is intended to by used with the PROGRAM
# directive inside of a udev rule.
@@ -81,6 +81,11 @@ test_digirig_mobile() {
exit 0
fi
+ if [[ "$ID" == "lab599-tx500mp" ]]; then
+ et-log "Old DigiRig Mobile detected for TX-500MP"
+ exit 0
+ fi
+
fi
exit 1
diff --git a/overlay/opt/emcomm-tools/sbin/wrapper-rigctld.sh b/overlay/opt/emcomm-tools/sbin/wrapper-rigctld.sh
index 1c1b9ab..534dd99 100755
--- a/overlay/opt/emcomm-tools/sbin/wrapper-rigctld.sh
+++ b/overlay/opt/emcomm-tools/sbin/wrapper-rigctld.sh
@@ -2,13 +2,16 @@
#
# Author : Gaston Gonzalez
# Date : 9 October 2024
-# Updated : 31 May 2025
+# Updated : 26 September 2025
# Purpose : Wrapper startup/shutdown script around systemd/rigctld
ET_HOME=/opt/emcomm-tools
ACTIVE_RADIO="${ET_HOME}/conf/radios.d/active-radio.json"
CAT_DEVICE=/dev/et-cat
+# Additional configuration to pass to rigctld
+SET_CONF=""
+
do_full_auto() {
et-log "Found ET_DEVICE='${ET_DEVICE}'"
@@ -95,8 +98,14 @@ start() {
exit 0
fi
+ # Handle optional configuration settings
+ CONF=$(jq -e -r '.rigctrl.conf' "${ET_HOME}/conf/radios.d/active-radio.json")
+ if [[ $? -eq 0 ]]; then
+ SET_CONF="--set-conf=${CONF}"
+ fi
+
# Generate command
- CMD="rigctld -m ${ID} -r ${CAT_DEVICE} -s ${BAUD} -P ${PTT} "
+ CMD="rigctld -m ${ID} -r ${CAT_DEVICE} -s ${BAUD} -P ${PTT} ${SET_CONF}"
et-log "Starting rigctld with: ${CMD}"
$CMD
}
diff --git a/overlay/usr/share/glib-2.0/schemas/90_ubuntu-settings.gschema.override b/overlay/usr/share/glib-2.0/schemas/90_ubuntu-settings.gschema.override
index 13f00af..af23eb0 100644
--- a/overlay/usr/share/glib-2.0/schemas/90_ubuntu-settings.gschema.override
+++ b/overlay/usr/share/glib-2.0/schemas/90_ubuntu-settings.gschema.override
@@ -12,7 +12,7 @@ show-desktop-icons = false
picture-uri = 'file:///usr/share/backgrounds/emcomm-tools-wallpaper.png'
[org.gnome.shell]
-favorite-apps = ['emcomm-tools.desktop', 'js8call.desktop', 'et-aircraft.desktop', 'org.gnome.Terminal.desktop', 'navit.desktop', 'min.desktop', 'org.gnome.Nautilus.desktop']
+favorite-apps = ['emcomm-tools.desktop', 'js8call.desktop', 'fldigi.desktop', 'et-aircraft.desktop', 'org.gnome.Terminal.desktop', 'navit.desktop', 'min.desktop', 'org.gnome.Nautilus.desktop']
last-selected-power-profile = 'performance'
[org.gnome.system.location]
diff --git a/scripts/install-et-portaudio.sh b/scripts/install-et-portaudio.sh
new file mode 100755
index 0000000..8326164
--- /dev/null
+++ b/scripts/install-et-portaudio.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# Author : Gaston Gonzalez
+# Date : 2 October 2025
+# Purpose : Builds and installs et-portaudio
+set -e
+trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
+trap 'et-log "\"${last_command}\" command failed with exit code $?."' ERR
+
+. ./env.sh
+
+APP="et-portaudio"
+VERSION="1.0.0"
+APP_AND_VERSION="${APP}-${VERSION}"
+INSTALL_DIR="/opt/${APP_AND_VERSION}"
+LINK_PATH="/opt/${APP}"
+
+et-log "Installing ${APP} ${VERSION}"
+
+CWD_DIR=`pwd`
+
+cd ../src/et-portaudio
+
+# Compile
+make install
+
+[[ -e ${LINK_PATH} ]] && rm ${LINK_PATH}
+ln -v -s ${INSTALL_DIR} ${LINK_PATH}
+
+stow -v -d /opt ${APP} -t /usr/local
+
+cd ${CWD}
diff --git a/scripts/install-fldigi.sh b/scripts/install-fldigi.sh
new file mode 100755
index 0000000..6c4e4ce
--- /dev/null
+++ b/scripts/install-fldigi.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+# Author : Gaston Gonzalez
+# Date : 17 September 2025
+# Updated : 2 October 2025
+# Purpose : Builds and installs fldigi
+set -e
+trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
+trap 'et-log "\"${last_command}\" command failed with exit code $?."' ERR
+
+. ./env.sh
+
+APP="fldigi"
+VERSION="4.2.09"
+APP_AND_VERSION="${APP}-${VERSION}"
+GIT_TAG="v4.2.09"
+GIT_URL="https://git.code.sf.net/p/fldigi/fldigi"
+GIT_WORKSPACE="fldigi"
+INSTALL_DIR="/opt/${APP_AND_VERSION}"
+LINK_PATH="/opt/${APP}"
+
+et-log "Installing ${APP} ${VERSION}"
+
+CWD_DIR=`pwd`
+
+cd ${ET_SRC_DIR}
+[[ ! -e ${GIT_WORKSPACE} ]] && git clone ${GIT_URL} ${GIT_WORKSPACE}
+
+cd ${GIT_WORKSPACE}
+git checkout ${GIT_TAG}
+
+# Generate config script
+autoreconf -i && ./configure --prefix=${INSTALL_DIR}
+
+# Compile
+make
+
+# Install
+make install
+
+[[ -e ${LINK_PATH} ]] && rm ${LINK_PATH}
+ln -v -s ${INSTALL_DIR} ${LINK_PATH}
+
+stow -v -d /opt ${APP} -t /usr/local
+
+cd ${CWD}
+
+# Use wrapper script as launcher executable
+sed -i 's|^Exec.*|Exec=/opt/emcomm-tools/bin/et-fldigi start|' /opt/fldigi/share/applications/fldigi.desktop
+
diff --git a/scripts/install.sh b/scripts/install.sh
index 655e658..06e94f8 100755
--- a/scripts/install.sh
+++ b/scripts/install.sh
@@ -2,7 +2,7 @@
#
# Author : Gaston Gonzalez
# Date : 16 March 2024
-# Updated : 16 August 2025
+# Updated : 2 October 2025
# Purpose : Main installer for EmComm Tools Community (ETC)
. ./env.sh
@@ -87,3 +87,9 @@ exitIfNotRoot
# Install prediction tools
./install-voacap.sh
+
+# Install fldigi suite
+./install-fldigi.sh
+./install-et-portaudio.sh
+
+# TODO: add installers for flmsg and flamp
diff --git a/src/et-portaudio/.gitignore b/src/et-portaudio/.gitignore
new file mode 100644
index 0000000..a75e2aa
--- /dev/null
+++ b/src/et-portaudio/.gitignore
@@ -0,0 +1,2 @@
+et-portaudio
+*.o
diff --git a/src/et-portaudio/Makefile b/src/et-portaudio/Makefile
new file mode 100644
index 0000000..61b64d4
--- /dev/null
+++ b/src/et-portaudio/Makefile
@@ -0,0 +1,25 @@
+CC = gcc
+CFLAGS = -Wall -O2
+LDFLAGS = -lportaudio -lasound
+
+TARGET = et-portaudio
+SRC = main.c
+VERSION=1.0.0
+INSTALL_DIR = /opt/et-portaudio-$(VERSION)/bin
+
+.PHONY: install
+
+all: $(TARGET)
+
+$(TARGET): $(SRC)
+ $(CC) $(CFLAGS) -o $(TARGET) $(SRC) $(LDFLAGS)
+
+install: $(TARGET)
+ @echo "Installing $(TARGET) to $(INSTALL_DIR)..."
+ @mkdir -p $(INSTALL_DIR)
+ @cp $(TARGET) $(INSTALL_DIR)/
+ @chmod 755 $(INSTALL_DIR)/$(TARGET)
+ @echo "Done."
+
+clean:
+ rm -f $(TARGET) *.o
diff --git a/src/et-portaudio/README.md b/src/et-portaudio/README.md
new file mode 100644
index 0000000..e4f6ac4
--- /dev/null
+++ b/src/et-portaudio/README.md
@@ -0,0 +1,32 @@
+# et-portaudio
+
+A utility program intended for script use to convert a supported
+EmComm Tools ALSA audio device (i.e. `ET_AUDIO`) to a PulseAudio device.
+
+## Usage
+
+Returns a JSON object with the PulseAudio device details on success.
+
+```bash
+./et-portaudio 2>/dev/null
+{
+ "device": "USB Audio Device: - (hw:1,0)",
+ "index": 6
+}
+```
+
+If no supported device is found or on error, the utility exits with an
+exit status of 1.
+
+
+## Build
+
+``bash
+make
+```
+
+## Install
+
+```bash
+sudo make install
+```
diff --git a/src/et-portaudio/gen-fldigi-cfg.sh b/src/et-portaudio/gen-fldigi-cfg.sh
new file mode 100755
index 0000000..9f85b8e
--- /dev/null
+++ b/src/et-portaudio/gen-fldigi-cfg.sh
@@ -0,0 +1,147 @@
+#!/bin/bash
+# Author : Gaston Gonzalez
+# Date : 1 October 2025
+# Updated : 2 October 2025
+# Purpose : Temporary script to fast-fail dynamic fldigi config for PnP
+#
+# NOTE: THIS IS SCRIPT IS INTENDED FOR DEVELOPMENT OF THE PNP SOLUTION.
+
+CMD=et-portaudio
+PORT_AUDIO_CONF=/tmp/conf.tmp
+GEO_CONF=/tmp/geo.tmp
+FLDIGI_CONF_DIR="${HOME}/.fldigi"
+FLDIGI_CONF_FILE="${FLDIGI_CONF_DIR}/fldigi_def.xml"
+
+[ -z "$ET_USER_CONFIG" ] && ET_USER_CONFIG="${HOME}/.config/emcomm-tools/user.json"
+
+# clean up temporary config that may exist
+[[ -e ${PORT_AUDIO_CONF} ]] && rm ${PORT_AUDIO_CONF}
+
+[[ ! -e ${CMD} ]] && make
+./${CMD} 2>/dev/null > ${PORT_AUDIO_CONF}
+
+if [[ $? -ne 0 ]]; then
+ echo "No supported ET_AUDIO device found"
+ exit 1
+fi
+
+DEVICE=$(jq -r -e '.device' ${PORT_AUDIO_CONF})
+if [[ $? -ne 0 ]]; then
+ echo "Error getting PulseAudio device name for ET_AUDIO device"
+ exit 1
+fi
+
+INDEX=$(jq -r -e '.index' ${PORT_AUDIO_CONF})
+if [[ $? -ne 0 ]]; then
+ echo "Error getting PulseAudio device index for ET_AUDIO device"
+ exit 1
+fi
+
+################################
+# Bootstrap fldigi configuration
+################################
+et-log "Checking for .fldigi directory"
+[[ ! -e ${FLDIGI_CONF_DIR} ]] && mkdir -v ${FLDIGI_CONF_DIR}
+
+et-log "Copying fldigi template..."
+cp -v ../../overlay/etc/skel/.fldigi/fldigi_def.xml ~/.fldigi/
+
+
+##############################################
+# Map ALSA ET_AUDIO device to PortAudio device
+##############################################
+et-log "Updating PortAudio device configuration..."
+
+sed -i "s|^.*|1|" ${FLDIGI_CONF_FILE}
+
+sed -i "s|^.*|${DEVICE}|" ${FLDIGI_CONF_FILE}
+sed -i "s|^.*|${INDEX}|" ${FLDIGI_CONF_FILE}
+
+sed -i "s|^.*|${DEVICE}|" ${FLDIGI_CONF_FILE}
+sed -i "s|^.*|${INDEX}|" ${FLDIGI_CONF_FILE}
+
+et-log "Using device '${DEVICE}' and device index '${INDEX}' for PortAudio configuration"
+
+
+#################
+# Update callsign
+#################
+et-log "Updating callsign configuration..."
+CALLSIGN=$(jq -r -e '.callsign' ${ET_USER_CONFIG})
+
+if [[ "${CALLSIGN}" = "N0CALL" ]]; then
+ et-log "Exiting early. No callsign set. Run: et-user."
+ exit 1
+fi
+
+et-log "Using callsign '${CALLSIGN}'"
+sed -i "s|^.*|${CALLSIGN}|" ${FLDIGI_CONF_FILE}
+
+
+###############################################
+# Update grid based on ETC geolocation services
+###############################################
+et-log "Updating your grid square..."
+curl -f -s "http://localhost:1981/api/geo/position" > ${GEO_CONF}
+
+if [[ $? -eq 0 ]]; then
+ GRID=$(jq -r -e '.position.gridSquare' ${GEO_CONF})
+ if [[ $? -eq 0 ]]; then
+ et-log "Using grid square '${GRID}' for your location"
+ sed -i "s|^.*|${GRID}|" ${FLDIGI_CONF_FILE}
+ fi
+fi
+
+[[ -e ${GEO_CONF} ]] && rm ${GEO_CONF}
+
+
+#####################################################################
+# Configure CAT interface using Hamlib's rig control daemon (rigctld)
+#####################################################################
+et-log "Updating CAT control configuration..."
+
+sed -i "s|^.*|1|" ${FLDIGI_CONF_FILE}
+sed -i "s|^.*|2|" ${FLDIGI_CONF_FILE}
+sed -i "s|^.*|1|" ${FLDIGI_CONF_FILE}
+sed -i "s|^.*|localhost:4532|" ${FLDIGI_CONF_FILE}
+
+
+######################################
+# Enable Reed Soloman ID for RX and TX
+######################################
+et-log "Enabling Reed Soloman ID for RX/TX..."
+
+sed -i "s|^.*|1|" ${FLDIGI_CONF_FILE}
+sed -i "s|^.*|1|" ${FLDIGI_CONF_FILE}
+
+
+###########################
+# Modem configuration: MT63
+###########################
+et-log "Updating MT63 modem configuration..."
+
+sed -i "s|^.*|1|" ${FLDIGI_CONF_FILE}
+
+
+########################
+# Repeater configuration
+########################
+et-log "Updating settings for linked repeater systems..."
+
+# Key up for 2 seconds before transmitting tone. Needed for linked repeater systems.
+sed -i "s|^.*|2|" ${FLDIGI_CONF_FILE}
+
+
+#####################
+# NBEMS configuration
+#####################
+et-log "Updating settings for NBEMS..."
+
+sed -i "s|^.*|1|" ${FLDIGI_CONF_FILE}
+sed -i "s|^.*|/usr/local/bin/flmsg|" ${FLDIGI_CONF_FILE}
+
+# TODO: Add flmsg to ETC installer
+# TODO: Add flamp to ETC installer
+# TODO: Revisit autostart configuration to start flamp
+# TODO: Revisit TCP/IP configuration when porting ETC R2 Build 56
+# TODO: Define TTP/ETC macros
diff --git a/src/et-portaudio/main.c b/src/et-portaudio/main.c
new file mode 100644
index 0000000..76aabfc
--- /dev/null
+++ b/src/et-portaudio/main.c
@@ -0,0 +1,89 @@
+/*
+ * Author : Gaston Gonzalez
+ * Date : 1 October 2025
+ * Purpose : Maps an ET_AUDIO ALSA device to a PortAudio device.
+ *
+ * This utility enumerates all ALSA audio devices using PortAudio
+ * to identify a currently plugged-in ET_AUDIO device. If a matching
+ * device is found, it generates a JSON object on STDOUT containing:
+ *
+ * - PortAudio device name
+ * - PortAudio device index
+ *
+ * Exit Status:
+ * 0 - ET_AUDIO device found and JSON output generated successfully
+ * 1 - ET_AUDIO device not found
+ */
+
+#include
+#include
+#include
+#include "portaudio.h"
+
+#define PROC_ALSA_PATH_FMT "/proc/asound/card%d/id"
+
+// Read the ALSA card ID from the /proc filesystem
+int get_alsa_card_id(int card, char *id_buf, size_t buf_size) {
+ char path[64];
+ snprintf(path, sizeof(path), PROC_ALSA_PATH_FMT, card);
+ FILE *f = fopen(path, "r");
+ if (!f) return -1;
+ if (!fgets(id_buf, buf_size, f)) {
+ fclose(f);
+ return -1;
+ }
+ id_buf[strcspn(id_buf, "\n")] = 0;
+ fclose(f);
+
+ return 0;
+}
+
+int main(void) {
+ PaError err;
+ int i, numDevices;
+ const PaDeviceInfo *deviceInfo;
+ const PaHostApiInfo *hostApiInfo;
+ int found = 0;
+
+ err = Pa_Initialize();
+ if (err != paNoError) {
+ fprintf(stderr, "PortAudio error: %s\n", Pa_GetErrorText(err));
+ return 1;
+ }
+
+ numDevices = Pa_GetDeviceCount();
+ if (numDevices < 0) {
+ fprintf(stderr, "No audio devices found");
+ Pa_Terminate();
+ return 1;
+ }
+
+ for (i = 0; i < numDevices; i++) {
+ deviceInfo = Pa_GetDeviceInfo(i);
+ hostApiInfo = Pa_GetHostApiInfo(deviceInfo->hostApi);
+
+ // Only show ALSA devices
+ if (hostApiInfo && strcmp(hostApiInfo->name, "ALSA") == 0) {
+ int card = -1, device = -1;
+
+ // Extract ALSA card and device (hw:X,Y)
+ if (sscanf(deviceInfo->name, "%*[^()](hw:%d,%d)", &card, &device) == 2) {
+ char card_id[64];
+ if (get_alsa_card_id(card, card_id, sizeof(card_id)) == 0) {
+
+ // Only print if card ID matches ET_AUDIO
+ if (strcmp(card_id, "ET_AUDIO") == 0) {
+ found = 1;
+ printf("{\n");
+ printf(" \"device\": \"%s\",\n", deviceInfo->name);
+ printf(" \"index\": %d\n", i);
+ printf("}\n");
+ }
+ }
+ }
+ }
+ }
+
+ Pa_Terminate();
+ return found ? 0 : 1;
+}
diff --git a/tests/test-et-portaudio.sh b/tests/test-et-portaudio.sh
new file mode 100755
index 0000000..d82bdcf
--- /dev/null
+++ b/tests/test-et-portaudio.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# Author : Gaston Gonzalez
+# Date : 2 October 2025
+# Purpose : Test et-portaudio installation
+
+OUT=$(which et-portaudio)
+exit $?
diff --git a/tests/test-fldigi.sh b/tests/test-fldigi.sh
new file mode 100755
index 0000000..8cb4197
--- /dev/null
+++ b/tests/test-fldigi.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# Author : Gaston Gonzalez
+# Date : 2 October 2025
+# Purpose : Test fldigi installation
+
+OUT=$(which fldigi)
+exit $?