[Feature] add GA346 baseline version

Change-Id: Ic62933698569507dcf98240cdf5d9931ae34348f
diff --git a/src/connectivity/gps/2.0/geofenceinf_example/geofenceinf.c b/src/connectivity/gps/2.0/geofenceinf_example/geofenceinf.c
new file mode 100755
index 0000000..c240d9f
--- /dev/null
+++ b/src/connectivity/gps/2.0/geofenceinf_example/geofenceinf.c
@@ -0,0 +1,1166 @@
+#include <string.h> //strstr

+#include <dirent.h>

+#include <sys/stat.h> //mkdir

+#include <stdio.h>

+#include <stdlib.h>

+#include <errno.h>

+#include <sys/time.h>

+#include <time.h>

+#include <stddef.h>  // offsetof

+#include <stdarg.h>

+#include <unistd.h>  // usleep

+#include <sys/socket.h>

+#include <fcntl.h>

+#include <arpa/inet.h>  // inet_addr

+#include <sys/un.h>  // struct sockaddr_un

+#include <pthread.h>

+#include <sys/epoll.h>

+#include <signal.h>

+#include <semaphore.h>

+#include <signal.h> //struct sigevent

+#include <string.h> //memset, strncpy

+#include <netdb.h> //struct addrinfo

+#include <sys/types.h> //gettid

+#include <netinet/in.h> //struct sockaddr_in

+#include <netinet/tcp.h> //TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT

+#include <netinet/ip.h> //IPTOS_LOWDELAY

+#include <sys/epoll.h> //epoll_create

+#include <semaphore.h> //sem_t

+#include <inttypes.h> //PRId64

+#include <stdbool.h>

+#include "geofence.h"

+//------------------MTK LBS Utility---------------------------------------------------

+#ifndef LOGD

+#define LOGD(...)   { printf(__VA_ARGS__); printf("\n"); fflush(stdout); }

+#define LOGW(...)   { printf("\E[1;35;40m"); printf(__VA_ARGS__); printf("\E[0m"); printf("\n"); fflush(stdout); }

+#define LOGE(...)   { printf("\E[1;31;40m"); printf(__VA_ARGS__); printf("\E[0m"); printf("\n"); fflush(stdout); }

+#define LOGI(...)   { printf("\E[1;35;40m"); printf(__VA_ARGS__); printf("\E[0m"); printf("\n"); fflush(stdout); }

+#endif

+

+#define GEOFENCEADP_MNL_TCP_DATA      "mtk_geofenceadp_mnl_data"

+#define GEOFENCEADP_MNL_TCP_CONTROL   "mtk_geofenceadp_mnl_control"

+

+//#define AT_COMMAND_PRINT

+

+#define MTK_ADD_GEOFENCE_SUCCESS   0

+#define MTK_ADD_GEOFENCE_ERROR    -1

+#define MTK_ADD_GEOFENCE_INSUFFICIENT_MEM -2

+#define MTK_ADD_GEOFENCE_TOO_MANY -3

+

+#define MNLD_STRNCPY(dst,src,size) do{\

+                                       strncpy((char *)(dst), (src), (size - 1));\

+                                      (dst)[size - 1] = '\0';\

+                                     }while(0)

+

+#define GEOFENCE_BUFF_SIZE   (1 * 1024)

+#define GEOFENCE_DATAPATH_SIZE   (10*1024)

+

+typedef struct {

+    int type; //MTK_GFC_COMMAND_T

+    unsigned int length;

+} mtk_geofence_msg;

+

+typedef struct {

+    bool geofence_support;

+    int server_data_fd;

+}mtk_geofence_server_init_msg;

+

+typedef enum {

+    GEOFENCE_SERVER_CAP,//geofence server capability

+    EXCUTE_RESULT,

+    GEOFENCE_NUM,

+    GEOFENCE_RESPONSE_INFO,

+    GEOFENCE_ALERT_INFO,

+    GNSS_TRACKING_STATUS,

+} mtk_geofence_ret_command;

+

+typedef struct mtk_geofence_create_status {

+    int createstat;//  success : 0, error : -1, insufficient_memory : -2, too many fences  : -3

+    int id;

+}mtk_geofence_create_status;

+

+typedef struct {

+    int cmdtype;//mtk_geofence_command

+    int result;

+} mtk_geofence_result;

+

+typedef struct cyclical_buffer{

+    char *next_write;

+    char *next_read;

+    char *start_buffer;

+    char *end_buffer;

+    int buffer_size;

+} cyclical_buffer_t;

+

+static char geofence_raw_data[GEOFENCE_DATAPATH_SIZE] = {0};

+static cyclical_buffer_t g_cyclical_buffer;    // io - cyclic buffer

+int server_data_fd = -1;

+

+//-1 means fail or serverfd is returned

+static int geofenceinf_socket_tcp_client_connect_local(bool abstract, const char* name) {

+    int fd;

+    int size;

+    struct sockaddr_un addr;

+

+    memset(&addr, 0, sizeof(addr));

+    addr.sun_family = AF_UNIX;

+    size = strlen(name) + offsetof(struct sockaddr_un, sun_path) + 1;

+    if(abstract) {

+        addr.sun_path[0] = 0;

+        memcpy(addr.sun_path + 1, name, strlen(name));

+    } else {

+        strncpy(addr.sun_path, name, sizeof(addr.sun_path));

+        if(unlink(addr.sun_path) == -1) {

+            LOGW("geofenceinf_socket_tcp_client_connect_local() unlink() failed, reason=[%s]%d",

+                strerror(errno), errno);

+        }

+    }

+    fd = socket(AF_UNIX, SOCK_STREAM, 0);

+    if(fd == -1) {

+        LOGE("geofenceinf_socket_tcp_client_connect_local() socket() failed, reason=[%s]%d",

+            strerror(errno), errno);

+        return -1;

+    }

+    if(connect(fd, (struct sockaddr*)&addr, size) == -1) {

+        LOGE("geofenceinf_socket_tcp_client_connect_local() connect() failed, abstruct=%d name=[%s] reason=[%s]%d",

+            abstract, name, strerror(errno), errno);

+        close(fd);

+        return -1;

+    }

+

+    return fd;

+}

+

+void geofenceinf_buffer_initialize

