# helper functions sourced from other scripts

logg(){
    logger -s -p "user.info" -t "$0" "$1"
}



loggerr(){
    logger -s -p "user.err" -t "$0" $1
}

Reboot(){
    if [ -e /var/local/telem/sysinit ]; then
        logg "Rebooting system (sysinit)"
        touch /var/local/telem/sysinit_reboot
    else
        logg "Rebooting system"
        reboot
    fi
}

fileRotate()
{
    # $1 filename
    # $2 count
    if [ -f "$1" ]; then
        for i in $(seq $2 -1 0); do
            mv "$1".$i "$1".$((i+1)) &>/dev/null
        done
        mv "$1" "$1".0 &>/dev/null
    fi
}

fileRotateXZ()
{
    # for uncompressed files
    # $1 filename
    # $2 count
    if [ -f "$1" ]; then
        if [ -f "$1.0" ]; then
            for i in $(seq $2 -1 1); do
                mv "$1".$i.tar.xz "$1".$((i+1)).tar.xz &>/dev/null
            done
            tar -cf - "$1".0 | xz -fz0 - > "$1".1.tar.xz
        fi
        mv "$1" "$1".0 &>/dev/null
    fi
}

modem_is_alive(){
    local USB_MODEM="nothing"
    [ -f /var/local/telem/usb-modem-vidpid ] && source /var/local/telem/usb-modem-vidpid
    lsusb | grep -q -- "$USB_MODEM"
}

telit_modem_rev4_turnOFF(){
    # Do not call outside this file.
    if $GPIO --is-on MODEM_PWR_MON; then
        # MODEM_PWR is inverted
        $GPIO -s MODEM_PWR; sleep 4; $GPIO -c MODEM_PWR; sleep 1;
        # wait for modem to shut down
        i="0"
        while $GPIO --is-on MODEM_PWR_MON && [ "$i" -lt "15" ]; do
            i=$((i+1))
            sleep 1
        done
        # HW SHUTDOWN Unconditional: if modem is still on
        $GPIO --is-on MODEM_PWR_MON && $GPIO -t RST_MODEM
    fi
}

telit_modem_rev4_reset(){
    # Do not call outside this file.
    # From HE910 Hardware User Guide
    # MODEM_PWR = ON_OFF pin
    # RST_MODEM = HW_SHUTDOWN pin ?
    lsmod | grep -q -- "cdc.*acm" || modprobe cdc-acm
    # turn off modem if it is on
    telit_modem_rev4_turnOFF
    # turn back on
    if $GPIO --is-off MODEM_PWR_MON; then
        i="0"
        while $GPIO --is-off MODEM_PWR_MON && [ "$i" -lt "2" ]; do
            i=$((i+1))
            $GPIO -s MODEM_PWR; sleep 6; $GPIO -c MODEM_PWR
            sleep 1
            # HW SHUTDOWN Unconditional: if modem is still off
            $GPIO --is-off MODEM_PWR_MON && $GPIO -t RST_MODEM
        done
        # Start AT CMD part not needed here
    fi
    $GPIO -s MODEM_USB_PWR
}

huawei_modem_reset(){
    lsmod | grep -q -- "option"   || modprobe option
    lsmod | grep -q -- "cdc.*acm" || modprobe cdc-acm

    if modem_is_alive; then
        # Modem is alive, lets try reset pin.

        # HUAWEI Reset pulse timing:
        # * 50-100ms
        # RESIN_N pin must not be pulled down for more than 1s.
        $GPIO -s RST_MODEM
        usleep 55000 # sleep 55ms
        $GPIO -c RST_MODEM
    else
        # modem is not alive, lets try to reset power

        # HUAWEI Power on timing sequence:
        # MU609: 3-5s
        # MU709: 7s
        # ME909: 14s
        # Do not toggle RESIN_N pin during the power on sequence.
        # Pulling RESIN_N pin low will extend time for module startup.
        if [ "$rev" -ge "9" ]; then
            if $GPIO --is-on MODEM_PWR; then
                # Modem is not really turning off?
                # Wait for capacitor to discharge?
                # TESTED: It is a hardware issue
                #   gpio.sh -c MODEM_PWR; sleep 1; gpio.sh -s MODEM_PWR
                #   command works without long sleep if power pin has a resistor to pull down power faster.
                $GPIO -c MODEM_PWR
                logg "Will sleep for 45 seconds now"
                sleep 25 # additional 20 seconds outside this if
            fi
            # keep it off for 20s, because we dont know if it has been off long enough.
            sleep 20
            $GPIO -s MODEM_PWR
            sleep 14
        fi
    fi
}

