#!/bin/sh

#
# Copyright (C) 2015 shibby
#

PREFIX=$1

MODE=`nvram get "$PREFIX"_proto`
LOCK="/tmp/switch4g.lock"
READY="/tmp/4g.ready"

if [ ! "$MODE" == "lte" ]; then
    exit 0
fi

connect() {
    APN=`nvram get "$PREFIX"_modem_apn`
    DEV=`nvram get modem_dev4g`
    TYPE=`nvram get modem_type`
    IFA=`nvram get wan_4g`
    SPEED=`nvram get "$PREFIX"_modem_speed`

    logger 4G MODEM - connecting ...

    if [ "$TYPE" == "non-hilink" -o "$TYPE" == "hw-ether" ]; then
        CONNECTED=0
        COUNT=0

        if [ -z "$DEV" ]; then
            logger 4G MODEM - DIAG interface not found - connection terminated
            exit 0;
        fi

        #we try use last diag iface first. If it failed then we try use any other ttyUSB device
        TTY=`ls /dev/ttyUSB* | grep -v $DEV`
        DEVS="$DEV $TTY"

        while [ $CONNECTED == "0" ]; do
            for i in $DEVS; do
                if [ "$COUNT" -lt "5" ]; then
                    #disconnect first
                    MODE="AT^NDISDUP=1,0" gcom -d $i -s /etc/gcom/setverbose.gcom > /tmp/4g.mode

                    #change network type if required
                    MODE="AT^SYSCFGEX?" gcom -d $i -s /etc/gcom/setverbose.gcom > /tmp/4g.mode
                    RESULT=`cat /tmp/4g.mode | grep SYSCFGEX | grep '"' | cut -d '"' -f2`

                    case "$RESULT" in
                        "00") RES1="Auto" ;;
                        "03") RES1="4G only" ;;
                        "02") RES1="3G only" ;;
                        "0302") RES1="4G/3G only" ;;
                        "030201") RES1="4G/3G/2G" ;;
                        *) RES1="unknown" ;;
                    esac

                    case "$SPEED" in
                        "00") SPD1="Auto" ;;
                        "03") SPD1="4G only" ;;
                        "02") SPD1="3G only" ;;
                        "0302") SPD1="4G/3G only" ;;
                        "030201") SPD1="4G/3G/2G" ;;
                        *) SPD1="unknown" ;;
                    esac


                    if [ "$RESULT" == "$SPEED" ]; then
                        logger 4G MODEM - Network type is $RES1
                    else
                        logger 4G MODEM - Network type changed: was $RES1, now $SPD1
                        MODE="AT^SYSCFGEX=\"$SPEED\",3fffffff,2,4,7fffffffffffffff,," gcom -d $i -s /etc/gcom/setverbose.gcom
                        sleep 5
                    fi

                    #connecting
                    MODE="AT^NDISDUP=1,1,\"$APN\"" gcom -d $i -s /etc/gcom/setverbose.gcom
                    MODE="AT+CGPADDR=1" gcom -d $i -s /etc/gcom/setverbose.gcom > /tmp/4g.mode

                    CHECK=`cat /tmp/4g.mode | grep "+CGPADDR:" | cut -d '"' -f2 | wc -l`
                    if [ "$CHECK" == "1" ]; then
                        logger 4G MODEM - connected ...
                        CONNECTED=1
                        COUNT=6
                        nvram set modem_dev4g="$i"
                        break;
                    else
                        logger 4G MODEM - device $i connection failed.
                        sleep 5
                        COUNT=`expr $COUNT + 1`
                    fi
                fi
            done

            # checked all devices but still not connected?
            if [ $CONNECTED == "0" ]; then
                INTERVAL=`nvram get mwan_cktime`
                if [ "$INTERVAL" -gt 0 ]; then
                    logger 4G MODEM - connection failed - watchdog enabled
                    watchdog add
                else
                    logger 4G MODEM - connection failed - process terminated!
                    watchdog del
                fi
                rm $LOCK;
                exit 0;
            fi
        done
    elif [ "$TYPE" == "qmi_wwan" ]; then
        CLID=""

        # wait till registered
        while [ `uqmi -s -d "$DEV" --get-serving-system | grep searching | wc -l` != "0" ]; do
            sleep 5
        done

        # set lte mode
        uqmi -s -d "$DEV" --set-network-modes "lte"
        sleep 2

        if [ "$CLID" == "" ]; then
            # get client id for wds - only once!
            CLID=`uqmi -s -d "$DEV" --get-client-id wds`
            nvram set modem_clid=$CLID
            logger 4G MODEM - got new Client ID: $CLID
        fi

        CONNECTED=0
        COUNT=0
        while [ $CONNECTED == "0" ]; do
            if [ "$COUNT" -lt "5" ]; then

                if [ "$CLID" != "" ]; then
                    #connect...
                    PDH=`uqmi -s -d "$DEV" --set-client-id wds,"$CLID" --start-network "$APN" --autoconnect`
                    case $PDH in
                    ''|*[!0-9]*)
                        logger "4G MODEM - device $DEV connection failed."
                        sleep 5
                        COUNT=`expr $COUNT + 1`
                        ;;
                    *)
                        logger "4G MODEM - connected ..."
                        CONNECTED=1
                        COUNT=6
                        logger 4G MODEM - Session ID: $PDH
                        nvram set modem_pdh=$PDH
                        break;
                        ;;
                    esac
                else
                    logger "4G MODEM - Unable to obtain client ID"
                    exit 0;
                fi
            else
                # checked 5 times but still not connected?
                INTERVAL=`nvram get mwan_cktime`
                if [ "$INTERVAL" -gt 0 ]; then
                    logger 4G MODEM - connection failed - watchdog enabled
                    watchdog add
                else
                    logger 4G MODEM - connection failed - process terminated!
                    watchdog del
                fi
                rm $LOCK;
                exit 0;
            fi
        done
    fi

    GO=0
    COUNT=1

    while [ $GO = "0" ]; do
        if [ "$COUNT" == "5" ]; then
            INTERVAL=`nvram get mwan_cktime`
            if [ "$INTERVAL" -gt 0 ]; then
                logger 4G MODEM WAN IFACE failed - watchdog enabled
                watchdog add
            else
                logger 4G MODEM WAN IFACE failed - connection process terminated!
                watchdog del
            fi
            rm $LOCK
            exit 0;
        else
            dhcpc-release $PREFIX
            sleep 1
            dhcpc-renew $PREFIX

            CHECKIFA=`ifconfig | grep $IFA | wc -l`
            if [ "$CHECKIFA" == "1" ]; then
                GO=1
                logger 4G MODEM - WAN IFACE configured ...
                watchdog add
                echo "1" > /tmp/state_$PREFIX
                signal
            else
                logger 4G MODEM WAN IFACE - count: $COUNT
                COUNT=`expr $COUNT + 1`
                sleep 5
            fi
        fi
    done
}

