#!/bin/sh
# SPDX-License-Identifier: MIT

EC25_VIDPID="2c7c:0125"
EC25_POWER_PATH="/sys/devices/platform/ec25-reset/reset/power"
ELS31_VIDPID="1e2d:00a0"
ELS31_POWER_PATH="/sys/devices/platform/els31-reset/els31_power_ctrl"
EMS31_POWER_PATH="/sys/devices/platform/ems31-reset/ems31_power_ctrl"
SIM7672_POWER_PATH="/sys/devices/platform/sim7672-reset/reset/power"
EM05G_VIDPID="2c7c:030e"
EM05G_POWER_PATH="/sys/devices/platform/em05g-reset/reset/power"

TTYSYMLINK="ttyCommModem"

NMCLI_UP_TIMEOUT_SEC=150
NMCLI_CONN_NAME=""

printdot() { :; }
tty > /dev/null && printdot() { printf .; }

. /usr/sbin/connection-recover-log

# using put_log() at /usr/sbin/connection-recover-log
put_wfr_log() {
	echo "$1"
	put_log "wwan-force-restart" "$1"
}

wait_wwan_usb_connect()
{
	i=0
	while [ "$i" -lt 90 ]
	do
		if lsusb | grep -q "$1"; then
			return 0;
		fi
		printdot
		sleep 1
		i=$((i+1))
	done
	return 1;
}

wait_wwan_nmcli_device_connect()
{
	i=0
	while [ "$i" -lt 90 ]
	do
		if nmcli device | grep -q "$TTYSYMLINK" > /dev/null; then
			return 0;
		fi
		printdot
		sleep 1
		i=$((i+1))
	done
	return 1;
}

g4_wwan_force_restart()
{
	put_wfr_log "start force restart ec25"

	# Power off and disconnect
	wwan-poweroff "$NMCLI_CONN_NAME"
	# need some interval between poweroff and poweron
	sleep 3

	# Power on and connect
	echo 1 > "$EC25_POWER_PATH"
	if ! wait_wwan_usb_connect "$EC25_VIDPID"; then
		put_wfr_log "error: ec25 usb connect wait timeout"
	fi
	if ! wait_wwan_nmcli_device_connect; then
		put_wfr_log "error: ec25 nmcli device wait timeout"
	fi
	sleep 10 # wait restart modemmanager, triggered udev
	timeout -sKILL "$NMCLI_UP_TIMEOUT_SEC" nmcli con up "$NMCLI_CONN_NAME" > /dev/null 2>&1

	put_wfr_log "end force restart ec25"
}

g4_wwan_restart()
{
	nmcli con down "$NMCLI_CONN_NAME"

	put_wfr_log "goto airplane mode: ec25"
	send-at /dev/ttymxc3 AT+CFUN=0

	put_wfr_log "sleep 10 seconds"
	sleep 10

	put_wfr_log "wakeup from airplane mode: ec25"
	send-at /dev/ttymxc3 AT+CFUN=1

	timeout -sKILL "$NMCLI_UP_TIMEOUT_SEC" nmcli con up "$NMCLI_CONN_NAME" > /dev/null 2>&1
}

a6e_els31_wwan_force_restart()
{
	put_wfr_log "start force restart els31"

	# Power off and disconnect
	wwan-poweroff "$NMCLI_CONN_NAME"
	# need some interval between poweroff and poweron
	sleep 3

	# Power on and connect
	echo 1 > "$ELS31_POWER_PATH"
	if ! wait_wwan_usb_connect "$ELS31_VIDPID"; then
		put_wfr_log "error: els31 usb connect wait timeout"
	fi
	rc-service modemmanager start
	if ! wait_wwan_nmcli_device_connect; then
		put_wfr_log "error: els31 nmcli device wait timeout"
	fi
	timeout -sKILL "$NMCLI_UP_TIMEOUT_SEC" nmcli con up "$NMCLI_CONN_NAME" > /dev/null 2>&1

	put_wfr_log "end force restart els31"
}

a6e_els31_wwan_restart()
{
	nmcli con down "$NMCLI_CONN_NAME"

	put_wfr_log "goto airplane mode: els31"
	send-at /dev/ttymxc3 AT+CFUN=0

	put_wfr_log "sleep 10 seconds"
	sleep 10

	put_wfr_log "wakeup from airplane mode: els31"
	send-at /dev/ttymxc3 AT+CFUN=1
	# need some interval after AT+CFUN=1 on ELS31
	sleep 10
	timeout -sKILL "$NMCLI_UP_TIMEOUT_SEC" nmcli con up "$NMCLI_CONN_NAME" > /dev/null 2>&1
}

a6e_ems31_force_restart()
{
	put_wfr_log "start force restart ems31"

	# Power off and disconnect
	wwan-poweroff "$NMCLI_CONN_NAME"

	# Restart modem and modemmanager
	rc-service ems31-boot start
	sleep 30
	timeout -sKILL "$NMCLI_UP_TIMEOUT_SEC" nmcli con up "$NMCLI_CONN_NAME" > /dev/null 2>&1

	put_wfr_log "end force restart ems31"
}

