Add gnss 5311 support.

Change-Id: I436cbc7eabe8e6448d318b6eee81f49dddcce756
diff --git a/mbtk/mbtk_gnssd/Makefile b/mbtk/mbtk_gnssd/Makefile
index 9f1ac01..79f937a 100755
--- a/mbtk/mbtk_gnssd/Makefile
+++ b/mbtk/mbtk_gnssd/Makefile
@@ -24,7 +24,7 @@
 #MY_FILES_PATH += $(LOCAL_PATH)/platform/linux
 #endif
 #LOCAL_SRC_FILES = $(wildcard *.c) $(wildcard *.cpp)
-LOCAL_SRC_FILES = gnss_main.c gnss_nmea.c gnss_6228.c gnss_utils.c gnss_hd8122.c
+LOCAL_SRC_FILES = gnss_main.c gnss_nmea.c gnss_6228.c gnss_utils.c gnss_hd8122.c gnss_asr5311.c
 
 # Enable ubus
 #LOCAL_SRC_FILES += gnss_ubus.c
diff --git a/mbtk/mbtk_gnssd/gnss_6228.c b/mbtk/mbtk_gnssd/gnss_6228.c
index 066ae36..0cc248c 100755
--- a/mbtk/mbtk_gnssd/gnss_6228.c
+++ b/mbtk/mbtk_gnssd/gnss_6228.c
Binary files differ
diff --git a/mbtk/mbtk_gnssd/gnss_6228.h b/mbtk/mbtk_gnssd/gnss_6228.h
index 3a2a41f..4bc50dd 100755
--- a/mbtk/mbtk_gnssd/gnss_6228.h
+++ b/mbtk/mbtk_gnssd/gnss_6228.h
@@ -24,11 +24,11 @@
 
 int gnss_6228_dev_close();
 
-int gnss_6228_open();
+int gnss_6228_open(const char *dev);
 
-int gnss_6228_close();
+int gnss_6228_close(int fd);
 
-int gnss_6228_fw_dl();
+int gnss_6228_fw_dl(int fd, const char *dev);
 
 void gnss_6228_dl_read_cb(const void *data, int data_len);
 