disconnect() {
    DEV=`nvram get modem_dev4g`
    TYPE=`nvram get modem_type`
    CLID=`nvram get modem_clid`

    logger 4G MODEM - disconnecting ...
    watchdog del
    dhcpc-release $PREFIX

    if [ "$TYPE" == "non-hilink" -o "$TYPE" == "hw-ether" ]; then
        MODE="AT^NDISDUP=1,0" gcom -d $DEV -s /etc/gcom/setmode.gcom
    elif [ "$TYPE" == "qmi_wwan" ]; then
        # disable previous autoconnect state using the global handle
        # do not reuse previous wds client id to prevent hangs caused by stale data
        uqmi -s -d "$DEV" --stop-network 0xffffffff --autoconnect
        if [ "$CLID" != "" ]; then
            logger 4G MODEM - release Client ID: $CLID
            uqmi -s -d "$DEV" --set-client-id wds,"$CLID" --release-client-id wds
            nvram unset modem_pdh
            nvram unset modem_clid
        fi
    fi

    logger 4G MODEM - disconnected ...

}

checkLock() {
    if [ -f $LOCK ]; then #lock exist
        logger 4G MODEM - previous proces of switch4g still working

        TEST=`ps | grep switch4g | grep -v "grep" | wc -l`
        if [ "$TEST" == "0" ]; then  #lock file exist but process doesn`t.
            rm $LOCK
        fi
        exit 0
    else
        touch $LOCK
    fi
}

