#!/bin/sh # som-console -- find the SOM's serial console among the USB-serial ports this # machine was granted, and open it. # # The console of an Emcraft SOM carrier is the carrier's own USB-to-UART # bridge: an FTDI FT232RL (0403:6001) on the SOM-BSB-EXT, a Silicon Labs CP2104 # (10c4:ea60) on the UCL-SOM-BSB starter kit, an FTDI FT230X (0403:6015) on the # SOM-NRF9151 starter kit. It reaches the guest as a WebUSB # grant of its own, separate from the JTAG adapter, and ftdi_sio or cp210x binds # it as a /dev/ttyUSB. The number depends on grant order -- the Olimex's # second interface is a UART too, and ftdi_sio takes a ttyUSB for it -- so the # port is found by USB identity, never assumed. 0403:6001 is a generic FTDI id, # so where two such bridges are granted, --serial names the one. # # som-console open the console in picocom (C-a C-x leaves) # som-console --find print the device node and exit # som-console --list list every USB-serial port with its identity # # Scripts (Expect; som-mfg-f7) take the node from --find: # spawn picocom -q -b 115200 [exec som-console --find] # # The interactive console takes the board's one lock (som-lock), shared with # som-program-nrf91, som-recover-nrf91 and som-test-nrf91, for as long as # picocom runs: held by another command, it names the holder and exits 4. # --find and --list take no lock. set -u PROG=som-console IDS="${SOM_CONSOLE_ID:-0403:6001 0403:6015 10c4:ea60}" SERIAL="${SOM_CONSOLE_SERIAL:-}" BAUD="${SOM_CONSOLE_BAUD:-115200}" # Overridable so the resolution can be exercised against a constructed tree. SYSFS="${SOM_SYSFS:-/sys}" DEVDIR="${SOM_DEVDIR:-/dev}" mode=open dev="" usage() { cat <&2; usage >&2; exit 2 ;; esac done for id in $IDS; do case "$id" in [0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]) ;; *) echo "$PROG: --id wants VID:PID in hex, got '$id'" >&2; exit 2 ;; esac done IDS=$(printf '%s' "$IDS" | tr 'A-F' 'a-f') WANT="$IDS${SERIAL:+ serial $SERIAL}" # The ports that match: id among $IDS, and the serial if one was given. matching() { ports | awk -v ids=" $IDS " -v ser="$SERIAL" \ 'index(ids, " " $3 " ") && (ser == "" || ($4 "") == (ser ""))' } # One line per USB-serial port: " ". The tty's # sysfs node sits under its interface, and the interface under the USB device # that carries idVendor/idProduct. ports() { for t in "$SYSFS"/bus/usb-serial/devices/*; do [ -e "$t" ] || continue tty=${t##*/} real=$(cd -P "$t" 2>/dev/null && pwd -P) || continue usbdev=${real%/*}; usbdev=${usbdev%/*} vid=$(cat "$usbdev/idVendor" 2>/dev/null) || vid=???? pid=$(cat "$usbdev/idProduct" 2>/dev/null) || pid=???? ser=$(cat "$usbdev/serial" 2>/dev/null) || ser=- drv=- if [ -e "$t/driver" ]; then d=$(cd -P "$t/driver" 2>/dev/null && pwd -P) && drv=${d##*/} fi echo "$tty $drv $vid:$pid ${ser:--}" done } if [ "$mode" = list ]; then out=$(ports) if [ -z "$out" ]; then echo "$PROG: no USB-serial ports -- has the console adapter been granted to this machine?" else # echo, not printf: on the served runtime printf to a tty fails (rc=1, nothing shown) right after a child exits. echo "$out" fi exit 0 fi if [ -z "$dev" ]; then hits=$(matching | awk '{ print $1 }') n=$(printf '%s' "$hits" | grep -c .) if [ "$n" -eq 0 ]; then echo "$PROG: no USB-serial port matching $WANT -- grant the SOM carrier's console (the USB-UART bridge on its miniUSB) to this machine" >&2 all=$(ports) [ -n "$all" ] && { echo "$PROG: ports present:" >&2; printf '%s\n' "$all" | sed 's/^/ /' >&2; } exit 1 fi if [ "$n" -gt 1 ]; then echo "$PROG: $n ports match $WANT -- name one with --serial or --dev:" >&2 matching | sed 's/^/ /' >&2 exit 1 fi dev="$DEVDIR/$hits" fi if [ "$mode" = find ]; then echo "$dev" exit 0 fi [ -c "$dev" ] || { echo "$PROG: $dev is not a character device" >&2; exit 1; } command -v picocom >/dev/null 2>&1 || { echo "$PROG: picocom is not installed" >&2; exit 1; } # picocom runs as a child, not exec'd, so the lock is released when it leaves; # a console killed outright leaves a holder that is gone, which the next take # takes over. locked=0 if command -v som-lock >/dev/null 2>&1; then if why=$(som-lock take "$PROG" $$); then locked=1 trap '[ "$locked" -eq 0 ] || som-lock release $$' EXIT trap 'exit 129' HUP trap 'exit 143' TERM else echo "$PROG: FAIL -- ${why:-cannot take the board lock ${SOM_LOCK:-/tmp/som-board.lock}}; nothing was done" >&2 exit 4 fi fi echo "$PROG: $dev at $BAUD 8N1 -- C-a C-x leaves" picocom -b "$BAUD" "$dev"