+                ( cyclical_buffer_t *buffer,           // buffer to initialize

+                  unsigned int buffer_size )     // size of buffer to create

+{

+   // Set up buffer manipulation pointers

+   // end_buffer points to the next byte after the buffer

+   buffer->end_buffer   = buffer->start_buffer + buffer_size;

+   buffer->next_read    = buffer->start_buffer;

+   buffer->next_write   = buffer->start_buffer;

+   buffer->buffer_size = buffer_size;

+   return;

+}

+

+int geofenceinf_check_fence_vadility(mtk_geofence_property *fence) {

+    if ((fence->latest_state != GEOFENCE_ENTERED)

+     && (fence->latest_state != GEOFENCE_EXITED)

+     && (fence->latest_state != GEOFENCE_UNKNOWN)){

+        LOGE("geofenceinf_check_fence_vadility latest_state:%d fail", fence->latest_state);

+        return MTK_GFC_ERROR;

+    }

+

+    if (!(fence->monitor_transition & MTK_GEOFENCE_ENTER) && !(fence->monitor_transition & MTK_GEOFENCE_EXIT)){

+        LOGE("geofenceinf_check_fence_vadility monitor_transition:%d fail", fence->monitor_transition);

+        return MTK_GFC_ERROR;

+    }

+

+    return MTK_GFC_SUCCESS;

+}

+

+int geofenceinf_socket_set_blocking(int fd, int blocking) {

+    if (fd < 0) {

+        LOGE("geofenceinf_socket_set_blocking() invalid fd=%d", fd);

+        return -1;

+    }

+

+    int flags = fcntl(fd, F_GETFL, 0);

+    if (flags == -1) {

+        LOGE("geofenceinf_socket_set_blocking() fcntl() failed invalid flags=%d reason=[%s]%d",

+            flags, strerror(errno), errno);

+        return -1;

+    }

+

+    flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);

+    return (fcntl(fd, F_SETFL, flags) == 0) ? 0 : -1;

+}

+

+int geofenceinf_epoll_add_fd2(int epfd, int fd, uint32_t events) {

+    struct epoll_event ev;

+    memset(&ev, 0, sizeof(ev));

+    ev.data.fd = fd;

+    ev.events = events;

+    // don't set the fd to edge trigger

+    // the some event like accept may be lost if two or more clients are connecting to server at the same time

+    // level trigger is preferred to avoid event lost

+    // do not set EPOLLOUT due to it will always trigger when write is available

+    if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {

+        LOGE("epoll_add_fd2() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",

+            strerror(errno), errno, epfd, fd);

+        return -1;

+    }

+    return 0;

+}

+

+int geofenceinf_socket_bind_udp(const char* path) {

+    int fd;

+    struct sockaddr_un addr;

+

+    fd = socket(PF_LOCAL, SOCK_DGRAM, 0);

+    if (fd < 0) {

+        LOGE("socket_bind_udp() socket() failed reason=[%s]%d",

+            strerror(errno), errno);

+        return -1;

+    }

+    LOGD("fd=%d,path=%s", fd, path);

+

+    memset(&addr, 0, sizeof(addr));

+    addr.sun_path[0] = 0;

+    MNLD_STRNCPY(addr.sun_path + 1, path,sizeof(addr.sun_path) - 1);

+    addr.sun_family = AF_UNIX;

+    unlink(addr.sun_path);

+    if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {

+        LOGE("socket_bind_udp() bind() failed path=[%s] reason=[%s]%d",

+            path, strerror(errno), errno);

+        close(fd);

+        return -1;

+    }

+    return fd;

+}

+

+

+// -1 means failure

+int geofenceinf_safe_sendto(const char* path, const char* buff, int len) {

+    int ret = 0;

+    struct sockaddr_un addr;

+    int retry = 10;

+    int fd = socket(PF_LOCAL, SOCK_DGRAM, 0);

+    if (fd < 0) {

+        LOGE("safe_sendto() socket() failed reason=[%s]%d",

+            strerror(errno), errno);

+        return -1;

+    }

+

+    int flags = fcntl(fd, F_GETFL, 0);

+    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1){

+        LOGE("fcntl failed reason=[%s]%d",

+                    strerror(errno), errno);

+

+        close(fd);

+        return -1;

+    }

+

+    memset(&addr, 0, sizeof(addr));

+    addr.sun_path[0] = 0;

+    MNLD_STRNCPY(addr.sun_path + 1, path,sizeof(addr.sun_path) - 1);

+    addr.sun_family = AF_UNIX;

+

+    while ((ret = sendto(fd, buff, len, 0,

+        (const struct sockaddr *)&addr, sizeof(addr))) == -1) {

+        if (errno == EINTR) continue;

+        if (errno == EAGAIN) {

+            if (retry-- > 0) {

+                usleep(100 * 1000);

+                continue;

+            }

+        }

+        LOGE("safe_sendto() sendto() failed path=[%s] ret=%d reason=[%s]%d",

+            path, ret, strerror(errno), errno);

+        break;

+    }

+

+    close(fd);

+    return ret;

+}

+void geofenceinf_client_init(void)

+{

+    g_cyclical_buffer.start_buffer = &geofence_raw_data[0];

+    geofenceinf_buffer_initialize(&g_cyclical_buffer, GEOFENCE_DATAPATH_SIZE);

+}

+

+int geofenceinf_get_server_init_msg(int fd, mtk_geofence_callback *callback)