a6e_ems31_restart()
{
	nmcli con down "$NMCLI_CONN_NAME"

	modem_num=$(mm-modem-num)
	put_wfr_log "goto airplane mode: ems31"
	mmcli -m "$modem_num" -d

	put_wfr_log "sleep 10 seconds"
	sleep 10

	put_wfr_log "wakeup from airplane mode: ems31"
	mmcli -m "$modem_num" -e

	timeout -sKILL "$NMCLI_UP_TIMEOUT_SEC" nmcli con up "$NMCLI_CONN_NAME" > /dev/null 2>&1
}

a9e_sim7672_force_restart()
{
	put_wfr_log "start force restart sim7672"

	# Power off and disconnect
	wwan-poweroff "$NMCLI_CONN_NAME"

	# Restart modem and modemmanager
	rc-service sim7672-boot restart
	sleep 10
	timeout -sKILL "$NMCLI_UP_TIMEOUT_SEC" nmcli con up "$NMCLI_CONN_NAME" > /dev/null 2>&1

	put_wfr_log "end force restart sim7672"
}

a9e_sim7672_restart()
{
	nmcli con down "$NMCLI_CONN_NAME"

	modem_num=$(mm-modem-num)
	put_wfr_log "goto airplane mode: sim7672"
	mmcli -m "$modem_num" -d

	put_wfr_log "sleep 10 seconds"
	sleep 10

	put_wfr_log "wakeup from airplane mode: sim7672"
	mmcli -m "$modem_num" -e

	timeout -sKILL "$NMCLI_UP_TIMEOUT_SEC" nmcli con up "$NMCLI_CONN_NAME" > /dev/null 2>&1
}

high_g1_em05g_force_restart()
{
	put_wfr_log "start force restart els31"

	# Power off and disconnect
	wwan-poweroff "$NMCLI_CONN_NAME"
	# need some interval between poweroff and poweron
	sleep 3

	# Power on and connect
	echo 1 > "$EM05G_POWER_PATH"
	if ! wait_wwan_usb_connect "$EM05G_VIDPID"; then
		put_wfr_log "error: em05g usb connect wait timeout"
	fi
	rc-service modemmanager start
	if ! wait_wwan_nmcli_device_connect; then
		put_wfr_log "error: em05g nmcli device wait timeout"
	fi
	timeout -sKILL "$NMCLI_UP_TIMEOUT_SEC" nmcli con up "$NMCLI_CONN_NAME" > /dev/null 2>&1

	put_wfr_log "end force restart em05g"
}

high_g1_em05g_restart()
{
	nmcli con down "$NMCLI_CONN_NAME"

	modem_num=$(mm-modem-num)
	put_wfr_log "goto airplane mode: em05g"
	mmcli -m "$modem_num" -d

	put_wfr_log "sleep 10 seconds"
	sleep 10

	put_wfr_log "wakeup from airplane mode: em05g"
	mmcli -m "$modem_num" -e

	timeout -sKILL "$NMCLI_UP_TIMEOUT_SEC" nmcli con up "$NMCLI_CONN_NAME" > /dev/null 2>&1
}

exec 3<"$0"
if ! flock -n 3; then
	echo "error: $0 is already running"
	exit 1
fi

if [ $# -ge 1 ]; then
	NMCLI_CONN_NAME="$1"
else
	NMCLI_CONN_NAME=gsm-"${TTYSYMLINK}"
fi


if [ -e "$EC25_POWER_PATH" ]; then
	if [ $# -ge 2 ] && [ "$2" = "airplane" ]; then
		run=g4_wwan_restart
	else
		run=g4_wwan_force_restart
	fi
elif [ -e "$ELS31_POWER_PATH" ]; then
	if [ $# -ge 2 ] && [ "$2" = "airplane" ]; then
		run=a6e_els31_wwan_restart
	else
		run=a6e_els31_wwan_force_restart
	fi
elif [ -e "$EMS31_POWER_PATH" ]; then
	if [ $# -ge 2 ] && [ "$2" = "airplane" ]; then
		run=a6e_ems31_restart
	else
		run=a6e_ems31_force_restart
	fi
elif [ -e "$SIM7672_POWER_PATH" ]; then
	if [ $# -ge 2 ] && [ "$2" = "airplane" ]; then
		run=a9e_sim7672_restart
	else
		run=a9e_sim7672_force_restart
	fi
elif [ -e "$EM05G_POWER_PATH" ]; then
	if [ $# -ge 2 ] && [ "$2" = "airplane" ]; then
		run=high_g1_em05g_restart
	else
		run=high_g1_em05g_force_restart
	fi
else
	put_wfr_log "error: not supported"
	exit 1
fi

# close lock file for subcommands so lock is not inherited
"$run" 3<&-