setPIN() {
    PIN=`nvram get "$PREFIX"_modem_pin`
    IS_PIN=`nvram get "$PREFIX"_modem_pin | wc -w`

    if [ "$IS_PIN" == "1" ]; then #only for non-hilink

        if [ "$TYPE" == "non-hilink" -o "$TYPE" == "hw-ether" ]; then
            #we try use last diag iface first. If it failed then we try use any other ttyUSB device
            TTY=`ls /dev/ttyUSB* | grep -v $DEV`
            DEVS="$DEV $TTY"
            COUNT=1

            if [ "$COUNT" -lt "5" ]; then
                for i in $DEVS; do
                    PINCODE="$PIN" gcom -d $i -s /etc/gcom/setpin.gcom > /tmp/4g.pin
                    IS_READY=`cat /tmp/4g.pin | grep successfully | wc -l`
                    if [ "$IS_READY" == "1" ]; then
                        logger 4G MODEM - SIM ready
                        nvram set modem_dev4g="$i"
                        break;
                    else
                        logger 4G MODEM - SIM not ready - count: $COUNT
                        COUNT=`expr $COUNT + 1`
                        sleep 5
                    fi
                done
            else
                logger 4G MODEM - SIM locked - connection process terminated!
                watchdogDel
                exit 0;
            fi
        elif [ "$TYPE" == "qmi_wwan" ]; then
            # get pin status
            PINSTATUS = `uqmi -s -d "$DEVNR" --get-pin-status | cut -d "," -f 1 | cut -d ":" -f 2 | cut -d "\"" -f2`
            if [ "$PINSTATUS" != 'disabled' ]; then
                uqmi -s -d "$DEVNR" --verify-pin1 "$PIN"
            fi
        fi
    fi
}

switchMode() {
    MODULES="qmi_wwan cdc_ether huawei_ether cdc_ncm"

    for MODULE in $MODULES; do
        modprobe -r $MODULE
    done

    COUNT=0
    FOUND=0

    while [ $FOUND == "0" ]; do
        #modem not found, try detect
        DEVICES=`lsusb | awk '{print $6}'`

        for SWITCH in $DEVICES; do
            SEARCH=`ls /etc/usb_modeswitch.d/$SWITCH | wc -l`

            # vendor:product

            if [ "$SEARCH" == "1" ]; then
                logger 4G MODEM FOUND - $SWITCH - Switching ...
                DV=`echo $SWITCH | cut -d ":" -f1`
                DP=`echo $SWITCH | cut -d ":" -f2`
                /usr/sbin/usb_modeswitch -Q -c /etc/usb_modeswitch.d/$SWITCH -v $DV -p $DP

                TEST1=`cat /etc/usb_modeswitch.d/$SWITCH | grep "TargetVendor" | cut -d "=" -f2 | wc -l`
                if [ "$TEST1" == "1" ]; then
                    VENDOR=`cat /etc/usb_modeswitch.d/$SWITCH | grep "TargetVendor" | cut -d "=" -f2 | cut -d "x" -f2`
                else
                    VENDOR=`echo $SWITCH | cut -d ":" -f1`
                fi

                TEST2=`lsusb | awk '{print $6}' | grep $VENDOR | wc -l`
                if [ "$TEST2" == "1" ]; then
                    PRODUCT=`lsusb | awk '{print $6}' | grep $VENDOR | cut -d ":" -f2`
                    logger 4G MODEM ready - $VENDOR:$PRODUCT
                    echo "$VENDOR:$PRODUCT" > /tmp/4g.detect
                fi
            fi
        done

        #need few seconds before modem will be detected once again after switch
        sleep 10

        # is modem ready?
        for MODULE in $MODULES; do
            modprobe $MODULE
            sleep 2

            SEARCH=`cat /proc/bus/usb/devices | grep Driver | grep $MODULE | wc -l`

            if [ "$SEARCH" -gt 0 ]; then
                if [ "$MODULE" == "cdc_ether" ]; then
                    TYPE="hilink"
                elif [ "$MODULE" == "cdc_ncm" ]; then
                    TYPE="non-hilink"
                elif [ "$MODULE" == "huawei_ether" ]; then
                    TYPE="hw-ether"
                elif [ "$MODULE" == "qmi_wwan" ]; then
                    TYPE="qmi_wwan"
                else
                    TYPE="unknown"
                fi

                logger 4G MODEM NDIS found - $TYPE - using $MODULE module
                nvram set 4g_module=$MODULE
                FOUND=1
                break;
            else
                if [ "$COUNT" == "5" ]; then
                    logger 4G MODEM NDIS not found - process terminated!
                    rm $LOCK
                    exit 0;
                else
                    logger 4G MODEM NDIS not found - $MODULE - count: $COUNT
                    modprobe -r $MODULE
                    COUNT=`expr $COUNT + 1`
                    sleep 5
                fi
            fi
        done
    done
}

