#!/bin/bash
#
# SPDX-License-Identifier: Apache-2.0
#
# Authors:
#     2021    Tzongyen Lin    <Tzongyen_Lin@moxa.com>

TOOL_VERSION="1.0.5"

FWR_PATH="/etc/moxa-cellular-firmware-upgrade-tool/firmware"
STATUS_PATH="/etc/moxa-cellular-firmware-upgrade-tool/status"
CACHE_PATH="/etc/moxa-cellular-firmware-upgrade-tool/cache"

ENABLE_NOPROMPT=
ENABLE_FORCE_INSTALL=
ENABLE_RECOVER_INSTALL=
CONTROL_BY_MCM=

SLOT_ID=1
MODEM_UPGRADE_PORT=
MODEM_ID=
MODEM_MANUFACTURER=
MODEM_NAME=
MODEM_HW_VERSION=
MODEM_SW_VERSION=
MODEM_IMEI=
MODEM_SYS_PATH=
PACKAGE_NAME=
MODEM_DEFAULT_INFO_NAME=
MODEM_FWR_INFO_FILEPATH=

TARGET_MODEM_IMEI=

regex="^[0-9]+$"
UNIT_REGEX="[0-9]+"

ERR_SUCCESS=0
ERR_CANCEL=1
ERR_GENERIC_FAIL=2
ERR_DOWNLOAD_FAIL=3
ERR_FIRMWARE_NOEXISTS=4
ERR_UPGRADE_FAIL=5

WAIT_MODEM_UPGRADE_FINISH_TIMEOUT=30 #300s

_logger () {
    logger -t "Moxa-Cellular-Firmware-Upgrade" "$*"
    echo -e "$*"
}

usage() {
    echo -e "Usage:"
    echo -e "    moxa-cellular-firmware-upgrade-tool <options>"
    echo -e "Options:"
    echo -e "    -s [Slot ID]"
    echo -e "        Specify the cellular module by slot id else use slot 1 by default."
    echo -e "        e.g."
    echo -e "            UC-3101-T-US-LX/UC-3121-T-US-LX/UC-3111-T-US-LX:"
    echo -e "            # moxa-cellular-firmware-upgrade-tool -s 1"
    echo -e "            MC-1200:"
    echo -e "           # moxa-cellular-firmware-upgrade-tool -s 1"
    echo -e "           # moxa-cellular-firmware-upgrade-tool -s 2"
    echo -e "    -m [Module IMEI]"
    echo -e "    -M"
    echo -e "        with MCM"
    echo -e "    -y"
    echo -e "        Upgrade module firmware with no prompt"
    echo -e "        e.g."
    echo -e "            # moxa-cellular-firmware-upgrade-tool -y"
    echo -e "    -f"
    echo -e "        force install  module firmware"
    echo -e "    -F"
    echo -e "        Specify module firmware file"
    echo -e "        e.g."
    echo -e "           # moxa-cellular-firmware-upgrade-tool -F /etc/moxa-cellular-firmware-upgrade-tool/firmware/Telit-LE910C1-EU-Info"
    echo -e "    -d"
    echo -e "        Only download lastest module firmware"
    echo -e "    -h"
    echo -e "        Show the usage manual"
    echo -e "    -v"
    echo -e "        Show firmware and utility version"
    exit 99
}

get_firmware_name () {
    local fwr_info_filename=${1}
    local fwr_bin_filename=$(cat ${fwr_info_filename} 2>/dev/null | grep "Name:" | tr -d ' ' | cut -d ':' -f 2)

    if [ -z "${fwr_bin_filename}" ];then
        return 1
    fi

    fwr_bin_filename=${FWR_PATH}/${fwr_bin_filename}

    echo ${fwr_bin_filename}
}

get_firmware_version () {
    local fwr_info_filename=${1}
    local fwr_bin_version=$(cat ${fwr_info_filename} 2>/dev/null | grep "Version:" | tr -d ' '| cut -d ':' -f 2)

    echo ${fwr_bin_version}
}

get_firmware_pkg_version () {
    local fwr_info_filename=${1}
    local fwr_pkg_version=$(cat ${fwr_info_filename} 2>/dev/null | grep "PKG:" | tr -d ' '| cut -d ':' -f 2)

    echo ${fwr_pkg_version}
}


