HEX
Server: Apache/2.2.34 (Unix) mod_fastcgi/mod_fastcgi-SNAP-0910052141
System: Linux Kou-Etsu-Dou 4.4.59+ #25556 SMP PREEMPT Thu Mar 4 18:03:46 CST 2021 x86_64
User: hosam (1026)
PHP: 7.2.29
Disabled: NONE
Upload Files
File: //lib64/udev/script/tty-util.sh
#!/bin/sh
# Copyright (c) 2000-2013 Synology Inc. All rights reserved.

USBMODEM_INFO="/tmp/usbmodem.info"
ADD_HANDLER_LOCK="/tmp/lock/lock_add_usbmodem_info"
TTYDEBUG="/tmp/ttydebug"

# copy from usb.agent
get_usbdev_number ()
{
	local BusDev=""
	local Digtal=""
	local busnum=""
	local devnum=""

	DEVICE=""
	#To fix bug [16677], we should search usbdev number from the nearest dev entry.
	#So the search logic change to "/sys/${PHYSDEVPATH}/../", then "/sys/${PHYSDEVPATH}/../../../../".
	#ex: PHYSDEVPATH=/devices/pci0000:00/0000:00:0e.1/usb1/1-3/1-3:1.2/host11/target11:0:0/11:0:0:0
	#ex: PHYSDEVPATH=/devices/pci0000:00/0000:00:0e.1/usb1/1-3/1-3:1.1
	#ex: PHYSDEVPATH=/devices/platform/orion-ehci.0/usb1/1-1/1-1.2/1-1.2:1.2/host4/target4:0:0/4:0:0:0
	#ex: PHYSDEVPATH=/devices/platform/orion-ehci.0/usb1/1-1/1-1.2/1-1.2.1/1-1.2.1:1.0/host6/target6:0:0/6:0:0:0
	local PHYSDEVPATH_TMP=`echo ${PHYSDEVPATH} | sed -e 's#/\(.*\)\([0-9]*-[0-9]*\(\.*[0-9]*\)*\)/.*#\1\2#'`
	for i in `/usr/bin/seq 1 5`; do
		#If sysfs kobject not ready, we will retry 5 times
		BusDev=`(cd /sys/${PHYSDEVPATH_TMP}/; ls -d usb_device:usbdev*) |  cut -d : -f 2 | cut -c 7-`
		#(6281)kernel 2.6.38 change the device file position
		if [ -z "${BusDev}" ]; then
			BusDev=`(cd /sys/${PHYSDEVPATH_TMP}/; ls -d usb_device/usbdev*) | sed 's/\//:/g' |  cut -d : -f 2 | cut -c 7-`
		fi
		# Fix file path on northstarplus & liinux 3.10
		if [ -z "${BusDev}" -a ! -z $BUSNUM -a ! -z $DEVNUM ]; then
			BusDev=`/usr/bin/printf "%d.%d" $BUSNUM $DEVNUM`
		fi
		if [ "${BusDev}" != "" ]; then
			break;
		fi
		sleep 1;
	done
	DEVICE="/proc/bus/usb/"

	Digtal=`echo ${BusDev} | cut -d . -f 1 | wc -c`
	Digtal=$((${Digtal}-1))         # Remove the \n count
	Digtal=$((3-${Digtal}))         # How many zero do we need
	while [ "$Digtal" -gt 0 ]
	do
		DEVICE="${DEVICE}0"
		Digtal=$((${Digtal}-1))
	done
	DEVICE=${DEVICE}`echo ${BusDev} | cut -d . -f 1`
	DEVICE="${DEVICE}/"

	Digtal=`echo ${BusDev} | cut -d . -f 2 | wc -c`
	Digtal=$((${Digtal}-1))		# Remove the \n count
	Digtal=$((3-${Digtal}))		# How many zero do we need
	while [ "$Digtal" -gt 0 ]
	do
		DEVICE="${DEVICE}0"
		Digtal=$((${Digtal}-1))
	done
	DEVICE=${DEVICE}`echo ${BusDev} | cut -d . -f 2`
}

