gnss: add mbtk gnss api

Change-Id: Ia2001b683cb9bdaf5b48dd7177b21c871ebd21cd
diff --git a/mbtk/include/mbtk/mbtk_gnss_5311.h b/mbtk/include/mbtk/mbtk_gnss_5311.h
new file mode 100644
index 0000000..71ba515
--- /dev/null
+++ b/mbtk/include/mbtk/mbtk_gnss_5311.h
@@ -0,0 +1,62 @@
+#ifndef __MBTK_GNSS_5311_H__
+#define __MBTK_GNSS_5311_H__
+
+#include "mbtk_log.h"
+
+typedef void (*mbtk_gnss_nmea_func_t)(void *nmea_data, int nmea_data_len);
+
+typedef enum {
+    ASR_GPS_INITIAL_SUCCESS             = 0,
+    ASR_GPS_INITIAL_FAILED              = 1,
+    ASR_GPS_INITIALED                   = 2,
+    ASR_GPS_DOWNLOAD_SUCCESS            = 3,
+    ASR_GPS_DOWNLOAD_FAIL               = 4,
+    ASR_GPS_SEND_DATA_SUCCESS           = 5,
+    ASR_GPS_SEND_DATA_FAIL              = 6,
+    ASR_GPS_DEINIT_SUCCESS,
+    ASR_GPS_DEINIT_FAIL,
+}USER_CB_STATE_T;
+
+typedef enum
+{
+    MBTK_GNSS_RESULT_SUCCESS = 0,
+    MBTK_GNSS_RESULT_FAIL,
+    MBTK_GNSS_RESULT_OPEN_SUCCESS,
+    MBTK_GNSS_RESULT_OPEN_FAIL,
+    MBTK_GNSS_RESULT_DOWNLOAD_SUCCESS,
+    MBTK_GNSS_RESULT_DOWNLOAD_FAIL,
+    MBTK_GNSS_RESULT_SEND_SUCCESS,
+    MBTK_GNSS_RESULT_SEND_FAIL,
+    MBTK_GNSS_RESULT_CLOSE_SUCCESS,
+    MBTK_GNSS_RESULT_CLOSE_FAIL,
+    MBTK_GNSS_RESULT_TIMEOUT,
+    MBTK_GNSS_RESULT_UNKNOWN_ERROR
+}MBTK_GNSS_5311_RESULT_TYPE;
+
+typedef enum
+{
+    MBTK_GNSS_MSG_LOCATION_INFO = 0,
+    MBTK_GNSS_MSG_NMEA_INFO
+}MBTK_GNSS_MSG_INFO_TYPE;
+
+typedef struct
+{
+    int                     init;
+    int                     fd;
+    mbtk_gnss_nmea_func_t   callbacks;
+    pthread_t               thread;
+    int                     control[2];
+    MBTK_GNSS_MSG_INFO_TYPE gnss_msg_state;
+}mbtk_gnss_nmea_status;
+
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_init(void);
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_deinit(void);
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_open(void);
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_close(void);
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_sleep(void);
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_wakeup(void);
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_param_config(const char *param_buf, int param_buf_len);
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_get_status(const char *status_buf, int status_buf_len, int *get_status_len);
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_add_nmea_out_func(mbtk_gnss_nmea_func_t cb);
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_set_nmea_out_type(MBTK_GNSS_MSG_INFO_TYPE type);
+#endif
\ No newline at end of file
diff --git a/mbtk/mbtk_lib/src/mbtk_gnss_5311.c b/mbtk/mbtk_lib/src/mbtk_gnss_5311.c
index 8b13789..8bbc64b 100755
--- a/mbtk/mbtk_lib/src/mbtk_gnss_5311.c
+++ b/mbtk/mbtk_lib/src/mbtk_gnss_5311.c
@@ -1 +1,892 @@
+/**
+ *   \file mbtk_gnss_5311.c
+ *   \brief gnss module.
+ *
+ *  Detailed description
+ *   \Author:  Sniper <yq.wang@mobiletek.cn>
+ *   \Version: 1.0.0
+ *   \Date: 2023-12-20
+ */
+#if 1
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <pthread.h>
+#include <sys/epoll.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <sys/socket.h>
 