check_need_download_firmware () {
    if [ "${ENABLE_FORCE_INSTALL}" = "Y" ];then
        return $ERR_SUCCESS
    fi

    if [ "${CONTROL_BY_MCM}" = "Y" ] ; then
        local package_version=$(get_firmware_pkg_version ${CACHE_PATH}/${PACKAGE_NAME}.cache)
        local latest_package_version=$(apt-cache policy ${PACKAGE_NAME} | grep "Candidate:" | tr -d ' ' | cut -d ':' -f 2)
        local package_sw_version=$(get_firmware_version ${CACHE_PATH}/${PACKAGE_NAME}.cache)

        if [ "${package_version}" = "${latest_package_version}" ] ; then
            if [ "${package_sw_version}" = "${MODEM_SW_VERSION}" ]; then
                _logger "The module is already up to date"
                return $ERR_CANCEL
            fi
        fi
    fi
    return $ERR_SUCCESS
}

Quectel_EC20_upgrade_hook() {
    local fwr_file=$1

    ps aux | grep QFirehose | awk '{print $2}' | xargs kill -9 2>/dev/null
    sleep 5
    QFirehose -f ${fwr_file} -p ${MODEM_UPGRADE_PORT}
}

Quectel_RM520N_CN_upgrade_hook () {
    local fwr_file=$1

    ps aux | grep QFirehose | awk '{print $2}' | xargs kill -9 2>/dev/null
    sleep 5
    QFirehose -f ${fwr_file} -p ${MODEM_UPGRADE_PORT}
}

Telit_LE910CX_upgrade_hook () {
    local fwr_file=$1
    local is_recovery=$2

    ps aux | grep uxfp | awk '{print $2}' | xargs kill -9 2>/dev/null
    sleep 5

    if [ "${is_recovery}" = "true" ];then
        uxfp --file ${fwr_file}  --lossrecovery
    else
        uxfp --file ${fwr_file} --port ${MODEM_UPGRADE_PORT}
    fi
}

Telit_LE910C1_AP_upgrade_hook () {
    Telit_LE910CX_upgrade_hook $1 $2
}

Telit_LE910C1_EU_upgrade_hook () {
    Telit_LE910CX_upgrade_hook $1 $2
}

Telit_LE910C1_NF_upgrade_hook () {
    Telit_LE910CX_upgrade_hook $1 $2
}

Telit_LE910C4_AP_upgrade_hook () {
    Telit_LE910CX_upgrade_hook $1 $2
}

Telit_LE910C4_EU_upgrade_hook () {
    Telit_LE910CX_upgrade_hook $1 $2
}

Telit_LE910C4_NF_upgrade_hook () {
    Telit_LE910CX_upgrade_hook $1 $2
}

Telit_FN990A28_upgrade_hook () {
    Telit_LE910CX_upgrade_hook $1 $2
}

Telit_LE910C4_WWXD_upgrade_hook () {
    Telit_LE910CX_upgrade_hook $1 $2
}

