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

source "/usr/lib/mx-gpio-lib"
source "/usr/lib/mx-common-lib"

SETSETIAL="/usr/bin/setserial"

MODEL_NAME=""
NUM_OF_UART=""
NUM_OF_UART_MODE=4
TARGET_UART_PORT=""
TARGET_UART_MODE=""
TARGET_OPCODE=0
TARGET_GET_MODE_OPCODE=1
TARGET_INVALID_OPCODE=2
TARGET_SET_MODE_OPCODE=3

OS_ID="$(awk -v opt="ID" -F= '$1==opt { print $2 ;}' /etc/os-release | tr -d '"')"

function DA680::profile() {
        UART_PORT_TBL=""
        UART_IO_BOARD_PORT_TBL=("ttyM0" "ttyM1" "ttyM2" "ttyM3"
                "ttyM4" "ttyM5" "ttyM6" "ttyM7"
                "ttyM8" "ttyM9" "ttyM10" "ttyM11"
                "ttyM12" "ttyM13" "ttyM14" "ttyM15")
        NUM_OF_IO_BOARD_PORT_UART=${#UART_IO_BOARD_PORT_TBL[@]}

        UART_MODE_TBL=""
        UART_IO_BOARD_MODE_TBL=("0x0000" "0x0001" "0x0002" "0x0003")

        UART_MODE_STR=""
        UART_MODE_STR1=("RS-232" "RS-485-2W" "RS-422" "RS-485-4W")
}

function DA680::init() {
        # Determine number of uart
        NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IO_BOARD_PORT_UART))

        UART_PORT_TBL=("${UART_IO_BOARD_PORT_TBL[@]}")
        UART_MODE_TBL=("${UART_IO_BOARD_MODE_TBL[@]}")
        UART_MODE_STR=("${UART_MODE_STR1[@]}")
}

function DA680::get_uart_mode() {
        get_uart_mode_mxu11x0 "$@"
}

function DA680::set_uart_mode() {
        set_uart_mode_mxu11x0 "$@"
}

function V3000::profile() {
        UART_PORT_TBL=""
        UART_IT87_GPIO_TBL_PORT0=(13 11 12 1)
        UART_IT87_GPIO_TBL_PORT1=(16 14 15 2)
        NUM_OF_IT87_UART=2

        UART_MODE_TBL=""
        UART_IT87_GPIO_VAL_TBL_MODE0=(1 0 0 0)
        UART_IT87_GPIO_VAL_TBL_MODE1=(0 1 0 1)
        UART_IT87_GPIO_VAL_TBL_MODE2=(0 0 1 1)
        UART_IT87_GPIO_VAL_TBL_MODE3=(0 0 1 1)

        UART_MODE_STR=""
        UART_MODE_STR1=("RS-232" "RS-485-2W" "RS-422/RS-485-4W")
}

function V3000::init() {
        # Determine number of uart
        NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IT87_UART))

        # Determine uart port and uart mode table
        UART_PORT_TBL="UART_IT87_GPIO_TBL_PORT${TARGET_UART_PORT}[@]"
        UART_PORT_TBL=("${!UART_PORT_TBL}")

        if [[ -n $TARGET_UART_MODE ]]; then
                UART_MODE_TBL="UART_IT87_GPIO_VAL_TBL_MODE${TARGET_UART_MODE}[@]"
                UART_MODE_TBL=("${!UART_MODE_TBL}")
        fi

        UART_MODE_STR=("${UART_MODE_STR1[@]}")
}

function V3000::get_uart_mode() {
        get_uart_mode_it87
}

function V3000::set_uart_mode() {
        set_uart_mode_it87
}

function MPC3000::profile() {
        UART_PORT_TBL=""
        UART_IT87_GPIO_TBL_PORT0=(13 11 12 1)
        UART_IT87_GPIO_TBL_PORT1=(16 14 15 2)
        NUM_OF_IT87_UART=2

        UART_MODE_TBL=""
        UART_IT87_GPIO_VAL_TBL_MODE0=(1 0 0 0)
        UART_IT87_GPIO_VAL_TBL_MODE1=(0 1 0 1)
        UART_IT87_GPIO_VAL_TBL_MODE2=(0 0 1 1)
        UART_IT87_GPIO_VAL_TBL_MODE3=(0 0 1 1)

        UART_MODE_STR=""
        UART_MODE_STR1=("RS-232" "RS-485-2W" "RS-422/RS-485-4W")
}

function MPC3000::init() {
        # Determine number of uart
        NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IT87_UART))

        # Determine uart port and uart mode table
        UART_PORT_TBL="UART_IT87_GPIO_TBL_PORT${TARGET_UART_PORT}[@]"
        UART_PORT_TBL=("${!UART_PORT_TBL}")

        if [[ -n $TARGET_UART_MODE ]]; then
                UART_MODE_TBL="UART_IT87_GPIO_VAL_TBL_MODE${TARGET_UART_MODE}[@]"
                UART_MODE_TBL=("${!UART_MODE_TBL}")
        fi

        UART_MODE_STR=("${UART_MODE_STR1[@]}")
}

function MPC3000::get_uart_mode() {
        get_uart_mode_it87
}

function MPC3000::set_uart_mode() {
        set_uart_mode_it87
}

function BXPA101::profile() {
        UART_PORT_TBL=""
        UART_IT87_GPIO_TBL_PORT0=(13 11 12 1)
        UART_IT87_GPIO_TBL_PORT1=(16 14 15 2)
        NUM_OF_IT87_UART=2

        UART_MODE_TBL=""
        UART_IT87_GPIO_VAL_TBL_MODE0=(1 0 0 0)
        UART_IT87_GPIO_VAL_TBL_MODE1=(0 1 0 1)
        UART_IT87_GPIO_VAL_TBL_MODE2=(0 0 1 1)
        UART_IT87_GPIO_VAL_TBL_MODE3=(0 0 1 1)

        UART_MODE_STR=""
        UART_MODE_STR1=("RS-232" "RS-485-2W" "RS-422/RS-485-4W" "RS-422/RS-485-4W")
}

function BXPA101::init() {
        # Determine number of uart
        NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IT87_UART))

        # Determine uart port and uart mode table
        UART_PORT_TBL="UART_IT87_GPIO_TBL_PORT${TARGET_UART_PORT}[@]"
        UART_PORT_TBL=("${!UART_PORT_TBL}")

        if [[ -n $TARGET_UART_MODE ]]; then
                UART_MODE_TBL="UART_IT87_GPIO_VAL_TBL_MODE${TARGET_UART_MODE}[@]"
                UART_MODE_TBL=("${!UART_MODE_TBL}")
        fi

        UART_MODE_STR=("${UART_MODE_STR1[@]}")
}

function BXPA101::get_uart_mode() {
        get_uart_mode_it87
}

function BXPA101::set_uart_mode() {
        set_uart_mode_it87
}

function DRPA100::profile() {
        DRP100_series_profile
}

function DRPA100::init() {
        DRP100_series_init
}

function DRPA100::get_uart_mode() {
        get_uart_mode_it87_and_mxuport "$@"
}

function DRPA100::set_uart_mode() {
        set_uart_mode_it87_and_mxuport "$@"
}

function DRPC100::profile() {
        DRP100_series_profile
}

function DRPC100::init() {
        DRP100_series_init
}

function DRPC100::get_uart_mode() {
        get_uart_mode_it87_and_mxuport "$@"
}

function DRPC100::set_uart_mode() {
        set_uart_mode_it87_and_mxuport "$@"
}

