Fix gnss 8122 and IPC socket.

Change-Id: Id413efb4dd8df3e5a52333cc0c1400db7f84ad9f
diff --git a/mbtk/mbtk_gnssd/Makefile b/mbtk/mbtk_gnssd/Makefile
index 70ac7ef..0cefa40 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_ubus.c gnss_utils.c gnss_hd8122.c
+LOCAL_SRC_FILES = gnss_main.c gnss_nmea.c gnss_6228.c gnss_ipc.c gnss_utils.c gnss_hd8122.c
 OBJS = $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(LOCAL_SRC_FILES)))
 $(info OBJS = $(OBJS))
 
diff --git a/mbtk/mbtk_gnssd/gnss_hd8122.c b/mbtk/mbtk_gnssd/gnss_hd8122.c
index dc36267..57b2e30 100755
--- a/mbtk/mbtk_gnssd/gnss_hd8122.c
+++ b/mbtk/mbtk_gnssd/gnss_hd8122.c
@@ -27,10 +27,91 @@
 
 #define UART_BITRATE_NMEA_DEF_FW    115200   // Default bitrate.
 #define GNSS_POWER_GPIO 43
+#define GNSS_SET_TIMEOUT           3000     // 3s
+#define GNSS_PACK_BUFF_SIZE           1024
+
 
 static pthread_cond_t read_cond;
 static pthread_mutex_t read_mutex;
+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 uint16 fletcher16(const uint8_t* data, int data_len) {
+    uint16_t sum1 = 0;
+    uint16_t sum2 = 0;
+    int index;
+
+    for (index = 0; index < data_len; ++index ) {
+        sum1 = (sum1 + data[index]) % 0xff;
+        sum2 = (sum2 + sum1) % 0xff;
+    }
+
+    // ???
+    sum2--;
+
+    return (sum2 << 8) | sum1;
+}
+
+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 int pack_create(hd8122_id_type_enum id_type, uint8 id, uint16 data_len, const uint8 *data, uint8 *pack, int pack_len)
+{
+    if(pack == NULL || pack_len < HD8122_PACK_LEN_MIN) {
+        return -1;
+    }
+    memset(pack, 0, pack_len);
+    uint8 *data_ptr = pack;
+    data_ptr += uint16_2_byte(HD8122_PACK_HEAD, data_ptr, false);
+    *data_ptr++ = (uint8)id_type;
+    *data_ptr++ = id;
+    data_ptr += uint16_2_byte(data_len, data_ptr, false);
+    if(data_len > 0) {
+        memcpy(data_ptr, data, data_len);
+        data_ptr += data_len;
+    }
+    data_ptr += uint16_2_byte(fletcher16(pack + 2, 4 + data_len), data_ptr, false);
+    return (data_ptr - pack);
+}
+
+static void gnss_cmd_rsp_process(const void *data, int data_len) {
+    const char *ptr = (const char*)data;
+    log_hex("RSP", data, data_len);
+    if(0)
+    {
+        mbtk_timer_clear();
+
+        pthread_mutex_lock(&read_mutex);
+        pthread_cond_signal(&read_cond);
+        pthread_mutex_unlock(&read_mutex);
+    }
+}
+
+static gnss_err_enum gnss_8122_reset(int fd, int reset)
+{
+    uint8 buff[GNSS_PACK_BUFF_SIZE];
+    LOGD("RESET");
+    int len = pack_create(HD8122_ID_TYPE_CFG, HD8122_ID_CFG_SIMPLERST, 1, (uint8*)(&reset), buff, sizeof(buff));
+    if(len <= 0) {
+        LOGE("pack_create() fail.");
+        return GNSS_ERR_ARG;
+    }
+    log_hex("PACK", buff, len);
+    gnss_write(fd, buff, len);
+    return GNSS_ERR_OK;
+}
 
 int gnss_8122_dev_open()
 {
@@ -61,9 +142,55 @@
     return 0;
 }
 