diff --git a/mbtk/mbtk_gnssd/gnss_asr5311.c b/mbtk/mbtk_gnssd/gnss_asr5311.c
new file mode 100755
index 0000000..654fcdc
--- /dev/null
+++ b/mbtk/mbtk_gnssd/gnss_asr5311.c
@@ -0,0 +1,320 @@
+/*
+*    gnss_asr5311.c
+*
+*    ASR 5311 gnss support source.
+*
+*/
+/******************************************************************************
+
+                          EDIT HISTORY FOR FILE
+
+  WHEN        WHO       WHAT,WHERE,WHY
+--------    --------    -------------------------------------------------------
+2024/6/19     LiuBin      Initial version
+
+******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "mbtk_log.h"
+#include "mbtk_type.h"
+#include "mbtk_gpio.h"
+#include "gnss_utils.h"
+#include "gnss_asr5311.h"
+
+#define UART_BITRATE_NMEA_DEF_FW    115200   // Default bitrate.
+#define GNSS_SET_TIMEOUT           3000     // 3s
+
+static pthread_cond_t read_cond;
+static pthread_mutex_t read_mutex;
+static bool setting_waitting = FALSE;
+static bool setting_busy = FALSE;
+static void *gnss_set_rsp_ptr = NULL;
+static gnss_err_enum gnss_set_result = GNSS_ERR_OK;
+
+int gnss_write(int fd, const void *data, int data_len);
+
+static void gnss_set_timer_cb(int signo)
+{
+    if(setting_busy) {
+        pthread_mutex_lock(&read_mutex);
+        pthread_cond_signal(&read_cond);
+        pthread_mutex_unlock(&read_mutex);
+        gnss_set_result = GNSS_ERR_TIMEOUT;
+    }
+    return;
+}
+
+static void gnss_hal_gpioctrl(char* str)
+{
+    int fd;
+    fd = open("/sys/devices/platform/asr-gps/ctrl", O_WRONLY);
+
+    if (fd >= 0) {
+        write(fd, str, strlen(str));
+        close(fd);
+    }
+}
+
+static int gnss_module_wait_fw_download_done()
+{
+    int fd;
+    char buf[64];
+    int len;
+    int ret = -1;
+
+    fd = open("/sys/devices/platform/asr-gps/status", O_RDONLY);
+    if (fd >= 0)  {
+        sleep(1);
+        len = read(fd, buf, 64);
+        LOGD("FW DONE %s, %d", buf, len);
+        if(!memcmp(buf, "status: on", 10))  {
+           /* FW Downloading is OK. */
+            ret = 0;
+        }
+
+        close(fd);
+    }
+
+    if(ret)
+        gnss_hal_gpioctrl("off");
+
+    return ret;
+}
+
+
+int gnss_5311_dev_open()
+{
+    return 0;
+}
+
+int gnss_5311_dev_close()
+{
+    return 0;
+}
+
+int gnss_5311_open(const char *dev)
+{
+    pthread_mutex_init(&read_mutex, NULL);
+    pthread_cond_init(&read_cond, NULL);
+    return gnss_port_open(dev, O_RDWR | O_NONBLOCK | O_NOCTTY, UART_BITRATE_NMEA_DEF_FW, TRUE);
+}
+
+int gnss_5311_close(int fd)
+{
+    pthread_mutex_destroy(&read_mutex);
+    pthread_cond_destroy(&read_cond);
+    return gnss_port_close(fd);
+}
+
+int gnss_5311_fw_dl(int fd, const char *dev)
+{
+    char cmd[256] = {0};
+    if(memcmp(dev, "/dev/", 5) == 0) {
+        snprintf(cmd, sizeof(cmd), "nice -n -10 aboot-tiny -B 2000000 -s %s -F /lib/firmware/jacana_fw.bin -P /system/etc/jacana_pvt.bin", dev + 5);
+    } else {
+        snprintf(cmd, sizeof(cmd), "nice -n -10 aboot-tiny -B 2000000 -s %s -F /lib/firmware/jacana_fw.bin -P /system/etc/jacana_pvt.bin", dev);
+    }
+    system(cmd);
+
+    return gnss_module_wait_fw_download_done();
+}
+
+void gnss_5311_set_cb(const void *data, int data_len)
+{
+    const char *buff = (const char*)data;
+    if(setting_busy) { // Has setting cmd process.
+
+    }
+}
+
+gnss_err_enum gnss_5311_set(int fd, const char *cmd, void *cmd_rsp, int cmd_rsp_len)
+{
+    if(setting_busy) {
+        return GNSS_ERR_SET_BUSY;
+    } else {
+        bool should_wait_rsp = TRUE;
+        setting_busy = TRUE;
+        gnss_set_rsp_ptr = cmd_rsp;
+        gnss_set_result = GNSS_ERR_OK;
+
+        mbtk_timer_set(gnss_set_timer_cb, GNSS_SET_TIMEOUT);
+
+        if(memcmp(cmd, "$RESET", 6) == 0) { // $RESET,<mode>
+            gnss_reset_type_enum mode = (gnss_reset_type_enum)atoi(cmd + 7);
+            if(mode == GNSS_RESET_TYPE_HOT) {
+
+            } else if(mode == GNSS_RESET_TYPE_WARM) {
+
+            } else if(mode == GNSS_RESET_TYPE_COLD) {
+
+            } else {
+                gnss_set_result = GNSS_ERR_ARG;
+                goto set_fail;
+            }
+            if(gnss_set_result != GNSS_ERR_OK) {
+                goto set_fail;
+            }
+            should_wait_rsp = FALSE;
+        } else if(memcmp(cmd, "$SYSCFG", 7) == 0) { // $SYSCFG,<mode>
+            uint32 mode = 0;
+            mode = (uint32)atoi(cmd + 8);
+            uint32 new_mode = 0;
+            if(((GNSS_SET_SYSCFG_GPS | GNSS_SET_SYSCFG_BDS | GNSS_SET_SYSCFG_GLO | GNSS_SET_SYSCFG_GAL) & mode) != mode) {
+                gnss_set_result = GNSS_ERR_ARG;
+                goto set_fail;
+            }
+
+            if(mode & GNSS_SET_SYSCFG_GPS) { // GPS
+                new_mode |= 0x00000001;
+            }
+            if(mode & GNSS_SET_SYSCFG_BDS) { // BDS
+                new_mode |= 0x00000002;
+            }
+            if(mode & GNSS_SET_SYSCFG_GLO) { // GLO
+                new_mode |= 0x00000004;
+            }
+            if(mode & GNSS_SET_SYSCFG_GAL) { // GAL
+                new_mode |= 0x00000010;
+            }
+
+
+            if(gnss_set_result != GNSS_ERR_OK) {
+                goto set_fail;
+            }
+            should_wait_rsp = TRUE;
+        } else if(memcmp(cmd, "$MSGCFG", 7) == 0) { // $MSGCFG,<mode>,<rate>
+            uint32 mode;
+            int rate;
+            if(2 == sscanf(cmd, "$MSGCFG,%d,%d", &mode, &rate)) {
+                int time = rate / 1000; // s
+                if(time < 0) {
+                    gnss_set_result = GNSS_ERR_ARG;
+                    goto set_fail;
+                }
+
+                if(((GNSS_SET_MSGCFG_RMC | GNSS_SET_MSGCFG_VTG | GNSS_SET_MSGCFG_GGA | GNSS_SET_MSGCFG_GSA
+                    | GNSS_SET_MSGCFG_GRS | GNSS_SET_MSGCFG_GSV | GNSS_SET_MSGCFG_GLL | GNSS_SET_MSGCFG_ZDA
+                    | GNSS_SET_MSGCFG_GST | GNSS_SET_MSGCFG_TXT) & mode) != mode) {
+                    gnss_set_result = GNSS_ERR_ARG;
+                    goto set_fail;
+                }
+
+                if(mode & GNSS_SET_MSGCFG_RMC) {
+
+                }
+
+                if(mode & GNSS_SET_MSGCFG_VTG) {
+
+                }
+
+                if(mode & GNSS_SET_MSGCFG_GGA) {
+
+                }
+
+                if(mode & GNSS_SET_MSGCFG_GSA) {
+
+                }
+
+                if(mode & GNSS_SET_MSGCFG_GRS) {
+
+                }
+
+                if(mode & GNSS_SET_MSGCFG_GSV) {
+
+                }
+
+                if(mode & GNSS_SET_MSGCFG_GLL) {
+
+                }
+
+                if(mode & GNSS_SET_MSGCFG_ZDA) {
+
+                }
+
+                if(mode & GNSS_SET_MSGCFG_GST) {
+
+                }
+
+                if(mode & GNSS_SET_MSGCFG_TXT) {
+
+                }
+            } else {
+                gnss_set_result = GNSS_ERR_ARG;
+                goto set_fail;
+            }
+
+            should_wait_rsp = TRUE;
+        } else if(memcmp(cmd, "$MINEL", 6) == 0) { // $MINEL,<elev>
+#if 0
+            float elev = 0.0f;
+            elev = (float)atof(cmd + 7);
+//            LOGD("ELEV : %f", elev);
+//            log_hex("ELEV", &elev, sizeof(double));
+            if(elev < -90.0f || elev > 90.0f) {
+                gnss_set_result = GNSS_ERR_ARG;
+                goto set_fail;
+            }
+            float elevs[2];
+            elevs[0] = elev;
+            elevs[1] = elev;
+            gnss_set_result = gnss_8122_minel(fd, elevs);
+            if(gnss_set_result != GNSS_ERR_OK) {
+                goto set_fail;
+            }
+            should_wait_rsp = FALSE;
+#else
+            gnss_set_result = GNSS_ERR_UNSUPPORT;
+            goto set_fail;
+#endif
+        } else if(memcmp(cmd, "$NMEACFG", 8) == 0) { // $NMEACFG,<ver>
+#if 0
+            gnss_memaver_type_enum version = (gnss_memaver_type_enum)atoi(cmd + 9);
+            if(version == GNSS_MEMAVER_TYPE_3_0) {
+                gnss_set_result = gnss_8122_nmeaver(fd, 1);
+            } else if(version == GNSS_MEMAVER_TYPE_4_0) {
+                gnss_set_result = gnss_8122_nmeaver(fd, 2);
+            } else if(version == GNSS_MEMAVER_TYPE_4_1) {
+                gnss_set_result = gnss_8122_nmeaver(fd, 3);
+            } else {
+                gnss_set_result = GNSS_ERR_ARG;
+                goto set_fail;
+            }
+            if(gnss_set_result != GNSS_ERR_OK) {
+                goto set_fail;
+            }
+            should_wait_rsp = FALSE;
+#else
+            gnss_set_result = GNSS_ERR_UNSUPPORT;
+            goto set_fail;
+#endif
+        }
+        else
+        {
+            LOGW("Unknown cmd:%s", cmd);
+            gnss_set_result = GNSS_ERR_UNSUPPORT;
+            goto set_fail;
+        }
+
+set_success:
+        if(should_wait_rsp) {
+            setting_waitting = TRUE;
+            pthread_mutex_lock(&read_mutex);
+            pthread_cond_wait(&read_cond, &read_mutex);
+            pthread_mutex_unlock(&read_mutex);
+        } else {
+            mbtk_timer_clear();
+        }
+
+        setting_busy = FALSE;
+        return gnss_set_result;
+set_fail:
+        setting_busy = FALSE;
+        mbtk_timer_clear();
+        return gnss_set_result;
+    }
+}
+
diff --git a/mbtk/mbtk_gnssd/gnss_asr5311.h b/mbtk/mbtk_gnssd/gnss_asr5311.h
new file mode 100755
index 0000000..78a676c
--- /dev/null
+++ b/mbtk/mbtk_gnssd/gnss_asr5311.h
@@ -0,0 +1,29 @@
+/*
+* gnss_asr5311.h
+*
+* ASR 5311 GNSS support header.
+*
+* Author : lb
+* Date   : 2024/6/19 15:50:15
+*/
+#ifndef _GNSS_ASR5311_H
+#define _GNSS_ASR5311_H
+#include "gnss_info.h"
+#include "mbtk_type.h"
+
+
+int gnss_5311_dev_open();
+
+int gnss_5311_dev_close();
+
+int gnss_5311_open(const char *dev);
+
+int gnss_5311_close(int fd);
+
+int gnss_5311_fw_dl();
+
+void gnss_5311_set_cb(const void *data, int data_len);
+
+gnss_err_enum gnss_5311_set(int fd, const char *cmd, void *cmd_rsp, int cmd_rsp_len);
+
+#endif /* _GNSS_ASR5311_H */
diff --git a/mbtk/mbtk_gnssd/gnss_hd8122.c b/mbtk/mbtk_gnssd/gnss_hd8122.c
index dff4599..5ee816c 100755
--- a/mbtk/mbtk_gnssd/gnss_hd8122.c
+++ b/mbtk/mbtk_gnssd/gnss_hd8122.c
@@ -75,7 +75,6 @@
     }
 }
 
