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

EC25_POWER_PATH="/sys/devices/platform/ec25-reset/reset/power"
EC25_STATUS_PATH="/sys/devices/platform/ec25-reset/reset/status"
EC25_QPOWD_RETRY=10
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"
SIM7672_STATUS_PATH="/sys/devices/platform/sim7672-reset/reset/status"
EM05G_VIDPID="2c7c:030e"
EM05G_POWER_PATH="/sys/devices/platform/em05g-reset/reset/power"

TTYSYMLINK="ttyCommModem"

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

put_log()
{
	echo "$1"
	logger -t "wwan-poweroff" "$1"
}

error()
{
	put_log "$1"
	flock -u 4
	exit 1
}

is_ec25_disconnected()
{
	[ "$(cat "$EC25_STATUS_PATH")" = off ]
}

is_els31_disconnected()
{
	! lsusb | grep -q "$ELS31_VIDPID"
}

is_sim7672_disconnected()
{
	[ "$(cat "$SIM7672_STATUS_PATH")" = off ]
}

is_em05g_disconnected()
{
	! lsusb | grep -q "$EM05G_VIDPID"
}

wait_wwan_disconnect()
{
	i=0
	while [ "$i" -lt 120 ]
	do
		if "$1"; then
			return
		fi
		printdot
		sleep 0.5
		i=$((i+1))
	done

	put_log "error: $2 disconnect wait timeout"
	return 1
}

g4_wwan_poweroff()
{
	nmcli con down "$NMCLI_CONN_NAME" 2>/dev/null
	rc-service modemmanager stop 2>/dev/null

	if [ "$(cat $EC25_STATUS_PATH)" = "running" ]; then
		local j
		j=0
		while [ "$j" -lt "$EC25_QPOWD_RETRY" ]
		do
			if send-at /dev/ttymxc3 AT+QPOWD 2>/dev/null; then
				break
			fi
			sleep 3
			j=$((j+1))
		done
		if [ "$j" -ge "$EC25_QPOWD_RETRY" ]; then
			put_log "failed AT+QPOWD for EC25 ($EC25_QPOWD_RETRY times)"
		fi
		wait_wwan_disconnect is_ec25_disconnected ec25
	fi
	echo 0 > "$EC25_POWER_PATH" 2>/dev/null
}

a6e_els31_poweroff()
{
	nmcli con down "$NMCLI_CONN_NAME" 2>/dev/null
	rc-service modemmanager stop 2>/dev/null
	if ! is_els31_disconnected; then
		send-at /dev/ttymxc3 AT^SMSO urc "MS OFF" 60 || error "send-at failed."
		wait_wwan_disconnect is_els31_disconnected els31
	fi
	echo 0 > "$ELS31_POWER_PATH"
}

a6e_ems31_poweroff()
{
	nmcli con down "$NMCLI_CONN_NAME" 2>/dev/null
	rc-service modemmanager stop 2>/dev/null
	rc-service ems31-boot stop 2>/dev/null

	if send-at /dev/ttymxc3 AT ems31; then
		# use original device file (not mux device)
		send-at /dev/ttymxc3 AT^SMSO urc "^SHUTDOWN" 60 ems31 || error "send-at failed."
		ems31-power-ctrl off
	fi
}

a9e_sim7672_poweroff()
{
	nmcli con down "$NMCLI_CONN_NAME" 2>/dev/null
	rc-service modemmanager stop 2>/dev/null
	rc-service sim7672-boot stop 2>/dev/null

	if [ "$(cat $SIM7672_STATUS_PATH)" = "running" ]; then
		send-at /dev/ttyCommModem AT+CPOF 2>/dev/null || error "send-at failed."
		wait_wwan_disconnect is_sim7672_disconnected sim7672
	fi
	echo 0 2>/dev/null > "$SIM7672_POWER_PATH"
}

high_g1_em05g_poweroff()
{
	nmcli con down "$NMCLI_CONN_NAME" 2>/dev/null
	rc-service modemmanager stop 2>/dev/null

	if ! is_em05g_disconnected; then
		send-at /dev/ttyCommModem AT+QPOWD 2>/dev/null || error "send-at failed."
		wait_wwan_disconnect is_em05g_disconnected em05g
	fi
	echo 0 > "$EM05G_POWER_PATH"
}

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

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

if [ -e "$EC25_POWER_PATH" ]; then
	run=g4_wwan_poweroff
elif [ -e "$ELS31_POWER_PATH" ]; then
	run=a6e_els31_poweroff
elif [ -e "$EMS31_POWER_PATH" ]; then
	run=a6e_ems31_poweroff
elif [ -e "$SIM7672_POWER_PATH" ]; then
	run=a9e_sim7672_poweroff
elif [ -e "$EM05G_POWER_PATH" ]; then
	run=high_g1_em05g_poweroff
else
	put_log "error: not supported"
	exit 1
fi

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