+void gnss_8122_set_cb(const void *data, int data_len)
+{
+    const char *buff = (const char*)data;
+    if(setting_busy) {
+        gnss_cmd_rsp_process(data, data_len);
+    }
+}
 
 gnss_err_enum gnss_8122_set(int fd, const char *cmd, void *cmd_rsp, int cmd_rsp_len)
 {
-    return GNSS_ERR_OK;
+    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", 5) == 0) {
+            gnss_set_result = gnss_8122_reset(fd, atoi(cmd + 6));
+            if(gnss_set_result != GNSS_ERR_OK) {
+                goto set_fail;
+            }
+            should_wait_rsp = FALSE;
+        }
+        else
+        {
+            LOGW("Unknown cmd:%s", cmd);
+            gnss_set_result = GNSS_ERR_UNSUPPORT;
+            goto set_fail;
+        }
+
+set_success:
+        if(should_wait_rsp) {
+            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_hd8122.h b/mbtk/mbtk_gnssd/gnss_hd8122.h
index ca938f3..fb9c1b8 100755
--- a/mbtk/mbtk_gnssd/gnss_hd8122.h
+++ b/mbtk/mbtk_gnssd/gnss_hd8122.h
@@ -11,6 +11,96 @@
 #include "gnss_info.h"
 #include "mbtk_type.h"
 
+#define HD8122_PACK_LEN_MIN 8
+#define HD8122_PACK_HEAD 0xD9F1
+
+typedef enum {
+    HD8122_ID_TYPE_NAV = 0x01,
+    HD8122_ID_TYPE_ACK = 0x05,
+    HD8122_ID_TYPE_CFG = 0x06,
+    HD8122_ID_TYPE_MON = 0x0A,
+    HD8122_ID_TYPE_AID = 0x0B
+} hd8122_id_type_enum;
+
+typedef enum {
+    HD8122_ID_NAV_POSECEF = 0x01,
+    HD8122_ID_NAV_POSLLH = 0x02,
+    HD8122_ID_NAV_DOP = 0x04,
+    HD8122_ID_NAV_TIME = 0x05,
+    HD8122_ID_NAV_VELECEF = 0x11,
+    HD8122_ID_NAV_VELNED = 0x12,
+    HD8122_ID_NAV_TIMEUTC = 0x21,
+    HD8122_ID_NAV_CLOCK = 0x22,
+    HD8122_ID_NAV_CLOCK2 = 0x23,
+    HD8122_ID_NAV_PVERR = 0x26,
+    HD8122_ID_NAV_SVINFO = 0x30,
+    HD8122_ID_NAV_SVSTATE = 0x32,
+    HD8122_ID_NAV_AUTO = 0xC0,
+    HD8122_ID_NAV_PVT = 0xC1
+} hd8122_id_nav_enum;
+
+typedef enum {
+    HD8122_ID_ACK_NAK = 0x00,
+    HD8122_ID_ACK_ACK = 0x01
+} hd8122_id_ack_enum;
+
+typedef enum {
+    HD8122_ID_CFG_PRT = 0x00,
+    HD8122_ID_CFG_MSG = 0x01,
+    HD8122_ID_CFG_PPS = 0x07,
+    HD8122_ID_CFG_CFG = 0x09,
+    HD8122_ID_CFG_DOP = 0x0A,
+    HD8122_ID_CFG_ELEV = 0x0B,
+    HD8122_ID_CFG_NAVSAT = 0x0C,
+    HD8122_ID_CFG_HEIGHT = 0x0D,
+    HD8122_ID_CFG_SBAS = 0x0E,
+    HD8122_ID_CFG_SPDHOLD = 0x0F,
+    HD8122_ID_CFG_EPHSAVE = 0x10,
+    HD8122_ID_CFG_NUMSV = 0x11,
+    HD8122_ID_CFG_SURVEY = 0x12,
+    HD8122_ID_CFG_FIXEDLLA = 0x13,
+    HD8122_ID_CFG_FIXEDECEF = 0x14,
+    HD8122_ID_CFG_ANTIJAM = 0x15,
+    HD8122_ID_CFG_BDGEO = 0x16,
+    HD8122_ID_CFG_CARRSMOOTH = 0x17,
+    HD8122_ID_CFG_GEOFENCE = 0x18,
+    HD8122_ID_CFG_SIMPLERST = 0x40,
+    HD8122_ID_CFG_SLEEP = 0x41,
+    HD8122_ID_CFG_PWRCTL = 0x42,
+    HD8122_ID_CFG_PWRCTL2 = 0x44,
+    HD8122_ID_CFG_NMEAVER = 0x43,
+    HD8122_ID_CFG_FWUP = 0x50
+} hd8122_id_cfg_enum;
+
+typedef enum {
+    HD8122_ID_MON_VER = 0x04,
+    HD8122_ID_MON_INFO = 0x05,
+    HD8122_ID_MON_TRKCHAN = 0x08,
+    HD8122_ID_MON_RCVCLK = 0x09,
+    HD8122_ID_MON_CWI = 0x0A,
+} hd8122_id_mon_enum;
+
+typedef enum {
+    HD8122_ID_AID_INI = 0x01,
+    HD8122_ID_AID_POS = 0x10,
+    HD8122_ID_AID_TIME = 0x11,
+    HD8122_ID_AID_PEPH_GPS = 0x32,
+    HD8122_ID_AID_PEPH_BDS = 0x33,
+    HD8122_ID_AID_PALM_GPS = 0x22,
+    HD8122_ID_AID_PALM_BD = 0x23,
+    HD8122_ID_AID_PALM_GLN = 0x24,
+    HD8122_ID_AID_PALM_GAL = 0x25,
+    HD8122_ID_AID_PALM_QZSS = 0x26
+} hd8122_id_aid_enum;
+
+typedef struct {
+    uint16 head;
+    uint8 id_type;
+    uint8 id;
+    uint16 data_len;
+    uint8 *data;
+} hd8122_pack_info_t;
+
 int gnss_8122_dev_open();
 
 int gnss_8122_dev_close();
@@ -25,7 +115,7 @@
 
 gnss_err_enum gnss_8122_set(int fd, const char *cmd, void *cmd_rsp, int cmd_rsp_len);
 
-//void gnss_8122_set_cb(const void *data, int data_len);
+void gnss_8122_set_cb(const void *data, int data_len);
 
 #endif /* _GNSS_HD8122_H */
 
diff --git a/mbtk/mbtk_gnssd/gnss_info.h b/mbtk/mbtk_gnssd/gnss_info.h
index a292db7..a6b64c9 100755
--- a/mbtk/mbtk_gnssd/gnss_info.h
+++ b/mbtk/mbtk_gnssd/gnss_info.h
@@ -25,6 +25,7 @@
     GNSS_ERR_TIMEOUT,
     GNSS_ERR_ARG,
     GNSS_ERR_CHECKSUM,
+    GNSS_ERR_SET_BUSY,
 
     GNSS_ERR_UNKNOWN
 } gnss_err_enum;