-
 static int msg_insert(uint8 gid, uint8 sid)
 {
     int i = 0;
@@ -335,7 +334,7 @@
     return gnss_port_close(fd);
 }
 
-int gnss_8122_fw_dl()
+int gnss_8122_fw_dl(int fd, const char *dev)
 {
     return 0;
 }
diff --git a/mbtk/mbtk_gnssd/gnss_hd8122.h b/mbtk/mbtk_gnssd/gnss_hd8122.h
index a922d2d..6d2792a 100755
--- a/mbtk/mbtk_gnssd/gnss_hd8122.h
+++ b/mbtk/mbtk_gnssd/gnss_hd8122.h
@@ -116,7 +116,7 @@
 
 int gnss_8122_close();
 
-int gnss_8122_fw_dl();
+int gnss_8122_fw_dl(int fd, const char *dev);
 
 //void gnss_8122_dl_read_cb(const void *data, int data_len);
 
diff --git a/mbtk/mbtk_gnssd/gnss_info.h b/mbtk/mbtk_gnssd/gnss_info.h
index 51b4421..e781103 100755
--- a/mbtk/mbtk_gnssd/gnss_info.h
+++ b/mbtk/mbtk_gnssd/gnss_info.h
@@ -74,7 +74,7 @@
 typedef int (*gnss_dev_close_func)();
 typedef int (*gnss_open_func)(const char *dev);
 typedef int (*gnss_close_func)(int fd);