# find out if the node can use for connection
# which have keyword "Interrupt" in node's path
get_usbmodem_node_type_interrupt ()
{
	local current_node_num=$1
	# ex: /sys/devices/pci0000:00/0000:00:1d.7/usb6/6-3/6-3:1.4/ttyUSB4
	#  -> /sys/devices/pci0000:00/0000:00:1d.7/usb6/6-3/6-3:1.4/
	local devdirpath=`/usr/bin/dirname /sys$PHYSDEVPATH`
	# ex: /sys/devices/pci0000:00/0000:00:1d.7/usb6/6-3/6-3:1.4/ep_86/type:Interrupt
	local interrupt_node_cnt=`/bin/grep -r Interrupt $devdirpath | /usr/bin/wc -l`

	echo "interrupt_node_cnt $interrupt_node_cnt" >> $TTYDEBUG

	get_usbmodem_info_file_name
	local file="${USBMODEM_INFO_FILE}"

	CONNECTNODE=`/bin/cat $file | /bin/grep CONNECTNODE= | /usr/bin/cut -d '=' -f2`

	# interrupt node is not found
	if [ 0 -eq $interrupt_node_cnt ]; then
		return
	fi

	# most dongle has only one port with Interrupt
	# for some dongle, ex: sierra at&t
	# has more than one Interrupt node, ex: ttyUSB3 & ttyUSB4
	# first one should be query node
	# let the last one replace the previous one
	if [ -z "$CONNECTNODE" ] || [ "$current_node_num" -ge "$CONNECTNODE" ] ; then
		CONNECTNODE=$current_node_num
	fi

	echo "CONNECTNODE $CONNECTNODE" >> $TTYDEBUG
}

get_usbmodem_id ()
{
	local PHYSDEVPATH_TMP=`echo ${PHYSDEVPATH} | sed -e 's#/\(.*\)\([0-9]*-[0-9]*\(\.*[0-9]*\)*\)/.*#\1\2#'`
	local enum_path="`ls -d /sys/${PHYSDEVPATH_TMP}/usb_device:usbdev*`"

	# for different kernel version, the enum path may be different
	if [ -z "${enum_path}" ]; then
		enum_path="`ls -d /sys/${PHYSDEVPATH_TMP}/usb_device/usbdev*`"
	fi
	# Fix file path on northstarplus & liinux 3.10
	if [ -z "${enum_path}" ]; then
		enum_path="`ls -d /sys/${PHYSDEVPATH_TMP}/`"
	fi

	local timeout=1

	while [ 3 -ge ${timeout} ]; do
		USB_VENDOR=`cat $enum_path/device/idVendor`
		USB_PRODUCT=`cat $enum_path/device/idProduct`

		# Fix file path on northstarplus & liinux 3.10
		if [ -z "${USB_VENDOR}" ]; then
			USB_VENDOR=`cat $enum_path/idVendor`
		fi
		if [ -z "${USB_PRODUCT}" ]; then
			USB_PRODUCT=`cat $enum_path/idProduct`
		fi

		if [ ! -z "${USB_VENDOR}" -a ! -z "${USB_PRODUCT}" ]; then
			break
		fi

		timeout=`expr $timeout + 1`
		sleep 1;
	done
}

check_device_to_skip ()
{
	# Vendor=04d8 ProdID=000a
	# this is LCD monitor used by bromolow, driver is cdc-acm, but it is not usbmodem
	if [ "x04d8" == "x${USB_VENDOR}" -a "x000a" == "x${USB_PRODUCT}" ]; then
		exit 0
	fi
}

enum_tty_node_on_same_device ()
{
	get_usbmodem_info_file_name
	local file="${USBMODEM_INFO_FILE}"
	# ex: /dev/ttyUSB0 -> 0
	local current_node_num=`/bin/echo $DEVNAME | /bin/sed 's/[^0-99]//g'`

	DEVICENODE=`/bin/cat $file | /bin/grep DEVICENODE= | /usr/bin/cut -d '=' -f2`

	if [ -z "$DEVICENODE" ]; then
		DEVICENODE=$current_node_num
	else
		local nodearray=$DEVICENODE','$current_node_num
		# replace comma with newline, do sort, replace newline with comma, delete the last comma
		DEVICENODE=`/bin/echo $nodearray | /bin/sed 's/,/\n/g' | /usr/bin/sort -n | /usr/bin/tr '\n' ',' | /bin/sed s/.$//g`
	fi

	echo "DEVICENODE $DEVICENODE" >> $TTYDEBUG

	get_usbmodem_node_type_interrupt $current_node_num
}

remove_tty_node_on_same_device ()
{
	file="$1"
	# ex: /dev/ttyUSB0 -> 0
	local current_node_num=`/bin/echo $DEVNAME | /bin/sed 's/[^0-99]//g'`

	DEVICENODE=`/bin/cat $file | /bin/grep DEVICENODE= | /usr/bin/cut -d '=' -f2 | /bin/sed 's/,/ /g'`

	if [ -z "$DEVICENODE" ]; then
		return
	fi

	# remove the node number from array
	# ex: DEVICENODE=0,1,2,3	current_node_num=1
	#		nodearray shoud be 0,2,3
	local nodearray=""
	for eachnode in $DEVICENODE; do
		if [ "x$eachnode" = "x$current_node_num" ]; then
			continue
		fi

		if [ -z "$nodearray" ]; then
			nodearray="$eachnode"
		else
			nodearray="$nodearray,$eachnode"
		fi
	done

	DEVICENODE=$nodearray

	echo "DEVICENODE $DEVICENODE" >> $TTYDEBUG

	get_usbmodem_node_type_interrupt $current_node_num
}

get_usbmodem_info_file_name ()
{
	local busname=`echo ${DEVICE} | sed 's/\// /g' | awk '{print $4 $5}' | sed -e 's/^[0]*//'`
	local file="${USBMODEM_INFO}${busname}"
	USBMODEM_INFO_FILE="${file}"
}

search_usbmodem_info_by_devicenode ()
{
	# clean global value
	_USBMODEM_INFO_FILE="${USBMODEM_INFO}*"
	local usbmodem_info="${USBMODEM_INFO}*"
	local tty_dev="`/usr/bin/basename ${DEVNAME}`"
	local tty_dev_num="`/bin/echo ${tty_dev} | /bin/sed 's/^tty[A|U][C|S][M|B]//g'`"
	#local enum_all_device_node_info=`/usr/bin/find -name "/tmp/${usbmodem_info}" -exec /bin/get_key_value {} DEVICENODE \; | tr "," " "`

	for each in `/bin/ls ${usbmodem_info}`; do
		for i in `/bin/get_key_value ${each} DEVICENODE | /usr/bin/tr "," " "`; do
			if [ ${i} -eq ${tty_dev_num} ]; then
				_USBMODEM_INFO_FILE="${each}"
				break 2
			fi
		done
	done
}

update_usbmodem_info()
{
	local file=""
	local tmp_file=""

	if [ "add" = "$1" ]; then
		get_usbmodem_info_file_name
		file="${USBMODEM_INFO_FILE}"
		tmp_file="${file}.tmp"

		enum_tty_node_on_same_device
	else
		search_usbmodem_info_by_devicenode
		file="${_USBMODEM_INFO_FILE}"
		tmp_file="${file}.tmp"

		remove_tty_node_on_same_device "$file"
	fi

	# if all the node is removed, rm the info file
	if [ -z ${DEVICENODE} ]; then
		/bin/rm -f ${file} > /dev/null 2>&1
		return
	fi

	echo "DEVICENODE=${DEVICENODE}" > ${tmp_file}
	#find /sys${PHYSDEVPATH}/.. -type d >> ${tmp_file}.${DEVNAME}.$$

	# add device node prefix
	echo "DEVICENODE_PREFIX=${DEVICENODE_PREFIX}" >> ${tmp_file}

	# add connect node
	echo "CONNECTNODE=${CONNECTNODE}" >> ${tmp_file}

	# add usb vendor id
	echo "USB_VENDOR=${USB_VENDOR}" >> ${tmp_file}
	echo "USB_PRODUCT=${USB_PRODUCT}" >> ${tmp_file}

	cp ${tmp_file} ${file}
	rm ${tmp_file}
}

find_tty_device_node_prefix ()
{
	DEVICENODE_PREFIX=`/bin/echo ${DEVNAME} | /bin/sed -e 's/[0-99]$//g'`

}

enum_usbmodem_info ()
{
	local usbmodem_info_list=`ls /tmp/usbmodem.info*`
	GLOBAL_USBMODEM_INFO_LIST="${usbmodem_info_list}"

	#echo "[${GLOBAL_USBMODEM_INFO_LIST}]" >> /tmp/_tmp_enum_usbmodem_info.$$
}

check_dongles_number ()
{
	local usbmodem_info_num=`ls -l /tmp/usbmodem.info* | wc -l`
	get_usbmodem_info_file_name
	local file="${USBMODEM_INFO_FILE}"
	enum_usbmodem_info
	local exist_file="${GLOBAL_USBMODEM_INFO_LIST}"

	#echo "file: [${file}] exist_file: [${exist_file}]" > /tmp/_tmp_check_dongles_number.$$

	if [ 1 -le ${usbmodem_info_num} -a "${file}" != "${exist_file}" ]; then
		exit 0
	fi
}

set_debug_record()
{
	echo "=========================" >> $TTYDEBUG
	echo "action=$action" >> $TTYDEBUG
	env >> $TTYDEBUG
}

add_handler ()
{

	[ ! -d /tmp/lock ] && /bin/mkdir /tmp/lock
	(flock -x 666
		set_debug_record
		get_usbmodem_id
		check_device_to_skip
		get_usbdev_number
		check_dongles_number
		find_tty_device_node_prefix
		update_usbmodem_info "add"
	) 666>${ADD_HANDLER_LOCK}
}

remove_handler ()
{
	[ ! -d /tmp/lock ] && /bin/mkdir /tmp/lock
	(flock -x 666
		# for now multi-dongle are not supported.
		set_debug_record
		get_usbmodem_id
		check_device_to_skip
		get_usbdev_number
		find_tty_device_node_prefix
		update_usbmodem_info "remove"
	) 666>${ADD_HANDLER_LOCK}
}

action=$1
shift;

case $action in
	add)
		add_handler
		;;
	remove)
		remove_handler
		;;
	*)
		;;
esac