#!/bin/bash
#
# Copyright (C) 2023 MOXA Inc. All rights reserved.
# This software is distributed under the terms of the MOXA SOFTWARE NOTICE.
# See the file LICENSE for details.
#
# Authors:
#	2022	Elvis Yao <ElvisCW.Yao@moxa.com>
#	2022    Wilson Huang <WilsonYS.Huang@moxa.com>
# Description:
#	For controlling gpio-sysfs value from Super IO LED
#

DMIDECODE="/usr/sbin/dmidecode"

_product_DA681C() {
	GPIO_MODULE="gpio_it87"

	LED_GPIO_TBL=(70 71 72 73 \
			74 75 76 77)

	# active low
	LED_STATE=("on" "off")
}

_product_DA820C() {
	GPIO_MODULE="gpio_it87"

	LED_GPIO_TBL=(70 71 72 73 \
			74 75 76 77)

	# active low
	LED_STATE=("on" "off")
}

_product_DA682C() {
	GPIO_MODULE="gpio_it87"

	LED_GPIO_TBL=(70 71 72 73 \
			74 75 76 77)

	# active low
	LED_STATE=("on" "off")
}

_product_V2201() {
	GPIO_MODULE="gpio_it87"

	LED_GPIO_TBL=(20 21 22)

	# active low
	LED_STATE=("on" "off")
}

_product_V3000() {
	GPIO_MODULE="gpio_it87"

	LED_GPIO_TBL=(77 76 75)

	# active low
	LED_STATE=("on" "off")
}

_product_DA680() {
	GPIO_MODULE="gpio_it87"

	LED_GPIO_TBL=(70 71 72 73 74 75 76 77)

	# active low
	LED_STATE=("on" "off")
}

_check_leading_zero_digit() {
    local digit
    digit=${1}

    [[ "$digit" =~ ^([1-9][0-9]*|0)$ ]]
}

declare -A PRODUCT_PROFILE=(
	["DA681C"]=_product_DA681C
	["DA682C"]=_product_DA682C
	["DA820C"]=_product_DA820C
	["V2201"]=_product_V2201
	["V3000"]=_product_V3000
	["DA680"]=_product_DA680
)

load_product_name_from_dmi() {
	local ret=1

	for m in $($DMIDECODE -t 12 | grep "Option " | awk -F ':' '{print substr($2,1,11)}' | sed 's/ //g');
	do
		if [[ ${PRODUCT_PROFILE[$m]} ]]; then
				${PRODUCT_PROFILE[$m]}
				ret=0
				break
		fi
	done

	for m in $($DMIDECODE -t 1 | grep "Product Name" | awk -F ':' '{print $2}' | sed 's/ //g');
	do
		if [[ ${PRODUCT_PROFILE[$m]} ]]; then
			TARGET_PRODUCT=$m
			${PRODUCT_PROFILE[$TARGET_PRODUCT]}
			ret=0
			break
		fi
	done

	return $ret
}

load_product_name_from_file() {
	echo "TBD"
}

load_product_config() {
	if load_product_name_from_dmi; then
		# Determine gpio chip profile
		gpc=${GPIO_CHIP[$GPIO_MODULE]}
	else
		echo "Error: model profile not found."
		exit 1
	fi
}

## gpio
gpc_it8786() {
	local gpio=$1
	local GPIO_TABLE=(
		10 11 12 13 14 15 16 17
		20 21 22 23 24 25 26 27
		30 31 32 33 34 35 36 37
		40 41 42 43 44 45 46 47
		50 51 52 53 54 55 56 57
		60 61 62 63 64 65 66 67
		70 71 72 73 74 75 76 77
		80 81 82 83 84 85 86 87
		90 91 92 93 94 95 96 97
                100 101 102 103 104 105
	)

	[[ ! ${GPIO_TABLE[*]} =~ $gpio ]] && \
			echo "Invalid gpio number." && exit 1

	for gpiochip in /sys/class/gpio/gpiochip*
	do
		if cat "${gpiochip}"/label | grep -q "gpio_it87"
		then
			base=$(cat "${gpiochip}"/base)
			break
		fi
	done

	group=$(($gpio / 10 - 1))
	bit=$(($gpio % 10))
	echo $((base + 8 * group + bit))
}

declare -A GPIO_CHIP=(
	["gpio_it87"]=gpc_it8786
)

gpio_request() {
	local gpio=${1}

	if [ ! -e "/sys/class/gpio/gpio${gpio}" ]
	then
		echo "${gpio}" > /sys/class/gpio/export
	fi
}

gpio_set_value() {
	local gpio=${1}
	local value=${2}

	gpio_request "${gpio}"
	case "${value}" in
	0)
		echo "low" > "/sys/class/gpio/gpio${gpio}/direction"
		;;
	1)
		echo "high" > "/sys/class/gpio/gpio${gpio}/direction"
		;;
	*)
		usage
	;;
	esac
}

gpio_get_value() {
	local gpio=${1}

	gpio_request "${gpio}"
	cat "/sys/class/gpio/gpio${gpio}/value"
}

## led
get_led_state() {
	local idx=$1
	local num=${LED_GPIO_TBL[$idx]}
	local state=$(gpio_get_value $($gpc $num))

	echo "Get Led#$idx state: ${LED_STATE[$state]}"
}

set_led_state() {
	local idx=$1
	local state=$2
	local num=${LED_GPIO_TBL[$idx]}

	gpio_set_value $($gpc $num) $state

	echo "Set Led#$idx state: ${LED_STATE[$state]}"
}

usage() {
cat << EOF
Usage:
		mx-led-ctl -i <led_index> [on|off]

OPTIONS:
		-i <led_index>
				Set LED index.

Example:
		Get state from index 1
		# mx-led-ctl -i 1

		Set index 1 to on
		# mx-led-ctl -i 1 on
EOF
}

load_product_config

# Parameter check
if [[ $# -lt 2 ]]; then
	usage
	exit 1
fi

case $1 in
	-i)
		if [[ $2 -lt 0 || $2 -ge ${#LED_GPIO_TBL[@]} ]]; then
			echo "Invalid LED index."
			exit 1
		fi

		TARGET_LED_INDEX="$2"
		if ! _check_leading_zero_digit $TARGET_LED_INDEX; then
            echo "Invaild led index format"
            exit 1
        fi

		TARGET_OPT="get"

		if [[ $# -gt 2 ]]; then
			case $3 in
				on)
					TARGET_LED_STATE=0
					TARGET_OPT="set"
					;;
				off)
					TARGET_LED_STATE=1
					TARGET_OPT="set"
					;;
				*)
					echo "only accept 'on' or 'off' in set state"
					usage
					exit 1
					;;
			esac
		fi
		;;
	*)
		echo "Unknown parameter passed"
		usage
		exit 1
		;;
esac

case $TARGET_OPT in
	get)
		get_led_state $TARGET_LED_INDEX
		;;
	set)
		set_led_state $TARGET_LED_INDEX $TARGET_LED_STATE
		;;
	*)
		exit 1
		;;
esac