function DRP100_series_profile() {
        IO_BOARD_GPIO_TBL=(33 34 36 37)
        # Refer to main circuit diagram P.37
        IO_BOARD_4_COM_2_LAN_GPIO=(0 0 0 1)
        IO_BOARD_6_COM_GPIO=(1 1 0 1)

        UART_PORT_TBL=""
        UART_IT87_GPIO_TBL_PORT0=(13 11 12 1)
        UART_IT87_GPIO_TBL_PORT1=(16 14 15 2)
        NUM_OF_IT87_UART=2
        UART_IO_BOARD_4_PORT_TBL=("ttyUSB0" "ttyUSB1" "ttyUSB2" "ttyUSB3")
        NUM_OF_IO_BOARD_4_PORT_UART=${#UART_IO_BOARD_4_PORT_TBL[@]}
        UART_IO_BOARD_6_PORT_TBL=("ttyUSB0" "ttyUSB1" "ttyUSB2" "ttyUSB3" "ttyUSB4" "ttyUSB5")
        NUM_OF_IO_BOARD_6_PORT_UART=${#UART_IO_BOARD_6_PORT_TBL[@]}

        UART_MODE_TBL=""
        UART_IT87_GPIO_VAL_TBL_MODE0=(1 0 0 0)
        UART_IT87_GPIO_VAL_TBL_MODE1=(0 1 0 1)
        UART_IT87_GPIO_VAL_TBL_MODE2=(0 0 1 1)
        UART_IT87_GPIO_VAL_TBL_MODE3=(0 0 1 1)
        UART_IO_BOARD_MODE_TBL=("0x0000" "0x0001" "0x0002" "0x0003")

        UART_MODE_STR=""
        UART_MODE_STR1=("RS-232" "RS-485-2W" "RS-422/RS-485-4W" "RS-422/RS-485-4W")
        UART_MODE_STR2=("RS-232" "RS-485-2W" "RS-422" "RS-485-4W")
}

function DRP100_series_init() {
        local io_board_gpio_pins
        local io_board_gpio_val
        local gpc_name
        local ret

        ret=0

        if ! is_module_loaded gpio_it87; then
                echo "gpio_it87 driver is not loaded"
                exit 1
        fi

        if [[ "${OS_ID}" == "centos" ]]; then
                io_board_gpio_pins[0]=$(gpc_it8786 ${IO_BOARD_GPIO_TBL[0]})
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_pins[1]=$(gpc_it8786 ${IO_BOARD_GPIO_TBL[1]})
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_pins[2]=$(gpc_it8786 ${IO_BOARD_GPIO_TBL[2]})
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_pins[3]=$(gpc_it8786 ${IO_BOARD_GPIO_TBL[3]})
                [[ $? -ne 0 ]] && ret=1

                if [[ $ret -ne 0 ]]; then
                        echo "Initialization Failed"
                        exit $ret
                fi

                io_board_gpio_val[0]=$(gpio_get_value_sysfs ${io_board_gpio_pins[0]})
                [[ $? -ne 0 ]] && ret=2
                io_board_gpio_val[1]=$(gpio_get_value_sysfs ${io_board_gpio_pins[1]})
                [[ $? -ne 0 ]] && ret=2
                io_board_gpio_val[2]=$(gpio_get_value_sysfs ${io_board_gpio_pins[2]})
                [[ $? -ne 0 ]] && ret=2
                io_board_gpio_val[3]=$(gpio_get_value_sysfs ${io_board_gpio_pins[3]})
                [[ $? -ne 0 ]] && ret=2

                if [[ $ret -ne 0 ]]; then
                        echo "Initialization Failed"
                        exit $ret
                fi
        else
                io_board_gpio_pins=(
                        $(gpc_it8786_remap ${IO_BOARD_GPIO_TBL[0]})
                        $(gpc_it8786_remap ${IO_BOARD_GPIO_TBL[1]})
                        $(gpc_it8786_remap ${IO_BOARD_GPIO_TBL[2]})
                        $(gpc_it8786_remap ${IO_BOARD_GPIO_TBL[3]})
                )

                gpc_name=$(gpio_get_gpiochip_name gpio_it87)
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_val[0]=$(gpio_get_value_libgpiod ${io_board_gpio_pins[0]} $gpc_name)
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_val[1]=$(gpio_get_value_libgpiod ${io_board_gpio_pins[1]} $gpc_name)
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_val[2]=$(gpio_get_value_libgpiod ${io_board_gpio_pins[2]} $gpc_name)
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_val[3]=$(gpio_get_value_libgpiod ${io_board_gpio_pins[3]} $gpc_name)
                [[ $? -ne 0 ]] && ret=1

                if [[ $ret -ne 0 ]]; then
                        echo "Initialization Failed"
                        exit $ret
                fi
        fi

        # Determine number of uart
        NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IT87_UART))

        if [[ "${IO_BOARD_4_COM_2_LAN_GPIO[*]}" == "${io_board_gpio_val[*]}" ]]; then
                NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IO_BOARD_4_PORT_UART))
        elif [[ "${IO_BOARD_6_COM_GPIO[*]}" == "${io_board_gpio_val[*]}" ]]; then
                NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IO_BOARD_6_PORT_UART))
        fi

        # Determine uart port and uart mode table
        if [[ $TARGET_UART_PORT -ge 0 ]] && [[ $TARGET_UART_PORT -lt $NUM_OF_IT87_UART ]]; then
                UART_PORT_TBL="UART_IT87_GPIO_TBL_PORT${TARGET_UART_PORT}[@]"
                UART_PORT_TBL=("${!UART_PORT_TBL}")

                if [[ -n $TARGET_UART_MODE ]]; then
                        UART_MODE_TBL="UART_IT87_GPIO_VAL_TBL_MODE${TARGET_UART_MODE}[@]"
                        UART_MODE_TBL=("${!UART_MODE_TBL}")
                fi

                UART_MODE_STR=("${UART_MODE_STR1[@]}")
        elif [[ $TARGET_UART_PORT -ge $NUM_OF_IT87_UART ]] && [[ $TARGET_UART_PORT -le $NUM_OF_UART ]]; then
                if [[ $NUM_OF_UART -eq 6 ]]; then
                        UART_PORT_TBL=("${UART_IO_BOARD_4_PORT_TBL[@]}")
                elif [[ $NUM_OF_UART -eq 8 ]]; then
                        UART_PORT_TBL=("${UART_IO_BOARD_6_PORT_TBL[@]}")
                fi

                UART_MODE_TBL=("${UART_IO_BOARD_MODE_TBL[@]}")
                UART_MODE_STR=("${UART_MODE_STR2[@]}")
        fi
}

function BXPA100::profile() {
        IO_BOARD_GPIO_TBL=(91 92 93)
        # Refer to circuit diagram P.3
        IO_BOARD_3_COM_2_LAN_GPIO=(0 1 0)
        IO_BOARD_8_COM_GPIO=(0 0 0)

        UART_PORT_TBL=""
        UART_IT87_GPIO_TBL_PORT0=(13 11 12 1)
        UART_IT87_GPIO_TBL_PORT1=(16 14 15 2)
        NUM_OF_IT87_UART=2
        UART_IO_BOARD_3_PORT_TBL=("ttyUSB0" "ttyUSB1" "ttyUSB2")
        NUM_OF_IO_BOARD_3_PORT_UART=${#UART_IO_BOARD_3_PORT_TBL[@]}
        UART_IO_BOARD_8_PORT_TBL=("ttyUSB0" "ttyUSB1" "ttyUSB2" "ttyUSB3" "ttyUSB4" "ttyUSB5" "ttyUSB6" "ttyUSB7")
        NUM_OF_IO_BOARD_8_PORT_UART=${#UART_IO_BOARD_8_PORT_TBL[@]}

        UART_MODE_TBL=""
        UART_IT87_GPIO_VAL_TBL_MODE0=(1 0 0 0)
        UART_IT87_GPIO_VAL_TBL_MODE1=(0 1 0 1)
        UART_IT87_GPIO_VAL_TBL_MODE2=(0 0 1 1)
        UART_IT87_GPIO_VAL_TBL_MODE3=(0 0 1 1)
        UART_IO_BOARD_MODE_TBL=("0x0000" "0x0001" "0x0002" "0x0003")

        UART_MODE_STR=""
        UART_MODE_STR1=("RS-232" "RS-485-2W" "RS-422/RS-485-4W" "RS-422/RS-485-4W")
        UART_MODE_STR2=("RS-232" "RS-485-2W" "RS-422" "RS-485-4W")
}

function BXPA100::init() {
        BXP100_series_init
}

function BXPA100::get_uart_mode() {
        get_uart_mode_it87_and_mxuport "$@"
}

function BXPA100::set_uart_mode() {
        set_uart_mode_it87_and_mxuport "$@"
}

function BXPC100::profile() {
        IO_BOARD_GPIO_TBL=(80 81 82)
        # Refer to circuit diagram P.3
        IO_BOARD_3_COM_2_LAN_GPIO=(0 1 0)
        IO_BOARD_8_COM_GPIO=(0 0 0)

        UART_PORT_TBL=""
        UART_IT87_GPIO_TBL_PORT0=(13 11 12 1)
        UART_IT87_GPIO_TBL_PORT1=(16 14 15 2)
        NUM_OF_IT87_UART=2
        UART_IO_BOARD_3_PORT_TBL=("ttyUSB0" "ttyUSB1" "ttyUSB2")
        NUM_OF_IO_BOARD_3_PORT_UART=${#UART_IO_BOARD_3_PORT_TBL[@]}
        UART_IO_BOARD_4_PORT_TBL=("ttyUSB0" "ttyUSB1" "ttyUSB2" "ttyUSB3")
        NUM_OF_IO_BOARD_4_PORT_UART=${#UART_IO_BOARD_4_PORT_TBL[@]}
        UART_IO_BOARD_8_PORT_TBL=("ttyUSB0" "ttyUSB1" "ttyUSB2" "ttyUSB3" "ttyUSB4" "ttyUSB5" "ttyUSB6" "ttyUSB7")
        NUM_OF_IO_BOARD_8_PORT_UART=${#UART_IO_BOARD_8_PORT_TBL[@]}

        UART_MODE_TBL=""
        UART_IT87_GPIO_VAL_TBL_MODE0=(1 0 0 0)
        UART_IT87_GPIO_VAL_TBL_MODE1=(0 1 0 1)
        UART_IT87_GPIO_VAL_TBL_MODE2=(0 0 1 1)
        UART_IT87_GPIO_VAL_TBL_MODE3=(0 0 1 1)
        UART_IO_BOARD_MODE_TBL=("0x0000" "0x0001" "0x0002" "0x0003")

        UART_MODE_STR=""
        UART_MODE_STR1=("RS-232" "RS-485-2W" "RS-422/RS-485-4W" "RS-422/RS-485-4W")
        UART_MODE_STR2=("RS-232" "RS-485-2W" "RS-422" "RS-485-4W")

        ADDRESS_OF_DAUGHTER_BOARD_EEPROM="0x54"
        BOARD_INDEX_OFFSET="0x06"
}

function BXPC100::init() {
        BXP100_series_init
}

function BXPC100::get_uart_mode() {
        get_uart_mode_it87_and_mxuport "$@"
}

function BXPC100::set_uart_mode() {
        set_uart_mode_it87_and_mxuport "$@"
}

function BXP100_series_init() {
        local io_board_gpio_pins
        local io_board_gpio_val
        local gpc_name
        local ret

        ret=0

        if ! is_module_loaded gpio_it87; then
                echo "gpio_it87 driver is not loaded"
                exit 1
        fi

        if [[ "${OS_ID}" == "centos" ]]; then
                io_board_gpio_pins[0]=$(gpc_it8786 ${IO_BOARD_GPIO_TBL[0]})
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_pins[1]=$(gpc_it8786 ${IO_BOARD_GPIO_TBL[1]})
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_pins[2]=$(gpc_it8786 ${IO_BOARD_GPIO_TBL[2]})
                [[ $? -ne 0 ]] && ret=1

                if [[ $ret -ne 0 ]]; then
                        echo "Initialization Failed"
                        exit $ret
                fi

                io_board_gpio_val[0]=$(gpio_get_value_sysfs ${io_board_gpio_pins[0]})
                [[ $? -ne 0 ]] && ret=2
                io_board_gpio_val[1]=$(gpio_get_value_sysfs ${io_board_gpio_pins[1]})
                [[ $? -ne 0 ]] && ret=2
                io_board_gpio_val[2]=$(gpio_get_value_sysfs ${io_board_gpio_pins[2]})
                [[ $? -ne 0 ]] && ret=2

                if [[ $ret -ne 0 ]]; then
                        echo "Initialization Failed"
                        exit $ret
                fi
        else
                io_board_gpio_pins=(
                        $(gpc_it8786_remap ${IO_BOARD_GPIO_TBL[0]})
                        $(gpc_it8786_remap ${IO_BOARD_GPIO_TBL[1]})
                        $(gpc_it8786_remap ${IO_BOARD_GPIO_TBL[2]})
                )

                gpc_name=$(gpio_get_gpiochip_name gpio_it87)
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_val[0]=$(gpio_get_value_libgpiod ${io_board_gpio_pins[0]} $gpc_name)
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_val[1]=$(gpio_get_value_libgpiod ${io_board_gpio_pins[1]} $gpc_name)
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_val[2]=$(gpio_get_value_libgpiod ${io_board_gpio_pins[2]} $gpc_name)
                [[ $? -ne 0 ]] && ret=1

                if [[ $ret -ne 0 ]]; then
                        echo "Initialization Failed"
                        exit $ret
                fi
        fi

        # Determine number of uart
        NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IT87_UART))

        local board_index=$(get_board_index_from_eeprom $ADDRESS_OF_DAUGHTER_BOARD_EEPROM $BOARD_INDEX_OFFSET)
        if [[ "${IO_BOARD_3_COM_2_LAN_GPIO[*]}" == "${io_board_gpio_val[*]}" ]]; then
                NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IO_BOARD_3_PORT_UART))
        elif [[ "${board_index}" == "0x06" ]]; then
                NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IO_BOARD_4_PORT_UART))
        elif [[ "${IO_BOARD_8_COM_GPIO[*]}" == "${io_board_gpio_val[*]}" ]]; then
                NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IO_BOARD_8_PORT_UART))
        fi

        # Determine uart port and uart mode table
        if [[ $TARGET_UART_PORT -ge 0 ]] && [[ $TARGET_UART_PORT -lt $NUM_OF_IT87_UART ]]; then
                UART_PORT_TBL="UART_IT87_GPIO_TBL_PORT${TARGET_UART_PORT}[@]"
                UART_PORT_TBL=("${!UART_PORT_TBL}")

                if [[ -n $TARGET_UART_MODE ]]; then
                        UART_MODE_TBL="UART_IT87_GPIO_VAL_TBL_MODE${TARGET_UART_MODE}[@]"
                        UART_MODE_TBL=("${!UART_MODE_TBL}")
                fi

                UART_MODE_STR=("${UART_MODE_STR1[@]}")
        elif [[ $TARGET_UART_PORT -ge $NUM_OF_IT87_UART ]] && [[ $TARGET_UART_PORT -le $NUM_OF_UART ]]; then
                if [[ $NUM_OF_UART -eq 5 ]]; then
                        UART_PORT_TBL=("${UART_IO_BOARD_3_PORT_TBL[@]}")
                elif [[ $NUM_OF_UART -eq 6 ]]; then
                        UART_PORT_TBL=("${UART_IO_BOARD_4_PORT_TBL[@]}")
                elif [[ $NUM_OF_UART -eq 10 ]]; then
                        UART_PORT_TBL=("${UART_IO_BOARD_8_PORT_TBL[@]}")
                fi

                UART_MODE_TBL=("${UART_IO_BOARD_MODE_TBL[@]}")
                UART_MODE_STR=("${UART_MODE_STR2[@]}")
        fi
}

