11.1Sthorpej#!/bin/sh -
21.1Sthorpej#
31.1Sthorpej# $NetBSD: 99-ucom-symlinks,v 1.1 2024/03/30 06:29:01 thorpej Exp $
41.1Sthorpej#
51.1Sthorpej# Attempt to create stable names (using symbolic links) to USB serial
61.1Sthorpej# devices, regardless of device enumeration order, suitable for use in
71.1Sthorpej# configuration files.  The format of the stable names is:
81.1Sthorpej#
91.1Sthorpej#	/dev/{cdt}ty-$driver-$serialnumber-$portnumber
101.1Sthorpej# - or -
111.1Sthorpej#	/dev/{cdt}ty-$driver-$serialnumber
121.1Sthorpej#
131.1Sthorpej# depending on whether or not the device is a multi-port adapter.
141.1Sthorpej#
151.1Sthorpej# e.g.
161.1Sthorpej#
171.1Sthorpej#	/dev/tty-uftdi-FT64S4YP-1 -> /dev/ttyU0
181.1Sthorpej#
191.1Sthorpej#	/dev/tty-uslsa-01E7ABCC -> /dev/ttyU4
201.1Sthorpej#
211.1Sthorpej# If $driver or $serialnumber cannot be determined, then no symbolic link
221.1Sthorpej# will be created.
231.1Sthorpej#
241.1Sthorpej# Written by Jason R. Thorpe, December 2022.  Public domain.
251.1Sthorpej#
261.1Sthorpej
271.1Sthorpejexport LC_ALL=C
281.1Sthorpej
291.1Sthorpejevent="$1"
301.1Sthorpejshift
311.1Sthorpejdevices=$@
321.1Sthorpej
331.1Sthorpejsymlink_name()
341.1Sthorpej{
351.1Sthorpej	local parent
361.1Sthorpej	local portnum
371.1Sthorpej	local serialnum
381.1Sthorpej	local driver
391.1Sthorpej
401.1Sthorpej	parent=$(drvctl -p $1 device-parent)
411.1Sthorpej	if [ x"$parent" != x ]; then
421.1Sthorpej		driver=$(drvctl -p $parent device-driver)
431.1Sthorpej		serialnum=$(drvctl -p $parent serialnumber)
441.1Sthorpej	fi
451.1Sthorpej
461.1Sthorpej	# If the device is a single-port device, it may have the default
471.1Sthorpej	# port number locator of '-1'.  In that case, elide the port
481.1Sthorpej	# number.
491.1Sthorpej	portnum=$(drvctl -p $1 port)
501.1Sthorpej	if [ x"$portnum" = x"-1" -o x"$portnum" = x ]; then
511.1Sthorpej		portnum=""
521.1Sthorpej	else
531.1Sthorpej		portnum="-${portnum}"
541.1Sthorpej	fi
551.1Sthorpej
561.1Sthorpej	if [ x"$driver" != x -a x"$serialnum" != x ]; then
571.1Sthorpej		echo "${driver}-${serialnum}${portnum}"
581.1Sthorpej	else
591.1Sthorpej		echo ""
601.1Sthorpej	fi
611.1Sthorpej}
621.1Sthorpej
631.1Sthorpejremove_ucom_symlink()
641.1Sthorpej{
651.1Sthorpej	local name
661.1Sthorpej	local unit
671.1Sthorpej
681.1Sthorpej	name=$(readlink "/dev/${1}")
691.1Sthorpej
701.1Sthorpej	if [ x"$name" != x ]; then
711.1Sthorpej		rm -f "/dev/tty-${name}"
721.1Sthorpej		rm -f "/dev/dty-${name}"
731.1Sthorpej		rm -f "/dev/cty-${name}"
741.1Sthorpej		rm -f "/dev/${1}"
751.1Sthorpej	fi
761.1Sthorpej}
771.1Sthorpej
781.1Sthorpejadd_ucom_symlink()
791.1Sthorpej{
801.1Sthorpej	local name
811.1Sthorpej	local tty_path
821.1Sthorpej	local dty_path
831.1Sthorpej	local cty_path
841.1Sthorpej
851.1Sthorpej	name=$(symlink_name $1)
861.1Sthorpej	unit=$(drvctl -p $1 device-unit)
871.1Sthorpej
881.1Sthorpej	if [ x"$name" != x -a x"$unit" != x ]; then
891.1Sthorpej		#
901.1Sthorpej		# We need to make two sets of symlinks:
911.1Sthorpej		#
921.1Sthorpej		# /dev/tty-uslsa-01E7ABCC -> /dev/ttyU4
931.1Sthorpej		#
941.1Sthorpej		# /dev/ucom4 -> uslsa-01E7ABCC
951.1Sthorpej		#
961.1Sthorpej		# This is needed because when we get the detach event
971.1Sthorpej		# for e.g. ucom4, the parent device (e.g. uslsa0) may
981.1Sthorpej		# already be gone, meaning we cannot query it.  So
991.1Sthorpej		# what we're doing is stashing the information in the
1001.1Sthorpej		# second symlink so we can readlink(1) it later to
1011.1Sthorpej		# recover the stable name.
1021.1Sthorpej		#
1031.1Sthorpej
1041.1Sthorpej		tty_path="/dev/ttyU${unit}"
1051.1Sthorpej		dty_path="/dev/dtyU${unit}"
1061.1Sthorpej		cty_path="/dev/ctyU${unit}"
1071.1Sthorpej
1081.1Sthorpej		ln -sf "${name}" "/dev/${1}"
1091.1Sthorpej		if [ -c ${tty_path} ]; then
1101.1Sthorpej			ln -sf ${tty_path} "/dev/tty-${name}"
1111.1Sthorpej		fi
1121.1Sthorpej		if [ -c ${dty_path} ]; then
1131.1Sthorpej			ln -sf ${dty_path} "/dev/dty-${name}"
1141.1Sthorpej		fi
1151.1Sthorpej		if [ -c ${cty_path} ]; then
1161.1Sthorpej			ln -sf ${cty_path} "/dev/cty-${name}"
1171.1Sthorpej		fi
1181.1Sthorpej	fi
1191.1Sthorpej}
1201.1Sthorpej
1211.1Sthorpejfor device in $devices; do
1221.1Sthorpej	case $device in
1231.1Sthorpej	ucom*)
1241.1Sthorpej		case $event in
1251.1Sthorpej		device-attach)
1261.1Sthorpej			remove_ucom_symlink $device
1271.1Sthorpej			add_ucom_symlink $device
1281.1Sthorpej			;;
1291.1Sthorpej		device-detach)
1301.1Sthorpej			remove_ucom_symlink $device
1311.1Sthorpej			;;
1321.1Sthorpej		esac
1331.1Sthorpej	esac
1341.1Sthorpejdone
135