upgrade_firmware() {
    local answer=""
    local fwr_file=
    local fwr_version=
    local info_file=

    if [ ! -e ${port} ]; then
        _logger "There is no ${port}"
        exit $ERR_GENERIC_FAIL
    fi

    if [ "${ENABLE_NOPROMPT}" != "Y" ] ; then
        echo -n "Do you want to continue? (y/N)"
        read answer
        if [ "${answer}" != "y" ] && [ "${answer}" != "Y" ]; then
            exit $ERR_CANCEL
        fi
    fi

    if [ -z ${MODEM_FWR_INFO_FILEPATH} ]; then
        info_file=${MODEM_DEFAULT_INFO_NAME}
    else
        info_file=${MODEM_FWR_INFO_FILEPATH}
    fi

    _logger "Firmware information: ${info_file}"

    fwr_file=$(get_firmware_name ${info_file})
    if [ -z "${fwr_file}" ] ||  [ ! -e ${fwr_file} ]; then
        _logger ${fwr_file} "no exist"
        exit $ERR_FIRMWARE_NOEXISTS
    fi

    check_fwr_name=${MODEM_NAME}
    if [ "${MODEM_NAME}" = "RM520N-CN" ];then
        check_fwr_name=RM520NCN
    fi
    #check module name
    modem_is_correct=$(echo ${fwr_file} | grep ${check_fwr_name})
    if [ -z "${modem_is_correct}" ] ; then
        _logger ${info_file} "is not a compatible firmware for this modem."
        exit $ERR_CANCEL
    fi

    _logger "Firmware File: ${fwr_file}"
    fwr_version=$(get_firmware_version ${info_file})
    _logger "Current  module firmware version: ${MODEM_SW_VERSION}"
    _logger "Target module firmware version: ${fwr_version}"

    if [ "${ENABLE_FORCE_INSTALL}" != "Y" ] && [[ ! "${fwr_version}" > "${MODEM_SW_VERSION}" ]]; then
        _logger "The target firmware is identical to or older than the current firmware. You can add -f flag to force the upgrade if you have evaluated the risk of using older firmware"

        mkdir -p ${CACHE_PATH}
        cp ${info_file} ${CACHE_PATH}/${PACKAGE_NAME}.cache
        sync
        exit $ERR_CANCEL
    fi

    mkdir -p ${STATUS_PATH}

    {
        echo NAME: ${MODEM_NAME}
        echo HW VERSION: ${MODEM_HW_VERSION}
        echo SW VERSION: ${MODEM_SW_VERSION}
        echo SYSPATH: ${MODEM_SYS_PATH}
        echo UPGRADE PORT: ${MODEM_UPGRADE_PORT}
        echo IMEI: ${MODEM_IMEI}
        echo MANUFACTURER: ${MODEM_MANUFACTURER}
    } > ${STATUS_PATH}/${MODEM_IMEI}.status
    sync

    modprobe option

    if [ -z "${CONTROL_BY_MCM}" ];then
        #stop moxa-connection-manager
        systemctl stop moxa-connection-manager
    fi

    #stop modem-manager
    systemctl stop ModemManager

    sleep 1

    # enter cellular module upgrade mode id
    local retry_count=0
    local upgrade_finish=0

    while true; do
        #retry 3 times
        if [ ${retry_count} -ge 3 ]; then
            break;
        fi

        eval ${HOOK_FUNCTION_NAME}_upgrade_hook ${fwr_file}

        if [ $? -eq 0 ];then
            upgrade_finish=1
            break;
        fi

        retry_count=$((retry_count+1))
    done

    if [ ${upgrade_finish} -eq 1 ]; then
        mkdir -p ${CACHE_PATH}
        rm -rf ${STATUS_PATH}/${MODEM_IMEI}.status
        cp ${info_file} ${CACHE_PATH}/${PACKAGE_NAME}.cache
        sync

        if [ "${CONTROL_BY_MCM}" = "Y" ];then
            _logger "Remove FWR package"
            apt-get purge -y  ${PACKAGE_NAME}
            sync
        fi
    fi

    sleep 5

    _logger "Restart Modemnager...."
    systemctl restart ModemManager
    local retry_count=0
    while true; do
        local modem_id
        systemctl restart ModemManager

        local check_count=0
        while true; do
            modem_id=$(find_modem_id_by_imei ${MODEM_IMEI})
            if [[ ${modem_id} =~ ${regex} ]]; then
                break;
            fi

            #check ${WAIT_MODEM_UPGRADE_FINISH_TIMEOUT} * 10 s
            if [ ${check_count} -ge ${WAIT_MODEM_UPGRADE_FINISH_TIMEOUT} ]; then
                break;
            fi
            sleep 10
            check_count=$((check_count+1))
        done

        if [ -n "${modem_id}" ]; then
            break;
        fi

        #retry 3 times
        if [ ${retry_count} -ge 3 ]; then
            break;
        fi

        retry_count=$((retry_count+1))
        _logger "Retry ${retry_count}"
    done


    sleep 1

    if [ -z "${CONTROL_BY_MCM}" ];then
        _logger "Restart moxa-connection-manager"
        systemctl start moxa-connection-manager
    fi
}