searchWAN() {

    #search WAN interface (usbX or ethX)
    FOUND=0
    COUNT=0

    KERNEL=`uname -r | cut -d "." -f1,2,3`

    while [ $FOUND == "0" ]; do
        if [ "$TYPE" == "hw-ether" ]; then
            WAN=`dmesg | grep huawei_ether | grep Device | grep register | cut -d ":" -f1 | tail -1`
        elif [ "$KERNEL" == "2.6.36" ]; then #ARM
            WAN=`dmesg | grep $MODULE | grep register | grep "'" | cut -d " " -f3 | cut -d ":" -f1 | tail -1`
        else #MIPSEL
            WAN=`dmesg | grep $MODULE | grep register | grep "'" | cut -d ":" -f1 | tail -1`
        fi

        IS_WAN=`echo $WAN | wc -w`

        if [ "$IS_WAN" -gt 0 ]; then
            logger 4G MODEM WAN found - $TYPE - using $WAN as WAN
            nvram set wan_4g="$WAN"
            nvram set modem_type=$TYPE
            FOUND=1
            echo "$WAN" > /tmp/4g.ready
        else
            if [ "$COUNT" == "5" ]; then
                logger 4G MODEM WAN not found - connection process terminated!
                rm $LOCK
                exit 0;
            else
                logger 4G MODEM WAN not found - count: $COUNT
                COUNT=`expr $COUNT + 1`
                sleep 5
            fi
        fi
    done
}

searchDiag() {
    FOUND=0

    if [ "$TYPE" == "non-hilink" -o "$TYPE" == "hw-ether" ]; then
        US=`cat /proc/bus/usb/devices | grep Driver | grep usbserial | wc -l`

        if [ "$US" -gt 0 ]; then
            logger 4G MODEM found - Diagnostic interface - using usbserial module
            break;
        else
            IS_VENDOR=`echo $VENDOR | wc -w`
            if [ "$IS_VENDOR" -gt 0 ]; then
                IS_PRODUCT=`echo $PRODUCT | wc -w`
                if [ "$IS_PRODUCT" -gt 0 ]; then
                    logger 4G MODEM - loading module usbserial
                    modprobe -r usbserial
                    insmod usbserial vendor=0x$VENDOR product=0x$PRODUCT
                    echo "$VENDOR:$PRODUCT" > /tmp/4g.detect
                fi
            fi

            DEV=`cat /proc/bus/usb/devices | grep Driver | grep usbserial | wc -l`
            if [ "$DEV" -gt 0 ]; then
                logger 4G MODEM ready - using usbserial module
                FOUND=1
                nvram set 4g_module=usbserial
            else
                #last change. try load usbserial for each usb devices
                DEVICES=`lsusb | awk '{print $6}'`
                for SWITCH in $DEVICES; do
                    if [ "$FOUND" == "0" ]; then
                        VENDOR=`echo $SWITCH | cut -d ":" -f1`
                        PRODUCT=`echo $SWITCH | cut -d ":" -f2`
                        modprobe -r usbserial
                        insmod usbserial vendor=0x$VENDOR product=0x$PRODUCT

                        DEV=`cat /proc/bus/usb/devices | grep Driver | grep usbserial | wc -l`
                        if [ "$DEV" -gt 0 ]; then
                            logger 4G MODEM ready - using usbserial module
                            nvram set 4g_module=usbserial
                            echo "$VENDOR:$PRODUCT" > /tmp/4g.detect
                            FOUND=1
                            break;
                        fi
                    fi
                done
            fi
        fi

        #search diagnostic device
        TTY=`ls /dev/ttyUSB*`

        for i in $TTY; do
            CHECKTTY=`gcom -d $i -s /etc/gcom/getcardinfo.gcom | grep OK | wc -l`
            if [ "$CHECKTTY" == "1" ]; then #found working interface
                logger 4G MODEM DIAG found - $i
                nvram set modem_dev4g=$i
                DEVNR=$i
            else
                logger 4G MODEM DIAG not found
            fi
        done
    elif [ "$TYPE" == "qmi_wwan" ]; then
        #search diagnostic device
        TTY=`ls /dev/cdc-wdm*`

        for i in $TTY; do
            CHECKTTY=`uqmi -s -d "$i" --get-versions | grep service | wc -l`
            if [ "$CHECKTTY" == "1" ]; then #found working interface
                logger 4G MODEM DIAG found - $i
                nvram set modem_dev4g=$i
                DEVNR=$i
            else
                logger 4G MODEM DIAG not found
            fi
        done
    fi
}