-typedef int (*gnss_fw_dl_func)(int fd);
+typedef int (*gnss_fw_dl_func)(int fd, const char *dev);
 typedef void (*gnss_dl_read_cb_func)(const void *data, int data_len);
 typedef gnss_err_enum (*gnss_set_func)(int fd, const char *cmd, void *cmd_rsp, int cmd_rsp_len);
 typedef void (*gnss_set_cb_func)(const void *data, int data_len);
@@ -109,6 +109,7 @@
     char dev_name[32];
     bool auto_open;        // Should auto open gnss?
     bool auto_dl_fw;       // Should download firmware int the first?
+    bool dl_befor_open;    // Should download firmware before open device?
     int fd;                // GNSS uart fd.
     int exit_fd[2];        // Use to exit thread.
     gnss_state_enum state;
diff --git a/mbtk/mbtk_gnssd/gnss_main.c b/mbtk/mbtk_gnssd/gnss_main.c
index 688f8dc..3f887f1 100755
--- a/mbtk/mbtk_gnssd/gnss_main.c
+++ b/mbtk/mbtk_gnssd/gnss_main.c
@@ -15,6 +15,8 @@
 
 #include "gnss_6228.h"
 #include "gnss_hd8122.h"
+#include "gnss_asr5311.h"
+
 
 #define GNSS_DEBUG 1
 #define GNSS_UBUS_ENABLE 1
