[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/connectivity/bt_others/boots/boots.c b/src/connectivity/bt_others/boots/boots.c
new file mode 100644
index 0000000..ac68a3b
--- /dev/null
+++ b/src/connectivity/bt_others/boots/boots.c
@@ -0,0 +1,874 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2016~2017. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+//- vim: set ts=4 sts=4 sw=4 et: --------------------------------------------
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "boots.h"
+#include "boots_skt.h"
+#include "boots_uart.h"
+#include "boots_eth.h"
+#include "boots_pkt.h"
+#include "boots_stress.h"
+#include "boots_country.h"
+#include "boots_osi.h"
+
+//---------------------------------------------------------------------------
+#define LOG_TAG "boots"
+
+//---------------------------------------------------------------------------
+static boots_if_s boots_if;
+static uint8_t boots_local_exe;
+int boots_loop_timer;
+rssi_set_s rssi_setting;
+
+//---------------------------------------------------------------------------
+static void boots_chk_if(int argc, char **argv)
+{
+    // Please follow the boots_if_e
+    char *c_inf[] = {"None", "stpbt", "hci", "All", "Socket", "UART", "Ethernet",
+        "User", "Tester_UART"};
+    int i = 0;
+#ifdef BOOTS_VERBOSE_MSG
+    BPRINT_D("%s: argc = %d", __func__, argc);
+    for (i = 0; i < argc; i++)
+        BPRINT_D("argv[%d]:%s", i, argv[i]);
+    i = 0;
+#endif
+
+#if 0
+    if (*argv[0] == '-') {
+        if (memcmp(argv[0], "-relay", strlen("-relay"))) {
+            boots_if.clif = BOOTS_CLIF_USER;
+            boots_if.csif = BOOTS_CSIF_SKT;
+        } else if (argc >= 2) {
+            // boots_srv as relayer in PC/NB
+            boots_if.csif = BOOTS_CSIF_UART;
+            if (argc == 2)
+                snprintf(boots_if.cs, sizeof(boots_if.cs), "%s", argv[1]);
+            else if (argc >= 3)
+                snprintf(boots_if.cs, sizeof(boots_if.cs), "%s %s", argv[1], argv[2]);
+            goto exit;
+        }
+    } else if (!memcmp(argv[0], "tty", strlen("tty"))) {
+        boots_if.csif = BOOTS_CSIF_UART;
+        snprintf(boots_if.cs, sizeof(boots_if.cs), "/dev/%s", argv[0]);
+    } else if (!memcmp(argv[0], "eth", strlen("eth"))) {
+        boots_if.csif = BOOTS_CSIF_ETH;
+        memcpy(boots_if.cs, argv[1], strlen(argv[1]));
+    }
+
+    if (argc > 2 && !memcmp(argv[1], "-relay", strlen("-relay"))) {
+        boots_if.clif = BOOTS_CLIF_UART;
+        snprintf(boots_if.cli, sizeof(boots_if.cli), "/dev/%s", argv[2]);
+    } else {
+        boots_if.clif = BOOTS_CLIF_USER;
+    }
+#else
+    while (i < argc) {
+        // check interface for BT side
+        if (!memcmp(argv[i], "tty", strlen("tty"))) {
+            if (i + 1 < argc) {
+                boots_if.csif = BOOTS_CSIF_UART;
+                if (memcmp(argv[i], "/dev/", strlen("/dev/")))
+                    snprintf(boots_if.cs, sizeof(boots_if.cs), "/dev/%s", argv[i]);
+                boots_if.cs_speed = strtol(argv[i + 1], NULL, 10);
+                BPRINT_D("cs_speed: %d", boots_if.cs_speed);
+                i += 2;
+            } else {
+                BPRINT_E("Lack a parameter for %s", argv[i]);
+                return;
+            }
+        } else if (!memcmp(argv[i], "eth", strlen("eth"))) {
+            boots_if.csif = BOOTS_CSIF_ETH;
+            long cp_len = strlen(argv[i + 1]) > sizeof(boots_if.cs) ? sizeof(boots_if.cs) : strlen(argv[i + 1]);
+            memcpy(boots_if.cs, argv[i + 1], cp_len);
+            i += 2;
+        } else if (!memcmp(argv[i], "-relay", strlen("-relay"))) {
+            if (boots_if.csif == BOOTS_IF_NONE) {
+                // boots_srv as relayer in PC/NB
+                if (i + 2 < argc && strtol(argv[i + 2], NULL, 10) != 0) {
+                    snprintf(boots_if.cs, sizeof(boots_if.cs), "%s %s", argv[i + 1], argv[i + 2]);
+                    i += 2;
+                } else if (i + 1 < argc) {
+                    snprintf(boots_if.cs, sizeof(boots_if.cs), "%s", argv[i + 1]);
+                    i++;
+                } else {
+                    BPRINT_E("Lack a parameter for %s", argv[i]);
+                    return;
+                }
+                boots_if.csif = BOOTS_CSIF_UART;
+            } else {
+                // boots CLI
+                if (i + 2 < argc && !memcmp(argv[i + 1], "tty", strlen("tty"))
+                        && strtol(argv[i + 2], NULL, 10) != 0) {
+                    snprintf(boots_if.cli, sizeof(boots_if.cli), "/dev/%s", argv[i + 1]);
+                    boots_if.cli_speed = strtol(argv[i + 2], NULL, 10);
+                    boots_if.clif = BOOTS_CLIF_UART;
+                    i += 2;
+                } else {
+                    BPRINT_E("Incorrect argument for %s", argv[i]);
+                    return;
+                }
+            }
+        } else if (*argv[i] == '-') {
+            boots_if.clif = BOOTS_CLIF_USER;
+            i++;
+        } else {
+            i++;
+        }
+    }
+
+    if (boots_if.csif == BOOTS_IF_NONE) {
+        boots_if.csif = BOOTS_CSIF_SKT;
+        boots_if.clif = BOOTS_CLIF_USER;
+    }
+#endif
+    BPRINT_D("cs: %s, cs_speed: %d", boots_if.cs, boots_if.cs_speed);
+    BPRINT_I("%s(%d) <-> %s(%d) <-> server", c_inf[boots_if.clif],
+            boots_if.clif, c_inf[boots_if.csif], boots_if.csif);
+}
+
+//---------------------------------------------------------------------------
+static char *boots_chk_btif(char *interface)
+{
+#define BOOTS_SRV_LOCAL "./boots_srv "
+#define BOOTS_SRV       "boots_srv "
+#define BOOTS_AND       " &"
+
+#define BTPROTO_HCI 1
+
+    int i = 0;
+    static char server[64] = {0};
+
+    if (*interface == '-') {    // no assign btif or clif
+        // do auto detect
+        BPRINT_D("%s: DO auto detect", __func__);
+        if (access(boots_btif[0].p, R_OK) == 0) {
+            // STPBT
+            i = 0;
+            boots_if.btif = BOOTS_BTIF_STPBT;
+        } else if ((i = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) != -1) {
+            // HCI
+            BPRINT_D("%s: HCI: %d", __func__, i);
+            close(i);
+            i = 1;
+            boots_if.btif = BOOTS_BTIF_HCI;
+        } else {
+            BPRINT_E("%s: stpbt/HCI are all not exist", __func__);
+            return NULL;
+        }
+    } else {
+        BPRINT_D("%s: btif assigned %s", __func__, interface);
+        while (boots_btif[i].inf) {
+            if (!strcmp(interface, boots_btif[i].n))
+                break;
+            i++;
+        }
+        boots_if.btif = boots_btif[i].inf;
+        if (i + 1 == ARRAY_SIZE(boots_btif)) {
+            BPRINT_E("%s: boots doesn't support \"%s\"", __func__, interface);
+            return NULL;
+        }
+    }
+
+    if (boots_if.clif == BOOTS_IF_NONE && boots_if.csif == BOOTS_CSIF_UART && strlen(boots_if.cs)) {
+        snprintf(server, sizeof(server), boots_local_exe ? BOOTS_SRV_LOCAL "%s %s &" : BOOTS_SRV "%s %s &", boots_if.cs, boots_btif[i].n);
+    } else {
+        snprintf(server, sizeof(server), boots_local_exe ? BOOTS_SRV_LOCAL "%s &" : BOOTS_SRV "%s &", boots_btif[i].n);
+    }
+    BPRINT_D("%s: server: %s", __func__, server);
+    return server;
+}
+
+//---------------------------------------------------------------------------
+static int boots_invoke_boots_srv(char *path)
+{
+    int cont = 0;
+    if (path == NULL) return 0;
+
+    // check boots_srv is running or not
+    if (osi_system("pidof boots_srv > /dev/null") != 0) {
+        if (osi_system(path) == 0) {
+            BPRINT_I("Server(%s) executing...", path);
+            while(access(BOOTS_SRVSK_NAME, F_OK) == -1) {
+                usleep(100 * 1000);
+                cont++;
+                if (cont > 20) {
+                    BPRINT_E("access BOOTS_SRVSK_NAME(%s) failed: %s(%d)", BOOTS_SRVSK_NAME, strerror(errno), errno);
+                    return 0;
+                }
+            }
+        } else {
+            BPRINT_E("***** WARNING: Please input # %s, if boots_srv isn't running *****",
+                    path);
+        }
+    }
+    return 1;
+}
+
+//---------------------------------------------------------------------------
+static int boots_killall_boots_srv(void)
+{
+    int ret = -1;
+
+    ret = osi_system("killall boots_srv > /dev/null");
+    if (ret) {
+        BPRINT_W("*** Please input #killall boots_srv ***");
+        BPRINT_D("%s: kill boots_srv(%d)", __func__, ret);
+    }
+
+    return ret;
+}
+
+//---------------------------------------------------------------------------
+static void boots_sig_handler(int signum)
+{
+    UNUSED(signum);
+    if (BOOTS_STRESS_MEASURE_IN_BOOTS)
+        boots_stress_deinit();
+    exit(0);
+}
+
+//---------------------------------------------------------------------------
+static void boots_tell_socket_end(int fd, struct sockaddr_un *addr)
+{
+    char skend[] = {'s', 'e', 'n', 'd'};
+
+    boots_sk_send(fd, (void *)skend, sizeof(skend), addr, BOOTS_SRVSK_NAME);
+}
+
+static void boots_tell_ethernet_end(int fd, struct sockaddr_in *addr)
+{
+    char skend[] = {'s', 'e', 'n', 'd'};
+    addr->sin_family = AF_INET;
+    addr->sin_port = ETH_UDP_SRV_PORT;
+    addr->sin_addr.s_addr = inet_addr(boots_if.cs);
+    boots_eth_send(fd, (void *)skend, sizeof(skend), addr);
+}
+
+//---------------------------------------------------------------------------
+#define USAGE_DETAILS      (1 << 0)
+#define USAGE_DETAILS_MTK  (1 << 1)
+static void boots_cmd_usage(uint8_t detail)
+{
+    int i = 0;
+    extern boots_cmds_s commands[];
+
+    printf("Boots - MTK Bluetooth Test Suite ver:%s(rev:%s)\n", VERSION, REV);
+    printf("Modular Commands:\n");
+    for (i = 0; commands[i].cmd; i++) {
+        if (commands[i].hidden == false)
+            printf("  "BLUE"%s"NONE" - %s\n", commands[i].cmd, commands[i].comment);
+        else if (detail & USAGE_DETAILS_MTK)
+            printf("  "BLUE"%s"NONE" - %s\n", commands[i].cmd, commands[i].comment);
+
+        if (detail & USAGE_DETAILS && commands[i].details) {
+            if (commands[i].hidden == false)
+                printf("%s\n", commands[i].details);
+            else if (detail & USAGE_DETAILS_MTK)
+                printf("%s\n", commands[i].details);
+        }
+    }
+    printf("For specfic command details use: ./boots -c <CMD> -h\n");
+}
+
+//---------------------------------------------------------------------------
+static void boots_country_cmd_usage(uint8_t detail)
+{
+    int i = 0;
+    extern boots_country_cmds_s country_commands[];
+
+    printf("Boots - MTK Bluetooth Test Suite ver:%s(rev:%s)\n", VERSION, REV);
+    printf("Power Limit Commands:\n");
+    for (i = 0; country_commands[i].cmd; i++) {
+        if (country_commands[i].hidden == false)
+            printf("  "BLUE"%s"NONE" - %s\n", country_commands[i].cmd, country_commands[i].comment);
+        else if (detail & USAGE_DETAILS_MTK)
+            printf("  "BLUE"%s"NONE" - %s\n", country_commands[i].cmd, country_commands[i].comment);
+
+        if (detail & USAGE_DETAILS && country_commands[i].details) {
+            if (country_commands[i].hidden == false)
+                printf("%s\n", country_commands[i].details);
+            else if (detail & USAGE_DETAILS_MTK)
+                printf("%s\n", country_commands[i].details);
+        }
+    }
+    printf("For specfic command details use: ./boots -c <CMD> -h\n");
+}
+
+//---------------------------------------------------------------------------
+static void boots_help(void)
+{
+    printf("Boots - MTK Bluetooth Test Suite ver:%s(rev:%s)\n", VERSION, REV);
+    printf("Usage:\n");
+    printf(BLUE"    boots [BT Interface] <InputMethod/RelayMode> [parameters]\n"NONE);
+    printf("      NOTE: DO NOTE reorder\n");
+    printf("    BT Interface:\n");
+    printf("\tPlease ignore this if not through UART/Ethernet to connect platform(BT)\n");
+    printf("\tttyX      Through UART send to BT\n");
+    printf("\t              ex: ./boots ttyACM0 115200 ...\n");
+    printf("\tethX      Through Ethernet send to BT, need server IP\n");
+    printf("\t              ex: ./boots eth0 10.1.1.1 ...\n");
+    printf("    InputMethod: [parameters]\n");
+    printf("\t-f        File, ex: ./boots -f test.boots\n");
+    printf("\t-r        Raw data, ex: ./boots -r CMD 03 0C 00\n");
+    printf("\t-c        Command, for more command information on the usage of everyone command use:\n");
+    printf("\t              ./boots -c [detail]\n");
+    printf("\t-relay    Through serial port to input\n");
+    printf("\t              ex: ./boots ttyACM0 115200 -relay ttyUSB0 115200\n");
+    printf("\t              ex: ./boots -relay ttyGS2\n");
+    printf("\t              ex: ./boots -relay eth0 10.1.1.1\n");
+    printf("    Others:\n");
+    printf("\tstop      Stop service since boots_srv is running in background\n");
+}
+
+//---------------------------------------------------------------------------
+static ssize_t boots_read(int fd, void *buf, size_t buf_size, int inf)
+{
+    ssize_t ret = 0;
+
+    if (!buf || !buf_size || !inf) {
+        BPRINT_E("%s: Invalid argument(buf: %p, buf size: %d, inf: %d)",
+                __func__, buf, (int)buf_size, inf);
+        return -EINVAL;
+    } else if (fd < 0) {
+        BPRINT_E("%s: Bad file descriptor(%d)", __func__, fd);
+        return -EBADFD;
+    }
+
+    if (inf == BOOTS_CSIF_SKT) {
+        ret = boots_sk_recv(fd, buf, buf_size, 0, NULL, NULL);
+    } else if (inf == BOOTS_CSIF_UART || inf == BOOTS_CLIF_UART) {
+        ret = boots_uart_read(fd, buf, buf_size);
+    } else if (inf == BOOTS_CSIF_ETH) {
+        ret = boots_eth_recv(fd, buf, buf_size, 0);
+    } else {
+        BPRINT_E("%s: Incorrect interface(%d)", __func__, inf);
+    }
+    return ret;
+}
+
+//---------------------------------------------------------------------------
+static ssize_t boots_write(int fd, const void *buf, size_t len, int inf)
+{
+    ssize_t ret = 0;
+
+    if (!buf || !len || !inf) {
+        BPRINT_E("%s: Invalid argument(buf: %p, len: %d, inf: %d)", __func__, buf, (int)len, inf);
+        return -EINVAL;
+    } else if (fd < 0) {
+        BPRINT_E("%s: Bad file descriptor(%d)", __func__, fd);
+        return -EBADFD;
+    }
+
+    if (inf == BOOTS_CSIF_SKT) {
+        ret = boots_sk_send(fd, buf, len, NULL, BOOTS_SRVSK_NAME);
+    } else if (inf == BOOTS_CSIF_UART || inf == BOOTS_CLIF_UART) {
+        ret = boots_uart_write(fd, buf, len);
+    } else if (inf == BOOTS_CSIF_ETH) {
+        struct sockaddr_in sockaddr;
+        sockaddr.sin_family = AF_INET;
+        sockaddr.sin_port = ETH_UDP_SRV_PORT;
+        sockaddr.sin_addr.s_addr = inet_addr(boots_if.cs);
+        ret = boots_eth_send(fd, buf, len, &sockaddr);
+    } else {
+        BPRINT_E("%s: Incorrect interface(%d)", __func__, inf);
+    }
+    return ret;
+}
+
+//---------------------------------------------------------------------------
+void boots_chk_local_exe(char *argv)
+{
+    if (argv == NULL) {
+        BPRINT_E("%s: argv should not NULL", __func__);
+        return;
+    }
+
+    if (*argv == '.' && *(argv + 1) == '/') {
+        boots_local_exe = 1;
+    } else {
+        boots_local_exe = 0;
+    }
+}
+
+//---------------------------------------------------------------------------
+int main(int argc, char *argv[])
+{
+    static pkt_list_s *pkt = NULL;
+    static script_set_s sfile = {NULL, 0, 0, 0, 0};
+    static uint8_t buf[HCI_BUF_SIZE] = {0};
+    static int cont = 0;
+    size_t len = 0;
+    ssize_t read_len = 0;
+    int csw_fd = -1;
+    int csr_fd = -1;
+    int cli_uartfd = -1;
+    int type = 0;
+    struct sockaddr_un skaddr_cli;
+    struct sockaddr_un skaddr_srv;
+    socklen_t sklen_cli = {0};
+    socklen_t sklen_srv = {0};
+    struct sockaddr_in ethaddr_cli;
+    struct sockaddr_in ethaddr_srv;
+    fd_set readfs;
+    struct sigaction sigact;
+    struct timeval time_start;
+    struct timeval time_end;
+    uint32_t diff_time;
+    int which = PRIO_PROCESS;
+    id_t pid;
+    int priority = -20;
+    int ret;
+
+    // Register signal handler
+    sigact.sa_handler = boots_sig_handler;
+    sigact.sa_flags = 0;
+    sigemptyset(&sigact.sa_mask);
+    sigaction(SIGINT, &sigact, NULL);
+    sigaction(SIGTERM, &sigact, NULL);
+    sigaction(SIGQUIT, &sigact, NULL);
+    sigaction(SIGKILL, &sigact, NULL);
+
+    // For root permission
+    CHECK_USERID();
+
+    // Local execute or not
+    boots_chk_local_exe(argv[0]);
+
+    if (argc == 2 && !memcmp("-c", argv[1], strlen("-c"))) {
+        // Print commands
+        boots_cmd_usage(0);
+        exit(0);
+    } else if (argc == 2 && !memcmp("-o", argv[1], strlen("-o"))) {
+        // Print commands
+        boots_country_cmd_usage(0);
+        exit(0);
+    } else if (argc == 3 && !memcmp("-c", argv[1], strlen("-c"))) {
+        if (!memcmp("detail", argv[2], strlen("detail"))) {
+            boots_cmd_usage(1);
+            exit(0);
+        } else if (!memcmp("mtk", argv[2], strlen("mtk"))) {
+            boots_cmd_usage(3);
+            exit(0);
+        } else {
+            // do nothing for command without any parameters.
+        }
+    } else if (argc == 2 && !memcmp("stop", argv[1], strlen("stop"))) {
+        boots_killall_boots_srv();
+        return 0;
+    } else if (argc == 3 && !memcmp("-o", argv[1], strlen("-o"))) {
+        if (!memcmp("detail", argv[2], strlen("detail"))) {
+            boots_country_cmd_usage(1);
+            exit(0);
+        } else if (!memcmp("mtk", argv[2], strlen("mtk"))) {
+            boots_country_cmd_usage(3);
+            exit(0);
+        } else {
+            // do nothing for command without any parameters.
+        }
+    } else if (argc < 3) {
+        // Print help
+        boots_help();
+        exit(0);
+    }
+
+    /** country command set, because it's not related controller operation
+     *    Only access file
+     */
+    if (!memcmp("-o", argv[1], strlen("-o"))) {
+        boots_country_set_handler(argv + 2, argc - 2);
+        goto exit;
+    }
+
+    // Confirm interface between client/server, upper layer
+    boots_chk_if(argc - 1, &argv[1]);
+
+    /** Communication Interface with boots_srv */
+    if (boots_if.csif == BOOTS_CSIF_SKT) {
+        // Check interface is support or not
+        if (!boots_invoke_boots_srv(boots_chk_btif(argv[1])))
+            exit(1);
+
+        // create socket
+        if (boots_sk_create(&csr_fd, &skaddr_cli, &sklen_cli, BOOTS_CLISK_NAME, 0)) {
+            BPRINT_E("Create socket failed");
+            exit(1);
+        }
+
+        // connect socket
+        if (boots_sk_create(&csw_fd, &skaddr_srv, &sklen_srv, BOOTS_SRVSK_NAME, 1)) {
+            BPRINT_E("Connect socket failed");
+            boots_sk_close(&csr_fd);
+            exit(1);
+        }
+
+    } else if (boots_if.csif == BOOTS_CSIF_UART) {
+        if (boots_if.clif == BOOTS_IF_NONE) {
+            // Maybe last time user use command ask BT into DUT mode
+            boots_killall_boots_srv();
+            sleep(1);
+            // means boots_srv as relayer in PC/NB
+            boots_invoke_boots_srv(boots_chk_btif(argv[1]));
+            exit(1);
+
+        } else {
+            // client/server communication interface
+            csw_fd = boots_uart_init(boots_if.cs, boots_if.cs_speed);
+            if (csw_fd < 0) {
+                BPRINT_E("%s: Open serial port:%s failed(%d)!", __func__, boots_if.cs, csw_fd);
+                exit(1);
+            }
+            csr_fd = csw_fd;
+        }
+
+    } else if (boots_if.csif == BOOTS_CSIF_ETH) {
+        // create socket
+        if (boots_eth_create(&csr_fd, &ethaddr_cli, 0)) {
+            BPRINT_E("Create socket failed");
+            exit(1);
+        }
+        // connect socket
+        if (boots_eth_create(&csw_fd, &ethaddr_srv, 1)) {
+            BPRINT_E("Connect socket failed");
+            boots_eth_close(&csr_fd);
+            exit(1);
+        }
+    } else {
+        BPRINT_E("Unknown communication interface");
+        exit(1);
+    }
+
+    /** Input Interface for boots */
+    if (boots_if.clif == BOOTS_CLIF_UART) {
+        cli_uartfd = boots_uart_init(boots_if.cli, boots_if.cli_speed);
+        if (cli_uartfd < 0) {
+            BPRINT_E("Open serial port:%s failed(%d)!!", boots_if.cli, cli_uartfd);
+            goto exit;
+        }
+        cont = 1;
+
+    } else {
+        if ((type = getopt(argc, argv, "frco")) != -1) {
+            BPRINT_D("optopt: %d, opterr: %d, optind: %d", optopt, opterr, optind);
+            switch (type) {
+            case 'f':   /** script file */
+                sfile.script = boots_script_open(*(argv + optind));
+                if (!sfile.script) {
+                    goto exit;
+                }
+                break;
+            case 'r':   /** raw data */
+                pkt = boots_raw_cmd_handler(argv + optind, argc - optind);
+                break;
+            case 'c':   /** command set */
+                pkt = boots_cmd_set_handler(argv + optind, argc - optind);
+                break;
+        #if 0 /** process this in above */
+            case 'o':
+                pkt = boots_country_set_handler(argv + optind, argc - optind);
+                break;
+        #endif
+            default:
+                BPRINT_W("Unknown type: %c", type);
+                break;
+            };
+            if (!pkt && !sfile.script) goto exit;
+        }
+    }
+
+    pid = getpid();
+    ret = setpriority(which, pid, priority);
+    if (ret != 0) {
+        BPRINT_I("setpriority fail: %s(%d)", strerror(errno), errno);
+    }
+
+    /** Process handler */
+    do {
+        int ret = -1;
+        struct timeval timo;
+
+        if (sfile.script) {
+            pkt = boots_script_get(sfile.script);
+            if (pkt == NULL)
+                break;  // Could end of file
+        }
+
+        // default timeout
+        if (sfile.timo) {
+            timo.tv_sec = sfile.timo / 1000;
+            timo.tv_usec = (sfile.timo % 1000) * 1000;
+        } else {
+            timo.tv_sec = 3;
+            timo.tv_usec = 0;
+        }
+        if (pkt) {
+            BPRINT_D("s_type: %d", pkt->s_type);
+            switch (pkt->s_type) {
+            case SCRIPT_NONE:       // modular commands
+            case SCRIPT_CMD:        // hci_cmd script
+            case SCRIPT_STRESS:     // stress test script
+            case SCRIPT_LOOPBACK:   // loopback test script
+            case SCRIPT_LPTIMER:    // loopback test script with timer
+                pkt = boots_pkt_node_pop(pkt, buf, &len);
+                break;
+            case SCRIPT_TX:         // combo tool script
+                pkt = boots_pkt_node_pop(pkt, buf, &len);
+                if (len) {
+                    // Send command, if input by user or script
+                    boots_write(csw_fd, (void *)buf, len, boots_if.csif);
+                    boots_pkt_handler(buf, len, NULL);
+                    memset(buf, 0, sizeof(buf));
+                    len = 0;
+                }
+                continue;
+            case SCRIPT_RX:
+            case SCRIPT_WAITRX:
+                FD_ZERO(&readfs);
+                if (csr_fd >= 0)
+                    FD_SET(csr_fd, &readfs);
+                ret = select(csr_fd + 1, &readfs, NULL, NULL, &timo);
+                if (ret > 0) {
+                    read_len = boots_read(csr_fd, buf, sizeof(buf), boots_if.csif);
+                    if (read_len > 0) {
+                        cont = boots_pkt_handler(buf, (size_t)read_len, pkt ? &pkt : NULL);
+                        memset(buf, 0, sizeof(buf));
+                        read_len = 0;
+                    }
+                } else if (ret == 0) {
+                    goto exit;
+                }
+                continue;
+            case SCRIPT_TITLE:
+            case SCRIPT_PROC:
+                BPRINT_I("%s", pkt->u_cnt.msg);     // Just print msg
+                pkt = boots_pkt_node_pop(pkt, NULL, NULL);
+                continue;
+            case SCRIPT_TIMEOUT:
+                if (pkt->u_cnt.timo) {
+                    sfile.timo = pkt->u_cnt.timo;
+                }
+                pkt = boots_pkt_node_pop(pkt, NULL, NULL);
+                continue;
+            case SCRIPT_WAIT:
+                if (pkt->u_cnt.wait) {
+                    (void)usleep(pkt->u_cnt.wait * 1000);
+                }
+                pkt = boots_pkt_node_pop(pkt, NULL, NULL);
+                continue;
+            case SCRIPT_USBALT:
+                // TODO
+                continue;
+            case SCRIPT_LOOP:
+                sfile.loop = pkt->u_cnt.loop;
+                if (sfile.script)
+                    sfile.loop_pos = ftell(sfile.script);
+                pkt = boots_pkt_node_pop(pkt, NULL, NULL);
+                BPRINT_D("Looping");
+                continue;
+            case SCRIPT_LOOPEND:
+                if (!sfile.loop) {
+                    sfile.loop_pos = 0;
+                    BPRINT_D("Loop End");
+                } else {
+                    if ((--sfile.loop) && sfile.script && sfile.loop_pos >= 0)
+                        boots_script_loop(sfile.script, sfile.loop_pos);
+                }
+                pkt = boots_pkt_node_pop(pkt, NULL, NULL);
+                continue;
+            case SCRIPT_RSSI:    // Background RSSI scan
+                if (pkt->u_cnt.rssi_s->stop)
+                    boots_pkt_cleanup_report_rssi(1);
+                else {
+                    boots_pkt_cleanup_report_rssi(0);
+                    memcpy(&rssi_setting, pkt->u_cnt.rssi_s, sizeof(rssi_set_s));
+                }
+                buf[0] = SCRIPT_RSSI;
+                memcpy(&buf[1], pkt->u_cnt.rssi_s, sizeof(rssi_set_s));
+                len = sizeof(rssi_set_s) + 1;
+                boots_write(csw_fd, (void *)buf, len, boots_if.csif);
+                memset(buf, 0, sizeof(buf));
+                len = 0;
+                pkt = boots_pkt_node_pop(pkt, NULL, NULL);
+                break;
+            case SCRIPT_END:
+                BPRINT_I("Script End");
+                pkt = boots_pkt_node_pop(pkt, NULL, NULL);
+                boots_script_close(sfile.script);
+                sfile.script = NULL;
+                goto exit;
+            default:
+                break;
+            }
+        }
+
+        if (len) {
+            if (pkt && (pkt->s_type == SCRIPT_STRESS || pkt->s_type == SCRIPT_LOOPBACK || pkt->s_type == SCRIPT_LPTIMER)) {
+                if (BOOTS_STRESS_MEASURE_IN_BOOTS)
+                    boots_stress_record_timestamp(BOOTS_STRESS_TIMESTAMP_SEND_CMD_START);
+            }
+
+            // Send command, if input by user or script
+            boots_write(csw_fd, (void *)buf, len, boots_if.csif);
+
+            if (pkt && (pkt->s_type == SCRIPT_STRESS || pkt->s_type == SCRIPT_LOOPBACK || pkt->s_type == SCRIPT_LPTIMER)) {
+                if (BOOTS_STRESS_MEASURE_IN_BOOTS)
+                    boots_stress_record_timestamp(BOOTS_STRESS_TIMESTAMP_SEND_CMD_FINISH);
+                if (BOOTS_STRESS_SHOW_ALL_CMD)
+                    boots_pkt_handler(buf, len, NULL);
+                if (pkt->s_type == SCRIPT_LPTIMER)
+                    gettimeofday(&time_start, NULL);
+            } else
+                boots_pkt_handler(buf, len, NULL);
+            memset(buf, 0, sizeof(buf));
+            len = 0;
+        }
+
+        FD_ZERO(&readfs);
+
+        if (cli_uartfd >= 0)
+            FD_SET(cli_uartfd, &readfs);
+        if (csr_fd >= 0)
+            FD_SET(csr_fd, &readfs);
+
+        ret = select(MAX(cli_uartfd, csr_fd) + 1, &readfs, NULL, NULL, &timo);
+        if (ret > 0) {
+            if (cli_uartfd >= 0 && FD_ISSET(cli_uartfd, &readfs)) {
+                // read from UART(CBT)
+                read_len = boots_read(cli_uartfd, buf, sizeof(buf), boots_if.clif);
+                if (read_len > 0) {
+                    // write to platform
+                    boots_write(csw_fd, (void *)buf, (size_t)read_len, boots_if.csif);
+                    boots_pkt_handler(buf, (size_t)read_len, NULL);
+                    memset(buf, 0, sizeof(buf));
+                    read_len = 0;
+                }
+            }
+            if (FD_ISSET(csr_fd, &readfs)) {
+                // read from platform
+                read_len = boots_read(csr_fd, buf, sizeof(buf), boots_if.csif);
+
+                if (read_len > 0 && boots_if.clif == BOOTS_CLIF_USER) {
+                    cont = boots_pkt_handler(buf, read_len, pkt ? &pkt : NULL);
+                } else if (read_len > 0 && boots_if.clif == BOOTS_CLIF_UART) {
+                    // write to UART(CBT)
+                    boots_write(cli_uartfd, (void *)buf, read_len, boots_if.clif);
+                    boots_pkt_handler(buf, read_len, NULL);
+                }
+
+                if (pkt && pkt->s_type == SCRIPT_STRESS) {
+                    if (BOOTS_STRESS_MEASURE_IN_BOOTS)
+                        boots_stress_record_timestamp(BOOTS_STRESS_TIMESTAMP_RECEIVE_EVENT_FINISH);
+                } else if (pkt && (pkt->s_type == SCRIPT_LOOPBACK || pkt->s_type == SCRIPT_LPTIMER)) {
+                    if (BOOTS_STRESS_MEASURE_IN_BOOTS && !BOOTS_STRESS_MEASURE_LBT_TOTAL_LATENCY)
+                        boots_stress_record_timestamp(BOOTS_STRESS_TIMESTAMP_RECEIVE_EVENT_FINISH);
+                    if (buf[0] == HCI_EVENT_PKT && read_len == 8) {
+                        // should read again (Titan:Why read again but not use it?)
+                        boots_read(csr_fd, buf, sizeof(buf), boots_if.csif);
+                    } else if (buf[0] == HCI_EVENT_PKT && buf[8] == HCI_ACL_PKT && ((size_t)read_len) == (8 + pkt->len)) {
+                        // current loopback test iteration is finished
+                    } else if (buf[0] == HCI_ACL_PKT) {
+                        // current loopback test iteration is finished
+                    } else {
+                        BPRINT_E("Receive unknonw type %02X, len=%d(EVENT/ACL is expected)", buf[0], (int)read_len);
+                        exit(0);
+                    }
+                    if (BOOTS_STRESS_MEASURE_IN_BOOTS && BOOTS_STRESS_MEASURE_LBT_TOTAL_LATENCY)
+                        boots_stress_record_timestamp(BOOTS_STRESS_TIMESTAMP_RECEIVE_EVENT_FINISH);
+                    if (pkt->s_type == SCRIPT_LPTIMER) {
+                        gettimeofday(&time_end, NULL);
+                        diff_time = (time_end.tv_usec + time_end.tv_sec * 1000000) - (time_start.tv_usec + time_start.tv_sec * 1000000);
+                        if (boots_loop_timer > 0 && (unsigned int)boots_loop_timer > (diff_time / 1000))
+                            usleep(boots_loop_timer*1000 - diff_time);
+                    }
+                }
+                memset(buf, 0, sizeof(buf));
+                read_len = 0;
+            }
+        } else if (ret == 0) {
+            // timeout
+            if (boots_if.clif == BOOTS_CLIF_UART)
+                cont = 1;
+            else
+                cont = 0;
+        } else {
+            BPRINT_D("Unexpect return: %d", ret);
+        }
+    } while (cont || sfile.script);
+
+exit:
+    if (boots_if.csif == BOOTS_CSIF_SKT) {
+        if (csw_fd >= 0)
+            boots_tell_socket_end(csw_fd, &skaddr_srv);
+        (void)usleep(1000);
+        if (csw_fd >= 0)
+            boots_sk_close(&csw_fd);
+        if (csr_fd >= 0)
+            boots_sk_close(&csr_fd);
+        unlink(BOOTS_CLISK_NAME);
+    } else if (boots_if.csif == BOOTS_CSIF_UART) {
+        if (csw_fd >= 0)
+            close(csw_fd);
+    } else if (boots_if.csif == BOOTS_CSIF_ETH) {
+        if (csw_fd >= 0)
+            boots_tell_ethernet_end(csw_fd, &ethaddr_srv);
+        (void)usleep(1000);
+        if (csw_fd >= 0)
+            boots_eth_close(&csw_fd);
+        if (csr_fd >= 0)
+            boots_eth_close(&csr_fd);
+    }
+    if (boots_if.clif == BOOTS_CLIF_UART) {
+        if (cli_uartfd >= 0)
+            close(cli_uartfd);
+    }
+    boots_pkt_list_destroy(pkt);
+    pkt = NULL;
+    boots_script_close(sfile.script);
+    BPRINT_D("Input End");
+    return 0;
+}
+
+//---------------------------------------------------------------------------