+{

+    int ret;

+    int recv_len = 0;

+    unsigned int read_count = 0, msg_len = 0;

+    char buffer[GEOFENCE_BUFF_SIZE] = {0};

+    char data[GEOFENCE_BUFF_SIZE] = {0};

+    mtk_geofence_msg *prmsg = NULL;

+    mtk_geofence_server_init_msg server_init_msg;

+    mtk_geofence_server_capability cap;

+

+    memset(&server_init_msg, 0, sizeof(mtk_geofence_server_init_msg));

+    //receive geofence server ack capability & server data fd

+    do {

+        ret = read(fd, buffer, GEOFENCE_BUFF_SIZE);

+        if(ret == -1) {

+            LOGW("geofenceinf_get_server_init_msg() read() fd=[%d] failed, reason=[%s]%d", fd, strerror(errno), errno);

+            return ret;

+        } else if(ret == 0) {

+            LOGW("geofenceinf_get_server_init_msg() read() fd=[%d] find the remote side has closed the session", fd);

+            return ret;

+        } else {

+            memcpy((char *)(data + recv_len), buffer, ret);

+            recv_len += ret;

+            read_count++;

+            if ((recv_len >= sizeof(mtk_geofence_msg)) && (msg_len == 0)){

+                prmsg = (mtk_geofence_msg *)&buffer[0];

+                msg_len = prmsg->length;

+            }

+            if (read_count >= 10){

+                LOGW("geofenceinf_get_server_init_msg() read() fd:%d too much counts:%d", fd, read_count);

+                return MTK_GFC_ERROR;

+            }

+        }

+        memset(buffer, 0, GEOFENCE_BUFF_SIZE);

+    } while((recv_len < msg_len) || (msg_len == 0));

+

+    msg_len = sizeof(mtk_geofence_msg) + sizeof(mtk_geofence_server_init_msg);

+    prmsg = (mtk_geofence_msg *)&data[0];

+    if (prmsg->length == msg_len){

+        memcpy(&server_init_msg, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(mtk_geofence_server_init_msg));

+    } else if (prmsg->length > msg_len) {

+        memcpy(&server_init_msg, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(mtk_geofence_server_init_msg));

+        LOGD("mnl msg len:%d > struct len:%d", prmsg->length, msg_len);

+    } else {

+        memset(buffer, 0, GEOFENCE_BUFF_SIZE);

+        memcpy(buffer, (char*)prmsg, prmsg->length);

+        memset((char *)(buffer + prmsg->length), 0, (msg_len - prmsg->length));

+        memcpy(&server_init_msg, (((char*)buffer)+sizeof(mtk_geofence_msg)), sizeof(mtk_geofence_server_init_msg));

+        LOGD("mnl msg len:%d < struct len:%d", prmsg->length, msg_len);

+    }

+

+    if (server_init_msg.server_data_fd >= 0){

+        server_data_fd = server_init_msg.server_data_fd;

+        LOGD("geofenceinf_get_server_init_msg:server data fd:%d", server_data_fd);

+    }

+

+    if (callback->geofence_capability_update != NULL){

+        memset(&cap, 0, sizeof(mtk_geofence_server_capability));

+        cap.geofence_support = server_init_msg.geofence_support;

+        callback->geofence_capability_update(&cap);

+    }

+    return MTK_GFC_SUCCESS;

+}

+

+int geofenceinf_client_register(const char* name, mtk_geofence_callback *callback)

+{

+    int fd;

+

+    if ( (fd = geofenceinf_socket_tcp_client_connect_local(true, GEOFENCEADP_MNL_TCP_DATA)) < 0){

+        LOGE("Geofence connect server failed:%d", fd);

+    } else {

+        LOGD("Geofence new client [%s], fd:%d", name, fd);

+        geofenceinf_client_init();

+        if (geofenceinf_get_server_init_msg(fd, callback) < 0){

+            close(fd);

+            return MTK_GFC_ERROR;

+        }

+        geofenceinf_socket_set_blocking(fd, 0);

+    }

+

+    return fd;

+}

+

+int geofenceinf_send2mnl(int fd, const char* buff, int len) {

+    int ret = write(fd, buff, len);

+    LOGD("geofence_send2mnl() write():length:%d", len);

+    if(ret == -1) {

+        LOGE("geofence_send2mnl() write() failed, reason=[%s]%d", strerror(errno), errno);

+    }

+    return ret;

+}

+

+int geofenceinf_safe_recv(int fd, char* buff, int len) {

+    int ret = 0;

+    int retry = 10;

+

+    while ((ret = read(fd, buff, len)) == -1) {

+        LOGW("geofenceinf_safe_recv() ret=%d len=%d", ret, len);

+        if (errno == EINTR) continue;

+        if (errno == EAGAIN) {

+            if (retry-- > 0) {

+                usleep(100 * 1000);

+                continue;

+            }

+        }

+        LOGE("geofenceinf_safe_recv() recvfrom() failed reason=[%s]%d",

+            strerror(errno), errno);

+        break;

+    }

+    return ret;

+}

+

+int geofenceinf_control_path_safe_recv(int fd, char* buff, int len, int expect_len) {

+    int ret = 0, ret1 = 0;

+    int retry = 10;

+    char data[GEOFENCE_BUFF_SIZE] = {0};

+

+    ret = read(fd, buff, len);

+    if(ret == -1) {

+        LOGW("geofenceinf_control_path_safe_recv() read() fd=[%d] failed, reason=[%s]%d",

+            fd, strerror(errno), errno);

+        return ret;

+    } else if(ret == 0) {

+        LOGW("geofenceinf_control_path_safe_recv() read() fd=[%d] find the remote side has closed the session", fd);

+        return ret;

+    }

+

+    if (ret < expect_len){

+        //set fd non-blocking, try it again.

+        geofenceinf_socket_set_blocking(fd, 0);

+        while ((ret1 = read(fd, data, GEOFENCE_BUFF_SIZE)) == -1) {

+            LOGW("geofenceinf_control_path_safe_recv() ret=%d", ret1);

+            if (errno == EINTR) continue;

+            if (errno == EAGAIN) {

+                if (retry-- > 0) {

+                    usleep(100 * 1000);

+                    continue;

+                }

+            }

+            LOGE("geofenceinf_safe_recv() recvfrom() failed reason=[%s]%d",

+                strerror(errno), errno);

+            break;

+        }

+        if ((ret1 > 0) && ((ret + ret1) < len)){

+            memcpy((char *)(buff + ret), data, ret1);

+            ret = ret + ret1;

+        }

+    }

+

+    return ret;

+}

+