@@ -29,10 +31,8 @@
 
 #ifdef GNSS_DEBUG
 #define GNSS_NMEA_FILE_LOG      "/tmp/mbtk_gnss_nmea.log"
-#define GNSS_NMEA_FILE_LOG_MAX  10485760    // 10MB
-
 #define GNSS_FILE_LOG           "/tmp/mbtk_gnss.log"
-#define GNSS_FILE_LOG_MAX       10485760    // 10MB
+#define GNSS_FILE_LOG_MAX       104857600    // 100MB
 #endif
 
 gnss_info_t gnss_info;
@@ -54,7 +54,8 @@
 #ifdef GNSS_DEBUG
 static bool nmea_log_enable = FALSE;
 static int nmea_log_fd = -1;
-static int nmea_log_fd_len = 0;
+static int debug_fd = -1;
+static int debug_fd_len = 0;
 #endif
 static int gnss_pty_master_fd = -1;
 static int gnss_pty_slave_fd = -1;
@@ -65,7 +66,7 @@
 
 static void help()
 {
-    LOGD("mbtk_gnssd <6228/8122...> <gnss_dev> <0/1>");
+    LOGD("mbtk_gnssd <6228/8122/5311> <gnss_dev> <0/1>");
 }
 
 static int arg_check(int argc, char *argv[])
@@ -74,8 +75,8 @@
         goto check_fail;
     }
 
-    // Only support 6228/8122.
-    if(strcmp(argv[1], GNSS_ID_6228) && strcmp(argv[1], GNSS_ID_8122)) {
+    // Only support 6228/8122/5311.
+    if(strcmp(argv[1], GNSS_ID_6228) && strcmp(argv[1], GNSS_ID_8122) && strcmp(argv[1], GNSS_ID_5311)) {
         goto check_fail;
     }
 
@@ -157,26 +158,44 @@
     return 0;
 }
 