function RKPA110::profile() {
        RKP110_series_profile
}

function RKPA110::init() {
        RKP110_series_init
}

function RKPA110::get_uart_mode() {
        get_uart_mode_it87_and_mxuport "$@"
}

function RKPA110::set_uart_mode() {
        set_uart_mode_it87_and_mxuport "$@"
}

function RKPC110::profile() {
        RKP110_series_profile
}

function RKPC110::init() {
        RKP110_series_init
}

function RKPC110::get_uart_mode() {
        get_uart_mode_it87_and_mxuport "$@"
}

function RKPC110::set_uart_mode() {
        set_uart_mode_it87_and_mxuport "$@"
}

function RKP110_series_profile() {
        IO_BOARD_GPIO_TBL=(50 47 63)
        # Refer to main circuit diagram P.57
        IO_BOARD_4_COM_2_LAN_GPIO=(0 0 1)
        IO_BOARD_8_COM_GPIO=(0 1 1)

        UART_PORT_TBL=""
        UART_IT87_GPIO_TBL_PORT0=(13 11 12 1)
        UART_IT87_GPIO_TBL_PORT1=(16 14 15 2)
        NUM_OF_IT87_UART=2
        UART_IO_BOARD_4_PORT_TBL=("ttyUSB0" "ttyUSB1" "ttyUSB2" "ttyUSB3")
        NUM_OF_IO_BOARD_4_PORT_UART=${#UART_IO_BOARD_4_PORT_TBL[@]}
        UART_IO_BOARD_8_PORT_TBL=("ttyUSB0" "ttyUSB1" "ttyUSB2" "ttyUSB3" "ttyUSB4" "ttyUSB5" "ttyUSB6" "ttyUSB7")
        NUM_OF_IO_BOARD_8_PORT_UART=${#UART_IO_BOARD_8_PORT_TBL[@]}

        UART_MODE_TBL=""
        UART_IT87_GPIO_VAL_TBL_MODE0=(1 0 0 0)
        UART_IT87_GPIO_VAL_TBL_MODE1=(0 1 0 1)
        UART_IT87_GPIO_VAL_TBL_MODE2=(0 0 1 1)
        UART_IT87_GPIO_VAL_TBL_MODE3=(0 0 1 1)
        UART_IO_BOARD_MODE_TBL=("0x0000" "0x0001" "0x0002" "0x0003")

        UART_MODE_STR=""
        UART_MODE_STR1=("RS-232" "RS-485-2W" "RS-422/RS-485-4W" "RS-422/RS-485-4W")
        UART_MODE_STR2=("RS-232" "RS-485-2W" "RS-422" "RS-485-4W")
}

function RKP110_series_init() {
        local io_board_gpio_pins
        local io_board_gpio_val
        local gpc_name
        local ret

        ret=0

        if ! is_module_loaded gpio_it87; then
                echo "gpio_it87 driver is not loaded"
                exit 1
        fi

        if [[ "${OS_ID}" == "centos" ]]; then
                io_board_gpio_pins[0]=$(gpc_it8786 ${IO_BOARD_GPIO_TBL[0]})
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_pins[1]=$(gpc_it8786 ${IO_BOARD_GPIO_TBL[1]})
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_pins[2]=$(gpc_it8786 ${IO_BOARD_GPIO_TBL[2]})
                [[ $? -ne 0 ]] && ret=1

                if [[ $ret -ne 0 ]]; then
                        echo "Initialization Failed"
                        exit $ret
                fi

                io_board_gpio_val[0]=$(gpio_get_value_sysfs ${io_board_gpio_pins[0]})
                [[ $? -ne 0 ]] && ret=2
                io_board_gpio_val[1]=$(gpio_get_value_sysfs ${io_board_gpio_pins[1]})
                [[ $? -ne 0 ]] && ret=2
                io_board_gpio_val[2]=$(gpio_get_value_sysfs ${io_board_gpio_pins[2]})
                [[ $? -ne 0 ]] && ret=2

                if [[ $ret -ne 0 ]]; then
                        echo "Initialization Failed"
                        exit $ret
                fi
        else
                io_board_gpio_pins=(
                        $(gpc_it8786_remap ${IO_BOARD_GPIO_TBL[0]})
                        $(gpc_it8786_remap ${IO_BOARD_GPIO_TBL[1]})
                        $(gpc_it8786_remap ${IO_BOARD_GPIO_TBL[2]})
                )

                gpc_name=$(gpio_get_gpiochip_name gpio_it87)
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_val[0]=$(gpio_get_value_libgpiod ${io_board_gpio_pins[0]} $gpc_name)
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_val[1]=$(gpio_get_value_libgpiod ${io_board_gpio_pins[1]} $gpc_name)
                [[ $? -ne 0 ]] && ret=1
                io_board_gpio_val[2]=$(gpio_get_value_libgpiod ${io_board_gpio_pins[2]} $gpc_name)
                [[ $? -ne 0 ]] && ret=1

                if [[ $ret -ne 0 ]]; then
                        echo "Initialization Failed"
                        exit $ret
                fi
        fi

        # Determine number of uart
        NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IT87_UART))

        if [[ "${IO_BOARD_4_COM_2_LAN_GPIO[*]}" == "${io_board_gpio_val[*]}" ]]; then
                NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IO_BOARD_4_PORT_UART))
        elif [[ "${IO_BOARD_8_COM_GPIO[*]}" == "${io_board_gpio_val[*]}" ]]; then
                NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IO_BOARD_8_PORT_UART))
        fi

        # Determine uart port and uart mode table
        if [[ $TARGET_UART_PORT -ge 0 ]] && [[ $TARGET_UART_PORT -lt $NUM_OF_IT87_UART ]]; then
                UART_PORT_TBL="UART_IT87_GPIO_TBL_PORT${TARGET_UART_PORT}[@]"
                UART_PORT_TBL=("${!UART_PORT_TBL}")

                if [[ -n $TARGET_UART_MODE ]]; then
                        UART_MODE_TBL="UART_IT87_GPIO_VAL_TBL_MODE${TARGET_UART_MODE}[@]"
                        UART_MODE_TBL=("${!UART_MODE_TBL}")
                fi

                UART_MODE_STR=("${UART_MODE_STR1[@]}")
        elif [[ $TARGET_UART_PORT -ge $NUM_OF_IT87_UART ]] && [[ $TARGET_UART_PORT -le $NUM_OF_UART ]]; then
                if [[ $NUM_OF_UART -eq 6 ]]; then
                        UART_PORT_TBL=("${UART_IO_BOARD_4_PORT_TBL[@]}")
                elif [[ $NUM_OF_UART -eq 10 ]]; then
                        UART_PORT_TBL=("${UART_IO_BOARD_8_PORT_TBL[@]}")
                fi

                UART_MODE_TBL=("${UART_IO_BOARD_MODE_TBL[@]}")
                UART_MODE_STR=("${UART_MODE_STR2[@]}")
        fi
}