+int geofenceinf_geofence_add_result(mtk_geofence_msg *prmsg, mtk_geofence_create_status *fence_ret) {

+    unsigned int msg_len;

+    #ifdef AT_COMMAND_PRINT

+    char data[GEOFENCE_BUFF_SIZE] = {0};

+    #endif

+

+    msg_len = sizeof(mtk_geofence_msg) + sizeof(mtk_geofence_create_status);

+    if (prmsg->length == msg_len){

+        memcpy(fence_ret, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(mtk_geofence_create_status));

+    } else {

+        //LOGE("geofenceinf_geofence_add_result:message len error %d %d",prmsg->length, msg_len);

+        return MTK_GFC_ERROR;

+    }

+

+    #ifdef AT_COMMAND_PRINT

+    /*Construct AT command */

+    if (fence_ret->createstat == MTK_ADD_GEOFENCE_SUCCESS){

+        sprintf(data, "+EGEOADDCIRCLE:%d,%d/r/n", fence_ret->createstat, fence_ret->id);

+        //Send AT command

+

+    } else {

+        sprintf(data, "+EGEOADDCIRCLE:%d/r/n", fence_ret->createstat);

+        //Send AT command

+    }

+    LOGD("AT command:%s",data);

+    #endif

+

+    return MTK_GFC_SUCCESS;

+}

+

+int geofenceinf_geofence_remove_result(mtk_geofence_msg *prmsg, mtk_geofence_result *remove_result) {

+    unsigned int msg_len;

+    #ifdef AT_COMMAND_PRINT

+    char data[GEOFENCE_BUFF_SIZE] = {0};

+    #endif

+

+    msg_len = sizeof(mtk_geofence_msg) + sizeof(mtk_geofence_result);

+    if (prmsg->length == msg_len){

+        memcpy(remove_result, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(mtk_geofence_result));

+    } else {

+        //LOGE("geofenceinf_get_remove_result:message len error %d %d",prmsg->length, msg_len);

+        return MTK_GFC_ERROR;

+    }

+

+    #ifdef AT_COMMAND_PRINT

+    /*Construct AT command */

+    if (remove_result->result == 0){

+        sprintf(data, "OK/r/n");

+    } else {

+        sprintf(data, "FAIL/r/n");

+    }

+    LOGD("AT command:%s",data);

+    #endif

+

+    return MTK_GFC_SUCCESS;

+}

+

+int geofenceinf_geofence_clear_result(mtk_geofence_msg *prmsg, mtk_geofence_result *clear_result) {

+    unsigned int msg_len;

+    #ifdef AT_COMMAND_PRINT

+    char data[GEOFENCE_BUFF_SIZE] = {0};

+    #endif

+

+    msg_len = sizeof(mtk_geofence_msg) + sizeof(mtk_geofence_result);

+    if (prmsg->length == msg_len){

+        memcpy(clear_result, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(mtk_geofence_result));

+    } else {

+        //LOGE("geofenceinf_geofence_clear_result:message len error %d %d",prmsg->length, msg_len);

+        return MTK_GFC_ERROR;

+    }

+

+    #ifdef AT_COMMAND_PRINT

+    /*Construct AT command */

+    if (clear_result->result == 0){

+        sprintf(data, "OK/r/n");

+    } else {

+        sprintf(data, "FAIL/r/n");

+    }

+    LOGD("AT command:%s",data);

+    #endif

+

+    return MTK_GFC_SUCCESS;

+}

+

+int geofenceinf_geofence_get_geofences_num(mtk_geofence_msg *prmsg, int *fence_nums) {

+    unsigned int msg_len;

+    #ifdef AT_COMMAND_PRINT

+    char data[GEOFENCE_BUFF_SIZE] = {0};

+    #endif

+

+    msg_len = sizeof(mtk_geofence_msg) + sizeof(int);

+    if (prmsg->length == msg_len){

+        memcpy(fence_nums, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(int));

+    } else {

+        //LOGE("geofenceinf_geofence_get_geofences_numgeofenceinf_geofence_get_geofences_numgeofenceinf_geofence_get_geofences_num:message len error %d %d",prmsg->length, msg_len);

+        return MTK_GFC_ERROR;

+    }

+

+    #ifdef AT_COMMAND_PRINT

+    /*Construct AT command */

+    sprintf(data, "+EGEOMAX: :%d/r/n", *fence_nums);

+    LOGD("AT command:%s",data);

+    #endif

+

+    return MTK_GFC_SUCCESS;

+}

+

+// GNSS Adaptor --> MNLD Message

+int geofenceinf_add_geofence(mtk_geofence_property *fence) {

+    int ret;

+    mtk_geofence_msg *geo_header = NULL;

+    unsigned int msg_len;

+    int recv_len, expect_len;

+    char buffer[GEOFENCE_BUFF_SIZE] = {0};

+    char geo_data[GEOFENCE_BUFF_SIZE] = {0};

+    mtk_geofence_create_status fence_status;

+    int fd = -1, temp_server_data_fd = -1;

+    mtk_geofence_msg *prmsg = NULL;

+

+    LOGD("geofence_add_geofences");

+    if (server_data_fd < 0){

+        LOGE("geofenceinf_add_geofence:wait server data fd");

+        return -1;

+    } else {

+        temp_server_data_fd = server_data_fd;

+    }

+    /* For geofence recover mechanism */

+    ret = geofenceinf_check_fence_vadility(fence);

+    if(ret < 0) {

+        LOGE("geofenceinf_check_fence_vadility fail");

+        return -1;

+    }

+

+    //construct add fence cmd

+    msg_len = sizeof(mtk_geofence_msg) + sizeof(int) + sizeof(mtk_geofence_property);

+    geo_header = (mtk_geofence_msg *)&geo_data[0];

+    if (msg_len > GEOFENCE_BUFF_SIZE){

+        LOGE("geofenceinf message length too long:%d", msg_len);

+        return MTK_GFC_ERROR;

+    }

+    //construct total message

+    //construct header

+    geo_header->type = ADD_GEOFENCE_AREA;

+    geo_header->length = msg_len;

+    //input server data fd

+    memcpy( ((char*)geo_header) + sizeof(mtk_geofence_msg), &temp_server_data_fd, sizeof(int));

+    //input geofence property payload

+    memcpy( ((char*)geo_header) + sizeof(mtk_geofence_msg) + sizeof(int), fence, sizeof(mtk_geofence_property));

+

+    //Create TCP client fd, and connect tcp server

+    if ( (fd = geofenceinf_socket_tcp_client_connect_local(true, GEOFENCEADP_MNL_TCP_CONTROL)) < 0){

+        LOGE("geofenceinf_add_geofence:create client fd failed:%d", fd);

+        return -1;

+    }

+

+    ret = geofenceinf_send2mnl(fd, (char *)geo_header, msg_len);

+    if(ret < 0) {

+        LOGE("geofenceinf_add_geofence:send message to mnl failed");

+        close(fd);

+        return -1;

+    }

+

+    //wait ack

+    expect_len = sizeof(mtk_geofence_msg) + sizeof(mtk_geofence_create_status);

+    if ( (recv_len = geofenceinf_control_path_safe_recv(fd, buffer, GEOFENCE_BUFF_SIZE, expect_len)) <= 0){

+        LOGE("geofenceinf_add_geofence:don't recv any data");

+        close(fd);

+        return -1;

+    } else {

+        prmsg = (mtk_geofence_msg *)&buffer[0];

+        ret = geofenceinf_geofence_add_result(prmsg, &fence_status);

+        if (ret == MTK_GFC_ERROR){

+            LOGE("geofenceinf_add_geofence:message data don't match struct %d %d", recv_len, expect_len);

+            close(fd);

+            return -1;

+        }

+    }

+

+    if (fence_status.createstat == 0){

+        close(fd);

+        return fence_status.id;

+    } else {

+        close(fd);

+        return fence_status.createstat;

+    }

+}