-static void nmea_print(const char *nmea, int nmea_len)
-{
 #ifdef GNSS_DEBUG
+static void log_save(int fd, const char *data, int data_len)
+{
     if(nmea_log_enable){
-        if(nmea_log_fd_len > GNSS_NMEA_FILE_LOG_MAX) {
+        if(0 /* debug_fd_len > GNSS_FILE_LOG_MAX */) {
+            LOGD("Reopen file:%s(len = %d)", GNSS_FILE_LOG, debug_fd_len);
+            close(debug_fd);
+            debug_fd = open(GNSS_FILE_LOG, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+            if(debug_fd < 0) {
+                LOGE("Open debug fd fail.");
+            }
+            debug_fd_len = 0;
+
+            LOGD("Reopen file:%s", GNSS_NMEA_FILE_LOG);
             close(nmea_log_fd);
             nmea_log_fd = open(GNSS_NMEA_FILE_LOG, O_WRONLY | O_CREAT | O_TRUNC, 0666);
             if(nmea_log_fd < 0) {
                 LOGE("Open debug fd fail.");
             }
-            nmea_log_fd_len = 0;
         }
 
-        if(nmea_log_fd > 0) {
-            write(nmea_log_fd, nmea, nmea_len);
-            nmea_log_fd_len += nmea_len;
+        if(fd == nmea_log_fd) {
+            if(nmea_log_fd > 0) {
+                write(nmea_log_fd, data, data_len);
+                debug_fd_len += data_len;
+            }
+        } else if(fd == debug_fd) {
+            if(debug_fd > 0) {
+                write(debug_fd, data, data_len);
+                debug_fd_len += data_len;
+            }
         }
     }
+}
 #endif
 
+static void nmea_print(const char *nmea, int nmea_len)
+{
     if(gnss_usb_at_port_fd > 0) {
         write(gnss_usb_at_port_fd, nmea, nmea_len);
     }
@@ -236,11 +255,22 @@
 
 static void gnss_nmea_process(const char *data, int data_len)
 {
+    // LOGD("gnss_nmea_process() : data_len - %d", data_len);
+#if 0
     char nmea[GNSS_BUFF_SIZE] = {0};
     memcpy(nmea, data, data_len);
+#else
+    const char *nmea = data;
+#endif
 
     if(!nmea_check(nmea, data_len)) {
-        gnss_info.gnss_set_cb(nmea, data_len);
+        LOGD("NO-NMEA:%s", nmea);
+#if GNSS_DEBUG
+        log_save(nmea_log_fd, "/**/", 4);
+        log_save(nmea_log_fd, nmea, data_len);
+#endif
+        if(gnss_info.gnss_set_cb)
+            gnss_info.gnss_set_cb(nmea, data_len);
         return;
     }
 
@@ -248,6 +278,8 @@
     if(nmea_log_enable) {
         LOGD("NMEA[%d]:%s", data_len, nmea);
     }
+
+    log_save(nmea_log_fd, nmea, data_len);
 #endif
 
     nmea_print(nmea, data_len);
@@ -265,7 +297,7 @@
 static bool nmea_char_check(char ch)
 {
     if(isalnum(ch) || ch == '$' || ch == '\r' || ch == '\n' || ch == '.'
-        || ch == ',' || ch == '*' || ch == '\0' || ch == '/' || ch == '_')
+        || ch == ',' || ch == '*' || ch == '\0' || ch == '/' || ch == '_' || ch == '=')
         return TRUE;
 
     return FALSE;
@@ -277,7 +309,9 @@
         LOGD("GNSS_OPEN[%d]:%s", data_len, data);
     } else if(gnss_info.state == GNSS_STATE_DOWNLOAD) {
         // LOGD("GNSS_DL[%d]:%s", data_len, data);
-        gnss_info.gnss_dl_read_cb(data, data_len);
+        if(gnss_info.gnss_dl_read_cb) {
+            gnss_info.gnss_dl_read_cb(data, data_len);
+        }
     } else if(gnss_info.state == GNSS_STATE_READY) {
         int index = 0;
         while(index < data_len) {
@@ -298,12 +332,26 @@
                     nmea_buff[nmea_buff_len++] = data[index];
                     if(nmea_buff[nmea_buff_len - 1] == '\n') {
                         if(data_buff_len > 0) {
-                            gnss_info.gnss_set_cb(data_buff, data_buff_len);
+#if GNSS_DEBUG
+                            log_save(nmea_log_fd, "/**/", 4);
+                            log_save(nmea_log_fd, data_buff, data_buff_len);
+#endif
+                            if(gnss_info.gnss_set_cb) {
+                                gnss_info.gnss_set_cb(data_buff, data_buff_len);
+                            }
                             data_buff_len = 0;
                         }
 
                         if(nmea_buff_len > 6 && nmea_buff[nmea_buff_len - 5] == '*') { // $XXX*YY\r\n
+                            nmea_buff[nmea_buff_len] = '\0';
                             gnss_nmea_process(nmea_buff, nmea_buff_len);
+                        } else if(nmea_buff_len > 0) {
+                            nmea_buff[nmea_buff_len] = '\0';
+                            LOGD("NO-NMEA:%s", nmea_buff);
+#if GNSS_DEBUG
+                            log_save(nmea_log_fd, "/**/", 4);
+                            log_save(nmea_log_fd, nmea_buff, nmea_buff_len);
+#endif
                         }
 
                         nmea_buff_len = 0;
@@ -346,8 +394,6 @@
     nmea_buff_len = 0;
     data_buff_len = 0;
 #if GNSS_DEBUG
-    int debug_fd = -1;
-    int debug_fd_len = 0;
     if(nmea_log_enable) {
         debug_fd = open(GNSS_FILE_LOG, O_WRONLY | O_CREAT | O_TRUNC, 0666);
         if(debug_fd < 0) {
@@ -357,7 +403,7 @@
         if(nmea_log_fd < 0) {
             LOGE("Open nmea fd fail.");
         }
-        nmea_log_fd_len = 0;
+        debug_fd_len = 0;
     }
 #endif
 
@@ -382,26 +428,13 @@
         if (FD_ISSET(gnss_info.fd, &fdr))
         {
             memset(buffer, 0, GNSS_BUFF_SIZE);
-            len = read(gnss_info.fd, buffer, GNSS_BUFF_SIZE);
+            len = read(gnss_info.fd, buffer, GNSS_BUFF_SIZE - 1);
             if(len > 0) {
                 //log_hex("READ", buffer, len);
 
 #if GNSS_DEBUG
-                if(nmea_log_enable){
-                    if(debug_fd_len > GNSS_FILE_LOG_MAX) {
-                        close(debug_fd);
-                        debug_fd = open(GNSS_FILE_LOG, O_WRONLY | O_CREAT | O_TRUNC, 0666);
-                        if(debug_fd < 0) {
-                            LOGE("Open debug fd fail.");
-                        }
-                        debug_fd_len = 0;
-                    }
-
-                    if(debug_fd > 0) {
-                        write(debug_fd, buffer, len);
-                        debug_fd_len += len;
-                    }
-                }
+                //LOGD("read data_len = %d", len);
+                log_save(debug_fd, buffer, len);
 #endif
 
                 gnss_data_process(buffer, len);
@@ -517,51 +550,100 @@
     }
 
     int ret = 0;
+    if(gnss_info.dl_befor_open) {
+        //if(gnss_info.auto_dl_fw) {
+            gnss_info.state = GNSS_STATE_DOWNLOAD;
+            ret = gnss_info.gnss_fw_dl(gnss_info.fd, gnss_info.dev_name);
+            if(ret) {
+                LOGE("gnss_fw_dl() fail : %d", ret);
+                gnss_info.state = GNSS_STATE_CLOSE;
+                return -1;
+            }
 
-    gnss_info.fd = gnss_info.gnss_open(gnss_info.dev_name);
-    if(gnss_info.fd <= 0) {
-        LOGE("gnss_open(%s) fail : %d", gnss_info.dev_name, gnss_info.fd);
-        gnss_info.state = GNSS_STATE_CLOSE;
-        return -1;
-    }
-    if(pipe(gnss_info.exit_fd)) {
-        LOGE("pipe() fail[%d].", errno);
-        return -1;
-    }
-    // GNSS is opened.
-    gnss_info.state = GNSS_STATE_OPEN;
+            gnss_info.fd = gnss_info.gnss_open(gnss_info.dev_name);
+            if(gnss_info.fd <= 0) {
+                LOGE("gnss_open(%s) fail : %d", gnss_info.dev_name, gnss_info.fd);
+                gnss_info.state = GNSS_STATE_CLOSE;
+                return -1;
+            }
+            if(pipe(gnss_info.exit_fd)) {
+                LOGE("pipe() fail[%d].", errno);
+                return -1;
+            }
+            // GNSS is opened.
+            gnss_info.state = GNSS_STATE_OPEN;
 
-    #if 0
-    // Start gnss read thread.
-    pthread_attr_t thread_attr;
-    pthread_attr_init(&thread_attr);
-    if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
-    {
-        LOGE("pthread_attr_setdetachstate() fail.");
-        goto main_exit;
-    }
+#if 0
+            // Start gnss read thread.
+            pthread_attr_t thread_attr;
+            pthread_attr_init(&thread_attr);
+            if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
+            {
+                LOGE("pthread_attr_setdetachstate() fail.");
+                goto main_exit;
+            }
 
-    if(pthread_create(&gnss_info.read_pid, &thread_attr, gnss_read_pthread, NULL))
+            if(pthread_create(&gnss_info.read_pid, &thread_attr, gnss_read_pthread, NULL))
 #else
-    if(pthread_create(&gnss_info.read_pid, NULL, gnss_read_pthread, NULL))
+            if(pthread_create(&gnss_info.read_pid, NULL, gnss_read_pthread, NULL))
 #endif
-    {
-        LOGE("pthread_create() fail.");
-        goto exit_with_close;
-    }
+            {
+                LOGE("pthread_create() fail.");
+                goto exit_with_close;
+            }
 
-    ret = gnss_info.gnss_dev_open();
-    if(ret) {
-        LOGE("gnss_dev_open() fail : %d", ret);
-        goto exit_with_thread_exit;
-    }
+            ret = gnss_info.gnss_dev_open();
+            if(ret) {
+                LOGE("gnss_dev_open() fail : %d", ret);
+                goto exit_with_thread_exit;
+            }
+        //}
+    } else {
+        gnss_info.fd = gnss_info.gnss_open(gnss_info.dev_name);
+        if(gnss_info.fd <= 0) {
+            LOGE("gnss_open(%s) fail : %d", gnss_info.dev_name, gnss_info.fd);
+            gnss_info.state = GNSS_STATE_CLOSE;
+            return -1;
+        }
+        if(pipe(gnss_info.exit_fd)) {
+            LOGE("pipe() fail[%d].", errno);
+            return -1;
+        }
+        // GNSS is opened.
+        gnss_info.state = GNSS_STATE_OPEN;
 
-    if(gnss_info.auto_dl_fw) {
-        gnss_info.state = GNSS_STATE_DOWNLOAD;
-        ret = gnss_info.gnss_fw_dl(gnss_info.fd);
+#if 0
+        // Start gnss read thread.
+        pthread_attr_t thread_attr;
+        pthread_attr_init(&thread_attr);
+        if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
+        {
+            LOGE("pthread_attr_setdetachstate() fail.");
+            goto main_exit;
+        }
+
+        if(pthread_create(&gnss_info.read_pid, &thread_attr, gnss_read_pthread, NULL))
+#else
+        if(pthread_create(&gnss_info.read_pid, NULL, gnss_read_pthread, NULL))
+#endif
+        {
+            LOGE("pthread_create() fail.");
+            goto exit_with_close;
+        }
+
+        ret = gnss_info.gnss_dev_open();
         if(ret) {
-            LOGE("gnss_fw_dl() fail : %d", ret);
-            goto exit_with_dev_close;
+            LOGE("gnss_dev_open() fail : %d", ret);
+            goto exit_with_thread_exit;
+        }
+
+        if(gnss_info.auto_dl_fw) {
+            gnss_info.state = GNSS_STATE_DOWNLOAD;
+            ret = gnss_info.gnss_fw_dl(gnss_info.fd, gnss_info.dev_name);
+            if(ret) {
+                LOGE("gnss_fw_dl() fail : %d", ret);
+                goto exit_with_dev_close;
+            }
         }
     }
 
@@ -745,6 +827,7 @@
         gnss_info.gnss_id = GNSS_TYPE_6228;
         gnss_info.auto_open = (bool)atoi(argv[3]);
         gnss_info.auto_dl_fw = TRUE;
+        gnss_info.dl_befor_open = FALSE;
         gnss_info.gnss_dev_open = gnss_6228_dev_open;
         gnss_info.gnss_dev_close = gnss_6228_dev_close;
         gnss_info.gnss_open = gnss_6228_open;
@@ -757,6 +840,7 @@
         gnss_info.gnss_id = GNSS_TYPE_8122;
         gnss_info.auto_open = (bool)atoi(argv[3]);
         gnss_info.auto_dl_fw = FALSE;
+        gnss_info.dl_befor_open = FALSE;
         gnss_info.gnss_dev_open = gnss_8122_dev_open;
         gnss_info.gnss_dev_close = gnss_8122_dev_close;
         gnss_info.gnss_open = gnss_8122_open;
@@ -765,6 +849,19 @@
         gnss_info.gnss_dl_read_cb = NULL;
         gnss_info.gnss_set = gnss_8122_set;
         gnss_info.gnss_set_cb = gnss_8122_set_cb;
+    } else if(!strcmp(argv[1], GNSS_ID_5311)) {
+        gnss_info.gnss_id = GNSS_TYPE_5311;
+        gnss_info.auto_open = (bool)atoi(argv[3]);
+        gnss_info.auto_dl_fw = TRUE;
+        gnss_info.dl_befor_open = TRUE;
+        gnss_info.gnss_dev_open = gnss_5311_dev_open;
+        gnss_info.gnss_dev_close = gnss_5311_dev_close;
+        gnss_info.gnss_open = gnss_5311_open;
+        gnss_info.gnss_close = gnss_5311_close;
+        gnss_info.gnss_fw_dl = gnss_5311_fw_dl;
+        gnss_info.gnss_dl_read_cb = NULL;
+        gnss_info.gnss_set = gnss_5311_set;
+        gnss_info.gnss_set_cb = gnss_5311_set_cb;
     } else {
         LOGE("No support : %s", argv[1]);
         return -1;