[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;
+}