+

+int geofenceinf_remove_geofence(const int geofence_id) {

+    int ret;

+    mtk_geofence_msg *geo_header=NULL;

+    unsigned int msg_len;

+    int recv_len;

+    int expect_len;

+    char buffer[GEOFENCE_BUFF_SIZE] = {0};

+    char geo_data[GEOFENCE_BUFF_SIZE] = {0};

+    int fd = -1, temp_server_data_fd = -1;

+    mtk_geofence_msg *prmsg = NULL;

+    mtk_geofence_result remove_result;

+

+    LOGD("geofence_remove_geofences,fence id:%d", geofence_id);

+    if (server_data_fd < 0){

+        LOGE("geofenceinf_remove_geofence:wait server data fd");

+        return MTK_GFC_ERROR;

+    } else {

+        temp_server_data_fd = server_data_fd;

+    }

+

+    //construct remove fence cmd

+    msg_len = sizeof(mtk_geofence_msg) + sizeof(int) + sizeof(int);

+    geo_header = (mtk_geofence_msg *)&geo_data[0];

+    if (msg_len > GEOFENCE_BUFF_SIZE){

+        LOGE("geofenceinf message length too long:%d", msg_len);

+        return MTK_GFC_ERROR;

+    }

+

+    //construct total message

+    //construct header

+    geo_header->type = REMOVE_GEOFENCE;

+    geo_header->length = msg_len;

+    //input server data fd

+    memcpy( ((char*)geo_header) + sizeof(mtk_geofence_msg), &temp_server_data_fd, sizeof(int));

+    //input geofence property payload

+    memcpy( ((char*)geo_header) + sizeof(mtk_geofence_msg) + sizeof(int), &geofence_id, sizeof(int));

+

+    //Create TCP client fd, and connect tcp server

+    if ( (fd = geofenceinf_socket_tcp_client_connect_local(true, GEOFENCEADP_MNL_TCP_CONTROL)) < 0){

+        LOGE("geofenceinf_remove_geofence:create client fd failed:%d", fd);

+        return MTK_GFC_ERROR;

+    }

+

+    ret = geofenceinf_send2mnl(fd, (char *)geo_header, msg_len);

+    if(ret < 0) {

+        LOGE("geofenceinf_remove_geofence:send message to mnl failed");

+        close(fd);

+        return MTK_GFC_ERROR;

+    }

+

+    //wait ack

+    expect_len = sizeof(mtk_geofence_msg) + sizeof(mtk_geofence_result);

+    if ( (recv_len = geofenceinf_control_path_safe_recv(fd, buffer, GEOFENCE_BUFF_SIZE, expect_len)) <= 0){

+        LOGE("geofenceinf_remove_geofence:don't recv any data");

+        close(fd);

+        return MTK_GFC_ERROR;

+    } else {

+        prmsg = (mtk_geofence_msg *)&buffer[0];

+        ret = geofenceinf_geofence_remove_result(prmsg, &remove_result);

+        if (ret == MTK_GFC_ERROR){

+            LOGE("geofenceinf_remove_geofence:message data don't match struct %d %d", recv_len, expect_len);

+            close(fd);

+            return MTK_GFC_ERROR;

+        }

+    }

+

+    if (remove_result.result == 0){

+        close(fd);

+        return MTK_GFC_SUCCESS;

+    } else {

+        close(fd);

+        return MTK_GFC_ERROR;

+    }

+}

+

+int geofenceinf_clear_geofences(void) {

+    int ret;

+    mtk_geofence_msg *geo_header=NULL;

+    unsigned int msg_len;

+    int recv_len;

+    int expect_len;

+    char buffer[GEOFENCE_BUFF_SIZE] = {0};

+    char geo_data[GEOFENCE_BUFF_SIZE] = {0};

+    int fd = -1, temp_server_data_fd = -1;

+    mtk_geofence_msg *prmsg = NULL;

+    mtk_geofence_result clear_result;

+

+    LOGD("geofence_clear_geofences");

+    if (server_data_fd < 0){

+        LOGE("geofenceinf_clear_geofences:wait server data fd");

+        return MTK_GFC_ERROR;

+    } else {

+        temp_server_data_fd = server_data_fd;

+    }

+

+    //construct remove fence cmd

+    msg_len = sizeof(mtk_geofence_msg) + sizeof(int);

+    geo_header = (mtk_geofence_msg *)&geo_data[0];

+    if (msg_len > GEOFENCE_BUFF_SIZE){

+        LOGE("geofenceinf message length too long:%d", msg_len);

+        return MTK_GFC_ERROR;

+    }

+

+    //construct total message

+    //construct header

+    geo_header->type = CLEAR_GEOFENCE;

+    geo_header->length = msg_len;

+    //input server data fd

+    memcpy( ((char*)geo_header) + sizeof(mtk_geofence_msg), &temp_server_data_fd, sizeof(int));

+

+    //Create TCP client fd, and connect tcp server

+    if ( (fd = geofenceinf_socket_tcp_client_connect_local(true, GEOFENCEADP_MNL_TCP_CONTROL)) < 0){

+        LOGE("geofenceinf_clear_geofences:create client fd failed:%d", fd);

+        return MTK_GFC_ERROR;

+    }

+

+    ret = geofenceinf_send2mnl(fd, (char *)geo_header, msg_len);

+    if(ret < 0) {

+        LOGE("geofenceinf_clear_geofences:send message to mnl failed");

+        close(fd);

+        return MTK_GFC_ERROR;

+    }

+

+    //wait ack

+    expect_len = sizeof(mtk_geofence_msg) + sizeof(mtk_geofence_result);

+    if ( (recv_len = geofenceinf_control_path_safe_recv(fd, buffer, GEOFENCE_BUFF_SIZE, expect_len)) <= 0){

+        LOGE("geofenceinf_clear_geofences:don't recv any data");

+        close(fd);

+        return MTK_GFC_ERROR;

+    } else {

+        prmsg = (mtk_geofence_msg *)&buffer[0];

+        ret = geofenceinf_geofence_clear_result(prmsg, &clear_result);

+        if (ret == MTK_GFC_ERROR){

+            LOGE("geofenceinf_clear_geofences:message data don't match struct %d %d", recv_len, expect_len);

+            close(fd);

+            return MTK_GFC_ERROR;

+        }

+    }

+

+    if (clear_result.result == 0){

+        close(fd);

+        return MTK_GFC_SUCCESS;

+    } else {

+        close(fd);

+        return MTK_GFC_ERROR;

+    }

+}