_reinstall_firmware() {
    local retval=0

    info_file=${MODEM_DEFAULT_INFO_NAME}

    _logger "Firmware information: ${info_file}"

    fwr_file=$(get_firmware_name ${info_file})
    if [ ! -e ${fwr_file} ]; then
        echo ${fwr_file} "no exist"
        exit $ERR_FIRMWARE_NOEXISTS
    fi
    _logger "Firmware File: ${fwr_file}"

    fwr_version=$(get_firmware_version ${info_file})
    _logger "Download module firmware version: ${fwr_version}"

    modprobe option

    if [ -z "${CONTROL_BY_MCM}" ];then
        #stop moxa-connection-manager
        systemctl stop moxa-connection-manager
    fi

    _logger "Stop Modemnager"
    #stop modem-manager
    systemctl stop ModemManager

    sleep 1

    # enter cellular module upgrade mode id
    local retry_count=0
    while true; do
        _logger "Retry ${retry_count}"

        #retry 3 times
        if [ ${retry_count} -ge 3 ]; then
            retval=1
            break;
        fi

        eval ${HOOK_FUNCTION_NAME}_upgrade_hook ${fwr_file} true

        if [ $? -eq 0 ];then
            break;
        fi

        retry_count=$((retry_count+1))
    done

    sleep 5

    _logger "Restart Modemnager...."
    local retry_count=0
    while true; do
        local modem_id
        systemctl restart ModemManager

        local check_count=0
        while true; do
            modem_id=$(find_modem_id_by_imei ${MODEM_IMEI})
            if [[ ${modem_id} =~ ${regex} ]]; then
                break;
            fi

            #check 60s
            if [ ${check_count} -ge 6 ]; then
                break;
            fi
            sleep 10
            check_count=$((check_count+1))
        done

        if [ -n "${modem_id}" ]; then
            break;
        fi

        #retry 3 times
        if [ ${retry_count} -ge 3 ]; then
            break;
        fi

        retry_count=$((retry_count+1))
        _logger "Retry ${retry_count}"
    done

    if [ -z "${CONTROL_BY_MCM}" ];then
        _logger "Restart moxa-connection-manager"
        systemctl start moxa-connection-manager
    fi
    return ${retval}
}

find_modem_id_by_slot() {
    local target_slot_id=$1
    local modem_index=-1
    local search_device=
    local port_data=

    local device_name=$(mx-interface-mgmt cellular Cellular${target_slot_id} 2>/dev/NULL | grep "DEVICE_NAME=" | cut -d '=' -f 2)

    if [ -z "${device_name}" ]; then
        echo "Slot" ${target_slot_id} "no exist"
        exit $ERR_GENERIC_FAIL
    fi

    local modem_index_list=$(mmcli -L | cut -d '/' -f6 | cut -d ' ' -f 1 | tr '\n' ' ')

    if [ -z "${modem_index_list}" ]; then
        echo "Not found Modem on IMEI" ${target_imei}
        exit $ERR_GENERIC_FAIL
    fi

    for modem_index in ${modem_index_list} ; do
        port_data=$(mmcli -m $modem_index -K | grep "ports.value")
        if [ -z "${port_data}" ]; then
            echo "No fount Modem on Slot" ${target_slot_id}
            exit $ERR_GENERIC_FAIL
        fi

        search_device=$(echo ${port_data} | grep ${device_name})
        if [ -n "${search_device}" ]; then
                echo $modem_index
                return
        fi

    done

    echo "No fount Modem on Slot" ${target_slot_id}
}

find_modem_id_by_imei() {
    local target_imei=$1
    local modem_index=
    local search_device=
    local port_data=

    local modem_index_list=$(mmcli -L | cut -d '/' -f6 | cut -d ' ' -f 1 | tr '\n' ' ')

    if [ -z "${modem_index_list}" ]; then
        echo "Not found Modem on IMEI" ${target_imei}
        exit $ERR_GENERIC_FAIL
    fi

    for modem_index in ${modem_index_list} ; do
        if [[ ! ${modem_index} =~ ${UNIT_REGEX} ]];then
            echo "No fount Modem on IMEI" ${target_imei}
            exit $ERR_GENERIC_FAIL
        fi

        imei=$(mmcli -m $modem_index -K | grep "modem.generic.equipment-identifier")
        if [ -z "${imei}" ]; then
            echo "No fount Modem on IMEI" ${target_imei}
            exit $ERR_GENERIC_FAIL
        fi

        search_device=$(echo ${imei} | grep ${target_imei})
        if [ -n "${search_device}" ]; then
                echo $modem_index
                return
        fi
    done
    echo "No fount Modem on IMEI" ${target_imei}
}

