Fix gnss 8122 and IPC socket.

Change-Id: Id413efb4dd8df3e5a52333cc0c1400db7f84ad9f
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;
+}
+