xref: /netbsd-src/share/examples/devpubd/hooks/99-ucom-symlinks (revision 70f7362772ba52b749c976fb5e86e39a8b2c9afc)
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
27export LC_ALL=C
28
29event="$1"
30shift
31devices=$@
32
33symlink_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
63remove_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
78add_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
121for 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
134done
135