find_modem_upgrade_port() {
    local modem_sys_path=$1

    local device_port=$(ls ${modem_sys_path} | grep "1.0")
    local _modem_upgrade_port=$(ls ${modem_sys_path}/${device_port} | grep "tty")
    local modem_upgrade_port=/dev/${_modem_upgrade_port}

    echo $modem_upgrade_port
}

download_firmware () {
    echo "Download Firmware..."
    echo -e "  Package Name:" $PACKAGE_NAME

    apt-get update

    check_need_download_firmware
    if [ $? -ne 0 ]; then
        return $ERR_CANCEL
    fi

    apt-get install -y $PACKAGE_NAME
    if [ $? -ne 0 ]; then
        return $ERR_DOWNLOAD_FAIL
    fi
    return $ERR_SUCCESS
}

version() {
    echo "Tool version: ${TOOL_VERSION}"
    echo "Current module firmware version: ${MODEM_SW_VERSION}"
}

function get_module_name () {
    local module_name=$(mmcli -m $MODEM_ID -K | grep model | awk '{print $3}')
    local module_sw_version=$(mmcli -m $MODEM_ID -K | grep modem.generic.revision | awk '{print $3}')
    local manufacturer=$(mmcli -m $MODEM_ID -K | grep manufacturer | awk '{print $3}')

    if [ "${manufacturer}" = "Telit" ]; then
          if [[ ${module_name} =~ "LE910C"* ]];then
               echo "TELIT_LE910CX"
               return 0
          fi
          if [[ ${module_name} =~ "FN990"* ]];then
               echo "TELIT_FN990"
               return 0
          fi
    fi

    if [ "${manufacturer}" = "Quectel" ]; then
          if [[ ${module_name} =~ "RM520N"* ]];then
               echo "QUECTEL_RM520"
               return 0
          fi
    fi

    if [ "${module_name}" = "QUECTEL" ]; then
          if [[ ${module_sw_version} =~ "EC20"* ]];then
               echo "QUECTEL_EC20"
               return 0
          fi
    fi

    if [ "${manufacturer}" = "Compal" ]; then
          if [[ ${module_name} =~ "RXM-E2"* ]];then
               echo "COMPAL_RMX"
               return 0
          fi
    fi
    return 0
}

