#!/bin/sh

NAME="aiot-set-wake-trigger"

put_log () {
    echo "$NAME: $*" 
    logger -t "$NAME" -- "$@"
}

is_enabled_or_disabled() {
    case "$1" in
    enabled|disabled) return 0;;
    esac
    return 1
}

set_io () {
    SW1="/sys/devices/platform/gpio-keys/power/wakeup"
    case "$(cat /etc/hwrevision)" in
        iot-a6e*)
            BOARD="A6E"
            RTC="/sys/devices/platform/soc/2100000.bus/21a4000.i2c/i2c-1/1-0032/power/wakeup"
            RS485="/sys/bus/platform/drivers/imx-uart/21f4000.serial/tty/ttymxc4/power/wakeup"
            TRIGGER="{usb|uart3|rs485|rtc|rtc_sec|gpio|sw1|ain}"
            ;;
        iot-a9e*)
            BOARD="A9E"
            RTC="/sys/devices/platform/i2c-rpbus-1/i2c-1/1-0032/power/wakeup"
            RS485="/sys/devices/platform/lpuart0/power/wakeup"
            TRIGGER="{rs485|rtc|gpio|sw1}"
            ;;
        *)
            echo "Unknown Board."
            exit 1
            ;;
    esac
}

make_trigger_A6E() {
    case "$1" in
        usb|uart3|rs485|rtc_sec|gpio|sw1|ain)
            "$1" "$2"
            ;;
        *)
            usage
            ;;
    esac
}

make_trigger_A9E() {
    case "$1" in
        rs485|sw1)
            "$1" "$2"
            ;;
        gpio)
            gpio_a9e "$2"
            ;;
        *)
            usage
            ;;
    esac
}

make_trigger() {
    "make_trigger_$BOARD" "$1" "$2"
}

usb () {
    put_log "usb $1"
    echo "$1" > /sys/bus/platform/devices/2184000.usb/power/wakeup
    echo "$1" > /sys/bus/platform/drivers/ci_hdrc/ci_hdrc.0/power/wakeup
    echo "$1" > /sys/bus/platform/drivers/ci_hdrc/ci_hdrc.0/usb1/power/wakeup
}

uart3 () {
    put_log "uart3 $1"
    echo "$1" > /sys/bus/platform/drivers/imx-uart/21ec000.serial/tty/ttymxc2/power/wakeup
}

rs485 () {
    put_log "rs485 $1"
    echo "$1" > "$RS485"
}

rtc () {
    put_log "rtc alarm $1"
    echo "$1" > "$RTC"
}

rtc_sec () {
    put_log "rtc_sec alarm $1"
    echo "$1" > /sys/devices/platform/soc/2000000.bus/20cc000.snvs/20cc000.snvs:snvs-rtc-lp/power/wakeup
}

gpio () {
    local ext_din_path="/sys/bus/i2c/devices/3-0027/power/wakeup"

    put_log "gpio $1"
    echo "$1" > /sys/bus/i2c/devices/1-0020/power/wakeup
    if [ -w "$ext_din_path" ]; then
        echo "$1" > "$ext_din_path"
    fi
}

gpio_a9e (){
    local gpio_path="/sys/devices/platform/gpio@1/setwake"
    local di_pins="12 14"
    local val=""
    put_log "gpio $1"
    echo "$1" > /sys/devices/platform/gpio@1/power/wakeup
    case "$1" in
        enabled)
            val="both"
            ;;
        disabled)
            val="disable"
            ;;
    esac
    echo "$val $di_pins" > "$gpio_path"
}

sw1 () {
    put_log "sw1 $1"
    echo "$1" > "$SW1"
}

ain_path="/sys/devices/platform/soc/2100000.bus/21f8000.i2c/i2c-3/3-0049/power/wakeup"
ain_set_wake_triggers_conf="/etc/atmark/ain-set-wake-triggers.conf"

ain () {
    if [ -w "$ain_path" ]; then
        if [ -e "$ain_set_wake_triggers_conf" ] || [ "$1" = "disabled" ]; then
            put_log "ain $1"
            echo "$1" > "$ain_path"
        else
            echo "ain-set-wake-triggers.conf not found"
        fi
    else
        put_log "ain interrupts are disabled"
    fi
}