+

+int geofenceinf_query_geofences_num(void) {

+    int ret;

+    mtk_geofence_msg *geo_header=NULL;

+    unsigned int msg_len;

+    int recv_len;

+    int expect_len;

+    char buffer[GEOFENCE_BUFF_SIZE] = {0};

+    char geo_data[GEOFENCE_BUFF_SIZE] = {0};

+    int fence_nums;

+    int fd = -1, temp_server_data_fd = -1;

+    mtk_geofence_msg *prmsg = NULL;

+

+    LOGD("geofence_query_geofences_num");

+    if (server_data_fd < 0){

+        LOGE("geofence_query_geofences_num:wait server data fd");

+        return -1;

+    } else {

+        temp_server_data_fd = server_data_fd;

+    }

+

+    //construct remove fence cmd

+    msg_len = sizeof(mtk_geofence_msg) + sizeof(int);

+    geo_header = (mtk_geofence_msg *)&geo_data[0];

+    if (msg_len > GEOFENCE_BUFF_SIZE){

+        LOGE("geofenceinf message length too long:%d", msg_len);

+        return MTK_GFC_ERROR;

+    }

+

+    //construct total message

+    //construct header

+    geo_header->type = QUERY_GEOFENCE_NUM;

+    geo_header->length = msg_len;

+    //input server data fd

+    memcpy( ((char*)geo_header) + sizeof(mtk_geofence_msg), &temp_server_data_fd, sizeof(int));

+

+    //Create TCP client fd, and connect tcp server

+    if ( (fd = geofenceinf_socket_tcp_client_connect_local(true, GEOFENCEADP_MNL_TCP_CONTROL)) < 0){

+        LOGE("geofence_query_geofences_num:create client fd failed:%d", fd);

+        return -1;

+    }

+

+    ret = geofenceinf_send2mnl(fd, (char *)geo_header, msg_len);

+    if(ret < 0) {

+        LOGE("geofence_query_geofences_num:send message to mnl failed");

+        close(fd);

+        return MTK_GFC_ERROR;

+    }

+

+    //wait ack

+    expect_len = sizeof(mtk_geofence_msg) + sizeof(fence_nums);

+    if ( (recv_len = geofenceinf_control_path_safe_recv(fd, buffer, GEOFENCE_BUFF_SIZE, expect_len)) <= 0){

+        LOGE("geofence_query_geofences_num:don't recv any data");

+        close(fd);

+        return MTK_GFC_ERROR;

+    } else {

+        prmsg = (mtk_geofence_msg *)&buffer[0];

+        ret = geofenceinf_geofence_get_geofences_num(prmsg, &fence_nums);

+        if (ret == MTK_GFC_ERROR){

+            LOGE("geofence_query_geofences_num:message data don't match struct %d %d", recv_len, expect_len);

+            close(fd);

+            return MTK_GFC_ERROR;

+        }

+    }

+

+    if (fence_nums > 0){

+        close(fd);

+        return fence_nums;

+    } else {

+        close(fd);

+        return MTK_GFC_ERROR;

+    }

+}

+

+// GNSS Adaptor --> MNLD Message

+int geofenceinf_client_capability_config(mtk_geofence_client_capability *cap) {

+    int ret;

+    mtk_geofence_msg *geo_header=NULL;

+    char geo_data[GEOFENCE_BUFF_SIZE] = {0};

+    unsigned int msg_len;

+    int fd = -1, temp_server_data_fd = -1;

+

+    LOGD("geofenceinf_client_capability_config");

+    if (server_data_fd < 0){

+        LOGE("geofenceinf_client_capability_config:wait server data fd");

+        return -1;

+    } else {

+        temp_server_data_fd = server_data_fd;

+    }

+

+    //construct remove fence cmd

+    msg_len = sizeof(mtk_geofence_msg) + sizeof(int) + sizeof(mtk_geofence_client_capability);

+    geo_header = (mtk_geofence_msg *)&geo_data[0];

+    if (msg_len > GEOFENCE_BUFF_SIZE){

+        LOGE("geofenceinf message length too long:%d", msg_len);

+        return MTK_GFC_ERROR;

+    }

+

+    //construct total message

+    //construct header

+    geo_header->type = GEOFENCE_CLIENT_CAP;

+    geo_header->length = msg_len;

+    //input server data fd

+    memcpy( ((char*)geo_header) + sizeof(mtk_geofence_msg), &temp_server_data_fd, sizeof(int));

+    memcpy( ((char*)geo_header) + sizeof(mtk_geofence_msg) + sizeof(int), cap, sizeof(mtk_geofence_client_capability));

+

+    //Create TCP client fd, and connect tcp server

+    if ( (fd = geofenceinf_socket_tcp_client_connect_local(true, GEOFENCEADP_MNL_TCP_CONTROL)) < 0){

+        LOGE("geofenceinf_client_capability_config:create client fd failed:%d", fd);

+        return -1;

+    }

+

+    ret = geofenceinf_send2mnl(fd, (char *)geo_header, msg_len);

+    if(ret < 0) {

+        LOGE("geofenceinf_client_capability_config:send message to mnl failed");

+        close(fd);

+        return MTK_GFC_ERROR;

+    }

+    return MTK_GFC_SUCCESS;

+}