signal() {
    DEVNR=`nvram get modem_dev4g`
    TYPE=`nvram get modem_type`



    if [ "$TYPE" == "non-hilink" -o "$TYPE" == "hw-ether" ]; then
        HCSQ=`MODE="AT^HCSQ?" gcom -d $DEVNR -s /etc/gcom/setverbose.gcom | grep "HCSQ:" | tr -d '\r'`
        SPEED=`echo $HCSQ | cut -d "," -f1 | cut -d '"' -f2`
        case "$SPEED" in
            "LTE")
                    VALUE=`echo $HCSQ | cut -d "," -f2`
                    RSSI=`awk "BEGIN {print -120+$VALUE}"` #dBm
                    VALUE=`echo $HCSQ | cut -d "," -f3`
                    RSRP=`awk "BEGIN {print -140+$VALUE}"` #dBm
                    VALUE=`echo $HCSQ | cut -d "," -f4`
                    SINR=`awk "BEGIN {print -20+$VALUE*0.2}"` #dB
                    VALUE=`echo $HCSQ | cut -d "," -f5`
                    RSRQ=`awk "BEGIN {print -19.5+$VALUE*0.5}"` #dB
                    logger "4G MODEM Current Mode: $SPEED"
                    logger "4G MODEM Signal Strength: RSSI $RSSI dBm, RSRP $RSRP dBm, SINR $SINR dB, RSRQ $RSRQ dB"
            ;;
            "WCDMA")
                    VALUE=`echo $HCSQ | cut -d "," -f2`
                    RSSI=`awk "BEGIN {print -120+$VALUE}"` #dBm
                    VALUE=`echo $HCSQ | cut -d "," -f3`
                    RSRP=`awk "BEGIN {print -120+$VALUE}"` #dBm
                    VALUE=`echo $HCSQ | cut -d "," -f4`
                    ECIO=`awk "BEGIN {print -32+$VALUE*0.5}"` #dB
                    logger "4G MODEM Current Mode: $SPEED"
                    logger "4G MODEM Signal Strength: RSSI $RSSI dBm, RSRP $RSRP dBm, ECIO $SINR dB"
            ;;
            "GSM")
                    VALUE=`echo $HCSQ | cut -d "," -f2`
                    RSSI=`awk "BEGIN {print -120+$VALUE}"` #dBm
                    logger "4G MODEM Current Mode: $SPEED"
                    logger "4G MODEM Signal Strength: RSSI $RSSI dBm"
            ;;
            *)
                    logger "4G MODEM Current Mode: unknown"
                    logger "4G MODEM Signal Strength: no data"
            ;;
        esac
    elif [ "$TYPE" == "qmi_wwan" ]; then
        RSSI=`uqmi -s -d "$DEVNR" --get-signal-info | cut -d "," -f2 | cut -d ":" -f2`
        RSRQ=`uqmi -s -d "$DEVNR" --get-signal-info | cut -d "," -f3 | cut -d ":" -f2`
        RSRP=`uqmi -s -d "$DEVNR" --get-signal-info | cut -d "," -f4 | cut -d ":" -f2`
        logger "4G MODEM Signal Strength: RSSI $RSSI dBm, RSRP $RSRP dB, RSRQ $RSRQ dB"
    fi
}


###################################################

if [ "$2" == "connect" ]; then
    connect
elif [ "$2" == "disconnect" ]; then
    disconnect
elif [ "$2" == "signal" ]; then
    signal
else
    checkLock

    if [ ! -f $READY ]; then #modem not detected
        switchMode

        searchWAN

        if [ "$TYPE" == "non-hilink" -o "$TYPE" == "hw-ether" -o "$TYPE" == "qmi_wwan" ]; then #only for non-hilink
            searchDiag

            setPIN
        fi
    fi

    #force connection after detect 4G modem
    connect

    #remove lock
    rm $LOCK
fi