modem_reset(){
    # Do not call outside this file.
    GPIO=/usr/local/bin/telem/gpio.sh
    rev=$(cat /tmp/telem/board/rev)
    if [ "$rev" -ge "8" ]; then
        # for rev 8+
        [ "$rev" -ge "9" ] && $GPIO -e MODEM_PWR
        $GPIO -e RST_MODEM
        # currently we support only huawei modems
        huawei_modem_reset
        sleep 7
    else
        $GPIO -e MODEM_USB_PWR
        $GPIO -e MODEM_PWR_MON
        $GPIO -e MODEM_PWR
        $GPIO -e RST_MODEM

        $GPIO -c MODEM_USB_PWR
        telit_modem_rev4_reset
        $GPIO -s MODEM_USB_PWR
    fi
}

# You have to wait for modem at least +10 seconds after modem device appears or chat script will fail
wait_for_modem()
{
    ret=0
    reset_lockFile="/tmp/modem_reset_2min_lock"  # file is touched before reset
    tty_cmdFile="/var/local/telem/modem_tty_cmd" # file is modified after device is created by mdev

    # find -mmin -0.2 will always be true if file epoch is < 12 seconds (current workaround: S01hwclock should set clock at lest to year 2000)
    # -mmin +0 avoids files whose date is in the future or to close to epoch 0

    # wait for 18 seconds after reset command
    while [ "$(find "$reset_lockFile" -mmin -0.3 -mmin +0 2>/dev/null)" == "$reset_lockFile" ]; do sleep 2; ret=1; done
    # wait for 12 seconds after modem device was created
    while [ "$(find -L "$tty_cmdFile" -mmin -0.2 -mmin +0 2>/dev/null)" == "$tty_cmdFile"    ]; do sleep 2; ret=1; done
    return $ret
}

# there are at least three scripts where modem reseting is initiated
# so it would be good idea to use modem_reset_lock
modem_reset_lock()
{
    reset_lockFile="/tmp/modem_reset_2min_lock"
    # Reset modem if there is no lock file newer than ~1.5 minutes
    if [ "$(find "$reset_lockFile" -mmin -1.5 -mmin +0 2>/dev/null)" != "$reset_lockFile" ] ; then
        touch "$reset_lockFile"
        logg "Resetting modem"
        modem_reset
    else
        # just wait
        logg "Can't reset modem, it is already being reset"
    fi
    wait_for_modem
}

modem_turnOFF()
{
    GPIO=/usr/local/bin/telem/gpio.sh
    rev=$(cat /tmp/telem/board/rev)
    if [ "$rev" -ge "8" ]; then
        # for rev 8+
        lsmod | grep -q -- "option"   || modprobe option
        lsmod | grep -q -- "cdc.*acm" || modprobe cdc-acm
        [ "$rev" -ge "9" ] && { $GPIO -e MODEM_PWR; $GPIO -c MODEM_PWR; }
        # rev8 can not be turned off, maybe with AT command
    else
        $GPIO -e MODEM_USB_PWR
        $GPIO -e MODEM_PWR_MON
        $GPIO -e MODEM_PWR
        $GPIO -e RST_MODEM

        $GPIO -c MODEM_USB_PWR
        telit_modem_rev4_turnOFF
    fi
}