+

+void geofenceinf_server_capability_sync(mtk_geofence_msg *prmsg, mtk_geofence_callback *at_callback) {

+    mtk_geofence_server_capability cap;

+    unsigned int msg_len;

+    char data[GEOFENCE_BUFF_SIZE] = {0};

+

+    msg_len = sizeof(mtk_geofence_msg) + sizeof(mtk_geofence_server_capability);

+    if (prmsg->length == msg_len){

+        memcpy(&cap, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(mtk_geofence_server_capability));

+    } else if (prmsg->length > msg_len) {

+        memcpy(&cap, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(mtk_geofence_server_capability));

+        LOGD("mnl msg len:%d > struct len:%d", prmsg->length, msg_len);

+    } else {

+        memcpy(data, (char*)prmsg, prmsg->length);

+        memset((char *)(data + prmsg->length), 0, (msg_len - prmsg->length));

+        memcpy(&cap, (((char*)data)+sizeof(mtk_geofence_msg)), sizeof(mtk_geofence_server_capability));

+        LOGD("mnl msg len:%d < struct len:%d", prmsg->length, msg_len);

+    }

+

+    if (at_callback->geofence_capability_update != NULL){

+        at_callback->geofence_capability_update(&cap);

+    }

+

+    return;

+}

+

+void geofenceinf_get_server_data_fd(mtk_geofence_msg *prmsg) {

+    int data_fd;

+    unsigned int msg_len;

+    char data[GEOFENCE_BUFF_SIZE] = {0};

+

+    msg_len = sizeof(mtk_geofence_msg) + sizeof(int);

+    if (prmsg->length == msg_len){

+        memcpy(&data_fd, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(int));

+    } else if (prmsg->length > msg_len) {

+        memcpy(&data_fd, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(int));

+        LOGD("mnl msg len:%d > struct len:%d", prmsg->length, msg_len);

+    } else {

+        memcpy(data, (char*)prmsg, prmsg->length);

+        memset((char *)(data + prmsg->length), 0, (msg_len - prmsg->length));

+        memcpy(&data_fd, (((char*)data)+sizeof(mtk_geofence_msg)), sizeof(int));

+        LOGD("mnl msg len:%d < struct len:%d", prmsg->length, msg_len);

+    }

+

+    if (data_fd < 0){

+        LOGD("geofenceinf_get_server_data_fd error");

+    } else {

+        server_data_fd = data_fd;

+        LOGD("geofenceinf_get_server_data_fd:%d", server_data_fd);

+    }

+

+    return;

+}

+

+void geofenceinf_geofence_alert(mtk_geofence_msg *prmsg, mtk_geofence_callback *at_callback) {

+    mtk_geofence_alert fence_alert;

+    unsigned int msg_len;

+    char data[GEOFENCE_BUFF_SIZE] = {0};

+

+    msg_len = sizeof(mtk_geofence_msg) + sizeof(mtk_geofence_alert);

+    if (prmsg->length == msg_len){

+        memcpy(&fence_alert, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(mtk_geofence_alert));

+    } else if (prmsg->length > msg_len) {

+        memcpy(&fence_alert, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(mtk_geofence_alert));

+        LOGD("mnl msg len:%d > struct len:%d", prmsg->length, msg_len);

+    } else {

+        memcpy(data, (char*)prmsg, prmsg->length);

+        memset((char *)(data + prmsg->length), 0, (msg_len - prmsg->length));

+        memcpy(&fence_alert, (((char*)data)+sizeof(mtk_geofence_msg)), sizeof(mtk_geofence_alert));

+        LOGD("mnl msg len:%d < struct len:%d", prmsg->length, msg_len);

+    }

+

+    #ifdef AT_COMMAND_PRINT

+    /*Construct AT command */

+    sprintf(data, "+EGEORESP:%d,%d,%.6f,%.6f,%.2f,%.2f,%.2f,%d,%d,%d,%d,%d,%.2f,%.2f,%.2f/r/n",

+            fence_alert.id,

+            fence_alert.alert_state,

+            fence_alert.latitude,

+            fence_alert.longitude,

+            fence_alert.altitude,

+            fence_alert.speed,

+            fence_alert.heading,

+            fence_alert.h_acc,

+            fence_alert.h_err_majoraxis,

+            fence_alert.h_err_minoraxis,

+            fence_alert.h_err_angle,

+            fence_alert.hor_conf,

+            fence_alert.pdop,

+            fence_alert.hdop,

+            fence_alert.vdop);

+    LOGD("AT command:%s",data);

+    #endif

+    //Send AT command

+    if (at_callback->geofence_fence_alert_callback != NULL){

+        at_callback->geofence_fence_alert_callback(&fence_alert);

+    }

+

+    return;

+}

+

+void geofenceinf_gnss_tracking_status(mtk_geofence_msg *prmsg, mtk_geofence_callback *at_callback) {

+    mtk_gnss_tracking_status tracking_Status;

+    unsigned int msg_len;

+    char data[GEOFENCE_BUFF_SIZE] = {0};

+

+    msg_len = sizeof(mtk_geofence_msg) + sizeof(mtk_gnss_tracking_status);

+    if (prmsg->length == msg_len){

+        memcpy(&tracking_Status, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(mtk_gnss_tracking_status));

+    } else if (prmsg->length > msg_len) {

+        memcpy(&tracking_Status, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(mtk_gnss_tracking_status));

+        LOGD("mnl msg len:%d > struct len:%d", prmsg->length, msg_len);

+    } else {

+        memcpy(data, (char*)prmsg, prmsg->length);

+        memset((char *)(data + prmsg->length), 0, (msg_len - prmsg->length));

+        memcpy(&tracking_Status, (((char*)data)+sizeof(mtk_geofence_msg)), sizeof(mtk_gnss_tracking_status));

+        LOGD("mnl msg len:%d < struct len:%d", prmsg->length, msg_len);

+    }

+

+    #ifdef AT_COMMAND_PRINT

+    /*Construct AT command */

+    sprintf(data, "+EGEOTRACK:%d,\"%d/%d/%d,%d:%d:%d\"",

+            tracking_Status.status,

+            tracking_Status.year,

+            tracking_Status.month,

+            tracking_Status.day,

+            tracking_Status.hour,

+            tracking_Status.minute,

+            tracking_Status.second

+            );

+    LOGD("AT command:%s",data);

+    #endif

+    //Send AT command

+    if (at_callback->geofence_tracking_status_callback != NULL){

+        at_callback->geofence_tracking_status_callback(&tracking_Status);

+    }

+

+    return;

+}