function DA820E::profile() {
        UART_PORT_TBL=""
        UART_IT87_GPIO_TBL_PORT0=(13 11 12 1)
        UART_IT87_GPIO_TBL_PORT1=(16 14 15 2)
        NUM_OF_IT87_UART=2

        # MODULE_A
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT0=(0 1 2 3)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT1=(4 5 6 7)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT2=(8 9 10 11)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT3=(12 13 14 15)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT4=(0 1 2 3)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT5=(4 5 6 7)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT6=(8 9 10 11)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT7=(12 13 14 15)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT0=(16 17 18 19)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT1=(20 21 22 23)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT2=(24 25 26 27)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT3=(28 29 30 31)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT4=(0 1 2 3)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT5=(4 5 6 7)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT6=(8 9 10 11)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT7=(12 13 14 15)

        NUM_OF_MODULE_A_UART=8
        UART_MODULE_A_CHIP_ADDRESS0="0x26"
        UART_MODULE_A_CHIP_ADDRESS1="0x27"
        UART_CHIP_ADDRESS=""
        UART_MODULE_GPIOCHIP_NAME=""

        UART_MODE_TBL=""
        UART_IT87_GPIO_VAL_TBL_MODE0=(1 0 0 0)
        UART_IT87_GPIO_VAL_TBL_MODE1=(0 1 0 1)
        UART_IT87_GPIO_VAL_TBL_MODE2=(0 0 1 1)
        UART_IT87_GPIO_VAL_TBL_MODE3=(0 0 1 1)
        UART_GPIO_VAL_TBL_MODE0=(1 1 0 0)
        UART_GPIO_VAL_TBL_MODE1=(0 0 0 1)
        UART_GPIO_VAL_TBL_MODE2=(0 0 1 0)
        UART_GPIO_VAL_TBL_MODE3=(0 0 1 0)

        UART_MODE_STR=""
        UART_MODE_STR1=("RS-232" "RS-485-2W" "RS-422/RS-485-4W" "RS-422/RS-485-4W")
}

function DA820E::init() {
        local ft260_module_num_str=$(get_i2c_device_minor_number_list "FT260")
        local ft260_module_num_array=($ft260_module_num_str)
        local ft260_module_num=${#ft260_module_num_array[@]}

        local ret=0

        # Determine number of uart & bind
        NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IT87_UART))
        if [[ $ft260_module_num -eq 1 ]]; then
                NUM_OF_UART=$((NUM_OF_UART += NUM_OF_MODULE_A_UART))
                ret=$(bind_i2c_driver "FT260" "pca9535" $UART_MODULE_A_CHIP_ADDRESS0 $UART_MODULE_A_CHIP_ADDRESS1)
                if [[ $ret -ne 0 ]]; then
                        echo "Bind i2c device fail"
                        exit $ret
                fi
        fi

        # Determine uart port and uart mode table
        if [[ $TARGET_UART_PORT -ge 0 ]] && [[ $TARGET_UART_PORT -lt $NUM_OF_IT87_UART ]]; then
                UART_PORT_TBL="UART_IT87_GPIO_TBL_PORT${TARGET_UART_PORT}[@]"
                UART_PORT_TBL=("${!UART_PORT_TBL}")

                if [[ -n $TARGET_UART_MODE ]]; then
                        UART_MODE_TBL="UART_IT87_GPIO_VAL_TBL_MODE${TARGET_UART_MODE}[@]"
                        UART_MODE_TBL=("${!UART_MODE_TBL}")
                fi

                UART_MODE_STR=("${UART_MODE_STR1[@]}")
        elif [[ $TARGET_UART_PORT -ge $NUM_OF_IT87_UART ]] && [[ $TARGET_UART_PORT -le $NUM_OF_UART ]]; then
                TARGET_MODULE_PORT=$((TARGET_UART_PORT - NUM_OF_IT87_UART))
                if [[ "${OS_ID}" == "centos" ]]; then
                        UART_PORT_TBL="UART_MODULE_A_GPIO_TBL_SYSFS_PORT${TARGET_MODULE_PORT}[@]"
                else
                        UART_PORT_TBL="UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT${TARGET_MODULE_PORT}[@]"
                fi
                UART_PORT_TBL=("${!UART_PORT_TBL}")
                UART_MODE_TBL="UART_GPIO_VAL_TBL_MODE${TARGET_UART_MODE}[@]"
                UART_MODE_TBL=("${!UART_MODE_TBL}")
                UART_MODE_STR=("${UART_MODE_STR1[@]}")
                if [[ $TARGET_UART_PORT -ge 2 ]] && [[ $TARGET_UART_PORT -le 5 ]]; then
                        UART_MODULE_GPIOCHIP_NAME=$(format_as_i2c_directory_name ${ft260_module_num_array[0]} ${UART_MODULE_A_CHIP_ADDRESS0})
                elif [[ $TARGET_UART_PORT -ge 6 ]] && [[ $TARGET_UART_PORT -le 9 ]]; then
                        UART_MODULE_GPIOCHIP_NAME=$(format_as_i2c_directory_name ${ft260_module_num_array[0]} ${UART_MODULE_A_CHIP_ADDRESS1})
                fi
        fi
}

function DA820E::get_uart_mode() {
        get_uart_mode_it87_and_pca953x "$@"
}

function DA820E::set_uart_mode() {
        set_uart_mode_it87_and_pca953x "$@"
}

function DA820C::profile() {
        UART_PORT_TBL=""
        UART_IT87_GPIO_TBL_PORT0=(13 11 12 1)
        UART_IT87_GPIO_TBL_PORT1=(16 14 15 2)
        NUM_OF_IT87_UART=2

        # MODULE_A
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT0=(0 1 2 3)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT1=(4 5 6 7)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT2=(8 9 10 11)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT3=(12 13 14 15)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT4=(0 1 2 3)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT5=(4 5 6 7)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT6=(8 9 10 11)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT7=(12 13 14 15)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT0=(16 17 18 19)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT1=(20 21 22 23)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT2=(24 25 26 27)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT3=(28 29 30 31)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT4=(0 1 2 3)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT5=(4 5 6 7)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT6=(8 9 10 11)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT7=(12 13 14 15)

        NUM_OF_MODULE_A_UART=8
        UART_MODULE_A_CHIP_ADDRESS0="0x26"
        UART_MODULE_A_CHIP_ADDRESS1="0x27"
        UART_CHIP_ADDRESS=""
        UART_MODULE_GPIOCHIP_NAME=""

        UART_MODE_TBL=""
        UART_IT87_GPIO_VAL_TBL_MODE0=(1 0 0 0)
        UART_IT87_GPIO_VAL_TBL_MODE1=(0 1 0 1)
        UART_IT87_GPIO_VAL_TBL_MODE2=(0 0 1 1)
        UART_IT87_GPIO_VAL_TBL_MODE3=(0 0 1 1)
        UART_GPIO_VAL_TBL_MODE0=(1 1 0 0)
        UART_GPIO_VAL_TBL_MODE1=(0 0 0 1)
        UART_GPIO_VAL_TBL_MODE2=(0 0 1 0)
        UART_GPIO_VAL_TBL_MODE3=(0 0 1 0)

        UART_MODE_STR=""
        UART_MODE_STR1=("RS-232" "RS-485-2W" "RS-422/RS-485-4W" "RS-422/RS-485-4W")
}

function DA820C::init() {
        local ft260_module_num_str=$(get_i2c_device_minor_number_list "FT260")
        local ft260_module_num_array=($ft260_module_num_str)
        local ft260_module_num=${#ft260_module_num_array[@]}

        local ret=0

        # Determine number of uart & bind
        NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IT87_UART))
        if [[ $ft260_module_num -eq 1 ]]; then
                NUM_OF_UART=$((NUM_OF_UART += NUM_OF_MODULE_A_UART))
                ret=$(bind_i2c_driver "FT260" "pca9535" $UART_MODULE_A_CHIP_ADDRESS0 $UART_MODULE_A_CHIP_ADDRESS1)
                if [[ $ret -ne 0 ]]; then
                        echo "Bind i2c device fail"
                        exit $ret
                fi
        fi

        # Determine uart port and uart mode table
        if [[ $TARGET_UART_PORT -ge 0 ]] && [[ $TARGET_UART_PORT -lt $NUM_OF_IT87_UART ]]; then
                UART_PORT_TBL="UART_IT87_GPIO_TBL_PORT${TARGET_UART_PORT}[@]"
                UART_PORT_TBL=("${!UART_PORT_TBL}")

                if [[ -n $TARGET_UART_MODE ]]; then
                        UART_MODE_TBL="UART_IT87_GPIO_VAL_TBL_MODE${TARGET_UART_MODE}[@]"
                        UART_MODE_TBL=("${!UART_MODE_TBL}")
                fi

                UART_MODE_STR=("${UART_MODE_STR1[@]}")
        elif [[ $TARGET_UART_PORT -ge $NUM_OF_IT87_UART ]] && [[ $TARGET_UART_PORT -le $NUM_OF_UART ]]; then
                TARGET_MODULE_PORT=$((TARGET_UART_PORT - NUM_OF_IT87_UART))
                if [[ "${OS_ID}" == "centos" ]]; then
                        UART_PORT_TBL="UART_MODULE_A_GPIO_TBL_SYSFS_PORT${TARGET_MODULE_PORT}[@]"
                else
                        UART_PORT_TBL="UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT${TARGET_MODULE_PORT}[@]"
                fi
                UART_PORT_TBL=("${!UART_PORT_TBL}")
                UART_MODE_TBL="UART_GPIO_VAL_TBL_MODE${TARGET_UART_MODE}[@]"
                UART_MODE_TBL=("${!UART_MODE_TBL}")
                UART_MODE_STR=("${UART_MODE_STR1[@]}")
                if [[ $TARGET_UART_PORT -ge 2 ]] && [[ $TARGET_UART_PORT -le 5 ]]; then
                        UART_MODULE_GPIOCHIP_NAME=$(format_as_i2c_directory_name ${ft260_module_num_array[0]} ${UART_MODULE_A_CHIP_ADDRESS0})
                elif [[ $TARGET_UART_PORT -ge 6 ]] && [[ $TARGET_UART_PORT -le 9 ]]; then
                        UART_MODULE_GPIOCHIP_NAME=$(format_as_i2c_directory_name ${ft260_module_num_array[0]} ${UART_MODULE_A_CHIP_ADDRESS1})
                fi
        fi
}