update_module_info () {
    local plugin_name=
    local module_alias_name=$(get_module_name)

    case "${module_alias_name}" in
    TELIT_FN990)
        MODEM_MANUFACTURER="Telit"
        MODEM_NAME=$(mmcli -m $MODEM_ID -K | grep model | awk '{print $3}')
        MODEM_HW_VERSION=$(mmcli -m $MODEM_ID --command="AT#HWREV" |sed s/response:[[:space:]]//g| tr -d \' | tr -d "\r\n")
        MODEM_SW_VERSION=$(mmcli -m $MODEM_ID --command="AT#SWPKGV" |sed s/response:[[:space:]]//g| tr -d \' | tr -d "\r\n")
        ;;

    TELIT_LE910CX)
        MODEM_MANUFACTURER="Telit"
        MODEM_NAME=$(mmcli -m $MODEM_ID -K | grep model | awk '{print $3}')
        MODEM_HW_VERSION=$(mmcli -m $MODEM_ID --command="AT#HWREV" |sed s/response:[[:space:]]//g| tr -d \' | tr -d "\r\n")
        MODEM_SW_VERSION=$(mmcli -m $MODEM_ID --command="AT#SWPKGV" |sed s/response:[[:space:]]//g| tr -d \' | tr -d "\r\n")
        ;;

    QUECTEL_RM520)
        MODEM_MANUFACTURER="Quectel"
        MODEM_NAME=$(mmcli -m $MODEM_ID -K | grep model | awk '{print $3}')
        MODEM_HW_VERSION=$(mmcli -m $MODEM_ID -K | grep "modem.generic.hardware-revision" | awk '{print $3}')
        MODEM_SW_VERSION=$(mmcli -m $MODEM_ID --command="AT+QGMR" |sed s/response:[[:space:]]//g| tr -d \' | tr -d "\r\n")
        ;;

    QUECTEL_EC20)
        MODEM_MANUFACTURER="Quectel"
        MODEM_NAME="EC20"
        MODEM_HW_VERSION=$(mmcli -m $MODEM_ID -K | grep "modem.generic.hardware-revision" | awk '{print $3}')
        MODEM_SW_VERSION=$(mmcli -m $MODEM_ID --command="AT+QGMR" |sed s/response:[[:space:]]//g| tr -d \' | tr -d "\r\n")
        ;;
    *)
        echo "No Support Module"
        exit $ERR_CANCEL
        ;;
    esac

    MODEM_SYS_PATH=$(mmcli -m $MODEM_ID -K | grep "modem.generic.device\ " | awk '{print $3}')
    MODEM_UPGRADE_PORT=$(find_modem_upgrade_port ${MODEM_SYS_PATH})

    local modem_name=$(echo ${MODEM_NAME}| awk '{print tolower($0)}')
    local modem_manufactuer=$(echo ${MODEM_MANUFACTURER}| awk '{print tolower($0)}')
    PACKAGE_NAME=moxa-${modem_manufactuer}-firmware-${modem_name}
    MODEM_DEFAULT_INFO_NAME=${FWR_PATH}/${MODEM_MANUFACTURER}-${MODEM_NAME}-Info

    local transfer_modem_name=$(echo ${MODEM_NAME}| tr "-" "_")
    HOOK_FUNCTION_NAME=${MODEM_MANUFACTURER}_${transfer_modem_name}
    echo HOOK_FUNCTION_NAME ${HOOK_FUNCTION_NAME}
}

init_normal() {
    if [ -z ${MODEM_IMEI} ]; then
        MODEM_ID=$(find_modem_id_by_slot ${SLOT_ID})

        if [[ ${MODEM_ID} =~ ${regex} ]]; then
            echo Modem Manager ID: ${MODEM_ID}
        else
            echo ${MODEM_ID} #display error message
            exit $ERR_GENERIC_FAIL
        fi

        MODEM_IMEI=$(mmcli -m $MODEM_ID -K | grep "modem.generic.equipment-identifier" | cut -d ':' -f 2 |  tr -d ' ')
    else
        MODEM_ID=$(find_modem_id_by_imei ${MODEM_IMEI})

        if [[ ${MODEM_ID} =~ ${regex} ]]; then
            echo Modem Manager ID: $${modem_id}
        else
            echo ${modem_id} #display error message
            exit $ERR_GENERIC_FAIL
        fi
    fi

    update_module_info

    echo -e "Parsing Module Info..."
    echo -e "  Modem ID:" ${MODEM_ID}
    echo -e "  Modem Name:" ${MODEM_NAME}
    echo -e "  Modem IMEI:" ${MODEM_IMEI}
    echo -e "  Modem HW Version:" ${MODEM_HW_VERSION}
    echo -e "  Modem SW Version:" ${MODEM_SW_VERSION}
    echo -e "  Modem SYS PATH:" ${MODEM_SYS_PATH}
    echo -e "  Modem Upgrade Port:" ${MODEM_UPGRADE_PORT}
    echo -e "  Modem PKG Name:" ${PACKAGE_NAME}
    echo -e "  Modem Default Info Name:"${MODEM_DEFAULT_INFO_NAME}
}

init_reinstall_info() {
    local status_file=$1
    local MODEM_NAME=$(cat ${status_file} | grep "NAME" | tr -d ' '| cut -d ':' -f 2)
    local MODEM_HW_VERSION=$(cat ${status_file} | grep "HW VERSION" | tr -d ' ' | cut -d ':' -f 2)
    local MODEM_SW_VERSION=$(cat ${status_file} | grep "SW VERSION" | tr -d ' '| cut -d ':' -f 2)
    local MODEM_SYS_PATH=$(cat ${status_file} | grep "SYSPATH"  | cut -d \  -f 2)
    local MODEM_IMEI=$(cat ${status_file} | grep "IMEI"  | tr -d ' '| cut -d ':' -f 2)
    local MODEM_MANUFACTURER=$(cat ${status_file} | grep "MANUFACTURER"  | tr -d ' '| cut -d ':' -f 2)
    #local modem_upgrade_port=$(cat ${status_file} | grep "UPGRADE PORT" | tr -d ' ' | cut -d ':' -f 2)
    local modem_upgrade_port=
    local device_port=

    if [ "${MODEM_MANUFACTURER}" = "Telit" ];then
        modprobe option
        echo 18d1 d00d > /sys/bus/usb-serial/drivers/option1/new_id
        sleep 1
    fi

    local retry_count=0
    while true; do
        device_port=$(ls ${MODEM_SYS_PATH} | grep "1.0")
        _modem_upgrade_port=$(ls ${MODEM_SYS_PATH}/${device_port} | grep "tty")
        modem_upgrade_port=/dev/${_modem_upgrade_port}

        if [ -n "${_modem_upgrade_port}" ]; then
            break;
        fi
        sleep 1

        #retry 10 times
        if [ ${retry_count} -ge 10 ]; then
            exit;
        fi

        _logger "Get TTY Port: Retry ${retry_count}"
        retry_count=$((retry_count + 1))
    done

    MODEM_UPGRADE_PORT=${modem_upgrade_port}

    local modem_name=$(echo ${MODEM_NAME}| awk '{print tolower($0)}')
    local modem_manufactuer=$(echo ${MODEM_MANUFACTURER}| awk '{print tolower($0)}')
    PACKAGE_NAME=moxa-${modem_manufactuer}-firmware-${modem_name}
    MODEM_DEFAULT_INFO_NAME=${FWR_PATH}/${MODEM_MANUFACTURER}-${MODEM_NAME}-Info
    local transfer_modem_name=$(echo ${MODEM_NAME}| tr "-" "_")
    HOOK_FUNCTION_NAME=${MODEM_MANUFACTURER}_${transfer_modem_name}

    _logger "Reinstall Module Info..."
    _logger "  Modem Name:" $modem_name
    _logger "  Modem HW Version:" ${modem_hwversion}
    _logger "  Modem SW Version:" ${modem_swversion}
    _logger "  Modem SYS Path:" ${MODEM_SYS_PATH}
    _logger "  Modem Upgrade Port:" ${MODEM_UPGRADE_PORT}
    _logger "  Modem IMEI:" ${MODEM_IMEI}
}

reinstall_firmware() {
    local files=$(ls ${STATUS_PATH})

    _logger "Reinstall firmware .... "
    _logger "Status File: $files"

    if [ -z "${files}" ]; then
        _logger "No Need to reinstall firmware .... "
        return 1
    fi

    for status_file in ${files} ;do
        init_reinstall_info ${STATUS_PATH}/${status_file}
        _reinstall_firmware

        if [ $? -eq 0 ];then
            rm -rf ${STATUS_PATH}/${status_file}
            sync

            if [ -n "${CONTROL_BY_MCM}" ];then
                _logger "System Reboot"
                reboot
            fi
        fi
    done
}

main() {
    local enable_download_fwr="N"
    _logger "Start Moxa-Cellular-Firmware-Upgrade"

    while getopts  "rds:Mm:fF:vhy" flag; do
        if [ "${flag}" = "s" ]; then
            re='^[0-9]+$'
            if ! [[ $OPTARG =~ $re ]] ; then
               echo "Error: Slot ID should be a number" >&2
               usage $0
               exit $ERR_GENERIC_FAIL
            fi

            SLOT_ID=$OPTARG
        elif [ "${flag}" = "m" ]; then
            MODEM_IMEI=$OPTARG
        elif [ "${flag}" = "r" ]; then
            ENABLE_RECOVER_INSTALL="Y"
        elif [ "${flag}" = "f" ]; then
            ENABLE_FORCE_INSTALL="Y"
        elif [ "${flag}" = "F" ]; then
            MODEM_FWR_INFO_FILEPATH=$OPTARG
        elif [ "${flag}" = "d" ]; then
            enable_download_fwr="Y"
        elif [ "${flag}" = "y" ]; then
            ENABLE_NOPROMPT="Y"
        elif [ "${flag}" = "M" ]; then
            CONTROL_BY_MCM="Y"
        elif [ "${flag}" = "h" ]; then
            usage $0
            exit 0
        elif [ "${flag}" = "v" ]; then
            version
            exit 0
        fi
    done

    if [ ! -z "${ENABLE_RECOVER_INSTALL}" ]; then
        reinstall_firmware
        exit 0
    fi

    init_normal

    if [ ${enable_download_fwr} = "Y" ]; then
        download_firmware
        exit $?
    fi

    upgrade_firmware
}

main $@

exit 0