+

+int geofenceinf_add_rawdata_to_buffer(char *data, int length)

+{

+    int i;

+    LOGD("geofenceadp rev raw data:%d", length);

+    for (i = 0; i < length; i++)

+    {

+        *(g_cyclical_buffer.next_write++) = data[i];

+        if (g_cyclical_buffer.next_write == g_cyclical_buffer.end_buffer){

+            g_cyclical_buffer.next_write = g_cyclical_buffer.start_buffer;

+        }

+

+        if (g_cyclical_buffer.next_write == g_cyclical_buffer.next_read){

+            LOGE("geofence ring_buffer overflow\r\n");

+            return -1;

+        }

+    }

+

+    return 0;

+}

+

+int geofenceinf_get_one_message(char *data, unsigned int len)

+{

+    char *next_write, *next_read;

+    unsigned int data_size, i, header_len;

+    char buffer[GEOFENCE_BUFF_SIZE] = {0};

+    unsigned int return_len = 0;

+    mtk_geofence_msg geo_header;

+

+    next_write = g_cyclical_buffer.next_write;

+    next_read = g_cyclical_buffer.next_read;

+

+    if (g_cyclical_buffer.next_read == next_write)

+    {

+        //buffer empty

+        return -1;

+    }

+

+    header_len = sizeof(mtk_geofence_msg);

+    /*Compute data length*/

+    if (g_cyclical_buffer.next_read < next_write)

+    {

+        data_size = (unsigned long)next_write - (unsigned long)g_cyclical_buffer.next_read;

+    }

+    else

+    {

+        data_size = (unsigned long)g_cyclical_buffer.end_buffer - (unsigned long)g_cyclical_buffer.next_read +

+                     (unsigned long)next_write - (unsigned long)g_cyclical_buffer.start_buffer;

+    }

+

+    /*Copy data header to buffer*/

+    if (data_size >= header_len)

+    {

+        for (i = 0; i < header_len; i++)

+        {

+            buffer[i] = *(next_read++);

+            if (next_read == g_cyclical_buffer.end_buffer){

+                next_read = g_cyclical_buffer.start_buffer;

+            }

+        }

+

+        memset(&geo_header, 0, sizeof(mtk_geofence_msg));

+        memcpy(&geo_header, buffer, sizeof(mtk_geofence_msg));

+        if (geo_header.length <= data_size){

+            for (i = 0; (i < geo_header.length)&&(i < len); i++)

+            {

+                data[i] = *(g_cyclical_buffer.next_read++);

+                return_len++;

+                if (g_cyclical_buffer.next_read == g_cyclical_buffer.end_buffer){

+                    g_cyclical_buffer.next_read = g_cyclical_buffer.start_buffer;

+                }

+            }

+        }

+        else {

+            //no enough data

+            return -2;

+        }

+    }

+    else

+    {

+        //no enough data

+        return -2;

+    }

+

+    return return_len;

+}

+

+int mnl2geofence_hdlr (int fd, mtk_geofence_callback *callback) {

+    char data[GEOFENCE_BUFF_SIZE] = {0};

+    char buff[GEOFENCE_BUFF_SIZE] = {0};

+    int len;

+    int read_len;

+    int msg_len;

+    mtk_geofence_ret_command cmd;

+    mtk_geofence_msg *prmsg = NULL;

+

+    read_len = geofenceinf_safe_recv(fd, buff, sizeof(buff));

+    if (read_len <= 0) {

+        close(fd);

+        server_data_fd = -1;

+        if(callback->geofence_connection_broken) {

+            LOGW("Connection broken...");

+            callback->geofence_connection_broken();

+        }

+        LOGE("mnl2geofence_hdlr() geofenceinf_safe_recv() failed read_len=%d, %s", read_len, strerror(errno));

+        return MTK_GFC_ERROR;

+    }

+

+    if (geofenceinf_add_rawdata_to_buffer(buff, read_len) < 0){

+        //error handle

+        LOGE("geofenceinf_add_rawdata_to_buffer() overflow\r\n");

+    }

+

+    while ((len = geofenceinf_get_one_message(data, GEOFENCE_BUFF_SIZE)) > 0)

+    {

+        if((len > 0) && (len <= GEOFENCE_BUFF_SIZE)) {

+            prmsg = (mtk_geofence_msg *)&data[0];

+        } else {

+            LOGE("len err:%d",len);

+            return MTK_GFC_ERROR;

+        }

+

+        cmd = prmsg->type;

+        msg_len = prmsg->length;

+        if (msg_len < 0){

+            LOGE("mnl2geofence_hdlr() message length error:%d", msg_len);

+            return MTK_GFC_ERROR;

+        }

+        //LOGD("command %d, len %d", cmd, msg_len);

+        switch (cmd) {

+            case GEOFENCE_ALERT_INFO:

+                geofenceinf_geofence_alert(prmsg, callback);

+                break;

+            case GNSS_TRACKING_STATUS:

+                geofenceinf_gnss_tracking_status(prmsg, callback);

+                break;

+            case GEOFENCE_SERVER_CAP:

+                geofenceinf_server_capability_sync(prmsg, callback);

+                break;

+            default:

+                LOGE("invalid geofence cmd:%d",cmd);

+                break;

+        }

+

+        memset(data, 0, GEOFENCE_BUFF_SIZE);

+        len = 0;

+    }

+    return MTK_GFC_SUCCESS;

+}