Skip to content

Instantly share code, notes, and snippets.

@EmbeddedAndroid
Created November 2, 2026 13:13
Show Gist options
  • Select an option

  • Save EmbeddedAndroid/3de51907c36ea1a2a483bed037e7fc98 to your computer and use it in GitHub Desktop.

Select an option

Save EmbeddedAndroid/3de51907c36ea1a2a483bed037e7fc98 to your computer and use it in GitHub Desktop.
alpaca-edl-check.sh: QTAC's Alpaca bootToEDL sequence (bit 4 + power key), lists the USB devices that appear
#!/bin/bash
# Put an Alpaca (EPM) driven QRD into EDL the way Qualcomm's test automation
# controller does (bootToEDL in configurations/TAC_PSOC_44.tcnf, legacy
# command table in TACPSOCLegacyCommands.cpp), and report every USB device
# the board brings up, so a missing serial or an unexpected port shows.
#
# Run on the cdba host with cdba-server NOT holding the Alpaca tty.
# Usage: alpaca-edl-check.sh <alpaca tty> <edl serial> [tries]
# e.g. alpaca-edl-check.sh /dev/serial/by-id/usb-QUALCOMM_Inc._Embedded_Power_Measurement__EPM__device_6E02020C040C1F14-if01 AAFD8CDA 3
# CONTROL=1 runs the same sequence without the EDL bit (expect no 9008).
# PKEY_MS (1300) is QTAC's EDL power key hold; WAIT_S (15) bounds the 9008 wait.
#
# Alpaca outputs (fixed by the Alpaca firmware, same on every board):
# devicePower 1/0 board power on/off
# usbDevicePower 1/0 board USB connected/disconnected
# ttl outputBit 1 power key, 1 = pressed
# ttl outputBit 2 volume down (cdba's fastboot key)
# ttl outputBit 4 primary EDL (force USB boot), 1 = asserted
set -u
tty=${1:?alpaca tty}; want=${2:?edl serial, e.g. AAFD8CDA}; tries=${3:-3}
pkey_ms=${PKEY_MS:-1300}; wait_s=${WAIT_S:-15}; control=${CONTROL:-0}
usb=${SYSFS_USB:-/sys/bus/usb/devices}
log=$(mktemp /tmp/alpaca-edl-check.XXXXXX)
if [ -n "${DRYRUN:-}" ]; then
cmd() { echo "> $*"; }
ms() { echo " (sleep ${1} ms)"; }
else
stty -F "$tty" 115200 raw -echo cs8 clocal cread || exit 1
cat "$tty" >> "$log" & reader=$!
trap 'kill $reader 2>/dev/null' EXIT
cmd() { printf '%s\r' "$*" > "$tty"; sleep 0.1; }
ms() { sleep "$(awk "BEGIN{print $1/1000}")"; }
fi
# One line per Qualcomm or fastboot USB device: <port path> <vid:pid> product=.. serial=..
snapshot() {
local d v p
for d in "$usb"/*; do
[ -r "$d/idVendor" ] || continue
v=$(cat "$d/idVendor"); p=$(cat "$d/idProduct")
case "$v" in 05c6|18d1) ;; *) continue ;; esac
printf '%s %s:%s product=%s serial=%s\n' "${d##*/}" "$v" "$p" \
"$(cat "$d/product" 2>/dev/null || echo -)" \
"$(cat "$d/serial" 2>/dev/null || echo -)"
done | sort
}
# EDL serial is the "_SN:<serial>" token of iProduct (qdl --serial matches the same token).
edl_match() {
grep ' 05c6:9008 ' | grep -i "_SN:${want}\(_\| \|\$\)"
}
all_off() {
cmd devicePower 0
cmd usbDevicePower 0
cmd ttl outputBit 1 0
cmd ttl outputBit 2 0
cmd ttl outputBit 4 0
}
boot_to_edl() {
all_off
[ "$control" = 1 ] || cmd ttl outputBit 4 1
ms 500
cmd devicePower 1
ms 900
cmd usbDevicePower 1
ms 30
cmd ttl outputBit 1 1
ms "$pkey_ms"
cmd ttl outputBit 1 0
cmd ttl outputBit 4 0
}
all_off; [ -n "${DRYRUN:-}" ] || sleep 3
before=$(snapshot)
if printf '%s\n' "$before" | edl_match >/dev/null; then
echo "EDL device $want is already present with the board off: another board or a stale device; stop."
printf '%s\n' "$before"; exit 2
fi
hits=0
for i in $(seq 1 "$tries"); do
echo "== try $i/$tries ($([ "$control" = 1 ] && echo control, EDL bit not set || echo EDL bit 4 high))"
boot_to_edl
got=; new=
for _ in $(seq 1 "$wait_s"); do
[ -n "${DRYRUN:-}" ] || sleep 1
now=$(snapshot)
new=$(comm -13 <(printf '%s\n' "$before") <(printf '%s\n' "$now"))
got=$(printf '%s\n' "$new" | edl_match) && break
done
echo "new USB devices:"; printf ' %s\n' "${new:-(none)}"
if [ -n "$got" ]; then
echo "EDL: $got"; hits=$((hits + 1))
elif printf '%s\n' "$new" | grep -q ' 05c6:9008 '; then
echo "EDL device present but without _SN:$want (see product/serial above)"
else
echo "no EDL device"
fi
all_off; [ -n "${DRYRUN:-}" ] || sleep 3
done
echo "== Alpaca replies (look for 'Command not recognized'):"
tr '\r' '\n' < "$log" | grep -v '^$' | sort | uniq -c | sort -rn | head -20
rm -f "$log"
echo "RESULT: $hits/$tries tries reached EDL $want ($([ "$control" = 1 ] && echo control || echo bit 4))"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment