#!/bin/sh

source "/lib/functions.sh"
source "/lib/functions/network.sh"
source "/lib/functions/system.sh"

PREVLINK=""
LINK=""
LINKSPEED=""
PREVWANMODE=""
WANMODE=""
CONFIGURED=0
CINDEX=0
WANPORT="$(jsonfilter -i /etc/board.json -e @.network.wan.device)"

delete_atm_device() {
	/userfs/bin/blapi_cmd xdsl atm_delete_interface $CINDEX
	CINDEX=$((CINDEX+1))
}

delete_atm_devices() {
	CINDEX=0
	config_load dsl
	config_foreach delete_atm_device atm-device
}

configure_atm_device() {
	local vpi vci encapsulation qos_class pcr mbs scr
	local encap qos ethmac

	config_get vpi $1 vpi "8"
	config_get vci $1 vci "35"
	config_get encapsulation $1 encapsulation "llc"
	config_get qos_class $1 qos_class "ubr"
	config_get pcr $1 pcr "0"
	config_get mbs $1 mbs "0"
	config_get scr $1 scr "0"

	case $encapsulation in # llc, vcmux
		vcmux)
			encap="1483 Bridged IP VC-Mux"
		;;
		*)
			encap="1483 Bridged IP LLC"
		;;

	esac

	ethmac="$(echo -n "$(macaddr_add 02:AA:BB:01:23:40 $((CINDEX+2)))" | sed 's#:##g')"

	/userfs/bin/blapi_cmd xdsl create_device $CINDEX ATM "" "$ethmac"
	/userfs/bin/blapi_cmd xdsl atm_create_interface $CINDEX ATM "$qos_class" "$encap" "$vpi" "$vci" "$pcr" "$scr" "$mbs" 0

	CINDEX=$((CINDEX+1))
}

create_atm_devices() {
	delete_atm_devices

	CINDEX=0
	config_foreach configure_atm_device atm-device
}

configure_line() {
	local mode profile bitswap sra us0 sesdrop sos roc ginp gvector mod prof
	local adsl1_flag=0 issue2_flag=0 Glite_flag=0 adsl2_flag=0 adsl2p_flag=0 vdsl2_flag=0
	local pro_8a_flag=0 pro_8b_flag=0 pro_8c_flag=0 pro_8d_flag=0 pro_12a_flag=0 pro_12b_flag=0 pro_17a_flag=0 pro_30a_flag=0 pro_35b_flag=0

	config_get mode $1 mode "vdsl2"
	config_get profile $1 profile "35b"
	config_get bitswap $1 bitswap "1"
	config_get sra $1 sra "1"
	config_get us0 $1 us0 "1"
	config_get sos $1 sos "0"
	config_get roc $1 roc "0"
	config_get ginp $1 ginp "1"
	config_get gvector $1 gvector "1"

	for mod in $mode; do
		[ "$mod" = "gdmt" ] && adsl1_flag=1
		[ "$mod" = "glite" ] && Glite_flag=1
		[ "$mod" = "t1413" ] && issue2_flag=1
		[ "$mod" = "adsl2" ] && adsl2_flag=1
		[ "$mod" = "adsl2p" ] && adsl2p_flag=1
		[ "$mod" = "vdsl2" ] && vdsl2_flag=1
	done

	for prof in $profile; do
		[ "$prof" = "8a" ] && pro_8a_flag=1
		[ "$prof" = "8b" ] && pro_8b_flag=1
		[ "$prof" = "8c" ] && pro_8c_flag=1
		[ "$prof" = "8d" ] && pro_8d_flag=1
		[ "$prof" = "12a" ] && pro_12a_flag=1
		[ "$prof" = "12b" ] && pro_12b_flag=1
		[ "$prof" = "17a" ] && pro_17a_flag=1
		[ "$prof" = "30a" ] && pro_30a_flag=1
		[ "$prof" = "35b" ] && pro_35b_flag=1
	done

	/userfs/bin/blapi_cmd xdsl set_adsl_profile "$pro_8a_flag" "$pro_8b_flag" "$pro_8c_flag" "$pro_8d_flag" "$pro_12a_flag" "$pro_12b_flag" "$pro_17a_flag" "$pro_30a_flag" "$pro_35b_flag"
	/userfs/bin/blapi_cmd xdsl set_adsl_mode "$adsl1_flag" "$issue2_flag" "$Glite_flag" "$adsl2_flag" "$adsl2p_flag" "$vdsl2_flag"
	/userfs/bin/blapi_cmd xdsl set_adsl_gvector "$((!gvector))"
	/userfs/bin/blapi_cmd xdsl set_adsl_ginp "$((!ginp))"
	/userfs/bin/blapi_cmd xdsl set_adsl_sos_roc "$((!sos))" "$((!roc))"
	/userfs/bin/blapi_cmd xdsl set_adsl_us0 "$((!us0))"
	/userfs/bin/blapi_cmd xdsl set_adsl_sra "$((!sra))"
	/userfs/bin/blapi_cmd xdsl set_adsl_bitswap "$((!bitswap))"

	CONFIGURED=1
}

configure_lines() {
	config_load dsl
	config_foreach configure_line dsl-line
}

call_wan_hotplug() {
	# initializations
	local updown="$1"
	local ethwan="$2"

	# ethernet hotlugs expect LINK and PORT environment variables set
	env -i LINK="$updown" PORT="$ethwan" /sbin/hotplug-call ethernet
}

if [ "$WANPORT" = "ae_wan" -a -f /proc/device-tree/ae_wan/wan-dsl ]; then
	/etc/init.d/br2684ctl stop
else
	/etc/init.d/br2684ctl start
fi

# Wait for nas0 interface to come up.
while [ "$(devstatus "$WANPORT" | jsonfilter -e @.up)" != "true" ]; do
	sleep 1
done

while [ true ]; do
	LINK="$(awk '/ADSL link status:/{print $4}' /proc/tc3162/adsl_stats)"
	[ \( "$LINK" = "down" -o "$LINK" = "up" \) ] && break
	sleep 1
done
sleep 2

/userfs/bin/blapi_cmd xdsl set_adsl_sysvid "26 00 47 4E 58 53 00 00" # GNXS vendor id
/userfs/bin/blapi_cmd xdsl set_adsl_version "$(ubus call fwbank dump | jsonfilter -e "@.bank[@.active=true].swver" | cut -f1 -d'_' | cut -f1 -d'-' | hexdump -e '11/1 "%02x " "\n"' | head -n1)"
/userfs/bin/blapi_cmd xdsl set_power_up_down 1
/userfs/bin/blapi_cmd xdsl set_power_up_down 0
sleep 1

while [ true ]; do
	LINK="$(awk '/ADSL link status:/{print $4}' /proc/tc3162/adsl_stats)"

	if [ "$LINK" != "$PREVLINK" -a \( "$LINK" = "down" -o "$LINK" = "up" \) ]; then
		if [ "$LINK" = "down" ]; then
			if [ ! -s /tmp/qos/wan_link_shape_rate ]; then
				rm -rf /tmp/qos/wan_link_shape_rate
				rm -rf /tmp/qos/wan_link_speed
				/usr/sbin/qos-uplink-bandwidth
			fi

			[ "$CONFIGURED" -eq 0 ] && configure_lines # Needs to be done once the slave SoC is in down state and we've not been able to auto-sync.
			if [ -n "$WANMODE" ]; then
				if [ "$WANMODE" = "PTM" ]; then
					/userfs/bin/blapi_cmd xdsl ptm_do_reset_sequence 0 1
				else
					delete_atm_devices
				fi
			fi

			call_wan_hotplug "down" "$WANPORT"
		else
			CONFIGURED=1
			WANMODE="$(awk '/TPSTC type:/{print $4}' /proc/tc3162/adsl_stats)"
			if [ "$WANMODE" != "$PREVWANMODE" ]; then
				OLDWANPORT="$WANPORT"
				network_defer_device "$OLDWANPORT"

				if [ -f /proc/device-tree/ae_wan/wan-dsl ]; then
					WANPORT="ae_wan"
				else
					WANPORT="nas10"
				fi

				if [ "$WANMODE" = "PTM" ]; then
					/etc/init.d/br2684ctl stop
					delete_atm_devices
					/userfs/bin/blapi_cmd system set_wan_mode 1
					/userfs/bin/blapi_cmd xdsl reload_ko 2
					/userfs/bin/blapi_cmd xdsl ptm_do_reset_sequence 1 2

					# Set extended TPID for PTM packet flow
					sys memwl 1FB50000 81001839
					# VLAN TPID - VLAN
					sys memwl 1FB50F18 8100

					ifconfig ${WANPORT} mtu 1500
				else
					/userfs/bin/blapi_cmd system set_wan_mode 0
					/userfs/bin/blapi_cmd xdsl reload_ko 1
					/etc/init.d/br2684ctl start

					# Set extended TPID for ATM packet flow
					sys memwl 1FB50000 884C1839
					# VLAN TPID - MPOA
					sys memwl 1FB50F18 884C

					ifconfig ${WANPORT} mtu 1982
					ifconfig ${WANPORT} down up

					OLDWANPORT="$WANPORT"
					ATMINDEX="$(cat /sys/class/atm/TSARM*/atmindex | tail -n1 2> /dev/null)"
					WANPORT="nas$((ATMINDEX))"
				fi

				if [ "$OLDWANPORT" != "$WANPORT" ]; then
					call_wan_hotplug "down" "$OLDWANPORT"

					FILES="$(grep "$OLDWANPORT" /etc/config/* | cut -f1 -d: | uniq | cut -f4 -d/ | xargs)"
					for FILE in $FILES; do
						sed -i -e "s#${OLDWANPORT}#${WANPORT}#g" "/etc/config/${FILE}"
						"/etc/init.d/${FILE}" restart
					done
				else
					/etc/init.d/network restart
				fi
				ifconfig ${OLDWANPORT} down up
			fi

			if [ "$WANMODE" = "PTM" ]; then
				: # ToDo
			else
				create_atm_devices
			fi

			call_wan_hotplug "up" "$WANPORT"
			PREVWANMODE="$WANMODE"

			if [ ! -s /tmp/qos/wan_link_shape_rate ]; then
				LINKSPEED="$(awk '/far-end interleaved channel bit rate/{print $6}' /proc/tc3162/adsl_stats)"
				LINKSPEED=$((LINKSPEED))
				if [ "$LINKSPEED" -eq 0 ]; then
					LINKSPEED="$(awk '/far-end fast channel bit rate/{print $6}' /proc/tc3162/adsl_stats)"
					LINKSPEED=$((LINKSPEED))
				fi

				if [ "$LINKSPEED" -ne 0 ]; then
					mkdir -p /tmp/qos
					touch /tmp/qos/wan_link_shape_rate

					/userfs/bin/qosrule discpline Rate uplink-bandwidth ${LINKSPEED}
					hw_nat -! > /dev/null 2>&1
				else
					rm -rf /tmp/qos/wan_link_speed
					/usr/sbin/qos-uplink-bandwidth
				fi
			fi
		fi

		# Toggle link state
		network_defer_device "$WANPORT"
		network_ready_device "$WANPORT"

		# We are only interested in the transtion from init -> up/down and up/down -> down/up and vice versa.
		# Since we poll the status via in-band signaling packets might get lost and the /procfs file is empty.
		# This state we don't want to handle as it will toggle the link and do a re-setup which is totally unnecessary and unwanted.
		PREVLINK="$LINK"
	fi

	sleep 5
done