function DA820C::get_uart_mode() {
        get_uart_mode_it87_and_pca953x "$@"
}

function DA820C::set_uart_mode() {
        set_uart_mode_it87_and_pca953x "$@"
}

function DA682C::profile() {
        UART_PORT_TBL=""
        UART_IT87_GPIO_TBL_PORT0=(13 11 12 1)
        UART_IT87_GPIO_TBL_PORT1=(16 14 15 2)
        NUM_OF_IT87_UART=2
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT0=(0 1 2 3)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT1=(4 5 6 7)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT2=(8 9 10 11)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT3=(12 13 14 15)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT4=(0 1 2 3)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT5=(4 5 6 7)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT6=(8 9 10 11)
        UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT7=(12 13 14 15)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT0=(16 17 18 19)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT1=(20 21 22 23)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT2=(24 25 26 27)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT3=(28 29 30 31)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT4=(0 1 2 3)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT5=(4 5 6 7)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT6=(8 9 10 11)
        UART_MODULE_A_GPIO_TBL_SYSFS_PORT7=(12 13 14 15)
        NUM_OF_MODULE_A_UART=8
        UART_MODULE_B_GPIO_TBL_LIBGPIOD_PORT0=(0 1 2 3)
        UART_MODULE_B_GPIO_TBL_LIBGPIOD_PORT1=(4 5 6 7)
        UART_MODULE_B_GPIO_TBL_LIBGPIOD_PORT2=(8 9 10 11)
        UART_MODULE_B_GPIO_TBL_LIBGPIOD_PORT3=(12 13 14 15)
        UART_MODULE_B_GPIO_TBL_LIBGPIOD_PORT4=(0 1 2 3)
        UART_MODULE_B_GPIO_TBL_LIBGPIOD_PORT5=(4 5 6 7)
        UART_MODULE_B_GPIO_TBL_LIBGPIOD_PORT6=(8 9 10 11)
        UART_MODULE_B_GPIO_TBL_LIBGPIOD_PORT7=(12 13 14 15)
        UART_MODULE_B_GPIO_TBL_SYSFS_PORT0=(48 49 50 51)
        UART_MODULE_B_GPIO_TBL_SYSFS_PORT1=(52 53 54 55)
        UART_MODULE_B_GPIO_TBL_SYSFS_PORT2=(56 57 58 59)
        UART_MODULE_B_GPIO_TBL_SYSFS_PORT3=(60 61 62 63)
        UART_MODULE_B_GPIO_TBL_SYSFS_PORT4=(32 33 34 35)
        UART_MODULE_B_GPIO_TBL_SYSFS_PORT5=(36 37 38 39)
        UART_MODULE_B_GPIO_TBL_SYSFS_PORT6=(40 41 42 43)
        UART_MODULE_B_GPIO_TBL_SYSFS_PORT7=(44 45 46 47)
        NUM_OF_MODULE_B_UART=8
        UART_MODULE_A_CHIP_ADDRESS0="0x26"
        UART_MODULE_A_CHIP_ADDRESS1="0x27"
        UART_MODULE_B_CHIP_ADDRESS0="0x26"
        UART_MODULE_B_CHIP_ADDRESS1="0x27"
        UART_CHIP_ADDRESS=""
        UART_MODULE_GPIOCHIP_NAME=""

        UART_MODE_TBL=""
        UART_IT87_GPIO_VAL_TBL_MODE0=(1 0 0 0)
        UART_IT87_GPIO_VAL_TBL_MODE1=(0 1 0 1)
        UART_IT87_GPIO_VAL_TBL_MODE2=(0 0 1 1)
        UART_IT87_GPIO_VAL_TBL_MODE3=(0 0 1 1)
        UART_GPIO_VAL_TBL_MODE0=(1 1 0 0)
        UART_GPIO_VAL_TBL_MODE1=(0 0 0 1)
        UART_GPIO_VAL_TBL_MODE2=(0 0 1 0)
        UART_GPIO_VAL_TBL_MODE3=(0 0 1 0)

        UART_MODE_STR=""
        UART_MODE_STR1=("RS-232" "RS-485-2W" "RS-422/RS-485-4W" "RS-422/RS-485-4W")
}

