#!/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. 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, BRINTOS-12) take the node from --find: # spawn picocom -q -b 115200 [exec som-console --find] set -u PROG=som-console IDS="${SOM_CONSOLE_ID:-0403:6001 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; } echo "$PROG: $dev at $BAUD 8N1 -- C-a C-x leaves" exec picocom -b "$BAUD" "$dev"