Home | History | Annotate | Line # | Download | only in hooks
99-ucom-symlinks revision 1.1
      1 #!/bin/sh -
      2 #
      3 # $NetBSD: 99-ucom-symlinks,v 1.1 2024/03/30 06:29:01 thorpej Exp $
      4 #
      5 # Attempt to create stable names (using symbolic links) to USB serial
      6 # devices, regardless of device enumeration order, suitable for use in
      7 # configuration files.  The format of the stable names is:
      8 #
      9 #	/dev/{cdt}ty-$driver-$serialnumber-$portnumber
     10 # - or -
     11 #	/dev/{cdt}ty-$driver-$serialnumber
     12 #
     13 # depending on whether or not the device is a multi-port adapter.
     14 #
     15 # e.g.
     16 #
     17 #	/dev/tty-uftdi-FT64S4YP-1 -> /dev/ttyU0
     18 #
     19 #	/dev/tty-uslsa-01E7ABCC -> /dev/ttyU4
     20 #
     21 # If $driver or $serialnumber cannot be determined, then no symbolic link
     22 # will be created.
     23 #
     24 # Written by Jason R. Thorpe, December 2022.  Public domain.
     25 #
     26 
     27 export LC_ALL=C
     28 
     29 event="$1"
     30 shift
     31 devices=$@
     32 
     33 symlink_name()
     34 {
     35 	local parent
     36 	local portnum
     37 	local serialnum
     38 	local driver
     39 
     40 	parent=$(drvctl -p $1 device-parent)
     41 	if [ x"$parent" != x ]; then
     42 		driver=$(drvctl -p $parent device-driver)
     43 		serialnum=$(drvctl -p $parent serialnumber)
     44 	fi
     45 
     46 	# If the device is a single-port device, it may have the default
     47 	# port number locator of '-1'.  In that case, elide the port
     48 	# number.
     49 	portnum=$(drvctl -p $1 port)
     50 	if [ x"$portnum" = x"-1" -o x"$portnum" = x ]; then
     51 		portnum=""
     52 	else
     53 		portnum="-${portnum}"
     54 	fi
     55 
     56 	if [ x"$driver" != x -a x"$serialnum" != x ]; then
     57 		echo "${driver}-${serialnum}${portnum}"
     58 	else
     59 		echo ""
     60 	fi
     61 }
     62 
     63 remove_ucom_symlink()
     64 {
     65 	local name
     66 	local unit
     67 
     68 	name=$(readlink "/dev/${1}")
     69 
     70 	if [ x"$name" != x ]; then
     71 		rm -f "/dev/tty-${name}"
     72 		rm -f "/dev/dty-${name}"
     73 		rm -f "/dev/cty-${name}"
     74 		rm -f "/dev/${1}"
     75 	fi
     76 }
     77 
     78 add_ucom_symlink()
     79 {
     80 	local name
     81 	local tty_path
     82 	local dty_path
     83 	local cty_path
     84 
     85 	name=$(symlink_name $1)
     86 	unit=$(drvctl -p $1 device-unit)
     87 
     88 	if [ x"$name" != x -a x"$unit" != x ]; then
     89 		#
     90 		# We need to make two sets of symlinks:
     91 		#
     92 		# /dev/tty-uslsa-01E7ABCC -> /dev/ttyU4
     93 		#
     94 		# /dev/ucom4 -> uslsa-01E7ABCC
     95 		#
     96 		# This is needed because when we get the detach event
     97 		# for e.g. ucom4, the parent device (e.g. uslsa0) may
     98 		# already be gone, meaning we cannot query it.  So
     99 		# what we're doing is stashing the information in the
    100 		# second symlink so we can readlink(1) it later to
    101 		# recover the stable name.
    102 		#
    103 
    104 		tty_path="/dev/ttyU${unit}"
    105 		dty_path="/dev/dtyU${unit}"
    106 		cty_path="/dev/ctyU${unit}"
    107 
    108 		ln -sf "${name}" "/dev/${1}"
    109 		if [ -c ${tty_path} ]; then
    110 			ln -sf ${tty_path} "/dev/tty-${name}"
    111 		fi
    112 		if [ -c ${dty_path} ]; then
    113 			ln -sf ${dty_path} "/dev/dty-${name}"
    114 		fi
    115 		if [ -c ${cty_path} ]; then
    116 			ln -sf ${cty_path} "/dev/cty-${name}"
    117 		fi
    118 	fi
    119 }
    120 
    121 for device in $devices; do
    122 	case $device in
    123 	ucom*)
    124 		case $event in
    125 		device-attach)
    126 			remove_ucom_symlink $device
    127 			add_ucom_symlink $device
    128 			;;
    129 		device-detach)
    130 			remove_ucom_symlink $device
    131 			;;
    132 		esac
    133 	esac
    134 done
    135