# without "gpio-keys" to use to escape from suspend-to-RAM
clear_all() {
    put_log "clear_all $1"
    find /sys/devices -name wakeup | while read -r file; do
        if [ ! -f "$file" ]; then continue; fi
        case "$file" in
        *gpio-keys*) continue;;
        esac
        echo "$1" > "$file"
    done
}

WAKE_TRIGGER_RTC="/var/run/wake_trigger_rtc"

alarm_timer () {
    put_log "alarm_timer $1 second"

    case "$1" in
    +*[!0-9]*) usage;;
    +[0-9]*) [ "$1" -ge "$2" ] || usage;;
    *) usage;;
    esac

    if echo "$1" > /sys/class/rtc/"$3"/wakealarm; then
        local trigger_rtc="$3"
        local trigger_rtc_path
        if [ -e "$WAKE_TRIGGER_RTC" ]; then
            trigger_rtc="$(cat $WAKE_TRIGGER_RTC)"
            [ -z "$trigger_rtc" ] && trigger_rtc="$3"
        fi
        trigger_rtc_path="/sys/class/rtc/$trigger_rtc"
        if [ -e "$trigger_rtc_path" ] && [ "$trigger_rtc" != "$3" ]; then
            local restsecs="$(($(cat "$trigger_rtc_path"/wakealarm) - $(cat "$trigger_rtc_path"/since_epoch)))"
            local new_trigger_rtc_path="/sys/class/rtc/$3"
            local new_restsecs="$(($(cat "$new_trigger_rtc_path"/wakealarm) - $(cat "$new_trigger_rtc_path"/since_epoch)))"
            [ "$new_restsecs" -gt "$restsecs" ] && trigger_rtc="$3"
        else
            trigger_rtc="$3"
        fi
        echo "$trigger_rtc" > "$WAKE_TRIGGER_RTC"
    fi
}

alarm_timer_off () {
    if echo 0 > /sys/class/rtc/"$1"/wakealarm; then
        rm -f "$WAKE_TRIGGER_RTC"
    fi
}

usage() {
    put_log "Argument error"
    echo "    $NAME TRIGGER enabled|disabled"
    echo "    TRIGGER := $TRIGGER"
    echo " "
    echo "    $NAME rtc enabled WAKEUP_SECOND"
    echo "    WAKEUP_SECOND := +second (ex: +600) must be at least 60 seconds"
    echo " "
    echo "    $NAME rtc disabled"
    echo " "
    case "$TRIGGER" in
        *"rtc_sec"*)
            echo "    $NAME rtc_sec enabled WAKEUP_SECOND"
            echo "    WAKEUP_SECOND := +second (ex: +600) must be at least 5 seconds"
            echo " "
            echo "    $NAME rtc_sec disabled"
            echo " "
            ;;
    esac
    echo "    $NAME all disabled"
    echo " "
    exit 1
}

set_io

if ! is_enabled_or_disabled "$2"; then
    usage
fi

case "$1" in
    usb|uart3|rs485|gpio|sw1|ain)
        make_trigger "$1" "$2"
        ;;
    rtc)
        rtc "$2"
        if [ "$2" = "enabled" ]; then
            alarm_timer "$3" 60 "rtc0"
        else
            alarm_timer_off "rtc0"
        fi;;
    rtc_sec)
        case "$TRIGGER" in
            *"rtc_sec"*)
                rtc_sec "$2"

                if [ "$2" = "enabled" ]; then
                    alarm_timer "$3" 5 "rtc1"
                else
                    alarm_timer_off "rtc1"
                fi;;
        esac
        ;;
    uart)
        case "$TRIGGER" in
            *"uart3"*)
                uart3 "$2"
                ;;
        esac
        case "$TRIGGER" in
            *"rs485"*)
                rs485 "$2"
                ;;
        esac;;
    all)
        if [ "$2" = "disabled" ]; then
            clear_all "$2"
            alarm_timer_off "rtc0"
            case "$TRIGGER" in
                *"rtc_set"*)
                    alarm_timer_off "rtc1"
                    ;;
            esac
        else
           usage
        fi;;
    * ) usage;;
esac
