First commit
This commit is contained in:
Executable
+154
@@ -0,0 +1,154 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Open the TranspOtter serial console.
|
||||
#
|
||||
# ./console.sh minicom, port auto-detected
|
||||
# ./console.sh /dev/ttyACM1 force a port
|
||||
# ./console.sh -m use `pio device monitor` instead
|
||||
# ./console.sh -r raw stty/cat fallback, no terminal program
|
||||
# ./console.sh -l list candidate ports and exit
|
||||
#
|
||||
# Exit minicom with Ctrl-A X.
|
||||
set -euo pipefail
|
||||
|
||||
PROFILE_NAME=transpotter
|
||||
PROFILE="$HOME/.minirc.$PROFILE_NAME"
|
||||
BAUD=115200
|
||||
MODE=minicom
|
||||
PORT="${TRANSPOTTER_PORT:-}"
|
||||
|
||||
# Print the comment block at the top of this file, stopping at the first line
|
||||
# of actual code, so the help text cannot drift out of sync with it.
|
||||
usage() { awk 'NR>2 && /^#/ { sub(/^# ?/, ""); print; next } NR>2 { exit }' "$0"; }
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-m|--monitor) MODE=monitor ;;
|
||||
-r|--raw) MODE=raw ;;
|
||||
-l|--list) MODE=list ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
-*) echo "unknown option: $1" >&2; usage >&2; exit 2 ;;
|
||||
*) PORT="$1" ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# --- find the board ----------------------------------------------------------
|
||||
# by-id first: the name is stable across replugs and unambiguous when several
|
||||
# USB serial devices are attached. Falls back to matching Espressif's USB vendor
|
||||
# id (0x303a) in sysfs, then to the usual device node.
|
||||
list_ports() {
|
||||
local found=0
|
||||
for l in /dev/serial/by-id/*Espressif*; do
|
||||
[ -e "$l" ] && { echo "$l"; found=1; }
|
||||
done
|
||||
for d in /sys/class/tty/ttyACM* /sys/class/tty/ttyUSB*; do
|
||||
[ -e "$d" ] || continue
|
||||
[ "$(cat "$d/device/../idVendor" 2>/dev/null)" = "303a" ] || continue
|
||||
echo "/dev/$(basename "$d")"; found=1
|
||||
done
|
||||
[ "$found" -eq 0 ] && [ -e /dev/ttyACM0 ] && echo /dev/ttyACM0
|
||||
return 0
|
||||
}
|
||||
|
||||
if [ "$MODE" = list ]; then
|
||||
echo "candidate ports:"; list_ports | sort -u | sed 's/^/ /'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -z "$PORT" ]; then
|
||||
PORT="$(list_ports | head -1 || true)"
|
||||
fi
|
||||
|
||||
if [ -z "$PORT" ] || [ ! -e "$PORT" ]; then
|
||||
echo "error: no serial port found." >&2
|
||||
echo " Plug the ESP32 in, or pass one explicitly: $0 /dev/ttyACM0" >&2
|
||||
echo " '$0 -l' lists candidates." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -w "$PORT" ]; then
|
||||
echo "error: $PORT is not writable. You likely need to be in the 'plugdev'" >&2
|
||||
echo " or 'dialout' group: sudo usermod -aG plugdev \$USER (then re-login)." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# A second reader steals half the bytes and makes the console look broken — and
|
||||
# blocks `pio run -t upload` outright. fuser/lsof are often not installed, so
|
||||
# walk /proc instead: our own processes' fds are always readable.
|
||||
port_holders() {
|
||||
local target pid
|
||||
target="$(readlink -f "$1" 2>/dev/null)" || return 0
|
||||
for l in /proc/[0-9]*/fd/*; do
|
||||
[ -e "$l" ] || continue
|
||||
[ "$(readlink -f "$l" 2>/dev/null)" = "$target" ] || continue
|
||||
pid="${l#/proc/}"; pid="${pid%%/*}"
|
||||
[ "$pid" = "$$" ] && continue
|
||||
echo "$pid $(tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null)"
|
||||
done | sort -u
|
||||
}
|
||||
|
||||
HOLDERS="$(port_holders "$PORT")"
|
||||
if [ -n "$HOLDERS" ]; then
|
||||
echo "warning: something else already has $PORT open:" >&2
|
||||
printf '%s\n' "$HOLDERS" | sed 's/^/ /' >&2
|
||||
echo " close it first — two readers split the bytes between them," >&2
|
||||
echo " and an upload cannot open the port at all." >&2
|
||||
fi
|
||||
|
||||
# --- alternate modes ---------------------------------------------------------
|
||||
case "$MODE" in
|
||||
monitor)
|
||||
exec pio device monitor -p "$PORT" -b "$BAUD"
|
||||
;;
|
||||
raw)
|
||||
echo "raw mode on $PORT — type a command and press Enter, Ctrl-C to quit."
|
||||
stty -F "$PORT" "$BAUD" raw -echo -crtscts
|
||||
cat "$PORT" &
|
||||
CATPID=$!
|
||||
trap 'kill $CATPID 2>/dev/null || true' EXIT
|
||||
while IFS= read -r line; do printf '%s\n' "$line" > "$PORT"; done
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# --- minicom -----------------------------------------------------------------
|
||||
command -v minicom >/dev/null 2>&1 || {
|
||||
echo "error: minicom is not installed. Try '$0 -m' (pio device monitor)" >&2
|
||||
echo " or '$0 -r' (raw), or: sudo apt install minicom" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Three minicom defaults make this board awkward, so the profile is written
|
||||
# rather than assumed:
|
||||
# rtscts No - the C3's USB CDC never asserts CTS, and minicom defaults
|
||||
# hardware flow control ON, silently blocking every keystroke.
|
||||
# localecho - the firmware does not echo, so without this nothing appears
|
||||
# as you type and the terminal seems unresponsive.
|
||||
# addcarreturn - turns a bare LF into CR+LF on the way in. Firmware that
|
||||
# prints "\n" without "\r" otherwise staircases off the right
|
||||
# of the screen. Harmless when the firmware already sends
|
||||
# CR+LF, so it is on regardless.
|
||||
WANT=$(cat <<PROFILE_EOF
|
||||
# Written by $(basename "$0") — see that script for why these matter.
|
||||
pu port $PORT
|
||||
pu baudrate $BAUD
|
||||
pu bits 8
|
||||
pu parity N
|
||||
pu stopbits 1
|
||||
pu rtscts No
|
||||
pu xonxoff No
|
||||
pu localecho Yes
|
||||
pu addcarreturn Yes
|
||||
PROFILE_EOF
|
||||
)
|
||||
# Rewrite whenever it differs, so a stale profile cannot quietly reintroduce
|
||||
# any of the problems above.
|
||||
if [ ! -f "$PROFILE" ] || [ "$(cat "$PROFILE")" != "$WANT" ]; then
|
||||
printf '%s\n' "$WANT" > "$PROFILE"
|
||||
echo "wrote $PROFILE"
|
||||
fi
|
||||
|
||||
echo "connecting to $PORT at $BAUD (Ctrl-A X to quit, Ctrl-A Z for help)"
|
||||
echo "note: opening the port resets the ESP32 — expect the boot banner."
|
||||
exec minicom "$PROFILE_NAME" -D "$PORT"
|
||||
Reference in New Issue
Block a user