+#include <libubox/blobmsg_json.h>
+#include <libubus.h>
+
+#include "mbtk_gnss_5311.h"
+
+/**********************************DEFINE***********************************/
+#define MBTK_GNSS_UBUS_SERVER "gps"
+#define MBTK_GNSS_UBUS_INIT "gnss_init"
+#define MBTK_GNSS_UBUS_INIT_PARAM "gnss_init_param"
+#define MBTK_GNSS_UBUS_SLEEP "gnss_sleep"
+#define MBTK_GNSS_UBUS_SLEEP_PARAM "gnss_sleep_param"
+#define MBTK_GNSS_UBUS_SET "gnss_setting"
+#define MBTK_GNSS_UBUS_SET_PARAM "gnss_setting_param"
+#define MBTK_GNSS_UBUS_GET_STATUS "gnss_get_state"
+
+#define MBTK_RESULT_FAIL -1
+#define MBTK_RESULT_SUCCESS 0
+
+#define MBTK_GNSS_CLOSE 0
+#define MBTK_GNSS_OPEN 1
+
+#define MBTK_GNSS_WAKEUP 0
+#define MBTK_GNSS_SLEEP 1
+
+#define DATABITS	CS8
+#define BAUD		B115200
+#define STOPBITS	0
+#define PARITYON	0
+#define PARITY		0
+
+#define MBTK_GNSS_NMEA_PORT "/dev/tty_gnss_nmea"
+/**********************************DEFINE***********************************/
+
+/**********************************VARIABLE***********************************/
+const struct blobmsg_policy mbtk_gnss_ubus_cb_policy[] = {
+    [0] = {
+        .name = "event",
+        .type = BLOBMSG_TYPE_INT32,
+    },
+};
+
+const struct blobmsg_policy mbtk_gnss_state_resp_cb_policy[] = {
+    [0] = {
+        .name = "gps_state_resp",
+        .type = BLOBMSG_TYPE_STRING,
+    },
+};
+
+static int mbtk_gnss_uloop_init = 0;
+static struct ubus_context *mbtk_gnss_ctx = NULL;
+static int mbtk_gnss_status = MBTK_GNSS_CLOSE;
+static mbtk_gnss_nmea_status nmea_state = {0};
+/**********************************VARIABLE***********************************/
+
+/**********************************FUNC***********************************/
+struct ubus_context *mbtk_get_ubus_ctx(void)
+{
+     if (!mbtk_gnss_uloop_init)
+     {
+         return NULL;
+     }
+     if (mbtk_gnss_ctx != NULL)
+     {
+         return mbtk_gnss_ctx;
+     }
+     
+     mbtk_gnss_ctx = ubus_connect(NULL);
+     if (!mbtk_gnss_ctx)
+     {
+         LOGE("[mbtk_gnss_api] ubus_connect connect fail.");
+         return NULL;
+     }
+
+     ubus_add_uloop(mbtk_gnss_ctx);
+     return mbtk_gnss_ctx;
+}
+
+int mbtk_gnss_ubus_uloop_init(void)
+{
+    int ret = -1;
+    if(mbtk_gnss_uloop_init == 0)
+    {
+        ret = uloop_init();
+        if(ret != 0)
+        {
+            LOGE("[mbtk_gnss_api] uloop_init fail.ret = [%d]", ret);
+            return MBTK_RESULT_FAIL;
+        }
+
+        if(mbtk_gnss_ctx != NULL)
+        {
+            LOGE("[mbtk_gnss_api] mbtk_gnss_ctx not NULL.");
+            return MBTK_RESULT_FAIL;
+        }
+
+        mbtk_gnss_ctx = ubus_connect(NULL);
+        if(!mbtk_gnss_ctx)
+        {
+            LOGE("[mbtk_gnss_api] ubus_connect fail.");
+            return MBTK_RESULT_FAIL;
+        }
+
+        ubus_add_uloop(mbtk_gnss_ctx);
+    }
+    mbtk_gnss_uloop_init = 1;
+    return MBTK_RESULT_SUCCESS;
+}
+
+
+int mbtk_gnss_ubus_uloop_deinit(void)
+{
+    if(mbtk_gnss_uloop_init == 1)
+    {
+        if(mbtk_gnss_ctx != NULL)
+        {
+            ubus_free(mbtk_gnss_ctx);
+            mbtk_gnss_ctx = NULL;
+        }
+
+        uloop_done();
+        mbtk_gnss_uloop_init = 0;
+    }
+    return MBTK_RESULT_SUCCESS;
+}
+
+static void mbtk_gnss_ubus_result_callback(struct ubus_request *req, int type, struct blob_attr *msg)
+{
+    UNUSED(type);
+    
+    struct blob_attr *tb[1];
+    struct blob_attr *cur = NULL;
+    unsigned int event;
+    MBTK_GNSS_5311_RESULT_TYPE* ubus_gnss_result = (MBTK_GNSS_5311_RESULT_TYPE *)req->priv;
+    int rc;
+
+    /*parsing blob to be accessed easily with tb array - parse "1" argument*/
+    rc = blobmsg_parse(mbtk_gnss_ubus_cb_policy, 1, tb, blob_data(msg), blob_len(msg));
+    if (rc < 0)
+    {
+        LOGE("[mbtk_gnss_api] blobmsg_parse fail.rc = [%d]", rc);
+        *ubus_gnss_result = MBTK_GNSS_RESULT_FAIL;
+        return;
+    }
+
+    /*parse first parameter*/
+    cur = tb[0];
+    if (!cur)
+    {
+        LOGE("[mbtk_gnss_api] cur is NULL.");
+        *ubus_gnss_result = MBTK_GNSS_RESULT_FAIL;
+        return;
+    }
+
+    event = blobmsg_get_u32(cur);
+    LOGE("[mbtk_gnss_api] get event = [%d].", event);
+    
+    switch(event)
+    {
+        case ASR_GPS_INITIAL_SUCCESS:
+        case ASR_GPS_INITIALED:
+            {
+                *ubus_gnss_result = MBTK_GNSS_RESULT_OPEN_SUCCESS;
+                break;
+            }
+        case ASR_GPS_INITIAL_FAILED:
+            {
+                *ubus_gnss_result = MBTK_GNSS_RESULT_OPEN_FAIL;
+                break;
+            }
+        case ASR_GPS_DOWNLOAD_SUCCESS:
+            {
+                *ubus_gnss_result = MBTK_GNSS_RESULT_DOWNLOAD_SUCCESS;
+                break;
+            }
+        case ASR_GPS_DOWNLOAD_FAIL:
+            {
+                *ubus_gnss_result = MBTK_GNSS_RESULT_DOWNLOAD_FAIL;
+                break;
+            }
+        case ASR_GPS_SEND_DATA_SUCCESS:
+            {
+                *ubus_gnss_result = MBTK_GNSS_RESULT_SEND_SUCCESS;
+                break;
+            }
+        case ASR_GPS_SEND_DATA_FAIL:
+            {
+                *ubus_gnss_result = MBTK_GNSS_RESULT_SEND_FAIL;
+                break;
+            }
+        case ASR_GPS_DEINIT_SUCCESS:
+            {
+                *ubus_gnss_result = MBTK_GNSS_RESULT_CLOSE_SUCCESS;
+                break;
+            }
+        case ASR_GPS_DEINIT_FAIL:
+            {
+                *ubus_gnss_result = MBTK_GNSS_RESULT_CLOSE_FAIL;
+                break;
+            }
+        default:
+            {
+                break;
+            }
+    }
+
+    return;
+}
+
+static void mbtk_gnss_state_get_callback(struct ubus_request *req, int type, struct blob_attr *msg)
+{
+    UNUSED(type);
+    
+    struct blob_attr *tb[1];
+    struct blob_attr *cur;
+    char *gps_state = NULL;
+    int rc;
+    char *outString = (char *)req->priv;
+
+    /*parsing blob to be accessed easily with tb array - parse "1" argument*/
+    rc = blobmsg_parse(mbtk_gnss_state_resp_cb_policy, 1, tb, blob_data(msg), blob_len(msg));
+    if (rc < 0)
+    {
+        LOGE("[mbtk_gnss_api] blobmsg_parse fail.rc = [%d]", rc);
+        return;
+    }
+
+    /*parse first parameter*/
+    cur = tb[0];
+    if (!cur)
+    {
+        LOGE("[mbtk_gnss_api] cur is NULL.");
+        return;
+    }
+
+    gps_state = blobmsg_get_string(cur);
+    LOGE("[mbtk_gnss_api] get status = [%s].", gps_state);
+    memset(outString, 0x0, 128);
+    memcpy(outString, gps_state, strlen(gps_state));
+
+    return;
+}
+
+static void mbtk_gnss_open_port(int *fd_ptr, const char *file_path, int flag, int tty)
+{
+
+	int fd = -1;
+
+	if((fd = open(file_path, flag)) < 0)
+	{
+        LOGE("[mbtk_gnss_api] Open %s fail errno = [%d].", file_path, errno);
+		return;
+	}
+
+    LOGE("[mbtk_gnss_api] Open %s success.", file_path);
+	if (tty)
+    {
+		/* set newtio */
+		struct termios newtio;
+		memset(&newtio, 0, sizeof(newtio));
+		//(void)fcntl(fd, F_SETFL, 0);
+
+		/* no flow control for uart by default */
+		newtio.c_cflag = BAUD | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
+		newtio.c_iflag = IGNPAR;
+        //newtio.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+		newtio.c_oflag = 0;
+		newtio.c_lflag = 0;    /* disable ECHO, ICANON, etc... */
+
+		newtio.c_cc[VERASE]   = 0x8;      /* del */
+		newtio.c_cc[VEOF]     = 4;      /* Ctrl-d */
+		newtio.c_cc[VMIN]     = 1;      /* blocking read until 1 character arrives */
+		newtio.c_cc[VEOL]     = 0xD;      /* '\0' */
+
+		tcflush(fd, TCIOFLUSH);
+		tcsetattr(fd, TCSANOW, &newtio);
+	}
+
+	*fd_ptr = fd;
+}
+
+static int epoll_deregister(int epoll_fd,int fd )
+{
+    int  ret;
+    do {
+        ret = epoll_ctl( epoll_fd, EPOLL_CTL_DEL, fd, NULL );
+    } while (ret < 0 && errno == EINTR);
+    return ret;
+}
+
+static int epoll_register(int epoll_fd, int fd)
+{
+    struct epoll_event  ev;
+    int    ret, flags;
+
+    /* important: make the fd non-blocking */
+    flags = fcntl(fd, F_GETFL);
+    fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+
+    ev.events  = EPOLLIN;
+    ev.data.fd = fd;
+    do {
+        ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev );
+    } while (ret < 0 && errno == EINTR);
+    
+    return ret;
+}
+
+
+static void *gnss_nmea_thread(void* arg)
+{
+    int                 epoll_fd= epoll_create(2);
+    int                 started    = 0;
+    int                 nmea_fd     = nmea_state.fd;
+    int                 control_fd = nmea_state.control[1];
+    int                 i          = 0;
+    int                 fd= -1;
+    int                 len = 0;
+    int                 offset = 0;
+    char                nmea_buf[1025] = {0};
+    struct epoll_event  events[2];
+    int                 ne, nevents;
+    int                 cmd = -1, ret = -1;
+    char                c;
+
+    int pos = 0;
+    int overflow = 0;
+    char in[128] = {0};
+
+    /* register control file descriptors for polling  */
+    epoll_register( epoll_fd, control_fd );
+    epoll_register( epoll_fd, nmea_fd );
+
+    LOGE("[mbtk_gnss_api] gnss_nmea_thread running");
+
+    for (;;)
+    {
+        nevents = -1;
+        nevents = epoll_wait( epoll_fd, events, 2, -1 );
+        if (nevents < 0)
+        {
+            if (errno != EINTR)
+            {
+                LOGE("[mbtk_gnss_api] epoll_wait() unexpected error: %s", strerror(errno));
+            }
+            continue;
+        }
+
+        for (ne = 0; ne < nevents; ne++)
+        {
+            if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0)
+            {
+                LOGE("[mbtk_gnss_api] EPOLLERR or EPOLLHUP after epoll_wait()!");
+                return;
+            }
+
+            if ((events[ne].events & EPOLLIN) != 0) 
+            {
+                fd = events[ne].data.fd;
+
+                if (fd == control_fd)
+                {
+                    do {
+                            ret = read( fd, &cmd, 1 );
+                    } while (ret < 0 && errno == EINTR);
+                    if (cmd == 1)
+                    {
+                        epoll_deregister( epoll_fd, control_fd );
+                        epoll_deregister( epoll_fd, nmea_fd );
+                        LOGE("[mbtk_gnss_api] gnss thread quitting on demand");
+                        return NULL;
+                    }
+                }
+                else if (fd == nmea_fd)
+                {
+                    memset(nmea_buf, 0x0, 1024);
+                    len = read(fd, nmea_buf, 1024);
+                    if(len > 0)
+                    {
+                        for(offset = 0; offset < len; offset++)
+                        {
+                            c = nmea_buf[offset];
+                            if(pos == 0 && c != '$')
+                            {
+                                continue;
+                            }
+                            
+                            if (overflow) {
+                                overflow = (c != '\n');
+                                continue;
+                            }
+
+                            if (pos >= (int) sizeof(in)-1 )
+                            {
+                                overflow = 1;
+                                pos      = 0;
+                                continue;
+                            }
+
+                            in[pos] = c;
+                            pos += 1;
+
+                            if (c == '\n')
+                            {
+                                if(nmea_state.callbacks != NULL)
+                                {
+                                    nmea_state.callbacks((void *)in, pos);
+                                }
+                                memset(in, 0x0, pos);
+                                pos = 0;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        LOGE("[mbtk_gnss_api] read() fail:%d, errno = %d\n", len, errno);
+                    }
+                }
+                else
+                {
+                    LOGE("[mbtk_gnss_api] epoll_wait() returned unkown fd %d ?", fd);
+                }
+            }
+        }
+    }
+}
+
+static int mbtk_gnss_nmea_thread_init(void)
+{
+    if(nmea_state.init == 1)
+    {
+        LOGE("[mbtk_gnss_api] nmea thread is open.");
+        return MBTK_RESULT_FAIL;
+    }
+
+    mbtk_gnss_open_port(&nmea_state.fd, MBTK_GNSS_NMEA_PORT, O_RDWR | O_NONBLOCK | O_NOCTTY, 1);
+
+    if (socketpair( AF_LOCAL, SOCK_STREAM, 0, nmea_state.control ) < 0 ) 
+    {
+        LOGE("[mbtk_gnss_api] could not create thread control socket pair: %s", strerror(errno));
+
+        /*close the control socket pair && Retry again.*/
+        if(nmea_state.control[0] > 0)
+        {
+            close( nmea_state.control[0] );
+            nmea_state.control[0] = -1;
+        }
+        
+        if(nmea_state.control[1] > 0)
+        {
+            close( nmea_state.control[1] );
+            nmea_state.control[1] = -1;
+        }
+        return MBTK_RESULT_FAIL;
+    }
+
+    pthread_create(&nmea_state.thread, NULL, gnss_nmea_thread, NULL);
+    if ( !nmea_state.thread )
+    {
+        LOGE("[mbtk_gnss_api] could not create gps thread: %s", strerror(errno));
+        return MBTK_RESULT_FAIL;
+    }
+
+    nmea_state.gnss_msg_state = MBTK_GNSS_MSG_NMEA_INFO;
+    nmea_state.init = 1;
+    return MBTK_RESULT_SUCCESS;
+}
+
+static int mbtk_gnss_nmea_thread_deinit(void)
+{
+    // tell the thread to quit, and wait for it
+    if(nmea_state.init == 1)
+    {
+        char   cmd = 1;
+        void*  dummy = NULL;
+        write( nmea_state.control[0], &cmd, 1 );
+        pthread_join(nmea_state.thread, &dummy);
+
+        // close the control socket pair
+        if(nmea_state.control[0] > 0)
+        {
+            close( nmea_state.control[0] );
+            nmea_state.control[0] = -1;
+        }
+        if(nmea_state.control[1] > 0)
+        {
+            close( nmea_state.control[1] );
+            nmea_state.control[1] = -1;
+        }
+
+        LOGE("[mbtk_gnss_api] %s: deinit", __FUNCTION__);
+
+        // close connection to the QEMU GPS daemon
+        if(nmea_state.fd)
+        {
+            close(nmea_state.fd);
+            nmea_state.fd   = -1;
+        }
+
+        nmea_state.callbacks = NULL;
+        nmea_state.gnss_msg_state = MBTK_GNSS_MSG_NMEA_INFO;
+        nmea_state.init = 0;
+    }
+
+    return MBTK_RESULT_SUCCESS;
+}
+
+int mbtk_invoke_reply_data_cb(const char *service, const char *method, struct blob_attr *msg,
+                         ubus_data_handler_t cb, void *cb_param, int timeout)
+{
+	struct ubus_context *ctx = NULL;
+	int rc = -1;
+	uint32_t id;
+	struct ubus_request req;
+
+    ctx = mbtk_get_ubus_ctx();
+	if(ctx == NULL)
+    {
+		LOGE("[mbtk_gnss_api] mbtk_get_ubus_ctx fail.");
+        return MBTK_RESULT_FAIL;
+    }
+
+	/* Look up the target object id by the object path */
+    rc = ubus_lookup_id(ctx, service, &id);
+	if(rc)
+    {
+        LOGE("[mbtk_gnss_api] ubus_lookup_id fail.rc = [%d]", rc);
+		return MBTK_RESULT_FAIL;
+    }
+
+	rc = ubus_invoke(ctx, id, method, msg, cb, cb_param, timeout);
+    if(rc)
+    {
+        LOGE("[mbtk_gnss_api] ubus_invoke fail.rc = [%d]", rc);
+		return MBTK_RESULT_FAIL;
+    }
+	return MBTK_RESULT_SUCCESS;
+}
+
+ int mbtk_invoke_noreply(const char *service, const char *method, struct blob_attr *msg)
+ {
+    struct ubus_context *ctx;
+    int rc = -1;
+    uint32_t id;
+    struct ubus_request req;
+
+    ctx = mbtk_get_ubus_ctx();
+    if(ctx == NULL)
+    {
+    	LOGE("[mbtk_gnss_api] mbtk_get_ubus_ctx fail.");
+        return MBTK_RESULT_FAIL;
+    }
+    /* Look up the target object id by the object path */
+    rc = ubus_lookup_id(ctx, service, &id);
+    if(rc)
+    {
+        LOGE("[mbtk_gnss_api] ubus_lookup_id fail.rc = [%d]", rc);
+		return MBTK_RESULT_FAIL;
+    }
+
+    rc = ubus_invoke_async(ctx, id, method, msg, &req);
+    if(rc)
+    {
+        LOGE("[mbtk_gnss_api] ubus_invoke_async fail.rc = [%d]", rc);
+		return MBTK_RESULT_FAIL;
+    }
+
+    /* cancel req (on client side) because noreply is needed */
+    ubus_abort_request(ctx, &req);
+    return MBTK_RESULT_SUCCESS;
+ }
+
+/**********************************FUNC***********************************/
+
+/**********************************API***********************************/
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_init(void)
+{
+    int ret = MBTK_RESULT_FAIL;
+
+    ret = mbtk_gnss_ubus_uloop_init();
+    if(ret < 0)
+    {
+        LOGE("[mbtk_gnss_api] mbtk_gnss_uloopinit fail.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    ret = mbtk_gnss_nmea_thread_init();
+    if(ret != 0)
+    {
+        LOGE("[mbtk_gnss_api] mbtk_gnss_nmea_thread_init fail.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+    return MBTK_GNSS_RESULT_SUCCESS;
+}
+
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_deinit(void)
+{
+    mbtk_gnss_nmea_thread_deinit();
+    mbtk_gnss_ubus_uloop_deinit();
+    return MBTK_GNSS_RESULT_SUCCESS;
+}
+
+
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_open(void)
+{
+    if (mbtk_gnss_uloop_init == 0)
+    {
+        LOGE("[mbtk_gnss_api] gnss not init.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+    
+    int ret = -1;
+    MBTK_GNSS_5311_RESULT_TYPE ubus_gnss_result = MBTK_GNSS_RESULT_SUCCESS;
+    uint gps_init_val = MBTK_GNSS_OPEN;
+    struct blob_buf outBlob;
+    memset(&outBlob, 0, sizeof(outBlob));
+    
+    blob_buf_init(&outBlob, 0);
+    blobmsg_add_u32(&outBlob, MBTK_GNSS_UBUS_INIT_PARAM, gps_init_val);
+
+    //UBUS_STATUS_OK
+    ret = mbtk_invoke_reply_data_cb(MBTK_GNSS_UBUS_SERVER, MBTK_GNSS_UBUS_INIT, outBlob.head,
+                                    (ubus_data_handler_t *)mbtk_gnss_ubus_result_callback, &ubus_gnss_result, 8000);
+    blob_buf_free(&outBlob);
+    if (ret != 0)
+    {
+        LOGE("[mbtk_gnss_api] mbtk_invoke_reply_data_cb fail.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    if(ubus_gnss_result != MBTK_GNSS_RESULT_OPEN_SUCCESS)
+    {
+        LOGE("[mbtk_gnss_api] ubus_gnss_result = [%d].", ubus_gnss_result);
+        return ubus_gnss_result;
+    }
+
+    
+    mbtk_gnss_status = MBTK_GNSS_OPEN;
+    return MBTK_GNSS_RESULT_SUCCESS;
+}
+
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_close(void)
+{
+    if (mbtk_gnss_uloop_init == 0)
+    {
+        LOGE("[mbtk_gnss_api] gnss not init.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    int ret = -1;
+    MBTK_GNSS_5311_RESULT_TYPE ubus_gnss_result = MBTK_GNSS_RESULT_SUCCESS;
+    uint gps_init_val = MBTK_GNSS_CLOSE;
+    struct blob_buf outBlob;
+    memset(&outBlob, 0, sizeof(outBlob));
+
+    blob_buf_init(&outBlob, 0);
+    blobmsg_add_u32(&outBlob, MBTK_GNSS_UBUS_INIT_PARAM, gps_init_val);
+
+    //UBUS_STATUS_OK
+    ret = mbtk_invoke_reply_data_cb(MBTK_GNSS_UBUS_SERVER, MBTK_GNSS_UBUS_INIT, outBlob.head,
+                                    (ubus_data_handler_t *)mbtk_gnss_ubus_result_callback, &ubus_gnss_result, 8000);
+    blob_buf_free(&outBlob);
+    if (ret != 0)
+    {
+        LOGE("[mbtk_gnss_api] mbtk_invoke_reply_data_cb fail.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    if(ubus_gnss_result != MBTK_GNSS_RESULT_CLOSE_SUCCESS)
+    {
+        LOGE("[mbtk_gnss_api] ubus_gnss_result = [%d].", ubus_gnss_result);
+        return ubus_gnss_result;
+    }
+
+    
+
+    mbtk_gnss_status = MBTK_GNSS_CLOSE;
+    return MBTK_GNSS_RESULT_SUCCESS;
+}
+
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_sleep(void)
+{
+    if (mbtk_gnss_uloop_init == 0)
+    {
+        LOGE("[mbtk_gnss_api] gnss not init.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    if(mbtk_gnss_status == MBTK_GNSS_CLOSE)
+    {
+        LOGE("[mbtk_gnss_api] gnss not open.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    int ret = -1;
+    struct blob_buf outBlob;
+    unsigned int gps_sleep_val = MBTK_GNSS_SLEEP;
+    memset(&outBlob, 0, sizeof(outBlob));
+    
+    blob_buf_init(&outBlob, 0);
+    blobmsg_add_u32(&outBlob, MBTK_GNSS_UBUS_SLEEP_PARAM, (unsigned int)gps_sleep_val);
+
+    ret = mbtk_invoke_noreply(MBTK_GNSS_UBUS_SERVER, MBTK_GNSS_UBUS_SLEEP, outBlob.head);
+    blob_buf_free(&outBlob);
+    if (ret != 0)
+    {
+        LOGE("[mbtk_gnss_api] mbtk_invoke_noreply fail.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    return MBTK_GNSS_RESULT_SUCCESS;
+}
+
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_wakeup(void)
+{
+    if (mbtk_gnss_uloop_init == 0)
+    {
+        LOGE("[mbtk_gnss_api] gnss not init.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    if(mbtk_gnss_status == MBTK_GNSS_CLOSE)
+    {
+        LOGE("[mbtk_gnss_api] gnss not open.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    int ret = -1;
+    struct blob_buf outBlob;
+    unsigned int gps_sleep_val = MBTK_GNSS_WAKEUP;
+    memset(&outBlob, 0, sizeof(outBlob));
+    
+    blob_buf_init(&outBlob, 0);
+    blobmsg_add_u32(&outBlob, MBTK_GNSS_UBUS_SLEEP_PARAM, (unsigned int)gps_sleep_val);
+
+    ret = mbtk_invoke_noreply(MBTK_GNSS_UBUS_SERVER, MBTK_GNSS_UBUS_SLEEP, outBlob.head);
+    blob_buf_free(&outBlob);
+    if (ret != 0)
+    {
+        LOGE("[mbtk_gnss_api] mbtk_invoke_noreply fail.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    return MBTK_GNSS_RESULT_SUCCESS;
+}
+
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_param_config(const char *param_buf, int param_buf_len)
+{
+    if (mbtk_gnss_uloop_init == 0)
+    {
+        LOGE("[mbtk_gnss_api] gnss not init.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    if(mbtk_gnss_status == MBTK_GNSS_CLOSE)
+    {
+        LOGE("[mbtk_gnss_api] gnss not open.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    if(param_buf == NULL || param_buf_len <= 0)
+    {
+        LOGE("[mbtk_gnss_api] param is error.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+    
+    int ret = -1;
+    struct blob_buf outBlob;
+    memset(&outBlob, 0, sizeof(outBlob));
+
+    LOGE("[mbtk_gnss_api] set command [%s].", param_buf);
+    blob_buf_init(&outBlob, 0);
+    blobmsg_add_string(&outBlob, MBTK_GNSS_UBUS_SET_PARAM, param_buf);
+
+    ret = mbtk_invoke_noreply(MBTK_GNSS_UBUS_SERVER, MBTK_GNSS_UBUS_SET, outBlob.head);
+    blob_buf_free(&outBlob);
+    if (ret != 0)
+    {
+        LOGE("[mbtk_gnss_api] mbtk_invoke_noreply fail.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    return MBTK_GNSS_RESULT_SUCCESS;
+}
+
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_get_status(const char *status_buf, int status_buf_len, int *get_status_len)
+{
+    if (mbtk_gnss_uloop_init == 0)
+    {
+        LOGE("[mbtk_gnss_api] gnss not init.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    if(mbtk_gnss_status == MBTK_GNSS_CLOSE)
+    {
+        LOGE("[mbtk_gnss_api] gnss not open.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    int ret = -1;
+    char status[128] = {0};
+    int status_len = 0;
+
+    ret = mbtk_invoke_reply_data_cb(MBTK_GNSS_UBUS_SERVER, MBTK_GNSS_UBUS_GET_STATUS, NULL, mbtk_gnss_state_get_callback, status, 4000);
+    if (ret != 0)
+    {
+        LOGE("[mbtk_gnss_api] mbtk_invoke_reply_data_cb fail.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    status_len = strlen(status);
+    if(status_len > 0 && status_len < status_buf_len)
+    {
+        memcpy(status_buf, status, status_len);
+        *get_status_len = status_len;
+    }
+    else
+    {
+        LOGE("[mbtk_gnss_api] status_len[%d] error.", status_len);
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    return MBTK_GNSS_RESULT_SUCCESS;
+}
+
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_set_nmea_out_type(MBTK_GNSS_MSG_INFO_TYPE type)
+{
+    if(mbtk_gnss_uloop_init == 0)
+    {
+        LOGE("[mbtk_gnss_api] gnss not init.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    if(type == MBTK_GNSS_MSG_LOCATION_INFO)
+    {
+        nmea_state.gnss_msg_state = type;
+    }
+    else if(type == MBTK_GNSS_MSG_NMEA_INFO)
+    {
+        nmea_state.gnss_msg_state = type;
+    }
+    else
+    {
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+    
+    return MBTK_GNSS_RESULT_SUCCESS;
+}
+
+
+MBTK_GNSS_5311_RESULT_TYPE mbtk_gnss_add_nmea_out_func(mbtk_gnss_nmea_func_t cb)
+{
+    if(mbtk_gnss_uloop_init == 0)
+    {
+        LOGE("[mbtk_gnss_api] gnss not init.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+
+    if(cb == NULL)
+    {
+        LOGE("[mbtk_gnss_api] cb is NULL.");
+        return MBTK_GNSS_RESULT_FAIL;
+    }
+    nmea_state.callbacks = cb;
+
+    return MBTK_GNSS_RESULT_SUCCESS;
+}
+
+
+/**********************************API***********************************/
+
+#endif