function DA682C::init() {
        local ft260_module_num_str=$(get_i2c_device_minor_number_list "FT260")
        local ft260_module_num_array=($ft260_module_num_str)
        local ft260_module_num=${#ft260_module_num_array[@]}

        local ret=0

        # Determine number of uart & bind
        NUM_OF_UART=$((NUM_OF_UART += NUM_OF_IT87_UART))
        if [[ $ft260_module_num -eq 1 ]]; then
                NUM_OF_UART=$((NUM_OF_UART += NUM_OF_MODULE_A_UART))
                ret=$(bind_i2c_driver "FT260" "pca9535" $UART_MODULE_A_CHIP_ADDRESS0 $UART_MODULE_A_CHIP_ADDRESS1)
                if [[ $ret -ne 0 ]]; then
                        echo "Bind i2c device fail"
                        exit $ret
                fi
        elif [[ $ft260_module_num -eq 2 ]]; then
                NUM_OF_UART=$((NUM_OF_UART += NUM_OF_MODULE_A_UART))
                NUM_OF_UART=$((NUM_OF_UART += NUM_OF_MODULE_B_UART))
                ret=$(bind_i2c_driver "FT260" "pca9535" $UART_MODULE_A_CHIP_ADDRESS0 $UART_MODULE_A_CHIP_ADDRESS1)
                if [[ $ret -ne 0 ]]; then
                        echo "Bind i2c device fail"
                        exit $ret
                fi
	fi


        # Determine uart port and uart mode table
        if [[ $TARGET_UART_PORT -ge 0 ]] && [[ $TARGET_UART_PORT -lt $NUM_OF_IT87_UART ]]; then
                UART_PORT_TBL="UART_IT87_GPIO_TBL_PORT${TARGET_UART_PORT}[@]"
                UART_PORT_TBL=("${!UART_PORT_TBL}")

                if [[ -n $TARGET_UART_MODE ]]; then
                        UART_MODE_TBL="UART_IT87_GPIO_VAL_TBL_MODE${TARGET_UART_MODE}[@]"
                        UART_MODE_TBL=("${!UART_MODE_TBL}")
                fi

                UART_MODE_STR=("${UART_MODE_STR1[@]}")
        elif [[ $TARGET_UART_PORT -ge $NUM_OF_IT87_UART ]] && [[ $TARGET_UART_PORT -lt $((NUM_OF_MODULE_A_UART + NUM_OF_IT87_UART)) ]]; then
                TARGET_MODULE_PORT=$((TARGET_UART_PORT - NUM_OF_IT87_UART))
                if [[ "${OS_ID}" == "centos" ]]; then
                        UART_PORT_TBL="UART_MODULE_A_GPIO_TBL_SYSFS_PORT${TARGET_MODULE_PORT}[@]"
                else
                        UART_PORT_TBL="UART_MODULE_A_GPIO_TBL_LIBGPIOD_PORT${TARGET_MODULE_PORT}[@]"
                fi
                UART_PORT_TBL=("${!UART_PORT_TBL}")
                UART_MODE_TBL="UART_GPIO_VAL_TBL_MODE${TARGET_UART_MODE}[@]"
                UART_MODE_TBL=("${!UART_MODE_TBL}")
                UART_MODE_STR=("${UART_MODE_STR1[@]}")
                if [[ $TARGET_UART_PORT -ge 2 ]] && [[ $TARGET_UART_PORT -le 5 ]]; then
                        UART_MODULE_GPIOCHIP_NAME=$(format_as_i2c_directory_name ${ft260_module_num_array[0]} ${UART_MODULE_A_CHIP_ADDRESS0})
                elif [[ $TARGET_UART_PORT -ge 6 ]] && [[ $TARGET_UART_PORT -le 9 ]]; then
                        UART_MODULE_GPIOCHIP_NAME=$(format_as_i2c_directory_name ${ft260_module_num_array[0]} ${UART_MODULE_A_CHIP_ADDRESS1})
                fi
        elif [[ $TARGET_UART_PORT -ge $((NUM_OF_MODULE_A_UART + NUM_OF_IT87_UART)) ]] && [[ $TARGET_UART_PORT -le $NUM_OF_UART ]]; then
                TARGET_MODULE_PORT=$((TARGET_UART_PORT - NUM_OF_IT87_UART))
                TARGET_MODULE_PORT=$((TARGET_MODULE_PORT - NUM_OF_MODULE_A_UART))
                if [[ "${OS_ID}" == "centos" ]]; then
                        UART_PORT_TBL="UART_MODULE_B_GPIO_TBL_SYSFS_PORT${TARGET_MODULE_PORT}[@]"
                else
                        UART_PORT_TBL="UART_MODULE_B_GPIO_TBL_LIBGPIOD_PORT${TARGET_MODULE_PORT}[@]"
                fi
                UART_PORT_TBL=("${!UART_PORT_TBL}")
                UART_MODE_TBL="UART_GPIO_VAL_TBL_MODE${TARGET_UART_MODE}[@]"
                UART_MODE_TBL=("${!UART_MODE_TBL}")
                UART_MODE_STR=("${UART_MODE_STR1[@]}")
                if [[ $TARGET_UART_PORT -ge 10 ]] && [[ $TARGET_UART_PORT -le 13 ]]; then
                        UART_MODULE_GPIOCHIP_NAME=$(format_as_i2c_directory_name ${ft260_module_num_array[1]} ${UART_MODULE_B_CHIP_ADDRESS0})
                elif [[ $TARGET_UART_PORT -ge 14 ]] && [[ $TARGET_UART_PORT -le 17 ]]; then
                        UART_MODULE_GPIOCHIP_NAME=$(format_as_i2c_directory_name ${ft260_module_num_array[1]} ${UART_MODULE_B_CHIP_ADDRESS1})
                fi
        fi

}

function DA682C::get_uart_mode() {
        get_uart_mode_it87_and_pca953x "$@"
}

function DA682C::set_uart_mode() {
        set_uart_mode_it87_and_pca953x "$@"
}

function DA681C::profile() {
        UART_GPIO_TBL_LIBGPIOD_PORT0=(0 1 2 3)
        UART_GPIO_TBL_LIBGPIOD_PORT1=(4 5 6 7)
        UART_GPIO_TBL_LIBGPIOD_PORT2=(8 9 10 11)
        UART_GPIO_TBL_LIBGPIOD_PORT3=(12 13 14 15)
        UART_GPIO_TBL_LIBGPIOD_PORT4=(0 1 2 3)
        UART_GPIO_TBL_LIBGPIOD_PORT5=(4 5 6 7)
        UART_GPIO_TBL_LIBGPIOD_PORT6=(8 9 10 11)
        UART_GPIO_TBL_LIBGPIOD_PORT7=(12 13 14 15)
        UART_GPIO_TBL_LIBGPIOD_PORT8=(0 1 2 3)
        UART_GPIO_TBL_LIBGPIOD_PORT9=(4 5 6 7)
        UART_GPIO_TBL_LIBGPIOD_PORT10=(8 9 10 11)
        UART_GPIO_TBL_LIBGPIOD_PORT11=(12 13 14 15)
        UART_GPIO_TBL_SYSFS_PORT0=(32 33 34 35)
        UART_GPIO_TBL_SYSFS_PORT1=(36 37 38 39)
        UART_GPIO_TBL_SYSFS_PORT2=(40 41 42 43)
        UART_GPIO_TBL_SYSFS_PORT3=(44 45 46 47)
        UART_GPIO_TBL_SYSFS_PORT4=(16 17 18 19)
        UART_GPIO_TBL_SYSFS_PORT5=(20 21 22 23)
        UART_GPIO_TBL_SYSFS_PORT6=(24 25 26 27)
        UART_GPIO_TBL_SYSFS_PORT7=(28 29 30 31)
        UART_GPIO_TBL_SYSFS_PORT8=(0 1 2 3)
        UART_GPIO_TBL_SYSFS_PORT9=(4 5 6 7)
        UART_GPIO_TBL_SYSFS_PORT10=(8 9 10 11)
        UART_GPIO_TBL_SYSFS_PORT11=(12 13 14 15)
        NUM_OF_UART=12
        UART_CHIP_ADDRESS0="0x20"
        UART_CHIP_ADDRESS1="0x21"
        UART_CHIP_ADDRESS2="0x22"
        UART_CHIP_ADDRESS=""

        UART_MODE_TBL=""
        UART_GPIO_VAL_TBL_MODE0=(1 1 0 0)
        UART_GPIO_VAL_TBL_MODE1=(0 0 0 1)
        UART_GPIO_VAL_TBL_MODE2=(0 0 1 0)
        UART_GPIO_VAL_TBL_MODE3=(0 0 1 0)

        UART_MODE_STR=""
        UART_MODE_STR1=("RS-232" "RS-485-2W" "RS-422/RS-485-4W" "RS-422/RS-485-4W")
}

function DA681C::init() {
        local ft260_module_num_str=$(get_i2c_device_minor_number_list "FT260")
        local ft260_module_num_array=($ft260_module_num_str)
        local ft260_module_num=${#ft260_module_num_array[@]}

        local ret=0

        ret=$(bind_i2c_driver "FT260" "pca9535" $UART_CHIP_ADDRESS0 $UART_CHIP_ADDRESS1 $UART_CHIP_ADDRESS2)
        if [[ $ret -ne 0 ]]; then
                echo "Bind i2c device fail"
                exit $ret
        fi

        # Determine uart port and uart mode table
        UART_PORT_TBL="UART_GPIO_TBL_PORT${TARGET_UART_PORT}[@]"
        if [[ "${OS_ID}" == "centos" ]]; then
                UART_PORT_TBL="UART_GPIO_TBL_SYSFS_PORT${TARGET_UART_PORT}[@]"
        else
                UART_PORT_TBL="UART_GPIO_TBL_LIBGPIOD_PORT${TARGET_UART_PORT}[@]"
        fi
        UART_PORT_TBL=("${!UART_PORT_TBL}")
        UART_MODE_TBL="UART_GPIO_VAL_TBL_MODE${TARGET_UART_MODE}[@]"
        UART_MODE_TBL=("${!UART_MODE_TBL}")
        UART_MODE_STR=("${UART_MODE_STR1[@]}")
        if [[ $TARGET_UART_PORT -ge 0 ]] && [[ $TARGET_UART_PORT -le 3 ]]; then
                UART_MODULE_GPIOCHIP_NAME=$(format_as_i2c_directory_name ${ft260_module_num_array[1]} ${UART_CHIP_ADDRESS0})
        elif [[ $TARGET_UART_PORT -ge 4 ]] && [[ $TARGET_UART_PORT -le 7 ]]; then
                UART_MODULE_GPIOCHIP_NAME=$(format_as_i2c_directory_name ${ft260_module_num_array[1]} ${UART_CHIP_ADDRESS1})
        elif [[ $TARGET_UART_PORT -ge 8 ]] && [[ $TARGET_UART_PORT -le 11 ]]; then
                UART_MODULE_GPIOCHIP_NAME=$(format_as_i2c_directory_name ${ft260_module_num_array[1]} ${UART_CHIP_ADDRESS2})
        fi
}

function DA681C::get_uart_mode() {
        get_uart_mode_pca953x $UART_MODULE_GPIOCHIP_NAME
}

function DA681C::set_uart_mode() {
        set_uart_mode_pca953x $UART_MODULE_GPIOCHIP_NAME
}

function get_uart_mode_it87_and_mxuport() {
        local port

        port=${1}

        if [[ $port -ge 0 ]] && [[ $port -le 1 ]]; then
                get_uart_mode_it87
        elif [[ $port -ge 2 ]] && [[ $port -le $NUM_OF_UART ]]; then
                port=$((port -= NUM_OF_IT87_UART))
                get_uart_mode_mxuport $port
        fi
}

function get_uart_mode_it87_and_pca953x() {
        local port

        port=${1}

        if [[ $port -ge 0 ]] && [[ $port -le 1 ]]; then
                get_uart_mode_it87
        elif [[ $port -ge 2 ]] && [[ $port -le $NUM_OF_UART ]]; then
                get_uart_mode_pca953x $UART_MODULE_GPIOCHIP_NAME
        fi
}

function set_uart_mode_it87_and_mxuport() {
        local port
        local mode

        port=${1}
        mode=${2}

        if [[ $port -ge 0 ]] && [[ $port -lt $NUM_OF_IT87_UART ]]; then
                set_uart_mode_it87
        elif [[ $port -ge $NUM_OF_IT87_UART ]] && [[ $port -le $NUM_OF_UART ]]; then
                port=$((port -= NUM_OF_IT87_UART))
                set_uart_mode_mxuport $port $mode
        fi
}

function set_uart_mode_it87_and_pca953x() {
        local port
        local mode

        port=${1}
        mode=${2}

        if [[ $port -ge 0 ]] && [[ $port -lt $NUM_OF_IT87_UART ]]; then
                set_uart_mode_it87
        elif [[ $port -ge $NUM_OF_IT87_UART ]] && [[ $port -le $NUM_OF_UART ]]; then
                port=$((port -= NUM_OF_IT87_UART))
                set_uart_mode_pca953x $UART_MODULE_GPIOCHIP_NAME
        fi
}

function get_uart_mode_it87() {
        if [[ "${OS_ID}" == "centos" ]]; then
                get_uart_mode_it87_via_sysfs
        else
                get_uart_mode_it87_via_libgpiod
        fi
}

function get_uart_mode_pca953x() {
        UART_MODULE_GPIOCHIP_NAME=$1
        if [[ "${OS_ID}" == "centos" ]]; then
                get_uart_mode_pca953x_via_sysfs
        else
                get_uart_mode_pca953x_via_libgpiod $UART_MODULE_GPIOCHIP_NAME
        fi
}

function get_uart_mode_mxuport() {
        local port

        port=${1}

        if ! is_module_loaded mxuport; then
                echo "mxuport driver is not loaded"
                exit 1
        fi

        get_uart_mode_via_setserial $port
}

function get_uart_mode_mxu11x0() {
        local port

        port=${1}

        if ! is_module_loaded mxu11x0; then
                echo "mxu11x0 driver is not loaded"
                exit 1
        fi

        get_uart_mode_via_setserial $port
}

function set_uart_mode_it87() {
        if [[ "${OS_ID}" == "centos" ]]; then
                set_uart_mode_it87_via_sysfs
        else
                set_uart_mode_it87_via_libgpiod
        fi
}

function set_uart_mode_pca953x() {
        UART_MODULE_GPIOCHIP_NAME=$1
        if [[ "${OS_ID}" == "centos" ]]; then
                set_uart_mode_pca953x_via_sysfs
        else
                set_uart_mode_pca953x_via_libgpiod $UART_MODULE_GPIOCHIP_NAME
        fi
}

function set_uart_mode_mxuport() {
        local port
        local mode

        port=${1}
        mode=${2}

        if ! is_module_loaded mxuport; then
                echo "mxuport driver is not loaded"
                exit 1
        fi

        set_uart_mode_via_setserial $port $mode
}

function set_uart_mode_mxu11x0() {
        local port
        local mode

        port=${1}
        mode=${2}

        if ! is_module_loaded mxu11x0; then
                echo "mxuport driver is not loaded"
                exit 1
        fi

        set_uart_mode_via_setserial $port $mode
}

function get_uart_mode_it87_via_sysfs() {
        local sio_gpio_pins
        local sio_values
        local mode_value_tbl
        local ret

        ret=0

        if ! is_module_loaded it87_serial; then
                echo "it87_serial driver is not loaded"
                exit 1
        fi

        sio_gpio_pins[0]=$(gpc_it8786 ${UART_PORT_TBL[0]})
        [[ $? -ne 0 ]] && ret=1
        sio_gpio_pins[1]=$(gpc_it8786 ${UART_PORT_TBL[1]})
        [[ $? -ne 0 ]] && ret=1
        sio_gpio_pins[2]=$(gpc_it8786 ${UART_PORT_TBL[2]})
        [[ $? -ne 0 ]] && ret=1

        if [[ $ret -ne 0 ]]; then
                echo "Get Mode Failed"
                exit $ret
        fi

        sio_values[0]=$(gpio_get_value_sysfs ${sio_gpio_pins[0]})
        [[ $? -ne 0 ]] && ret=2
        sio_values[1]=$(gpio_get_value_sysfs ${sio_gpio_pins[1]})
        [[ $? -ne 0 ]] && ret=2
        sio_values[2]=$(gpio_get_value_sysfs ${sio_gpio_pins[2]})
        [[ $? -ne 0 ]] && ret=2
        sio_values[3]=$(cat /sys/class/misc/it87_serial/serial${UART_PORT_TBL[3]}/serial${UART_PORT_TBL[3]}_rs485 2>/dev/null)
        [[ $? -ne 0 ]] && ret=2

        if [[ $ret -ne 0 ]]; then
                echo "Get Mode Failed"
                exit $ret
        fi

        for ((i = 0; i < $NUM_OF_UART_MODE; ++i)); do
                mode_value_tbl="UART_IT87_GPIO_VAL_TBL_MODE${i}[@]"
                mode_value_tbl=("${!mode_value_tbl}")
                if [[ "${sio_values[*]}" == "${mode_value_tbl[*]}" ]]; then
                        echo "Current uart mode is ${UART_MODE_STR[$i]} interface."
                        return 0
                fi
        done

        echo "Unknown Mode"
        return 1
}

function get_uart_mode_it87_via_libgpiod() {
        local gpc_name
        local sio_gpio_pins
        local sio_values
        local mode_value_tbl
        local ret

        ret=0

        if ! is_module_loaded gpio_it87; then
                echo "gpio_it87 driver is not loaded"
                exit 1
        fi

        if ! is_module_loaded it87_serial; then
                echo "it87_serial driver is not loaded"
                exit 1
        fi

        gpc_name=$(gpio_get_gpiochip_name gpio_it87)

        sio_gpio_pins=(
                $(gpc_it8786_remap ${UART_PORT_TBL[0]})
                $(gpc_it8786_remap ${UART_PORT_TBL[1]})
                $(gpc_it8786_remap ${UART_PORT_TBL[2]})
        )

        sio_values[0]=$(gpio_get_value_libgpiod ${sio_gpio_pins[0]} $gpc_name)
        [[ $? -ne 0 ]] && ret=1
        sio_values[1]=$(gpio_get_value_libgpiod ${sio_gpio_pins[1]} $gpc_name)
        [[ $? -ne 0 ]] && ret=1
        sio_values[2]=$(gpio_get_value_libgpiod ${sio_gpio_pins[2]} $gpc_name)
        [[ $? -ne 0 ]] && ret=1
        sio_values[3]=$(cat /sys/class/misc/it87_serial/serial${UART_PORT_TBL[3]}/serial${UART_PORT_TBL[3]}_rs485 2>/dev/null)
        [[ $? -ne 0 ]] && ret=1

        if [[ $ret -ne 0 ]]; then
                echo "Get Mode Failed"
                exit $ret
        fi

        for ((i = 0; i < $NUM_OF_UART_MODE; ++i)); do
                mode_value_tbl="UART_IT87_GPIO_VAL_TBL_MODE${i}[@]"
                mode_value_tbl=("${!mode_value_tbl}")
                if [[ "${sio_values[*]}" == "${mode_value_tbl[*]}" ]]; then
                        echo "Current uart mode is ${UART_MODE_STR[$i]} interface."
                        return 0
                fi
        done

        echo "Unknown Mode"
        return 1
}

function get_uart_mode_pca953x_via_sysfs() {
        local sio_gpio_pins
        local sio_values
        local mode_value_tbl
        local ret

        ret=0

        sio_gpio_pins[0]=$(gpc_pca953x ${UART_PORT_TBL[0]})
        [[ $? -ne 0 ]] && ret=1
        sio_gpio_pins[1]=$(gpc_pca953x ${UART_PORT_TBL[1]})
        [[ $? -ne 0 ]] && ret=1
        sio_gpio_pins[2]=$(gpc_pca953x ${UART_PORT_TBL[2]})
        [[ $? -ne 0 ]] && ret=1
        sio_gpio_pins[3]=$(gpc_pca953x ${UART_PORT_TBL[3]})
        [[ $? -ne 0 ]] && ret=1

        if [[ $ret -ne 0 ]]; then
                echo "Get Mode Failed"
                exit $ret
        fi

        sio_values[0]=$(gpio_get_value_sysfs ${sio_gpio_pins[0]})
        [[ $? -ne 0 ]] && ret=2
        sio_values[1]=$(gpio_get_value_sysfs ${sio_gpio_pins[1]})
        [[ $? -ne 0 ]] && ret=2
        sio_values[2]=$(gpio_get_value_sysfs ${sio_gpio_pins[2]})
        [[ $? -ne 0 ]] && ret=2
        sio_values[3]=$(gpio_get_value_sysfs ${sio_gpio_pins[3]})
        [[ $? -ne 0 ]] && ret=2

        if [[ $ret -ne 0 ]]; then
                echo "Get Mode Failed"
                exit $ret
        fi

        for ((i = 0; i < $NUM_OF_UART_MODE; ++i)); do
                mode_value_tbl="UART_GPIO_VAL_TBL_MODE${i}[@]"
                mode_value_tbl=("${!mode_value_tbl}")
                if [[ "${sio_values[*]}" == "${mode_value_tbl[*]}" ]]; then
                        echo "Current uart mode is ${UART_MODE_STR[$i]} interface."
                        return 0
                fi
        done

        echo "Unknown Mode"
        return 1
}

function get_uart_mode_pca953x_via_libgpiod() {
	local gpc_name
        local sio_gpio_pins
        local sio_values
        local mode_value_tbl
        local ret

        ret=0

	gpiochip_name=$1
	gpc_name=$(gpio_get_gpiochip_name $gpiochip_name)

        sio_gpio_pins=(
                ${UART_PORT_TBL[0]}
                ${UART_PORT_TBL[1]}
                ${UART_PORT_TBL[2]}
		${UART_PORT_TBL[3]}
        )

        sio_values[0]=$(gpio_get_value_libgpiod ${sio_gpio_pins[0]} $gpc_name)
        [[ $? -ne 0 ]] && ret=1
        sio_values[1]=$(gpio_get_value_libgpiod ${sio_gpio_pins[1]} $gpc_name)
        [[ $? -ne 0 ]] && ret=1
        sio_values[2]=$(gpio_get_value_libgpiod ${sio_gpio_pins[2]} $gpc_name)
        [[ $? -ne 0 ]] && ret=1
        sio_values[3]=$(gpio_get_value_libgpiod ${sio_gpio_pins[3]} $gpc_name)
        [[ $? -ne 0 ]] && ret=1

        if [[ $ret -ne 0 ]]; then
                echo "Get Mode Failed"
                exit $ret
        fi

        for ((i = 0; i < $NUM_OF_UART_MODE; ++i)); do
                mode_value_tbl="UART_GPIO_VAL_TBL_MODE${i}[@]"
                mode_value_tbl=("${!mode_value_tbl}")
                if [[ "${sio_values[*]}" == "${mode_value_tbl[*]}" ]]; then
                        echo "Current uart mode is ${UART_MODE_STR[$i]} interface."
                        return 0
                fi
        done

        echo "Unknown Mode"
        return 1
}

function get_uart_mode_via_setserial() {
        local port
        local port_name
        local pattern
        local mode_value_tbl
        local ret

        ret=0

        if [[ ! -e "$SETSETIAL" ]]; then
                echo "setserial is not installed"
                exit 1
        fi

        port=${1}
        port_name=${UART_PORT_TBL[$port]}
        pattern='port (0x[0-9]+)'
        result=$($SETSETIAL -G "/dev/$port_name")
        [[ $? -ne 0 ]] && ret=1

        if [[ $ret -ne 0 ]]; then
                echo "Get Mode Failed"
                exit $ret
        fi

        if [[ "$result" =~ $pattern ]]; then
                for ((i = 0; i < $NUM_OF_UART_MODE; ++i)); do
                        if [[ "${BASH_REMATCH[1]}" == "${UART_MODE_TBL[$i]}" ]]; then
                                echo "Current uart mode is ${UART_MODE_STR[$i]} interface."
                                return 0
                        fi
                done
        fi

        echo "Unknown"
        return 1
}

function set_uart_mode_it87_via_sysfs() {
        local sio_pins
        local sio_values
        local ret

        ret=0

        sio_pins[0]=$(gpc_it8786 ${UART_PORT_TBL[0]})
        [[ $? -ne 0 ]] && ret=1
        sio_pins[1]=$(gpc_it8786 ${UART_PORT_TBL[1]})
        [[ $? -ne 0 ]] && ret=1
        sio_pins[2]=$(gpc_it8786 ${UART_PORT_TBL[2]})
        [[ $? -ne 0 ]] && ret=1
        sio_pins[3]="/sys/class/misc/it87_serial/serial${UART_PORT_TBL[3]}/serial${UART_PORT_TBL[3]}_rs485"

        if [[ $ret -ne 0 ]]; then
                echo "Set Mode Failed"
                exit $ret
        fi

        gpio_set_value_sysfs ${sio_pins[0]} ${UART_MODE_TBL[0]}
        [[ $? -ne 0 ]] && ret=2
        gpio_set_value_sysfs ${sio_pins[1]} ${UART_MODE_TBL[1]}
        [[ $? -ne 0 ]] && ret=2
        gpio_set_value_sysfs ${sio_pins[2]} ${UART_MODE_TBL[2]}
        [[ $? -ne 0 ]] && ret=2
        echo "${UART_MODE_TBL[3]}" 2>/dev/null >"${sio_pins[3]}"
        [[ $? -ne 0 ]] && ret=2

        if [[ $ret -ne 0 ]]; then
                echo "Set Mode Failed"
                exit $ret
        fi

        echo "Set OK."
        echo "Current uart mode is ${UART_MODE_STR[$TARGET_UART_MODE]} interface."
}

function set_uart_mode_it87_via_libgpiod() {
        local gpc_name
        local sio_pins
        local sio_values
        local ret

        ret=0

        if ! is_module_loaded gpio_it87; then
                echo "gpio_it87 driver is not loaded"
                exit 1
        fi

        if ! is_module_loaded it87_serial; then
                echo "it87_serial driver is not loaded"
                exit 1
        fi

        sio_pins=(
                $(gpc_it8786_remap ${UART_PORT_TBL[0]})
                $(gpc_it8786_remap ${UART_PORT_TBL[1]})
                $(gpc_it8786_remap ${UART_PORT_TBL[2]})
                "/sys/class/misc/it87_serial/serial${UART_PORT_TBL[3]}/serial${UART_PORT_TBL[3]}_rs485"
        )

        gpc_name=$(gpio_get_gpiochip_name gpio_it87)
        [[ $? -ne 0 ]] && ret=1
        gpio_set_value_libgpiod ${sio_pins[0]} ${UART_MODE_TBL[0]} $gpc_name
        [[ $? -ne 0 ]] && ret=1
        gpio_set_value_libgpiod ${sio_pins[1]} ${UART_MODE_TBL[1]} $gpc_name
        [[ $? -ne 0 ]] && ret=1
        gpio_set_value_libgpiod ${sio_pins[2]} ${UART_MODE_TBL[2]} $gpc_name
        [[ $? -ne 0 ]] && ret=1
        echo "${UART_MODE_TBL[3]}" 2>/dev/null >"${sio_pins[3]}"
        [[ $? -ne 0 ]] && ret=1

        if [[ $ret -ne 0 ]]; then
                echo "Set Mode Failed"
                exit $ret
        fi

        echo "Set OK."
        echo "Current uart mode is ${UART_MODE_STR[$TARGET_UART_MODE]} interface."
}

function set_uart_mode_pca953x_via_sysfs() {
        local sio_pins
        local sio_values
        local ret

        ret=0

        sio_pins[0]=$(gpc_pca953x ${UART_PORT_TBL[0]})
        [[ $? -ne 0 ]] && ret=1
        sio_pins[1]=$(gpc_pca953x ${UART_PORT_TBL[1]})
        [[ $? -ne 0 ]] && ret=1
        sio_pins[2]=$(gpc_pca953x ${UART_PORT_TBL[2]})
        [[ $? -ne 0 ]] && ret=1
        sio_pins[3]=$(gpc_pca953x ${UART_PORT_TBL[3]})
        [[ $? -ne 0 ]] && ret=1

        if [[ $ret -ne 0 ]]; then
                echo "Set Mode Failed"
                exit $ret
        fi

        gpio_set_value_sysfs ${sio_pins[0]} ${UART_MODE_TBL[0]}
        [[ $? -ne 0 ]] && ret=2
        gpio_set_value_sysfs ${sio_pins[1]} ${UART_MODE_TBL[1]}
        [[ $? -ne 0 ]] && ret=2
        gpio_set_value_sysfs ${sio_pins[2]} ${UART_MODE_TBL[2]}
        [[ $? -ne 0 ]] && ret=2
        gpio_set_value_sysfs ${sio_pins[3]} ${UART_MODE_TBL[3]}
        [[ $? -ne 0 ]] && ret=2

        if [[ $ret -ne 0 ]]; then
                echo "Set Mode Failed"
                exit $ret
        fi

        echo "Set OK."
        echo "Current uart mode is ${UART_MODE_STR[$TARGET_UART_MODE]} interface."
}

function set_uart_mode_pca953x_via_libgpiod() {
	local gpc_name
        local sio_pins
        local sio_values
        local ret

        ret=0

	gpiochip_name=$1
	gpc_name=$(gpio_get_gpiochip_name $gpiochip_name)

        sio_pins=(
                ${UART_PORT_TBL[0]}
                ${UART_PORT_TBL[1]}
                ${UART_PORT_TBL[2]}
		${UART_PORT_TBL[3]}
        )

        [[ $? -ne 0 ]] && ret=1
        gpio_set_value_libgpiod ${sio_pins[0]} ${UART_MODE_TBL[0]} $gpc_name
        [[ $? -ne 0 ]] && ret=1
        gpio_set_value_libgpiod ${sio_pins[1]} ${UART_MODE_TBL[1]} $gpc_name
        [[ $? -ne 0 ]] && ret=1
        gpio_set_value_libgpiod ${sio_pins[2]} ${UART_MODE_TBL[2]} $gpc_name
        [[ $? -ne 0 ]] && ret=1
        gpio_set_value_libgpiod ${sio_pins[3]} ${UART_MODE_TBL[3]} $gpc_name
        [[ $? -ne 0 ]] && ret=1

        if [[ $ret -ne 0 ]]; then
                echo "Set Mode Failed"
                exit $ret
        fi

        echo "Set OK."
        echo "Current uart mode is ${UART_MODE_STR[$TARGET_UART_MODE]} interface."
}

function set_uart_mode_via_setserial() {
        local port
        local port_name
        local mode
        local ret

        ret=0

        if [[ ! -e "$SETSETIAL" ]]; then
                echo "setserial is not installed"
                exit 1
        fi

        port=${1}
        port_name=${UART_PORT_TBL[$port]}
        mode=${2}

        $SETSETIAL "/dev/$port_name" port "${UART_MODE_TBL[$mode]}" >/dev/null 2>&1
        [[ $? -ne 0 ]] && ret=1

        if [[ $ret -ne 0 ]]; then
                echo "Get Mode Failed"
                exit $ret
        fi

        echo "Set OK."
        echo "Current uart mode is ${UART_MODE_STR[$TARGET_UART_MODE]} interface."
}

function load_model_name() {
        for name in $(get_model_name_from_dmi_type12); do
                if [[ "$(type -t "${name}::profile")" = 'function' ]]; then
                        MODEL_NAME="${name}"
                        break
                fi
        done

        if [[ -z "${MODEL_NAME}" ]]; then
                for name in $(get_model_name_from_dmi_type1); do
                        if [[ "$(type -t "${name}::profile")" = 'function' ]]; then
                                MODEL_NAME="${name}"
                                break
                        fi
                done
        fi

        if [[ -z "${MODEL_NAME}" ]]; then
                echo "Unsupported model"
                exit 38
        fi
}

function script_usage() {
        cat <<EOF
USAGE:
	mx-uart-ctl -p <port> [-m <mode>]

OPTIONS:
	-p <port>
		(Required) Determine uart port. Without option '-m', it will get uart mode

	-m <uart_mode>
                (Optional) Set uart mode
			0: RS-232
			1: RS-485-2W
			2: RS-422
                        3: RS-485-4W

EXAMPLE:
	Get port 0 mode
	mx-uart-ctl -p 0

	Set port 1 to mode RS-232
	mx-uart-ctl -p 1 -m 0

EOF
}

function script_params() {
        if [[ $# -eq 0 ]]; then
                script_usage
                exit 1
        fi

        while getopts "hp:m:" opt; do
                case "${opt}" in
                p)
                        TARGET_UART_PORT="$OPTARG"
                        TARGET_OPCODE=$((TARGET_OPCODE += 1))
                        ;;

                m)
                        TARGET_UART_MODE="$OPTARG"
                        TARGET_OPCODE=$((TARGET_OPCODE += 2))
                        ;;
                h)
                        script_usage
                        exit 0
                        ;;
                \?)
                        script_usage
                        exit 22
                        ;;
                :)
                        echo "Option -$OPTARG requires an argument." >&2
                        script_usage
                        exit 22
                        ;;
                esac
        done
}