@@ -74,4 +75,10 @@
     gnss_set_cb_func gnss_set_cb;
 } gnss_info_t;
 
+int gnss_init(uint32 print_port);
+
+int gnss_deinit();
+
+int gnss_set(const void* buf, unsigned int buf_len, void *cmd_rsp, int cmd_rsp_len);
+
 #endif /* _GNSS_INFO_H */
diff --git a/mbtk/mbtk_gnssd/gnss_ipc.c b/mbtk/mbtk_gnssd/gnss_ipc.c
new file mode 100755
index 0000000..a8dece8
--- /dev/null
+++ b/mbtk/mbtk_gnssd/gnss_ipc.c
@@ -0,0 +1,276 @@
+/*
+*    gnss_ipc.c
+*
+*    MBTK GNSS IPC service source.
+*
+*/
+/******************************************************************************
+
+                          EDIT HISTORY FOR FILE
+
+  WHEN        WHO       WHAT,WHERE,WHY
+--------    --------    -------------------------------------------------------
+2024/6/15     LiuBin      Initial version
+
+******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <sys/epoll.h>
+
+#include "mbtk_log.h"
+#include "mbtk_type.h"
+#include "gnss_info.h"
+
+#define GNSS_SOCK_PATH "/tmp/mbtk_gnss_sock"
+#define SOCK_CLIENT_MAX 3
+#define EPOLL_LISTEN_MAX 100
+
+static int sock_listen_fd = -1;
+static int sock_cli_fds[SOCK_CLIENT_MAX];
+
+int gnss_write(int fd, const void* buf, unsigned int buf_len);
+
+static int gnss_cli_fd_find(int fd)
+{
+    int i = 0;
+    while(i < SOCK_CLIENT_MAX) {
+        if(fd == sock_cli_fds[i])
+            return i;
+        i++;
+    }
+
+    return -1;
+}
+
+static void gnss_msg_process(int fd, const char *msg, int msg_len)
+{
+    // gnss_init:x
+    if(memcmp(msg, "gnss_init", 9) == 0) {
+        int init_mode = atoi(msg + 10);
+        LOGD("init_mode=%d", init_mode);
+        int ret = 0;
+        if(init_mode == 0) { // Close gnss.
+            ret = gnss_deinit();
+        } else {
+            if(((GNSS_PRINT_PORT_UART1 | GNSS_PRINT_PORT_USB_NMEA | GNSS_PRINT_PORT_USB_AT | GNSS_PRINT_PORT_TTY_AT) & init_mode) == init_mode) {
+                ret = gnss_init(init_mode);
+            } else { // ARG error, no print nmea.
+                ret = gnss_init(0);
+            }
+        }
+
+        char rsp[100] = {0};
+        sprintf(rsp, "gnss_init:%d", ret);
+        gnss_write(fd, rsp, strlen(rsp));
+    } else if(memcmp(msg, "gnss_deinit", 11) == 0) {
+        LOGD("gnss_deinit");
+        int ret = gnss_deinit();
+
+        char rsp[100] = {0};
+        sprintf(rsp, "gnss_deinit:%d", ret);
+        gnss_write(fd, rsp, strlen(rsp));
+    } else {
+        LOGW("Unknown gnss msg : %s", msg);
+    }
+}
+
+static void* gnss_ser_pthread(void* arg)
+{
+    UNUSED(arg);
+    int epoll_fd = epoll_create(SOCK_CLIENT_MAX + 1);
+    if(epoll_fd < 0)
+    {
+        LOGE("epoll_create() fail[%d].", errno);
+        return NULL;
+    }
+
+    int i = 0;
+    while(i < SOCK_CLIENT_MAX) {
+        sock_cli_fds[i++] = -1;
+    }
+
+    uint32 event = EPOLLIN | EPOLLET;
+    struct epoll_event ev;
+    ev.data.fd = sock_listen_fd;
+    ev.events = event; //EPOLLIN | EPOLLERR | EPOLLET;
+    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock_listen_fd, &ev);
+
+    int nready = -1;
+    struct epoll_event epoll_events[EPOLL_LISTEN_MAX];
+    while(1)
+    {
+        nready = epoll_wait(epoll_fd, epoll_events, EPOLL_LISTEN_MAX, -1);
+        if(nready > 0)
+        {
+            for(i = 0; i < nready; i++)
+            {
+                LOGD("fd[%d] event = %x",epoll_events[i].data.fd, epoll_events[i].events);
+                if(epoll_events[i].events & EPOLLHUP)   // Client Close.
+                {
+                    int index = gnss_cli_fd_find(epoll_events[i].data.fd);
+                    if(index != -1)
+                    {
+                        memset(&ev,0,sizeof(struct epoll_event));
+                        ev.data.fd = epoll_events[i].data.fd;
+                        ev.events = EPOLLIN | EPOLLERR | EPOLLET;
+                        epoll_ctl(epoll_fd, EPOLL_CTL_DEL, epoll_events[i].data.fd, &ev);
+
+                        close(epoll_events[i].data.fd);
+                        sock_cli_fds[index] = -1;
+                    }
+                    else
+                    {
+                        LOGE("Unknown client[fd = %d].", epoll_events[i].data.fd);
+                    }
+                }
+                else if(epoll_events[i].events & EPOLLIN)
+                {
+                    if(epoll_events[i].data.fd == sock_listen_fd)   // New clients connected.
+                    {
+                        int client_fd = -1;
+                        while(1)
+                        {
+                            struct sockaddr_in cliaddr;
+                            socklen_t clilen = sizeof(cliaddr);
+                            client_fd = accept(epoll_events[i].data.fd, (struct sockaddr *) &cliaddr, &clilen);
+                            if(client_fd <= 0)
+                            {
+                                if(errno == EAGAIN)
+                                {
+                                    LOGE("All client connect get.");
+                                }
+                                else
+                                {
+                                    LOGE("accept() error[%d].", errno);
+                                }
+                                break;
+                            } else {
+                                i = 0;
+                                while(i < SOCK_CLIENT_MAX) {
+                                    if(sock_cli_fds[i] <= 0) {
+                                        sock_cli_fds[i] = client_fd;
+                                        break;
+                                    }
+                                    i++;
+                                }
+
+                                if(i >= SOCK_CLIENT_MAX) {
+                                    LOGE("Client is full.");
+                                    break;
+                                }
+                            }
+                            // Set O_NONBLOCK
+                            int flags = fcntl(client_fd, F_GETFL, 0);
+                            if (flags > 0)
+                            {
+                                flags |= O_NONBLOCK;
+                                if (fcntl(client_fd, F_SETFL, flags) < 0)
+                                {
+                                    LOGE("Set flags error:%d", errno);
+                                }
+                            }
+
+                            memset(&ev,0,sizeof(struct epoll_event));
+                            ev.data.fd = client_fd;
+                            ev.events = event;//EPOLLIN | EPOLLERR | EPOLLET;
+                            epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev);
+                        }
+                    }
+                    else if(epoll_events[i].data.fd > 0)    // Client data arrive.
+                    {
+                        char buff[1024] = {0};
+                        int len = read(epoll_events[i].data.fd, buff, sizeof(buff));
+                        if(len > 0) {
+                            gnss_msg_process(epoll_events[i].data.fd, buff, len);
+                        }
+                    }
+                    else
+                    {
+                        LOGE("Unknown socket : %d", epoll_events[i].data.fd);
+                    }
+                }
+                else
+                {
+                    LOGE("Unknown event : %x", epoll_events[i].events);
+                }
+            }
+        }
+        else
+        {
+            LOGE("epoll_wait() fail[%d].", errno);
+        }
+    }
+
+    return NULL;
+}
+
+
+int gnss_ipc_service_start()
+{
+    struct sockaddr_un server_addr;
+    sock_listen_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+    if(sock_listen_fd < 0)
+    {
+        LOGE("socket() fail[%d].", errno);
+        return -1;
+    }
+
+    // Set O_NONBLOCK
+    int flags = fcntl(sock_listen_fd, F_GETFL, 0);
+    if (flags < 0)
+    {
+        LOGE("Get flags error:%d", errno);
+        goto error;
+    }
+    flags |= O_NONBLOCK;
+    if (fcntl(sock_listen_fd, F_SETFL, flags) < 0)
+    {
+        LOGE("Set flags error:%d", errno);
+        goto error;
+    }
+
+    unlink(GNSS_SOCK_PATH);
+    memset(&server_addr, 0, sizeof(struct sockaddr_un));
+    server_addr.sun_family = AF_LOCAL;
+    strcpy(server_addr.sun_path, GNSS_SOCK_PATH);
+    if(bind(sock_listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)))
+    {
+        LOGE("bind() fail[%d].", errno);
+        goto error;
+    }
+
+    if(listen(sock_listen_fd, SOCK_CLIENT_MAX))
+    {
+        LOGE("listen() fail[%d].", errno);
+        goto error;
+    }
+
+    pthread_t pid;
+    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 error;
+    }
+
+    if(pthread_create(&pid, &thread_attr, gnss_ser_pthread, NULL))
+    {
+        LOGE("pthread_create() fail.");
+        goto error;
+    }
+
+    LOGD("GNSS IPC service is running...");
+    return 0;
+error:
+    close(sock_listen_fd);
+    return -1;
+}
+
diff --git a/mbtk/mbtk_gnssd/gnss_main.c b/mbtk/mbtk_gnssd/gnss_main.c
index 3922f8f..b3ab5c6 100755
--- a/mbtk/mbtk_gnssd/gnss_main.c
+++ b/mbtk/mbtk_gnssd/gnss_main.c
@@ -17,6 +17,7 @@
 #include "gnss_hd8122.h"
 
 #define GNSS_DEBUG 1
+#define GNSS_UBUS_ENABLE 0
 
 #define GNSS_TAG "MBTK_GNSS"
 #define GNSS_BUFF_SIZE 2048
@@ -36,7 +37,12 @@
 
 gnss_info_t gnss_info;
 
+#if GNSS_UBUS_ENABLE
 struct ubus_context *gnss_ubus_init(void);
+#else
+int gnss_ipc_service_start();
+#endif
+
 int gnss_init_config(int fd);
 
 static char gnss_buff[GNSS_BUFF_SIZE*2] = {0};
@@ -742,7 +748,7 @@
         gnss_info.gnss_fw_dl = gnss_8122_fw_dl;
         gnss_info.gnss_dl_read_cb = NULL;
         gnss_info.gnss_set = gnss_8122_set;
-        gnss_info.gnss_set_cb = NULL;
+        gnss_info.gnss_set_cb = gnss_8122_set_cb;
     } else {
         LOGE("No support : %s", argv[1]);
         return -1;
@@ -758,12 +764,23 @@
     }
 
     // Init ubus and waitting IPC commands.
+#if GNSS_UBUS_ENABLE
     if(gnss_ubus_init()) {
         LOGD("main() run...");
         uloop_run();
     } else {
         LOGE("gnss_ubus_init() fail.");
     }
+#else
+    if(!gnss_ipc_service_start()) {
+        LOGD("main() run...");
+        while(1) {
+            sleep(24 * 60 * 60);
+        }
+    } else {
+        LOGE("gnss_ipc_service_start() fail.");
+    }
+#endif
 
     LOGD("main() exit.");
     return 0;
diff --git a/mbtk/mbtk_gnssd/gnss_ubus.c b/mbtk/mbtk_gnssd/gnss_ubus.c
index 30de33a..ff877a1 100755
--- a/mbtk/mbtk_gnssd/gnss_ubus.c
+++ b/mbtk/mbtk_gnssd/gnss_ubus.c
@@ -14,10 +14,6 @@
 //static struct blob_buf b;
 static struct blob_buf gps_blob;
 
-int gnss_init(uint32 print_port);
-int gnss_deinit();
-int gnss_set(const void* buf, unsigned int buf_len, void *cmd_rsp, int cmd_rsp_len);
-
 const struct blobmsg_policy gnss_init_policy[] ={
 	[0] = {
 		.name = "gnss_init_param",
diff --git a/mbtk/test/others/mbtk_gnss_cli.c b/mbtk/test/others/mbtk_gnss_cli.c
new file mode 100755
index 0000000..d830e0c
--- /dev/null
+++ b/mbtk/test/others/mbtk_gnss_cli.c
@@ -0,0 +1,140 @@
+/*
+*    gnss_ipc.c
+*
+*    MBTK GNSS IPC service source.
+*
+*/
+/******************************************************************************
+
+                          EDIT HISTORY FOR FILE
+
+  WHEN        WHO       WHAT,WHERE,WHY
+--------    --------    -------------------------------------------------------
+2024/6/15     LiuBin      Initial version
+
+******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <sys/epoll.h>
+
+#include "mbtk_log.h"
+#include "mbtk_type.h"
+
+#define GNSS_SOCK_PATH "/tmp/mbtk_gnss_sock"
+
+static int sock_listen_fd = -1;
+
+typedef enum {
+    GNSS_CMD_INIT = 0,
+    GNSS_CMD_DEINIT
+} gnss_cmd_enum;
+
+static void help()
+{
+    printf("gnss_cli gnss_init xxx\n");
+    printf("gnss_cli gnss_deinit\n");
+}
+
+static int cmd_process(gnss_cmd_enum cmd, void *arg)
+{
+    if(sock_listen_fd < 0) {
+        sock_listen_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+        if(sock_listen_fd < 0)
+        {
+            printf("socket() fail[%d].\n", errno);
+            return -1;
+        }
+
+        struct sockaddr_un cli_addr;
+        memset(&cli_addr, 0, sizeof(cli_addr));
+        cli_addr.sun_family = AF_LOCAL;
+        strcpy(cli_addr.sun_path, GNSS_SOCK_PATH);
+        if(connect(sock_listen_fd, (struct sockaddr *)&cli_addr, sizeof(cli_addr)))
+        {
+            printf("connect() fail[%d].\n", errno);
+            close(sock_listen_fd);
+            sock_listen_fd = -1;
+            return -1;
+        }
+    }
+
+    char buff[100] = {0};
+    if(cmd == GNSS_CMD_INIT) {
+        if(arg) {
+            int type = atoi((char*)arg);
+            sprintf(buff, "gnss_init:%d", type);
+        } else {
+            return -1;
+        }
+    } else if(cmd == GNSS_CMD_DEINIT) {
+        sprintf(buff, "gnss_deinit");
+    } else {
+        printf("Unknown cmd.\n");
+        return -1;
+    }
+
+    write(sock_listen_fd, buff, strlen(buff));
+
+    int len = 0;
+    while(1) {
+        memset(buff, 0, sizeof(buff));
+        len = read(sock_listen_fd, buff, sizeof(buff));
+        if(len > 0) {
+            printf("RSP : %s\n", buff);
+            if(cmd == GNSS_CMD_INIT) {
+                if(memcmp(buff, "gnss_init", 9) == 0) {
+                    return atoi(buff + 10);
+                } else {
+                    printf("gnss_init response error.\n");
+                    return -1;
+                }
+            } else if(cmd == GNSS_CMD_DEINIT) {
+                if(memcmp(buff, "gnss_deinit", 11) == 0) {
+                    return atoi(buff + 12);
+                } else {
+                    printf("gnss_deinit response error.\n");
+                    return -1;
+                }
+            } else {
+                printf("Unknown response.\n");
+                return -1;
+            }
+        } else {
+            printf("read = %d:errno = %d\n", len, errno);
+        }
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    int ret = 0;
+    if(argc == 2) {
+        if(strcmp(argv[1], "gnss_deinit")) {
+            help();
+            return -1;
+        }
+
+        ret = cmd_process(GNSS_CMD_DEINIT, NULL);
+    } else if(argc == 3) {
+        if(strcmp(argv[1], "gnss_init")) {
+            help();
+            return -1;
+        }
+
+        ret = cmd_process(GNSS_CMD_INIT, argv[2]);
+    } else {
+        help();
+        return -1;
+    }
+
+    printf("Result : %d\n", ret);
+    return 0;
+}
+