USB Serial console server
If you ever ran a serial console server with a lot of USB dongles you'll find that the numbering of your devices may change due to un-re-plug events or when you reboot the machine where your USB adapters are attached to.
Please see the answers to my post from Poul-Henning Kamp and Daniel O'Connor. Also there is a review open D21886 highly related to this.
I have since (in a night hack; forgive the horrible shell) improved the script as I also like to have device names and not just serial numbers. In addition I have 4-port USB-Serial dongles which means I see the same serial number 4 times.
- /usr/local/etc/devd/usbserial.conf
attach 500 { #match "system" "USB"; #match "subsystem" "DEVICE"; match "device-name" "(uftdi|umodem|uplcom|uslcom)[0-9]*"; match "vendor" ".+"; match "product" ".+"; match "sernum" ".+"; action "/usr/local/libexec/usbserial ATTACH $sernum $ttyname $device-name"; #action "ln -fs /dev/cua$ttyname /dev/cua_$sernum"; }; notify 500 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "DETACH"; match "vendor" ".+"; match "product" ".+"; match "sernum" ".+"; action "/usr/local/libexec/usbserial $type $sernum $ttyname $device-name"; #action "rm -f /dev/cua_$sernum"; };
- /usr/local/libexec/usbserial (remove the first white space and make shell script root executable; hope the wiki doesn't mangle anything else, otherwise check the raw page)
#!/bin/sh MODE="$1" SERNUM="$2" TTYNAME="$3" DEVNAME="$4" if test -z "${MODE}" -o -z "${SERNUM}"; then logger -p daemon.err -t usbserial "$0 mandatory argument empty: '$1' '$2'" printf "$0 ERROR: mandatory argument empty: '$1' '$2'\n" >&2 exit 1 fi # Prefixes for tty and cua, for serial and name. CUA_S_PREFIX="/dev/cua.s." CUA_N_PREFIX="/dev/cua.n." TTY_S_PREFIX="/dev/tty.s." TTY_N_PREFIX="/dev/tty.n." S="${SERNUM}" NN="${SERNUM}" DETACHNODES="" case "${SERNUM}" in XXXXXXXX) NN="nanopc-t4.1500000" ;; FTYYYYY) FTYYYYY_S_0="${S}.0" FTYYYYY_S_1="${S}.1" FTYYYYY_S_2="${S}.2" FTYYYYY_S_3="${S}.3" FTYYYYY_N_0="amachine.9600" FTYYYYY_N_1="bsd42.115200" FTYYYYY_N_2="ccomp.19200" FTYYYYY_N_3="dlang.115200" case "${MODE}" in ATTACH) # 4 Ports; needs special treatment; 4x called on attach (assumed in order), 1x on detach if test -e ${CUA_S_PREFIX}${FTYYYYY_S_3}; then logger -p daemon.err -t usbserial "$0 4 port serial ${SERNUM} with more device nodes" printf "$0 ERROR: 4 port serial ${SERNUM} with more device nodes\n" >&2 exit 2 elif test -e ${CUA_S_PREFIX}${FTYYYYY_S_2}; then S="${FTYYYYY_S_3}" NN="${FTYYYYY_N_3}" elif test -e ${CUA_S_PREFIX}${FTYYYYY_S_1}; then S="${FTYYYYY_S_2}" NN="${FTYYYYY_N_2}" elif test -e ${CUA_S_PREFIX}${FTYYYYY_S_0}; then S="${FTYYYYY_S_1}" NN="${FTYYYYY_N_1}" else S="${FTYYYYY_S_0}" NN="${FTYYYYY_N_0}" fi ;; DETACH) DETACHNODES="${DETACHNODES} ${FTYYYYY_S_0}:${FTYYYYY_N_0}" DETACHNODES="${DETACHNODES} ${FTYYYYY_S_1}:${FTYYYYY_N_1}" DETACHNODES="${DETACHNODES} ${FTYYYYY_S_2}:${FTYYYYY_N_2}" DETACHNODES="${DETACHNODES} ${FTYYYYY_S_3}:${FTYYYYY_N_3}" ;; esac ;; *) logger -p daemon.info -t usbserial "$0 unknown serial device '${SERNUM}'" printf "$0 INFO: unknown serial device '${SERNUM}'\n" >&2 ;; esac case "${MODE}" in ATTACH) if test -z "${TTYNAME}"; then logger -p daemon.err -t usbserial "$0 no ttyname given for '${SERNUM}'" printf "$0 ERROR: no ttyname given for '${SERNUM}'\n" >&2 exit 1 fi logger -p daemon.notice -t usbserial "$0 creating symlinks for ${TTYNAME} -> ${S}" ln -sf cua${TTYNAME} ${CUA_S_PREFIX}${S} ln -sf tty${TTYNAME} ${TTY_S_PREFIX}${S} case "${NN}" in ${S}) ;; *) logger -p daemon.notice -t usbserial "$0 creating symlinks for ${TTYNAME} -> ${NN}" ln -sf cua${TTYNAME} ${CUA_N_PREFIX}${NN} ln -sf tty${TTYNAME} ${TTY_N_PREFIX}${NN} ;; esac ;; DETACH) # Strip any leading space. DETACHNODES=${DETACHNODES#* } case "${DETACHNODES}" in "") if test ! -L ${CUA_S_PREFIX}${S}; then logger -p daemon.notice -t usbserial "$0 SKIPPING removing symlinks for ${CUA_S_PREFIX}${S}: `ls -l ${CUA_S_PREFIX}${S}`" exit 0 fi logger -p daemon.notice -t usbserial "$0 removing symlinks for ${SERNUM} -> ${S} ${NN}" rm -f ${CUA_S_PREFIX}${S} ${TTY_S_PREFIX}${S} \ ${CUA_N_PREFIX}${NN} ${TTY_N_PREFIX}${NN} ;; [A-Za-z0-9]*) for x in ${DETACHNODES}; do s=${x%%:*} n=${x##*:} if test ! -L ${CUA_S_PREFIX}${s}; then logger -p daemon.notice -t usbserial "$0 SKIPPING removing symlinks for ${CUA_S_PREFIX}${s} / ${n}: `ls -l ${CUA_S_PREFIX}${s} ${CUA_S_PREFIX}${n}`" continue fi logger -p daemon.notice -t usbserial "$0 removing symlinks for ${SERNUM} -> ${s} ${n}" rm -f ${CUA_S_PREFIX}${s} ${TTY_S_PREFIX}${s} \ ${CUA_N_PREFIX}${n} ${TTY_N_PREFIX}${n} done ;; *) logger -p daemon.err -t usbserial "$0 unsupported detach nodes '${DETACHNODES}' for '${SERNUM}'" printf "$0 ERROR: unsupported number of detach nodes ${DETACHNODES} for '${SERNUM}'\n" >&2 exit 3 ;; esac ;; *) logger -p daemon.err -t usbserial "$0 mode '${MODE}' unknown for '${SERNUM}'" printf "$0 ERROR: mode '${MODE}' unknown for '${SERNUM}'\n" >&2 exit 1 ;; esac # end