function script_init() {
        load_model_name

        if [[ ! $(type -t "${MODEL_NAME}"::profile) == function ]]; then
                echo "${MODEL_NAME} profile function is not define"
                exit 1
        fi

        "${MODEL_NAME}"::profile

        if [[ ! $(type -t "${MODEL_NAME}"::init) == function ]]; then
                echo "${MODEL_NAME} init function is not define"
                exit 1
        fi

        "${MODEL_NAME}"::init
}

function verify_uart_port() {
        if ! check_leading_zero_digit $TARGET_UART_PORT; then
                echo "Invaild serial port format."
                exit 1
        fi

        if [[ $TARGET_UART_PORT -lt 0 || $TARGET_UART_PORT -ge $NUM_OF_UART ]]; then
                echo "Invalid serial port."
                exit 1
        fi
}

function verift_uart_mode() {
        if ! check_leading_zero_digit $TARGET_UART_MODE; then
                echo "Invalid UART mode format."
                exit 1
        fi

        if [[ $TARGET_UART_MODE -lt 0 || $TARGET_UART_MODE -ge $NUM_OF_UART_MODE ]]; then
                echo "Invalid UART mode."
                exit 1
        fi
}

function main() {
        script_params "$@"
        script_init

        verify_uart_port

        case $TARGET_OPCODE in
        $TARGET_GET_MODE_OPCODE)
                if [[ ! $(type -t "${MODEL_NAME}"::get_uart_mode) == function ]]; then
                        echo "${MODEL_NAME} get_uart_mode function is not define"
                        exit 1
                fi

                "${MODEL_NAME}"::get_uart_mode $TARGET_UART_PORT
                ;;
        $TARGET_SET_MODE_OPCODE)
                verift_uart_mode

                if [[ ! $(type -t "${MODEL_NAME}"::set_uart_mode) == function ]]; then
                        echo "${MODEL_NAME} set_uart_mode function is not define"
                        exit 1
                fi

                "${MODEL_NAME}"::set_uart_mode $TARGET_UART_PORT $TARGET_UART_MODE
                ;;
        $TARGET_INVALID_OPCODE)
                echo "Require -p argument for port number"
                script_usage
                exit 1
                ;;
        *)
                script_usage
                exit 1
                ;;
        esac

        exit 0
}

main $@
