[Feature] add GA346 baseline version
Change-Id: Ic62933698569507dcf98240cdf5d9931ae34348f
diff --git a/src/connectivity/agps/2.0/lbs_em/src/1_build_run.sh b/src/connectivity/agps/2.0/lbs_em/src/1_build_run.sh
new file mode 100755
index 0000000..42f6892
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/1_build_run.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+make_success()
+{
+ echo -e "\E[1;32;40m-----------------------------make success-----------------------------\E[0m"
+ read -n1 -r -p "Press any key to continue..." key
+ ./lbs_em
+ ret=$?
+ case $ret in
+ 0) echo -e "\E[1;32;40m-----------------------------end of program success-----------------------------\E[0m";;
+ *) echo -e "\E[1;31;40m-----------------------------end of program failed ret=${ret}-----------------------------\E[0m";;
+ esac
+}
+
+make_failed()
+{
+ echo -e "\E[1;31;40m-----------------------------make failed, ret=${ret}-----------------------------\E[0m"
+}
+
+#----------------------------------------------------
+
+make clean
+make
+ret=$?
+case $ret in
+ 0) make_success;;
+ *) make_failed ret;;
+esac
+make clean
+
+
+#./mtk_agps_test_case
+#./mtk_agps_test_case 1 supl.nokia.com 7275 1
diff --git a/src/connectivity/agps/2.0/lbs_em/src/MTK_LICENSE b/src/connectivity/agps/2.0/lbs_em/src/MTK_LICENSE
new file mode 100644
index 0000000..901b162
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/MTK_LICENSE
@@ -0,0 +1,35 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein
+is confidential and proprietary to MediaTek Inc. and/or its licensors.
+Without the prior written permission of MediaTek inc. and/or its licensors,
+any reproduction, modification, use or disclosure of MediaTek Software,
+and information contained herein, in whole or in part, shall be strictly prohibited.
+
+MediaTek Inc. (C) 2018. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+
+The following software/firmware and/or related documentation ("MediaTek Software")
+have been modified by MediaTek Inc. All revisions are subject to any receiver's
+applicable license agreements with MediaTek Inc.
+
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/1_build.sh b/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/1_build.sh
new file mode 100755
index 0000000..2e0e21a
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/1_build.sh
@@ -0,0 +1,2 @@
+make clean
+make
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/Android.mk b/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/Android.mk
new file mode 100755
index 0000000..42ce9ff
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/Android.mk
@@ -0,0 +1,29 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/inc \
+
+LOCAL_SRC_FILES := \
+ src/agps_debug_interface.c \
+ src/data_coder.c \
+
+LOCAL_CFLAGS += \
+ -g \
+ -Wall \
+ -D __ANDROID_OS__ \
+
+# -D __LINUX_OS__ \
+# -D __ANDROID_OS__ \
+# -D __TIZEN_OS__ \
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := agps_debug_interface
+
+include $(BUILD_STATIC_LIBRARY)
+# include $(call all-makefiles-under,$(LOCAL_PATH)) # Include subdirectory makefiles
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/inc/agps_debug_interface.h b/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/inc/agps_debug_interface.h
new file mode 100755
index 0000000..d7b2305
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/inc/agps_debug_interface.h
@@ -0,0 +1,25 @@
+#ifndef __AGPS_DEBUG_INTERFACE_H__
+#define __AGPS_DEBUG_INTERFACE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ void (*toast_message) (const char* msg);
+ void (*view_message) (int color, const char* msg);
+ void (*dialog_message) (const char* title, const char* msg);
+} agps_debug_interface;
+
+// -1 means failure
+int agps_debug_interface_msg_handler(int fd, agps_debug_interface* handlers);
+
+// -1 means failure
+int agps_debug_interface_get_fd();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/inc/data_coder.h b/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/inc/data_coder.h
new file mode 100755
index 0000000..d9c3ff8
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/inc/data_coder.h
@@ -0,0 +1,32 @@
+
+#ifndef __DATA_CODER_H__
+#define __DATA_CODER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+char get_byte(char* buff, int* offset);
+short get_short(char* buff, int* offset);
+int get_int(char* buff, int* offset);
+long long get_long(char* buff, int* offset);
+float get_float(char* buff, int* offset);
+double get_double(char* buff, int* offset);
+char* get_string(char* buff, int* offset);
+char* get_string2(char* buff, int* offset);
+int get_binary(char* buff, int* offset, char* output);
+
+void put_byte(char* buff, int* offset, const char input);
+void put_short(char* buff, int* offset, const short input);
+void put_int(char* buff, int* offset, const int input);
+void put_long(char* buff, int* offset, const long long input);
+void put_float(char* buff, int* offset, const float input);
+void put_double(char* buff, int* offset, const double input);
+void put_string(char* buff, int* offset, const char* input);
+void put_binary(char* buff, int* offset, const char* input, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/makefile b/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/makefile
new file mode 100755
index 0000000..59c22f7
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/makefile
@@ -0,0 +1,43 @@
+CC=gcc
+CXX=g++
+
+FLAGS=\
+ -g \
+ -D __LINUX_OS__ \
+
+INCLUDE=\
+ -g \
+ -Wall \
+ -I./inc \
+
+LIBS=\
+ -ldl \
+ -lrt \
+ -lpthread \
+
+CXXSRC = \
+
+CSRC= \
+ src/agps_debug_interface.c \
+ src/data_coder.c \
+
+STATIC_LIB=agps_debug_interface.a
+
+COBJS=$(CSRC:.c=.o)
+CXXOBJS=$(CXXSRC:.cpp=.o)
+
+all: $(STATIC_LIB)
+
+$(STATIC_LIB): $(COBJS) $(CXXOBJS)
+ ar rcs $@ $^
+
+%.o : %.c
+ $(CC) -g -c $(INCLUDE) $(FLAGS) -o $@ $<
+
+%.o : %.cpp
+ $(CXX) -g -c $(INCLUDE) $(FLAGS) -o $@ $<
+
+.PHONY: clean
+clean:
+ rm -f $(STATIC_LIB) rm -rf *.o
+ find ./ -name *.o | xargs rm -rf
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/src/agps_debug_interface.c b/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/src/agps_debug_interface.c
new file mode 100755
index 0000000..d6c109e
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/src/agps_debug_interface.c
@@ -0,0 +1,241 @@
+#include <stdio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h> // for open
+#include <unistd.h> // for close
+#include <errno.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <arpa/inet.h> //inet_addr
+#include <sys/un.h> //struct sockaddr_un
+#if defined(__ANDROID_OS__)
+#include <cutils/sockets.h>
+#include <android/log.h>
+#endif
+#include <string.h>
+
+#include "data_coder.h"
+#include "agps_debug_interface.h"
+
+#define LOGD(...) { printf(__VA_ARGS__); fflush(stdout); }
+#define LOGE(...) { printf(__VA_ARGS__); fflush(stdout); }
+#define AGPS_DEBUG_INTERFACE_PATH "agpsd3"
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+typedef enum {
+ DEBUG_MGR_MESSAGE = 0,
+ DEBUG_MGR_STATE,
+} debug_mgr_type_enum;
+
+#define DEBUG_MGR_MESSAGE_TOAST (1<<0)
+#define DEBUG_MGR_MESSAGE_VIEW (1<<1)
+#define DEBUG_MGR_MESSAGE_DIALOG (1<<2)
+
+// -1 means failure
+static int local_socket_stream_connect(const char* path) {
+ struct sockaddr_un addr;
+ int fd = socket(PF_LOCAL, SOCK_STREAM, 0);
+ if(fd < 0) {
+ LOGE("local_socket_stream_connect() socket() failed fd=%d\n", fd);
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, path, strlen(path));
+ addr.sun_family = AF_UNIX;
+
+ if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ LOGE("local_socket_stream_connect() connect() failed reason=[%s] path=[%s]\n", strerror(errno), path);
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+//-1 means failure
+static int safe_read(int fd, void* buf, int len) {
+ int n, retry = 10;
+
+ if(fd < 0 || buf == NULL || len < 0) {
+ LOGE("safe_read() fd=%d buf=%p len=%d\n", fd, buf, len);
+ return -1;
+ }
+
+ if(len == 0) {
+ return 0;
+ }
+
+ while((n = read(fd, buf, len)) < 0) {
+ if(errno == EINTR) continue;
+ if(errno == EAGAIN) {
+ if(retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ goto exit;
+ }
+ goto exit;
+ }
+ return n;
+
+exit:
+ if(errno != EAGAIN) {
+ LOGE("safe_read() reason=[%s] fd=%d len=%d buf=%p\n",
+ strerror(errno), fd, len, buf);
+ }
+ return -1;
+}
+
+// -1 means failure
+int agps_debug_interface_msg_handler(int fd, agps_debug_interface* handlers) {
+ char tmp[1024] = {0};
+ int ret;
+ int offset;
+ int len;
+
+ debug_mgr_type_enum type = 0;
+ int data1 = 0;
+ int data2 = 0;
+ int data3 = 0;
+ char msg1[1024] = {0};
+ char msg2[1024] = {0};
+ char binary[1024] = {0};
+ int binary_size = 0;
+
+ UNUSED(type);
+ UNUSED(data1);
+ UNUSED(data2);
+ UNUSED(data3);
+ UNUSED(binary_size);
+
+ // read type
+ memset(tmp, 0, sizeof(tmp));
+ ret = safe_read(fd, tmp, 4);
+ if(ret < 4) {
+ LOGE("agps_debug_interface_msg_handler() read type failure, ret=%d\n", ret);
+ return -1;
+ }
+ offset = 0;
+ type = get_int(tmp, &offset);
+
+ // read data1
+ memset(tmp, 0, sizeof(tmp));
+ ret = safe_read(fd, tmp, 4);
+ if(ret < 4) {
+ LOGE("agps_debug_interface_msg_handler() read data1 failure, ret=%d\n", ret);
+ return -1;
+ }
+ offset = 0;
+ data1 = get_int(tmp, &offset);
+
+ // read data2
+ ret = safe_read(fd, tmp, 4);
+ if(ret < 4) {
+ LOGE("agps_debug_interface_msg_handler() read data2 failure, ret=%d\n", ret);
+ return -1;
+ }
+ offset = 0;
+ data2 = get_int(tmp, &offset);
+
+ // read data3
+ ret = safe_read(fd, tmp, 4);
+ if(ret < 4) {
+ LOGE("agps_debug_interface_msg_handler() read data3 failure, ret=%d\n", ret);
+ return -1;
+ }
+ offset = 0;
+ data3 = get_int(tmp, &offset);
+
+ // read msg1
+ ret = safe_read(fd, tmp, 1);
+ if(ret < 1) {
+ LOGE("agps_debug_interface_msg_handler() read msg1 failure, ret=%d\n", ret);
+ return -1;
+ }
+ if(tmp[0]) {
+ // read msg1 length
+ ret = safe_read(fd, tmp, 4);
+ if(ret < 4) {
+ LOGE("agps_debug_interface_msg_handler() read msg1 failure in length, ret=%d\n", ret);
+ return -1;
+ }
+ offset = 0;
+ len = get_int(tmp, &offset);
+ // read msg1 pdu
+ ret = safe_read(fd, msg1, len);
+ if(ret < len) {
+ LOGE("agps_debug_interface_msg_handler() read msg1 failure in pdu, ret=%d\n", ret);
+ return -1;
+ }
+ }
+
+ // read msg2
+ ret = safe_read(fd, tmp, 1);
+ if(ret < 1) {
+ LOGE("agps_debug_interface_msg_handler() read msg2 failure, ret=%d\n", ret);
+ return -1;
+ }
+ if(tmp[0]) {
+ // read msg2 length
+ ret = safe_read(fd, tmp, 4);
+ if(ret < 4) {
+ LOGE("agps_debug_interface_msg_handler() read msg2 failure in length, ret=%d\n", ret);
+ return -1;
+ }
+ offset = 0;
+ len = get_int(tmp, &offset);
+ // read msg2 pdu
+ ret = safe_read(fd, msg2, len);
+ if(ret < len) {
+ LOGE("agps_debug_interface_msg_handler() read msg2 failure in pdu, ret=%d\n", ret);
+ return -1;
+ }
+ }
+
+ // read binary
+ ret = safe_read(fd, tmp, 4);
+ if(ret < 4) {
+ LOGE("agps_debug_interface_msg_handler() read binary failure in length, ret=%d\n", ret);
+ return -1;
+ }
+ offset = 0;
+ binary_size = get_int(tmp, &offset);
+ if(binary_size > 0) {
+ ret = safe_read(fd, binary, binary_size);
+ if(ret < binary_size) {
+ LOGE("agps_debug_interface_msg_handler() read binary failure in pdu, ret=%d\n", ret);
+ return -1;
+ }
+ }
+
+ // handling
+ if(type == DEBUG_MGR_MESSAGE) {
+ if(data1 & DEBUG_MGR_MESSAGE_TOAST) {
+ handlers->toast_message(msg2);
+ }
+ if(data1 & DEBUG_MGR_MESSAGE_VIEW) {
+ handlers->view_message(data2, msg2);
+ }
+ if(data1 & DEBUG_MGR_MESSAGE_DIALOG) {
+ handlers->dialog_message(msg1, msg2);
+ }
+ }
+
+ return 0;
+}
+
+// -1 means failure
+int agps_debug_interface_get_fd() {
+#if defined(__ANDROID_OS__)
+ int fd = local_socket_stream_connect(AGPS_DEBUG_INTERFACE_PATH);
+#else
+ int fd = local_socket_stream_connect(AGPS_DEBUG_INTERFACE_PATH);
+#endif
+ return fd;
+}
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/src/data_coder.c b/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/src/data_coder.c
new file mode 100755
index 0000000..a4d360f
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_debug_interface/src/data_coder.c
@@ -0,0 +1,129 @@
+#include <stdio.h>
+#include <string.h>
+
+//===============================================================
+//get
+char get_byte(char* buff, int* offset) {
+ char ret = buff[*offset];
+ *offset += 1;
+ return ret;
+}
+
+short get_short(char* buff, int* offset) {
+ short ret = 0;
+ ret |= get_byte(buff, offset) & 0xff;
+ ret |= (get_byte(buff, offset) << 8);
+ return ret;
+}
+
+int get_int(char* buff, int* offset) {
+ int ret = 0;
+ ret |= get_short(buff, offset) & 0xffff;
+ ret |= (get_short(buff, offset) << 16);
+ return ret;
+}
+
+long long get_long(char* buff, int* offset) {
+ long long ret = 0;
+ ret |= get_int(buff, offset) & 0xffffffffL;
+ ret |= ((long long)get_int(buff, offset) << 32);
+ return ret;
+}
+
+float get_float(char* buff, int* offset) {
+ float ret;
+ int tmp = get_int(buff, offset);
+ ret = *((float*)&tmp);
+ return ret;
+}
+
+double get_double(char* buff, int* offset) {
+ double ret;
+ long long tmp = get_long(buff, offset);
+ ret = *((double*)&tmp);
+ return ret;
+}
+
+char* get_string(char* buff, int* offset) {
+ char ret = get_byte(buff, offset);
+ if(ret == 0) {
+ return NULL;
+ } else {
+ char* p = NULL;
+ int len = get_int(buff, offset);
+ p = &buff[*offset];
+ *offset += len;
+ return p;
+ }
+}
+
+char* get_string2(char* buff, int* offset) {
+ char* output = get_string(buff, offset);
+ if(output == NULL) {
+ return "";
+ } else {
+ return output;
+ }
+}
+
+int get_binary(char* buff, int* offset, char* output) {
+ int len = get_int(buff, offset);
+ if(len > 0) {
+ memcpy(output, &buff[*offset], len);
+ *offset += len;
+ }
+ return len;
+}
+
+//===============================================================
+//put
+void put_byte(char* buff, int* offset, const char input) {
+ *((char*)&buff[*offset]) = input;
+ *offset += 1;
+}
+
+void put_short(char* buff, int* offset, const short input) {
+ put_byte(buff, offset, input & 0xff);
+ put_byte(buff, offset, (input >> 8) & 0xff);
+}
+
+void put_int(char* buff, int* offset, const int input) {
+ put_short(buff, offset, input & 0xffff);
+ put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void put_long(char* buff, int* offset, const long long input) {
+ put_int(buff, offset, input & 0xffffffffL);
+ put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void put_float(char* buff, int* offset, const float input) {
+ int* data = (int*)&input;
+ put_int(buff, offset, *data);
+}
+
+void put_double(char* buff, int* offset, const double input) {
+ long long* data = (long long*)&input;
+ put_long(buff, offset, *data);
+}
+
+void put_string(char* buff, int* offset, const char* input) {
+ if(input == NULL) {
+ put_byte(buff, offset, 0);
+ } else {
+ int len = strlen(input) + 1;
+ put_byte(buff, offset, 1);
+ put_int(buff, offset, len);
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+ }
+}
+
+void put_binary(char* buff, int* offset, const char* input, const int len) {
+ put_int(buff, offset, len);
+ if(len > 0) {
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+ }
+}
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_interface/cfg/inc/agpsprofile.h b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/cfg/inc/agpsprofile.h
new file mode 100755
index 0000000..7742507
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/cfg/inc/agpsprofile.h
@@ -0,0 +1,65 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2019. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#ifndef __AGPSPROFILE_H__
+#define __AGPSPROFILE_H__
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ char name[64];
+ char addr[128];
+ int port;
+ bool tls;
+} agps_mgr_supl_profile;
+
+typedef struct {
+ int maj_ver;
+ int min_ver;
+ int supl_profiles_num;
+ agps_mgr_supl_profile* supl_profiles;
+} agps_mgr_agps_config;
+
+bool agps_xml_load(agps_mgr_agps_config* xml, const char* path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_interface/cfg/libs/mtkexpat/mtkexpat.c b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/cfg/libs/mtkexpat/mtkexpat.c
new file mode 100755
index 0000000..eceabc3
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/cfg/libs/mtkexpat/mtkexpat.c
@@ -0,0 +1,385 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2019. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include <stdio.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "mtkexpat.h"
+#include "expat.h"
+//#include "utility.h"
+
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+#define MTK_EXPAT_DEBUG_ENABLE 0
+
+void mtk_expat_init(mtk_expat_context* ctx) {
+ if(ctx == NULL) return;
+ ctx->element = NULL;
+ ctx->last_element = &(ctx->element);
+ ctx->last_attr = NULL;
+ sprintf(ctx->error_string, "none");
+}
+
+void mtk_expat_cleanup(mtk_expat_context* ctx) {
+ if(ctx == NULL) return;
+ mtk_expat_element* element = ctx->element;
+ while(element) {
+ if(element->name) {
+ free(element->name);
+ element->name = NULL;
+ }
+ mtk_expat_attribute* attr = element->attr;
+ while(attr) {
+ if(attr->key) {
+ free(attr->key);
+ attr->key = NULL;
+ }
+ if(attr->value) {
+ free(attr->value);
+ attr->value = NULL;
+ }
+ mtk_expat_attribute* tmp_attr = attr;
+ attr = attr->next;
+ free(tmp_attr);
+ }
+ mtk_expat_element* tmp_element = element;
+ element = element->next;
+ free(tmp_element);
+ }
+ mtk_expat_init(ctx);
+}
+
+void mtk_expat_dump(mtk_expat_context* ctx) {
+ printf("mtk_expat_dump()\n");
+ if(ctx == NULL) {
+ printf(" null\n");
+ return;
+ }
+ mtk_expat_element* element = ctx->element;
+ while(element) {
+ printf(" name=[%s]", element->name);
+ mtk_expat_attribute* attr = element->attr;
+ while(attr) {
+ printf(" [%s]=[%s]", attr->key, attr->value);
+ attr = attr->next;
+ }
+ printf("\n");
+ element = element->next;
+ }
+}
+
+void mtk_expat_dump_element(mtk_expat_element* element) {
+ printf("mtk_expat_dump_element\n");
+ if(element == NULL) {
+ printf(" null\n");
+ return;
+ }
+ printf(" name=[%s]", element->name);
+ mtk_expat_attribute* attr = element->attr;
+ while(attr) {
+ printf(" [%s]=[%s]", attr->key, attr->value);
+ attr = attr->next;
+ }
+ printf("\n");
+}
+
+mtk_expat_element* mtk_expat_add_element(mtk_expat_context* ctx, const char* name) {
+ mtk_expat_element* element = NULL;
+ (*ctx->last_element) = malloc(sizeof(mtk_expat_element));
+ element = (*ctx->last_element);
+ memset(element, 0, sizeof(mtk_expat_element));
+ element->name = malloc(strlen(name) + 1);
+ safe_strncpy(element->name, name, strlen(name) + 1);
+ ctx->last_attr = &(element->attr);
+ ctx->last_element = &element->next;
+ return element;
+}
+
+void mtk_expat_add_attr_string(mtk_expat_context* ctx, const char* key, const char* value) {
+ if(ctx->last_attr == NULL) return;
+ (*ctx->last_attr) = malloc(sizeof(mtk_expat_attribute));
+ memset((*ctx->last_attr), 0, sizeof(mtk_expat_attribute));
+ (*ctx->last_attr)->key = malloc(strlen(key) + 1);
+ safe_strncpy((*ctx->last_attr)->key, key, strlen(key) + 1);
+ (*ctx->last_attr)->value = malloc(strlen(value) + 1);
+ safe_strncpy((*ctx->last_attr)->value, value, strlen(value) + 1);
+ ctx->last_attr = &((*ctx->last_attr)->next);
+}
+
+void mtk_expat_add_attr_bool(mtk_expat_context* ctx, const char* key, bool value) {
+ mtk_expat_add_attr_string(ctx, key, value? "true" : "false");
+}
+
+void mtk_expat_add_attr_int(mtk_expat_context* ctx, const char* key, int value) {
+ char tmp[16] = {0};
+ sprintf(tmp, "%d", value);
+ mtk_expat_add_attr_string(ctx, key, tmp);
+}
+
+int mtk_expat_get_element_num(mtk_expat_context* ctx, const char* name) {
+ int count = 0;
+ mtk_expat_element* element = ctx->element;
+ while(element) {
+ if(strcmp(element->name, name) == 0) {
+ count++;
+ }
+ element = element->next;
+ }
+ return count;
+}
+
+mtk_expat_element* mtk_expat_get_element(mtk_expat_context* ctx, const char* name) {
+ mtk_expat_element* element = ctx->element;
+ while(element) {
+ if(strcmp(element->name, name) == 0) {
+ return element;
+ }
+ element = element->next;
+ }
+ return NULL;
+}
+
+mtk_expat_element* mtk_expat_get_element_index(mtk_expat_context* ctx, const char* name, int index) {
+ int count = 0;
+ mtk_expat_element* element = ctx->element;
+ while(element) {
+ if(strcmp(element->name, name) == 0) {
+ if(count == index) {
+ return element;
+ }
+ count++;
+ }
+ element = element->next;
+ }
+ return NULL;
+}
+
+const char* mtk_expat_get_attr_string(mtk_expat_element* element, const char* key, const char* default_value) {
+ if(element == NULL) return default_value;
+ mtk_expat_attribute* attr = element->attr;
+ while(attr) {
+ if(strcmp(attr->key, key) == 0) {
+ return attr->value;
+ }
+ attr = attr->next;
+ }
+ return default_value;
+}
+
+bool mtk_expat_get_attr_bool(mtk_expat_element* element, const char* key, bool default_value) {
+ const char* value = mtk_expat_get_attr_string(element, key, "");
+ if(strcmp(value, "true") == 0) {
+ return true;
+ }
+ if(strcmp(value, "false") == 0) {
+ return false;
+ }
+ return default_value;
+}
+
+int mtk_expat_get_attr_int(mtk_expat_element* element, const char* key, int default_value) {
+ int ret = 0;
+ const char* value = mtk_expat_get_attr_string(element, key, "");
+ if(sscanf((char*)value, "%d", &ret) <= 0) {
+ return default_value;
+ }
+ return ret;
+}
+
+const char* mtk_expat_strerror(mtk_expat_context* ctx) {
+ return ctx->error_string;
+}
+
+static void mtk_expat_xml_save_int(FILE* fp, mtk_expat_context* ctx) {
+ mtk_expat_element* element = ctx->element;
+ mtk_expat_attribute* attr;
+ const char* tag = NULL;
+ if(element) {
+ tag = element->name;
+ fprintf(fp, "<%s", tag);
+ attr = element->attr;
+ while(attr) {
+ fprintf(fp, " %s=\"%s\"", attr->key, attr->value);
+ attr = attr->next;
+ }
+ fprintf(fp, ">\n");
+ element = element->next;
+ }
+
+ while(element) {
+ fprintf(fp, " <%s", element->name);
+ attr = element->attr;
+ while(attr) {
+ fprintf(fp, " %s=\"%s\"", attr->key, attr->value);
+ attr = attr->next;
+ }
+ fprintf(fp, "/>\n");
+ element = element->next;
+ }
+
+ if(tag) {
+ fprintf(fp, "</%s>\n", tag);
+ }
+}
+
+// return false means error and can use mtk_expat_strerror(ctx) to get the error info in the string format
+bool mtk_expat_xml_save(mtk_expat_context* ctx, const char* file) {
+ bool ret = false;
+ FILE* fp = NULL;
+
+ do {
+ fp = fopen(file, "w");
+ if(fp == NULL) {
+
+ sprintf(ctx->error_string, "fopen() failed reason=[%s]", strerror(errno));
+ break;
+ }
+ fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
+ mtk_expat_xml_save_int(fp, ctx);
+
+ ret = true;
+ sprintf(ctx->error_string, "none");
+ } while(0);
+
+ if(fp) {
+ fclose(fp);
+ }
+ return ret;
+}
+
+static int mtk_expat_get_file_size(const char* file) {
+ struct stat s;
+ if(stat(file, &s) == -1) {
+ return -1;
+ }
+ return s.st_size;
+}
+
+//======================= non-reentrant ==================================
+static mtk_expat_context g_expat_ctx;
+static int g_depth = 0;
+
+static void mtk_expat_start_element(void *data, const char *element, const char **attribute) {
+ int i;
+ UNUSED(data);
+ for(i = 0; i < g_depth; i++) {
+ if(MTK_EXPAT_DEBUG_ENABLE) printf(" ");
+ }
+ if(MTK_EXPAT_DEBUG_ENABLE) printf("element=[%s]", element);
+ mtk_expat_add_element(&g_expat_ctx, element);
+
+ for(i = 0; attribute[i]; i += 2) {
+ if(MTK_EXPAT_DEBUG_ENABLE) printf(" [%s]=[%s]", attribute[i], attribute[i + 1]);
+ mtk_expat_add_attr_string(&g_expat_ctx, attribute[i], attribute[i + 1]);
+ }
+
+ if(MTK_EXPAT_DEBUG_ENABLE) printf("\n");
+ g_depth++;
+}
+
+static void mtk_expat_end_element(void *data, const char *el) {
+ UNUSED(data);
+ UNUSED(el);
+ g_depth--;
+}
+
+// this is non-reentrant API, do not call this API from different thread in the same time
+// return false means error and can use mtk_expat_strerror(ctx) to get the error info in the string format
+bool mtk_expat_xml_load(mtk_expat_context* ctx, const char* file) {
+ bool ret = false;
+ XML_Parser parser = NULL;
+ char* buff = NULL;
+ FILE *fp = NULL;
+
+ g_expat_ctx = *ctx;
+
+ do {
+ fp = fopen(file, "r");
+ if(fp == NULL) {
+ sprintf(ctx->error_string, "fopen() failed reason=[%s]", strerror(errno));
+ break;
+ }
+
+ int file_size = mtk_expat_get_file_size(file);
+ if(file_size == -1) {
+ sprintf(ctx->error_string, "stat() failed reason=[%s]", strerror(errno));
+ break;
+ }
+
+ buff = (char*)malloc(file_size);
+ if(buff == NULL) {
+ sprintf(ctx->error_string, "malloc() failed");
+ break;
+ }
+ memset(buff, 0, file_size);
+
+ size_t read_file_size = 0;
+ read_file_size = fread(buff, sizeof(char), file_size, fp);
+ if(read_file_size != (size_t)file_size) {
+ sprintf(ctx->error_string, "fread() failed");
+ break;
+ }
+
+ parser = XML_ParserCreate(NULL);
+ XML_SetElementHandler(parser, mtk_expat_start_element, mtk_expat_end_element);
+ if(XML_Parse(parser, buff, file_size, XML_TRUE) == XML_STATUS_ERROR) {
+ sprintf(ctx->error_string, "XML_Parse() failed reason=[%s]",
+ XML_ErrorString(XML_GetErrorCode(parser)));
+ break;
+ }
+
+ ret = true;
+ sprintf(ctx->error_string, "none");
+ } while(0);
+
+ if(parser) {
+ XML_ParserFree(parser);
+ parser = NULL;
+ }
+ if(buff) {
+ free(buff);
+ buff = NULL;
+ }
+ if(fp) {
+ fclose(fp);
+ fp = NULL;
+ }
+ return ret;
+}
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_interface/cfg/libs/mtkexpat/mtkexpat.h b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/cfg/libs/mtkexpat/mtkexpat.h
new file mode 100755
index 0000000..e6cfefb
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/cfg/libs/mtkexpat/mtkexpat.h
@@ -0,0 +1,104 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2019. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#ifndef __MTKEXPAT_H__
+#define __MTKEXPAT_H__
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _mtk_expat_attribute {
+ //data
+ char* key;
+ char* value;
+ //link
+ struct _mtk_expat_attribute* next;
+} mtk_expat_attribute;
+
+typedef struct _mtk_expat_element {
+ //data
+ char* name;
+ mtk_expat_attribute* attr;
+ //link
+ struct _mtk_expat_element* next;
+} mtk_expat_element;
+
+typedef struct {
+ mtk_expat_element* element;
+
+ //to speed up mtk_expat_add_element()
+ mtk_expat_element** last_element;
+
+ //to speed up mtk_expat_add_attr()
+ mtk_expat_attribute** last_attr;
+
+ char error_string[128];
+} mtk_expat_context;
+
+void mtk_expat_init(mtk_expat_context* ctx);
+void mtk_expat_cleanup(mtk_expat_context* ctx);
+void mtk_expat_dump(mtk_expat_context* ctx);
+void mtk_expat_dump_element(mtk_expat_element* element);
+
+mtk_expat_element* mtk_expat_add_element(mtk_expat_context* ctx, const char* name);
+void mtk_expat_add_attr_bool(mtk_expat_context* ctx, const char* key, bool value);
+void mtk_expat_add_attr_int(mtk_expat_context* ctx, const char* key, int value);
+void mtk_expat_add_attr_string(mtk_expat_context* ctx, const char* key, const char* value);
+
+int mtk_expat_get_element_num(mtk_expat_context* ctx, const char* name);
+mtk_expat_element* mtk_expat_get_element(mtk_expat_context* ctx, const char* name);
+mtk_expat_element* mtk_expat_get_element_index(mtk_expat_context* ctx, const char* name, int index);
+bool mtk_expat_get_attr_bool(mtk_expat_element* element, const char* key, bool default_value);
+int mtk_expat_get_attr_int(mtk_expat_element* element, const char* key, int default_value);
+const char* mtk_expat_get_attr_string(mtk_expat_element* element, const char* key, const char* default_value);
+
+const char* mtk_expat_strerror(mtk_expat_context* ctx);
+
+// return false means error and can use mtk_expat_strerror(ctx) to get the error info in the string format
+bool mtk_expat_xml_save(mtk_expat_context* ctx, const char* file);
+
+// this is non-reentrant API, do not call this API from different thread in the same time
+// return false means error and can use mtk_expat_strerror(ctx) to get the error info in the string format
+bool mtk_expat_xml_load(mtk_expat_context* ctx, const char* file);
+
+char *safe_strncpy(char *dest, const char *src, size_t n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_interface/cfg/src/agpsprofile.c b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/cfg/src/agpsprofile.c
new file mode 100755
index 0000000..d46669c
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/cfg/src/agpsprofile.c
@@ -0,0 +1,170 @@
+/*****************************************************************************
+* Copyright Statement:
+* --------------------
+* This software is protected by Copyright and the information contained
+* herein is confidential. The software may not be copied and the information
+* contained herein may not be used or disclosed except with the written
+* permission of MediaTek Inc. (C) 2019
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "mtkexpat.h"
+#include "agpsprofile.h"
+//#include "utility.h"
+#if defined(__ANDROID_OS__) | defined(__KAIOS__)
+#include <android/log.h>
+#endif
+
+#define AGPS_XML_NODE_MTK_AGPS_PROFILE "mtk_agps_profiles"
+#define AGPS_XML_NODE_SUPL_PROFILE "supl_profile"
+
+char *safe_strncpy(char *dest, const char *src, size_t n) {
+ if (dest && n > 0) {
+ // Use strncat for performance because strncpy will always fill n bytes in dest
+ dest[0] = '\0'; // Let dest be an empty string
+ strncat(dest, src, --n); // n-1 because strncat may fill n+1 bytes
+ }
+ return dest;
+}
+
+#if defined(__ANDROID_OS__) || defined(__KAIOS__)
+static void _LOGD(const char* message) {
+ __android_log_print(ANDROID_LOG_DEBUG, "[agpsprofile]", "%s", message);
+}
+
+static void _LOGW(const char* message) {
+ __android_log_print(ANDROID_LOG_DEBUG, "[agpsprofile] WRN:", "%s", message);
+}
+
+#elif defined(__LINUX_OS__) || defined(__YOCTO_OS__)
+static void _LOGD(const char* message) {
+ printf("%s\n", message);
+ fflush(stdout);
+}
+
+static void _LOGW(const char* message) {
+ printf("%s\n", message);
+ fflush(stdout);
+}
+#endif
+
+static void LOGD(const char *fmt, ...) {
+ char out_buf[1100] = {0};
+ char buf[1024] = {0};
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ sprintf(out_buf, "%s", buf);
+ _LOGD(out_buf);
+}
+
+static void LOGW(const char *fmt, ...) {
+ char out_buf[1100] = {0};
+ char buf[1024] = {0};
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ sprintf(out_buf, "%s", buf);
+ _LOGW(out_buf);
+}
+
+static void agps_xml_init(agps_mgr_agps_config* xml) {
+ memset(xml, 0, sizeof(*xml));
+}
+
+static void agps_xml_get_supl_profile(mtk_expat_element* element, agps_mgr_supl_profile* p) {
+ safe_strncpy(p->name, mtk_expat_get_attr_string(element, "name", ""), sizeof(p->name));
+ safe_strncpy(p->addr, mtk_expat_get_attr_string(element, "addr", ""), sizeof(p->addr));
+ p->port = mtk_expat_get_attr_int(element, "port", 0);
+ p->tls = mtk_expat_get_attr_bool(element, "tls", true);
+}
+
+bool agps_xml_load(agps_mgr_agps_config* xml, const char* path) {
+ int i;
+ int count;
+ bool ret;
+ mtk_expat_context expat_ctx;
+ mtk_expat_element* element = NULL;
+
+ agps_xml_init(xml);
+ mtk_expat_init(&expat_ctx);
+ ret = mtk_expat_xml_load(&expat_ctx, path);
+ if(ret == false) {
+ LOGW("mtk_expat_xml_load() failed reason=[%s]\n", mtk_expat_strerror(&expat_ctx));
+ return false;
+ }
+
+ element = mtk_expat_get_element(&expat_ctx, AGPS_XML_NODE_MTK_AGPS_PROFILE);
+ if(element) {
+ xml->maj_ver = mtk_expat_get_attr_int(element, "maj_ver", 1);
+ xml->min_ver = mtk_expat_get_attr_int(element, "min_ver", 0);
+ }
+
+ count = mtk_expat_get_element_num(&expat_ctx, AGPS_XML_NODE_SUPL_PROFILE);
+ xml->supl_profiles_num = count;
+ xml->supl_profiles = malloc(count * sizeof(agps_mgr_supl_profile));
+ for(i = 0; i < count; i++) {
+ element = mtk_expat_get_element_index(&expat_ctx, AGPS_XML_NODE_SUPL_PROFILE, i);
+ agps_xml_get_supl_profile(element, &xml->supl_profiles[i]);
+ }
+
+ mtk_expat_cleanup(&expat_ctx);
+
+ return true;
+}
+
+#ifdef UNUSED_PLACE
+static void agps_xml_dump_supl_profiles(agps_mgr_agps_config* agps_config) {
+ int i = 0;
+ for(i = 0; i < agps_config->supl_profiles_num; i++) {
+ agps_mgr_supl_profile* profile = &agps_config->supl_profiles[i];
+ LOGD("profile i=%d name=[%s] addr=[%s] port=[%d] tls=[%d]\n",
+ i,
+ profile->name,
+ profile->addr,
+ profile->port,
+ profile->tls);
+ }
+}
+
+void agps_xml_dump(agps_mgr_agps_config* config) {
+ LOGW(" =================== agps_xml_dump ===================\n");
+ agps_xml_dump_supl_profiles(config);
+}
+#endif
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_interface/inc/agps_interface.h b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/inc/agps_interface.h
new file mode 100755
index 0000000..55e173d
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/inc/agps_interface.h
@@ -0,0 +1,2310 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2019. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * agps_interface.h
+ *
+ * Description:
+ * ------------
+ * Use this interface to do the communication with mtk_agpsd to
+ * get/set the AGPS configurations with mtk_agpsd
+ *
+ ****************************************************************************/
+#ifndef __AGPS_INTERFACE_H__
+#define __AGPS_INTERFACE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define agps_bool char
+
+#define AGPS_INTF_STRING_LEN 64
+#define AGPS_SUPL_ADDR_LEN 128
+#define MNL_MCC_STRING_LEN 16
+#define EXTERNAL_ADD_LEN 20
+#define MLC_NUMBER_LEN 20
+#define EPC_MOLR_LPP_PAYLOAD_LEN 300
+#define SUPL_PROFILES_NUM 30
+#define PROFILING_MESSAGE_LEN 64
+#define PROFILING_ELEMENT_NUM 20
+
+// Bits for TC10 CP Capability Control
+#define AGPS_INTF_TC10_CP_CAPABILITY_AGNSS 0x01
+#define AGPS_INTF_TC10_CP_CAPABILITY_OTDOA 0x02
+#define AGPS_INTF_TC10_CP_CAPABILITY_ECID 0x04
+#define AGPS_INTF_TC10_CP_CAPABILITY_CONVENTIONAL_GPS 0x08
+//#define AGPS_INTF_TC10_CP_CAPABILITY_LPP_EXTENSION 0x10 // Use MTK's cp_lppe_enable instead
+#define AGPS_INTF_TC10_CP_CAPABILITY_INTER_FREQ_OTDOA 0x20
+
+// Mode values for TC10 SSL method
+#define AGPS_INTF_TC10_SUPL_SSL_METHOD_NEGOTIATION 0 // Default
+#define AGPS_INTF_TC10_SUPL_SSL_METHOD_SSLV3 1
+#define AGPS_INTF_TC10_SUPL_SSL_METHOD_SSLV23 2
+#define AGPS_INTF_TC10_SUPL_SSL_METHOD_TLSV1 3
+#define AGPS_INTF_TC10_SUPL_SSL_METHOD_TLSV1_1 4
+#define AGPS_INTF_TC10_SUPL_SSL_METHOD_TLSV1_2 5
+
+// Bits for UP_PRIVACY_OVERRIDE_MODE. You can also use a combined value of them
+#define AGPS_INTF_UP_PRIVACY_OVERRIDE_MODE_DEFAULT 0 // no privacy will be overridden
+#define AGPS_INTF_UP_PRIVACY_OVERRIDE_MODE_ALLOW_HIDING_ICON 1 // allow po-supl to hide location icon
+#define AGPS_INTF_UP_PRIVACY_OVERRIDE_MODE_ALLOW_LOCATIONING 2 // accept po-supl even if GVC does not allow locationing
+#define AGPS_INTF_UP_PRIVACY_OVERRIDE_MODE_ALLOW_ESUPL 4 // accept e-supl even if GVC does not allow locationing
+#define AGPS_INTF_UP_PRIVACY_OVERRIDE_MODE_ALLOW_ALL 8 // accept all (Ignore GVC)
+#define AGPS_INTF_UP_PRIVACY_OVERRIDE_MODE_ALLOW_TC10 16 // accept all for TC10 (Ignore GVC, and GPS / AGPS settings)
+
+typedef enum {
+ AGPS_INTF_PDE_IP_TYPE_IPV4 = 0,
+ AGPS_INTF_PDE_IP_TYPE_IPV6 = 1,
+} agps_intf_pde_ip_type;
+
+typedef enum {
+ AGPS_INTF_CDMA_PREFERRED_WCDMA = 0,
+ AGPS_INTF_CDMA_PREFERRED_CDMA = 1,
+ AGPS_INTF_CDMA_PREFERRED_CDMA_FORCE = 2,
+} agps_intf_cdma_preferred;
+
+typedef enum {
+ AGPS_INTF_PREF_METHOD_MSA = 0,
+ AGPS_INTF_PREF_METHOD_MSB = 1,
+ AGPS_INTF_PREF_METHOD_NO_PREF = 2,
+} agps_intf_pref_method;
+
+typedef enum {
+ AGPS_INTF_MOLR_POS_METHOD_LOC_EST = 0,
+ AGPS_INTF_MOLR_POS_METHOD_ASSIST_DATA = 1,
+} agps_intf_molr_pos_method;
+
+typedef enum {
+ AGPS_INTF_AGPS_PROTOCOL_UP = 0,
+ AGPS_INTF_AGPS_PROTOCOL_CP = 1,
+} agps_intf_agps_protocol;
+
+typedef enum {
+ AGPS_INTF_SUPL_VERSION_1 = 1,
+ AGPS_INTF_SUPL_VERSION_2 = 2,
+} agps_intf_supl_version;
+
+typedef enum {
+ AGPS_INTF_TLS_VERSION_1_0 = 0,
+ AGPS_INTF_TLS_VERSION_1_1 = 1,
+ AGPS_INTF_TLS_VERSION_1_2 = 2,
+} agps_intf_tls_version;
+
+typedef enum {
+ agps_intf_area_event_type_entering = 0,
+ agps_intf_area_event_type_inside = 1,
+ agps_intf_area_event_type_outside = 2,
+ agps_intf_area_event_type_leaving = 3,
+} agps_intf_area_event_type;
+
+typedef enum {
+ AGPS_INTF_PROFILING_TYPE_NORMAL = 0,
+ AGPS_INTF_PROFILING_TYPE_WARNING = 1,
+ AGPS_INTF_PROFILING_TYPE_ERROR = 2,
+} agps_intf_profiling_type;
+
+typedef enum {
+ AGPS_INTF_ESUPL_APN_EIMS_IMS = 0,
+ AGPS_INTF_ESUPL_APN_EIMS = 1,
+ AGPS_INTF_ESUPL_APN_IMS = 2,
+ AGPS_INTF_ESUPL_APN_AS_NORMAL = 3,
+} agps_intf_esupl_apn;
+
+typedef enum {
+ AGPS_INTF_SUPL_IP_VERSION_IPV6 = 0,
+ AGPS_INTF_SUPL_IP_VERSION_IPV4 = 1,
+} agps_supl_ip_version_type;
+
+typedef struct {
+ char name[AGPS_INTF_STRING_LEN];
+ char addr[AGPS_SUPL_ADDR_LEN];
+ int port;
+ agps_bool tls;
+ char mcc_mnc[MNL_MCC_STRING_LEN];
+ char app_id[AGPS_INTF_STRING_LEN];
+ char provider_id[AGPS_INTF_STRING_LEN];
+ char default_apn[AGPS_INTF_STRING_LEN];
+ char optional_apn[AGPS_INTF_STRING_LEN];
+ char optional_apn_2[AGPS_INTF_STRING_LEN];
+ char address_type[AGPS_INTF_STRING_LEN];
+} agps_intf_supl_profile;
+
+typedef struct {
+ char name[AGPS_INTF_STRING_LEN];
+ agps_bool mcp_enable;
+ char mcp_addr[AGPS_INTF_STRING_LEN];
+ int mcp_port;
+ agps_bool pde_addr_valid;
+ agps_intf_pde_ip_type pde_ip_type; //0=IPV4 1=IPV6
+ char pde_addr[AGPS_INTF_STRING_LEN];
+ int pde_port;
+ agps_bool pde_url_valid;
+ char pde_url_addr[AGPS_INTF_STRING_LEN];
+} agps_intf_cdma_profile;
+
+typedef struct {
+ agps_bool agps_enable;
+ agps_intf_agps_protocol agps_protocol;
+ agps_bool gpevt;
+ agps_bool e911_gps_icon_enable;
+ agps_bool e911_open_gps;
+ agps_bool tc10_ignore_fw_config;
+ agps_bool lppe_hide_wifi_bt_status;
+ agps_bool lppe_network_location_disable;
+ agps_bool agps_nvram_enable;
+ agps_bool lbs_log_enable;
+ int lppe_crowd_source_confident;
+ agps_bool ignore_si_for_e911; // North America operator 'V' asks us to ignore SI triggered by GMS
+ agps_bool use_tc10_config;
+ agps_bool lppe_def_nlp_enable;
+ int emergency_ext_secs;
+} agps_intf_agps_setting;
+
+typedef struct {
+ agps_intf_molr_pos_method molr_pos_method;
+ agps_bool external_addr_enable;
+ char external_addr[EXTERNAL_ADD_LEN];
+ agps_bool mlc_number_enable;
+ char mlc_number[MLC_NUMBER_LEN];
+ agps_bool cp_auto_reset;
+ agps_bool epc_molr_lpp_payload_enable;
+ int epc_molr_lpp_payload_len;
+ char epc_molr_lpp_payload[EPC_MOLR_LPP_PAYLOAD_LEN];
+ agps_bool cp_lppe_enable;
+ agps_bool support_cp_lppe;
+ agps_bool reject_non911_nilr_enable;
+ agps_bool cp_2g_disable;
+ agps_bool cp_3g_disable;
+ agps_bool cp_4g_disable;
+ agps_bool cp_lppe_wlan_enable;
+ agps_bool cp_lppe_srn_enable;
+ agps_bool cp_lppe_sensor_enable;
+ agps_bool cp_lppe_dbh_enable;
+} agps_intf_cp_setting;
+
+typedef struct {
+ agps_bool ca_enable;
+ agps_bool ni_request;
+ agps_bool roaming;
+ agps_intf_cdma_preferred cdma_preferred;
+ agps_intf_pref_method pref_method;
+ agps_intf_supl_version supl_version;
+ agps_intf_tls_version tls_version;
+ agps_bool supl_log;
+ agps_bool msa_enable;
+ agps_bool msb_enable;
+ agps_bool ecid_enable;
+ agps_bool otdoa_enable;
+ int qop_hacc;
+ int qop_vacc;
+ int qop_loc_age;
+ int qop_delay;
+ agps_bool lpp_enable;
+ agps_bool cert_from_sdcard;
+ agps_bool auto_profile_enable;
+ char ut2;
+ char ut3;
+ agps_bool apn_enable;
+ agps_bool sync_to_slp;
+ agps_bool udp_enable;
+ agps_bool autonomous_enable;
+ agps_bool aflt_enable;
+ agps_bool imsi_enable;
+ char supl_ver_minor;
+ char supl_ver_ser_ind;
+ int sha_version; // 0: SHA1 for SUPL1.0 and SHA256 for SUPL2.0, 1: SHA1 for SUPL1.0 and SUPL2.0, 2: SHA256 for SUPL1.0 and SUPL2.0
+ int preferred_2g3g_cell_age;
+ char ut1;
+ agps_bool no_sensitive_log;
+ agps_bool tls_reuse_enable;
+ agps_bool imsi_cache_enable;
+ agps_bool supl_raw_data_enable;
+ agps_bool tc10_enable;
+ agps_bool tc10_use_apn;
+ agps_bool tc10_use_fw_dns;
+ agps_bool allow_ni_for_gps_off;
+ agps_bool force_otdoa_assist_req;
+ agps_bool up_lppe_enable;
+ agps_intf_esupl_apn esupl_apn_mode;
+ int tcp_keepalive;
+ agps_bool aosp_profile_enable;
+ agps_bool bind_nlp_setting_to_supl;
+ agps_bool up_lppe_wlan_enable;
+ agps_bool up_lppe_srn_enable;
+ agps_bool up_lppe_sensor_enable;
+ agps_bool up_lppe_dbh_enable;
+ int ip_version_prefer; //0=IPv6 prefer 1=IPv4 prefer
+ agps_bool up_lppe_in_2g3g_disable; // For ATT SUPL server
+ agps_bool up_rrlp_in_4g_disable; // For ATT SUPL server
+ agps_bool up_si_disable; // For Sprint
+ agps_bool use_ni_slp; // tc10 (ALPS04423530)
+ agps_bool aosp_pos_mode_enable;
+ int privacy_override_mode;
+} agps_intf_up_setting;
+
+typedef struct {
+ agps_bool sib8_sib16_enable;
+ agps_bool gps_satellite_enable;
+ agps_bool glonass_satellite_enable;
+ agps_bool beidou_satellite_enable;
+ agps_bool galileo_satellite_enable;
+ agps_bool a_glonass_satellite_enable;
+
+ agps_bool gps_satellite_support;
+ agps_bool glonass_satellite_support;
+ agps_bool beidou_satellite_support;
+ agps_bool galileo_satellite_support;
+
+ agps_bool a_gps_satellite_enable;
+ agps_bool a_beidou_satellite_enable;
+ agps_bool a_galileo_satellite_enable;
+
+ agps_bool mnl_support_lppe;
+} agps_intf_gnss_setting;
+
+typedef struct {
+ int supl_profiles_num;
+ agps_intf_supl_profile supl_profiles[SUPL_PROFILES_NUM];
+ agps_intf_supl_profile cur_supl_profile;
+ agps_intf_cdma_profile cdma_profile;
+ agps_intf_agps_setting agps_setting;
+ agps_intf_cp_setting cp_setting;
+ agps_intf_up_setting up_setting;
+ agps_intf_gnss_setting gnss_setting;
+ agps_bool valid;
+} agps_intf_agps_config;
+
+typedef struct {
+ agps_intf_profiling_type type;
+ long long timestamp;
+ char message[PROFILING_MESSAGE_LEN];
+} agps_intf_profiling_element;
+
+typedef struct {
+ int element_num;
+ agps_intf_profiling_element elements[PROFILING_ELEMENT_NUM];
+} agps_intf_profiling_info;
+
+typedef struct {
+ agps_bool valid;
+ char agpsd_version_string[AGPS_INTF_STRING_LEN];
+} agps_intf_agpsd_version;
+
+typedef struct {
+ agps_bool valid;
+ char imsi[AGPS_INTF_STRING_LEN];
+ agps_bool is_2_digit_mnc;
+} agps_intf_imsi;
+
+/*****************************************************************************
+ * FUNCTION
+ * get_agps_config_v3
+ * DESCRIPTION
+ * get the current agps configuration from mtk_agpsd.
+ * fill supl_profiles.
+ * fill cur_supl_profile.
+ * fill agps_setting.
+ * fill cp_setting.
+ * fill up_setting to cert_from_sdcard.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * agps_intf_agps_config
+ *****************************************************************************/
+agps_intf_agps_config get_agps_config_v3();
+
+/*****************************************************************************
+ * FUNCTION
+ * get_agps_config_v14
+ * DESCRIPTION
+ * get the current agps configuration from mtk_agpsd.
+ * fill agps_intf_up_setting to supl_ver_ser_ind.
+ * fill agps_intf_gnss_setting to galileo_satellite_support.
+ * fill cdma_profile
+ * PARAMETERS
+ * none
+ * RETURNS
+ * agps_intf_agps_config
+ *****************************************************************************/
+agps_intf_agps_config get_agps_config_v14();
+
+/*****************************************************************************
+ * FUNCTION
+ * get_agps_config_v20
+ * DESCRIPTION
+ * get the current agps configuration from mtk_agpsd.
+ * fill sib8_16_enable, gnss_enable, and gnss_support.
+ * fill supl_ver_minor, supl_ver_ser_ind.
+ * fill a_glonass_satellite_enable
+ * fill cdma profiles
+ * fill e911_gps_icon_enable
+ * fill e911_open_gps
+ * fill a_beidou_satellite_enable, a_galileo_satellite_enable
+ * fill supl_raw_data_enable, allow_ni_for_gps_off, force_otdoa_assist_req
+ * fill lppe_network_location_disable, cp_lppe_enable, up_lppe_enable
+ * fill support_cp_lppe and mnl_support_lppe
+ * PARAMETERS
+ * none
+ * RETURNS
+ * agps_intf_agps_config
+ *****************************************************************************/
+agps_intf_agps_config get_agps_config_v20();
+
+/*****************************************************************************
+ * FUNCTION
+ * get_agps_config_v21
+ * DESCRIPTION
+ * get the current agps configuration from mtk_agpsd.
+ * fill agps_nvram_enable, lbs_log_enable, lppe_crowd_source_confident
+ * fill esupl_apn_mode, tcp_keepalive, aosp_profile_enable, bind_nlp_setting_to_supl
+ * PARAMETERS
+ * none
+ * RETURNS
+ * agps_intf_agps_config
+ *****************************************************************************/
+agps_intf_agps_config get_agps_config_v21();
+
+/*****************************************************************************
+ * FUNCTION
+ * get_agps_config_v22
+ * DESCRIPTION
+ * get the current agps configuration from mtk_agpsd.
+ * fill ignore_si_for_e911, cp_lppe_wlan_enable, cp_lppe_srn_enable, cp_lppe_sensor_enable,
+ * fill cp_lppe_dbh_enable, up_lppe_wlan_enable, up_lppe_srn_enable, up_lppe_sensor_enable,
+ * fill up_lppe_dbh_enable, ip_version_prefer, up_lpp_in_2g3g_disable, up_rrlp_in_4g_disable,
+ * fill up_si_disable,
+ * PARAMETERS
+ * none
+ * RETURNS
+ * agps_intf_agps_config
+ *****************************************************************************/
+agps_intf_agps_config get_agps_config_v22();
+
+/*****************************************************************************
+ * FUNCTION
+ * get_agps_config_v23
+ * DESCRIPTION
+ * get the current agps configuration from mtk_agpsd.
+ * fill use_ni_slp, use_tc10_config, lppe_def_nlp_enable
+ * PARAMETERS
+ * none
+ * RETURNS
+ * agps_intf_agps_config
+ *****************************************************************************/
+agps_intf_agps_config get_agps_config_v23();
+
+/*****************************************************************************
+ * FUNCTION
+ * get_agps_config_v24
+ * DESCRIPTION
+ * get the current agps configuration from mtk_agpsd.
+ * fill emergency_ext_secs, aosp_pos_mode_enable, privacy_override_mode
+ * PARAMETERS
+ * none
+ * RETURNS
+ * agps_intf_agps_config
+ *****************************************************************************/
+agps_intf_agps_config get_agps_config_v24();
+
+/*****************************************************************************
+ * FUNCTION
+ * get_cdma_profile
+ * DESCRIPTION
+ * get the cdma profiles.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * agps_intf_cdma_profile
+ *****************************************************************************/
+agps_intf_cdma_profile get_cdma_profile();
+
+/*****************************************************************************
+ * FUNCTION
+ * get_supl_profile
+ * DESCRIPTION
+ * get the current agps supl profile from mtk_agpsd.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * agps_intf_supl_profile
+ *****************************************************************************/
+agps_intf_supl_profile get_supl_profile();
+
+/*****************************************************************************
+ * FUNCTION
+ * get_agps_profiling_info
+ * DESCRIPTION
+ * get the current agps profiling information from mtk_agpsd.
+ * (just for debugging)
+ * PARAMETERS
+ * none
+ * RETURNS
+ * agps_intf_supl_profile
+ *****************************************************************************/
+agps_intf_profiling_info get_agps_profiling_info();
+
+/*****************************************************************************
+ * FUNCTION
+ * get_emulator_mode
+ * DESCRIPTION
+ * get the current agps emulator mode from mtk_agpsd.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * normal mode (0), emulator mode (1)
+ *****************************************************************************/
+int get_emulator_mode();
+
+/*****************************************************************************
+ * FUNCTION
+ * get_agpsd_version
+ * DESCRIPTION
+ * get the current mtk_agpsd version
+ * PARAMETERS
+ * none
+ * RETURNS
+ * agps_intf_agpsd_version
+ *****************************************************************************/
+agps_intf_agpsd_version get_agpsd_version();
+
+/*****************************************************************************
+ * FUNCTION
+ * get_imsi_from_agpsd
+ * DESCRIPTION
+ * get the current imsi stored in the state of mtk_agpsd
+ * PARAMETERS
+ * none
+ * RETURNS
+ * agps_intf_imsi
+ *****************************************************************************/
+agps_intf_imsi get_imsi_from_agpsd();
+
+/*****************************************************************************
+ * FUNCTION
+ * set_agps_enabled
+ * DESCRIPTION
+ * enable/disable AGPS status.
+ * PARAMETERS
+ * enabled [INPUT] 0: SUPL SET Initiated will not be triggered anymore.
+ * 1: SUPL SET Initiated will be triggered if MNLD need help from mtk_agpsd.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_agps_enabled(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_protocol
+ * DESCRIPTION
+ * change AGPS protocol to CP or UP only for SET Initiated session.
+ * PARAMETERS
+ * protocol [INPUT] AGPS_INTF_AGPS_PROTOCOL_UP: UP (SUPL) SET Initiated will be triggered if MNLD need help from mtk_agpsd.
+ * AGPS_INTF_AGPS_PROTOCOL_CP: CP MOLR session will be triggered if MNLD need help from mtk_agpsd.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_protocol(agps_intf_agps_protocol protocol);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_cdma_pref
+ * DESCRIPTION
+ * change CDMA preferred setting only for SET Initiated session.
+ * PARAMETERS
+ * cdma_preferred [INPUT] AGPS_INTF_CDMA_PREFERRED_WCDMA: mtk_agpsd prefers to use SUPL under Wi-Fi connection or WCDMA connection, otherwise use AGPS EVDO sesion.
+ * AGPS_INTF_CDMA_PREFERRED_CDMA: mtk_agpsd prefers to use SUPL under Wi-Fi connection or WCDMA connection, otherwise use AGPS EVDO sesion.
+ * AGPS_INTF_CDMA_PREFERRED_CDMA_FORCE: mtk_agpsd always choose to use AGPS EVDO session.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_cdma_pref(agps_intf_cdma_preferred cdma_preferred);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_pref_method
+ * DESCRIPTION
+ * change UP prefer method only for SET Initiated session.
+ * PARAMETERS
+ * pref_method [INPUT] AGPS_INTF_PREF_METHOD_MSA: set SETCapabilities.prefMethod to agpsSETassistedPreferred in SUPL_START message.
+ * AGPS_INTF_PREF_METHOD_MSB: set SETCapabilities.prefMethod to agpsSETBasedPreferred in SUPL_START message.
+ * AGPS_INTF_PREF_METHOD_NO_PREF: set SETCapabilities.prefMethod to noPreference in SUPL_START message.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_pref_method(agps_intf_pref_method pref_method);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_pos_technology_msa
+ * DESCRIPTION
+ * enable/disable SETCapabilities.PosTechnology.agpsSETassisted in SUPL messages.
+ * PARAMETERS
+ * enabled [INPUT] 0: SETCapabilities.PosTechnology.agpsSETassisted is disabled.
+ * 1: SETCapabilities.PosTechnology.agpsSETassisted is enabled.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_pos_technology_msa(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_pos_technology_msb
+ * DESCRIPTION
+ * enable/disable SETCapabilities.PosTechnology.agpsSETBased in SUPL messages.
+ * PARAMETERS
+ * enabled [INPUT] 0: SETCapabilities.PosTechnology.agpsSETBased is disabled.
+ * 1: SETCapabilities.PosTechnology.agpsSETBased is enabled.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_pos_technology_msb(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_pos_technology_ecid
+ * DESCRIPTION
+ * enable/disable SETCapabilities.PosTechnology.eCID in SUPL messages.
+ * PARAMETERS
+ * enabled [INPUT] 0: SETCapabilities.PosTechnology.eCID is disabled.
+ * 1: SETCapabilities.PosTechnology.eCID is enabled.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_pos_technology_ecid(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_pos_technology_otdoa
+ * DESCRIPTION
+ * enable/disable SETCapabilities.PosTechnology.oTDOA in SUPL messages.
+ * PARAMETERS
+ * enabled [INPUT] 0: SETCapabilities.PosTechnology.oTDOA is disabled.
+ * 1: SETCapabilities.PosTechnology.oTDOA is enabled.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_pos_technology_otdoa(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_supl_version
+ * DESCRIPTION
+ * change SUPL version.
+ * PARAMETERS
+ * supl_version [INPUT] AGPS_INTF_SUPL_VERSION_1: change to SUPL1.0.
+ * AGPS_INTF_SUPL_VERSION_2: change to SUPL2.0.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_supl_version(agps_intf_supl_version supl_version);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_tls_version
+ * DESCRIPTION
+ * change TLS version.
+ * PARAMETERS
+ * tls_version [INPUT] AGPS_INTF_TLS_VERSION_1_0: change to TLS 1.0.
+ * AGPS_INTF_TLS_VERSION_1_1: change to TLS 1.1.
+ * AGPS_INTF_TLS_VERSION_1_2: change to TLS 1.2.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_tls_version(agps_intf_tls_version tls_version);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_cert_verify
+ * DESCRIPTION
+ * enable/disable AGPS certification verificaton procedure.
+ * PARAMETERS
+ * enabled [INPUT] 0: do not check certificate chain sent by server.
+ * 1: check certificate chain sent by server.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_cert_verify(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_udp_enable
+ * DESCRIPTION
+ * enable mtk_agpsd to bind the port, 7275, for listening SUPL_INIT message from UDP.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_udp_enable();
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lpp_enable
+ * DESCRIPTION
+ * enable/disable SETCapabilities.PosProtocol.Ver2-PosProtocol-extension.lpp in SUPL messages.
+ * PARAMETERS
+ * enabled [INPUT] 0: SETCapabilities.PosProtocol.Ver2-PosProtocol-extension.lpp is disabled.
+ * 1: SETCapabilities.PosProtocol.Ver2-PosProtocol-extension.lpp is enabled.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lpp_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_cert_from_sdcard
+ * DESCRIPTION
+ * enable/disable mtk_agpsd to load the extra AGPS certfications from /sdcard/agps/cacerts/,
+ * the certification file format must be PEM or ASN1.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable to load extra AGPS certfications from /sdcard/agps/cacerts/.
+ * 1: enable to load extra AGPS certfications from /sdcard/agps/cacerts/.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_cert_from_sdcard(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_supl_profile
+ * DESCRIPTION
+ * change SUPL profile.
+ * PARAMETERS
+ * addr [INPUT] Server address, it can be IP address or FQDN.
+ * port [INPUT] Server Port.
+ * tls_enabled [INPUT] 0: disable TLS connection with this Server.
+ * 1: enable TLS connection with this Server.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_supl_profile(const char* addr, int port, agps_bool tls_enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_qop
+ * DESCRIPTION
+ * change SUPL QoP only for SET Initiated session.
+ * PARAMETERS
+ * hacc [INPUT] change QoP.horacc (K value).
+ * vacc [INPUT] change QoP.veracc (K value).
+ * loc_age [INPUT] change QoP.maxLocAge, seconds from 0 to 65535.
+ * delay [INPUT] change QoP.delay, 2^N, N from (0..7), unit is seconds.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_qop(int hacc, int vacc, int loc_age, int delay);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_molr_pos_methd
+ * DESCRIPTION
+ * change AGPS CP position method only for MOLR session.
+ * PARAMETERS
+ * molr_pos_method [INPUT] AGPS_INTF_MOLR_POS_METHOD_LOC_EST: change to LocationEstimate.
+ * AGPS_INTF_MOLR_POS_METHOD_ASSIST_DATA: change to AssistanceData.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_molr_pos_methd(agps_intf_molr_pos_method molr_pos_method);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_external_addr
+ * DESCRIPTION
+ * enable/disable AGPS CP external address only for MOLR session.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable AGPS CP external address only for MOLR session.
+ * 1: enable AGPS CP external address only for MOLR session.
+ * external_addr [INPUT] external address
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_external_addr(agps_bool enabled, const char* external_addr);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_mlc_number
+ * DESCRIPTION
+ * enable/disable AGPS CP MLC number only for MOLR session.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable AGPS CP MLC number only for MOLR session.
+ * 1: enable AGPS CP MLC number only for MOLR session.
+ * mlc_number [INPUT] MLC number
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_mlc_number(agps_bool enabled, const char* mlc_number);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_cp_auto_reset
+ * DESCRIPTION
+ * enable/disable CP automatically reset funcationlity.
+ * In some test scenario, there is no GPS_RESET command from NW, then we need to enable this feature.
+ * After enabling this feature, MD AGPS will issue GPS_RESET by itself when AGPS session is finished
+ * to make sure there is a GPS_RESET between each AGPS session
+ * PARAMETERS
+ * enabled [INPUT] 0: disable CP automatically reset funcationlity.
+ * 1: enable CP automatically reset funcationlity.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_cp_auto_reset(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_allow_ni
+ * DESCRIPTION
+ * enable/disable AGPS UP Network Initiated session.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable AGPS UP Network Initiated session.
+ * 1: eable AGPS UP Network Initiated session.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_allow_ni(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_allow_roaming
+ * DESCRIPTION
+ * enable/disable AGPS UP session when DUT is under roaming.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable AGPS UP session when DUT is under roaming.
+ * 1: enable AGPS UP session when DUT is under roaming.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_allow_roaming(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_supl_to_file
+ * DESCRIPTION
+ * enable/disable SUPL log to /sdcard/A-GPS.LOG or /data/agps_supl/log/A-GPS.LOG.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable SUPL log to /sdcard/A-GPS.LOG or /data/agps_supl/log/A-GPS.LOG.
+ * 1: enable SUPL log to /sdcard/A-GPS.LOG or /data/agps_supl/log/A-GPS.LOG.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_supl_to_file(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_reset_to_default
+ * DESCRIPTION
+ * reset all AGPS configurations to the default setting.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_reset_to_default();
+
+/*****************************************************************************
+ * FUNCTION
+ * set_supl_profile_full
+ * DESCRIPTION
+ * change SUPL profile.
+ * PARAMETERS
+ * supl_profile [INPUT] specify SUPL profile in detail.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_supl_profile_full(agps_intf_supl_profile supl_profile);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_epc_molr_pdu_enable
+ * DESCRIPTION
+ * enable/disable AGPS CP EPC MOLR PDU only for MOLR session in LTE network.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable AGPS CP EPC MOLR PDU only for MOLR session in LTE network.
+ * 1: enable AGPS CP EPC MOLR PDU only for MOLR session in LTE network.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_epc_molr_pdu_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_epc_molr_pdu
+ * DESCRIPTION
+ * change AGPS CP EPC MOLR PDU only for MOLR session in LTE network.
+ * PARAMETERS
+ * data [INPUT] AGPS CP EPC MOLR PDU.
+ * data_len [INPUT] length of data.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_epc_molr_pdu(const char* data, int data_len);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_imsi_enable
+ * DESCRIPTION
+ * enable/disable the valid IMSI in SUPL messages.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the valid IMSI in SUPL messages.
+ * 1: enable the valid IMSI in SUPL messages, this follows the OMA spec.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_imsi_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_supl_sha_version
+ * DESCRIPTION
+ * change the SUPL SHA version.
+ * PARAMETERS
+ * enabled [INPUT] 0: SHA1 for SUPL1.0 and SHA256 for SUPL2.0.
+ * 1: SHA1 for SUPL1.0 and SUPL2.0.
+ * 2: SHA256 for SUPL1.0 and SUPL2.0.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_supl_sha_version(int version);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_supl_tls_version
+ * DESCRIPTION
+ * change the SUPL TLS version.
+ * PARAMETERS
+ * enabled [INPUT] 0: TLS1.0.
+ * 1: TLS1.1.
+ * 2: TLS1.2.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_supl_tls_version(int version);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_supl_ut1
+ * DESCRIPTION
+ * change the SUPL UT1 Timer.
+ * PARAMETERS
+ * timeout_in_second [INPUT] 11 (default) ~ 127
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_supl_ut1(int timeout_in_second);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_supl_ut2
+ * DESCRIPTION
+ * change the SUPL UT2 Timer.
+ * PARAMETERS
+ * timeout_in_second [INPUT] 11 (default) ~ 127
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_supl_ut2(int timeout_in_second);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_supl_ut3
+ * DESCRIPTION
+ * change the SUPL UT3 Timer.
+ * PARAMETERS
+ * timeout_in_second [INPUT] 10 (default) ~ 127
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_supl_ut3(int timeout_in_second);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_supl_ver_minor
+ * DESCRIPTION
+ * change the SUPL minor version.
+ * PARAMETERS
+ * version [INPUT] 0 (default) ~ 255
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_supl_ver_minor(int version);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_supl_ver_ser_ind
+ * DESCRIPTION
+ * change the SUPL servind version.
+ * PARAMETERS
+ * version [INPUT] 0 (default) ~ 255
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_supl_ver_ser_ind(int version);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_sib8_16_enable
+ * DESCRIPTION
+ * enable/disable SIB8/SIB16.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable SIB8/SIB16.
+ * 1: enable SIB8/SIB16. (default)
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_sib8_16_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_glonass_enable
+ * DESCRIPTION
+ * enable/disable Glonass.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable Glonass.
+ * 1: enable Glonass. (default)
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_glonass_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_a_glonass_enable
+ * DESCRIPTION
+ * enable/disable A-Glonass.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable A-Glonass.
+ * 1: enable A-Glonass. (default)
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_a_glonass_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_beidou_enable
+ * DESCRIPTION
+ * enable/disable Beidou.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable Beidou.
+ * 1: enable Beidou. (default)
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_beidou_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_galileo_enable
+ * DESCRIPTION
+ * enable/disable Galileo.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable Gelileo.
+ * 1: enable Gelileo. (default)
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_galileo_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_supl_apn_enable
+ * DESCRIPTION
+ * enable/disable SUPL APN.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable SUPL APN. (default)
+ * 1: enable SUPL APN.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_supl_apn_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_pde_profile
+ * DESCRIPTION
+ * set pde profile.
+ * PARAMETERS
+ * addr [INPUT] Server IP as "11.11.11.11".
+ * port [INPUT] Server Port.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_pde_profile(const char* addr, int port);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_reject_non911_nilr_enable
+ * DESCRIPTION
+ * set reject NILR if there is no E911 call and GPS setting is OFF.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable to reject NILR if there is no E911 call
+ * and GPS setting is OFF (default)
+ * 1: enable to reject NILR if there is no E911 call
+ * and GPS setting is OFF
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_reject_non911_nilr_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_allow_ni_for_gps_off
+ * DESCRIPTION
+ * set allow SUPL NI if GPS setting is OFF
+ * PARAMETERS
+ * enabled [INPUT] 0: disable to SUPL NI if GPS setting is OFF (default)
+ * 1: enable to SUPL NI if GPS setting is OFF
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_allow_ni_for_gps_off(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_force_otdoa_assist_req
+ * DESCRIPTION
+ * set if forcing filling otdoa assist request in SUPL LPP in a SET-assisted
+ * session
+ * PARAMETERS
+ * enabled [INPUT] 0: do not fill otdoa assist request in SUPL LPP in a
+ * SET-assisted session (default)
+ * 1: fill otdoa assist request in SUPL LPP in a
+ * SET-assisted session
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_force_otdoa_assist_req(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_cp_2g_disable
+ * DESCRIPTION
+ * set if we need to disable Control Plane AGPS for GSM network
+ * PARAMETERS
+ * enabled [INPUT] 0: do not disable CP AGPS for GSM
+ * 1: disable CP AGPS for GSM
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_cp_2g_disable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_cp_3g_disable
+ * DESCRIPTION
+ * set if we need to disable Control Plane AGPS for WCDMA network
+ * PARAMETERS
+ * enabled [INPUT] 0: do not disable CP AGPS for WCDMA
+ * 1: disable CP AGPS for WCDMA
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_cp_3g_disable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_cp_4g_disable
+ * DESCRIPTION
+ * set if we need to disable Control Plane AGPS for LTE network
+ * PARAMETERS
+ * enabled [INPUT] 0: do not disable CP AGPS for LTE
+ * 1: disable CP AGPS for LTE
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_cp_4g_disable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_tc10_ignore_fw_config
+ * DESCRIPTION
+ * set if we need to ignore configuration from TC10 Location Framework
+ * PARAMETERS
+ * enabled [INPUT] 0: do not ignore configuration from TC10 Location Framework
+ * 1: ignore configuration from TC10 Location Framework
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_tc10_ignore_fw_config(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lppe_hide_wifi_bt_status
+ * DESCRIPTION
+ * decide if lppe needs to hide the wifi/bt icon when users disable the wifi/bt in settings
+ * (This may not work if the platfrom does not support it)
+ * PARAMETERS
+ * enabled [INPUT] 0: disable lppe to hide icon
+ * 1: enable lppe to hide icon
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lppe_hide_wifi_bt_status(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lppe_network_location_disable
+ * DESCRIPTION
+ * tell lppe if it is not allowed to use the network location
+ * PARAMETERS
+ * enabled [INPUT] 0: allowed to use the network location
+ * 1: not allowed to use the network location
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lppe_network_location_disable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_e911_open_gps_enable
+ * DESCRIPTION
+ * enable/disable opening GPS earlier when E911 call is dialed
+ * PARAMETERS
+ * enabled [INPUT] 0: do not need to open GPS earlier for e911
+ * 1: allowed to open GPS earlier for e911
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_e911_open_gps_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lppe_cp_enable
+ * DESCRIPTION
+ * enable/disable lppe for cp (control plane)
+ * PARAMETERS
+ * enabled [INPUT] 0: disable lppe for cp
+ * 1: enable lppe for cp (default)
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lppe_cp_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lppe_up_enable
+ * DESCRIPTION
+ * enable/disable lppe for up (user plane)
+ * PARAMETERS
+ * enabled [INPUT] 0: disable lppe for up
+ * 1: enable lppe for up (default)
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lppe_up_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_vzw_debug_screen_enable
+ * DESCRIPTION
+ * enable/disable showing debug info in LocationEM as per VZW's request
+ * PARAMETERS
+ * enabled [INPUT] 0: disable showing debug info in LocationEM as per
+ * VZW's request
+ * 1: enable showing debug info in LocationEM as per
+ * VZW's request
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_vzw_debug_screen_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lppe_crowd_source_confident
+ * DESCRIPTION
+ * specify the value of lppe crowd source confidence
+ * PARAMETERS
+ * confident [INPUT] 0 ~ 99
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lppe_crowd_source_confident(int confident);
+
+/*****************************************************************************
+ * FUNCTION
+ * start_supl_2_periodic_session
+ * DESCRIPTION
+ * start SUPL2.0 periodic session.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * none
+ *****************************************************************************/
+void start_supl_2_periodic_session();
+
+/*****************************************************************************
+ * FUNCTION
+ * stop_supl_2_periodic_session
+ * DESCRIPTION
+ * stop SUPL2.0 periodic session.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * none
+ *****************************************************************************/
+void stop_supl_2_periodic_session();
+
+/*****************************************************************************
+ * FUNCTION
+ * start_supl_2_area_event_session
+ * DESCRIPTION
+ * start SUPL2.0 area event session.
+ * PARAMETERS
+ * type [INPUT] agps_intf_area_event_type_entering: area event type is entering.
+ * agps_intf_area_event_type_inside: area event type is inside.
+ * agps_intf_area_event_type_outside: area event type is outside.
+ * agps_intf_area_event_type_leaving: area event type is leaving.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void start_supl_2_area_event_session(agps_intf_area_event_type type);
+
+/*****************************************************************************
+ * FUNCTION
+ * stop_supl_2_area_event_session
+ * DESCRIPTION
+ * stop SUPL2.0 area event session.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * none
+ *****************************************************************************/
+void stop_supl_2_area_event_session();
+
+/*****************************************************************************
+ * FUNCTION
+ * start_test_case
+ * DESCRIPTION
+ * start the test case, just for debugging
+ * PARAMETERS
+ * i [INPUT] 0: All TC Loop 1
+ * 1: All TC Loop 2
+ * 2: All TC Loop 1000
+ * 3: All Common TC
+ * 4: All UP TC
+ * 5: All UP TC
+ * 6: All EVDO TC
+ * 7: Partial TC 1
+ * 8: pARTIAL TC 2
+ * RETURNS
+ * none
+ *****************************************************************************/
+void start_test_case(int i);
+
+/*****************************************************************************
+ * FUNCTION
+ * start_test_button
+ * DESCRIPTION
+ * start the test button, just for debugging
+ * PARAMETERS
+ * i [INPUT] 0: agps2mnl_agps_open_gps_req(1);
+ * 1: agps2mnl_agps_close_gps_req();
+ * 2: agps2mnl_agps_reset_gps_req(0xffff);
+ * 3: agps2mnl_ni_notify(2, MNL_AGPS_NOTIFY_TYPE_NOTIFY_ONLY, "hugo_requestor2", "hugo_client")
+ * 4: agps2mnl_ni_notify(3, MNL_AGPS_NOTIFY_TYPE_NOTIFY_ALLOW_NO_ANSWER, "hugo_requestor3", "hugo_client");
+ * 5: agps2mnl_ni_notify2(123, MNL_AGPS_NOTIFY_TYPE_NOTIFY_ONLY, "4875676F526571756573746F72", "4875676F436C69656E74", MNL_AGPS_NI_ENCODING_TYPE_UTF8, MNL_AGPS_NI_ENCODING_TYPE_UTF8);
+ * 6: agps2mnl_ni_notify2(123, MNL_AGPS_NOTIFY_TYPE_NOTIFY_DENY_NO_ANSWER, "FEFF004800750067006F0052006500710075006500730074006F0072", "FEFF004800750067006F0043006C00690065006E0074", MNL_AGPS_NI_ENCODING_TYPE_UCS2, MNL_AGPS_NI_ENCODING_TYPE_UCS2);
+ * 7: agps2mnl_data_conn_req(0x12345678, 0)
+ * 8: agps2mnl_data_conn_release()
+ * 9: cp2_util_send_sim_info_req(get_cp2_ctx()->fds.mdfd1)
+ * 10: cp2_util_send_data_connection_state_req(get_cp2_ctx()->fds.mdfd1)
+ * RETURNS
+ * none
+ *****************************************************************************/
+void start_test_button(int i);
+
+/*****************************************************************************
+ * FUNCTION
+ * do_reset_agpsd
+ * DESCRIPTION
+ * reboot mtk_agpsd, it is only for debugging.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * none
+ *****************************************************************************/
+void do_reset_agpsd();
+
+/*****************************************************************************
+ * FUNCTION
+ * start_emualator_mode
+ * DESCRIPTION
+ * enable/disable mtk_agpsd emualtor mode, it will also cause reboot mtk_agpsd.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable mtk_agpsd emualtor mode, it will also cause reboot mtk_agpsd.
+ * 1: enable mtk_agpsd emualtor mode, it will also cause reboot mtk_agpsd.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void start_emualator_mode(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * dump_agps_intf_supl_profile
+ * DESCRIPTION
+ * dump dump_agps_intf_supl_profile, just for debugging
+ * PARAMETERS
+ * profile [INPUT] dump all parameters to log
+ * RETURNS
+ * none
+ *****************************************************************************/
+void dump_agps_intf_supl_profile(agps_intf_supl_profile profile);
+
+/*****************************************************************************
+ * FUNCTION
+ * dump_agps_intf_agps_config
+ * DESCRIPTION
+ * dump dump_agps_intf_agps_config, just for debugging
+ * PARAMETERS
+ * agps_intf_agps_config [INPUT] dump all parameters to log
+ * RETURNS
+ * none
+ *****************************************************************************/
+void dump_agps_intf_agps_config(agps_intf_agps_config config);
+
+/*****************************************************************************
+ * FUNCTION
+ * dump_agps_intf_profiling_info
+ * DESCRIPTION
+ * dump dump_agps_intf_profiling_info, just for debugging
+ * PARAMETERS
+ * profiling [INPUT] dump all parameters to log
+ * RETURNS
+ * none
+ *****************************************************************************/
+void dump_agps_intf_profiling_info(agps_intf_profiling_info profiling);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_pos_technology_autonomous
+ * DESCRIPTION
+ * enable/disable the Autonomous capability
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the autonomous capability
+ * 1: enable the autonomous capability
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_pos_technology_autonomous(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_pos_technology_aflt
+ * DESCRIPTION
+ * enable/disable the AFLT capability
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the AFLT capability
+ * 1: enable the AFLT capability
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_pos_technology_aflt(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_preferred_2g3g_cell_age
+ * DESCRIPTION
+ * set the max age of preferred cell
+ * RAT of cell info: (older, preferred) 2G, 3G, 4G, 5G (newer, not preferred)
+ * PARAMETERS
+ * age [INPUT] 0 ~ 1800 in seconds
+ * 0: do not use preferred cell info. Use the latest cell info
+ * RETURNS
+ * none
+
+ *****************************************************************************/
+void set_preferred_2g3g_cell_age(int age);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_no_sensitive_log
+ * DESCRIPTION
+ * remove/allow agps daemon's log with sensitive info (e.g., the current location)
+ * PARAMETERS
+ * enabled [INPUT] 0: allow agps daemon's to log with sensitive info (e.g., the current location)
+ * 1: Agps not to log sensitive logs.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_no_sensitive_log(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_tls_reuse_enable
+ * DESCRIPTION
+ * enable/disable TLS reuse
+ * PARAMETERS
+ * enabled [INPUT] 0: disable TLS reuse (default)
+ * 1: ensable TLS reuse
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_tls_reuse_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_imsi_cache_enable
+ * DESCRIPTION
+ * enable/disable cached IMSI
+ * PARAMETERS
+ * enabled [INPUT] 0: disable cached IMSI (default)
+ * do not update IMSI for each SUPL session
+ * 1: enable cached IMSI
+ * update IMSI for each SUPL session
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_imsi_cache_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_supl_raw_data_enable
+ * DESCRIPTION
+ * enable/disable SUPL raw data log in main log
+ * PARAMETERS
+ * enabled [INPUT] 0: disable SUPL raw data log in main log
+ * 1: enable SUPL raw data log in main log
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_supl_raw_data_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_tc10_enable
+ * DESCRIPTION
+ * enable/disable TC10 mode
+ * PARAMETERS
+ * enabled [INPUT] 0: disable TC10 mode
+ * 1: enable TC10 mode
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_tc10_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_auto_profile_enable
+ * DESCRIPTION
+ * enable/disable the auto profile configuration based on current mcc or mcc_mnc specified in cur_supl_profile or supl_profile
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the auto profile configuration feature
+ * 1: enable the auto profile configuration feature
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_auto_profile_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_sync_to_slp_enable
+ * DESCRIPTION
+ * sync the AGPS setting (ex: SUPL profile, SUPL version, TLS version) from AGPSD to SLPD in runtime
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the AGPS settings sync to SPLD function
+ * 1: enable the AGPS settings sync to SPLD function
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_sync_to_slp_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_e911_gps_icon_enable
+ * DESCRIPTION
+ * enable/disable showing GPS icon during E911 location
+ * PARAMETERS
+ * enabled [INPUT] 0: disable showing the GPS icon
+ * 1: enable showing the GPS icon
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_e911_gps_icon_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_aosp_profile_enable
+ * DESCRIPTION
+ * enable/disable the supl profile configuration from GnssLocationProvider via native_set_agps_server
+ * auto_profile_enable will be ignored when aosp_profile_enable is true because AOSP Location Framework
+ * can load SUPL_HOST and SUPL_PORT from framework resource for different MCC/MNC
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the supl profile configuration from AOSP framework
+ * 1: enable the supl profile configuration from AOSP framework
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_aosp_profile_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_bind_nlp_setting_to_supl
+ * DESCRIPTION
+ * enable/disable to bind nlp setting to SUPL SI flow.
+ * If it is enabled, the SUPL SI is enabled only if network location setting is enabled by user.
+ * If it is disabled, agps_enable will be used and it's same as previous design.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the SUPL SI by network location settings, check agps_enable option
+ * 1: enable the SUPL SI by network location settings
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_bind_nlp_setting_to_supl(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_esupl_apn_mode
+ * DESCRIPTION
+ * select the APN mode for E-SUPL
+ * PARAMETERS
+ * time [INPUT] 0: use Emergency / IMS APN if they are available as GSMA
+ * IR92 (default)
+ * 1: use Emergency APN if it is available
+ * 2: use IMS APN if it is available
+ * 3: do not use Emergency / IMS APN (just as a normal supl)
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_esupl_apn_mode(int mode);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lbs_log_enable
+ * DESCRIPTION
+ * enable/disable tc10 lbs log to the debugging port
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the tc10 lbs log to the debugging port
+ * 1: enable the tc10 lbs log to the debugging port
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lbs_log_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_a_beidou_enable
+ * DESCRIPTION
+ * enable/disable the Beidou aiding if hardware can support A-Beidou
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the A-Beidou function
+ * 1: enable the A-Beidou function
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_a_beidou_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_a_galileo_enable
+ * DESCRIPTION
+ * enable/disable the Galileo aiding if hardware can support A-Galileo
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the A-Galileo function
+ * 1: enable the A-Galileo function
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_a_galileo_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_tcp_keep_alive
+ * DESCRIPTION
+ * enable/disable TCP Keepalive functionality for SUPL
+ * PARAMETERS
+ * time [INPUT] 0: disable the TCP keepalive function
+ * >0: enable to send TCP keepalive packetets and interval value is tcp_keepalive in second
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_tcp_keep_alive(int time);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_agps_nvram_enable
+ * DESCRIPTION
+ * set if we can save configuration of suppl profile and GNSS capabilities
+ * into NVRAM for VZW requirement
+ * PARAMETERS
+ * enabled [INPUT] 0: do not save the configuration into NVRAM
+ * 1: save the configuration into NVRAM
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_agps_nvram_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_udp_enable_v2
+ * DESCRIPTION
+ * enable/disable the UDP 7275 port by default, if you enable it, you may cause
+ * Android Compatible Test Suit failure for checking netstat.
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the UDP 7275 port
+ * 1: enable the UDP 7275 port
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_udp_enable_v2(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * get_agps_supl_profiles
+ * DESCRIPTION
+ * get_agps_supl_profiles from xml parser
+ * PARAMETERS
+ * none
+ * RETURNS
+ * Agps config data structure with supl_profiles data member.
+ *****************************************************************************/
+agps_intf_agps_config get_agps_supl_profiles();
+
+/*****************************************************************************
+ * FUNCTION
+ * set_ingore_si_for_e911
+ * DESCRIPTION
+ * enable/disable to ignore MOLR / SI for Emergency Call
+ * PARAMETERS
+ * enabled [INPUT] 0: disable to ignore
+ * 1: enable to ignore MOLR /SI for emergency call
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_ingore_si_for_e911(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lppe_cp_wlan_enable
+ * DESCRIPTION
+ * enable/disable for LPPe CP wlan function
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the LPPe cp wlan function
+ * 1: enable the LPPe cp wlan function
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lppe_cp_wlan_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lppe_cp_srn_enable
+ * DESCRIPTION
+ * enable/disable for LPPe CP srn function
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the LPPe cp srn function
+ * 1: enable the LPPe cp srn function
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lppe_cp_srn_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lppe_cp_sensor_enable
+ * DESCRIPTION
+ * enable/disable the LPPe CP sensor function
+ * PARAMETERS
+ * enabled [INPUT] 0: disalbe the LPPe CP sensor function
+ * 1: enable the LPPe CP sensor function
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lppe_cp_sensor_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lppe_cp_dbh_enable
+ * DESCRIPTION
+ * enable/disable the LPPe CP DBH function
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the LPPe CP DBH function
+ * 1: enable the LPPe CP DBH function
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lppe_cp_dbh_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lppe_up_wlan_enable
+ * DESCRIPTION
+ * enable/disable the LPPe UP wlan function
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the LPPe UP wlan function
+ * 1: enable the LPPe UP wlan function
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lppe_up_wlan_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lppe_up_srn_enable
+ * DESCRIPTION
+ * enable/disable the LPPe UP srn function
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the LPPe UP srn function
+ * 1: enable the LPPe UP srn function
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lppe_up_srn_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lppe_up_sensor_enable
+ * DESCRIPTION
+ * enable/disable the LPPe UP sensor function
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the LPPe UP sensor function
+ * 1: enable the LPPe UP sensor function
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lppe_up_sensor_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lppe_up_dbh_enable
+ * DESCRIPTION
+ * enable/disable the LPPe UP DBH function
+ * PARAMETERS
+ * enabled [INPUT] 0: disable the LPPe UP DBH function
+ * 1: enable the LPPe UP DBH function
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lppe_up_dbh_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_ip_version_prefer
+ * DESCRIPTION
+ * select the preferred mode for IP version when connnecting to the SUPL server
+ * PARAMETERS
+ * ip_version_type [INPUT] AGPS_INTF_SUPL_IP_VERSION_IPV6 ,
+ * AGPS_INTF_SUPL_IP_VERSION_IPV4
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_ip_version_prefer(agps_supl_ip_version_type ip_version_type);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_lpp_in_2g3g_disable
+ * DESCRIPTION
+ * decide if we need to turn off lpp in 2G / 3G network
+ * US ATT SUPL server may not provide assistance data if we have the lpp capability in 2G / 3G network
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to turn off the LPP in 2G /3G network
+ * 1: Trun off the LPP in 2G /3G network
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_lpp_in_2g3g_disable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_rrlp_in_4g_disable
+ * DESCRIPTION
+ * Decide if we need to turn off RRLP in 4G network when we have SUPL 2.0 and LPP
+ * US ATT SUPL server may not provide assistance data if we have the rrlp capability in 4G network
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to turn off the RRLP in 4G network
+ * 1: Turn off RRLP in 4G network
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_rrlp_in_4g_disable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_si_disable
+ * DESCRIPTION
+ * Decide if we need to reject SUPL SI request
+ * Sprint_2019Feb_GTR-LBS-00219 asks us not to trigger SUPL SI.
+ * Sprint_2019Feb_GTR-LBS-00222 asks us to support NI including normal and emergency
+ * Sprint_2019Feb_GTR-LBS-00223 asks us to use Sprint SLP in our configuration
+ * If we turn off agps_enable, we will allow Emergency NI only (reject SI and normal NI)
+ * If we turn on up_si_disable, we will allow both normal NI and Emergency NI (reject SI only)
+ * So this option is more suitable for Sprint requirements.
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to disable UP SI functions
+ * 1: Disable UP SI functions
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_si_disable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_use_ni_slp
+ * DESCRIPTION
+ * Decide if we can use the SLP Address or E-SPL Address in SUPL INIT
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to use the SLP Address or E-SPL Address in SUPL INIT
+ * 1: Allow using the SLP Address or E-SPL Address in SUPL INIT
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_use_ni_slp(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_use_tc10_config
+ * DESCRIPTION
+ * Decide if we can use TC10's secgps configuration file
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to use TC10's secgps configuration file
+ * 1: Allow using TC10's secgps configuration file
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_use_tc10_config(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_lppe_def_nlp_enable
+ * DESCRIPTION
+ * Decide if we can provide a default NLP measurement for LPPe
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to provide a default NLP measurement for LPPe
+ * 1: Allow providing a default NLP measurement for LPPe
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_lppe_def_nlp_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_aosp_pos_mode_enable
+ * DESCRIPTION
+ * Decide if we can use the position mode from Location Framework to decide
+ * the Pref Method in SET capabilities in SUPL START , SUPL POS INIT, SUPL
+ * TRIGGERED START
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to use the position mode from Location Framework
+ * We will use the pref_method in agps configuration
+ * 1: Allow using the position mode from Location Framework
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_aosp_pos_mode_enable(agps_bool enabled);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_privacy_override_mode
+ * DESCRIPTION
+ * From Android 10, GVC(Gnss Visibility Control) defines some rules to
+ * show location status or to disable sending location info to the network.
+ * We provide this option to allow OEM / ODM to break rules of GVC.
+ * For older Android or non-Android, this option will be ignored.
+ * PARAMETERS
+ * i [INPUT] 0 = AGPS_INTF_UP_PRIVACY_OVERRIDE_MODE_DEFAULT:
+ * No privacy will be overridden
+ * 1 = AGPS_INTF_UP_PRIVACY_OVERRIDE_MODE_ALLOW_HIDING_ICON:
+ * Allow hiding the location icon for the privacy
+ * override SUPL INIT
+ * We need this to pass SUPL-2.0-con-023 when GVC
+ * allows non-framework locationing
+ * 2 = AGPS_INTF_UP_PRIVACY_OVERRIDE_MODE_ALLOW_LOCATIONING:
+ * Allow locationing for the privacy override SUPL INIT
+ * even if GVC does not allow non-framework locationing
+ * 4 = AGPS_INTF_UP_PRIVACY_OVERRIDE_MODE_ALLOW_ESUPL:
+ * Allow locationing for the emergency SUPL INIT without
+ * emergency call even if GVC does not allow non-framework
+ * locationing
+ * (Known operators may need this: 1. Claro Colomiba 2. LG U+)
+ * (Please discuss this with Google before getting GMS License)
+ * 8 = AGPS_INTF_UP_PRIVACY_OVERRIDE_MODE_ALLOW_ALL:
+ * Ignore GVC for SUPL (AGPS OTA test uses normal supl.
+ * And AOSP power manager may turn off GPS when screen off)
+ * 16 = AGPS_INTF_UP_PRIVACY_OVERRIDE_MODE_ALLOW_TC10:
+ * Ignore GVC and GPS / AGPS settings to accept the
+ * network-initiated session
+ * [*] You can also mix them with bitwise-OR
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_privacy_override_mode(int i);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_emergency_ext_secs
+ * DESCRIPTION
+ * Set the extension time in seconds to accept network-initiated AGPS session
+ * after an emergency call
+ * PARAMETERS
+ * i [INPUT] 0 (default) ~ 300
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_emergency_ext_secs(int i);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_tc10_supl_ssl_method
+ * DESCRIPTION
+ * Set the SUPL SSL Method for TC10
+ * PARAMETERS
+ * m [INPUT] 0 = AGPS_INTF_TC10_SUPL_SSL_METHOD_NEGOTIATION (default)
+ * 1 = AGPS_INTF_TC10_SUPL_SSL_METHOD_SSLV3
+ * 2 = AGPS_INTF_TC10_SUPL_SSL_METHOD_SSLV23
+ * 3 = AGPS_INTF_TC10_SUPL_SSL_METHOD_TLSV1
+ * 4 = AGPS_INTF_TC10_SUPL_SSL_METHOD_TLSV1_1
+ * 5 = AGPS_INTF_TC10_SUPL_SSL_METHOD_TLSV1_2
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_tc10_supl_ssl_method(int m);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_tc10_auto_supl_ver_for_ni
+ * DESCRIPTION
+ * Decide if we can fill same SUPL version as the SUPL version in the SUPL
+ * INIT from the SUPL server
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to use the SUPL version in the SUPL INIT.
+ * 1: Allow using the SUPL version in the SUPL INIT
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_tc10_auto_supl_ver_for_ni(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_tc10_supl_ver_skt_ni
+ * DESCRIPTION
+ * Decide if we can fill SUPL 2.0.1 in NI sessions for SK Telecom requirement
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to use.
+ * 1: Allow using SUPL 2.0.1 in network-initiated sessions
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_tc10_supl_ver_skt_ni(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_tc10_use_apn_si
+ * DESCRIPTION
+ * Decide if we can call APIs provided by TC10 to request APN for both of
+ * SUPL SI and NI sessions
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to use TC10 APIs.
+ * 1: Allow using TC10 APIs to request APN.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_tc10_use_apn_si(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_tc10_use_apn_ni
+ * DESCRIPTION
+ * Decide if we can call APIs provided by TC10 to request APN for SUPL
+ * NI sessions even if up_tc10_use_apn_si = 0
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to use TC10 APIs.
+ * 1: Allow using TC10 APIs to request APN for
+ * network-initiated sessions
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_tc10_use_apn_ni(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_tc10_use_apn_ni
+ * DESCRIPTION
+ * From Android 10, GVC(Gnss Visibility Control) allows users to reject
+ * network-initiated sessions if it is not in an emergency call.
+ *
+ * For TC10, GVC can reject network-initiated sessions even for control plane
+ *
+ * Decide if we can ignore GVC for control plane
+ *
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to ignore GVC in TC10 projects
+ * 1: Allow ignoring GVC for CP NILR in TC10 projects
+ * (debug purpose)
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_cp_tc10_privacy_override(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_supl_addr_ni
+ * DESCRIPTION
+ * Set the SLP address for network-initiated sessions
+ * PARAMETERS
+ * addr [INPUT] Server address for NI, it can be IP address or FQDN.
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_supl_addr_ni(const char* addr);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_rrlp_google_supl
+ * DESCRIPTION
+ * Decide if we can force using RRLP in SET-Initiated sessions when using
+ * Google SLP
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to force using RRLP in SET-Initiated sessions
+ * when using Google SLP
+ * 1: Force using RRLP in SET-Initiated sessions when
+ * using Google SLP
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_rrlp_google_supl(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_supl2_cap_ext_disable
+ * DESCRIPTION
+ * Decide if we can fill ver2_SETCapabilities_extension in ULP_SETCapabilities
+ * Google SLP
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to fill the info
+ * 1: Allow filling the info
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_supl2_cap_ext_disable(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_ni_statistic_enable
+ * DESCRIPTION
+ * Decide if we can collect statistics of network-initiated sessions.
+ *
+ * We can read/clean the info in MTK LocationEM when do mass testing
+ * with tools like auto-dialer (e.g, North America Field Trial)
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to fill the info
+ * 1: Allow filling the info
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_ni_statistic_enable(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_operation_mode
+ * DESCRIPTION
+ * Set the SUPL SSL Method for TC10
+ * PARAMETERS
+ * m [INPUT] 0: common for most standards (default)
+ * 1: for DoCoMo requirements (disable capabilities not
+ * supported by DoCoMo SLP)
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_operation_mode(int m);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_glonass_msa_enable
+ * DESCRIPTION
+ * enable/disable SET-Assisted capability of GLONASS
+ * PARAMETERS
+ * enabled [INPUT] 0: disable SET-Assisted capability of GLONASS
+ * 1: enable SET-Assisted capability of GLONASS
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_glonass_msa_enable(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_glonass_msb_enable
+ * DESCRIPTION
+ * enable/disable SET-Based capability of GLONASS
+ * PARAMETERS
+ * enabled [INPUT] 0: disable SET-Based capability of GLONASS
+ * 1: enable SET-Based capability of GLONASS
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_glonass_msb_enable(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_glonass_msa_enable
+ * DESCRIPTION
+ * enable/disable SET-Assisted capability of Beidou
+ * PARAMETERS
+ * enabled [INPUT] 0: disable SET-Assisted capability of Beidou
+ * 1: enable SET-Assisted capability of Beidou
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_beidou_msa_enable(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_glonass_msb_enable
+ * DESCRIPTION
+ * enable/disable SET-Based capability of Beidou
+ * PARAMETERS
+ * enabled [INPUT] 0: disable SET-Based capability of Beidou
+ * 1: enable SET-Based capability of Beidou
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_beidou_msb_enable(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_glonass_msa_enable
+ * DESCRIPTION
+ * enable/disable SET-Assisted capability of Galileo
+ * PARAMETERS
+ * enabled [INPUT] 0: disable SET-Assisted capability of Galileo
+ * 1: enable SET-Assisted capability of Galileo
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_galileo_msa_enable(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_glonass_msb_enable
+ * DESCRIPTION
+ * enable/disable SET-Based capability of Galileo
+ * PARAMETERS
+ * enabled [INPUT] 0: disable SET-Based capability of Galileo
+ * 1: enable SET-Based capability of Galileo
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_galileo_msb_enable(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_tc10_auto_supl_ver_for_eni
+ * DESCRIPTION
+ * Decide if we can fill same SUPL version as the SUPL version in the SUPL
+ * INIT with the Emergency Flag from the SUPL server
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to use the SUPL version in the SUPL INIT.
+ * 1: Allow using the SUPL version in the SUPL INIT
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_up_tc10_auto_supl_ver_for_eni(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_cp_tc10_lpp_guard_time_sec
+ * DESCRIPTION
+ * Set the LPP guard time.
+ * After providing assistance data, location server will specify a response
+ * time N for UE to provide location estimate or satellite measurement.
+ * TMO-US asks UE using (N - t) to be the actual response time for control
+ * plane sessions where t is called LPP Guard Time.
+ * By default, MTK modem will decide t automatically by checking IMSI and
+ * the serving cell.
+ * TC10 may change this value.
+ * PARAMETERS
+ * t [INPUT] -1 (default): auto configured by MTK modem
+ * 0 ~ 127
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_cp_tc10_lpp_guard_time_sec(int t);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_cp_tc10_capability_control_enable
+ * DESCRIPTION
+ * Decide if we can use CP capability control flags for TC10
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to use it
+ * 1: Allow using it
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_cp_tc10_capability_control_enable(agps_bool enable);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_up_tc10_supl_ssl_method
+ * DESCRIPTION
+ * Set the SUPL SSL Method for TC10
+ * PARAMETERS
+ * flags [INPUT] 1 = AGPS_INTF_TC10_CP_CAPABILITY_AGNSS
+ * 2 = AGPS_INTF_TC10_CP_CAPABILITY_OTDOA
+ * 4 = AGPS_INTF_TC10_CP_CAPABILITY_ECID
+ * 8 = AGPS_INTF_TC10_CP_CAPABILITY_CONVENTIONAL_GPS
+ * 16 = N/A
+ * 32 = AGPS_INTF_TC10_CP_CAPABILITY_INTER_FREQ_OTDOA
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_cp_tc10_capability_control(int flags);
+
+/*****************************************************************************
+ * FUNCTION
+ * set_ignore_emergency_ext_secs_from_framework
+ * DESCRIPTION
+ * Decide if we can ignore the change of emergency_ext_secs from Android
+ * GNSS HIDL.
+ * Several customer prefers to specify the value of emergency_ext_secs
+ * in MTK's agps_profiles_conf2.xml
+ * PARAMETERS
+ * enabled [INPUT] 0: Not to ignore the change of emergency_ext_secs from
+ * Android (default)
+ * 1: Ignore the change of emergency_ext_secs from Android
+ * RETURNS
+ * none
+ *****************************************************************************/
+void set_ignore_emergency_ext_secs_from_framework(agps_bool does_ignore);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_interface/inc/data_coder.h b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/inc/data_coder.h
new file mode 100755
index 0000000..85efb3f
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/inc/data_coder.h
@@ -0,0 +1,66 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2019. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef __DATA_CODER_H__
+#define __DATA_CODER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+char get_byte(char* buff, int* offset);
+short get_short(char* buff, int* offset);
+int get_int(char* buff, int* offset);
+long long get_long(char* buff, int* offset);
+float get_float(char* buff, int* offset);
+double get_double(char* buff, int* offset);
+char* get_string(char* buff, int* offset);
+char* get_string2(char* buff, int* offset);
+int get_binary(char* buff, int* offset, char* output);
+
+void put_byte(char* buff, int* offset, const char input);
+void put_short(char* buff, int* offset, const short input);
+void put_int(char* buff, int* offset, const int input);
+void put_long(char* buff, int* offset, const long long input);
+void put_float(char* buff, int* offset, const float input);
+void put_double(char* buff, int* offset, const double input);
+void put_string(char* buff, int* offset, const char* input);
+void put_binary(char* buff, int* offset, const char* input, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_interface/makefile b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/makefile
new file mode 100644
index 0000000..efb05fb
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/makefile
@@ -0,0 +1,50 @@
+#CC=gcc
+#CXX=g++
+
+TARGET = libagps_interface.so
+
+FLAGS = \
+ -g \
+ -Wall \
+ -fPIC \
+ -D __YOCTO_OS__ \
+ -D __LBS_EM_OS_LINUX__ \
+
+INCLUDE = \
+ -I./inc \
+ -I./cfg/inc \
+ -I./cfg/libs/mtkexpat \
+ -I./cfg/libs/mtkexpat/libexpat \
+
+
+LIBS = \
+ -lrt \
+ -lpthread \
+
+CXXSRC = \
+
+CSRC = \
+ src/agps_interface.c \
+ src/data_coder.c \
+ cfg/src/agpsprofile.c \
+ cfg/libs/mtkexpat/libexpat/xmlparse.c \
+ cfg/libs/mtkexpat/libexpat/xmlrole.c \
+ cfg/libs/mtkexpat/libexpat/xmltok.c \
+ cfg/libs/mtkexpat/mtkexpat.c \
+
+COBJS = $(CSRC:.c=.o)
+CXXOBJS = $(CXXSRC:.cpp=.o)
+
+CFLAGS += $(FLAGS) $(INCLUDE)
+CXXFLAGS += $(FLAGS) $(INCLUDE)
+
+SHARE := -fPIC -shared
+
+$(TARGET): $(COBJS)
+ ${CC} ${CFLAGS} $(SHARE) $^ -o $@
+
+.PHONY: clean
+clean:
+ rm -f $(TARGET) rm -rf *.o
+ find ./ -name *.o | xargs rm -rf
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_interface/src/agps_interface.c b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/src/agps_interface.c
new file mode 100755
index 0000000..c01e795
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/src/agps_interface.c
@@ -0,0 +1,1841 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2019. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h> // for open
+#include <unistd.h> // for close
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/stat.h>
+#include "agps_interface.h"
+#include "data_coder.h"
+#include "agpsprofile.h"
+
+#if defined(__ANDROID_OS__) | defined(__KAIOS__)
+#include <cutils/sockets.h>
+#include <android/log.h>
+
+#define AGPS_INTERFACE_PATH "agpsd2"
+
+#elif defined(__LINUX_OS__) | defined(__YOCTO_OS__)
+#include <sys/socket.h>
+#include <arpa/inet.h> //inet_addr
+#include <sys/un.h> //struct sockaddr_un
+
+#define AGPS_INTERFACE_PATH "agpsd2"
+#endif
+
+#define MAX_BUFF_SIZE 8192
+#define ORIGINAL_AGPES_PROFILE_PATH2 "/vendor/etc/agps_profiles_conf2.xml"
+
+#define LBS_STRNCPY(dst,src,size) do{\
+ strncpy((char *)(dst), (src), (size - 1));\
+ (dst)[size - 1] = '\0';\
+ }while(0)
+
+typedef enum {
+ // Command Enum APP -> AGPSD
+ APP_MGR_CMD_CODER_TEST = 0,
+ APP_MGR_CMD_VERSION = 1,
+
+ APP_MGR_CMD_GET_CONFIG = 100, //AgpsConfig
+ APP_MGR_CMD_GET_OMA_CP_SUPL_PROFILE = 101,
+ APP_MGR_CMD_GET_SYSTEM_PROPERTY = 102,
+ APP_MGR_CMD_GET_AGPS_PROFILING = 103,
+ APP_MGR_CMD_GET_EMULATOR_MODE = 104,
+ APP_MGR_CMD_GET_CONFIG_V2 = 105,
+ APP_MGR_CMD_GET_CONFIG_V3 = 106, // add cert_from_sdcard
+ APP_MGR_CMD_GET_CONFIG_V14 = 117,
+ APP_MGR_CMD_GET_CONFIG_V20 = 123,
+ APP_MGR_CMD_GET_CONFIG_V21 = 124,
+ APP_MGR_CMD_GET_CONFIG_V22 = 125,
+ APP_MGR_CMD_GET_CONFIG_V23 = 126,
+ APP_MGR_CMD_GET_CONFIG_V24 = 127,
+
+ APP_MGR_CMD_SET_AGPS_ENABLE = 200,
+ APP_MGR_CMD_SET_PROTOCOL,
+ APP_MGR_CMD_SET_CDMA_PREF,
+ APP_MGR_CMD_SET_UP_PREF_METHOD,
+ APP_MGR_CMD_SET_POS_TECHNOLOGY_MSA,
+ APP_MGR_CMD_SET_POS_TECHNOLOGY_MSB,
+ APP_MGR_CMD_SET_POS_TECHNOLOGY_ECID,
+ APP_MGR_CMD_SET_POS_TECHNOLOGY_OTDOA,
+ APP_MGR_CMD_SET_SUPL_VERSION,
+ APP_MGR_CMD_SET_SUPL_PROFILE, //AgpsProfil
+ APP_MGR_CMD_SET_QOP = 210, //AgpsQoP
+ APP_MGR_CMD_SET_MOLR_POS_METHDO,
+ APP_MGR_CMD_SET_EXTERNAL_ADDR,
+ APP_MGR_CMD_SET_MLC_NUMBER,
+ APP_MGR_CMD_SET_CP_AUTO_RESET,
+ APP_MGR_CMD_SET_ALLOW_NI,
+ APP_MGR_CMD_SET_ALLOW_ROAMING,
+ APP_MGR_CMD_SET_SUPL_2_FILE,
+ APP_MGR_CMD_SET_RESET_TO_DEFAULT,
+ APP_MGR_CMD_SET_OMA_CP_SUPL_PROFILE,
+ APP_MGR_CMD_SET_NI_REQ = 220, //un-implemented for test
+ APP_MGR_CMD_SET_EPC_MOLR_PDU_ENABLE,
+ APP_MGR_CMD_SET_EPC_MOLR_PDU,
+ APP_MGR_CMD_SET_TLS_VERSION,
+ APP_MGR_CMD_SET_CA_ENABLE,
+ APP_MGR_CMD_SET_UDP_ENABLE,
+ APP_MGR_CMD_SET_LPP_ENABLE,
+ APP_MGR_CMD_SET_CERT_FROM_SDCARD_ENABLE,
+ APP_MGR_CMD_SET_AUTO_PROFILE_ENABLE,
+ APP_MGR_CMD_SET_UT2,
+ APP_MGR_CMD_SET_UT3 = 230,
+ APP_MGR_CMD_SET_SUPL_APN_ENABLE,
+ APP_MGR_CMD_SET_SYNC_TO_SLP,
+ APP_MGR_CMD_SET_UDP_ENABLE_V2,
+ APP_MGR_CMD_SET_AUTONOMOUS_ENABLE,
+ APP_MGR_CMD_SET_AFLT_ENABLE,
+ APP_MGR_CMD_SET_IMSI_ENABLE,
+ APP_MGR_CMD_SET_SIB8_16_ENABLE,
+ APP_MGR_CMD_SET_GPS_ENABLE,
+ APP_MGR_CMD_SET_GLONASS_ENABLE,
+ APP_MGR_CMD_SET_BEIDOU_ENABLE = 240,
+ APP_MGR_CMD_SET_GALILEO_ENABLE,
+ APP_MGR_CMD_SET_SUPL_SHA_VERSION,
+ APP_MGR_CMD_SET_SUPL_TLS_VERSION,
+ APP_MGR_CMD_SET_SUPL_VER_MINOR,
+ APP_MGR_CMD_SET_SUPL_VER_SER_IND,
+ APP_MGR_CMD_SET_A_GLONASS_ENABLE,
+ APP_MGR_CMD_SET_PDE_PROFILE,
+ APP_MGR_CMD_SET_E911_GPS_ICON_ENABLE,
+ APP_MGR_CMD_SET_E911_OPEN_GPS_ENABLE,
+ APP_MGR_CMD_SET_A_GPS_ENABLE = 250,
+ APP_MGR_CMD_SET_A_BEIDOU_ENABLE,
+ APP_MGR_CMD_SET_A_GALILEO_ENABLE,
+ APP_MGR_CMD_SET_PREF_2G3G_CELL_AGE,
+ APP_MGR_CMD_SET_UT1,
+ APP_MGR_CMD_SET_NO_SENSITIVE_LOG,
+ APP_MGR_CMD_SET_TLS_REUSE_ENABLE,
+ APP_MGR_CMD_SET_IMSI_CACHE_ENABLE,
+ APP_MGR_CMD_SET_SUPL_RAW_DATA_ENABLE,
+ APP_MGR_CMD_SET_TC10_ENABLE,
+ APP_MGR_CMD_SET_TC10_USE_APN = 260,
+ APP_MGR_CMD_SET_TC10_USE_FW_DNS,
+ APP_MGR_CMD_SET_ALLOW_NI_FOR_GPS_OFF,
+ APP_MGR_CMD_SET_FORCE_OTDOA_ASSIST_REQ,
+ APP_MGR_CMD_SET_REJECT_NON911_NILR_ENABLE,
+ APP_MGR_CMD_SET_CP_2G_DISABLE,
+ APP_MGR_CMD_SET_CP_3G_DISABLE,
+ APP_MGR_CMD_SET_CP_4G_DISABLE,
+ APP_MGR_CMD_SET_TC10_IGNORE_FW_CONFIG,
+ APP_MGR_CMD_SET_LPPE_HIDE_WIFI_BT_STATUS,
+ APP_MGR_CMD_SET_LPPE_NETWORK_LOCATION_DISABLE = 270,
+ APP_MGR_CMD_SET_LPPE_CP_ENABLE,
+ APP_MGR_CMD_SET_LPPE_UP_ENABLE,
+ APP_MGR_CMD_SET_VZW_DEBUG_SCREEN_ENABLE,
+ APP_MGR_CMD_SET_AOSP_PROFILE_ENABLE,
+ APP_MGR_CMD_SET_BIND_NLP_SETTING_TO_SUPL,
+ APP_MGR_CMD_SET_ESUPL_APN_MODE,
+ APP_MGR_CMD_SET_TCP_KEEPALIVE,
+ APP_MGR_CMD_SET_AGPS_NVRAM_ENABLE,
+ APP_MGR_CMD_SET_LBS_LOG_ENABLE,
+ APP_MGR_CMD_SET_LPPE_CROWD_SOURCE_CONFIDENT = 280,
+ APP_MGR_CMD_SET_IGNORE_SI_FOR_E911,
+ APP_MGR_CMD_SET_LPPE_CP_WLAN_ENABLE,
+ APP_MGR_CMD_SET_LPPE_CP_SRN_ENABLE,
+ APP_MGR_CMD_SET_LPPE_CP_SENSOR_ENABLE,
+ APP_MGR_CMD_SET_LPPE_CP_DBH_ENABLE,
+ APP_MGR_CMD_SET_LPPE_UP_WLAN_ENABLE,
+ APP_MGR_CMD_SET_LPPE_UP_SRN_ENABLE,
+ APP_MGR_CMD_SET_LPPE_UP_SENSOR_ENABLE,
+ APP_MGR_CMD_SET_LPPE_UP_DBH_ENABLE,
+ APP_MGR_CMD_SET_IP_VERSION_PREFER = 290,
+ APP_MGR_CMD_SET_UP_LPP_IN_2G3G_DISABLE,
+ APP_MGR_CMD_SET_UP_RRLP_IN_4G_DISABLE,
+ APP_MGR_CMD_UP_SI_DISABLE,
+
+ // To implement
+ APP_MGR_CMD_SET_USE_NI_SLP,
+ APP_MGR_CMD_SET_USE_TC10_CONFIG,
+ APP_MGR_CMD_SET_LPPE_DEF_NLP_ENABLE,
+ APP_MGR_CMD_SET_AOSP_POS_MODE_ENABLE,
+ APP_MGR_CMD_SET_PRIVACY_OVERRIDE_MODE,
+ APP_MGR_CMD_SET_EMERGENCY_EXT_SECS, // 299
+
+
+ APP_MGR_CMD_START_PERIODIC = 300,
+ APP_MGR_CMD_ABORT_PERIODIC,
+ APP_MGR_CMD_START_AREA_EVENT,
+ APP_MGR_CMD_ABORT_AREA_EVENT,
+
+ APP_MGR_CMD_START_TEST_CASE = 400,
+ APP_MGR_CMD_START_TEST_BUTTON,
+ APP_MGR_CMD_START_RESET_AGPSD,
+ APP_MGR_CMD_START_EMULATOR_MODE,
+
+
+ // To implement
+ APP_MGR_CMD_SET_TC10_SUPL_SSL_METHOD = 500,
+ APP_MGR_CMD_SET_TC10_AUTO_SUPL_VER_FOR_NI,
+ APP_MGR_CMD_SET_TC10_SUPL_VER_SKT_NI,
+ APP_MGR_CMD_SET_TC10_USE_APN_NI,
+ APP_MGR_CMD_SET_TC10_USE_APN_SI,
+ APP_MGR_CMD_SET_CP_PRIVACY_OVERRIDE,
+ APP_MGR_CMD_SET_SUPL_ADDR_NI,
+ APP_MGR_CMD_SET_RRLP_GOOGLE_SUPL,
+ APP_MGR_CMD_SET_SUPL2_CAP_EXT_DISABLE,
+ APP_MGR_CMD_SET_NI_STATISTIC_ENABLE,
+ APP_MGR_CMD_SET_UP_OPERATION_MODE, // 510
+ APP_MGR_CMD_SET_GLONASS_MSA_ENABLE,
+ APP_MGR_CMD_SET_GLONASS_MSB_ENABLE,
+ APP_MGR_CMD_SET_BEIDOU_MSA_ENABLE,
+ APP_MGR_CMD_SET_BEIDOU_MSB_ENABLE,
+ APP_MGR_CMD_SET_GALILEO_MSA_ENABLE,
+ APP_MGR_CMD_SET_GALILEO_MSB_ENABLE,
+ APP_MGR_CMD_SET_TC10_AUTO_SUPL_VER_FOR_ENI,
+ APP_MGR_CMD_SET_TC10_CP_LPP_GUARD_TIME_SEC,
+ APP_MGR_CMD_SET_TC10_CP_CAPABILITY_VALID_ENABLE,
+ APP_MGR_CMD_SET_TC10_CP_CAPABILITY_ENABLE, // 520
+ APP_MGR_CMD_SET_IGNORE_EMERGENCY_EXT_SECS_FROM_FRAMEWORK,
+ APP_MGR_CMD_GET_AGPSD_VERSION,
+ APP_MGR_CMD_GET_IMSI,
+} app_mgr_cmd_enum;
+
+static void LOGDD(const char *fmt, ...);
+static void LOGEE(const char *fmt, ...);
+
+/******************************************************
+*
+* Adaptation Layer
+*
+*******************************************************/
+#if defined(__ANDROID_OS__) | defined(__KAIOS__)
+static void _LOGD(const char* message) {
+ __android_log_print(ANDROID_LOG_DEBUG, "[agps]", "%s", message);
+}
+
+static void _LOGE(const char* message) {
+ __android_log_print(ANDROID_LOG_DEBUG, "[agps] ERR:", "%s", message);
+}
+
+// -1 means failure
+static int socket_connect() {
+ int ret;
+ int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(fd < 0) {
+ LOGDD("socket() failed fd=%d\n", fd);
+ return -1;
+ }
+
+ ret = socket_local_client_connect(
+ fd,
+ AGPS_INTERFACE_PATH,
+ 1,
+ SOCK_STREAM);
+ if(ret < 0) {
+ close(fd);
+ LOGDD("socket_local_client_connect() failed ret=%d\n", ret);
+ return -1;
+ }
+
+ return fd;
+}
+#elif defined(__LINUX_OS__) | defined(__YOCTO_OS__)
+static void _LOGD(const char* message) {
+ printf("%s\n", message);
+ fflush(stdout);
+}
+
+static void _LOGE(const char* message) {
+ printf("%s\n", message);
+ fflush(stdout);
+}
+
+// -1 means failure
+int do_socket_connect(const char* path) {
+ struct sockaddr_un addr;
+ int fd = socket(PF_LOCAL, SOCK_STREAM, 0);
+ if(fd < 0) {
+ LOGDD("socket() failed fd=%d\n", fd);
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, path, strlen(path));
+ addr.sun_family = AF_UNIX;
+
+ if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ LOGEE("connect failed reason=[%s] path=[%s]\n", strerror(errno), path);
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+int socket_connect() {
+ return do_socket_connect(AGPS_INTERFACE_PATH);
+}
+
+#endif
+
+/******************************************************
+*
+* Implementation Utils
+*
+*******************************************************/
+static void LOGDD(const char *fmt, ...) {
+ char out_buf[1100] = {0};
+ char buf[1024] = {0};
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ sprintf(out_buf, "%s", buf);
+ _LOGD(out_buf);
+}
+
+static void LOGEE(const char *fmt, ...) {
+ char out_buf[1100] = {0};
+ char buf[1024] = {0};
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ sprintf(out_buf, "%s", buf);
+ _LOGE(out_buf);
+}
+
+//-1 means failure
+static int safe_write(int fd, void* buf, int len) {
+ int n, retry = 10;
+
+ if(fd < 0 || buf == NULL || len < 0) {
+ LOGEE("safe_write fd=%d buf=%p len=%d\n", fd, buf, len);
+ return -1;
+ }
+
+ while((n = write(fd, buf, len)) != len) {
+ if(errno == EINTR) continue;
+ if(errno == EAGAIN) {
+ if(retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ goto exit;
+ }
+ goto exit;
+ }
+ return n;
+exit:
+ LOGEE("safe_write reason=[%s]%d\n", strerror(errno), errno);
+ return -1;
+}
+
+
+//-1 means failure
+static int safe_read(int fd, void* buf, int len) {
+ int n, retry = 10;
+
+ if(fd < 0 || buf == NULL || len < 0) {
+ LOGEE("safe_read fd=%d buf=%p len=%d\n", fd, buf, len);
+ return -1;
+ }
+
+ if(len == 0) {
+ return 0;
+ }
+
+ while((n = read(fd, buf, len)) < 0) {
+ if(errno == EINTR) continue;
+ if(errno == EAGAIN) {
+ if(retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ goto exit;
+ }
+ goto exit;
+ }
+ return n;
+
+exit:
+ if(errno != EAGAIN) {
+ LOGEE("safe_read reason=[%s] fd=%d len=%d buf=%p\n",
+ strerror(errno), fd, len, buf);
+ }
+ return -1;
+}
+
+static char socket_get_byte(int fd) {
+ int read_len = 0;
+ char buff[1] = {0};
+ int offset = 0;
+
+ read_len = safe_read(fd, buff, sizeof(buff));
+ if(read_len != sizeof(buff)) {
+ LOGEE("socket_get_byte read_len=%d\n", read_len);
+ }
+ return get_byte(buff, &offset);
+}
+
+#if 0 // unused
+static short socket_get_short(int fd) {
+ int read_len = 0;
+ char buff[2] = {0};
+ int offset = 0;
+
+ read_len = safe_read(fd, buff, sizeof(buff));
+ if(read_len != sizeof(buff)) {
+ LOGEE("socket_get_short read_len=%d\n", read_len);
+ }
+ return get_short(buff, &offset);
+}
+#endif
+
+static int socket_get_int(int fd) {
+ int read_len = 0;
+ char buff[4] = {0};
+ int offset = 0;
+
+ read_len = safe_read(fd, buff, sizeof(buff));
+ if(read_len != sizeof(buff)) {
+ LOGEE("socket_get_int read_len=%d\n", read_len);
+ }
+ return get_int(buff, &offset);
+}
+
+static long long socket_get_long(int fd) {
+ int read_len = 0;
+ char buff[8] = {0};
+ int offset = 0;
+
+ read_len = safe_read(fd, buff, sizeof(buff));
+ if(read_len != sizeof(buff)) {
+ LOGEE("socket_get_long read_len=%d\n", read_len);
+ }
+ return get_long(buff, &offset);
+}
+
+#if 0 // unused
+static float socket_get_float(int fd) {
+ int read_len = 0;
+ char buff[4] = {0};
+ int offset = 0;
+
+ read_len = safe_read(fd, buff, sizeof(buff));
+ if(read_len != sizeof(buff)) {
+ LOGEE("socket_get_float read_len=%d\n", read_len);
+ }
+ return get_float(buff, &offset);
+}
+
+static double socket_get_double(int fd) {
+ int read_len = 0;
+ char buff[8] = {0};
+ int offset = 0;
+
+ read_len = safe_read(fd, buff, sizeof(buff));
+ if(read_len != sizeof(buff)) {
+ LOGEE("socket_get_double read_len=%d\n", read_len);
+ }
+ return get_double(buff, &offset);
+}
+#endif
+
+static char* socket_get_string(int fd, char* buff, int buff_len) {
+ int read_len = 0;
+
+ char ret = socket_get_byte(fd);
+ if(ret == 0) {
+ return NULL;
+ } else {
+ int len = socket_get_int(fd);
+ if(len > buff_len) {
+ LOGEE("socket_get_string your buff len=%d is too small, need len=%d\n",
+ buff_len, len);
+ return NULL;
+ }
+
+ read_len = safe_read(fd, buff, len);
+ if(read_len != len) {
+ LOGEE("socket_get_string read_len=%d len=%d\n", read_len, len);
+ return NULL;
+ }
+
+ return buff;
+ }
+}
+
+static int socket_get_binary(int fd, char* buff) {
+ int read_len = 0;
+
+ int len = socket_get_int(fd);
+ if(len > 0) {
+ read_len = safe_read(fd, buff, len);
+ if(read_len != len) {
+ LOGEE("socket_get_binary read_len=%d len=%d\n", read_len, len);
+ return 0;
+ }
+ }
+ return len;
+}
+
+void dump_agps_intf_supl_profile(agps_intf_supl_profile profile) {
+ LOGDD("name=%s", profile.name);
+ LOGDD("addr=%s", profile.addr);
+ LOGDD("port=%d", profile.port);
+ LOGDD("tls=%d", profile.tls);
+ LOGDD("mcc_mnc=%s", profile.mcc_mnc);
+ LOGDD("app_id=%s", profile.app_id);
+ LOGDD("provider_id=%s", profile.provider_id);
+ LOGDD("default_apn=%s", profile.default_apn);
+ LOGDD("optional_apn=%s", profile.optional_apn);
+ LOGDD("optional_apn_2=%s", profile.optional_apn_2);
+ LOGDD("address_type=%s", profile.address_type);
+}
+
+void dump_agps_intf_agps_config(agps_intf_agps_config config) {
+ LOGDD("agps_setting");
+ LOGDD(" agps_enable=%d", config.agps_setting.agps_enable);
+ LOGDD(" agps_protocol=%d (0=UP 1=CP)", config.agps_setting.agps_protocol);
+ LOGDD(" gpevt=%d", config.agps_setting.gpevt);
+ LOGDD(" e911_gps_icon_enable=%d", config.agps_setting.e911_gps_icon_enable);
+ LOGDD(" lppe_network_location_disable=%d", config.agps_setting.lppe_network_location_disable);
+
+ LOGDD("cp_setting");
+ LOGDD(" molr_pos_method=%d (0=LOC_EST 1=ASSIST_DATA)", config.cp_setting.molr_pos_method);
+ LOGDD(" external_addr_enable=%d", config.cp_setting.external_addr_enable);
+ LOGDD(" external_addr=%s", config.cp_setting.external_addr);
+ LOGDD(" mlc_number_enable=%d", config.cp_setting.mlc_number_enable);
+ LOGDD(" mlc_number=%s", config.cp_setting.mlc_number);
+ LOGDD(" cp_auto_reset=%d", config.cp_setting.cp_auto_reset);
+ LOGDD(" epc_molr_lpp_payload_enable=%d", config.cp_setting.epc_molr_lpp_payload_enable);
+ LOGDD(" epc_molr_lpp_payload_len=%d", config.cp_setting.epc_molr_lpp_payload_len);
+ LOGDD(" molr_pos_method=0x%02x 0x%02x 0x%02x",
+ config.cp_setting.epc_molr_lpp_payload[0] & 0xff,
+ config.cp_setting.epc_molr_lpp_payload[1] & 0xff,
+ config.cp_setting.epc_molr_lpp_payload[2] & 0xff);
+
+ LOGDD("up_setting");
+ LOGDD(" ca_enable=%d", config.up_setting.ca_enable);
+ LOGDD(" udp_enable=%d", config.up_setting.udp_enable);
+ LOGDD(" ni_request=%d", config.up_setting.ni_request);
+ LOGDD(" roaming=%d", config.up_setting.roaming);
+ LOGDD(" cdma_preferred=%d (0=WCDMA 1=CDMA 2=CDMA_FORCE)", config.up_setting.cdma_preferred);
+ LOGDD(" pref_method=%d (0=MA 1=MB 2=NO_PREFER)", config.up_setting.pref_method);
+ LOGDD(" supl_version=%d (1=SUPL1 2=SUPL2)", config.up_setting.supl_version);
+ LOGDD(" tls_version=%d (0=1_0 1=1_1 2=1_2)", config.up_setting.tls_version);
+ LOGDD(" supl_log=%d", config.up_setting.supl_log);
+ LOGDD(" msa_enable=%d", config.up_setting.msa_enable);
+ LOGDD(" msb_enable=%d", config.up_setting.msb_enable);
+ LOGDD(" ecid_enable=%d", config.up_setting.ecid_enable);
+ LOGDD(" otdoa_enable=%d", config.up_setting.otdoa_enable);
+ LOGDD(" autonomous_enable=%d", config.up_setting.autonomous_enable);
+ LOGDD(" aflt_enable=%d", config.up_setting.aflt_enable);
+ LOGDD(" qop_hacc=%d", config.up_setting.qop_hacc);
+ LOGDD(" qop_vacc=%d", config.up_setting.qop_vacc);
+ LOGDD(" qop_loc_age=%d", config.up_setting.qop_loc_age);
+ LOGDD(" qop_delay=%d", config.up_setting.qop_delay);
+ LOGDD(" lpp_enable=%d", config.up_setting.lpp_enable);
+ LOGDD(" cert_from_sdcard=%d", config.up_setting.cert_from_sdcard);
+ LOGDD(" up_setting.ut2=%d", config.up_setting.ut2);
+ LOGDD(" up_setting.ut3=%d", config.up_setting.ut3);
+ LOGDD(" supl_ver_minor=%d", config.up_setting.supl_ver_minor);
+ LOGDD(" supl_ver_ser_ind=%d", config.up_setting.supl_ver_ser_ind);
+ LOGDD(" supl_log=%d", config.up_setting.supl_log);
+ LOGDD(" no_sensitive_log=%d", config.up_setting.no_sensitive_log);
+ LOGDD(" apn_enable=%d", config.up_setting.apn_enable);
+ LOGDD(" sync_to_slp=%d", config.up_setting.sync_to_slp);
+ LOGDD(" imsi_enable=%d", config.up_setting.imsi_enable);
+ LOGDD(" cp_lppe_enable=%d", config.cp_setting.cp_lppe_enable);
+ LOGDD(" up_lppe_enable=%d", config.up_setting.up_lppe_enable);
+ LOGDD(" aosp_profile_enable=%d", config.up_setting.aosp_profile_enable);
+ LOGDD(" bind_nlp_setting_to_supl=%d", config.up_setting.bind_nlp_setting_to_supl);
+ LOGDD(" lbs_log_enable=%d", config.agps_setting.lbs_log_enable);
+ LOGDD(" tcp_keepalive=%d", config.up_setting.tcp_keepalive);
+ LOGDD(" sib8_sib16_enable=%d", config.gnss_setting.sib8_sib16_enable);
+ LOGDD(" a_glonass_satellite_enable=%d", config.gnss_setting.a_glonass_satellite_enable);
+ LOGDD(" a_beidou_satellite_enable=%d", config.gnss_setting.a_beidou_satellite_enable);
+ LOGDD(" a_galileo_satellite_enable=%d", config.gnss_setting.a_galileo_satellite_enable);
+
+ LOGDD("cur_supl_profile");
+ LOGDD(" name=%s", config.cur_supl_profile.name);
+ LOGDD(" addr=%s", config.cur_supl_profile.addr);
+ LOGDD(" port=%d", config.cur_supl_profile.port);
+ LOGDD(" tls=%d", config.cur_supl_profile.tls);
+ LOGDD(" mcc_mnc=%s", config.cur_supl_profile.mcc_mnc);
+ LOGDD(" app_id=%s", config.cur_supl_profile.app_id);
+ LOGDD(" provider_id=%s", config.cur_supl_profile.provider_id);
+ LOGDD(" default_apn=%s", config.cur_supl_profile.default_apn);
+ LOGDD(" optional_apn=%s", config.cur_supl_profile.optional_apn);
+ LOGDD(" optional_apn_2=%s", config.cur_supl_profile.optional_apn_2);
+ LOGDD(" address_type=%s", config.cur_supl_profile.address_type);
+}
+
+void dump_agps_intf_profiling_info(agps_intf_profiling_info profiling) {
+ int i = 0;
+ LOGDD("element_num=%d", profiling.element_num);
+ for(i = 0; i < profiling.element_num; i++) {
+ agps_intf_profiling_element* element = &profiling.elements[i];
+ LOGDD(" i=%d type=%d timestamp=%lld message=[%s]\n", i, element->type, element->timestamp, element->message);
+ }
+}
+
+int set_template_0(app_mgr_cmd_enum cmd) {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return -1;
+ }
+
+ // write
+ put_int(buff, &offset, cmd);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return -1;
+ }
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+ return 0;
+}
+
+int set_template_1(app_mgr_cmd_enum cmd, char data) {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return -1;
+ }
+
+ // write
+ put_int(buff, &offset, cmd);
+ put_byte(buff, &offset, data);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return -1;
+ }
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+ return 0;
+}
+
+int set_template_1_int(app_mgr_cmd_enum cmd, int data) {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return -1;
+ }
+
+ // write
+ put_int(buff, &offset, cmd);
+ put_int(buff, &offset, data);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return -1;
+ }
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+ return 0;
+}
+
+int get_template_agps_config(app_mgr_cmd_enum cmd, agps_intf_agps_config *config) {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return -1;
+ }
+
+ // write
+ put_int(buff, &offset, cmd);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return -1;
+ }
+
+ // read
+ config->agps_setting.agps_enable = socket_get_byte(fd);
+ config->agps_setting.agps_protocol = socket_get_int(fd);
+ config->agps_setting.gpevt = socket_get_byte(fd);
+
+ config->cp_setting.molr_pos_method = socket_get_int(fd);
+ config->cp_setting.external_addr_enable = socket_get_byte(fd);
+ socket_get_string(fd, config->cp_setting.external_addr, sizeof(config->cp_setting.external_addr));
+ config->cp_setting.mlc_number_enable = socket_get_byte(fd);
+ socket_get_string(fd, config->cp_setting.mlc_number, sizeof(config->cp_setting.mlc_number));
+ config->cp_setting.cp_auto_reset = socket_get_byte(fd);
+ config->cp_setting.epc_molr_lpp_payload_enable = socket_get_byte(fd);
+ config->cp_setting.epc_molr_lpp_payload_len =
+ socket_get_binary(fd, config->cp_setting.epc_molr_lpp_payload);
+
+ config->up_setting.ca_enable = socket_get_byte(fd);
+ config->up_setting.ni_request = socket_get_byte(fd);
+ config->up_setting.roaming = socket_get_byte(fd);
+ config->up_setting.cdma_preferred = socket_get_int(fd);
+ config->up_setting.pref_method = socket_get_int(fd);
+ config->up_setting.supl_version = socket_get_int(fd);
+ config->up_setting.tls_version = socket_get_int(fd);
+ config->up_setting.supl_log = socket_get_byte(fd);
+ config->up_setting.msa_enable = socket_get_byte(fd);
+ config->up_setting.msb_enable = socket_get_byte(fd);
+ config->up_setting.ecid_enable = socket_get_byte(fd);
+ config->up_setting.otdoa_enable = socket_get_byte(fd);
+ config->up_setting.qop_hacc = socket_get_int(fd);
+ config->up_setting.qop_vacc = socket_get_int(fd);
+ config->up_setting.qop_loc_age = socket_get_int(fd);
+ config->up_setting.qop_delay = socket_get_int(fd);
+ config->up_setting.lpp_enable = socket_get_byte(fd);
+ config->up_setting.cert_from_sdcard = socket_get_byte(fd);
+
+ if(cmd >= APP_MGR_CMD_GET_CONFIG_V14) {
+ config->up_setting.auto_profile_enable = socket_get_byte(fd);
+ config->up_setting.ut2 = socket_get_byte(fd);
+ config->up_setting.ut3 = socket_get_byte(fd);
+ config->up_setting.apn_enable = socket_get_byte(fd);
+ config->up_setting.sync_to_slp = socket_get_byte(fd);
+ config->up_setting.udp_enable = socket_get_byte(fd);
+ config->up_setting.autonomous_enable = socket_get_byte(fd);
+ config->up_setting.aflt_enable = socket_get_byte(fd);
+ config->up_setting.imsi_enable = socket_get_byte(fd);
+
+ config->gnss_setting.sib8_sib16_enable = socket_get_byte(fd);
+ config->gnss_setting.gps_satellite_enable = socket_get_byte(fd);
+ config->gnss_setting.glonass_satellite_enable = socket_get_byte(fd);
+ config->gnss_setting.beidou_satellite_enable = socket_get_byte(fd);
+ config->gnss_setting.galileo_satellite_enable = socket_get_byte(fd);
+ config->gnss_setting.gps_satellite_support = socket_get_byte(fd);
+ config->gnss_setting.glonass_satellite_support = socket_get_byte(fd);
+ config->gnss_setting.beidou_satellite_support = socket_get_byte(fd);
+ config->gnss_setting.galileo_satellite_support = socket_get_byte(fd);
+
+ config->up_setting.supl_ver_minor = socket_get_byte(fd);
+ config->up_setting.supl_ver_ser_ind = socket_get_byte(fd);
+
+ config->gnss_setting.a_glonass_satellite_enable = socket_get_byte(fd);
+ }
+
+ socket_get_string(fd, config->cur_supl_profile.name, sizeof(config->cur_supl_profile.name));
+ socket_get_string(fd, config->cur_supl_profile.addr, sizeof(config->cur_supl_profile.addr));
+ config->cur_supl_profile.port = socket_get_int(fd);
+ config->cur_supl_profile.tls = socket_get_byte(fd);
+ socket_get_string(fd, config->cur_supl_profile.mcc_mnc, sizeof(config->cur_supl_profile.mcc_mnc));
+ socket_get_string(fd, config->cur_supl_profile.app_id, sizeof(config->cur_supl_profile.app_id));
+ socket_get_string(fd, config->cur_supl_profile.provider_id, sizeof(config->cur_supl_profile.provider_id));
+ socket_get_string(fd, config->cur_supl_profile.default_apn, sizeof(config->cur_supl_profile.default_apn));
+ socket_get_string(fd, config->cur_supl_profile.optional_apn, sizeof(config->cur_supl_profile.optional_apn));
+ socket_get_string(fd, config->cur_supl_profile.optional_apn_2, sizeof(config->cur_supl_profile.optional_apn_2));
+ socket_get_string(fd, config->cur_supl_profile.address_type, sizeof(config->cur_supl_profile.address_type));
+
+ if(cmd >= APP_MGR_CMD_GET_CONFIG_V14) {
+ socket_get_string(fd, config->cdma_profile.name, sizeof(config->cdma_profile.name));
+ config->cdma_profile.mcp_enable = socket_get_byte(fd);;
+ socket_get_string(fd, config->cdma_profile.mcp_addr, sizeof(config->cdma_profile.mcp_addr));
+ config->cdma_profile.mcp_port = socket_get_int(fd);;
+ config->cdma_profile.pde_addr_valid = socket_get_byte(fd);;
+ config->cdma_profile.pde_ip_type = socket_get_int(fd);;
+ socket_get_string(fd, config->cdma_profile.pde_addr, sizeof(config->cdma_profile.pde_addr));
+ config->cdma_profile.pde_port = socket_get_int(fd);;
+ config->cdma_profile.pde_url_valid = socket_get_byte(fd);;
+ socket_get_string(fd, config->cdma_profile.pde_url_addr, sizeof(config->cdma_profile.pde_url_addr));
+ }
+
+ if(cmd >= APP_MGR_CMD_GET_CONFIG_V20) {
+ //V15
+ config->agps_setting.e911_gps_icon_enable = socket_get_byte(fd);
+ //V16
+ config->agps_setting.e911_open_gps = socket_get_byte(fd);
+ //V17
+ config->gnss_setting.a_gps_satellite_enable = socket_get_byte(fd);
+ config->gnss_setting.a_beidou_satellite_enable = socket_get_byte(fd);
+ config->gnss_setting.a_galileo_satellite_enable = socket_get_byte(fd);
+ //V18
+ config->up_setting.sha_version = socket_get_int(fd);
+ config->up_setting.preferred_2g3g_cell_age = socket_get_int(fd);
+ config->up_setting.ut1 = socket_get_byte(fd);
+ config->up_setting.no_sensitive_log = socket_get_byte(fd);
+ config->up_setting.tls_reuse_enable = socket_get_byte(fd);
+ config->up_setting.imsi_cache_enable = socket_get_byte(fd);
+ config->up_setting.supl_raw_data_enable = socket_get_byte(fd);
+ config->up_setting.tc10_enable = socket_get_byte(fd);
+ config->up_setting.tc10_use_apn = socket_get_byte(fd);
+ config->up_setting.tc10_use_fw_dns = socket_get_byte(fd);
+ config->up_setting.allow_ni_for_gps_off = socket_get_byte(fd);
+ config->up_setting.force_otdoa_assist_req = socket_get_byte(fd);
+ config->cp_setting.reject_non911_nilr_enable = socket_get_byte(fd);
+ config->cp_setting.cp_2g_disable = socket_get_byte(fd);
+ config->cp_setting.cp_3g_disable = socket_get_byte(fd);
+ config->cp_setting.cp_4g_disable = socket_get_byte(fd);
+ config->agps_setting.tc10_ignore_fw_config = socket_get_byte(fd);
+ config->agps_setting.lppe_hide_wifi_bt_status = socket_get_byte(fd);
+ //V19
+ config->agps_setting.lppe_network_location_disable = socket_get_byte(fd);
+ config->cp_setting.cp_lppe_enable = socket_get_byte(fd);
+ config->up_setting.up_lppe_enable = socket_get_byte(fd);
+ //V20
+ config->cp_setting.support_cp_lppe = socket_get_byte(fd);
+ config->gnss_setting.mnl_support_lppe = socket_get_byte(fd);
+ }
+
+ if(cmd >= APP_MGR_CMD_GET_CONFIG_V21) {
+ config->agps_setting.agps_nvram_enable = socket_get_byte(fd);
+ config->agps_setting.lbs_log_enable = socket_get_byte(fd);
+ config->agps_setting.lppe_crowd_source_confident = socket_get_int(fd);
+
+ config->up_setting.esupl_apn_mode = socket_get_int(fd);
+ config->up_setting.tcp_keepalive = socket_get_int(fd);
+ config->up_setting.aosp_profile_enable = socket_get_byte(fd);
+ config->up_setting.bind_nlp_setting_to_supl = socket_get_byte(fd);
+ }
+
+ if(cmd >= APP_MGR_CMD_GET_CONFIG_V22) {
+ config->agps_setting.ignore_si_for_e911 = socket_get_byte(fd);
+ config->cp_setting.cp_lppe_wlan_enable = socket_get_byte(fd);
+ config->cp_setting.cp_lppe_srn_enable = socket_get_byte(fd);
+ config->cp_setting.cp_lppe_sensor_enable = socket_get_byte(fd);
+ config->cp_setting.cp_lppe_dbh_enable = socket_get_byte(fd);
+
+ config->up_setting.up_lppe_wlan_enable = socket_get_byte(fd);
+ config->up_setting.up_lppe_srn_enable = socket_get_byte(fd);
+ config->up_setting.up_lppe_sensor_enable = socket_get_byte(fd);
+ config->up_setting.up_lppe_dbh_enable = socket_get_byte(fd);
+ config->up_setting.ip_version_prefer = socket_get_int(fd);
+ config->up_setting.up_lppe_in_2g3g_disable = socket_get_byte(fd);
+ config->up_setting.up_rrlp_in_4g_disable = socket_get_byte(fd);
+ config->up_setting.up_si_disable = socket_get_byte(fd);
+ }
+
+ if(cmd >= APP_MGR_CMD_GET_CONFIG_V23) {
+ config->up_setting.use_ni_slp = socket_get_byte(fd);
+ config->agps_setting.use_tc10_config = socket_get_byte(fd);
+ config->agps_setting.lppe_def_nlp_enable = socket_get_byte(fd);
+ }
+
+ if(cmd >= APP_MGR_CMD_GET_CONFIG_V24) {
+ config->agps_setting.emergency_ext_secs = socket_get_int(fd);
+ config->up_setting.aosp_pos_mode_enable = socket_get_byte(fd);
+ config->up_setting.privacy_override_mode = socket_get_int(fd);
+ }
+
+ config->valid = 1;
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+ return 0;
+}
+
+/******************************************************
+*
+* Implementation API
+*
+*******************************************************/
+
+agps_intf_agps_config get_agps_config_v3() {
+ agps_intf_agps_config config;
+ memset(&config, 0, sizeof(config));
+
+ get_template_agps_config(APP_MGR_CMD_GET_CONFIG_V3, &config);
+
+ return config;
+}
+
+agps_intf_agps_config get_agps_config_v14() {
+ agps_intf_agps_config config;
+ memset(&config, 0, sizeof(config));
+
+ get_template_agps_config(APP_MGR_CMD_GET_CONFIG_V14, &config);
+ return config;
+}
+
+agps_intf_agps_config get_agps_config_v20() {
+ agps_intf_agps_config config;
+ memset(&config, 0, sizeof(config));
+
+ get_template_agps_config(APP_MGR_CMD_GET_CONFIG_V20, &config);
+ return config;
+}
+
+agps_intf_agps_config get_agps_config_v21() {
+ agps_intf_agps_config config;
+ memset(&config, 0, sizeof(config));
+
+ get_template_agps_config(APP_MGR_CMD_GET_CONFIG_V21, &config);
+ return config;
+}
+
+agps_intf_agps_config get_agps_config_v22() {
+ agps_intf_agps_config config;
+ memset(&config, 0, sizeof(config));
+
+ get_template_agps_config(APP_MGR_CMD_GET_CONFIG_V22, &config);
+ return config;
+}
+
+agps_intf_agps_config get_agps_config_v23() {
+ agps_intf_agps_config config;
+ memset(&config, 0, sizeof(config));
+
+ get_template_agps_config(APP_MGR_CMD_GET_CONFIG_V23, &config);
+ return config;
+}
+
+agps_intf_agps_config get_agps_config_v24() {
+ agps_intf_agps_config config;
+ memset(&config, 0, sizeof(config));
+
+ get_template_agps_config(APP_MGR_CMD_GET_CONFIG_V24, &config);
+ return config;
+}
+
+agps_intf_cdma_profile get_cdma_profile() {
+ agps_intf_agps_config config;
+ memset(&config, 0, sizeof(config));
+
+ get_template_agps_config(APP_MGR_CMD_GET_CONFIG_V14, &config);
+
+ return config.cdma_profile;
+}
+
+agps_intf_supl_profile get_supl_profile() {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+ agps_intf_supl_profile profile;
+
+ memset(&profile, 0, sizeof(profile));
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return profile;
+ }
+
+ // write
+ put_int(buff, &offset, APP_MGR_CMD_GET_OMA_CP_SUPL_PROFILE);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return profile;
+ }
+
+ // read
+ socket_get_string(fd, profile.name, sizeof(profile.name));
+ socket_get_string(fd, profile.addr, sizeof(profile.addr));
+ profile.port = socket_get_int(fd);
+ profile.tls = socket_get_byte(fd);
+ socket_get_string(fd, profile.mcc_mnc, sizeof(profile.mcc_mnc));
+ socket_get_string(fd, profile.app_id, sizeof(profile.app_id));
+ socket_get_string(fd, profile.provider_id, sizeof(profile.provider_id));
+ socket_get_string(fd, profile.default_apn, sizeof(profile.default_apn));
+ socket_get_string(fd, profile.optional_apn, sizeof(profile.optional_apn));
+ socket_get_string(fd, profile.optional_apn_2, sizeof(profile.optional_apn_2));
+ socket_get_string(fd, profile.address_type, sizeof(profile.address_type));
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+ return profile;
+}
+
+agps_intf_profiling_info get_agps_profiling_info() {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+ agps_intf_profiling_info profiling;
+
+ memset(&profiling, 0, sizeof(profiling));
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return profiling;
+ }
+
+ // write
+ put_int(buff, &offset, APP_MGR_CMD_GET_AGPS_PROFILING);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return profiling;
+ }
+
+ // read
+ profiling.element_num = socket_get_int(fd);
+ int i = 0;
+ for(i = 0; i < profiling.element_num; i++) {
+ agps_intf_profiling_element* element = &profiling.elements[i];
+ element->type = socket_get_int(fd);
+ element->timestamp = socket_get_long(fd);
+ socket_get_string(fd, element->message, sizeof(element->message));
+ }
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+ return profiling;
+}
+
+agps_intf_agpsd_version get_agpsd_version() {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+ agps_intf_agpsd_version info;
+
+ memset(&info, 0, sizeof(info));
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return info;
+ }
+
+ // write
+ put_int(buff, &offset, APP_MGR_CMD_GET_AGPSD_VERSION);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return info;
+ }
+
+ if(socket_get_string(fd, info.agpsd_version_string, sizeof(info.agpsd_version_string))) {
+ info.valid = 1;
+ }
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+ return info;
+}
+
+agps_intf_imsi get_imsi_from_agpsd() {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+ agps_intf_imsi info;
+
+ memset(&info, 0, sizeof(info));
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return info;
+ }
+
+ // write
+ put_int(buff, &offset, APP_MGR_CMD_GET_IMSI);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return info;
+ }
+
+ info.valid = socket_get_byte(fd);
+ socket_get_string(fd, info.imsi, sizeof(info));
+ info.is_2_digit_mnc = socket_get_byte(fd);
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+ return info;
+}
+
+int get_emulator_mode() {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+ int ret = 0;
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return 0;
+ }
+
+ // write
+ put_int(buff, &offset, APP_MGR_CMD_GET_EMULATOR_MODE);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return -1;
+ }
+
+ // read
+ ret = socket_get_int(fd);
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+ return ret;
+}
+
+agps_intf_agps_config get_agps_supl_profiles() {
+ agps_intf_agps_config config;
+ memset(&config, 0, sizeof(config));
+
+ agps_mgr_agps_config xml;
+ int i = 0;
+ if (agps_xml_load(&xml, ORIGINAL_AGPES_PROFILE_PATH2)) { // for vendor partition
+ LOGDD("AGPS XML load from %s", ORIGINAL_AGPES_PROFILE_PATH2);
+ LOGDD("xml.supl_profiles_num = %d", xml.supl_profiles_num);
+
+ config.supl_profiles_num = xml.supl_profiles_num;
+ LOGDD("get_agps_supl_profiles[%d] name=%s, addr=%s, port=%d, tls=%d",
+ i, config.supl_profiles[0].name, config.supl_profiles[0].addr,
+ config.supl_profiles[0].port, config.supl_profiles[0].tls);
+ for(i = 0; i < xml.supl_profiles_num; i++) {
+ LBS_STRNCPY(config.supl_profiles[i].name, xml.supl_profiles[i].name, sizeof(config.supl_profiles[i].name));
+ LBS_STRNCPY(config.supl_profiles[i].addr, xml.supl_profiles[i].addr, sizeof(config.supl_profiles[i].addr));
+ config.supl_profiles[i].port = xml.supl_profiles[i].port;
+ config.supl_profiles[i].tls = xml.supl_profiles[i].tls;
+ }
+ free(xml.supl_profiles);
+ } else {
+ LOGDD("Failed to load AGPS XML from %s", ORIGINAL_AGPES_PROFILE_PATH2);
+ }
+ return config;
+
+}
+
+void set_agps_enabled(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_AGPS_ENABLE, enabled);
+}
+
+void set_protocol(agps_intf_agps_protocol protocol) {
+ set_template_1(APP_MGR_CMD_SET_PROTOCOL, protocol);
+}
+
+void set_cdma_pref(agps_intf_cdma_preferred cdma_preferred) {
+ set_template_1(APP_MGR_CMD_SET_CDMA_PREF, cdma_preferred);
+}
+
+void set_up_pref_method(agps_intf_pref_method pref_method) {
+ set_template_1(APP_MGR_CMD_SET_UP_PREF_METHOD, pref_method);
+}
+
+void set_pos_technology_msa(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_POS_TECHNOLOGY_MSA, enabled);
+}
+
+void set_pos_technology_msb(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_POS_TECHNOLOGY_MSB, enabled);
+}
+
+void set_pos_technology_ecid(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_POS_TECHNOLOGY_ECID, enabled);
+}
+
+void set_pos_technology_otdoa(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_POS_TECHNOLOGY_OTDOA, enabled);
+}
+
+void set_pos_technology_autonomous(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_AUTONOMOUS_ENABLE, enabled);
+}
+
+void set_pos_technology_aflt(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_AFLT_ENABLE, enabled);
+}
+
+void set_supl_version(agps_intf_supl_version supl_version) {
+ set_template_1(APP_MGR_CMD_SET_SUPL_VERSION, supl_version);
+}
+
+void set_tls_version(agps_intf_tls_version tls_version) {
+ set_template_1(APP_MGR_CMD_SET_TLS_VERSION, tls_version);
+}
+
+void set_cert_verify(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_CA_ENABLE, enabled);
+}
+
+void set_supl_apn_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_SUPL_APN_ENABLE, enabled);
+}
+
+void set_sync_to_slp_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_SYNC_TO_SLP, enabled);
+}
+
+void set_udp_enable() {
+ set_template_0(APP_MGR_CMD_SET_UDP_ENABLE);
+}
+
+void set_udp_enable_v2(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_UDP_ENABLE_V2, enabled);
+}
+
+void set_lpp_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LPP_ENABLE, enabled);
+}
+
+void set_cert_from_sdcard(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_CERT_FROM_SDCARD_ENABLE, enabled);
+}
+
+void set_imsi_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_IMSI_ENABLE, enabled);
+}
+
+void set_auto_profile_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_AUTO_PROFILE_ENABLE, enabled);
+}
+
+void set_supl_ut1(int timeout_in_second) {
+ set_template_1(APP_MGR_CMD_SET_UT1, timeout_in_second);
+}
+
+void set_supl_ut2(int timeout_in_second) {
+ set_template_1(APP_MGR_CMD_SET_UT2, timeout_in_second);
+}
+
+void set_supl_ut3(int timeout_in_second) {
+ set_template_1(APP_MGR_CMD_SET_UT3, timeout_in_second);
+}
+
+void set_supl_sha_version(int version) {
+ set_template_1_int(APP_MGR_CMD_SET_SUPL_SHA_VERSION, version);
+}
+
+void set_supl_tls_version(int version) {
+ set_template_1_int(APP_MGR_CMD_SET_SUPL_TLS_VERSION, version);
+}
+
+void set_supl_ver_minor(int version) {
+ set_template_1_int(APP_MGR_CMD_SET_SUPL_VER_MINOR, version);
+}
+
+void set_supl_ver_ser_ind(int version) {
+ set_template_1_int(APP_MGR_CMD_SET_SUPL_VER_SER_IND, version);
+}
+
+void set_sib8_16_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_SIB8_16_ENABLE, enabled);
+}
+
+void set_gps_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_GPS_ENABLE, enabled);
+}
+
+void set_a_gps_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_A_GPS_ENABLE, enabled);
+}
+
+void set_glonass_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_GLONASS_ENABLE, enabled);
+}
+
+void set_a_glonass_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_A_GLONASS_ENABLE, enabled);
+}
+
+void set_beidou_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_BEIDOU_ENABLE, enabled);
+}
+
+void set_a_beidou_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_A_BEIDOU_ENABLE, enabled);
+}
+
+void set_galileo_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_GALILEO_ENABLE, enabled);
+}
+
+void set_a_galileo_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_A_GALILEO_ENABLE, enabled);
+}
+
+void set_supl_profile(const char* addr, int port, agps_bool tls_enabled) {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return;
+ }
+
+ // write
+ put_int(buff, &offset, APP_MGR_CMD_SET_SUPL_PROFILE);
+ put_string(buff, &offset, addr);
+ put_int(buff, &offset, port);
+ put_byte(buff, &offset, tls_enabled);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return;
+ }
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+}
+
+//hacc, vacc: K value, loc_age: seconds from 0 to 65535, delay: 2^N, N from (0..7), unit is seconds
+void set_qop(int hacc, int vacc, int loc_age, int delay) {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return;
+ }
+
+ // write
+ put_int(buff, &offset, APP_MGR_CMD_SET_QOP);
+ put_int(buff, &offset, hacc);
+ put_int(buff, &offset, vacc);
+ put_int(buff, &offset, loc_age);
+ put_int(buff, &offset, delay);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return;
+ }
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+}
+
+void set_molr_pos_methd(agps_intf_molr_pos_method molr_pos_method) {
+ set_template_1(APP_MGR_CMD_SET_MOLR_POS_METHDO, molr_pos_method);
+}
+
+void set_external_addr(agps_bool enabled, const char* external_addr) {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return;
+ }
+
+ // write
+ put_int(buff, &offset, APP_MGR_CMD_SET_EXTERNAL_ADDR);
+ put_byte(buff, &offset, enabled);
+ put_string(buff, &offset, external_addr);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return;
+ }
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+}
+
+void set_mlc_number(agps_bool enabled, const char* mlc_number) {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return;
+ }
+
+ // write
+ put_int(buff, &offset, APP_MGR_CMD_SET_MLC_NUMBER);
+ put_byte(buff, &offset, enabled);
+ put_string(buff, &offset, mlc_number);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return;
+ }
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+}
+
+void set_cp_auto_reset(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_CP_AUTO_RESET, enabled);
+}
+
+void set_allow_ni(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_ALLOW_NI, enabled);
+}
+
+void set_allow_roaming(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_ALLOW_ROAMING, enabled);
+}
+
+void set_supl_to_file(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_SUPL_2_FILE, enabled);
+}
+
+void set_reset_to_default() {
+ set_template_0(APP_MGR_CMD_SET_RESET_TO_DEFAULT);
+}
+
+void set_supl_profile_full(agps_intf_supl_profile supl_profile) {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return;
+ }
+
+ // write
+ put_int(buff, &offset, APP_MGR_CMD_SET_OMA_CP_SUPL_PROFILE);
+ put_string(buff, &offset, supl_profile.name);
+ put_string(buff, &offset, supl_profile.addr);
+ put_int(buff, &offset, supl_profile.port);
+ put_byte(buff, &offset, supl_profile.tls);
+ put_string(buff, &offset, supl_profile.mcc_mnc);
+ put_string(buff, &offset, supl_profile.app_id);
+ put_string(buff, &offset, supl_profile.provider_id);
+ put_string(buff, &offset, supl_profile.default_apn);
+ put_string(buff, &offset, supl_profile.optional_apn);
+ put_string(buff, &offset, supl_profile.optional_apn_2);
+ put_string(buff, &offset, supl_profile.address_type);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return;
+ }
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+}
+
+void set_epc_molr_pdu_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_EPC_MOLR_PDU_ENABLE, enabled);
+}
+
+void set_epc_molr_pdu(const char* data, int data_len) {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return;
+ }
+
+ // write
+ put_int(buff, &offset, APP_MGR_CMD_SET_EPC_MOLR_PDU);
+ put_binary(buff, &offset, data, data_len);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return;
+ }
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+}
+
+void set_pde_profile(const char* addr, int port) {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return;
+ }
+
+ // write
+ put_int(buff, &offset, APP_MGR_CMD_SET_PDE_PROFILE);
+ put_string(buff, &offset, addr);
+ put_int(buff, &offset, port);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return;
+ }
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+}
+
+void set_e911_gps_icon_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_E911_GPS_ICON_ENABLE, enabled);
+}
+
+void set_e911_open_gps_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_E911_OPEN_GPS_ENABLE, enabled);
+}
+
+void set_preferred_2g3g_cell_age(int preferred2g3gCellAge) {
+ set_template_1_int(APP_MGR_CMD_SET_PREF_2G3G_CELL_AGE, preferred2g3gCellAge);
+}
+
+void set_no_sensitive_log(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_NO_SENSITIVE_LOG, enabled);
+}
+
+void set_tls_reuse_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_TLS_REUSE_ENABLE, enabled);
+}
+
+void set_imsi_cache_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_IMSI_CACHE_ENABLE, enabled);
+}
+
+void set_supl_raw_data_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_SUPL_RAW_DATA_ENABLE, enabled);
+}
+
+void set_tc10_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_TC10_ENABLE, enabled);
+}
+
+void set_tc10_use_apn(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_TC10_USE_APN, enabled);
+}
+
+void set_tc10_use_fw_dns(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_TC10_USE_FW_DNS, enabled);
+}
+
+void set_allow_ni_for_gps_off(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_ALLOW_NI_FOR_GPS_OFF, enabled);
+}
+
+void set_force_otdoa_assist_req(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_FORCE_OTDOA_ASSIST_REQ, enabled);
+}
+
+void set_reject_non911_nilr_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_REJECT_NON911_NILR_ENABLE, enabled);
+}
+
+void set_cp_2g_disable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_CP_2G_DISABLE, enabled);
+}
+
+void set_cp_3g_disable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_CP_3G_DISABLE, enabled);
+}
+
+void set_cp_4g_disable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_CP_4G_DISABLE, enabled);
+}
+
+void set_tc10_ignore_fw_config(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_TC10_IGNORE_FW_CONFIG, enabled);
+}
+
+void set_lppe_hide_wifi_bt_status(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LPPE_HIDE_WIFI_BT_STATUS, enabled);
+}
+
+void set_lppe_network_location_disable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LPPE_NETWORK_LOCATION_DISABLE, enabled);
+}
+
+void set_lppe_cp_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LPPE_CP_ENABLE, enabled);
+}
+
+void set_lppe_up_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LPPE_UP_ENABLE, enabled);
+}
+
+void set_vzw_debug_screen_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_VZW_DEBUG_SCREEN_ENABLE, enabled);
+}
+
+void set_aosp_profile_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_AOSP_PROFILE_ENABLE, enabled);
+}
+
+void set_bind_nlp_setting_to_supl(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_BIND_NLP_SETTING_TO_SUPL, enabled);
+}
+
+void set_esupl_apn_mode(int mode) {
+ set_template_1_int(APP_MGR_CMD_SET_ESUPL_APN_MODE, mode);
+}
+
+void set_tcp_keep_alive(int time) {
+ set_template_1_int(APP_MGR_CMD_SET_TCP_KEEPALIVE, time);
+}
+
+void set_agps_nvram_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_AGPS_NVRAM_ENABLE, enabled);
+}
+
+void set_lbs_log_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LBS_LOG_ENABLE, enabled);
+}
+
+void set_lppe_crowd_source_confident(int confident) {
+ set_template_1_int(APP_MGR_CMD_SET_LPPE_CROWD_SOURCE_CONFIDENT, confident);
+}
+
+void set_ingore_si_for_e911(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_IGNORE_SI_FOR_E911, enabled);
+}
+
+void set_lppe_cp_wlan_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LPPE_CP_WLAN_ENABLE, enabled);
+}
+
+void set_lppe_cp_srn_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LPPE_CP_SRN_ENABLE, enabled);
+}
+
+void set_lppe_cp_sensor_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LPPE_CP_SENSOR_ENABLE, enabled);
+}
+
+void set_lppe_cp_dbh_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LPPE_CP_DBH_ENABLE, enabled);
+}
+
+void set_lppe_up_wlan_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LPPE_UP_WLAN_ENABLE, enabled);
+}
+
+void set_lppe_up_srn_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LPPE_UP_SRN_ENABLE, enabled);
+}
+
+void set_lppe_up_sensor_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LPPE_UP_SENSOR_ENABLE, enabled);
+}
+
+void set_lppe_up_dbh_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LPPE_UP_DBH_ENABLE, enabled);
+}
+
+void set_ip_version_prefer(agps_supl_ip_version_type ip_version_type) {
+ set_template_1(APP_MGR_CMD_SET_IP_VERSION_PREFER, ip_version_type);
+}
+
+void set_up_lpp_in_2g3g_disable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_UP_LPP_IN_2G3G_DISABLE, enabled);
+}
+
+void set_up_rrlp_in_4g_disable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_UP_RRLP_IN_4G_DISABLE, enabled);
+}
+
+void set_up_si_disable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_UP_SI_DISABLE, enabled);
+}
+
+void set_up_use_ni_slp(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_USE_NI_SLP, enabled);
+}
+
+void set_use_tc10_config(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_USE_TC10_CONFIG, enabled);
+}
+
+void set_lppe_def_nlp_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_LPPE_DEF_NLP_ENABLE, enabled);
+}
+
+void set_up_aosp_pos_mode_enable(agps_bool enabled) {
+ set_template_1(APP_MGR_CMD_SET_AOSP_POS_MODE_ENABLE, enabled);
+}
+
+void set_privacy_override_mode(int flags) {
+ set_template_1_int(APP_MGR_CMD_SET_PRIVACY_OVERRIDE_MODE, flags);
+}
+
+void set_emergency_ext_secs(int seconds) {
+ set_template_1_int(APP_MGR_CMD_SET_EMERGENCY_EXT_SECS, seconds);
+}
+
+void start_supl_2_periodic_session() {
+ set_template_0(APP_MGR_CMD_START_PERIODIC);
+}
+
+void stop_supl_2_periodic_session() {
+ set_template_0(APP_MGR_CMD_ABORT_PERIODIC);
+}
+
+void start_supl_2_area_event_session(agps_intf_area_event_type type) {
+ set_template_1_int(APP_MGR_CMD_START_AREA_EVENT, type);
+}
+
+void stop_supl_2_area_event_session() {
+ set_template_0(APP_MGR_CMD_ABORT_AREA_EVENT);
+}
+
+void start_test_case(int i) {
+ set_template_1_int(APP_MGR_CMD_START_TEST_CASE, i);
+}
+
+void start_test_button(int i) {
+ set_template_1_int(APP_MGR_CMD_START_TEST_BUTTON, i);
+}
+
+void do_reset_agpsd() {
+ //TODO need to do IT
+ set_template_0(APP_MGR_CMD_START_RESET_AGPSD);
+}
+
+void start_emualator_mode(agps_bool enabled) {
+ //TODO need to do IT
+ set_template_1(APP_MGR_CMD_START_EMULATOR_MODE, enabled);
+}
+
+void set_up_tc10_supl_ssl_method(int m) {
+ set_template_1_int(APP_MGR_CMD_SET_TC10_SUPL_SSL_METHOD, m);
+}
+
+void set_up_tc10_auto_supl_ver_for_ni(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_TC10_AUTO_SUPL_VER_FOR_NI, enable);
+}
+
+void set_up_tc10_supl_ver_skt_ni(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_TC10_SUPL_VER_SKT_NI, enable);
+}
+
+void set_up_tc10_use_apn_ni(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_TC10_USE_APN_NI, enable);
+}
+
+void set_up_tc10_use_apn_si(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_TC10_USE_APN_SI, enable);
+}
+
+void set_cp_tc10_privacy_override(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_CP_PRIVACY_OVERRIDE, enable);
+}
+
+void set_up_supl_addr_ni(const char* addr) {
+ char buff[MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int fd = 0;
+
+ fd = socket_connect();
+ if(fd < 0) {
+ return;
+ }
+
+ // write
+ put_int(buff, &offset, APP_MGR_CMD_SET_SUPL_ADDR_NI);
+ put_string(buff, &offset, addr);
+ if(safe_write(fd, buff, offset) == -1) {
+ close(fd);
+ return;
+ }
+
+ // read ACK
+ socket_get_byte(fd);
+
+ close(fd);
+}
+
+void set_up_rrlp_google_supl(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_RRLP_GOOGLE_SUPL, enable);
+}
+
+void set_up_supl2_cap_ext_disable(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_SUPL2_CAP_EXT_DISABLE, enable);
+}
+
+void set_ni_statistic_enable(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_NI_STATISTIC_ENABLE, enable);
+}
+
+void set_up_operation_mode(int m) {
+ set_template_1_int(APP_MGR_CMD_SET_UP_OPERATION_MODE, m);
+}
+
+void set_up_glonass_msa_enable(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_GLONASS_MSA_ENABLE, enable);
+}
+
+void set_up_glonass_msb_enable(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_GLONASS_MSB_ENABLE, enable);
+}
+
+void set_up_beidou_msa_enable(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_BEIDOU_MSA_ENABLE, enable);
+}
+
+void set_up_beidou_msb_enable(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_BEIDOU_MSB_ENABLE, enable);
+}
+
+void set_up_galileo_msa_enable(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_GALILEO_MSA_ENABLE, enable);
+}
+
+void set_up_galileo_msb_enable(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_GALILEO_MSB_ENABLE, enable);
+}
+
+void set_up_tc10_auto_supl_ver_for_eni(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_TC10_AUTO_SUPL_VER_FOR_ENI, enable);
+}
+
+void set_cp_tc10_lpp_guard_time_sec(int t) {
+ set_template_1_int(APP_MGR_CMD_SET_TC10_CP_LPP_GUARD_TIME_SEC, t);
+}
+
+void set_cp_tc10_capability_control_enable(agps_bool enable) {
+ set_template_1(APP_MGR_CMD_SET_TC10_CP_CAPABILITY_VALID_ENABLE, enable);
+}
+
+void set_cp_tc10_capability_control(int flags) {
+ set_template_1_int(APP_MGR_CMD_SET_TC10_CP_CAPABILITY_ENABLE, flags);
+}
+
+void set_ignore_emergency_ext_secs_from_framework(agps_bool does_ignore) {
+ set_template_1(APP_MGR_CMD_SET_IGNORE_EMERGENCY_EXT_SECS_FROM_FRAMEWORK, does_ignore);
+}
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/agps_interface/src/data_coder.c b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/src/data_coder.c
new file mode 100755
index 0000000..ed215c4
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/agps_interface/src/data_coder.c
@@ -0,0 +1,163 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2019. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include <stdio.h>
+#include <string.h>
+
+//===============================================================
+//get
+char get_byte(char* buff, int* offset) {
+ char ret = buff[*offset];
+ *offset += 1;
+ return ret;
+}
+
+short get_short(char* buff, int* offset) {
+ short ret = 0;
+ ret |= get_byte(buff, offset) & 0xff;
+ ret |= (get_byte(buff, offset) << 8);
+ return ret;
+}
+
+int get_int(char* buff, int* offset) {
+ int ret = 0;
+ ret |= get_short(buff, offset) & 0xffff;
+ ret |= (get_short(buff, offset) << 16);
+ return ret;
+}
+
+long long get_long(char* buff, int* offset) {
+ long long ret = 0;
+ ret |= get_int(buff, offset) & 0xffffffffL;
+ ret |= ((long long)get_int(buff, offset) << 32);
+ return ret;
+}
+
+float get_float(char* buff, int* offset) {
+ float ret;
+ int tmp = get_int(buff, offset);
+ ret = *((float*)&tmp);
+ return ret;
+}
+
+double get_double(char* buff, int* offset) {
+ double ret;
+ long long tmp = get_long(buff, offset);
+ ret = *((double*)&tmp);
+ return ret;
+}
+
+char* get_string(char* buff, int* offset) {
+ char ret = get_byte(buff, offset);
+ if(ret == 0) {
+ return NULL;
+ } else {
+ char* p = NULL;
+ int len = get_int(buff, offset);
+ p = &buff[*offset];
+ *offset += len;
+ return p;
+ }
+}
+
+char* get_string2(char* buff, int* offset) {
+ char* output = get_string(buff, offset);
+ if(output == NULL) {
+ return "";
+ } else {
+ return output;
+ }
+}
+
+int get_binary(char* buff, int* offset, char* output) {
+ int len = get_int(buff, offset);
+ if(len > 0) {
+ memcpy(output, &buff[*offset], len);
+ *offset += len;
+ }
+ return len;
+}
+
+//===============================================================
+//put
+void put_byte(char* buff, int* offset, const char input) {
+ *((char*)&buff[*offset]) = input;
+ *offset += 1;
+}
+
+void put_short(char* buff, int* offset, const short input) {
+ put_byte(buff, offset, input & 0xff);
+ put_byte(buff, offset, (input >> 8) & 0xff);
+}
+
+void put_int(char* buff, int* offset, const int input) {
+ put_short(buff, offset, input & 0xffff);
+ put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void put_long(char* buff, int* offset, const long long input) {
+ put_int(buff, offset, input & 0xffffffffL);
+ put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void put_float(char* buff, int* offset, const float input) {
+ int* data = (int*)&input;
+ put_int(buff, offset, *data);
+}
+
+void put_double(char* buff, int* offset, const double input) {
+ long long* data = (long long*)&input;
+ put_long(buff, offset, *data);
+}
+
+void put_string(char* buff, int* offset, const char* input) {
+ if(input == NULL) {
+ put_byte(buff, offset, 0);
+ } else {
+ int len = strlen(input) + 1;
+ put_byte(buff, offset, 1);
+ put_int(buff, offset, len);
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+ }
+}
+
+void put_binary(char* buff, int* offset, const char* input, const int len) {
+ put_int(buff, offset, len);
+ if(len > 0) {
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+ }
+}
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/certs/UbuntuOne-Go_Daddy_CA.pem b/src/connectivity/agps/2.0/lbs_em/src/certs/UbuntuOne-Go_Daddy_CA.pem
new file mode 100755
index 0000000..b6276d4
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/certs/UbuntuOne-Go_Daddy_CA.pem
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx
+ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
+RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw
+MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH
+QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j
+b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j
+b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H
+KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm
+VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR
+SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT
+cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ
+6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu
+MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS
+kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB
+BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f
+BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv
+c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH
+AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO
+BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG
+OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU
+A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o
+0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX
+RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH
+qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV
+U+4=
+-----END CERTIFICATE-----
diff --git a/src/connectivity/agps/2.0/lbs_em/src/lbs_em.c b/src/connectivity/agps/2.0/lbs_em/src/lbs_em.c
new file mode 100755
index 0000000..9dcf1c4
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/lbs_em.c
@@ -0,0 +1,5545 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h> /* usleep */
+#include <sys/time.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <errno.h>
+#include <semaphore.h>
+#include <math.h>
+
+#include "mtk_tree.h"
+#include "agps_interface.h"
+#include "agps_debug_interface.h"
+#include "mnldinf_basic.h"
+#include "mnldinf_ext.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_gnss_at_client.h"
+#include "MtkNlp.h"
+
+// ------------- history-----------------
+// 1.00 MTK LBS EM implementation done
+// 1.01 Add MTK GNSS AT Command
+// 1.02 porting to OpenWrt
+// 1.03 Change MNLD interface to TCP mnldinf
+// ------------- definition -----------------
+#define MTK_LBS_EM_VERSION "1.03"
+
+//---------------------------------- porting configurations -------------------------------------------
+#define MTK_LBS_EM_TEST_CERT_PATH "certs/UbuntuOne-Go_Daddy_CA.pem"
+#define MTK_LBS_EM_TEST_CERT_NAME "UbuntuOne-Go_Daddy_CA.pem"
+
+//-------------------------------------------------------------------------------------------------
+#define INVALID_VALUE -1
+#define LBS_EM_INT_CMD_RETRY_CONNECT 3
+#define LBS_EM_MAX_RETRY_CONNECT_TIMES 10
+#define LBS_EM_RETRY_CONNECT_INTERVAL 3000
+#define LBS_EM_WAKE_LOCK_TIMEOUT (5 * 1000)
+#define LBS_EM_WAKE_LOCK_ID "lbs_em_wakelock"
+
+typedef enum {
+ UI_MAIN_TYPE_EXIT = 0,
+ UI_MAIN_TYPE_GPS_CONTROL = 1,
+ UI_MAIN_TYPE_AGPS_SETTINGS,
+ UI_MAIN_TYPE_DEBUG_SETTINGS,
+ UI_MAIN_TYPE_GNSS_AT_SETTINGS,
+ UI_MAIN_TYPE_NLP_TEST,
+ UI_MAIN_TYPE_DEBUG_1 = 3646633,
+} ui_main_type;
+
+typedef enum {
+ UI_GPS_CONTROL_TYPE_BACK = 0,
+ UI_GPS_CONTROL_TYPE_GPS_INIT,
+ UI_GPS_CONTROL_TYPE_GPS_START,
+ UI_GPS_CONTROL_TYPE_GPS_START_WITH_WAKE_LOCK_RELEASE,
+ UI_GPS_CONTROL_TYPE_GPS_STOP,
+ UI_GPS_CONTROL_TYPE_GPS_CLEANUP,
+ UI_GPS_CONTROL_TYPE_GPS_DELETE_AIDING_DATA,
+ UI_GPS_CONTROL_TYPE_GPS_NI_NOTIRY_RESPONSE,
+} ui_gps_control_type;
+
+typedef enum {
+ UI_GPS_DELETE_AIDING_TYPE_BACK = 0,
+ UI_GPS_DELETE_AIDING_TYPE_HOT_START,
+ UI_GPS_DELETE_AIDING_TYPE_WARM_START,
+ UI_GPS_DELETE_AIDING_TYPE_COLD_START,
+ UI_GPS_DELETE_AIDING_TYPE_FULL_START,
+} ui_gps_delete_aiding_type;
+
+typedef enum {
+ UI_AGPS_SETTINGS_TYPE_BACK = 0,
+
+ UI_AGPS_SETTINGS_TYPE_GET_AGPS_SETTINGS = 1,
+ UI_AGPS_SETTINGS_TYPE_SET_AGPS_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_AGPS_PROTOCOL,
+ UI_AGPS_SETTINGS_TYPE_SET_CDMA_PREFERENCE,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_PREFER_METHOD,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_MSA_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_MSB_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_ECID_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_AUTONOMOUS_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_AFLT_ENABLE = 10,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_LPP_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_SUPL_VERSION,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_TLS_VERSION,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_CA_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_UDP_ENABLE =15,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_UT2,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_UT3,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_SUPL_VER_MINOR,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_SUPL_VER_SER_IND,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_PROFILE = 20,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_PERIODIC_SETTINGS,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_AREA_SETTINGS,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_SI_QOP_SETTINGS,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_ALLOW_NI_REQUEST,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_ALLOW_ROAMING = 25,
+ UI_AGPS_SETTINGS_TYPE_SET_CP_AUTO_RESET,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_SUPL_LOG_TO_FILE,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_SENSITIVE_LOG,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_CERT_FROM_SDCARD,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_AUTO_PROFILE = 30,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_DEDICATE_APN,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_SYNC_TO_SLP,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_IMSI_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_E911_GPS_ICON,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_LPPE_NETWORK_LOCATION_DISABLE = 35,
+ UI_AGPS_SETTINGS_TYPE_SET_CP_LPPE_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_UP_LPPE_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_AOSP_PROFILE_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_BIND_NLP_SETTING_TO_SUPL,
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_LBS_LOG_ENABLE = 40,
+
+ UI_AGPS_SETTINGS_TYPE_SET_INGORE_SI_FOR_E911,
+ UI_AGPS_SETTINGS_TYPE_SET_LPPE_CP_WLAN,
+ UI_AGPS_SETTINGS_TYPE_SET_LPPE_CP_SRN,
+ UI_AGPS_SETTINGS_TYPE_SET_LPPE_CP_SENSOR,
+ UI_AGPS_SETTINGS_TYPE_SET_LPPE_CP_DBH = 45,
+ UI_AGPS_SETTINGS_TYPE_SET_LPPE_UP_WLAN,
+ UI_AGPS_SETTINGS_TYPE_SET_LPPE_UP_SRN,
+ UI_AGPS_SETTINGS_TYPE_SET_LPPE_UP_SENSOR,
+ UI_AGPS_SETTINGS_TYPE_SET_LPPE_UP_DBH,
+ UI_AGPS_SETTINGS_TYPE_SET_UP_LPP_IN_2G_3G_DISABLE = 50,
+ UI_AGPS_SETTINGS_TYPE_SET_UP_RRLP_IN_4G_DISABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_UP_SI_DISABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_LPPE_DEFAULT_NLP_LOCATION_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_FORCE_OTDOA_ASSIST_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_AOSP_POSITION_MODE_ENABLE = 55,
+ UI_AGPS_SETTINGS_TYPE_SET_PRIVACY_OVERRIDE_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_ALLOW_NI_FOR_GPS_OFF_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_IP_VERSION_PREFER,
+
+ UI_AGPS_SETTINGS_TYPE_SET_SUPL_TCP_KEEPALIVE,
+ UI_AGPS_SETTINGS_TYPE_SET_LPPE_CROWD_SOURCE_CONFIDENT = 60,
+ UI_AGPS_SETTINGS_TYPE_SET_GNSS_SIB8_SIB16_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_GNSS_A_GLONASS_SATELLITE_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_GNSS_A_BEIDOU_SATELLITE_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_GNSS_A_GALILEO_SATELLITE_ENABLE,
+
+ UI_AGPS_SETTINGS_TYPE_SET_CP_MOLR_POS_METHOD = 100,
+ UI_AGPS_SETTINGS_TYPE_SET_CP_EXTERNAL_ADDR_ENABLE,
+ UI_AGPS_SETTINGS_TYPE_SET_CP_MLC_NUMBER,
+ UI_AGPS_SETTINGS_TYPE_SET_CP_EPC_MOLR_LPP_PAYLOAD_ENABLE,
+
+ UI_AGPS_SETTINGS_TYPE_RESET_TO_DEFAULT = 999,
+} ui_agps_settings_type;
+
+typedef enum {
+ UI_AT_SETTINGS_TYPE_BACK = 0,
+
+ UI_AT_SETTINGS_GNSS_START_REQUEST,
+ UI_AT_SETTINGS_GNSS_START_WITH_WAKE_LOCK_RELEASE,
+ UI_AT_SETTINGS_GNSS_STOP_REQUEST,
+ UI_AT_SETTINGS_HOST_REBOOT_NOTIFY,
+ UI_AT_SETTINGS_GNSS_STATUS_REQUEST = 5,
+ UI_AT_SETTINGS_GNSS_ENABLE_SET,
+ UI_AT_SETTINGS_NI_ENABLE_SET,
+ UI_AT_SETTINGS_AGPS_MODE_SET,
+ UI_AT_SETTINGS_SUPL_VERSION_SET,
+ UI_AT_SETTINGS_SUPL_ADDRESS_SET = 10,
+ UI_AT_SETTINGS_DELETE_AIDING_DATA_REQUEST,
+ UI_AT_SETTINGS_NI_NOTIFY_RESPONSE,
+ UI_AT_SETTINGS_REFERENCE_LOCATION_RESPONSE,
+ UI_AT_SETTINGS_REFERENCE_TIME_RESPONSE,
+ UI_AT_SETTINGS_NMEA_CONFIG_SET = 15,
+ UI_AT_SETTINGS_LOOPBACK_REQUEST,
+
+ UI_AT_SETTINGS_GEOFENCE_MAX_NUMBER_REQUEST = 31,
+ UI_AT_SETTINGS_GEOFENCE_ADD_CIRCLE_REQUEST,
+ UI_AT_SETTINGS_GEOFENCE_ADD_CIRCLE_WITH_WAKE_LOCK_RELEASE,
+ UI_AT_SETTINGS_GEOFENCE_DELETE_REQUEST,
+ UI_AT_SETTINGS_GEOFENCE_DELETE_ALL_REQUEST,
+
+ UI_AT_SETTINGS_CERTIFICATE_INJECT = 51,
+ UI_AT_SETTINGS_CERTIFICATE_NAME_LIST_REQUEST,
+ UI_AT_SETTINGS_CERTIFICATE_DELETE,
+ UI_AT_SETTINGS_CERTIFICATE_DELETE_ALL,
+
+ UI_AT_SETTINGS_INPUT_A_GNSS_AT_COMMAND_MANUALLY = 99,
+} ui_at_test_type;
+
+typedef enum {
+ UI_NLP_TEST_TYPE_BACK = 0,
+ UI_NLP_TEST_TYPE_START_RQUEST,
+ UI_NLP_TEST_TYPE_STOP_RQUEST,
+ UI_NLP_TEST_TYPE_GET_LAST_LOC,
+ UI_NLP_TEST_TYPE_GET_SINGLE_UPDATE,
+} ui_nlp_test_type;
+
+typedef enum {
+ UI_DEBUG_1_TYPE_BACK = 0,
+ UI_DEBUG_1_TYPE_RESET_AGPSD,
+ UI_DEBUG_1_TYPE_TEST_BUTTON,
+ UI_DEBUG_1_TYPE_EMULATOR_MODE_ON,
+ UI_DEBUG_1_TYPE_EMULATOR_MODE_OFF,
+ UI_DEBUG_1_TYPE_START_TEST_CASE,
+} ui_debug_1_type;
+
+#define MAX_GEOFENCE_NUM 20
+
+typedef struct {
+ int id;
+} at_geofence_ctx;
+
+typedef struct {
+ int num;
+ at_geofence_ctx elem[MAX_GEOFENCE_NUM];
+} at_geofence_list;
+
+
+// LBS EM (client) <-> GNSS ADP (server)
+#define GNSSADP_AT_SOCKET "mtk_gnssadp_at"
+
+// LBS EM (client) <-> LBS EM (server)
+#define LBSEM_INTERNAL_SOCKET "mtk_lbsem_internal"
+int g_epfd;
+int g_agps_debug_fd = -1;
+int g_gnssadp_fd = -1;
+int g_mnld_basic_fd = -1;
+int g_mnld_ext_fd = -1;
+int g_internal_fd = -1;
+mtk_socket_fd g_nlpservice_fd; // nlp client
+timer_t g_connect_retry_timer;
+int g_connect_retry_count = 0;
+agps_intf_agps_config g_config;
+at_geofence_list g_geo_list;
+
+// wake lock
+pthread_mutex_t g_mutex;
+timer_t g_wake_unlock_timer;
+bool g_wake_lock_acquired = false;
+bool g_at_geofence_add_with_wake_lock_release = false;
+
+
+void mnldinf_location_hdlr(gps_location location);
+void mnldinf_nmea_hdlr(int64_t timestamp, const char* nmea, int length);
+void mnldinf_gnss_sv_hdlr(gnss_sv_info sv);
+static void lbs_em_acquire_wake_lock_mutex();
+
+bool geofence_list_add(at_geofence_list* list, int id) {
+ if(list->num >= MAX_GEOFENCE_NUM) {
+ LOGE("[Geofence] Fail to add due to MAX_GEOFENCE_NUM=%d", MAX_GEOFENCE_NUM);
+ return false;
+ }
+
+ list->elem[list->num].id = id;
+ list->num++;
+ return true;
+}
+
+bool geofence_list_remove(at_geofence_list* list, int id) {
+ int i = 0;
+ for(i = 0; i < list->num; i++) {
+ if(list->elem[i].id == id) {
+ for(; i < list->num - 1; i++) {
+ list->elem[i] = list->elem[i + 1];
+ }
+ memset(&list->elem[i], 0, sizeof(at_geofence_ctx));
+ list->num--;
+ return true;
+ }
+ }
+ return false;
+}
+
+// ------------- utils -----------------
+
+static void clear_stdin_buff() {
+ char c;
+ while((c = (char)getchar()) != '\n' && c != EOF);
+}
+
+static int scanf_int(int default_value, bool clear_screen) {
+ int ret;
+ int input;
+ ret = scanf("%d", &input);
+ clear_stdin_buff();
+ if(clear_screen) {
+ system("clear");
+ }
+ if(ret <= 0) {
+ return default_value;
+ } else {
+ return input;
+ }
+}
+
+static long long scanf_long(long long default_value, bool clear_screen) {
+ int ret;
+ long long input;
+ ret = scanf("%lld", &input);
+ clear_stdin_buff();
+ if(clear_screen) {
+ system("clear");
+ }
+ if(ret <= 0) {
+ return default_value;
+ } else {
+ return input;
+ }
+}
+
+static double scanf_double(double default_value, bool clear_screen) {
+ int ret;
+ double input;
+ ret = scanf("%lf", &input);
+ clear_stdin_buff();
+ if(clear_screen) {
+ system("clear");
+ }
+ if(ret <= 0) {
+ return default_value;
+ } else {
+ return input;
+ }
+}
+
+
+//-1 means failure
+static int get_time_str(char* buf, int len) {
+ struct timeval tv;
+ struct timezone tz;
+ struct tm *tm;
+
+ gettimeofday(&tv, &tz);
+ tm = localtime(&tv.tv_sec);
+
+ memset(buf, 0, len);
+ sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d.%03d",
+ tm->tm_year + 1900, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec,
+ (int)(tv.tv_usec / 1000));
+
+ return 0;
+}
+
+#define msleep(usec) {\
+ int ret = usleep((usec)*1000);\
+ if(ret == -1) {\
+ LOGE("usleep() failed, usec=%lu reason=[%s]%d", strerror(errno), errno);\
+ }\
+}
+
+// ------------- global_variable -----------------
+traversal_path g_traversal;
+tree_node g_tree_root;
+
+int g_agps_debug_enable = 0;
+int g_gps_info_enable = 1;
+int g_nmea_enable = 1;
+int g_at_cmd_enable = 1;
+
+bool g_at_cert_injecting = false;
+sem_t g_cert_sem;
+bool g_cert_result = false;
+int g_notify_id = 0;
+
+static bool cert_inject_full_test(mtk_gnss_cert *cert) {
+ //test 41 full cert testing
+ memset(cert, 0, sizeof(*cert));
+ FILE* fp = fopen(MTK_LBS_EM_TEST_CERT_PATH, "r");
+ if(fp == NULL) {
+ LOGE("cert_inject_procedure() fopen() failed");
+ return false;
+ }
+
+ //get file size
+ fseek(fp, 0L, SEEK_END);
+ cert->total_msg_len = ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+
+ cert->seq_no = 0;
+ LBS_STRNCPY(cert->name, MTK_LBS_EM_TEST_CERT_NAME, sizeof(cert->name));
+
+ int ret;
+ do {
+ memset(cert->data, 0, sizeof(cert->data));
+ ret = fread(cert->data, 1, 1000, fp);
+ if(ret > 0) {
+ //LOGD("fread() ret=[%d] buff=[%s]", ret, buff);
+ cert->seq_no++;
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != true) {
+ LOGE("cert_inject_procedure() test 41 failed!!");
+ fclose(fp);
+ return false;
+ }
+ }
+ } while(ret > 0);
+
+ fclose(fp);
+ LOGW("cert_inject_procedure() all test cases are passed!!");
+ return true;
+}
+
+static void cert_inject_procedure() {
+ g_at_cert_injecting = true;
+ mtk_gnss_cert cert;
+ memset(&cert, 0, sizeof(cert));
+
+ do {
+ //test 1 invalid total_msg_len 0
+ cert.total_msg_len = 0;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "d", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 1 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 2 invalid seq_no 0
+ cert.total_msg_len = 1;
+ cert.seq_no = 0;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "d", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 2 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 3 empy name
+ cert.total_msg_len = 1;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "d", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 3 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 4 empy data
+ cert.total_msg_len = 1;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 4 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 5 total_msg_len < data size
+ cert.total_msg_len = 1;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "data", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 5 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 6 invalid total_msg_len -1
+ cert.total_msg_len = -1;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "d", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 6 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 7 invalid total_msg_len 64001
+ cert.total_msg_len = 64001;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "d", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 7 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 8 invalid seq_no -1
+ cert.total_msg_len = 1;
+ cert.seq_no = -1;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "d", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 8 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 9 invalid seq_no 65
+ cert.total_msg_len = 1;
+ cert.seq_no = 65;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "d", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 9 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 10 invlid name
+ cert.total_msg_len = 1;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "/", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "d", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 10 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 11 invlid name
+ cert.total_msg_len = 1;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "d2", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 11 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 21 invalid total_msg_len
+ cert.total_msg_len = 2;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "d", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != true) {
+ LOGE("cert_inject_procedure() test 21.1 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+ cert.total_msg_len = 1;
+ cert.seq_no = 2;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "e", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 21.2 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 22 invalid seq_no
+ cert.total_msg_len = 2;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "d", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != true) {
+ LOGE("cert_inject_procedure() test 22.1 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+ cert.total_msg_len = 2;
+ cert.seq_no = 3;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "e", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 22.2 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 23 invalid name
+ cert.total_msg_len = 2;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "d", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != true) {
+ LOGE("cert_inject_procedure() test 23.1 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+ cert.total_msg_len = 2;
+ cert.seq_no = 2;
+ LBS_STRNCPY(cert.name, "d2", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "e", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 23.2 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 24 data over total size
+ cert.total_msg_len = 2;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "d", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != true) {
+ LOGE("cert_inject_procedure() test 24.1 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+ cert.total_msg_len = 2;
+ cert.seq_no = 2;
+ LBS_STRNCPY(cert.name, "d", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "e2", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != false) {
+ LOGE("cert_inject_procedure() test 24.2 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 31 simple test
+ cert.total_msg_len = 4;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "test", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "data", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != true) {
+ LOGE("cert_inject_procedure() test 31 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 32 valid name
+ cert.total_msg_len = 5;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 []()-._", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "data2", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != true) {
+ LOGE("cert_inject_procedure() test 32 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 33 simple sequence test
+ cert.total_msg_len = 3;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "test2", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "a", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != true) {
+ LOGE("cert_inject_procedure() test 33.1 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ cert.total_msg_len = 3;
+ cert.seq_no = 2;
+ LBS_STRNCPY(cert.name, "test2", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "b", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != true) {
+ LOGE("cert_inject_procedure() test 33.2 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ cert.total_msg_len = 3;
+ cert.seq_no = 3;
+ LBS_STRNCPY(cert.name, "test2", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "c", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != true) {
+ LOGE("cert_inject_procedure() test 33.3 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 34 test seq_no reset
+ cert.total_msg_len = 2;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "test3", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "a", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != true) {
+ LOGE("cert_inject_procedure() test 34.1 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+ cert.total_msg_len = 2;
+ cert.seq_no = 1;
+ LBS_STRNCPY(cert.name, "test4", sizeof(cert.name));
+ LBS_STRNCPY(cert.data, "ab", sizeof(cert.data));
+ mtk_at_send_gnss_cert_set(g_gnssadp_fd, &cert);
+ sem_wait(&g_cert_sem);
+ if(g_cert_result != true) {
+ LOGE("cert_inject_procedure() test 34.2 failed!!");
+ g_at_cert_injecting = false;
+ break;
+ }
+
+ //test 41 full cert testing
+ if (!cert_inject_full_test(&cert)) {
+ g_at_cert_injecting = false;
+ break;
+ }
+ } while(false);
+
+}
+
+// ------------- implementation -----------------
+
+void ui_main() {
+ LOGD("=== Main Menu, Version=[%s] ===", MTK_LBS_EM_VERSION);
+ LOGD("0. Exit");
+ LOGD(" ");
+ LOGD("1. GPS Control (ex: Start, Stop, Delete Aiding Data, ...etc.)"); // more
+ LOGD("2. AGPS Settings (ex: SUPL profile, ...etc.)"); // more
+ LOGD("3. Debug Settings"); // more
+ LOGD("4. GNSS AT Command Test"); // more
+ LOGD("5. NLP Service Test"); // more
+
+ LOGD("input: ");
+ ui_main_type input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case UI_MAIN_TYPE_EXIT:
+ exit(0);
+ break;
+ case UI_MAIN_TYPE_GPS_CONTROL:
+ case UI_MAIN_TYPE_AGPS_SETTINGS:
+ case UI_MAIN_TYPE_DEBUG_SETTINGS:
+ case UI_MAIN_TYPE_GNSS_AT_SETTINGS:
+ case UI_MAIN_TYPE_NLP_TEST:
+ case UI_MAIN_TYPE_DEBUG_1:
+ traversal_path_go(&g_traversal, input);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_gps_control() {
+ LOGD("=== GPS Control ====");
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. GPS Init");
+ LOGD("2. GPS Start");
+ LOGD("3. GPS Start with Wake Lock Release");
+ LOGD("4. GPS Stop");
+ LOGD("5. GPS Cleanup");
+ LOGD("6. GPS Delete Aiding Data"); // more
+ LOGD("7. GPS Ni Notify Response");
+
+ LOGD("input: ");
+ ui_gps_control_type input = scanf_int(INVALID_VALUE, false);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case UI_GPS_CONTROL_TYPE_BACK:
+ traversal_path_back(&g_traversal);
+ break;
+ case UI_GPS_CONTROL_TYPE_GPS_INIT:
+ LOGD("GPS Init");
+ mnldinf_basic_gnss_init(g_mnld_basic_fd);
+ break;
+ case UI_GPS_CONTROL_TYPE_GPS_START:
+ LOGD("GPS Start");
+ mnldinf_basic_gnss_start(g_mnld_basic_fd);
+ break;
+ case UI_GPS_CONTROL_TYPE_GPS_START_WITH_WAKE_LOCK_RELEASE:
+ LOGD("GPS Start With wake lock release");
+ mnldinf_basic_gnss_start(g_mnld_basic_fd);
+ //delay to do wake_unlock to ensure the msg can be deliveried to other process
+ timer_start(g_wake_unlock_timer, LBS_EM_WAKE_LOCK_TIMEOUT);
+ break;
+ case UI_GPS_CONTROL_TYPE_GPS_STOP:
+ LOGD("GPS Stop");
+ mnldinf_basic_gnss_stop(g_mnld_basic_fd);
+ lbs_em_acquire_wake_lock_mutex();
+ break;
+ case UI_GPS_CONTROL_TYPE_GPS_CLEANUP:
+ LOGD("GPS Cleanup");
+ mnldinf_basic_gnss_cleanup(g_mnld_basic_fd);
+ break;
+ case UI_GPS_CONTROL_TYPE_GPS_DELETE_AIDING_DATA:
+ traversal_path_go(&g_traversal, input);
+ break;
+ case UI_GPS_CONTROL_TYPE_GPS_NI_NOTIRY_RESPONSE: {
+ LOGD("NI Notify Response: Response Type (1=Accept, 2=Deny, 3=NO Response) input:");
+ int user_response = scanf_int(INVALID_VALUE, false);
+ if(user_response == INVALID_VALUE) {
+ LOGE("ERR: read invalid resp_type");
+ return;
+ }
+
+ system("clear");
+ mnldinf_ext_ni_respond(g_mnld_ext_fd, g_notify_id, user_response);
+ LOGD("NI Notify Response id=[%d] resp_type=[%d] Sent", g_notify_id, user_response);
+ }
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_gps_control_delete_aiding_data() {
+ LOGD("=== GPS Delete Aiding Data ====");
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Hot Start");
+ LOGD("2. Warm Start");
+ LOGD("3. Cold Start");
+ LOGD("4. Full Start");
+
+ LOGD("input: ");
+ ui_gps_delete_aiding_type input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+#define GPS_DELETE_EPHEMERIS 0x0001
+#define GPS_DELETE_ALMANAC 0x0002
+#define GPS_DELETE_POSITION 0x0004
+#define GPS_DELETE_TIME 0x0008
+#define GPS_DELETE_IONO 0x0010
+#define GPS_DELETE_UTC 0x0020
+#define GPS_DELETE_HEALTH 0x0040
+#define GPS_DELETE_SVDIR 0x0080
+#define GPS_DELETE_SVSTEER 0x0100
+#define GPS_DELETE_SADATA 0x0200
+#define GPS_DELETE_RTI 0x0400
+#define GPS_DELETE_CELLDB_INFO 0x8000
+#define GPS_DELETE_ALL 0xFFFF
+
+ switch(input) {
+ case UI_GPS_DELETE_AIDING_TYPE_BACK:
+ traversal_path_back(&g_traversal);
+ break;
+ case UI_GPS_DELETE_AIDING_TYPE_HOT_START:
+ LOGD("Hot Start");
+ mnldinf_ext_gnss_delete_aiding_data(g_mnld_ext_fd, GPS_DELETE_RTI);
+ traversal_path_back(&g_traversal);
+ break;
+ case UI_GPS_DELETE_AIDING_TYPE_WARM_START:
+ LOGD("Warm Start");
+ mnldinf_ext_gnss_delete_aiding_data(g_mnld_ext_fd, GPS_DELETE_EPHEMERIS);
+ traversal_path_back(&g_traversal);
+ break;
+ case UI_GPS_DELETE_AIDING_TYPE_COLD_START:
+ LOGD("Cold Start");
+ mnldinf_ext_gnss_delete_aiding_data(g_mnld_ext_fd, GPS_DELETE_EPHEMERIS |
+ GPS_DELETE_POSITION | GPS_DELETE_TIME | GPS_DELETE_IONO |
+ GPS_DELETE_UTC | GPS_DELETE_HEALTH);
+ traversal_path_back(&g_traversal);
+ break;
+ case UI_GPS_DELETE_AIDING_TYPE_FULL_START:
+ LOGD("Full Start");
+ mnldinf_ext_gnss_delete_aiding_data(g_mnld_ext_fd, GPS_DELETE_ALL);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+agps_intf_agps_config ui_agps_settings_read() {
+ agps_intf_agps_config config = get_agps_config_v24();
+ LOGD("Read AGPS Settings (V24): %s", config.valid? "Success": "Failure");
+ dump_agps_intf_agps_config(config);
+ return config;
+}
+
+char* get_agps_protocol() {
+ switch(g_config.agps_setting.agps_protocol) {
+ case 0:
+ return "User Plane";
+ case 1:
+ return "Control Plane";
+ default:
+ return "Unknown value";
+ }
+}
+
+char* get_cdma_preferred() {
+ switch(g_config.up_setting.cdma_preferred) {
+ case 0:
+ return "WCDMA prefer";
+ case 2:
+ return "CDMA Force";
+ default:
+ return "Unknown value";
+ }
+}
+
+char* get_pref_method() {
+ switch(g_config.up_setting.pref_method) {
+ case 0:
+ return "MSA";
+ case 1:
+ return "MSB";
+ case 2:
+ return "No prefer";
+ default:
+ return "Unknown value";
+ }
+}
+
+char* get_supl_version() {
+ switch(g_config.up_setting.supl_version) {
+ case 1:
+ return "SUPL1.0";
+ case 2:
+ return "SUPL2.0";
+ default:
+ return "Unknown value";
+ }
+}
+
+char* get_tls_version() {
+ switch(g_config.up_setting.tls_version) {
+ case 0:
+ return "1_0";
+ case 1:
+ return "1_1";
+ case 2:
+ return "2_0";
+ default:
+ return "Unknown value";
+ }
+}
+
+char* get_ip_version_prefer() {
+ switch(g_config.up_setting.ip_version_prefer) {
+ case 0:
+ return "IP V6";
+ case 1:
+ return "IP V4";
+ default:
+ return "Unknown value";
+ }
+}
+
+char* get_molr_pos_method() {
+ switch(g_config.cp_setting.molr_pos_method) {
+ case 0:
+ return "Location Estimate";
+ case 1:
+ return "Assistance Data";
+ default:
+ return "Unknown value";
+ }
+}
+
+char* get_enabled_status(int value) {
+ switch(value) {
+ case 0:
+ return "Disabled";
+ case 1:
+ return "Enabled";
+ default:
+ return "Unknown value";
+ }
+}
+
+char* get_disabled_status(int value) {
+ switch(value) {
+ case 0:
+ return "Enabled";
+ case 1:
+ return "Disabled";
+ default:
+ return "Unknown value";
+ }
+}
+void ui_agps_settings() {
+ g_config = ui_agps_settings_read();
+ LOGD("=== AGPS Settings ====");
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Read AGPS Settings");
+ LOGD(" ");
+ LOGD("2. Set AGPS Enable: [%d]", g_config.agps_setting.agps_enable);
+ LOGD("3. UP/CP switching (SI only): [%s]", get_agps_protocol());
+ LOGD("4. CDMA Settings: [%s]", get_cdma_preferred());
+ LOGD("5. Set SUPL Prefer Settings: [%s]", get_pref_method());
+ LOGD("6. UP Pos Technology MSA Enable: [%d]", g_config.up_setting.msa_enable);
+ LOGD("7. UP Pos Technology MSB Enable: [%d]", g_config.up_setting.msb_enable);
+ LOGD("8. UP Pos Technology ECID Enable: [%d]", g_config.up_setting.ecid_enable);
+ LOGD("9. UP Pos Technology Autonomus Enable: [%d]", g_config.up_setting.autonomous_enable);
+ LOGD("10. UP Pos Technology AFLT Enable: [%d]", g_config.up_setting.aflt_enable);
+ LOGD("11. UP Pos Protocol LPP Enable: [%d]", g_config.up_setting.lpp_enable);
+ LOGD("12. SUPL Version: [%s]", get_supl_version());
+ LOGD("13. Set SUPL TLS Version: [%s]", get_tls_version());
+ LOGD("14. Certification Verification Enable: [%d]", g_config.up_setting.ca_enable);
+ LOGD("15. UDP Enable: [%d]", g_config.up_setting.udp_enable);
+ LOGD("16. Set SUPL UT2 Timer: [%d]", g_config.up_setting.ut2);
+ LOGD("17. Set SUPL UT3 Timer: [%d]", g_config.up_setting.ut3);
+ LOGD("18. Set SUPL VER Miner: [%d]", g_config.up_setting.supl_ver_minor);
+ LOGD("19. Set SUPL VER Serind: [%d]", g_config.up_setting.supl_ver_ser_ind);
+ LOGD("20. Set SUPL Profile: SLP Address: [%s] SLP Port: [%d] TLS Enable: [%d]",
+ g_config.cur_supl_profile.addr,
+ g_config.cur_supl_profile.port,
+ g_config.cur_supl_profile.tls);
+ LOGD("21. Periodic Settings");
+ LOGD("22. Area Settings");
+ LOGD("23. SUPL SI QOP Settings");
+ LOGD("24. Allow Network Initiated Request: [%d]", g_config.up_setting.ni_request);
+ LOGD("25. Allow Roaming: [%d]", g_config.up_setting.roaming);
+ LOGD("26. CP Auto Reset: [%d]", g_config.cp_setting.cp_auto_reset);
+ LOGD("27. Log SUPL to File: [%d]", g_config.up_setting.supl_log);
+ LOGD("28. Log Sensitive Data: [%d]", !g_config.up_setting.no_sensitive_log);
+ LOGD("29. Allow AGPS Certificates for Lab Test: [%d]", g_config.up_setting.cert_from_sdcard);
+ LOGD("30. Allow Auto Configuring SUPL Profile Base on Current Plmn: [%d]", g_config.up_setting.auto_profile_enable);
+ LOGD("31. Allow SUPL dedicated APN: [%d]", g_config.up_setting.apn_enable);
+ LOGD("32. Sync AGPS Settings to SLPD: [%d]", g_config.up_setting.sync_to_slp);
+ LOGD("33. Allow valid IMSI in SUPL messages: [%d]", g_config.up_setting.imsi_enable);
+ LOGD("34. Show GPS Icon during Network Initiated Session: [%d]", g_config.agps_setting.e911_gps_icon_enable);
+ LOGD("35. LPPe Disable Crowd-Source Location: [%d]", g_config.agps_setting.lppe_network_location_disable);
+ LOGD("36. LPPe CP Enable: [%d]", g_config.cp_setting.cp_lppe_enable);
+ LOGD("37. LPPe UP Enable: [%d]", g_config.up_setting.up_lppe_enable);
+ LOGD("38. AOSP Profiling Enable: [%d]", g_config.up_setting.aosp_profile_enable);
+ LOGD("39. Use NLP Settings to Supl: [%d]", g_config.up_setting.bind_nlp_setting_to_supl);
+ LOGD("40. LBS Log Enable: [%d]", g_config.agps_setting.lbs_log_enable);
+ LOGD("41. Ingore SI for E911: [%d]", g_config.agps_setting.ignore_si_for_e911);
+ LOGD("42. LPPe CP Wlan Enable: [%d]", g_config.cp_setting.cp_lppe_wlan_enable);
+ LOGD("43. LPPe CP SRN Enable: [%d]", g_config.cp_setting.cp_lppe_srn_enable);
+ LOGD("44. LPPe CP Sensor Enable: [%d]", g_config.cp_setting.cp_lppe_sensor_enable);
+ LOGD("45. LPPe CP DBH Enable: [%d]", g_config.cp_setting.cp_lppe_dbh_enable);
+ LOGD("46. LPPe UP Wlan Enable: [%d]", g_config.up_setting.up_lppe_wlan_enable);
+ LOGD("47. LPPe UP SRN Enable: [%d]", g_config.up_setting.up_lppe_srn_enable);
+ LOGD("48. LPPe UP Sensor Enable: [%d]", g_config.up_setting.up_lppe_sensor_enable);
+ LOGD("49. LPPe UP DBH Enable: [%d]", g_config.up_setting.up_lppe_dbh_enable);
+ LOGD("50. UP LPP in 2G/3G Disable: [%d]", g_config.up_setting.up_lppe_in_2g3g_disable);
+ LOGD("51. UP RRLP in 4G Disable: [%d]", g_config.up_setting.up_rrlp_in_4g_disable);
+ LOGD("52. UP SI Disable: [%d]", g_config.up_setting.up_si_disable);
+ LOGD("53. LPPe Default NLP Location Enable: [%d]", g_config.agps_setting.lppe_def_nlp_enable);
+ LOGD("54. Force OTDOA Assist Enable: [%d]", g_config.up_setting.force_otdoa_assist_req);
+ LOGD("55. AOSP Position Mode Enable: [%d]", g_config.up_setting.aosp_pos_mode_enable);
+ LOGD("56. Privacy Override Enable: [%d]", g_config.up_setting.privacy_override_mode);
+ LOGD("57. Allow Ni For GPS OFF Enable: [%d]", g_config.up_setting.allow_ni_for_gps_off);
+ LOGD("58. IP Version Prefer: [%s]", get_ip_version_prefer());
+ LOGD("59. TCP Keep Alive Settings: [%d]", g_config.up_setting.tcp_keepalive);
+ LOGD("60. LPPe Crowd Source Confident: [%d]", g_config.agps_setting.lppe_crowd_source_confident);
+ LOGD("61. SIB8 SIB16 Enable: [%d]", g_config.gnss_setting.sib8_sib16_enable);
+ LOGD("62. A-GLONASS Enable: [%d]", g_config.gnss_setting.a_glonass_satellite_enable);
+ LOGD("63. A-Beidou Enable: [%d]", g_config.gnss_setting.a_beidou_satellite_enable);
+ LOGD("64. A-Galileo Enable: [%d]", g_config.gnss_setting.a_galileo_satellite_enable);
+ LOGD(" ");
+ LOGD(" ");
+ LOGD("100. MOLR PosMethod: [%s]", get_molr_pos_method());
+ LOGD("101. Set CP External Address: [%s] [%s]", get_enabled_status(g_config.cp_setting.external_addr_enable), g_config.cp_setting.external_addr);
+ LOGD("102. Set CP MLC number: [%s] [%s]", get_enabled_status(g_config.cp_setting.mlc_number_enable), g_config.cp_setting.mlc_number);
+ LOGD("103. Set CP EPC MOLR PDU Enable: [%d]", g_config.cp_setting.epc_molr_lpp_payload_enable);
+ LOGD(" ");
+ LOGD("999. Reset To Default");
+
+ LOGD("input: ");
+ ui_agps_settings_type input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case UI_AGPS_SETTINGS_TYPE_BACK:
+ traversal_path_back(&g_traversal);
+ break;
+ case UI_AGPS_SETTINGS_TYPE_GET_AGPS_SETTINGS:
+ ui_agps_settings_read();
+ break;
+ case UI_AGPS_SETTINGS_TYPE_SET_AGPS_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_AGPS_PROTOCOL:
+ case UI_AGPS_SETTINGS_TYPE_SET_CDMA_PREFERENCE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_PREFER_METHOD:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_MSA_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_MSB_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_ECID_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_AUTONOMOUS_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_AFLT_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_LPP_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_SUPL_VERSION:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_TLS_VERSION:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_CA_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_UDP_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_UT2:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_UT3:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_SUPL_VER_MINOR:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_SUPL_VER_SER_IND:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_PROFILE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_PERIODIC_SETTINGS:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_AREA_SETTINGS:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_SI_QOP_SETTINGS:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_ALLOW_NI_REQUEST:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_ALLOW_ROAMING:
+ case UI_AGPS_SETTINGS_TYPE_SET_CP_AUTO_RESET:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_SUPL_LOG_TO_FILE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_SENSITIVE_LOG:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_CERT_FROM_SDCARD:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_AUTO_PROFILE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_DEDICATE_APN:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_SYNC_TO_SLP:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_IMSI_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_E911_GPS_ICON:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_LPPE_NETWORK_LOCATION_DISABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_CP_LPPE_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_UP_LPPE_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_AOSP_PROFILE_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_BIND_NLP_SETTING_TO_SUPL:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_LBS_LOG_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_INGORE_SI_FOR_E911:
+ case UI_AGPS_SETTINGS_TYPE_SET_LPPE_CP_WLAN:
+ case UI_AGPS_SETTINGS_TYPE_SET_LPPE_CP_SRN:
+ case UI_AGPS_SETTINGS_TYPE_SET_LPPE_CP_SENSOR:
+ case UI_AGPS_SETTINGS_TYPE_SET_LPPE_CP_DBH:
+ case UI_AGPS_SETTINGS_TYPE_SET_LPPE_UP_WLAN:
+ case UI_AGPS_SETTINGS_TYPE_SET_LPPE_UP_SRN:
+ case UI_AGPS_SETTINGS_TYPE_SET_LPPE_UP_SENSOR:
+ case UI_AGPS_SETTINGS_TYPE_SET_LPPE_UP_DBH:
+ case UI_AGPS_SETTINGS_TYPE_SET_UP_LPP_IN_2G_3G_DISABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_UP_RRLP_IN_4G_DISABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_UP_SI_DISABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_LPPE_DEFAULT_NLP_LOCATION_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_FORCE_OTDOA_ASSIST_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_AOSP_POSITION_MODE_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_PRIVACY_OVERRIDE_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_ALLOW_NI_FOR_GPS_OFF_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_IP_VERSION_PREFER:
+ case UI_AGPS_SETTINGS_TYPE_SET_SUPL_TCP_KEEPALIVE:
+ case UI_AGPS_SETTINGS_TYPE_SET_LPPE_CROWD_SOURCE_CONFIDENT:
+ case UI_AGPS_SETTINGS_TYPE_SET_GNSS_SIB8_SIB16_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_GNSS_A_GLONASS_SATELLITE_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_GNSS_A_BEIDOU_SATELLITE_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_GNSS_A_GALILEO_SATELLITE_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_CP_MOLR_POS_METHOD:
+ case UI_AGPS_SETTINGS_TYPE_SET_CP_EXTERNAL_ADDR_ENABLE:
+ case UI_AGPS_SETTINGS_TYPE_SET_CP_MLC_NUMBER:
+ case UI_AGPS_SETTINGS_TYPE_SET_CP_EPC_MOLR_LPP_PAYLOAD_ENABLE:
+ traversal_path_go(&g_traversal, input);
+ break;
+ case UI_AGPS_SETTINGS_TYPE_RESET_TO_DEFAULT:
+ LOGD("Reset To Default");
+ set_reset_to_default();
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_agps_enable() {
+ LOGD("=== Set AGPS Enable ====");
+ LOGD("Current value: [%d]", g_config.agps_setting.agps_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Set AGPS Enable");
+ LOGD("2. Set AGPS Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Set AGPS Enable");
+ set_agps_enabled(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Set AGPS Disable");
+ set_agps_enabled(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_agps_protocol() {
+ LOGD("=== UP/CP switching (SI only) ====");
+ LOGD("Current Value: [%s]", get_agps_protocol());
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Set AGPS Protocol to User Plane");
+ LOGD("2. Set AGPS Protocol to Control Plane");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Set AGPS Protocol to User Plane");
+ set_protocol(AGPS_INTF_AGPS_PROTOCOL_UP);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Set AGPS Protocol to Control Plane");
+ set_protocol(AGPS_INTF_AGPS_PROTOCOL_CP);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_cdma_preference() {
+ LOGD("=== CDMA Settings ====");
+ LOGD("Current Value: [%s]", get_cdma_preferred());
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Set WCDMA Prefer");
+ LOGD("2. Set CDMA Force");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Set WCDMA Prefer");
+ set_cdma_pref(AGPS_INTF_CDMA_PREFERRED_WCDMA);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Set CDMA Force");
+ set_cdma_pref(AGPS_INTF_CDMA_PREFERRED_CDMA_FORCE);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_prefer_method() {
+ LOGD("=== Set SUPL Prefer Settings ====");
+ LOGD("Current Value: [%s]", get_pref_method());
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Set MSA Prefer");
+ LOGD("2. Set MSB Prefer");
+ LOGD("3. Set NO Prefer");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Set MSA Prefer");
+ set_up_pref_method(AGPS_INTF_PREF_METHOD_MSA);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Set MSB Prefer");
+ set_up_pref_method(AGPS_INTF_PREF_METHOD_MSB);
+ traversal_path_back(&g_traversal);
+ break;
+ case 3:
+ LOGD("Set NO Prefer");
+ set_up_pref_method(AGPS_INTF_PREF_METHOD_NO_PREF);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_pos_tech_msa_enable() {
+ LOGD("=== UP Pos Technology MSA Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.msa_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. UP Pos Technology MSA Enable");
+ LOGD("2. UP Pos Technology MSA Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("UP Pos Technology MSA Enable");
+ set_pos_technology_msa(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("UP Pos Technology MSA Disable");
+ set_pos_technology_msa(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_pos_tech_msb_enable() {
+ LOGD("=== UP Pos Technology MSB Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.msb_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. UP Pos Technology MSB Enable");
+ LOGD("2. UP Pos Technology MSB Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("UP Pos Technology MSB Enable");
+ set_pos_technology_msb(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("UP Pos Technology MSB Disable");
+ set_pos_technology_msb(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_pos_tech_ecid_enable() {
+ LOGD("=== UP Pos Technology ECID Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.ecid_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. UP Pos Technology ECID Enable");
+ LOGD("2. UP Pos Technology ECID Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("UP Pos Technology ECID Enable");
+ set_pos_technology_ecid(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("UP Pos Technology ECID Disable");
+ set_pos_technology_ecid(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_pos_tech_autonomous_enable() {
+ LOGD("=== UP Pos Technology AUTONOMOUS Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.autonomous_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. UP Pos Technology AUTONOMOUS Enable");
+ LOGD("2. UP Pos Technology AUTONOMOUS Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("UP Pos Technology AUTONOMOUS Enable");
+ set_pos_technology_autonomous(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("UP Pos Technology AUTONOMOUS Disable");
+ set_pos_technology_autonomous(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_pos_tech_aflt_enable() {
+ LOGD("=== UP Pos Technology AFLT Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.aflt_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. UP Pos Technology AFLT Enable");
+ LOGD("2. UP Pos Technology AFLT Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("UP Pos Technology AFLT Enable");
+ set_pos_technology_aflt(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("UP Pos Technology AFLT Disable");
+ set_pos_technology_aflt(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_lpp_enable() {
+ LOGD("=== UP Pos Protocol LPP Settings ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.lpp_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. UP Pos Protocol LPP Enable");
+ LOGD("2. UP Pos Protocol LPP Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("UP Pos Protocol LPP Enable");
+ set_lpp_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("UP Pos Protocol LPP Disable");
+ set_lpp_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_version() {
+ LOGD("=== SUPL Version ====");
+ LOGD("Current Value: [%s]", get_supl_version());
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. SUPL Version 1.0");
+ LOGD("2. SUPL Version 2.0");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("SUPL Version 1.0");
+ set_supl_version(AGPS_INTF_SUPL_VERSION_1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("SUPL Version 2.0");
+ set_supl_version(AGPS_INTF_SUPL_VERSION_2);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_tls_version() {
+ LOGD("=== TLS Version ====");
+ LOGD("Current Value: [%s]", get_tls_version());
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. TLS Version - TLS 1.0");
+ LOGD("2. TLS Version - TLS 1.1");
+ LOGD("3. TLS Version - TLS 1.2");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("TLS Version - TLS 1.0");
+ set_supl_tls_version(0);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("TLS Version - TLS 1.1");
+ set_supl_tls_version(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 3:
+ LOGD("TLS Version - TLS 1.2");
+ set_supl_tls_version(2);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_profile() {
+ int ret;
+ char supl_host[128] = {0};
+ int supl_port = 0;
+ int supl_tls = 0;
+ LOGD("=== Set SUPL Profile ====");
+
+ LOGD("SUPL Host: ");
+ ret = scanf("%s", supl_host);
+ clear_stdin_buff();
+ if(ret <= 0) {
+ system("clear");
+ traversal_path_back(&g_traversal);
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ LOGD("SUPL Port: ");
+ ret = scanf("%d", &supl_port);
+ clear_stdin_buff();
+ if(ret <= 0) {
+ system("clear");
+ traversal_path_back(&g_traversal);
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ LOGD("SUPL TLS (0 is disable, otherwise is enable): ");
+ ret = scanf("%d", &supl_tls);
+ clear_stdin_buff();
+ if(ret <= 0) {
+ system("clear");
+ traversal_path_back(&g_traversal);
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ if(supl_tls) {
+ supl_tls = 1;
+ }
+
+ system("clear");
+ traversal_path_back(&g_traversal);
+ LOGD("SUPL Host=[%s]", supl_host);
+ LOGD("SUPL Port=[%d]", supl_port);
+ LOGD("SUPL TLS=[%d]", supl_tls);
+ LOGD("Set SUPL Profile");
+ set_supl_profile(supl_host, supl_port, supl_tls);
+}
+
+void ui_agps_settings_supl_periodic_settings() {
+ LOGD("=== PERIODIC SETTINGS ====");
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Start Periodic Session");
+ LOGD("2. Stop Periodic Session");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Start Periodic Session");
+ start_supl_2_periodic_session();
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Stop Periodic Session");
+ stop_supl_2_periodic_session();
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_area_settings() {
+ LOGD("=== AREA EVENT SETTINGS ====");
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Start Area Entering Event");
+ LOGD("2. Start Area Inside Event");
+ LOGD("3. Start Area Outside Event");
+ LOGD("4. Start Area Leaving Event");
+ LOGD("5. Stop Area Event");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Start Area Entering Event");
+ start_supl_2_area_event_session(agps_intf_area_event_type_entering);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Start Area Inside Event");
+ start_supl_2_area_event_session(agps_intf_area_event_type_inside);
+ traversal_path_back(&g_traversal);
+ break;
+ case 3:
+ LOGD("Start Area Outside Event");
+ start_supl_2_area_event_session(agps_intf_area_event_type_outside);
+ traversal_path_back(&g_traversal);
+ break;
+ case 4:
+ LOGD("Start Area Leaving Event");
+ start_supl_2_area_event_session(agps_intf_area_event_type_leaving);
+ traversal_path_back(&g_traversal);
+ break;
+ case 5:
+ LOGD("Stop Area Event");
+ stop_supl_2_area_event_session();
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+int calc_meter_from_k_value(int k) {
+ double meter;
+ if (k == 1)
+ return 1;
+ meter = (pow(1.1, k) - 1) *10;
+ return (int) ceil(meter);
+}
+
+int calc_k_value_from_meter(int meter) {
+ double k;
+ k = log((double) meter / 10 + 1) / log(1.1);
+ return (int) floor(k);
+ }
+
+void ui_agps_settings_supl_qop() {
+ int horizontal_acc = 0;
+ int vertical_acc = 0;
+ int location_age = 0;
+ int delay = 0;
+ LOGD("=== Set SUPL QOP ====");
+
+ LOGD("Current K-Value: Horizontal Accuracy:[%d] Vertical Accuracy:[%d] Location Age:[%d] Delay:[%d]",
+ g_config.up_setting.qop_hacc,
+ g_config.up_setting.qop_vacc,
+ g_config.up_setting.qop_loc_age,
+ g_config.up_setting.qop_delay);
+ LOGD("(Meter-Value: Horizontal Accuracy:[%d] Vertical Accuracy:[%d] Location Age:[%d] Delay:[%d])",
+ calc_meter_from_k_value(g_config.up_setting.qop_hacc),
+ calc_meter_from_k_value(g_config.up_setting.qop_vacc),
+ g_config.up_setting.qop_loc_age,
+ g_config.up_setting.qop_delay);
+
+ LOGD("Select input format (1: K-value 2: Meter): ");
+ int format = scanf_int(INVALID_VALUE, false);
+ if(format != 1 && format != 2) {
+ system("clear");
+ traversal_path_back(&g_traversal);
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ char* sFormat = NULL;
+ if (format == 1) {
+ sFormat = "K-value";
+ } else {
+ sFormat = "Meter";
+ }
+
+ LOGD("Horizontal Accuracy (%s): ", sFormat);
+ horizontal_acc = scanf_int(INVALID_VALUE, false);
+ if(horizontal_acc == INVALID_VALUE) {
+ system("clear");
+ traversal_path_back(&g_traversal);
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ LOGD("Vertical Accuracy (%s): ", sFormat);
+ vertical_acc = scanf_int(INVALID_VALUE, false);
+ if(vertical_acc == INVALID_VALUE) {
+ system("clear");
+ traversal_path_back(&g_traversal);
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ LOGD("Location Age: ");
+ location_age = scanf_int(INVALID_VALUE, false);
+ if(location_age == INVALID_VALUE) {
+ system("clear");
+ traversal_path_back(&g_traversal);
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ LOGD("Delay: ");
+ delay = scanf_int(INVALID_VALUE, false);
+ if(delay == INVALID_VALUE) {
+ system("clear");
+ traversal_path_back(&g_traversal);
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ system("clear");
+ traversal_path_back(&g_traversal);
+ LOGD("Horizontal Accuracy (%s)=[%d]", sFormat, horizontal_acc);
+ LOGD("Vertical Accuracy (%s)=[%d]", sFormat, vertical_acc);
+ LOGD("Location Age=[%d]", location_age);
+ LOGD("Delay=[%d]", delay);
+ LOGD("Set SUPL QOP");
+ if (format == 2) {
+ horizontal_acc = calc_k_value_from_meter(horizontal_acc);
+ vertical_acc = calc_k_value_from_meter(vertical_acc);
+ }
+ set_qop(horizontal_acc, vertical_acc, location_age, delay);
+}
+
+void ui_agps_settings_supl_ca_enable() {
+ LOGD("=== Certification Verification Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.ca_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Certification Verification Enable");
+ LOGD("2. Certification Verification Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Certification Verification Enable");
+ set_cert_verify(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Certification Verification Disable");
+ set_cert_verify(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_udp_enable() {
+ LOGD("=== UDP Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.udp_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. UDP Enable");
+ LOGD("2. UDP Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("UDP Enable");
+ set_udp_enable_v2(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("UDP Disable");
+ set_udp_enable_v2(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_ut2() {
+ LOGD("=== Change SUPL UT2 Timer ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.ut2);
+ LOGD("input integer: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ LOGD("Change SUPL UT2 Timer=[%d]", input);
+ traversal_path_back(&g_traversal);
+ set_supl_ut2(input);
+}
+
+void ui_agps_settings_supl_ut3() {
+ LOGD("=== Change SUPL UT3 Timer ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.ut3);
+ LOGD("input integer: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ LOGD("Change SUPL UT3 Timer=[%d]", input);
+ traversal_path_back(&g_traversal);
+ set_supl_ut3(input);
+}
+
+void ui_agps_settings_supl_ver_minor() {
+ LOGD("=== Change SUPL VER MINOR ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.supl_ver_minor);
+ LOGD("input integer: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ LOGD("Change SUPL VER MINOR=[%d]", input);
+ traversal_path_back(&g_traversal);
+ set_supl_ver_minor(input);
+}
+
+void ui_agps_settings_supl_ver_ser_ind() {
+ LOGD("=== Change SUPL SERIND ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.supl_ver_ser_ind);
+ LOGD("input integer: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ LOGD("Change SUPL VER SERIND=[%d]", input);
+ traversal_path_back(&g_traversal);
+ set_supl_ver_ser_ind(input);
+}
+
+void ui_agps_settings_supl_ni_request() {
+ LOGD("=== Allow Network Initiated Request ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.ni_request);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Allow Network Initiated Request Enable");
+ LOGD("2. Allow Network Initiated Request Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Allow Network Initiated Request Enable");
+ set_allow_ni(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Allow Network Initiated Request Disable");
+ set_allow_ni(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_allow_roaming() {
+ LOGD("=== Allow Roaming ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.roaming);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Allow Roaming Enable");
+ LOGD("2. Allow Roaming Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Allow Roaming Enable");
+ set_allow_roaming(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Allow Roaming Disable");
+ set_allow_roaming(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_cp_molr_pos_method() {
+ LOGD("=== CP MOLR PosMethod ====");
+ LOGD("Current Value: [%s]", get_molr_pos_method());
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Set Location Estimate");
+ LOGD("2. Set Assistance Data");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Set Location Estimate");
+ set_molr_pos_methd(AGPS_INTF_MOLR_POS_METHOD_LOC_EST);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Set Assistance Data");
+ set_molr_pos_methd(AGPS_INTF_MOLR_POS_METHOD_ASSIST_DATA);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_cp_external_addr_enable() {
+ LOGD("=== External Addr ====");
+ LOGD("Current Value: [%s] [%s]", get_enabled_status(g_config.cp_setting.external_addr_enable), g_config.cp_setting.external_addr);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. External Addr Enable");
+ LOGD("2. External Addr Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, false);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ {
+ char external_addr[128] = {0};
+ LOGD("External Addr: ");
+ int ret = scanf("%s", external_addr);
+ clear_stdin_buff();
+ if(ret <= 0) {
+ system("clear");
+ traversal_path_back(&g_traversal);
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ set_external_addr(1,external_addr);
+ traversal_path_back(&g_traversal);
+ }
+ break;
+ case 2:
+ LOGD("External Addr Disable");
+ set_external_addr(0, g_config.cp_setting.external_addr);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_cp_mlc_number() {
+ LOGD("=== MLC Number ====");
+ LOGD("Current Value: [%s] [%s]", get_enabled_status(g_config.cp_setting.mlc_number_enable), g_config.cp_setting.mlc_number);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. MLC Number Enable");
+ LOGD("2. MLC Number Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, false);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ {
+ char mlc_number[128] = {0};
+ LOGD("MLC Number: ");
+ int ret = scanf("%s", mlc_number);
+ clear_stdin_buff();
+ if(ret <= 0) {
+ system("clear");
+ traversal_path_back(&g_traversal);
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ set_mlc_number(1,mlc_number);
+ traversal_path_back(&g_traversal);
+ }
+ break;
+ case 2:
+ LOGD("MLC Number Disable");
+ set_mlc_number(0, g_config.cp_setting.mlc_number);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_cp_auto_reset_enable() {
+ LOGD("=== CP Auto Reset ====");
+ LOGD("Current Value: [%d]", g_config.cp_setting.cp_auto_reset);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. CP Auto Reset Enable");
+ LOGD("2. CP Auto Reset Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("CP Auto Reset Enable");
+ set_cp_auto_reset(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("CP Auto Reset Disable");
+ set_cp_auto_reset(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_epc_molr_pdu_enable() {
+ LOGD("=== EPC MOLR PDU Enable ====");
+ LOGD("Current Value: [%d]", g_config.cp_setting.epc_molr_lpp_payload_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. EPC MOLR PDU Enable");
+ LOGD("2. EPC MOLR PDU Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("EPC MOLR PDU Enable");
+ set_epc_molr_pdu_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("EPC MOLR PDU Disable");
+ set_epc_molr_pdu_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_log_to_file() {
+ LOGD("=== Log SUPL To File ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.supl_log);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Log SUPL To File Enable");
+ LOGD("2. Log SUPL To File Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Log SUPL To File Enable");
+ set_supl_to_file(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Log SUPL To File Disable");
+ set_supl_to_file(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_sensitive_log() {
+ LOGD("=== Log Sensitive Data ====");
+ LOGD("Current Value: [%d]", !g_config.up_setting.no_sensitive_log);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Log Sensitive Data Enable");
+ LOGD("2. Log Sensitive Data Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Log Sensitive Data Enable");
+ set_no_sensitive_log(0);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Log Sensitive Data Disable");
+ set_no_sensitive_log(1);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+void ui_agps_settings_supl_cert_from_sdcard() {
+ LOGD("=== Allow AGPS Certificates for Lab Test ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.cert_from_sdcard);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Allow AGPS Certificates for Lab Test Enable");
+ LOGD("2. Allow AGPS Certificates for Lab Test Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Allow AGPS Certificates for Lab Test Enable");
+ set_cert_from_sdcard(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Allow AGPS Certificates for Lab Test Disable");
+ set_cert_from_sdcard(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_auto_profile() {
+ LOGD("=== Allow Auto Configuring SUPL Profile Base on Current Plmn ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.auto_profile_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Allow Auto Configuring SUPL Profile Base on Current Plmn Enable");
+ LOGD("2. Allow Auto Configuring SUPL Profile Base on Current Plmn Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Allow Auto Configuring SUPL Profile Base on Current Plmn Enable");
+ set_auto_profile_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Allow Auto Configuring SUPL Profile Base on Current Plmn Disable");
+ set_auto_profile_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_dedicate_apn() {
+ LOGD("=== Set SUPL Dedicate APN ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.apn_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Allow SUPL Dedicate APN Enable");
+ LOGD("2. Allow SUPL Dedicate APN Didable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Allow SUPL Dedicate APN Enable");
+ set_supl_apn_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Allow SUPL Dedicate APN Disable");
+ set_supl_apn_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_sync_to_slp() {
+ LOGD("=== Sync AGPS Settings to SLPD ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.sync_to_slp);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Sync AGPS Settings to SLPD Enable");
+ LOGD("2. Sync AGPS Settings to SLPD Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Sync AGPS Settings to SLPD Enable");
+ set_sync_to_slp_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Sync AGPS Settings to SLPD Disable");
+ set_sync_to_slp_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_imsi_enable() {
+ LOGD("=== Allow valid IMSI in SUPL message ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.imsi_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Allow valid IMSI in SUPL message Enable");
+ LOGD("2. Allow valid IMSI in SUPL message Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Allow valid IMSI in SUPL message Enable");
+ set_imsi_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Allow valid IMSI in SUPL message Disable");
+ set_imsi_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_e911_gps_icon() {
+ LOGD("=== Show GPS Icon during Network Initial Session ====");
+ LOGD("Current Value: [%d]", g_config.agps_setting.e911_gps_icon_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Show GPS Icon during Network Initial Session Enable");
+ LOGD("2. Show GPS Icon during Network Initial Session Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Show GPS Icon during Network Initial Session Enable");
+ set_e911_gps_icon_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Show GPS Icon during Network Initial Session Disable");
+ set_e911_gps_icon_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_lppe_nlp_disable() {
+ LOGD("=== Disable LPPe Crowd-Source Location ====");
+ LOGD("Current Value: [%d]", g_config.agps_setting.lppe_network_location_disable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Disable LPPe Crowd-Source Location");
+ LOGD("2. Enable LPPe Crowd-Source Location");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Disable LPPe Crowd-Source Location");
+ set_lppe_network_location_disable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Enable LPPe Crowd-Source Location");
+ set_lppe_network_location_disable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_cp_lppe_enable() {
+ LOGD("=== LPPe CP Enable ====");
+ LOGD("Current Value: [%d]", g_config.cp_setting.cp_lppe_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. LPPe CP Enable");
+ LOGD("2. LPPe CP Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("LPPe CP Enable");
+ set_lppe_cp_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("LPPe CP Disable");
+ set_lppe_cp_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_up_lppe_enable() {
+ LOGD("=== LPPe UP Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.up_lppe_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. LPPe UP Enable");
+ LOGD("2. LPPe UP Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("LPPe UP Enable");
+ set_lppe_up_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("LPPe UP Disable");
+ set_lppe_up_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_aosp_profile_enable() {
+ LOGD("=== AOSP Profiling Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.aosp_profile_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. AOSP Profiling Enable");
+ LOGD("2. AOSP Profiling Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("AOSP Profiling Enable");
+ set_aosp_profile_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("AOSP Profiling Disable");
+ set_aosp_profile_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_bind_nlp_settings_to_supl() {
+ LOGD("=== Use NLP Settings to Supl ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.bind_nlp_setting_to_supl);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Use NLP Settings to Supl Enable");
+ LOGD("2. Use NLP Settings to Supl Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Use NLP Settings to Supl Enable");
+ set_bind_nlp_setting_to_supl(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Use NLP Settings to Supl Disable");
+ set_bind_nlp_setting_to_supl(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_supl_lbs_log_enable() {
+ LOGD("=== LBS log Enable ====");
+ LOGD("Current Value: [%d]", g_config.agps_setting.lbs_log_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. LBS log Enable");
+ LOGD("2. LBS log Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("LBS log Enable");
+ set_lbs_log_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("LBS log Disable");
+ set_lbs_log_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_ignore_si_for_e911() {
+ LOGD("=== Ingore SI for E911 ====");
+ LOGD("Current Value: [%d]", g_config.agps_setting.ignore_si_for_e911);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Ingore SI for E911 Enable");
+ LOGD("2. Ingore SI for E911 Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Ingore SI for E911 Enable");
+ set_ingore_si_for_e911(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Ingore SI for E911 Disable");
+ set_ingore_si_for_e911(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_lppe_cp_wlan() {
+ LOGD("=== LPPe CP Wlan Enable ====");
+ LOGD("Current Value: [%d]", g_config.cp_setting.cp_lppe_wlan_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. LPPe CP Wlan Enable");
+ LOGD("2. LPPe CP Wlan Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("LPPe CP Wlan Enable");
+ set_lppe_cp_wlan_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("LPPe CP Wlan Disable");
+ set_lppe_cp_wlan_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_lppe_cp_srn() {
+ LOGD("=== LPPe CP SRN Enable ====");
+ LOGD("Current Value: [%d]", g_config.cp_setting.cp_lppe_srn_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. LPPe CP SRN Enable");
+ LOGD("2. LPPe CP SRN Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("LPPe CP SRN Enable");
+ set_lppe_cp_srn_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("LPPe CP SRN Disable");
+ set_lppe_cp_srn_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_lppe_cp_sensor() {
+ LOGD("=== LPPe CP Sensor Enable ====");
+ LOGD("Current Value: [%d]", g_config.cp_setting.cp_lppe_sensor_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. LPPe CP Sensor Enable");
+ LOGD("2. LPPe CP Sensor Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("LPPe CP Sensor Enable");
+ set_lppe_cp_sensor_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("LPPe CP Sensor Disable");
+ set_lppe_cp_sensor_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_lppe_cp_dbh() {
+ LOGD("=== LPPe CP DBH Enable ====");
+ LOGD("Current Value: [%d]", g_config.cp_setting.cp_lppe_dbh_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. LPPe CP DBH Enable");
+ LOGD("2. LPPe CP DBH Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("LPPe CP DBH Enable");
+ set_lppe_cp_dbh_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("LPPe CP DBH Disable");
+ set_lppe_cp_dbh_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_lppe_up_wlan() {
+ LOGD("=== LPPe UP Wlan Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.up_lppe_wlan_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. LPPe UP Wlan Enable");
+ LOGD("2. LPPe UP Wlan Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("LPPe UP Wlan Enable");
+ set_lppe_up_wlan_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("LPPe UP Wlan Disable");
+ set_lppe_up_wlan_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_lppe_up_srn() {
+ LOGD("=== LPPe UP SRN Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.up_lppe_srn_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. LPPe UP SRN Enable");
+ LOGD("2. LPPe UP SRN Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("LPPe UP SRN Enable");
+ set_lppe_up_srn_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("LPPe UP SRN Disable");
+ set_lppe_up_srn_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_lppe_up_sensor() {
+ LOGD("=== LPPe UP Sensor Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.up_lppe_sensor_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. LPPe UP Sensor Enable");
+ LOGD("2. LPPe UP Sensor Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("LPPe UP Sensor Enable");
+ set_lppe_up_sensor_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("LPPe UP Sensor Disable");
+ set_lppe_up_sensor_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+
+void ui_agps_settings_lppe_up_dbh() {
+ LOGD("=== LPPe UP DBH Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.up_lppe_dbh_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. LPPe UP DBH Enable");
+ LOGD("2. LPPe UP DBH Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("LPPe UP DBH Enable");
+ set_lppe_up_dbh_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("LPPe UP DBH Disable");
+ set_lppe_up_dbh_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_up_lppe_2g_3g_disable() {
+ LOGD("=== UP LPP in 2G/3G Disable ====");
+ LOGD("Current Value: [%s]", get_disabled_status(g_config.up_setting.up_lppe_in_2g3g_disable));
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. UP LPP in 2G/3G Disable");
+ LOGD("2. UP LPP in 2G/3G Enable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("UP LPP in 2G/3G Disable");
+ set_up_lpp_in_2g3g_disable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("UP LPP in 2G/3G Enable");
+ set_up_lpp_in_2g3g_disable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_up_rrlp_in_4g_disable() {
+ LOGD("=== UP RRLP in 4G Disable ====");
+ LOGD("Current Value: [%s]", get_disabled_status(g_config.up_setting.up_rrlp_in_4g_disable));
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. UP RRLP in 4G Disable");
+ LOGD("2. UP RRLP in 4G Enable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("UP RRLP in 4G Disable");
+ set_up_rrlp_in_4g_disable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("UP RRLP in 4G Enable");
+ set_up_rrlp_in_4g_disable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_up_si_disable() {
+ LOGD("=== UP SI Disable ====");
+ LOGD("Current Value: [%s]", get_disabled_status(g_config.up_setting.up_si_disable));
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. UP SI Disable");
+ LOGD("2. UP SI Enable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("UP SI Disable");
+ set_up_si_disable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("UP SI Enable");
+ set_up_si_disable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_lppe_default_nlp_location() {
+ LOGD("=== LPPe Default NLP Location Enable ====");
+ LOGD("Current Value: [%d]", g_config.agps_setting.lppe_def_nlp_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. LPPe Default NLP Location Enable");
+ LOGD("2. LPPe Default NLP Location Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("LPPe Default NLP Location Enable");
+ set_lppe_def_nlp_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("LPPe Default NLP Location Disable");
+ set_lppe_def_nlp_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_force_otdoa_assist() {
+ LOGD("=== Force OTDOA Assist Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.force_otdoa_assist_req);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Force OTDOA Assist Enable");
+ LOGD("2. Force OTDOA Assist Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Force OTDOA Assist Enable");
+ set_force_otdoa_assist_req(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Force OTDOA Assist Disable");
+ set_force_otdoa_assist_req(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_up_aosp_pos_mode() {
+ LOGD("=== AOSP Position Mode Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.aosp_pos_mode_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. AOSP Position Mode Enable");
+ LOGD("2. AOSP Position Mode Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("AOSP Position Mode Enable");
+ set_up_aosp_pos_mode_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("AOSP Position Mode Disable");
+ set_up_aosp_pos_mode_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_privacy_override() {
+ LOGD("=== Privacy Override Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.privacy_override_mode);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Privacy Override Enable");
+ LOGD("2. Privacy Override Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Privacy Override Enable");
+ set_privacy_override_mode(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Privacy Override Disable");
+ set_privacy_override_mode(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_allow_ni_for_gps_off() {
+ LOGD("=== Allow Ni For GPS OFF Enable ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.allow_ni_for_gps_off);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Allow Ni For GPS OFF Enable");
+ LOGD("2. Allow Ni For GPS OFF Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("Allow Ni For GPS OFF Enable");
+ set_allow_ni_for_gps_off(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("Allow Ni For GPS OFF Disable");
+ set_allow_ni_for_gps_off(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_ip_version_prefer() {
+ LOGD("=== IP Version Prefer ====");
+ LOGD("Current Value: [%s]", get_ip_version_prefer());
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. IP V6");
+ LOGD("2. IP V4");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("IP V6");
+ set_ip_version_prefer(AGPS_INTF_SUPL_IP_VERSION_IPV6);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("IP V4");
+ set_ip_version_prefer(AGPS_INTF_SUPL_IP_VERSION_IPV4);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+
+
+void ui_agps_settings_supl_tcp_keepalive() {
+ LOGD("=== TCP Keep Alive ====");
+ LOGD("Current Value: [%d]", g_config.up_setting.tcp_keepalive);
+ LOGD("input integer: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ LOGD("TCP Keep Alive=[%d]", input);
+ traversal_path_back(&g_traversal);
+ set_tcp_keep_alive(input);
+}
+
+void ui_agps_settings_lppe_crowd_source_confident() {
+ LOGD("=== LPPe Crowd Source Confident ====");
+ LOGD("Current Value: [%d]", g_config.agps_setting.lppe_crowd_source_confident);
+ LOGD("input integer: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ LOGD("LPPe Crowd Source Confident=[%d]", input);
+ traversal_path_back(&g_traversal);
+ set_lppe_crowd_source_confident(input);
+}
+
+
+void ui_agps_settings_gnss_sib8_sib16_enable() {
+ LOGD("=== SIB8/SIB16 Enable ====");
+ LOGD("Current Value: [%d]", g_config.gnss_setting.sib8_sib16_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. SIB8/SIB16 Enable");
+ LOGD("2. SIB8/SIB16 Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("SIB8/SIB16 Enable");
+ set_sib8_16_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("SIB8/SIB16 Disable");
+ set_sib8_16_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_gnss_a_glonass_enable() {
+ LOGD("=== A-GLONASS Enable ====");
+ LOGD("Current Value: [%d]", g_config.gnss_setting.a_glonass_satellite_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. A-GLONASS Enable");
+ LOGD("2. A-GLONASS Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("A-GLONASS Enable");
+ set_a_glonass_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("A-GLONASS Disable");
+ set_a_glonass_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_gnss_a_beidou_enable() {
+ LOGD("=== A-Beidou Enable ====");
+ LOGD("Current Value: [%d]", g_config.gnss_setting.a_beidou_satellite_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. A-Beidou Enable");
+ LOGD("2. A-Beidou Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("A-Beidou Enable");
+ set_a_beidou_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("A-Beidou Disable");
+ set_a_beidou_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_agps_settings_gnss_a_galileo_enable() {
+ LOGD("=== A-Galileo Enable ====");
+ LOGD("Current Value: [%d]", g_config.gnss_setting.a_galileo_satellite_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. A-Galileo Enable");
+ LOGD("2. A-Galileo Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("A-Galileo Enable");
+ set_a_galileo_enable(1);
+ traversal_path_back(&g_traversal);
+ break;
+ case 2:
+ LOGD("A-Galileo Disable");
+ set_a_galileo_enable(0);
+ traversal_path_back(&g_traversal);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_debug_settings() {
+ LOGD("=== Debug Settings ====");
+ LOGD(" AGPS Debug Interface: [%d]", g_agps_debug_enable);
+ LOGD(" GPS Information: [%d]", g_gps_info_enable);
+ LOGD(" NMEA Information: [%d]", g_nmea_enable);
+ LOGD(" GNSS AT Command Information: [%d]", g_at_cmd_enable);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. AGPS Debug Interface Enable");
+ LOGD("2. AGPS Debug Interface Disable");
+ LOGD("3. GPS Information Enable");
+ LOGD("4. GPS Information Disable");
+ LOGD("5. NMEA Information Enable");
+ LOGD("6. NMEA Information Disable");
+ LOGD("7. GNSS AT Command Information Enable");
+ LOGD("8. GNSS AT Command Information Disable");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ LOGD("AGPS Debug Interface Enable");
+ g_agps_debug_enable = 1;
+ break;
+ case 2:
+ LOGD("AGPS Debug Interface Disable");
+ g_agps_debug_enable = 0;
+ break;
+ case 3:
+ LOGD("GPS Information Enable");
+ g_gps_info_enable = 1;
+ break;
+ case 4:
+ LOGD("GPS Information Disable");
+ g_gps_info_enable = 0;
+ break;
+ case 5:
+ LOGD("NMEA Information Enable");
+ g_nmea_enable = 1;
+ break;
+ case 6:
+ LOGD("NMEA Information Disable");
+ g_nmea_enable = 0;
+ break;
+ case 7:
+ LOGD("GNSS AT Command Information Enable");
+ g_at_cmd_enable = 1;
+ break;
+ case 8:
+ LOGD("GNSS AT Command Information Disable");
+ g_at_cmd_enable = 0;
+ break;
+ //TODO test only
+ case 11:
+ // phased out
+ //mnl2hal_mnld_reboot();
+ break;
+ case 12: {
+ gps_location location;
+ memset(&location, 0, sizeof(location));
+ location.flags = 0xffff;
+ location.lat = 1.1;
+ location.lng = 2.2;
+ location.alt = 3.3;
+ location.speed = 4.4;
+ location.bearing = 5.5;
+ location.h_accuracy = 6.6;
+ location.timestamp = 1234567890123456L;
+ mnldinf_location_hdlr(location);
+ break;
+ }
+ case 13:
+ mnldinf_nmea_hdlr(10000, "$GPGSV,2,1,08,01,40,083,46,02,17,308,41,12,07,344,39,14,22,228,45*75", 250);
+ mnldinf_nmea_hdlr(10001, "$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A", 251);
+ mnldinf_nmea_hdlr(10002, "$GPGLL,4916.45,N,12311.12,W,225444,A,*1D", 252);
+ mnldinf_nmea_hdlr(10003, "$GPVTG,054.7,T,034.4,M,005.5,N,010.2,K*48", 253);
+ msleep2(500);
+ break;
+ case 14: {
+ gnss_sv_info sv;
+ memset(&sv, 0, sizeof(sv));
+ sv.num_svs = 3;
+
+ sv.sv_list[0].svid = 1;
+ sv.sv_list[0].constellation = 11;
+ sv.sv_list[0].c_n0_dbhz = 31;
+ sv.sv_list[0].elevation = 1.1;
+ sv.sv_list[0].azimuth = 1.11;
+ sv.sv_list[0].flags = 11;
+
+ sv.sv_list[1].svid = 2;
+ sv.sv_list[1].constellation = 22;
+ sv.sv_list[1].c_n0_dbhz = 32;
+ sv.sv_list[1].elevation = 2.2;
+ sv.sv_list[1].azimuth = 2.22;
+ sv.sv_list[1].flags = 22;
+
+ sv.sv_list[2].svid = 3;
+ sv.sv_list[2].constellation = 33;
+ sv.sv_list[2].c_n0_dbhz = 33;
+ sv.sv_list[2].elevation = 3.3;
+ sv.sv_list[2].azimuth = 3.33;
+ sv.sv_list[2].flags = 33;
+
+ mnldinf_gnss_sv_hdlr(sv);
+ break;
+ }
+ case 15:
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_debug_1() {
+ int emulator_mode = get_emulator_mode();
+ LOGD("=== Debug 1 , emulator_mode=[%d] ====", emulator_mode);
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. Reset AGPSD");
+ LOGD("2. Test Button");
+ LOGD("3. Emulator Mode ON");
+ LOGD("4. Emulator Mode OFF");
+ LOGD("5. Start Test Case");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case UI_DEBUG_1_TYPE_BACK:
+ traversal_path_back(&g_traversal);
+ break;
+ case UI_DEBUG_1_TYPE_RESET_AGPSD:
+ LOGD("Reset AGPSD");
+ do_reset_agpsd();
+ msleep2(1000); // give the time for system to re-start AGPSD
+ break;
+ case UI_DEBUG_1_TYPE_TEST_BUTTON:
+ traversal_path_go(&g_traversal, input);
+ break;
+ case UI_DEBUG_1_TYPE_EMULATOR_MODE_ON:
+ LOGD("Emulator Mode ON");
+ start_emualator_mode(1);
+ msleep2(1000); // give the time for system to re-start AGPSD
+ break;
+ case UI_DEBUG_1_TYPE_EMULATOR_MODE_OFF:
+ LOGD("Emulator Mode OFF");
+ start_emualator_mode(0);
+ msleep2(1000); // give the time for system to re-start AGPSD
+ break;
+ case UI_DEBUG_1_TYPE_START_TEST_CASE:
+ traversal_path_go(&g_traversal, input);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_debug_1_test_case() {
+ LOGD("=== Test Case ====");
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1: All TC Loop 1");
+ LOGD("2: All TC Loop 2");
+ LOGD("3: All TC Loop 1000");
+ LOGD("4: All Common TC");
+ LOGD("5: All UP TC");
+ LOGD("6: All CP TC");
+ LOGD("7: All EVDO TC");
+ LOGD("8: Partial TC 1");
+ LOGD("9: Partial TC 2");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case 0:
+ traversal_path_back(&g_traversal);
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ start_test_case(input - 1);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void ui_debug_1_test_button() {
+ LOGD("=== Test Button ====");
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1: agps_open_gps_req");
+ LOGD("2: agps_close_gps_req");
+ LOGD("3: agps_reset_gps_req");
+ LOGD("4: ni_notify1 notify");
+ LOGD("5: ni_notify1 verify");
+ LOGD("6: ni_notify2 notify");
+ LOGD("7: ni_notify2 verify");
+ LOGD("8: data_conn_req");
+ LOGD("9: data_conn_release");
+ LOGD("10: md_sim_info_req");
+ LOGD("11: md_data_conn_state_req");
+ LOGD("12: lppe_capability");
+ LOGD("13: lppe_start_meas");
+ LOGD("14: lppe_stop_meas");
+ LOGD("15: lppe_query_meas");
+ LOGD("16: agps_md_huge_data");
+ LOGD("17: agps_open_gps_rejected");
+ LOGD("18: ni_notify3 notify");
+ LOGD("19: Test 19");
+ LOGD("20: Test 20");
+ LOGD("21: Test 21");
+ LOGD("22: Test 22");
+ LOGD("23: Test 23");
+ LOGD("24: Test 24");
+ LOGD("25: Test 25");
+ LOGD("26: 500 lppe meas stress test");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ if (input == 0) {
+ traversal_path_back(&g_traversal);
+ } else if (input >0 && input <= 25) {
+ start_test_button(input - 1);
+ } else if (input == 26) {
+ LOGE("Stress test for 500 lppe meas requests");
+ int i =0;
+ for (i = 0; i< 500; i++) {
+ start_test_button(13 - 1); // start meas
+ msleep2(5500);
+ start_test_button(14 - 1); // stop meas
+ msleep2(500);
+ start_test_button(15 - 1); // query meas
+ }
+ } else {
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void at_geofence_add_circle_request() {
+ mtk_geo_add_circle c;
+ memset(&c, 0, sizeof(c));
+ LOGD("Geofence Add Circle Request: Alert Type (1=Enter 2=Exit) input:");
+ c.alert_type = scanf_int(INVALID_VALUE, false);
+ if(c.alert_type == INVALID_VALUE) {
+ LOGE("ERR: read invalid alert_type");
+ return;
+ }
+ LOGD("Geofence Add Circle Request: Initial State (0=Unkown 1=Entered 2=Exited) input:");
+ c.initial_state = scanf_int(INVALID_VALUE, false);
+ if(c.initial_state == INVALID_VALUE) {
+ LOGE("ERR: read invalid initial_state");
+ return;
+ }
+ LOGD("Geofence Add Circle Request: Latitude (xx.xxxxxx in degrees, WGS84 coordinate system) input:");
+ c.lat = scanf_double(0, false);
+ if(c.lat == 0) {
+ LOGE("ERR: read invalid lat");
+ return;
+ }
+ LOGD("Geofence Add Circle Request: Longitude (xx.xxxxxx in degrees, WGS84 coordinate system) input:");
+ c.lng = scanf_double(0, false);
+ if(c.lng == 0) {
+ LOGE("ERR: read invalid lng");
+ return;
+ }
+ LOGD("Geofence Add Circle Request: Radius (in meter) input:");
+ c.radius = scanf_double(0, false);
+ if(c.radius == 0) {
+ LOGE("ERR: read invalid radius");
+ return;
+ }
+ LOGD("Geofence Add Circle Request: Unknown Timer (in millisecond) input:");
+ c.unknowntimerms = scanf_int(INVALID_VALUE, false);
+ if(c.unknowntimerms == INVALID_VALUE) {
+ LOGE("ERR: read invalid unknowntimerms");
+ return;
+ }
+
+ system("clear");
+ mtk_at_send_geo_add_circle_request(g_gnssadp_fd, &c);
+ LOGD("Geofence Add Circle Request alert=[%d] initial=[%d] lat=[%.6f] lng=[%.6f] radius=[%.2f] unknowntimerms=[%d] Sent",
+ c.alert_type, c.initial_state, c.lat, c.lng, c.radius, c.unknowntimerms);
+}
+void ui_gnss_at_settings() {
+ LOGD("=== GNSS AT Command ====");
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1: GNSS Start Request");
+ LOGD("2: GNSS Start Request With Wake Lock Release");
+ LOGD("3: GNSS Stop Request");
+ LOGD("4: Host Reboot Notify");
+ LOGD("5: GNSS Status Request");
+ LOGD("6: GNSS Enable Set");
+ LOGD("7: NI Enable Set");
+ LOGD("8: AGPS Mode Set");
+ LOGD("9: SUPL Version Set");
+ LOGD("10: SUPL Address Set");
+ LOGD("11: Delete Aiding Data Request");
+ LOGD("12: NI Notify Response");
+ LOGD("13: Reference Location Response");
+ LOGD("14: Reference Time Response");
+ LOGD("15: NMEA Config Set");
+ LOGD("16: Loopback Request");
+ LOGD(" ");
+ LOGD("31: Geofence Max Number Request");
+ LOGD("32: Geofence Add Circle Request");
+ LOGD("33: Geofence Add Circle Request With Wake Lock Release");
+ LOGD("34: Geofence Delete Request");
+ LOGD("35: Geofence Delete All Request");
+ LOGD(" ");
+ LOGD("51: Certificate Inject");
+ LOGD("52: Certificate Name List Request");
+ LOGD("53: Certificate Delete");
+ LOGD("54: Certificate Delete All");
+ LOGD(" ");
+ LOGD("99: Input a GNSS AT Command manually");
+
+ LOGD("input: ");
+ int input = scanf_int(INVALID_VALUE, false);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ switch(input) {
+ case UI_AT_SETTINGS_TYPE_BACK: {
+ system("clear");
+ traversal_path_back(&g_traversal);
+ break;
+ }
+ case UI_AT_SETTINGS_GNSS_START_REQUEST: {
+ system("clear");
+ mtk_at_send_gnss_start_request(g_gnssadp_fd);
+ LOGD("GNSS Start Request Sent");
+ break;
+ }
+ case UI_AT_SETTINGS_GNSS_START_WITH_WAKE_LOCK_RELEASE: {
+ system("clear");
+ mtk_at_send_gnss_start_request(g_gnssadp_fd);
+ LOGD("GNSS Start Request Sent with wake lock release");
+ //delay to do wake_unlock to ensure the msg can be deliveried to other process
+ timer_start(g_wake_unlock_timer, LBS_EM_WAKE_LOCK_TIMEOUT);
+ break;
+ }
+ case UI_AT_SETTINGS_GNSS_STOP_REQUEST: {
+ system("clear");
+ mtk_at_send_gnss_stop_request(g_gnssadp_fd);
+ LOGD("GNSS Stop Request Sent");
+ lbs_em_acquire_wake_lock_mutex();
+ break;
+ }
+ case UI_AT_SETTINGS_HOST_REBOOT_NOTIFY: {
+ system("clear");
+ mtk_at_send_gnss_host_reset_notify(g_gnssadp_fd);
+ LOGD("Host Reboot Notify Sent");
+ break;
+ }
+ case UI_AT_SETTINGS_GNSS_STATUS_REQUEST: {
+ system("clear");
+ mtk_at_send_gnss_status_request(g_gnssadp_fd);
+ LOGD("GNSS Status Request Sent");
+ break;
+ }
+ case UI_AT_SETTINGS_GNSS_ENABLE_SET: {
+ LOGD("GNSS Enable Set (0=disable, 1=enable) input:");
+ int value = scanf_int(INVALID_VALUE, false);
+ if(value == INVALID_VALUE) {
+ LOGE("ERR: read invalid value");
+ return;
+ }
+
+ system("clear");
+ mtk_at_send_gnss_enable_set(g_gnssadp_fd, value);
+ LOGD("GNSS Enable Set [%d] Sent", value);
+ break;
+ }
+ case UI_AT_SETTINGS_NI_ENABLE_SET: {
+ LOGD("NI Enable Set (0=disable, 1=enable) input:");
+ int value = scanf_int(INVALID_VALUE, false);
+ if(value == INVALID_VALUE) {
+ LOGE("ERR: read invalid value");
+ return;
+ }
+
+ system("clear");
+ mtk_at_send_gnss_ni_enable_set(g_gnssadp_fd, value);
+ LOGD("NI Enable Set [%d] Sent", value);
+ break;
+ }
+ case UI_AT_SETTINGS_AGPS_MODE_SET: {
+ int ret = 0;
+ mtk_gnss_agps_mode mode;
+ memset(&mode, 0, sizeof(mode));
+ LOGD("AGPS Mode Set: MSA (0=disable, 1=enable, others=ignore) input:");
+ ret = scanf_int(INVALID_VALUE, false);
+ if(ret == INVALID_VALUE) {
+ LOGE("ERR: read invalid msa");
+ return;
+ }
+ if(ret == 0 || ret == 1) {
+ mode.msa_valid = true;
+ mode.msa = ret;
+ }
+
+ LOGD("AGPS Mode Set: MSB (0=disable, 1=enable, others=ignore) input:");
+ ret = scanf_int(INVALID_VALUE, false);
+ if(ret == INVALID_VALUE) {
+ LOGE("ERR: read invalid msb");
+ return;
+ }
+ if(ret == 0 || ret == 1) {
+ mode.msb_valid = true;
+ mode.msb = ret;
+ }
+
+ LOGD("AGPS Mode Set: MSS (0=disable, 1=enable, others=ignore) input:");
+ ret = scanf_int(INVALID_VALUE, false);
+ if(ret == INVALID_VALUE) {
+ LOGE("ERR: read invalid mss");
+ return;
+ }
+ if(ret == 0 || ret == 1) {
+ mode.mss_valid = true;
+ mode.mss = ret;
+ }
+
+ LOGD("AGPS Mode Set: CID (0=disable, 1=enable, others=ignore) input:");
+ ret = scanf_int(INVALID_VALUE, false);
+ if(ret == INVALID_VALUE) {
+ LOGE("ERR: read invalid cid");
+ return;
+ }
+ if(ret == 0 || ret == 1) {
+ mode.cid_valid = true;
+ mode.cid = ret;
+ }
+
+ LOGD("AGPS Mode Set: AFLT (0=disable, 1=enable, others=ignore) input:");
+ ret = scanf_int(INVALID_VALUE, false);
+ if(ret == INVALID_VALUE) {
+ LOGE("ERR: read invalid aflt");
+ return;
+ }
+ if(ret == 0 || ret == 1) {
+ mode.aflt_valid = true;
+ mode.aflt = ret;
+ }
+
+ LOGD("AGPS Mode Set: OTDOA (0=disable, 1=enable, others=ignore) input:");
+ ret = scanf_int(INVALID_VALUE, false);
+ if(ret == INVALID_VALUE) {
+ LOGE("ERR: read invalid otdoa");
+ return;
+ }
+ if(ret == 0 || ret == 1) {
+ mode.otdoa_valid = true;
+ mode.otdoa = ret;
+ }
+
+ LOGD("AGPS Mode Set: supl_pref_method (0=MSA, 1=MSB, 2=NO Preference, others=ignore) input:");
+ ret = scanf_int(INVALID_VALUE, false);
+ if(ret == INVALID_VALUE) {
+ LOGE("ERR: read invalid supl_pref_method");
+ return;
+ }
+ if(ret == 0 || ret == 1 || ret == 2) {
+ mode.supl_pref_method_valid = true;
+ mode.supl_pref_method = ret;
+ }
+
+ LOGD("SUPL Enable/Disable (0=disable, 1=enable, others=ignore) input:");
+ ret = scanf_int(INVALID_VALUE, false);
+ if(ret == INVALID_VALUE) {
+ LOGE("ERR: read invalid supl");
+ return;
+ }
+ if(ret == 0 || ret == 1) {
+ mode.supl_valid = true;
+ mode.supl = ret;
+ }
+
+ LOGD("EPO Enable/Disable (0=disable, 1=enable, others=ignore) input:");
+ ret = scanf_int(INVALID_VALUE, false);
+ if(ret == INVALID_VALUE) {
+ LOGE("ERR: read invalid epo");
+ return;
+ }
+ if(ret == 0 || ret == 1) {
+ mode.epo_valid = true;
+ mode.epo = ret;
+ }
+
+ system("clear");
+ mtk_at_send_gnss_agps_mode_set(g_gnssadp_fd, &mode);
+ LOGD("AGPS Mode Set msa=[%d] msb=[%d] mss=[%d] cid=[%d] aflt=[%d] otdoa=[%d] supl_pref_method=[%d] Sent",
+ mode.msa, mode.msb, mode.mss, mode.cid, mode.aflt, mode.otdoa, mode.supl_pref_method);
+ break;
+ }
+ case UI_AT_SETTINGS_SUPL_VERSION_SET: {
+ LOGD("SUPL Version Set: Major Version input:");
+ int maj = scanf_int(INVALID_VALUE, false);
+ if(maj == INVALID_VALUE) {
+ LOGE("ERR: read invalid maj");
+ return;
+ }
+ LOGD("SUPL Version Set: Minor Version input:");
+ int min = scanf_int(INVALID_VALUE, false);
+ if(min == INVALID_VALUE) {
+ LOGE("ERR: read invalid min");
+ return;
+ }
+ LOGD("SUPL Version Set: Service Indicator Version input:");
+ int ser_ind = scanf_int(INVALID_VALUE, false);
+ if(min == INVALID_VALUE) {
+ LOGE("ERR: read invalid ser_ind");
+ return;
+ }
+
+ system("clear");
+ mtk_at_send_gnss_supl_version_set(g_gnssadp_fd, maj, min, ser_ind);
+ LOGD("SUPL Version Set maj=[%d] min=[%d] ser_ind=[%d] Sent", maj, min, ser_ind);
+ break;
+ }
+ case UI_AT_SETTINGS_SUPL_ADDRESS_SET: {
+ LOGD("SUPL Address Set: SUPL Address (FQDN/IPv4/IPv6) input:");
+ char addr[128] = {0};
+ int ret = scanf("%[^\n]", addr); //get a whole line
+ clear_stdin_buff();
+ if(ret <= 0) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+ LOGD("SUPL Address Set: Port (ex: 7275) input:");
+ int port = scanf_int(INVALID_VALUE, false);
+ if(port == INVALID_VALUE) {
+ LOGE("ERR: read invalid port");
+ return;
+ }
+ LOGD("SUPL Address Set: TLS enable (0=disable, 1=enable) input:");
+ int tls_enable = scanf_int(INVALID_VALUE, false);
+ if(tls_enable == INVALID_VALUE) {
+ LOGE("ERR: read invalid tls_enable");
+ return;
+ }
+
+ system("clear");
+ mtk_at_send_gnss_supl_addr_set(g_gnssadp_fd, addr, port, tls_enable);
+ LOGD("SUPL Address Set addr=[%s] port=[%d] tls_enable=[%d] Sent", addr, port, tls_enable);
+ break;
+ }
+ case UI_AT_SETTINGS_DELETE_AIDING_DATA_REQUEST: {
+ mtk_gnss_aiding_data flags;
+ memset(&flags, 0, sizeof(flags));
+
+ LOGD("Delete Aiding Data Request: All (0=no, 1=yes) input:");
+ int input = scanf_int(INVALID_VALUE, false);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid flags.all");
+ return;
+ } else {
+ flags.all = (input == 1);
+ }
+
+ if(!flags.all) {
+ LOGD("Delete Aiding Data Request: EPH (0=no, 1=yes) input:");
+ input = scanf_int(INVALID_VALUE, false);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid flags.eph");
+ return;
+ } else {
+ flags.eph = (input == 1);
+ }
+ LOGD("Delete Aiding Data Request: ALM (0=no, 1=yes) input:");
+ input = scanf_int(INVALID_VALUE, false);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid flags.alm");
+ return;
+ } else {
+ flags.alm = (input == 1);
+ }
+ LOGD("Delete Aiding Data Request: Position (0=no, 1=yes) input:");
+ input = scanf_int(INVALID_VALUE, false);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid flags.pos");
+ return;
+ } else {
+ flags.pos = (input == 1);
+ }
+ LOGD("Delete Aiding Data Request: Time (0=no, 1=yes) input:");
+ input = scanf_int(INVALID_VALUE, false);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid flags.time");
+ return;
+ } else {
+ flags.time = (input == 1);
+ }
+ LOGD("Delete Aiding Data Request: IONO (0=no, 1=yes) input:");
+ input = scanf_int(INVALID_VALUE, false);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid flags.iono");
+ return;
+ } else {
+ flags.iono = (input == 1);
+ }
+ LOGD("Delete Aiding Data Request: UTC (0=no, 1=yes) input:");
+ input = scanf_int(INVALID_VALUE, false);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid flags.utc");
+ return;
+ } else {
+ flags.utc = (input == 1);
+ }
+ LOGD("Delete Aiding Data Request: SVDIR (0=no, 1=yes) input:");
+ input = scanf_int(INVALID_VALUE, false);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid flags.svdir");
+ return;
+ } else {
+ flags.svdir = (input == 1);
+ }
+ LOGD("Delete Aiding Data Request: RTI (0=no, 1=yes) input:");
+ input = scanf_int(INVALID_VALUE, false);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid flags.rti");
+ return;
+ } else {
+ flags.rti = (input == 1);
+ }
+ LOGD("Delete Aiding Data Request: CellID (0=no, 1=yes) input:");
+ input = scanf_int(INVALID_VALUE, false);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid flags.celldb");
+ return;
+ } else {
+ flags.celldb = (input == 1);
+ }
+
+ }
+
+ system("clear");
+ mtk_at_send_gnss_delete_aiding_data_request(g_gnssadp_fd, &flags);
+ LOGD("Delete Aiding Data Request all=[%d] eph=[%d] alm=[%d] pos=[%d] time=[%d] iono=[%d] utc=[%d] svdir=[%d] rti=[%d] celldb=[%d] Sent",
+ flags.all, flags.eph, flags.alm, flags.pos, flags.time, flags.iono, flags.utc, flags.svdir, flags.rti, flags.celldb);
+ break;
+ }
+ case UI_AT_SETTINGS_NI_NOTIFY_RESPONSE: {
+ LOGD("NI Notify Response: Response Type (1=Accept, 2=Deny, 3=NO Response) input:");
+ int resp_type = scanf_int(INVALID_VALUE, false);
+ if(resp_type == INVALID_VALUE) {
+ LOGE("ERR: read invalid resp_type");
+ return;
+ }
+
+ system("clear");
+ mtk_at_send_gnss_ni_notify_response(g_gnssadp_fd, g_notify_id, resp_type);
+ LOGD("NI Notify Response id=[%d] resp_type=[%d] Sent", g_notify_id, resp_type);
+ break;
+ }
+ case UI_AT_SETTINGS_REFERENCE_LOCATION_RESPONSE: {
+ LOGD("Reference Location Response: Age (seconds) input:");
+ int age = scanf_int(INVALID_VALUE, false);
+ if(age == INVALID_VALUE) {
+ LOGE("ERR: read invalid age");
+ return;
+ }
+ LOGD("Reference Location Response: Latitude (xx.xxxxxx in degrees, WGS84 coordinate system) input:");
+ double lat = scanf_double(0, false);
+ if(lat == 0) {
+ LOGE("ERR: read invalid lat");
+ return;
+ }
+ LOGD("Reference Location Response: Longitude (xx.xxxxxx in degrees, WGS84 coordinate system) input:");
+ double lng = scanf_double(0, false);
+ if(lng == 0) {
+ LOGE("ERR: read invalid lng");
+ return;
+ }
+ LOGD("Reference Location Response: Accuracy (horizontal position accuracy, radial, in meters, 68%% confidence) input:");
+ float acc = scanf_double(0, false);
+ if(acc == 0) {
+ LOGE("ERR: read invalid acc");
+ return;
+ }
+
+ system("clear");
+ mtk_at_send_gnss_ref_location_response(g_gnssadp_fd, age, lat, lng, acc);
+ LOGD("Reference Location Response age=[%d] lat=[%.6f] lng=[%.6f] acc=[%.2f] Sent", age, lat, lng, acc);
+ break;
+ }
+ case UI_AT_SETTINGS_REFERENCE_TIME_RESPONSE: {
+ LOGD("Reference Time Response: Time (Milliseconds since January 1, 1970) input:");
+ long long time = scanf_long(INVALID_VALUE, false);
+ if(time == INVALID_VALUE) {
+ LOGE("ERR: read invalid time");
+ return;
+ }
+ LOGD("Reference Time Response: Uncertainty (milliseconds) input:");
+ int uncertainty = scanf_int(INVALID_VALUE, false);
+ if(uncertainty == INVALID_VALUE) {
+ LOGE("ERR: read invalid uncertainty");
+ return;
+ }
+
+ system("clear");
+ mtk_at_send_gnss_ref_time_response(g_gnssadp_fd, time, uncertainty);
+ LOGD("Reference Time Response time=[%lld] uncertainty=[%d] Sent", time, uncertainty);
+ break;
+ }
+ case UI_AT_SETTINGS_NMEA_CONFIG_SET: {
+ LOGD("NMEA Config Set (0=disable, 1=enable) input:");
+ int value = scanf_int(INVALID_VALUE, false);
+ if(value == INVALID_VALUE) {
+ LOGE("ERR: read invalid value");
+ return;
+ }
+
+ system("clear");
+ mtk_at_send_gnss_nmea_config_set(g_gnssadp_fd, value);
+ LOGD("NMEA Config Set [%d] Sent", value);
+ break;
+ }
+ case UI_AT_SETTINGS_LOOPBACK_REQUEST: {
+ LOGD("Loopback Request: Test Message input:");
+ char msg[128] = {0};
+ int ret = scanf("%[^\n]", msg); //get a whole line
+ clear_stdin_buff();
+ if(ret <= 0) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ system("clear");
+ mtk_at_send_gnss_loopback_request(g_gnssadp_fd, msg);
+ LOGD("Loopback Request [%s] Sent", msg);
+ break;
+ }
+ case UI_AT_SETTINGS_GEOFENCE_MAX_NUMBER_REQUEST: {
+ system("clear");
+ mtk_at_send_geo_max_num_request(g_gnssadp_fd);
+ LOGD("Geofence Max Number Request Sent");
+ break;
+ }
+ case UI_AT_SETTINGS_GEOFENCE_ADD_CIRCLE_REQUEST: {
+ g_at_geofence_add_with_wake_lock_release = false;
+ at_geofence_add_circle_request();
+ break;
+ }
+ case UI_AT_SETTINGS_GEOFENCE_ADD_CIRCLE_WITH_WAKE_LOCK_RELEASE: {
+ g_at_geofence_add_with_wake_lock_release = true;
+ at_geofence_add_circle_request();
+ break;
+ }
+ case UI_AT_SETTINGS_GEOFENCE_DELETE_REQUEST: {
+ LOGD("Geofence Delete Request: id (integer) input:");
+ int id = scanf_int(INVALID_VALUE, false);
+ if(id == INVALID_VALUE) {
+ LOGE("ERR: read invalid id");
+ return;
+ }
+
+ system("clear");
+ mtk_at_send_geo_delete_request(g_gnssadp_fd, id);
+ LOGD("Geofence Delete Request id=[%d] Sent", id);
+
+ geofence_list_remove(&g_geo_list,id);
+ if (g_geo_list.num == 0) {
+ LOGD("Geofence all elements are removed, acquire wake lock");
+ g_at_geofence_add_with_wake_lock_release = false;
+ lbs_em_acquire_wake_lock_mutex();
+ }
+
+ break;
+ }
+ case UI_AT_SETTINGS_GEOFENCE_DELETE_ALL_REQUEST: {
+ system("clear");
+ mtk_at_send_geo_delete_all_request(g_gnssadp_fd);
+ LOGD("Geofence Delete All Request is sent, acquire wake lock");
+ g_at_geofence_add_with_wake_lock_release = false;
+ lbs_em_acquire_wake_lock_mutex();
+ break;
+ }
+ case UI_AT_SETTINGS_CERTIFICATE_INJECT: {
+ system("clear");
+ cert_inject_procedure();
+ break;
+ }
+ case UI_AT_SETTINGS_CERTIFICATE_NAME_LIST_REQUEST: {
+ system("clear");
+ mtk_at_send_gnss_cert_name_request(g_gnssadp_fd);
+ LOGD("Certificate Name List Request Sent");
+ break;
+ }
+ case UI_AT_SETTINGS_CERTIFICATE_DELETE: {
+ LOGD("Certificate Delete: file name:");
+ char name[128] = {0};
+ int ret = scanf("%[^\n]", name); //get a whole line
+ clear_stdin_buff();
+ if(ret <= 0) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ system("clear");
+ mtk_at_send_gnss_cert_delete_request(g_gnssadp_fd, name);
+ LOGD("Certificate Delete Sent name=[%s]", name);
+ break;
+ }
+ case UI_AT_SETTINGS_CERTIFICATE_DELETE_ALL: {
+ system("clear");
+ mtk_at_send_gnss_cert_delete_all_request(g_gnssadp_fd);
+ LOGD("Certificate Delete All Sent");
+ break;
+ }
+ case 99: {
+ char buff[1024] = {0};
+ LOGD("Input a GNSS AT Command manually input:");
+ int ret = scanf("%[^\n]", buff); //get a whole line
+ clear_stdin_buff();
+ if(ret <= 0) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ //append \r\n to the string
+ int i = 0;
+ while(buff[i] != 0) {
+ i++;
+ }
+ buff[i] = '\r';
+ buff[i + 1] = '\n';
+
+ system("clear");
+ ret = write(g_gnssadp_fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ }
+ LOGD("GNSS AT Command Sent: %s", buff);
+ break;
+ }
+ default: {
+ system("clear");
+ LOGE("ERR: read unhandled value=[%d]", input);
+ break;
+ }
+ }
+}
+
+bool mtk_nlp_send_start_request(int fd) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_cert_delete_all_request(buff, sizeof(buff));
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+void ui_nlp_test() {
+ LOGD("=== NLP Test ====");
+ LOGD("0. Back");
+ LOGD(" ");
+ LOGD("1. NLP Start Request");
+ LOGD("2. NLP Stop Request");
+ LOGD("3. Get Last Location");
+ LOGD("4. Single Location Request");
+
+ LOGD("input: ");
+ ui_gps_control_type input = scanf_int(INVALID_VALUE, true);
+ if(input == INVALID_VALUE) {
+ LOGE("ERR: read invalid input");
+ return;
+ }
+
+ switch(input) {
+ case UI_NLP_TEST_TYPE_BACK:
+ traversal_path_back(&g_traversal);
+ break;
+ case UI_NLP_TEST_TYPE_START_RQUEST:
+ LOGD("NLP start request");
+ MtkNlp_start_location_updates(&g_nlpservice_fd, 1000);
+ break;
+ case UI_NLP_TEST_TYPE_STOP_RQUEST:
+ LOGD("NLP stop request");
+ MtkNlp_stop_location_updates(&g_nlpservice_fd);
+ break;
+ case UI_NLP_TEST_TYPE_GET_LAST_LOC:
+ LOGD("Get last location");
+ MtkNlp_get_last_location(&g_nlpservice_fd);
+ break;
+ case UI_NLP_TEST_TYPE_GET_SINGLE_UPDATE:
+ LOGD("Get single location update");
+ MtkNlp_get_single_update(&g_nlpservice_fd);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]", input);
+ return;
+ }
+}
+
+void mtk_lbs_em_tree_construction(tree_node* header) {
+ tree_node* n = NULL; // for manipulate
+
+ tree_init(header, ui_main);
+
+ n = header;
+ n = tree_add_child(n, UI_MAIN_TYPE_GPS_CONTROL, ui_gps_control);
+ tree_add_child(n, UI_GPS_CONTROL_TYPE_GPS_DELETE_AIDING_DATA, ui_gps_control_delete_aiding_data);
+ n = n->parent;
+ n = tree_add_child(n, UI_MAIN_TYPE_AGPS_SETTINGS, ui_agps_settings);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_AGPS_ENABLE, ui_agps_settings_agps_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_AGPS_PROTOCOL, ui_agps_settings_agps_protocol);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_CDMA_PREFERENCE, ui_agps_settings_cdma_preference);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_PREFER_METHOD, ui_agps_settings_supl_prefer_method);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_MSA_ENABLE, ui_agps_settings_supl_pos_tech_msa_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_MSB_ENABLE, ui_agps_settings_supl_pos_tech_msb_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_ECID_ENABLE, ui_agps_settings_supl_pos_tech_ecid_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_AUTONOMOUS_ENABLE, ui_agps_settings_supl_pos_tech_autonomous_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_POS_TECT_AFLT_ENABLE, ui_agps_settings_supl_pos_tech_aflt_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_LPP_ENABLE, ui_agps_settings_supl_lpp_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_SUPL_VERSION, ui_agps_settings_supl_version);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_TLS_VERSION, ui_agps_settings_supl_tls_version);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_CA_ENABLE, ui_agps_settings_supl_ca_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_UDP_ENABLE, ui_agps_settings_supl_udp_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_UT2, ui_agps_settings_supl_ut2);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_UT3, ui_agps_settings_supl_ut3);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_SUPL_VER_MINOR, ui_agps_settings_supl_ver_minor);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_SUPL_VER_SER_IND, ui_agps_settings_supl_ver_ser_ind);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_PROFILE, ui_agps_settings_supl_profile);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_PERIODIC_SETTINGS, ui_agps_settings_supl_periodic_settings);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_AREA_SETTINGS, ui_agps_settings_supl_area_settings);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_SI_QOP_SETTINGS, ui_agps_settings_supl_qop);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_ALLOW_NI_REQUEST, ui_agps_settings_supl_ni_request);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_ALLOW_ROAMING, ui_agps_settings_supl_allow_roaming);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_CP_AUTO_RESET, ui_agps_settings_cp_auto_reset_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_SUPL_LOG_TO_FILE, ui_agps_settings_supl_log_to_file);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_SENSITIVE_LOG, ui_agps_settings_supl_sensitive_log);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_CERT_FROM_SDCARD, ui_agps_settings_supl_cert_from_sdcard);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_AUTO_PROFILE, ui_agps_settings_supl_auto_profile);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_DEDICATE_APN, ui_agps_settings_supl_dedicate_apn);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_SYNC_TO_SLP, ui_agps_settings_supl_sync_to_slp);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_IMSI_ENABLE, ui_agps_settings_supl_imsi_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_E911_GPS_ICON, ui_agps_settings_supl_e911_gps_icon);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_LPPE_NETWORK_LOCATION_DISABLE, ui_agps_settings_supl_lppe_nlp_disable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_CP_LPPE_ENABLE, ui_agps_settings_cp_lppe_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_UP_LPPE_ENABLE, ui_agps_settings_supl_up_lppe_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_AOSP_PROFILE_ENABLE, ui_agps_settings_supl_aosp_profile_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_BIND_NLP_SETTING_TO_SUPL, ui_agps_settings_supl_bind_nlp_settings_to_supl);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_LBS_LOG_ENABLE, ui_agps_settings_supl_lbs_log_enable);
+
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_INGORE_SI_FOR_E911, ui_agps_settings_ignore_si_for_e911);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_LPPE_CP_WLAN, ui_agps_settings_lppe_cp_wlan);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_LPPE_CP_SRN, ui_agps_settings_lppe_cp_srn);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_LPPE_CP_SENSOR, ui_agps_settings_lppe_cp_sensor);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_LPPE_CP_DBH, ui_agps_settings_lppe_cp_dbh);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_LPPE_UP_WLAN, ui_agps_settings_lppe_up_wlan);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_LPPE_UP_SRN, ui_agps_settings_lppe_up_srn);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_LPPE_UP_SENSOR, ui_agps_settings_lppe_up_sensor);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_LPPE_UP_DBH, ui_agps_settings_lppe_up_dbh);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_UP_LPP_IN_2G_3G_DISABLE, ui_agps_settings_up_lppe_2g_3g_disable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_UP_RRLP_IN_4G_DISABLE, ui_agps_settings_up_rrlp_in_4g_disable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_UP_SI_DISABLE, ui_agps_settings_up_si_disable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_LPPE_DEFAULT_NLP_LOCATION_ENABLE, ui_agps_settings_lppe_default_nlp_location);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_FORCE_OTDOA_ASSIST_ENABLE, ui_agps_settings_force_otdoa_assist);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_AOSP_POSITION_MODE_ENABLE, ui_agps_settings_up_aosp_pos_mode);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_PRIVACY_OVERRIDE_ENABLE, ui_agps_settings_privacy_override);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_ALLOW_NI_FOR_GPS_OFF_ENABLE, ui_agps_settings_allow_ni_for_gps_off);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_IP_VERSION_PREFER, ui_agps_settings_ip_version_prefer);
+
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_SUPL_TCP_KEEPALIVE, ui_agps_settings_supl_tcp_keepalive);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_LPPE_CROWD_SOURCE_CONFIDENT, ui_agps_settings_lppe_crowd_source_confident);
+
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_GNSS_SIB8_SIB16_ENABLE, ui_agps_settings_gnss_sib8_sib16_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_GNSS_A_GLONASS_SATELLITE_ENABLE, ui_agps_settings_gnss_a_glonass_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_GNSS_A_BEIDOU_SATELLITE_ENABLE, ui_agps_settings_gnss_a_beidou_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_GNSS_A_GALILEO_SATELLITE_ENABLE, ui_agps_settings_gnss_a_galileo_enable);
+
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_CP_MOLR_POS_METHOD, ui_agps_settings_cp_molr_pos_method);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_CP_EXTERNAL_ADDR_ENABLE, ui_agps_settings_cp_external_addr_enable);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_CP_MLC_NUMBER, ui_agps_settings_cp_mlc_number);
+ tree_add_child(n, UI_AGPS_SETTINGS_TYPE_SET_CP_EPC_MOLR_LPP_PAYLOAD_ENABLE, ui_agps_settings_epc_molr_pdu_enable);
+
+ n = n->parent;
+ n = tree_add_child(n, UI_MAIN_TYPE_DEBUG_SETTINGS, ui_debug_settings);
+ n = n->parent;
+ n = tree_add_child(n, UI_MAIN_TYPE_DEBUG_1, ui_debug_1);
+ tree_add_child(n, UI_DEBUG_1_TYPE_START_TEST_CASE, ui_debug_1_test_case);
+ tree_add_child(n, UI_DEBUG_1_TYPE_TEST_BUTTON, ui_debug_1_test_button);
+ n = n->parent;
+ n = tree_add_child(n, UI_MAIN_TYPE_GNSS_AT_SETTINGS, ui_gnss_at_settings);
+ n = n->parent;
+ n = tree_add_child(n, UI_MAIN_TYPE_NLP_TEST, ui_nlp_test);
+ n = n->parent;
+}
+
+int mtk_lbs_em_start() {
+
+ traversal_path_init(&g_traversal);
+
+ mtk_lbs_em_tree_construction(&g_tree_root);
+
+ //TODO need to remove
+ //traversal_path_go(&g_traversal, UI_MAIN_TYPE_GNSS_AT_SETTINGS);
+
+ system("clear");
+ while(1) {
+ int ret = tree_traversal(&g_tree_root, &g_traversal);
+ if(ret) {
+ LOGE("ERR: tree_traversal() line=[%d]", __LINE__);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+// ------------- AGPS Debug Interface handlers -----------------
+
+void toast_message (const char* msg) {
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ LOGD("\E[1;32;40m");
+ LOGD("%s [AGPS Debug][Toast] msg=[%s]", time_buff, msg);
+ LOGD("\E[0m");
+}
+
+void view_message (int color, const char* msg) {
+ if(g_agps_debug_enable) {
+ int is_red = (color == 0xffff0000)? 1 : 0;
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ if(is_red) {
+ LOGD("\E[1;31;40m");
+ }
+ LOGD("%s [AGPS Debug][Info] color=[%x] msg=[%s]", time_buff, color, msg);
+ if(is_red) {
+ LOGD("\E[0m");
+ }
+ }
+}
+
+void dialog_message (const char* title, const char* msg) {
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ LOGD("\E[1;33;40m");
+ LOGD("%s [AGPS Debug][Dialog] title=[%s] msg=[%s]", time_buff, title, msg);
+ LOGD("\E[0m");
+}
+
+agps_debug_interface g_agps_debug_interface = {
+ toast_message,
+ view_message,
+ dialog_message,
+};
+
+static void agps_debug_message_hdlr(int epfd) {
+ int ret = agps_debug_interface_msg_handler(g_agps_debug_fd, &g_agps_debug_interface);
+ if(ret) {
+ LOGE("ERR: agps_message_thread() re-connect AGPS Debug Interface");
+ while(1) {
+ if(g_agps_debug_fd >= 0) {
+ close(g_agps_debug_fd);
+ }
+ msleep2(1000);
+ g_agps_debug_fd = agps_debug_interface_get_fd();
+ if(g_agps_debug_fd >= 0) {
+ epoll_add_fd3(epfd, g_agps_debug_fd);
+ break;
+ } else {
+ LOGE("ERR: agps_message_thread() re-connect fail, retry it in next second");
+ }
+ }
+ }
+}
+
+static void mtk_lbs_em_close_fd(int fd) {
+ close(fd);
+ if(g_epfd != -1 && fd == g_epfd) {
+ g_epfd = -1;
+ LOGW("epfd is closed");
+ } else if(g_mnld_basic_fd != -1 && fd == g_mnld_basic_fd) {
+ g_mnld_basic_fd = -1;
+ LOGW("MNL Basic Interface is closed");
+ } else if(g_mnld_ext_fd != -1 && fd == g_mnld_ext_fd) {
+ g_mnld_ext_fd = -1;
+ LOGW("MNL Ext Interface is closed");
+ } else if(g_nlpservice_fd.fd != -1 && fd == g_nlpservice_fd.fd) {
+ g_nlpservice_fd.fd = -1;
+ LOGW("NLP Service Interface is closed");
+ } else {
+ LOGE("unexpected fd=[%d] to be close", fd);
+ }
+}
+
+static void mtk_lbs_em_timer_retry_port_routine(int id) {
+ char cmd = LBS_EM_INT_CMD_RETRY_CONNECT;
+ int fd = socket_udp_client_create_local(true, LBSEM_INTERNAL_SOCKET);
+ if(fd == -1) {
+ LOGE("open() failed, reason=[%s]%d", strerror(errno), errno);
+ return;
+ }
+
+ int ret = write(fd, &cmd, sizeof(cmd));
+ if(ret == -1) {
+ LOGE("write() failed id=[%d], reason=[%s]%d", LBS_EM_INT_CMD_RETRY_CONNECT, strerror(errno), errno);
+ }
+ close(fd);
+}
+
+static void mtk_lbs_em_timer_retry_connect_hdlr() {
+ g_connect_retry_count++;
+ LOGW("try times=(%d/%d)", g_connect_retry_count, LBS_EM_MAX_RETRY_CONNECT_TIMES);
+
+ bool all_success = true;
+
+ if(g_mnld_basic_fd < 0) {
+ g_mnld_basic_fd = mnldinf_basic_register("LBS EM");
+ if(g_mnld_basic_fd < 0) {
+ all_success = false;
+ } else {
+ LOGW("mnldinf_basic_register() success fd=[%d]", g_mnld_basic_fd);
+ epoll_add_fd3(g_epfd, g_mnld_basic_fd);
+ mnldinf_basic_client_cap cap;
+ cap.support_gnss = true;
+ mnldinf_basic_capability_config(g_mnld_basic_fd, &cap);
+ }
+ }
+
+ if(g_mnld_ext_fd < 0) {
+ g_mnld_ext_fd = mnldinf_ext_register("LBS EM");
+ if(g_mnld_ext_fd < 0) {
+ all_success = false;
+ } else {
+ LOGW("mnldinf_ext_register() success fd=[%d]", g_mnld_basic_fd);
+ epoll_add_fd3(g_epfd, g_mnld_ext_fd);
+ mnldinf_ext_client_cap cap;
+ cap.support_gnss = true;
+ mnldinf_ext_capability_config(g_mnld_ext_fd, &cap);
+ }
+ }
+
+ if(g_nlpservice_fd.fd < 0) {
+ g_nlpservice_fd.fd = MtkNlp_get_fd();
+ if(g_nlpservice_fd.fd < 0) {
+ all_success = false;
+ } else {
+ LOGW("MtkNlp_get_fd() success fd=[%d]", g_nlpservice_fd.fd);
+ epoll_add_fd3(g_epfd, g_nlpservice_fd.fd);
+ }
+ }
+
+ if(all_success) {
+ LOGW("all scuess");
+ g_connect_retry_count = 0; //reset count for next time use
+ } else {
+ if(g_connect_retry_count < LBS_EM_MAX_RETRY_CONNECT_TIMES) {
+ timer_start(g_connect_retry_timer, LBS_EM_RETRY_CONNECT_INTERVAL);
+ } else {
+ g_connect_retry_count = 0; //reset count for next time use
+ LOGW("port retry count reach to max, no retry anymore");
+ }
+ }
+}
+
+static void mtk_lbs_em_epoll_internal_hdlr(int fd) {
+ char buff[1024] = {0};
+ int ret = read(fd, buff, sizeof(buff));
+ if(ret == -1) {
+ LOGE("read() failed, fd=[%d] reason=[%s]%d", fd, strerror(errno), errno);
+ crash_with_log();
+ }
+ int cmd = buff[0];
+ switch(cmd) {
+ case LBS_EM_INT_CMD_RETRY_CONNECT:
+ mtk_lbs_em_timer_retry_connect_hdlr();
+ break;
+ default:
+ LOGE("unknown cmd=[%d]", cmd);
+ break;
+ }
+}
+/**
+ * Decodes GSM 7-bit septets in 8-bit octets.
+ *
+ * @param ud The 8-bit octets representing 7-bit data
+ * @param fillBits The number of fill bits, if any
+ * @param udl The message length, if known
+ * @return The converted message
+ */
+//public static int[] decode7bit(int[] ud, int udl, int fillBits)
+static void decodeGSMPackedString(const char* input, char* output, int length)
+{
+ int udl = -1;
+ const char* ud = input;
+
+ const char upperBits[] = {
+ 0xFE, // 0 = B7|B6|B5|B4|B3|B2|B1
+ 0xFC, // 1 = B7|B6|B5|B4|B3|B2
+ 0xF8, // 2 = B7|B6|B5|B4|B3
+ 0xF0, // 3 = B7|B6|B5|B4
+ 0xE0, // 4 = B7|B6|B5
+ 0xC0, // 5 = B7|B6
+ 0x80 // 6 = B7
+ };
+
+ const char lowerBits[] = {
+ 0x01, // 0 = B0
+ 0x03, // 1 = B1|B0
+ 0x07, // 2 = B2|B1|B0
+ 0x0F, // 3 = B3|B2|B1|B0
+ 0x1F, // 4 = B4|B3|B2|B1|B0
+ 0x3F, // 5 = B5|B4|B3|B2|B1|B0
+ 0x7F // 6 = B6|B5|B4|B3|B2|B1|B0
+ };
+
+ if (udl < 0) {
+ udl = length * 8 / 7;
+ }
+
+ int b = 6, p = 0;
+ int i = 0;
+ for (i = 0; i < udl; i++) {
+ switch (b) {
+ case 7: // U0
+ output[i] = (ud[p] & upperBits[0]) >> 1;
+ break;
+
+ case 6: // L6
+ output[i] = ud[p] & lowerBits[b];
+ break;
+
+ default: // The rest
+ output[i] = ((ud[p] & lowerBits[b]) << (6 - b))
+ + ((ud[p-1] & upperBits[b+1]) >> (b+2));
+ break;
+ }
+
+ if (--b == -1) {
+ b = 7;
+ } else {
+ p++;
+ }
+ }
+}
+
+// Converts a string (or Hex string) to a char array
+static int stringToByteArray(const char* original, char* output)
+{
+ int final_len = strlen(original)/2;
+ size_t i=0, j=0;
+
+ for (i=0, j=0; j<final_len; i+=2, j++) {
+ output[j] = (original[i] % 32 + 9) % 25 * 16 + (original[i+1] % 32 + 9) % 25;
+ }
+ output[final_len] = '\0';
+ return final_len;
+}
+
+static void decodeUCS2ASCII(const char* input, char* output, int len)
+{
+ char* asc_input = (char*) input+2;
+ int asc_len = len/2 - 1;
+ int i = 0;
+
+ for (i = 0; i < asc_len; i++) {
+ output[i] = (asc_input[i*2 + 1]);
+ }
+ output[i] = '\0';
+}
+
+static void decodeString(const char* original, char* output, ni_encoding_type coding)
+{
+ char inputByte[1024] = {};
+ int len = stringToByteArray(original, inputByte);
+
+ switch (coding) {
+ case NI_ENCODING_TYPE_NONE:
+ strncpy(output, inputByte, 1024);
+ break;
+
+ case NI_ENCODING_TYPE_GSM7:
+ decodeGSMPackedString(inputByte, output, len);
+ break;
+
+ case NI_ENCODING_TYPE_UTF8:
+ strncpy(output, inputByte, 1024);
+ break;
+
+ case NI_ENCODING_TYPE_UCS2:
+ decodeUCS2ASCII(inputByte, output, len);
+ break;
+
+ default:
+ LOGE("Unknown encoding:%d for NI text: %s", coding, original);
+ break;
+ }
+}
+
+
+#define MNL_LOG(...) { printf("\E[0;30;43m"); printf(__VA_ARGS__); printf("\E[0m"); fflush(stdout); }
+// ------------- mnldinf basic handlers -----------------
+void mnldinf_basic_connection_broken_hdlr() {
+ LOGW("MNLD is crash, start to re-connection procedure for Basic");
+ mtk_lbs_em_close_fd(g_mnld_basic_fd);
+ timer_start(g_connect_retry_timer, LBS_EM_RETRY_CONNECT_INTERVAL);
+}
+
+void mnldinf_location_hdlr(gps_location location) {
+// LOGD("flags=[0x%x] time=[%"PRId64"] hacc=[%.1f] alt=[%.1f] vacc=[%.1f]",
+// location.flags, location.timestamp, location.h_accuracy, location.alt, location.v_accuracy);
+
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ MNL_LOG("%s [MNL] location flags=0x%x timestamp=%lld",
+ time_buff, location.flags, (long long)location.timestamp);
+ if(location.flags & MTK_GPS_LOCATION_HAS_LAT_LONG) {
+ //MNL_LOG(" lat,lng = %f,%f", location.lat, location.lng);
+ }
+ if(location.flags & MTK_GPS_LOCATION_HAS_ALT) {
+ MNL_LOG(" alt=%f", location.alt);
+ }
+ if(location.flags & MTK_GPS_LOCATION_HAS_SPEED) {
+ MNL_LOG(" speed=%f", location.speed);
+ }
+ if(location.flags & MTK_GPS_LOCATION_HAS_BEARING) {
+ MNL_LOG(" bearing=%f", location.bearing);
+ }
+ if(location.flags & MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY) {
+ MNL_LOG(" accuracy=%f", location.h_accuracy);
+ }
+}
+
+void mnldinf_gnss_status_hdlr(gps_status status) {
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ if(!g_gps_info_enable) return;
+ MNL_LOG("%s [MNL] gps_status status=[%d] (BEGIN=1 END=2 ENGINE_ON=3 ENGINE_OFF=4)",
+ time_buff, status);
+}
+
+void mnldinf_gnss_sv_hdlr(gnss_sv_info sv) {
+ if(!g_gps_info_enable) return;
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ MNL_LOG("%s [MNL] gps_sv num=[%d]", time_buff, sv.num_svs);
+ int i = 0;
+ for(i = 0; i < sv.num_svs; i++) {
+ gnss_sv* s = &sv.sv_list[i];
+ MNL_LOG(" i=[%d] svid=[%02d] constellation=[%02d] cn=[%f] ele=[%f] azi=[%f] flags=[%02d]",
+ i, s->svid, s->constellation, s->c_n0_dbhz, s->elevation, s->azimuth, s->flags);
+ }
+}
+
+void mnldinf_nmea_hdlr(int64_t timestamp, const char* nmea, int length) {
+ if(!g_nmea_enable) return;
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ MNL_LOG("%s [MNL] nmea timestamp=[%lld] len=[%d] %s", time_buff, (long long)timestamp, length, nmea);
+}
+
+void mnldinf_nmea_done_hdlr() {
+ if(!g_nmea_enable) return;
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ MNL_LOG("%s [MNL] nmea done", time_buff);
+}
+
+void mnldinf_gnss_measurements_hdlr(gnss_data *data) {
+ if(!g_gps_info_enable) return;
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ MNL_LOG("%s [MNL] gps_measurements", time_buff);
+}
+
+void mnldinf_basic_capability_update_hdlr(mnldinf_basic_server_cap *cap) {
+ //LOGD("support_gnss=[%d]", cap->support_gnss);
+}
+
+//MNLD send the message to GNSS adaptor
+static mnldinf_basic g_mnld_basic_callbacks = {
+ mnldinf_basic_connection_broken_hdlr,
+ mnldinf_location_hdlr,
+ mnldinf_gnss_status_hdlr,
+ mnldinf_gnss_sv_hdlr,
+ mnldinf_nmea_hdlr,
+ mnldinf_nmea_done_hdlr,
+ mnldinf_gnss_measurements_hdlr,
+ mnldinf_basic_capability_update_hdlr,
+};
+
+// ------------- mnldinf ext handlers -----------------
+void mnldinf_ext_connection_broken_hdlr() {
+ LOGW("MNLD is crash, start to re-connection procedure for EXT");
+ mtk_lbs_em_close_fd(g_mnld_ext_fd);
+ timer_start(g_connect_retry_timer, LBS_EM_RETRY_CONNECT_INTERVAL);
+}
+
+void mnldinf_request_wakelock_hdlr() {
+ if(!g_gps_info_enable) return;
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ MNL_LOG("%s [MNL] request_wakelock", time_buff);
+}
+
+void mnldinf_release_wakelock_hdlr() {
+ if(!g_gps_info_enable) return;
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ MNL_LOG("%s [MNL] release_wakelock", time_buff);
+}
+
+void mnldinf_request_utc_time_hdlr() {
+ if(!g_gps_info_enable) return;
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ MNL_LOG("%s [MNL] request_utc_time", time_buff);
+}
+
+void mnldinf_request_nlp_hdlr(bool independentFromGnss, bool isUserEmergency) {
+ if(!g_gps_info_enable) return;
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ MNL_LOG("%s [MNL] request_nlp_loc independentFromGnss=%d isUserEmergency=%d",
+ time_buff, independentFromGnss, isUserEmergency);
+}
+
+void mnldinf_request_ni_notify_hdlr(int notify_id, agps_ni_type ni_type,
+ agps_notify_type notify_type,
+ const char* requestor_id, const char* client_name,
+ ni_encoding_type requestor_id_encoding, ni_encoding_type client_name_encoding) {
+ char output[1024] = {};
+ g_notify_id = notify_id;
+ LOGD("ni notify requested notify_id=[%d]", notify_id);
+ LOGD("ni notify requested ni_type=[%d]"
+ " (1=VOICE 2=UMTS_SUPL 3=UMTS_CTRL_PLANE 4=EMERGENCY_SUPL)", ni_type);
+ LOGD("ni notify requested notify_type=[%d]"
+ " (0=NONE 1=NOTIFY_ONLY 2=NOTIFY_ALLOW_NO_ANSWER 3=NOTIFY_DENY_NO_ANSWER 4=PRIVACY)"
+ , notify_type);
+
+ decodeString(requestor_id, output, requestor_id_encoding);
+ LOGD("ni notify requestor_id_encoding=[%d] (0=NONE 1=GSM7 2=UTF8 3=UCS2), requstor_id: [%s]",
+ requestor_id_encoding, output);
+
+ decodeString(client_name, output, client_name_encoding);
+ LOGD("ni notify client_name_encoding=[%d] (0=NONE 1=GSM7 2=UTF8 3=UCS2), client_name: [%s]",
+ client_name_encoding, output);
+
+}
+
+void mnldinf_request_data_conn_hdlr(struct sockaddr_storage* addr, agps_type type) {
+ //the host is not allowed the device to setup the data connection, only the host can setup APN by itself, do nothing
+}
+
+void mnldinf_release_data_conn_hdlr() {
+ //the host is not allowed the device to setup the data connection, only the host can setup APN by itself, do nothing
+}
+
+void mnldinf_request_set_id_hdlr(request_setid flags) {
+ if(!g_gps_info_enable) return;
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ MNL_LOG("%s [MNL] request_set_id", time_buff);
+}
+
+void mnldinf_request_ref_loc_hdlr(request_refloc flags) {
+ if(!g_gps_info_enable) return;
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ MNL_LOG("%s [MNL] request_ref_loc", time_buff);
+}
+
+void mnldinf_output_vzw_debug_hdlr(const char* str) {
+ //no need to support this, do nothing
+}
+
+void mnldinf_update_gnss_name_hdlr(const char* name, int length) {
+ if(!g_gps_info_enable) return;
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ //MNL_LOG("%s [MNL] gnss_name len=[%d] %s", time_buff, length, name);
+}
+
+void mnldinf_gnss_navigation_msg_hdlr(gnss_nav_msg *msg) {
+ if(!g_gps_info_enable) return;
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ MNL_LOG("%s [MNL] gps_navigation", time_buff);
+}
+
+
+void mnldinf_nfw_access_notify_hdlr(mnldinf_nfw_notification *nfw_notify) {
+ //no AT command to forward AOSP non-framework notification, do nothing
+}
+
+void mnldinf_ext_capability_update_hdlr(mnldinf_ext_server_cap *cap) {
+ if(!g_gps_info_enable) return;
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ //MNL_LOG("%s [MNL] mnld_capabilities support_gnss=[%d]", time_buff, cap->support_gnss);
+}
+
+void mnldinf_agps_location_update(mnldinf_agps_location location) {
+ MNL_LOG("[MNL] mnldinf_agps_location_update");
+}
+
+static mnldinf_ext g_mnld_ext_callbacks = {
+ mnldinf_ext_connection_broken_hdlr,
+ mnldinf_request_wakelock_hdlr,
+ mnldinf_release_wakelock_hdlr,
+
+ mnldinf_request_utc_time_hdlr,
+ mnldinf_request_nlp_hdlr,
+ mnldinf_request_ni_notify_hdlr,
+
+ mnldinf_request_data_conn_hdlr,
+ mnldinf_release_data_conn_hdlr,
+
+ mnldinf_request_set_id_hdlr,
+ mnldinf_request_ref_loc_hdlr,
+ mnldinf_output_vzw_debug_hdlr,
+
+ mnldinf_update_gnss_name_hdlr,
+
+ mnldinf_gnss_navigation_msg_hdlr,
+ mnldinf_nfw_access_notify_hdlr,
+ mnldinf_ext_capability_update_hdlr,
+ mnldinf_agps_location_update,
+};
+
+
+// ------------- mk at handlers -----------------
+static void mtk_at_result_hdlr(int fd, bool is_ok, const char* msg) {
+ UNUSED(msg);
+ if(is_ok) {
+ LOGW("GNSS Adapter reply: OK");
+ } else {
+ LOGE("GNSS Adapter reply: ERROR");
+ }
+ if(g_at_cert_injecting) {
+ g_cert_result = is_ok;
+ sem_post(&g_cert_sem);
+ }
+}
+
+static void mtk_at_gnss_nmea_notify_hdlr(int fd, const char* nmea) {
+ if (g_at_cmd_enable) {
+ LOGD("mtk_at_gnss_nmea_notify_hdlr() fd=[%d] nmea=[%s]", fd, nmea);
+ }
+}
+
+static void mtk_at_gnss_nmea_end_notify_hdlr(int fd) {
+ if (g_at_cmd_enable) {
+ LOGD("mtk_at_gnss_nmea_end_notify_hdlr() fd=[%d]", fd);
+ }
+}
+
+static void mtk_at_gnss_satellite_notify_hdlr(int fd, mtk_gnss_satellite_list* list) {
+ if (g_at_cmd_enable) {
+ LOGD("mtk_at_gnss_satellite_notify_hdlr() fd=[%d]", fd);
+ mtk_at_dump_mtk_gnss_satellite_list(list);
+ }
+}
+
+static void mtk_at_gnss_location_notify_hdlr(int fd, mtk_gnss_location* location) {
+ if (g_at_cmd_enable) {
+ LOGD("mtk_at_gnss_location_notify_hdlr() fd=[%d]", fd);
+ mtk_at_dump_mtk_gnss_location(location);
+ }
+}
+
+static void mtk_at_gnss_agnss_location_notify_hdlr(int fd, mtk_agnss_location* location) {
+ LOGW("mtk_at_gnss_agnss_location_notify_hdlr() fd=[%d]", fd);
+ mtk_at_dump_mtk_agnss_location(location);
+}
+
+static void mtk_at_gnss_device_reset_notify_hdlr(int fd, const char* reason) {
+ LOGW("mtk_at_gnss_device_reset_notify_hdlr() fd=[%d] reason=[%s]", fd, reason);
+}
+
+static void mtk_at_gnss_status_response_hdlr(int fd, mtk_gnss_status* status) {
+ LOGW("mtk_at_gnss_status_response_hdlr() fd=[%d]", fd);
+ mtk_at_dump_mtk_gnss_status(status);
+}
+
+static void mtk_at_gnss_ni_notify_request_hdlr(int fd, mtk_gnss_ni_notify* notify) {
+ LOGW("mtk_at_gnss_ni_notify_request_hdlr() fd=[%d]", fd);
+ mtk_at_dump_mtk_gnss_ni_notify(notify);
+ mnldinf_request_ni_notify_hdlr(notify->id, notify->type, notify->notify_type, notify->request_id,
+ notify->text, notify->request_id_encode_type, notify->text_encode_type);
+}
+
+static void mtk_at_gnss_ref_location_request_hdlr(int fd) {
+ LOGW("mtk_at_gnss_ref_location_request_hdlr() fd=[%d]", fd);
+}
+
+static void mtk_at_gnss_ref_time_request_hdlr(int fd) {
+ LOGW("mtk_at_gnss_ref_time_request_hdlr() fd=[%d]", fd);
+}
+
+static void mtk_at_gnss_loopback_response_hdlr(int fd, const char* msg) {
+ LOGW("mtk_at_gnss_loopback_response_hdlr() fd=[%d] msg=[%s]", fd, msg);
+}
+
+static void mtk_at_gnss_cert_name_response_hdlr(int fd, mtk_gnss_cert_name_list* list) {
+ LOGW("mtk_at_gnss_cert_name_response_hdlr() fd=[%d]", fd);
+ mtk_at_dump_mtk_gnss_cert_name_list(list);
+}
+
+static void mtk_at_geo_max_num_response_hdlr(int fd, int num) {
+ LOGW("mtk_at_geo_max_num_response_hdlr() fd=[%d] num=[%d]", fd, num);
+}
+
+static void mtk_at_geo_add_circle_response_hdlr(int fd, mtk_geo_fence_create_state state, int id) {
+ LOGW("mtk_at_geo_add_circle_response_hdlr() fd=[%d] state=[%d] (0=success) id=[%d]", fd, state, id);
+ if (g_at_geofence_add_with_wake_lock_release) {
+ LOGD("Geofence Add Circle Request with wake lock release");
+ //delay to do wake_unlock to ensure the msg can be deliveried to other process
+ timer_start(g_wake_unlock_timer, LBS_EM_WAKE_LOCK_TIMEOUT);
+ }
+}
+
+static void mtk_at_geo_alert_notify_hdlr(int fd, mtk_geo_alert_notify* notify) {
+ LOGD("mtk_at_geo_alert_notify_hdlr() fd=[%d]", fd);
+ mtk_at_dump_mtk_geo_alert_notify(notify);
+}
+
+static void mtk_at_geo_track_notify_hdlr(int fd, mtk_geo_track_state state, const char* date_time) {
+ LOGD("mtk_at_geo_track_notify_hdlr() fd=[%d] state=[%d] (0=success) date_time=[%s]", fd, state, date_time);
+}
+
+
+static mtk_gnss_at_client_callbacks g_gnss_at_client_callbacks = {
+ mtk_at_result_hdlr,
+ mtk_at_gnss_nmea_notify_hdlr,
+ mtk_at_gnss_nmea_end_notify_hdlr,
+ mtk_at_gnss_satellite_notify_hdlr,
+ mtk_at_gnss_location_notify_hdlr,
+ mtk_at_gnss_agnss_location_notify_hdlr,
+ mtk_at_gnss_device_reset_notify_hdlr,
+ mtk_at_gnss_status_response_hdlr,
+ mtk_at_gnss_ni_notify_request_hdlr,
+ mtk_at_gnss_ref_location_request_hdlr,
+ mtk_at_gnss_ref_time_request_hdlr,
+ mtk_at_gnss_loopback_response_hdlr,
+ mtk_at_gnss_cert_name_response_hdlr,
+ mtk_at_geo_max_num_response_hdlr,
+ mtk_at_geo_add_circle_response_hdlr,
+ mtk_at_geo_alert_notify_hdlr,
+ mtk_at_geo_track_notify_hdlr,
+};
+
+static void gnssadp_hdlr(int fd) {
+ char buff[8192] = {0};
+ int len = read(fd, buff, sizeof(buff));
+ if(len <= 0) {
+ LOGE("gnssadp_hdlr() the connection between EM and GNSS Adaptor is broken");
+ close(fd);
+ return;
+ }
+
+ buff[sizeof(buff)-1] = '\0';
+ //TCP packets are combined together, need to extract them
+ const char* p1 = buff;
+ while(p1) {
+ char buff2[3456] = {0};
+ const char* p2 = strstr(p1, "\n");
+ if(p2 != NULL) {
+ len = (p2 - p1) + 1;
+ //to support \r\n at beginning of the string
+ if(len == 2 && p1[0] == '\r' && p1[1] == '\n') {
+ p2++;
+ p2 = strstr(p2, "\n");
+ if(p2 == NULL) {
+ LOGE("unexpected data");
+ dump_buff(buff, len);
+ break;
+ }
+ }
+ memcpy(buff2, p1, (p2 - p1) + 1);
+ mtk_at_client_parser(fd, buff2, &g_gnss_at_client_callbacks);
+ p2++;
+ }
+ p1 = p2;
+ }
+}
+
+static void nlp_client_read_and_decode(int fd) {
+ char buff[8192] = {0};
+ int len = read(fd, buff, sizeof(buff));
+ if(len <= 0) {
+ LOGE("nlp_client_read_and_decode() the connection between EM and NLP Service is broken");
+ mtk_lbs_em_close_fd(fd);
+ timer_start(g_connect_retry_timer, LBS_EM_RETRY_CONNECT_INTERVAL);
+ return;
+ }
+ LOGW(" MtkNlp_client_read_and_decode fd=%d size=%d", fd, len);
+
+ MtkNlp_decoded_location decLoc = MtkNlp_receiver_decode_location(fd, buff);
+ LOGD("MtkNlp_Location_dump()");
+ if (decLoc.nlp_location_valid) {
+ SOCK_LOGD(" valid=[%d]", decLoc.nlp_location_valid);
+ MtkNlp_location* data = &decLoc.nlp_location;
+ SOCK_LOGD(" time=[%lld]", data->time);
+ SOCK_LOGD(" elapsed_real_time_nanos=[%lld]", data->elapsed_real_time_nanos);
+ SOCK_LOGD(" latitude=[%f]", data->latitude);
+ SOCK_LOGD(" longitude=[%f]", data->longitude);
+ SOCK_LOGD(" altitude_valid=[%d]", data->altitude_valid);
+ SOCK_LOGD(" altitude=[%f]", data->altitude);
+ SOCK_LOGD(" horizontal_accuracy_valid=[%d]", data->horizontal_accuracy_valid);
+ SOCK_LOGD(" horizontal_accuracy=[%f]", data->horizontal_accuracy);
+ SOCK_LOGD(" vertical_accuracy_valid=[%d]", data->vertical_accuracy_valid);
+ SOCK_LOGD(" vertical_accuracy=[%f]", data->vertical_accuracy);
+ SOCK_LOGD(" location_source_valid=[%d]", data->location_source_valid);
+ SOCK_LOGD(" location_source=[%d]", data->location_source);
+ } else {
+ SOCK_LOGE(" No valid location reported");
+ }
+}
+
+
+bool lbs_em_wake_lock() {
+#if !defined(__LBS_EM_OS_LINUX__) //no permission to open wake_lock on Linux
+ int fd = open("/sys/power/wake_lock", O_RDWR | O_NONBLOCK);
+ if(fd == -1) {
+ LOGE("open() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+
+ int ret = write(fd, LBS_EM_WAKE_LOCK_ID, strlen(LBS_EM_WAKE_LOCK_ID));
+ if(ret == -1) {
+ LOGE("write() failed id=[%s], reason=[%s]%d", LBS_EM_WAKE_LOCK_ID, strerror(errno), errno);
+ close(fd);
+ return false;
+ }
+
+ close(fd);
+#endif
+ return true;
+}
+
+bool lbs_em_wake_unlock() {
+#if !defined(__LBS_EM_OS_LINUX__) //no permission to open wake_unlock on Linux
+ int fd = open("/sys/power/wake_unlock", O_RDWR | O_NONBLOCK);
+ if(fd == -1) {
+ LOGE("open() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+
+ int ret = write(fd, LBS_EM_WAKE_LOCK_ID, strlen(LBS_EM_WAKE_LOCK_ID));
+ if(ret == -1) {
+ LOGE("write() failed id=[%s], reason=[%s]%d", LBS_EM_WAKE_LOCK_ID, strerror(errno), errno);
+ close(fd);
+ return false;
+ }
+
+ close(fd);
+#endif
+ return true;
+}
+
+void lbs_em_mutex_lock() {
+ int ret = pthread_mutex_lock(&g_mutex);
+ if(ret != 0) {
+ LOGE("pthread_mutex_lock() failed, reason=[%s]%d", strerror(ret), ret);
+ }
+}
+
+void lbs_em_mutex_unlock() {
+ int ret = pthread_mutex_unlock(&g_mutex);
+ if(ret != 0) {
+ LOGE("pthread_mutex_unlock() failed, reason=[%s]%d", strerror(ret), ret);
+ }
+}
+
+static void lbs_em_timer_wake_unlock_routine(int id) {
+ //do not use the internal msg or it will cause infinite loop in epoll_wait
+ lbs_em_mutex_lock();
+ if(g_wake_lock_acquired) {
+ if(lbs_em_wake_unlock()) {
+ g_wake_lock_acquired = false;
+ }
+ }
+ LOGD("lbs_em_timer_wake_unlock_routine g_wake_lock_acquired=%d", g_wake_lock_acquired);
+ lbs_em_mutex_unlock();
+}
+
+static void lbs_em_acquire_wake_lock_mutex() {
+ lbs_em_mutex_lock();
+ timer_stop(g_wake_unlock_timer);
+ if(!g_wake_lock_acquired) {
+ g_wake_lock_acquired = lbs_em_wake_lock();
+ }
+ LOGD("lbs_em_acquire_wake_lock g_wake_lock_acquired=%d", g_wake_lock_acquired);
+ lbs_em_mutex_unlock();
+}
+
+// ------------- message receiving thread -----------------
+static void* event_thread(void *arg) {
+ #define MAX_EPOLL_EVENT 50
+ struct epoll_event events[MAX_EPOLL_EVENT];
+
+ msleep2(300);
+ LOGD(" ");
+ g_epfd = epoll_create(MAX_EPOLL_EVENT);
+ if(g_epfd == -1) {
+ LOGE("ERR: event_thread() epoll_create() fail reason=[%s]", strerror(errno));
+ return NULL;
+ }
+
+ g_agps_debug_fd = agps_debug_interface_get_fd();
+ if(g_agps_debug_fd < 0) {
+ LOGE("ERR: event_thread() agps_debug_interface_get_fd() fail");
+ } else {
+ epoll_add_fd3(g_epfd, g_agps_debug_fd);
+ }
+
+ g_mnld_basic_fd = mnldinf_basic_register("LBS EM");
+ if(g_mnld_basic_fd < 0) {
+ LOGE("ERR: event_thread() mnldinf_basic_register fail");
+ } else {
+ epoll_add_fd3(g_epfd, g_mnld_basic_fd);
+ mnldinf_basic_client_cap cap;
+ cap.support_gnss = true;
+ mnldinf_basic_capability_config(g_mnld_basic_fd, &cap);
+ }
+
+ g_mnld_ext_fd = mnldinf_ext_register("LBS EM");
+ if(g_mnld_ext_fd < 0) {
+ LOGE("ERR: event_thread() mnldinf_basic_register fail");
+ } else {
+ epoll_add_fd3(g_epfd, g_mnld_ext_fd);
+ mnldinf_ext_client_cap cap;
+ cap.support_gnss = true;
+ mnldinf_ext_capability_config(g_mnld_ext_fd, &cap);
+ }
+
+
+ g_gnssadp_fd = socket_tcp_client_connect_local(true, GNSSADP_AT_SOCKET);
+ if(g_gnssadp_fd < 0) {
+ LOGE("ERR: event_thread() socket_tcp_client_connect_local(true, GNSSADP_AT_SOCKET) fail");
+ } else {
+ epoll_add_fd3(g_epfd, g_gnssadp_fd);
+ }
+
+
+ g_internal_fd = socket_udp_server_bind_local(true, LBSEM_INTERNAL_SOCKET);
+ if(g_internal_fd < 0) {
+ LOGE("socket_udp_server_bind_local(true, LBSEM_INTERNAL_SOCKET) failed");
+ exit(1);
+ } else {
+ epoll_add_fd3(g_epfd, g_internal_fd);
+ }
+
+
+ g_connect_retry_timer = timer_init(mtk_lbs_em_timer_retry_port_routine, 0);
+ if(g_connect_retry_timer == NULL) {
+ LOGE("timer_init(mtk_lbs_em_timer_retry_port_routine, 0) failed");
+ exit(1);
+ }
+
+ g_wake_unlock_timer = timer_init(lbs_em_timer_wake_unlock_routine, 0);
+ if(g_wake_unlock_timer == NULL) {
+ LOGE("timer_init(lbs_em_timer_wake_unlock_routine, 0) failed");
+ exit(1);
+ }
+
+ mtk_socket_client_init_local(&g_nlpservice_fd, NLP_SERVICE_CHANNEL, SOCK_NS_ABSTRACT);// nlp client
+ g_nlpservice_fd.fd = MtkNlp_get_fd();
+ if(g_nlpservice_fd.fd < 0) {
+ LOGE("ERR: event_thread() socket_tcp_client_connect_local(true, NLP_SERVICE_CHANNEL) fail");
+ } else {
+ epoll_add_fd3(g_epfd, g_nlpservice_fd.fd);
+ }
+
+ lbs_em_acquire_wake_lock_mutex();
+
+
+ while(1) {
+ int i;
+ int n;
+
+ n = epoll_wait(g_epfd, events, MAX_EPOLL_EVENT , -1);
+ if(n == -1) {
+ if(errno == EINTR) {
+ continue;
+ } else {
+ LOGE("ERR: event_thread() epoll_wait failure reason=[%s]", strerror(errno));
+ return NULL;
+ }
+ }
+
+ for(i = 0; i < n; i++) {
+ // agps debug interface
+ if(events[i].data.fd == g_agps_debug_fd) {
+ if(events[i].events & EPOLLIN) {
+ agps_debug_message_hdlr(g_epfd);
+ }
+ }
+ // mnldinf basic interface
+ if(events[i].data.fd == g_mnld_basic_fd) {
+ if(events[i].events & EPOLLIN) {
+ mnldinf_basic_cmd_hdlr(g_mnld_basic_fd, &g_mnld_basic_callbacks); }
+ }
+ // mnldinf ext interface
+ if(events[i].data.fd == g_mnld_ext_fd) {
+ if(events[i].events & EPOLLIN) {
+ mnldinf_ext_cmd_hdlr(g_mnld_ext_fd, &g_mnld_ext_callbacks);
+ }
+ }
+
+ if(events[i].data.fd == g_gnssadp_fd) {
+ if(events[i].events & EPOLLIN) {
+ gnssadp_hdlr(g_gnssadp_fd);
+ }
+ }
+
+ if(events[i].data.fd == g_nlpservice_fd.fd) {
+ if(events[i].events & EPOLLIN) {
+ nlp_client_read_and_decode(g_nlpservice_fd.fd);
+ }
+ }
+ // internal event interface
+ if(events[i].data.fd == g_internal_fd) {
+ if(events[i].events & EPOLLIN) {
+ mtk_lbs_em_epoll_internal_hdlr(g_internal_fd);
+ }
+ }
+ }
+ }
+
+ g_wake_lock_acquired = false;
+ lbs_em_timer_wake_unlock_routine(0);
+ //delay to do wake_unlock to ensure the msg can be deliveried to other process
+ //timer_start(g_wake_unlock_timer, LBS_EM_WAKE_LOCK_TIMEOUT);
+
+ return NULL;
+}
+
+// ------------- main() -----------------
+
+int main() {
+ sem_init(&g_cert_sem, 0 /*pshared*/, 0 /*value*/);
+
+ pthread_t pthread1;
+ pthread_create(&pthread1, NULL, event_thread, NULL);
+
+ g_geo_list.num = 0;
+
+ return mtk_lbs_em_start();
+}
+
+/*
+printf("\E[0;30;47m");
+printf("\E[0m");
+
+the type of word:
+0 normal
+1 bold
+4 underline
+5 gray in background
+7 switch the color of word and the color of background
+
+the color of word:
+30 black
+31 red
+32 green
+33 yellow
+34 blue
+35 purple
+36 light green
+37 white
+
+the color of background:
+40 black
+41 red
+42 green
+43 yellow
+44 blue
+45 purple
+46 light green
+47 white
+*/
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/makefile b/src/connectivity/agps/2.0/lbs_em/src/makefile
new file mode 100644
index 0000000..a752853
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/makefile
@@ -0,0 +1,109 @@
+#CC=gcc
+#CXX=g++
+
+FLAGS = \
+ -g \
+ -Wall \
+ -D __YOCTO_OS__ \
+ -D __LBS_EM_OS_LINUX__\
+
+
+INCLUDE = \
+ -I$(BB_SYSROOT_ADD)/usr/include/openssl \
+ -I$(BB_SYSROOT_ADD)/usr/include/openssl/include \
+ -I$(BB_SYSROOT_ADD)/usr/include/openssl/crypto \
+ -I./mtk_tree/inc \
+ -I./agps_interface/inc \
+ -I./agps_interface/cfg/inc \
+ -I./agps_interface/cfg/libs/mtkexpat \
+ -I./agps_debug_interface/inc \
+ -I./mnldinf/inc/ \
+ -I./mtk_gnss_at_command \
+ -I./nlp/inc \
+ -I./utility/inc \
+
+
+LIBS = \
+ -lrt \
+ -lpthread \
+ -lssl \
+ -lcrypto \
+ -lexpat \
+ -llog \
+# -lagps_interface \
+
+
+EM_CXXSRC = \
+
+EM_CSRC = \
+ ./mtk_tree/src/mtk_tree.c \
+ \
+ ./agps_interface/src/agps_interface.c \
+ ./agps_interface/src/data_coder.c \
+ ./agps_interface/cfg/src/agpsprofile.c \
+ ./agps_interface/cfg/libs/mtkexpat/mtkexpat.c \
+ \
+ ./agps_debug_interface/src/agps_debug_interface.c \
+ \
+ ./mnldinf/src/mnldinf_basic.c \
+ ./mnldinf/src/mnldinf_data_coder.c \
+ ./mnldinf/src/mnldinf_ext.c \
+ ./mnldinf/src/mnldinf_log.c \
+ ./mnldinf/src/mnldinf_utility.c \
+ \
+ ./mtk_gnss_at_command/mtk_gnss_at_struct.c \
+ ./mtk_gnss_at_command/mtk_gnss_at_client.c \
+ \
+ ./nlp/src/MtkNlp.c \
+ \
+ ./utility/src/mtk_socket_data_coder.c \
+ ./utility/src/mtk_socket_utils.c \
+ ./utility/src/mtk_lbs_utility.c \
+ \
+ ./lbs_em.c \
+
+EM_EXECUTABLE = lbs_em_tool
+EM_COBJS = $(EM_CSRC:.c=.o)
+EM_CXXOBJS = $(EM_CXXSRC:.cpp=.o)
+
+#AGPS_INTERFACE_LIB_TARGET = libagps_interface.so
+#AGPS_INTERFACE_LIB_SRC = ./agps_interface
+
+TEST_CXXSRC = \
+
+TEST_CSRC = \
+ ./agps_interface/src/agps_interface.c \
+ ./agps_interface/src/data_coder.c \
+ ./agps_interface/cfg/src/agpsprofile.c \
+ ./agps_interface/cfg/libs/mtkexpat/mtkexpat.c \
+ \
+ ./utility/src/mtk_lbs_utility.c \
+ \
+ ./mtk_agps_test_case.c \
+
+TEST_EXECUTABLE = mtk_agps_test_case
+TEST_COBJS = $(TEST_CSRC:.c=.o)
+TEST_CXXOBJS = $(TEST_CXXSRC:.cpp=.o)
+
+CFLAGS += $(FLAGS) $(INCLUDE)
+CXXFLAGS += $(FLAGS) $(INCLUDE)
+
+#all: $(AGPS_INTERFACE_LIB_TARGET) $(EM_EXECUTABLE)
+all: $(EM_EXECUTABLE) $(TEST_EXECUTABLE)
+
+$(EM_EXECUTABLE): $(EM_COBJS) $(EM_CXXOBJS)
+ $(CXX) $^ $(LIBS) $(LDFLAGS) -o $@
+# $(CXX) $^ $(LIBS) $(LDFLAGS) -L$(AGPS_INTERFACE_LIB_SRC) -o $@
+
+#$(AGPS_INTERFACE_LIB_TARGET): $(AGPS_INTERFACE_LIB_SRC)
+# make -C $(AGPS_INTERFACE_LIB_SRC)
+
+$(TEST_EXECUTABLE): $(TEST_COBJS) $(TEST_CXXOBJS)
+ $(CXX) $^ $(LIBS) $(LDFLAGS) -o $@
+
+.PHONY: clean
+
+clean:
+ rm -f $(EM_EXECUTABLE) rm -rf *.o
+# rm -f $(EM_EXECUTABLE) $(AGPS_INTERFACE_LIB_TARGET) rm -rf *.o
+ find ./ -name *.o | xargs rm -rf
\ No newline at end of file
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_basic.h b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_basic.h
new file mode 100755
index 0000000..c172f4d
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_basic.h
@@ -0,0 +1,43 @@
+#ifndef __MNLDINF_BASIC_INTERFACE_H__
+#define __MNLDINF_BASIC_INTERFACE_H__
+
+#include "mnldinf_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MNLDINF_BASIC_TCP "mnldinf_basic"
+
+typedef struct {
+ void (*mnldinf_connection_broken)();
+ void (*mnldinf_location)(gps_location location);
+ void (*mnldinf_gnss_status)(gps_status status);
+ void (*mnldinf_gnss_sv)(gnss_sv_info sv);
+ void (*mnldinf_nmea)(int64_t timestamp, const char* nmea, int length);
+ void (*mnldinf_nmea_done)(void);
+ void (*mnldinf_gnss_measurements)(gnss_data *data);
+
+ void (*mnldinf_capability_update)(mnldinf_basic_server_cap *cap);
+} mnldinf_basic;
+
+int mnldinf_basic_gnss_init(int fd);
+int mnldinf_basic_gnss_start(int fd);
+int mnldinf_basic_gnss_stop(int fd);
+int mnldinf_basic_gnss_cleanup(int fd);
+
+int mnldinf_basic_gnss_measurement_enable(int fd, bool enable);
+
+// -1 means failure
+int mnldinf_basic_cmd_hdlr(int fd, mnldinf_basic* hdlr);
+
+int mnldinf_basic_register(char *client_name);
+
+void mnldinf_basic_capability_config(int fd, mnldinf_basic_client_cap *cap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_common.h b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_common.h
new file mode 100755
index 0000000..f1bf7f5
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_common.h
@@ -0,0 +1,1781 @@
+#ifndef __MNLDINF_INTERFACE_COMMON_H__
+#define __MNLDINF_INTERFACE_COMMON_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define HAL_MNL_BUFF_SIZE (10 * 1000)
+#define HAL_MNL_BUFF_SIZE_SND (32 * 1000)
+#define HAL_MNL_INTERFACE_VERSION 1
+
+//======================================================
+// Send to MNLD
+//======================================================
+
+typedef enum {
+ HAL2MNL_HAL_REBOOT = 0,
+ HAL2MNL_GPS_INIT = 101,
+ HAL2MNL_GPS_START = 102,
+ HAL2MNL_GPS_STOP = 103,
+ HAL2MNL_GPS_CLEANUP = 104,
+ HAL2MNL_GPS_INJECT_TIME = 105,
+ HAL2MNL_GPS_INJECT_LOCATION = 106,
+ HAL2MNL_GPS_DELETE_AIDING_DATA = 107,
+ HAL2MNL_GPS_SET_POSITION_MODE = 108,
+ HAL2MNL_DATA_CONN_OPEN = 201,
+ HAL2MNL_DATA_CONN_OPEN_WITH_APN_IP_TYPE = 202,
+ HAL2MNL_DATA_CONN_CLOSED = 203,
+ HAL2MNL_DATA_CONN_FAILED = 204,
+ HAL2MNL_SET_SERVER = 301,
+ HAL2MNL_SET_REF_LOCATION = 302,
+ HAL2MNL_SET_ID = 303,
+ HAL2MNL_NI_MESSAGE = 401,
+ HAL2MNL_NI_RESPOND = 402,
+ HAL2MNL_UPDATE_NETWORK_STATE = 501,
+ HAL2MNL_UPDATE_NETWORK_AVAILABILITY = 502,
+ HAL2MNL_GPS_MEASUREMENT = 601,
+ HAL2MNL_GPS_NAVIGATION = 602,
+ HAL2MNL_VZW_DEBUG = 603,
+ HAL2MNL_GNSS_CONFIG = 604,
+ HAL2MNL_SV_BLACKLIST = 605,
+ HAL2MNL_CORRECTION = 606,
+ HAL2MNL_NFW_ACCESS = 607,
+ HAL2MNL_FULL_TRACKING = 701,
+ HAL2MNL_SEND_PMTK = 702,
+ HAL2MNL_EPO_ENABLE = 703,
+ HAL2MNL_SET_TTFF_ACC = 704,
+ HAL2MNL_BASIC_CAP_SYNC = 705,
+ HAL2MNL_EXT_CAP_SYNC = 706,
+} hal2mnl_cmd;
+
+typedef int gps_pos_mode;
+#define GPS_POS_MODE_STANDALONE 0
+#define GPS_POS_MODE_MSB 1
+
+typedef int gps_pos_recurrence;
+#define GPS_POS_RECURRENCE_PERIODIC 0
+#define GPS_POS_RECURRENCE_SINGLE 1
+
+typedef int ni_user_response_type;
+#define NI_USER_RESPONSE_ACCEPT 1
+#define NI_USER_RESPONSE_DENY 2
+#define NI_USER_RESPONSE_NORESP 3
+
+typedef int cell_type;
+#define CELL_TYPE_GSM 1
+#define CELL_TYPE_UMTS 2
+
+typedef int agps_id_type;
+#define AGPS_ID_TYPE_NONE 0
+#define AGPS_ID_TYPE_IMSI 1
+#define AGPS_ID_TYPE_MSISDN 2
+
+typedef int network_type;
+#define NETWORK_TYPE_MOBILE 0
+#define NETWORK_TYPE_WIFI 1
+#define NETWORK_TYPE_MOBILE_MMS 2
+#define NETWORK_TYPE_MOBILE_SUPL 3
+#define NETWORK_TYPE_MOBILE_DUN 4
+#define NETWORK_TYPE_MOBILE_HIPRI 5
+#define NETWORK_TYPE_WIMAX 6
+
+typedef int apn_ip_type;
+#define MTK_APN_IP_INVALID 0
+#define MTK_APN_IP_IPV4 1
+#define MTK_APN_IP_IPV6 2
+#define MTK_APN_IP_IPV4V6 3
+
+typedef int agps_type;
+#define MTK_AGPS_TYPE_SUPL 1
+#define MTK_AGPS_TYPE_C2K 2
+
+typedef int epo_bitmap;
+#define MTK_EPO_CFG_EPO (1U<<0)
+#define MTK_EPO_CFG_QEPO (1U<<1)
+
+typedef int ttff_acc;
+#define MTK_TTFF_ACC_LOW 0
+#define MTK_TTFF_ACC_MID 1
+#define MTK_TTFF_ACC_HIGH 2
+
+typedef int gnss_delete_flag;
+#define MTK_GNSS_DELETE_EPHEMERIS 0x0001
+#define MTK_GNSS_DELETE_ALMANAC 0x0002
+#define MTK_GNSS_DELETE_POSITION 0x0004
+#define MTK_GNSS_DELETE_TIME 0x0008
+#define MTK_GNSS_DELETE_IONO 0x0010
+#define MTK_GNSS_DELETE_UTC 0x0020
+#define MTK_GNSS_DELETE_HEALTH 0x0040
+#define MTK_GNSS_DELETE_SVDIR 0x0080
+#define MTK_GNSS_DELETE_SVSTEER 0x0100
+#define MTK_GNSS_DELETE_SADATA 0x0200
+#define MTK_GNSS_DELETE_RTI 0x0400
+#define MTK_GNSS_DELETE_CLK 0x0800
+#define MTK_GNSS_DELETE_CELLDB_INFO 0x8000
+#define MTK_GNSS_DELETE_ALL 0xFFFF
+
+//======================================================
+// Receive from MNLD
+//======================================================
+
+typedef enum {
+ MNL2HAL_MNLD_REBOOT = 1,
+ MNL2HAL_LOCATION = 101,
+ MNL2HAL_GPS_STATUS = 102,
+ MNL2HAL_GPS_SV = 103,
+ MNL2HAL_NMEA = 104,
+ MNL2HAL_GPS_CAPABILITIES = 105,
+ MNL2HAL_GPS_MEASUREMENTS = 106,
+ MNL2HAL_GPS_NAVIGATION = 107,
+ MNL2HAL_GNSS_MEASUREMENTS = 108,
+ MNL2HAL_GNSS_NAVIGATION = 109,
+ MNL2HAL_REQUEST_WAKELOCK = 201,
+ MNL2HAL_RELEASE_WAKELOCK = 202,
+ MNL2HAL_REQUEST_UTC_TIME = 301,
+ MNL2HAL_REQUEST_DATA_CONN = 302,
+ MNL2HAL_RELEASE_DATA_CONN = 303,
+ MNL2HAL_REQUEST_NI_NOTIFY = 304,
+ MNL2HAL_REQUEST_SET_ID = 305,
+ MNL2HAL_REQUEST_REF_LOC = 306,
+ MNL2HAL_VZW_DEBUG_OUTPUT = 307,
+ MNL2HAL_UPDATE_GNSS_NAME = 308,
+ MNL2HAL_REQUEST_NLP = 309,
+ MNL2HAL_NFW_NOTIFY = 310,
+ MNL2HAL_BASIC_CAP_SYNC = 311,
+ MNL2HAL_EXT_CAP_SYNC = 312,
+ MNL2HAL_NMEA_DONE = 313,
+ MNL2HAL_AGPS_LOCATION = 314,
+} mnl2hal_cmd;
+
+#define MTK_HAL_GNSS_MAX_SVS (32+7+24+63+36+19+14) //195, GPS+QZSS+Glonass+Beidou+Galileo+SBAS+IRNSS_SV
+#define GPS_MAX_MEASUREMENT 32
+#define MTK_HAL_GNSS_MAX_MEASUREMENT (100)
+
+typedef int gps_location_flags;
+#define MTK_GPS_LOCATION_HAS_LAT_LONG 0x0001
+#define MTK_GPS_LOCATION_HAS_ALT 0x0002
+#define MTK_GPS_LOCATION_HAS_SPEED 0x0004
+#define MTK_GPS_LOCATION_HAS_BEARING 0x0008
+#define MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY 0x0010
+#define MTK_GPS_LOCATION_HAS_VERTICAL_ACCURACY 0x0020
+#define MTK_GPS_LOCATION_HAS_SPEED_ACCURACY 0x0040
+#define MTK_GPS_LOCATION_HAS_BEARING_ACCURACY 0x0080
+#define MTK_GPS_LOCATION_HAS_PDOP 0x0100
+#define MTK_GPS_LOCATION_HAS_HDOP 0x0200
+#define MTK_GPS_LOCATION_HAS_VDOP 0x0400
+
+typedef int gps_capabilites;
+#define GPS_CAP_NONE 0x0010000
+#define GPS_CAP_SCHEDULING 0x0000001
+#define GPS_CAP_MSB 0x0000002
+#define GPS_CAP_MSA 0x0000004
+#define GPS_CAP_SINGLE_SHOT 0x0000008
+#define GPS_CAP_ON_DEMAND_TIME 0x0000010
+#define GPS_CAP_GEOFENCING 0x0000020
+#define GPS_CAP_MEASUREMENTS 0x0000040
+#define GPS_CAP_NAV_MESSAGES 0x0000080
+#define GPS_CAP_LOW_POWER_MODE 0x0000100
+#define GPS_CAP_SATELLITE_BLACKLIST 0x0000200
+#define GPS_CAP_CORRECTION 0x0000400
+#define GPS_CAPABILITY_ANTENNA_INFO 0x0000800
+
+typedef int request_setid;
+#define REQUEST_SETID_IMSI (1<<0L)
+#define REQUEST_SETID_MSISDN (1<<1L)
+
+typedef int request_refloc;
+#define REQUEST_REFLOC_CELLID (1<<0L)
+#define REQUEST_REFLOC_MAC (1<<1L) // not ready
+
+typedef short gps_clock_flags;
+#define GPS_CLK_HAS_LEAP_SECOND (1<<0)
+#define GPS_CLK_HAS_TIME_UNCERTAINTY (1<<1)
+#define GPS_CLK_HAS_FULL_BIAS (1<<2)
+#define GPS_CLK_HAS_BIAS (1<<3)
+#define GPS_CLK_HAS_BIAS_UNCERTAINTY (1<<4)
+#define GPS_CLK_HAS_DRIFT (1<<5)
+#define GPS_CLK_HAS_DRIFT_UNCERTAINTY (1<<6)
+
+typedef char gps_clock_type;
+#define GPS_CLOCK_TYPE_UNKNOWN 0
+#define GPS_CLOCK_TYPE_LOCAL_HW_TIME 1
+#define GPS_CLOCK_TYPE_GPS_TIME 2
+
+typedef int gps_measurement_flags;
+#define GPS_MEASUREMENT_HAS_SNR (1<<0)
+#define GPS_MEASUREMENT_HAS_ELEVATION (1<<1)
+#define GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY (1<<2)
+#define GPS_MEASUREMENT_HAS_AZIMUTH (1<<3)
+#define GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY (1<<4)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE (1<<5)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY (1<<6)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE (1<<7)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY (1<<8)
+#define GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9)
+#define GPS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12)
+#define GPS_MEASUREMENT_HAS_BIT_NUMBER (1<<13)
+#define GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT (1<<14)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT (1<<15)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY (1<<16)
+#define GPS_MEASUREMENT_HAS_USED_IN_FIX (1<<17)
+
+typedef short gps_measurement_state;
+#define GPS_MEASUREMENT_STATE_UNKNOWN 0
+#define GPS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define GPS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define GPS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define GPS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+#define GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4)
+
+typedef short gps_accumulated_delta_range_state;
+#define GPS_ADR_STATE_UNKNOWN 0
+#define GPS_ADR_STATE_VALID (1<<0)
+#define GPS_ADR_STATE_RESET (1<<1)
+#define GPS_ADR_STATE_CYCLE_SLIP (1<<2)
+
+typedef char gps_loss_of_lock;
+#define GPS_LOSS_OF_LOCK_UNKNOWN 0
+#define GPS_LOSS_OF_LOCK_OK 1
+#define GPS_LOSS_OF_LOCK_CYCLE_SLIP 2
+
+typedef char gps_multipath_indicator;
+#define GPS_MULTIPATH_INDICATOR_UNKNOWN 0
+#define GPS_MULTIPATH_INDICATOR_DETECTED 1
+#define GPS_MULTIPATH_INDICATOR_NOT_USED 2
+
+typedef char gps_nav_msg_type;
+#define GPS_NAV_MSG_TYPE_UNKNOWN 0
+#define GPS_NAV_MSG_TYPE_L1CA 1
+#define GPS_NAV_MSG_TYPE_L2CNAV 2
+#define GPS_NAV_MSG_TYPE_L5CNAV 3
+#define GPS_NAV_MSG_TYPE_CNAV2 4
+
+typedef short nav_msg_status;
+#define NAV_MSG_STATUS_UNKONW 0
+#define NAV_MSG_STATUS_PARITY_PASSED (1<<0)
+#define NAV_MSG_STATUS_PARITY_REBUILT (1<<1)
+
+typedef int gps_status;
+#define MTK_GPS_STATUS_SESSION_BEGIN 1
+#define MTK_GPS_STATUS_SESSION_END 2
+#define MTK_GPS_STATUS_SESSION_ENGINE_ON 3
+#define MTK_GPS_STATUS_SESSION_ENGINE_OFF 4
+
+typedef int agps_ni_type;
+#define AGPS_NI_TYPE_VOICE 1
+#define AGPS_NI_TYPE_UMTS_SUPL 2
+#define AGPS_NI_TYPE_UMTS_CTRL_PLANE 3
+#define AGPS_NI_TYPE_EMERGENCY_SUPL 4
+
+typedef int agps_notify_type;
+#define AGPS_NOTIFY_TYPE_NONE 0
+#define AGPS_NOTIFY_TYPE_NOTIFY_ONLY 1
+#define AGPS_NOTIFY_TYPE_NOTIFY_ALLOW_NO_ANSWER 2
+#define AGPS_NOTIFY_TYPE_NOTIFY_DENY_NO_ANSWER 3
+#define AGPS_NOTIFY_TYPE_PRIVACY 4
+
+typedef int ni_encoding_type;
+#define NI_ENCODING_TYPE_NONE 0
+#define NI_ENCODING_TYPE_GSM7 1
+#define NI_ENCODING_TYPE_UTF8 2
+#define NI_ENCODING_TYPE_UCS2 3
+
+/**
+ * Flags that indicate information about the satellite
+ */
+typedef uint8_t gnss_sv_flags;
+#define MTK_GNSS_SV_FLAGS_NONE 0
+#define MTK_GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA (1 << 0)
+#define MTK_GNSS_SV_FLAGS_HAS_ALMANAC_DATA (1 << 1)
+#define MTK_GNSS_SV_FLAGS_USED_IN_FIX (1 << 2)
+
+typedef unsigned int loc_type;
+#define MTK_LOC_TYPE_AGPS_AFLT 0 // From C2K AFLT flow
+#define MTK_LOC_TYPE_AGPS_CDMA_CELL 1 // From C2K Cell
+#define MTK_LOC_TYPE_AGPS_MOLR_BEGIN_RSP 2 // For CP MOLR after UE provides MSA result, the network will send CISS_FACILITY to provide UE a MSA location. Refer to 3GPP TS37.571-2 7.2.2.2
+#define MTK_LOC_TYPE_AGPS_SUPL_END 3 // From the SUPL END in a supl session. It may be the result of MSA, E-CID, OTDOA, or their hybrid.
+#define MTK_LOC_TYPE_AGPS_SUPL_REF_LOC 4 // For Reference Location assistance data in SUPL flow (equivalent to PMTK713 in SUPL flow)
+#define MTK_LOC_TYPE_AGPS_CP_REF_LOC 5 // For Reference Location assistance data in CP AGPS flow (equivalent to PMTK713 in CP AGPS flow)
+#define MTK_LOC_TYPE_GNSS_STANDALONE 0xfe // GNSS Standalone
+#define MTK_LOC_TYPE_GNSS_UNKNOWN 0xff // Unknown
+
+typedef struct {
+ gps_location_flags flags;
+ double lat;
+ double lng;
+ double alt;
+ float speed;
+ float bearing;
+ float h_accuracy; //horizontal
+ float v_accuracy; //vertical
+ float s_accuracy; //spedd
+ float b_accuracy; //bearing
+ int64_t timestamp;
+ float pdop;
+ float hdop;
+ float vdop;
+ loc_type type;
+} gps_location;
+
+typedef struct {
+ int16_t svid;
+ uint8_t constellation;
+ float c_n0_dbhz;
+ float elevation;
+ float azimuth;
+ gnss_sv_flags flags;
+ float carrier_frequency; //Hz
+ double basebandCN0DbHz;
+} gnss_sv;
+
+typedef struct {
+ int num_svs;
+ gnss_sv sv_list[MTK_HAL_GNSS_MAX_SVS];
+} gnss_sv_info;
+
+typedef struct {
+ int prn;
+ bool has_ephemeris_data;
+ bool has_almanac_data;
+ bool used_in_fix;
+} NmeaCash;
+
+typedef uint16_t mtk_hal_navigation_message_status;
+#define MTK_NAV_MESSAGE_STATUS_UNKNOWN 0
+#define MTK_NAV_MESSAGE_STATUS_PARITY_PASSED (1<<0)
+#define MTK_NAV_MESSAGE_STATUS_PARITY_REBUILT (1<<1)
+
+typedef int16_t mtk_hal_gnss_navigation_message_type;
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN 0
+/** GPS L1 C/A message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA 0x0101
+/** GPS L2-CNAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV 0x0102
+/** GPS L5-CNAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV 0x0103
+/** GPS CNAV-2 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2 0x0104
+/** Glonass L1 CA message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA 0x0301
+/** Beidou D1 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1 0x0501
+/** Beidou D2 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2 0x0502
+/** Galileo I/NAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I 0x0601
+/** Galileo F/NAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F 0x0602
+
+typedef uint8_t mtk_hal_gnss_multipath_indicator;
+/** The indicator is not available or unknown. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_UNKNOWN 0
+/** The measurement is indicated to be affected by multipath. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_PRESENT 1
+/** The measurement is indicated to be not affected by multipath. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_NOT_PRESENT 2
+
+typedef uint16_t mtk_hal_gnss_accumulated_delta_range_state;
+#define MTK_GNSS_ADR_STATE_UNKNOWN 0
+#define MTK_GNSS_ADR_STATE_VALID (1<<0)
+#define MTK_GNSS_ADR_STATE_RESET (1<<1)
+#define MTK_GNSS_ADR_STATE_CYCLE_SLIP (1<<2)
+
+typedef uint32_t mtk_hal_gnss_measurement_state;
+#define MTK_GNSS_MEASUREMENT_STATE_UNKNOWN 0
+#define MTK_GNSS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define MTK_GNSS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define MTK_GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define MTK_GNSS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+#define MTK_GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4)
+#define MTK_GNSS_MEASUREMENT_STATE_SYMBOL_SYNC (1<<5)
+#define MTK_GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC (1<<6)
+#define MTK_GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED (1<<7)
+#define MTK_GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC (1<<8)
+#define MTK_GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC (1<<9)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK (1<<10)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK (1<<11)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC (1<<12)
+#define MTK_GNSS_MEASUREMENT_STATE_SBAS_SYNC (1<<13)
+
+typedef uint8_t mtk_hal_gnss_constellation_type;
+#define MTK_GNSS_CONSTELLATION_UNKNOWN 0
+#define MTK_GNSS_CONSTELLATION_GPS 1
+#define MTK_GNSS_CONSTELLATION_SBAS 2
+#define MTK_GNSS_CONSTELLATION_GLONASS 3
+#define MTK_GNSS_CONSTELLATION_QZSS 4
+#define MTK_GNSS_CONSTELLATION_BEIDOU 5
+#define MTK_GNSS_CONSTELLATION_GALILEO 6
+#define MTK_GNSS_CONSTELLATION_IRNSS 7
+
+typedef uint32_t mtk_hal_gnss_measurement_flags;
+/** A valid 'snr' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_SNR (1<<0)
+/** A valid 'carrier frequency' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9)
+/** A valid 'carrier cycles' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10)
+/** A valid 'carrier phase' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11)
+/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12)
+
+typedef uint16_t mtk_hal_gnss_clock_flags;
+/** A valid 'leap second' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_LEAP_SECOND (1<<0)
+/** A valid 'time uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_TIME_UNCERTAINTY (1<<1)
+/** A valid 'full bias' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_FULL_BIAS (1<<2)
+/** A valid 'bias' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_BIAS (1<<3)
+/** A valid 'bias uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_BIAS_UNCERTAINTY (1<<4)
+/** A valid 'drift' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_DRIFT (1<<5)
+/** A valid 'drift uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY (1<<6)
+
+typedef struct {
+ /** A set of flags indicating the validity of the fields in this data structure. */
+ gps_clock_flags flags;
+
+ /**
+ * Leap second data.
+ * The sign of the value is defined by the following equation:
+ * utc_time_ns = time_ns + (full_bias_ns + bias_ns) - leap_second * 1,000,000,000
+ *
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_LEAP_SECOND.
+ */
+ short leap_second;
+
+ /**
+ * Indicates the type of time reported by the 'time_ns' field.
+ */
+ gps_clock_type type;
+
+ /**
+ * The GPS receiver internal clock value. This can be either the local hardware clock value
+ * (GPS_CLOCK_TYPE_LOCAL_HW_TIME), or the current GPS time derived inside GPS receiver
+ * (GPS_CLOCK_TYPE_GPS_TIME). The field 'type' defines the time reported.
+ *
+ * For local hardware clock, this value is expected to be monotonically increasing during
+ * the reporting session. The real GPS time can be derived by compensating the 'full bias'
+ * (when it is available) from this value.
+ *
+ * For GPS time, this value is expected to be the best estimation of current GPS time that GPS
+ * receiver can achieve. Set the 'time uncertainty' appropriately when GPS time is specified.
+ *
+ * Sub-nanosecond accuracy can be provided by means of the 'bias' field.
+ * The value contains the 'time uncertainty' in it.
+ */
+ int64_t time_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * This value should be set if GPS_CLOCK_TYPE_GPS_TIME is set.
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_TIME_UNCERTAINTY.
+ */
+ double time_uncertainty_ns;
+
+ /**
+ * The difference between hardware clock ('time' field) inside GPS receiver and the true GPS
+ * time since 0000Z, January 6, 1980, in nanoseconds.
+ * This value is used if and only if GPS_CLOCK_TYPE_LOCAL_HW_TIME is set, and GPS receiver
+ * has solved the clock for GPS time.
+ * The caller is responsible for using the 'bias uncertainty' field for quality check.
+ *
+ * The sign of the value is defined by the following equation:
+ * true time (GPS time) = time_ns + (full_bias_ns + bias_ns)
+ *
+ * This value contains the 'bias uncertainty' in it.
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_FULL_BIAS.
+
+ */
+ int64_t full_bias_ns;
+
+ /**
+ * Sub-nanosecond bias.
+ * The value contains the 'bias uncertainty' in it.
+ *
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_BIAS.
+ */
+ double bias_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's bias in nanoseconds.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_BIAS_UNCERTAINTY.
+ */
+ double bias_uncertainty_ns;
+
+ /**
+ * The clock's drift in nanoseconds (per second).
+ * A positive value means that the frequency is higher than the nominal frequency.
+ *
+ * The value contains the 'drift uncertainty' in it.
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_DRIFT.
+ *
+ * If GpsMeasurement's 'flags' field contains GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE,
+ * it is encouraged that this field is also provided.
+ */
+ double drift_nsps;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_DRIFT_UNCERTAINTY.
+ */
+ double drift_uncertainty_nsps;
+} gps_clock;
+
+typedef struct {
+ mtk_hal_gnss_constellation_type constellation;
+ double carrierFrequencyHz;
+ uint8_t codeType[8];
+}MTK_GnssSignalType;
+/**
+ * Represents an estimate of the GPS clock time.
+ */
+typedef struct {
+ /**
+ * A set of flags indicating the validity of the fields in this data
+ * structure.
+ */
+ mtk_hal_gnss_clock_flags flags;
+
+ /**
+ * Leap second data.
+ * The sign of the value is defined by the following equation:
+ * utc_time_ns = time_ns - (full_bias_ns + bias_ns) - leap_second *
+ * 1,000,000,000
+ *
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_LEAP_SECOND.
+ */
+ int16_t leap_second;
+
+ /**
+ * The GNSS receiver internal clock value. This is the local hardware clock
+ * value.
+ *
+ * For local hardware clock, this value is expected to be monotonically
+ * increasing while the hardware clock remains power on. (For the case of a
+ * HW clock that is not continuously on, see the
+ * hw_clock_discontinuity_count field). The receiver's estimate of GPS time
+ * can be derived by substracting the sum of full_bias_ns and bias_ns (when
+ * available) from this value.
+ *
+ * This GPS time is expected to be the best estimate of current GPS time
+ * that GNSS receiver can achieve.
+ *
+ * Sub-nanosecond accuracy can be provided by means of the 'bias_ns' field.
+ * The value contains the 'time uncertainty' in it.
+ *
+ * This field is mandatory.
+ */
+ int64_t time_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_CLOCK_HAS_TIME_UNCERTAINTY. This value is effectively zero (it is
+ * the reference local clock, by which all other times and time
+ * uncertainties are measured.) (And thus this field can be not provided,
+ * per GNSS_CLOCK_HAS_TIME_UNCERTAINTY flag, or provided & set to 0.)
+ */
+ double time_uncertainty_ns;
+
+ /**
+ * The difference between hardware clock ('time' field) inside GPS receiver
+ * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
+ *
+ * The sign of the value is defined by the following equation:
+ * local estimate of GPS time = time_ns - (full_bias_ns + bias_ns)
+ *
+ * This value is mandatory if the receiver has estimated GPS time. If the
+ * computed time is for a non-GPS constellation, the time offset of that
+ * constellation to GPS has to be applied to fill this value. The error
+ * estimate for the sum of this and the bias_ns is the bias_uncertainty_ns,
+ * and the caller is responsible for using this uncertainty (it can be very
+ * large before the GPS time has been solved for.) If the data is available
+ * 'flags' must contain GNSS_CLOCK_HAS_FULL_BIAS.
+ */
+ int64_t full_bias_ns;
+
+ /**
+ * Sub-nanosecond bias.
+ * The error estimate for the sum of this and the full_bias_ns is the
+ * bias_uncertainty_ns
+ *
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_BIAS. If GPS
+ * has computed a position fix. This value is mandatory if the receiver has
+ * estimated GPS time.
+ */
+ double bias_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the local estimate of GPS time (clock
+ * bias) in nanoseconds. The uncertainty is represented as an absolute
+ * (single sided) value.
+ *
+ * If the data is available 'flags' must contain
+ * GNSS_CLOCK_HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+ * has estimated GPS time.
+ */
+ double bias_uncertainty_ns;
+
+ /**
+ * The clock's drift in nanoseconds (per second).
+ *
+ * A positive value means that the frequency is higher than the nominal
+ * frequency, and that the (full_bias_ns + bias_ns) is growing more positive
+ * over time.
+ *
+ * The value contains the 'drift uncertainty' in it.
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_DRIFT.
+ *
+ * This value is mandatory if the receiver has estimated GNSS time
+ */
+ double drift_nsps;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available 'flags' must contain
+ * GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY. If GPS has computed a position fix this
+ * field is mandatory and must be populated.
+ */
+ double drift_uncertainty_nsps;
+
+ /**
+ * When there are any discontinuities in the HW clock, this field is
+ * mandatory.
+ *
+ * A "discontinuity" is meant to cover the case of a switch from one source
+ * of clock to another. A single free-running crystal oscillator (XO)
+ * should generally not have any discontinuities, and this can be set and
+ * left at 0.
+ *
+ * If, however, the time_ns value (HW clock) is derived from a composite of
+ * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+ * restarted, then this value shall be incremented each time a discontinuity
+ * occurs. (E.g. this value may start at zero at device boot-up and
+ * increment each time there is a change in clock continuity. In the
+ * unlikely event that this value reaches full scale, rollover (not
+ * clamping) is required, such that this value continues to change, during
+ * subsequent discontinuity events.)
+ *
+ * While this number stays the same, between GnssClock reports, it can be
+ * safely assumed that the time_ns value has been running continuously, e.g.
+ * derived from a single, high quality clock (XO like, or better, that's
+ * typically used during continuous GNSS signal sampling.)
+ *
+ * It is expected, esp. during periods where there are few GNSS signals
+ * available, that the HW clock be discontinuity-free as long as possible,
+ * as this avoids the need to use (waste) a GNSS measurement to fully
+ * re-solve for the GPS clock bias and drift, when using the accompanying
+ * measurements, from consecutive GnssData reports.
+ */
+ uint32_t hw_clock_discontinuity_count;
+ MTK_GnssSignalType referenceSignalTypeForIsb;
+} gnss_clock;
+
+typedef struct {
+ /** A set of flags indicating the validity of the fields in this data structure. */
+ gps_measurement_flags flags;
+
+ /**
+ * Pseudo-random number in the range of [1, 32]
+ * This is a Mandatory value.
+ */
+ int8_t prn;
+
+ /**
+ * Time offset at which the measurement was taken in nanoseconds.
+ * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+ * interpreted in the same way as indicated by GpsClock::type.
+ *
+ * The sign of time_offset_ns is given by the following equation:
+ * measurement time = GpsClock::time_ns + time_offset_ns
+ *
+ * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+ * This is a Mandatory value.
+ */
+ double time_offset_ns;
+
+ /**
+ * Per satellite sync state. It represents the current sync state for the associated satellite.
+ * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+ * This is a Mandatory value.
+ */
+ gps_measurement_state state;
+
+ /**
+ * Received GPS Time-of-Week at the measurement time, in nanoseconds.
+ * The value is relative to the beginning of the current GPS week.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : GPS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : GPS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync : [ 0 20ms ] : GPS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe sync : [ 0 6s ] : GPS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * TOW decoded : [ 0 1week ] : GPS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * However, if there is any ambiguity in integer millisecond,
+ * GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+ * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+ */
+ int64_t received_gps_tow_ns;
+
+ /**
+ * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+ * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+ */
+ int64_t received_gps_tow_uncertainty_ns;
+
+ /**
+ * Carrier-to-noise density in dB-Hz, in the range [0, 63].
+ * It contains the measured C/N0 value for the signal at the antenna input.
+ * This is a Mandatory value.
+ */
+ double c_n0_dbhz;
+
+ /**
+ * Pseudorange rate at the timestamp in m/s.
+ * The value also includes the effects of the receiver clock frequency and satellite clock
+ * frequency errors.
+ *
+ * The value includes the 'pseudorange rate uncertainty' in it.
+ * A positive value indicates that the pseudorange is getting larger.
+ * This is a Mandatory value.
+ */
+ double pseudorange_rate_mps;
+
+ /**
+ * 1-Sigma uncertainty of the pseudurange rate in m/s.
+ * The uncertainty is represented as an absolute (single sided) value.
+ * This is a Mandatory value.
+ */
+ double pseudorange_rate_uncertainty_mps;
+
+ /**
+ * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+ * (indicating loss of lock).
+ * This is a Mandatory value.
+ */
+ gps_accumulated_delta_range_state accumulated_delta_range_state;
+
+ /**
+ * Accumulated delta range since the last channel reset in meters.
+ * A positive value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+ * is given by the equation:
+ * accumulated delta range = -k * carrier phase (where k is a constant)
+ *
+ * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ * However, it is expected that the data is only accurate when:
+ * 'accumulated delta range state' == GPS_ADR_STATE_VALID.
+ */
+ double accumulated_delta_range_m;
+
+ /**
+ * 1-Sigma uncertainty of the accumulated delta range in meters.
+ * The data is available if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ */
+ double accumulated_delta_range_uncertainty_m;
+
+ /**
+ * Best derived Pseudorange by the chip-set, in meters.
+ * The value contains the 'pseudorange uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_PSEUDORANGE.
+ */
+ double pseudorange_m;
+
+ /**
+ * 1-Sigma uncertainty of the pseudorange in meters.
+ * The value contains the 'pseudorange' and 'clock' uncertainty in it.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY.
+ */
+ double pseudorange_uncertainty_m;
+
+ /**
+ * A fraction of the current C/A code cycle, in the range [0.0, 1023.0]
+ * This value contains the time (in Chip units) since the last C/A code cycle (GPS Msec epoch).
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'code-phase uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CODE_PHASE.
+ */
+ double code_phase_chips;
+
+ /**
+ * 1-Sigma uncertainty of the code-phase, in a fraction of chips.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY.
+ */
+ double code_phase_uncertainty_chips;
+
+ /**
+ * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+ * If the field is not set, the carrier frequency is assumed to be L1.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+ */
+ float carrier_frequency_hz;
+
+ /**
+ * The number of full carrier cycles between the satellite and the receiver.
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_CYCLES.
+ */
+ int64_t carrier_cycles;
+
+ /**
+ * The RF phase detected by the receiver, in the range [0.0, 1.0].
+ * This is usually the fractional part of the complete carrier phase measurement.
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'carrier-phase uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_PHASE.
+ */
+ double carrier_phase;
+
+ /**
+ * 1-Sigma uncertainty of the carrier-phase.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+ */
+ double carrier_phase_uncertainty;
+
+ /**
+ * An enumeration that indicates the 'loss of lock' state of the event.
+ */
+ gps_loss_of_lock loss_of_lock;
+
+ /**
+ * The number of GPS bits transmitted since Sat-Sun midnight (GPS week).
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_BIT_NUMBER.
+ */
+ int32_t bit_number;
+
+ /**
+ * The elapsed time since the last received bit in milliseconds, in the range [0, 20]
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT.
+ */
+ int16_t time_from_last_bit_ms;
+
+ /**
+ * Doppler shift in Hz.
+ * A positive value indicates that the SV is moving toward the receiver.
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'doppler shift uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_DOPPLER_SHIFT.
+ */
+ double doppler_shift_hz;
+
+ /**
+ * 1-Sigma uncertainty of the doppler shift in Hz.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY.
+ */
+ double doppler_shift_uncertainty_hz;
+
+ /**
+ * An enumeration that indicates the 'multipath' state of the event.
+ */
+ gps_multipath_indicator multipath_indicator;
+
+ /**
+ * Signal-to-noise ratio in dB.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_SNR.
+ */
+ double snr_db;
+
+ /**
+ * Elevation in degrees, the valid range is [-90, 90].
+ * The value contains the 'elevation uncertainty' in it.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_ELEVATION.
+ */
+ double elevation_deg;
+
+ /**
+ * 1-Sigma uncertainty of the elevation in degrees, the valid range is [0, 90].
+ * The uncertainty is represented as the absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY.
+ */
+ double elevation_uncertainty_deg;
+
+ /**
+ * Azimuth in degrees, in the range [0, 360).
+ * The value contains the 'azimuth uncertainty' in it.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_AZIMUTH.
+ * */
+ double azimuth_deg;
+
+ /**
+ * 1-Sigma uncertainty of the azimuth in degrees, the valid range is [0, 180].
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY.
+ */
+ double azimuth_uncertainty_deg;
+
+ /**
+ * Whether the GPS represented by the measurement was used for computing the most recent fix.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_USED_IN_FIX.
+ */
+ bool used_in_fix;
+} gps_measurement;
+
+/**
+ * Represents a GNSS Measurement, it contains raw and computed information.
+ *
+ * Independence - All signal measurement information (e.g. sv_time,
+ * pseudorange_rate, multipath_indicator) reported in this struct should be
+ * based on GNSS signal measurements only. You may not synthesize measurements
+ * by calculating or reporting expected measurements based on known or estimated
+ * position, velocity, or time.
+ */
+typedef struct {
+ /** A set of flags indicating the validity of the fields in this data structure. */
+ mtk_hal_gnss_measurement_flags flags;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ * This is a mandatory value.
+ */
+ int16_t svid;
+
+ /**
+ * Defines the constellation of the given SV. Value should be one of those
+ * GNSS_CONSTELLATION_* constants
+ */
+ mtk_hal_gnss_constellation_type constellation;
+
+ /**
+ * Time offset at which the measurement was taken in nanoseconds.
+ * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+ * interpreted in the same way as indicated by GpsClock::type.
+ *
+ * The sign of time_offset_ns is given by the following equation:
+ * measurement time = GpsClock::time_ns + time_offset_ns
+ *
+ * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+ * This is a mandatory value.
+ */
+ double time_offset_ns;
+
+ /**
+ * Per satellite sync state. It represents the current sync state for the associated satellite.
+ * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+ *
+ * This is a mandatory value.
+ */
+ mtk_hal_gnss_measurement_state state;
+
+ /**
+ * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+ * Ensure that this field is independent (see comment at top of
+ * GnssMeasurement struct.)
+ *
+ * For GPS & QZSS, this is:
+ * Received GPS Time-of-Week at the measurement time, in nanoseconds.
+ * The value is relative to the beginning of the current GPS week.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range
+ * for this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync : [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe sync : [ 0 6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * TOW decoded : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * Note well: if there is any ambiguity in integer millisecond,
+ * GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+ *
+ * This value must be populated if 'state' != GNSS_MEASUREMENT_STATE_UNKNOWN.
+ *
+ * For Glonass, this is:
+ * Received Glonass time of day, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 10ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+ * Bit sync : [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * String sync : [ 0 2s ] : GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC is set
+ * Time of day : [ 0 1day ] : GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED is set
+ *
+ * For Beidou, this is:
+ * Received Beidou time of week, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync (D2): [ 0 2ms ] : GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC is set
+ * Bit sync (D1): [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe (D2): [ 0 0.6s ] : GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC is set
+ * Subframe (D1): [ 0 6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * Time of week : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * For Galileo, this is:
+ * Received Galileo time of week, at the measurement time in nanoseconds.
+ *
+ * E1BC code lock : [ 0 4ms ] : GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK is set
+ * E1C 2nd code lock: [ 0 100ms ] :
+ * GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is set
+ *
+ * E1B page : [ 0 2s ] : GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC is set
+ * Time of week: [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * For SBAS, this is:
+ * Received SBAS time, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite,
+ * valid range for this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 2ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+ * Message : [ 0 1s ] : GNSS_MEASUREMENT_STATE_SBAS_SYNC is set
+ */
+ int64_t received_sv_time_in_ns;
+
+ /**
+ * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+ *
+ * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+ */
+ int64_t received_sv_time_uncertainty_in_ns;
+
+ /**
+ * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+ * It contains the measured C/N0 value for the signal at the antenna port.
+ *
+ * This is a mandatory value.
+ */
+ double c_n0_dbhz;
+
+ /**
+ * Pseudorange rate at the timestamp in m/s. The correction of a given
+ * Pseudorange Rate value includes corrections for receiver and satellite
+ * clock frequency errors. Ensure that this field is independent (see
+ * comment at top of GnssMeasurement struct.)
+ *
+ * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
+ * 'drift' field as well (When providing the uncorrected pseudorange rate, do not apply the
+ * corrections described above.)
+ *
+ * The value includes the 'pseudorange rate uncertainty' in it.
+ * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler
+ * shift' is given by the equation:
+ * pseudorange rate = -k * doppler shift (where k is a constant)
+ *
+ * This should be the most accurate pseudorange rate available, based on
+ * fresh signal measurements from this channel.
+ *
+ * It is mandatory that this value be provided at typical carrier phase PRR
+ * quality (few cm/sec per second of uncertainty, or better) - when signals
+ * are sufficiently strong & stable, e.g. signals from a GPS simulator at >=
+ * 35 dB-Hz.
+ */
+ double pseudorange_rate_mps;
+
+ /**
+ * 1-Sigma uncertainty of the pseudorange_rate_mps.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * This is a mandatory value.
+ */
+ double pseudorange_rate_uncertainty_mps;
+
+ /**
+ * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+ * (indicating loss of lock).
+ *
+ * This is a mandatory value.
+ */
+ mtk_hal_gnss_accumulated_delta_range_state accumulated_delta_range_state;
+
+ /**
+ * Accumulated delta range since the last channel reset in meters.
+ * A positive value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+ * is given by the equation:
+ * accumulated delta range = -k * carrier phase (where k is a constant)
+ *
+ * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ * However, it is expected that the data is only accurate when:
+ * 'accumulated delta range state' == GPS_ADR_STATE_VALID.
+ */
+ double accumulated_delta_range_m;
+
+ /**
+ * 1-Sigma uncertainty of the accumulated delta range in meters.
+ * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ */
+ double accumulated_delta_range_uncertainty_m;
+
+ /**
+ * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+ * If the field is not set, the carrier frequency is assumed to be L1.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+ */
+ float carrier_frequency_hz;
+
+ /**
+ * The number of full carrier cycles between the satellite and the receiver.
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * Indications of possible cycle slips and resets in the accumulation of
+ * this value can be inferred from the accumulated_delta_range_state flags.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
+ */
+ int64_t carrier_cycles;
+
+ /**
+ * The RF phase detected by the receiver, in the range [0.0, 1.0].
+ * This is usually the fractional part of the complete carrier phase measurement.
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'carrier-phase uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_PHASE.
+ */
+ double carrier_phase;
+
+ /**
+ * 1-Sigma uncertainty of the carrier-phase.
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+ */
+ double carrier_phase_uncertainty;
+
+ /**
+ * An enumeration that indicates the 'multipath' state of the event.
+ *
+ * The multipath Indicator is intended to report the presence of overlapping
+ * signals that manifest as distorted correlation peaks.
+ *
+ * - if there is a distorted correlation peak shape, report that multipath
+ * is GNSS_MULTIPATH_INDICATOR_PRESENT.
+ * - if there is not a distorted correlation peak shape, report
+ * GNSS_MULTIPATH_INDICATOR_NOT_PRESENT
+ * - if signals are too weak to discern this information, report
+ * GNSS_MULTIPATH_INDICATOR_UNKNOWN
+ *
+ * Example: when doing the standardized overlapping Multipath Performance
+ * test (3GPP TS 34.171) the Multipath indicator should report
+ * GNSS_MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+ * contain multipath, and GNSS_MULTIPATH_INDICATOR_NOT_PRESENT for those
+ * signals that are tracked and do not contain multipath.
+ */
+ mtk_hal_gnss_multipath_indicator multipath_indicator;
+
+ /**
+ * Signal-to-noise ratio at correlator output in dB.
+ * If the data is available, 'flags' must contain GNSS_MEASUREMENT_HAS_SNR.
+ * This is the power ratio of the "correlation peak height above the
+ * observed noise floor" to "the noise RMS".
+ */
+ double snr_db;
+ /**
+ * The full inter-signal bias (ISB) in nanoseconds.
+ *
+ * This value is the sum of the estimated receiver-side and the space-segment-side
+ * inter-system bias, inter-frequency bias and inter-code bias, including
+ *
+ * - Receiver inter-constellation bias (with respect to the constellation in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Receiver inter-frequency bias (with respect to the carrier frequency in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Receiver inter-code bias (with respect to the code type in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPS-UTC Time Offset
+ * (TauGps), BDS-GLO Time Offset (BGTO)) (with respect to the constellation in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Group delay (e.g., Total Group Delay (TGD))
+ * - Satellite inter-frequency bias (GLO only) (with respect to the carrier frequency in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Satellite inter-code bias (e.g., Differential Code Bias (DCB)) (with respect to the
+ * code type in GnssClock.referenceSignalTypeForIsb)
+ *
+ * If a component of the above is already compensated in the provided
+ * GnssMeasurement.receivedSvTimeInNs, then it must not be included in the reported full
+ * ISB.
+ *
+ * The value does not include the inter-frequency Ionospheric bias.
+ *
+ * The full ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
+ */
+ double fullInterSignalBiasNs;
+ /**
+ * 1-sigma uncertainty associated with the full inter-signal bias in nanoseconds.
+ */
+ double fullInterSignalBiasUncertaintyNs;
+ /**
+ * The satellite inter-signal bias in nanoseconds.
+ *
+ * This value is the satellite-and-control-segment-side inter-system (different from the
+ * constellation in GnssClock.referenceSignalTypeForIsb) bias and inter-frequency (different
+ * from the carrier frequency in GnssClock.referenceSignalTypeForIsb) bias, including:
+ *
+ * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPT-UTC Time Offset (TauGps),
+ * BDS-GLO Time Offset (BGTO))
+ * - Group delay (e.g., Total Group Delay (TGD))
+ * - Satellite inter-signal bias, which includes satellite inter-frequency bias (GLO only),
+ * and satellite inter-code bias (e.g., Differential Code Bias (DCB)).
+ *
+ * The receiver ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
+ */
+ double satelliteInterSignalBiasNs;
+ /**
+ * 1-sigma uncertainty associated with the satellite inter-signal bias in nanoseconds.
+ */
+ double satelliteInterSignalBiasUncertaintyNs;
+ /**
+ * Baseband Carrier-to-noise density in dB-Hz, typically in the range [0, 63]. It contains
+ * the measured C/N0 value for the signal measured at the baseband.
+ *
+ * This is typically a few dB weaker than the value estimated for C/N0 at the antenna port,
+ * which is reported in cN0DbHz.
+ *
+ * If a signal has separate components (e.g. Pilot and Data channels) and the receiver only
+ * processes one of the components, then the reported basebandCN0DbHz reflects only the
+ * component that is processed.
+ *
+ * This value is mandatory.
+ */
+ double basebandCN0DbHz;
+
+ /**
+ * Automatic gain control (AGC) level. AGC acts as a variable gain
+ * amplifier adjusting the power of the incoming signal. The AGC level
+ * may be used to indicate potential interference. When AGC is at a
+ * nominal level, this value must be set as 0. Higher gain (and/or lower
+ * input power) must be output as a positive number. Hence in cases of
+ * strong jamming, in the band of this signal, this value must go more
+ * negative.
+ */
+ double agc_level_db;
+
+ /// v2.0
+ char code_type[8];
+} gnss_measurement;
+
+typedef struct {
+ /** Number of measurements. */
+ size_t measurement_count;
+
+ /** The array of measurements. */
+ gps_measurement measurements[GPS_MAX_MEASUREMENT];
+
+ /** The GPS clock time reading. */
+ gps_clock clock;
+} gps_data;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+ /** Number of measurements. */
+ size_t measurement_count;
+
+ /** The array of measurements. */
+ gnss_measurement measurements[MTK_HAL_GNSS_MAX_MEASUREMENT];
+
+ /** The GPS clock time reading. */
+ gnss_clock clock;
+} gnss_data;
+
+#define MAX_NAV_DATA_LEN 40
+
+typedef struct {
+ /**
+ * Pseudo-random number in the range of [1, 32]
+ * This is a Mandatory value.
+ */
+ int8_t prn;
+
+ /**
+ * The type of message contained in the structure.
+ * This is a Mandatory value.
+ */
+ gps_nav_msg_type type;
+
+ /**
+ * The status of the received navigation message.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+ nav_msg_status status;
+
+ /**
+ * Message identifier.
+ * It provides an index so the complete Navigation Message can be assembled. i.e. fo L1 C/A
+ * subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message.
+ * Subframe 1, 2, 3 does not contain a 'frame id' and this value can be set to -1.
+ */
+ short message_id;
+
+ /**
+ * Sub-message identifier.
+ * If required by the message 'type', this value contains a sub-index within the current
+ * message (or frame) that is being transmitted.
+ * i.e. for L1 C/A the submessage id corresponds to the sub-frame id of the navigation message.
+ */
+ short submessage_id;
+
+ /**
+ * The length of the data (in bytes) contained in the current message.
+ * If this value is different from zero, 'data' must point to an array of the same size.
+ * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+ * This is a Mandatory value.
+ */
+ size_t data_length;
+
+ /**
+ * The data of the reported GPS message.
+ * The bytes (or words) specified using big endian format (MSB first).
+ *
+ * For L1 C/A, each subframe contains 10 30-bit GPS words. Each GPS word (30 bits) should be
+ * fitted into the last 30 bits in a 4-byte word (skip B31 and B32), with MSB first.
+ */
+ char data[MAX_NAV_DATA_LEN];
+} gps_nav_msg;
+
+/** Represents a GPS navigation message (or a fragment of it). */
+typedef struct {
+ /** set to sizeof(GnssNavigationMessage) */
+ size_t size;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ * This is a mandatory value.
+ */
+ int16_t svid;
+
+ /**
+ * The type of message contained in the structure.
+ * This is a mandatory value.
+ */
+ mtk_hal_gnss_navigation_message_type type;
+
+ /**
+ * The status of the received navigation message.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+ mtk_hal_navigation_message_status status;
+
+ /**
+ * Message identifier. It provides an index so the complete Navigation
+ * Message can be assembled.
+ *
+ * - For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+ * id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+ * does not contain a 'frame id' and this value can be set to -1.)
+ *
+ * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+ *
+ * - For BeiDou D1, this refers to the frame number in the range of 1-24
+ *
+ * - For Beidou D2, this refers to the frame number, in the range of 1-120
+ *
+ * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+ * number, in the range of 1-12
+ *
+ * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+ * number in the range of 1-24
+ */
+ int16_t message_id;
+
+ /**
+ * Sub-message identifier. If required by the message 'type', this value
+ * contains a sub-index within the current message (or frame) that is being
+ * transmitted.
+ *
+ * - For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to
+ * the subframe number of the navigation message, in the range of 1-5.
+ *
+ * - For Glonass L1 C/A, this refers to the String number, in the range from
+ * 1-15
+ *
+ * - For Galileo F/NAV, this refers to the page type in the range 1-6
+ *
+ * - For Galileo I/NAV, this refers to the word type in the range 1-10+
+ */
+ int16_t submessage_id;
+
+ /**
+ * The length of the data (in bytes) contained in the current message.
+ * If this value is different from zero, 'data' must point to an array of the same size.
+ * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+ *
+ * This is a mandatory value.
+ */
+ size_t data_length;
+
+ /**
+ * The data of the reported GPS message. The bytes (or words) specified
+ * using big endian format (MSB first).
+ *
+ * - For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+ * words. Each word (30 bits) should be fit into the last 30 bits in a
+ * 4-byte word (skip B31 and B32), with MSB first, for a total of 40
+ * bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
+ *
+ * - For Glonass L1 C/A, each string contains 85 data bits, including the
+ * checksum. These bits should be fit into 11 bytes, with MSB first (skip
+ * B86-B88), covering a time period of 2 seconds.
+ *
+ * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+ * excluded). Each word should be fit into 30-bytes, with MSB first (skip
+ * B239, B240), covering a time period of 10 seconds.
+ *
+ * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+ * a total of 2x114 = 228 bits, (sync & tail excluded) that should be fit
+ * into 29 bytes, with MSB first (skip B229-B232).
+ */
+ uint8_t data[MAX_NAV_DATA_LEN];
+} gnss_nav_msg;
+
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GNSS_MAX_SVS 64
+
+/**
+ * A struct containing the characteristics of the reflecting plane that the satellite signal has
+ * bounced from.
+ *
+ * The value is only valid if HAS_REFLECTING_PLANE flag is set. An invalid reflecting plane
+ * means either reflection planes serving is not supported or the satellite signal has gone
+ * through multiple reflections.
+ */
+typedef struct {
+ /** Represents latitude of the reflecting plane in degrees. */
+ double latitude_degrees;
+
+ /** Represents longitude of the reflecting plane in degrees. */
+ double longitude_degrees;
+
+ /**
+ * Represents altitude of the reflecting point in the plane in meters above the WGS 84 reference
+ * ellipsoid.
+ */
+ double altitude_meters;
+
+ /** Represents azimuth clockwise from north of the reflecting plane in degrees. */
+ double azimuth_degrees;
+} reflecting_plane ;
+
+typedef struct {
+
+ /** Contains Gnsssingle_sat_correctionFlags bits. */
+ uint16_t single_sat_correctionFlags;
+
+ /**
+ * Defines the constellation of the given satellite.
+ */
+ mtk_hal_gnss_constellation_type constellation;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ */
+ uint16_t svid;
+
+ /**
+ * Carrier frequency of the signal to be corrected, for example it can be the
+ * GPS center frequency for L1 = 1,575,420,000 Hz, varying GLO channels, etc.
+ *
+ * For a receiver with capabilities to track multiple frequencies for the same satellite,
+ * multiple corrections for the same satellite may be provided.
+ */
+ float carrier_frequency_hz;
+
+ /**
+ * The probability that the satellite is estimated to be in Line-of-Sight condition at the given
+ * location.
+ */
+ float prob_satIs_los;
+
+ /**
+ * Excess path length to be subtracted from pseudorange before using it in calculating location.
+ *
+ * Note this value is NOT to be used to adjust the GnssMeasurementCallback outputs.
+ */
+ float excess_path_length_meters;
+
+ /** Error estimate (1-sigma) for the Excess path length estimate */
+ float excess_path_length_uncertainty_meters;
+
+ /**
+ * Defines the reflecting plane characteristics such as location and azimuth
+ *
+ * The value is only valid if HAS_REFLECTING_PLANE flag is set. An invalid reflecting plane
+ * means either reflection planes serving is not supported or the satellite signal has gone
+ * through multiple reflections.
+ */
+ reflecting_plane reflecting_plane;
+}single_sat_correction;
+
+
+/**
+ * A struct containing a set of measurement corrections for all used GNSS satellites at the location
+ * specified by latitude_degrees, longitude_degrees, altitude_meters and at the time of week specified
+ * toa_gps_nanoseconds_of_week
+ */
+typedef struct {
+ /** Represents latitude in degrees at which the corrections are computed.. */
+ double latitude_degrees;
+
+ /** Represents longitude in degrees at which the corrections are computed.. */
+ double longitude_degrees;
+
+ /**
+ * Represents altitude in meters above the WGS 84 reference ellipsoid at which the corrections
+ * are computed.
+ */
+ double altitude_meters;
+
+ /**
+ * Represents the horizontal uncertainty (68% confidence) in meters on the device position at
+ * which the corrections are provided.
+ *
+ * This value is useful for example to judge how accurate the provided corrections are.
+ */
+ double horizontal_position_uncertainty_meters;
+
+ /**
+ * Represents the vertical uncertainty (68% confidence) in meters on the device position at
+ * which the corrections are provided.
+ *
+ * This value is useful for example to judge how accurate the provided corrections are.
+ */
+ double vertical_position_uncertainty_meters;
+
+ /** Time Of Applicability, GPS time of week in nanoseconds. */
+ uint64_t toa_gps_nanoseconds_of_week;
+
+ /** Number of single_sat_correction */
+ size_t num_sat_correction;
+
+ /**
+ * A set of single_sat_correction each containing measurement corrections for a satellite in view
+ */
+ single_sat_correction sat_corrections[GNSS_MAX_SVS];
+} measurement_corrections;
+
+/**
+ * Protocol stack that is requesting the non-framework location information.
+ */
+enum {
+ /** Cellular control plane requests */
+ MNLDINF_CTRL_PLANE = 0,
+ /** All types of SUPL requests */
+ MNLDINF_SUPL = 1,
+
+ /** All types of requests from IMS */
+ MNLDINF_IMS = 10,
+ /** All types of requests from SIM */
+ MNLDINF_SIM = 11,
+
+ /** Requests from other protocol stacks */
+ MNLDINF_OTHER_PROTOCOL_STACK = 100
+};
+typedef uint8_t MNLDINF_NfwProtocolStack;
+
+////////////////////// GNSS HIDL v2.0 ////////////////////////////
+
+#define MNLDINF_STRING_MAXLEN 256
+
+/*
+ * Entity that is requesting/receiving the location information.
+ */
+enum { //mnldinf_nfw_equestor : uint8_t {
+ /** Wireless service provider */
+ MNLDINF_CARRIER = 0,
+ /** Device manufacturer */
+ MNLDINF_OEM = 10,
+ /** Modem chipset vendor */
+ MNLDINF_MODEM_CHIPSET_VENDOR = 11,
+ /** GNSS chipset vendor */
+ MNLDINF_GNSS_CHIPSET_VENDOR = 12,
+ /** Other chipset vendor */
+ MNLDINF_OTHER_CHIPSET_VENDOR = 13,
+ /** Automobile client */
+ MNLDINF_AUTOMOBILE_CLIENT = 20,
+ /** Other sources */
+ MNLDINF_OTHER_REQUESTOR = 100
+ };
+typedef uint8_t mnldinf_nfw_equestor;
+
+/**
+ * GNSS response type for non-framework location requests.
+ */
+enum {//mnldinf_nfw_response_type : uint8_t {
+ /** Request rejected because framework has not given permission for this use case */
+ MNLDINF_REJECTED = 0,
+
+ /** Request accepted but could not provide location because of a failure */
+ MNLDINF_ACCEPTED_NO_LOCATION_PROVIDED = 1,
+
+ /** Request accepted and location provided */
+ MNLDINF_ACCEPTED_LOCATION_PROVIDED = 2,
+};
+typedef uint8_t mnldinf_nfw_response_type;
+
+/**
+ * Represents a non-framework location information request/response notification.
+ */
+typedef struct {
+ /**
+ * Package name of the Android proxy application representing the non-framework
+ * entity that requested location. Set to empty string if unknown.
+ */
+ char proxy_app_package_name[MNLDINF_STRING_MAXLEN];
+
+ /** Protocol stack that initiated the non-framework location request. */
+ MNLDINF_NfwProtocolStack protocol_stack;
+
+ /**
+ * Name of the protocol stack if protocol_stack field is set to OTHER_PROTOCOL_STACK.
+ * Otherwise, set to empty string.
+ *
+ * This field is opaque to the framework and used for logging purposes.
+ */
+ char other_protocol_stack_name[MNLDINF_STRING_MAXLEN];
+
+ /** Source initiating/receiving the location information. */
+ mnldinf_nfw_equestor requestor;
+
+ /**
+ * Identity of the endpoint receiving the location information. For example, carrier
+ * name, OEM name, SUPL SLP/E-SLP FQDN, chipset vendor name, etc.
+ *
+ * This field is opaque to the framework and used for logging purposes.
+ */
+ char requestor_id[MNLDINF_STRING_MAXLEN];
+
+ /** Indicates whether location information was provided for this request. */
+ mnldinf_nfw_response_type response_type;
+
+ /** Is the device in user initiated emergency session. */
+ bool in_emergency_mode;
+
+ /** Is cached location provided */
+ bool is_cached_location;
+} mnldinf_nfw_notification;
+
+/*
+*mnld basic interface support capability.
+*This structure is dedicated for mnld interface's compatibility.
+*MUST upgrade this structure,if Add a new feature or upgrade an uncompatible feature
+*/
+typedef struct {
+ /*An example for initialization version*/
+ bool support_gnss;
+ /**MUST add new support capability to the end**/
+} mnldinf_basic_client_cap;
+
+/*
+*mnld extension interface support capability.
+*This structure is dedicated for mnld interface's compatibility.
+*MUST upgrade this structure,if Add a new feature or upgrade an uncompatible feature
+*/
+typedef struct {
+ /*An example for initialization version*/
+ bool support_gnss;
+ /**MUST add new support capability to the end**/
+} mnldinf_ext_client_cap;
+
+/*
+*mnld server support capability.
+*This structure is dedicated for mnld interface's compatibility.
+*MUST upgrade this structure,if Add a new feature or upgrade an uncompatible feature
+*/
+typedef struct {
+ /*An example for initialization version*/
+ bool support_gnss;
+ /**MUST add new support capability to the end**/
+} mnldinf_basic_server_cap;
+
+/*
+*mnld server support capability.
+*This structure is dedicated for mnld interface's compatibility.
+*MUST upgrade this structure,if Add a new feature or upgrade an uncompatible feature
+*/
+typedef struct {
+ /*An example for initialization version*/
+ bool support_gnss;
+ /**MUST add new support capability to the end**/
+} mnldinf_ext_server_cap;
+
+typedef unsigned int mnldinf_agps_loc_type;
+#define MNLDINF_AGPS_LOC_TYPE_AFLT 0 // From C2K AFLT flow
+#define MNLDINF_AGPS_LOC_TYPE_CDMA_CELL 1 // From C2K Cell
+#define MNLDINF_AGPS_LOC_TYPE_MOLR_BEGIN_RSP 2 // For CP MOLR after UE provides MSA result, the network will send CISS_FACILITY to provide UE a MSA location. Refer to 3GPP TS37.571-2 7.2.2.2
+#define MNLDINF_AGPS_LOC_TYPE_SUPL_END 3 // From the SUPL END in a supl session. It may be the result of MSA, E-CID, OTDOA, or their hybrid.
+#define MNLDINF_AGPS_LOC_TYPE_SUPL_REF_LOC 4 // For Reference Location assistance data in SUPL flow (equivalent to PMTK713 in SUPL flow)
+#define MNLDINF_AGPS_LOC_TYPE_CP_REF_LOC 5 // For Reference Location assistance data in CP AGPS flow (equivalent to PMTK713 in CP AGPS flow)
+#define MNLDINF_AGPS_LOC_TYPE_UNKNOWN 0xff // Unknown
+
+typedef struct {
+ double latitude; // Represents latitude in degrees
+ double longitude; // Represents longitude in degrees
+ char altitude_used; // 0=disabled 1=enabled
+ double altitude; // Represents altitude in meters above the WGS 84 reference
+ char speed_used; // 0=disabled 1=enabled
+ float speed; // Represents speed in meters per second
+ char bearing_used; // 0=disabled 1=enabled
+ float bearing; // Represents heading in degrees
+ char accuracy_used; // 0=disabled 1=enabled
+ float accuracy; // Represents expected accuracy in meters
+ char timestamp_used; // 0=disabled 1=enabled
+ long long timestamp; // Milliseconds since January 1, 1970
+ char type_used; // 0=disabled 1=enabled
+ mnldinf_agps_loc_type type; // Reference location source type
+} mnldinf_agps_location;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_data_coder.h b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_data_coder.h
new file mode 100755
index 0000000..f534d19
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_data_coder.h
@@ -0,0 +1,32 @@
+#ifndef __MNLDINF_DATA_CODER_H__
+#define __MNLDINF_DATA_CODER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char mnldinf_get_byte(char* buff, int* offset, int src_len);
+short mnldinf_get_short(char* buff, int* offset, int src_len);
+int mnldinf_get_int(char* buff, int* offset, int src_len);
+long long mnldinf_get_long(char* buff, int* offset, int src_len);
+float mnldinf_get_float(char* buff, int* offset, int src_len);
+double mnldinf_get_double(char* buff, int* offset, int src_len);
+char* mnldinf_get_string(char* buff, int* offset, int src_len);
+char* mnldinf_get_string2(char* buff, int* offset, int src_len);
+int mnldinf_get_binary(char* buff, int* offset, char* output, int src_len, int des_len);
+
+void mnldinf_put_byte(char* buff, int* offset, const char input);
+void mnldinf_put_short(char* buff, int* offset, const short input);
+void mnldinf_put_int(char* buff, int* offset, const int input);
+void mnldinf_put_long(char* buff, int* offset, const long long input);
+void mnldinf_put_float(char* buff, int* offset, const float input);
+void mnldinf_put_double(char* buff, int* offset, const double input);
+void mnldinf_put_string(char* buff, int* offset, const char* input);
+void mnldinf_put_binary(char* buff, int* offset, const char* input, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_ext.h b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_ext.h
new file mode 100755
index 0000000..28d6b89
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_ext.h
@@ -0,0 +1,84 @@
+#ifndef __MNLDINF_EXT_INTERFACE_H__
+#define __MNLDINF_EXT_INTERFACE_H__
+
+#include "mnldinf_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MNLDINF_EXT_TCP "mnldinf_ext"
+
+typedef struct {
+ void (*mnldinf_connection_broken)();
+ void (*mnldinf_request_wakelock)();
+ void (*mnldinf_release_wakelock)();
+
+ void (*mnldinf_request_utc_time)();
+ void (*mnldinf_request_nlp)(bool independent_from_gnss, bool is_user_emergency);
+ void (*mnldinf_request_ni_notify)(int session_id, agps_ni_type ni_type, agps_notify_type type, const char* requestor_id,
+ const char* client_name, ni_encoding_type requestor_id_encoding,
+ ni_encoding_type client_name_encoding);
+
+ void (*mnldinf_request_data_conn)(struct sockaddr_storage* addr, agps_type type);
+ void (*mnldinf_release_data_conn)();
+
+ void (*mnldinf_request_set_id)(request_setid flags);
+ void (*mnldinf_request_ref_loc)(request_refloc flags);
+ void (*mnldinf_output_vzw_debug)(const char* str);
+
+ void (*mnldinf_update_gnss_name)(const char* name, int length);
+
+ void (*mnldinf_gnss_navigation_msg)(gnss_nav_msg *msg);
+ void (*mnldinf_nfw_access_notify)(mnldinf_nfw_notification *nfw_notify);
+ void (*mnldinf_capability_update)(mnldinf_ext_server_cap *cap);
+ void (*mnldinf_agps_location_update)(mnldinf_agps_location location);
+} mnldinf_ext;
+
+int mnldinf_ext_data_conn_open(int fd, const char* apn);
+int mnldinf_ext_data_conn_open_with_apn_ip_type(int fd, uint64_t network_handle, const char* apn, apn_ip_type ip_type);
+int mnldinf_ext_data_conn_closed(int fd);
+int mnldinf_ext_data_conn_failed(int fd);
+
+int mnldinf_ext_set_server(int fd, agps_type type, const char* hostname, int port);
+int mnldinf_ext_set_ref_location(int fd, cell_type type, int mcc, int mnc, int lac, int cid);
+int mnldinf_ext_set_id(int fd, agps_id_type type, const char* setid);
+//OpenWRT can't response
+int mnldinf_ext_update_network_state(int fd, uint64_t network_handle, bool is_connected,
+ uint16_t capabilities, const char* apn);
+
+int mnldinf_ext_update_network_availability(int fd, int available, const char* apn);
+
+int mnldinf_ext_set_vzw_debug(int fd, bool enabled);
+
+int mnldinf_ext_gnss_inject_time(int fd, int64_t time, int64_t time_reference, int uncertainty);
+int mnldinf_ext_gnss_inject_location(int fd, double lat, double lng, float acc);
+int mnldinf_ext_ni_message(int fd, char* msg, int len);
+int mnldinf_ext_ni_respond(int fd, int notif_id, ni_user_response_type user_response);
+
+int mnldinf_ext_gnss_delete_aiding_data(int fd, gnss_delete_flag flags);
+int mnldinf_ext_gnss_set_position_mode(int fd, gps_pos_mode mode);
+int mnldinf_ext_update_gnss_config(int fd, const char* config_data, int length);
+int mnldinf_ext_set_sv_blacklist(int fd, long long* blacklist, int32_t size);
+int mnldinf_ext_send_pmtk(int fd, char* msg, int len);
+
+int mnldinf_ext_gnss_navigation_msg_enable(int fd, bool enable);
+int mnldinf_ext_gnss_full_tracking_enable(int fd, bool enable); //To be implement
+
+int mnldinf_ext_epo_enable(int fd, epo_bitmap epo_cfg);
+int mnldinf_ext_set_nfw_access(int fd, char* proxy_apps, int32_t length);
+int mnldinf_ext_set_correction(int fd, measurement_corrections* corrections);
+int mnldinf_ext_set_ttff_acc(int fd, ttff_acc acc_mode);
+
+// -1 means failure
+int mnldinf_ext_cmd_hdlr(int fd, mnldinf_ext* hdlr);
+
+int mnldinf_ext_register(char *client_name);
+
+void mnldinf_ext_capability_config(int fd, mnldinf_ext_client_cap *cap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_log.h b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_log.h
new file mode 100755
index 0000000..0c7a7ce
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_log.h
@@ -0,0 +1,222 @@
+/*
+* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2017. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*/
+#ifndef __MNLDINF_LOG_H_
+#define __MNLDINF_LOG_H_
+#include <string.h>
+
+/**
+ * @enum LOG_LEVEL
+ * @brief Define Log Level
+ */
+typedef enum {
+ L_VERBOSE = 0, L_DEBUG, L_INFO, L_WARN, L_ERROR, L_ASSERT, L_SUPPRESS
+} LOG_LEVEL;
+
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+
+#ifndef LOG_TAG
+#define LOG_TAG "gnss_hal"
+#endif
+
+#ifdef LOGA
+#undef LOGA
+#endif
+
+#ifdef LOGE
+#undef LOGE
+#endif
+
+#ifdef LOGW
+#undef LOGW
+#endif
+
+#ifdef LOGI
+#undef LOGI
+#endif
+
+#ifdef LOGD
+#undef LOGD
+#endif
+
+#ifdef LOGV
+#undef LOGV
+#endif
+
+#define mnldinf_LOG_LEVEL L_DEBUG
+int set_log_level(int *dst_level, int src_level);
+
+extern int log_dbg_level;
+#define LOG_IS_ENABLED(level) (log_dbg_level <= level)
+
+#define FILE_NAME(x) strrchr(x, '/')?strrchr(x, '/') + 1 : x
+
+#if defined(__ANDROID_OS__)
+
+#include <cutils/sockets.h>
+#include <log/log.h> /*logging in logcat*/
+#include <cutils/android_filesystem_config.h>
+#include <cutils/properties.h>
+
+#define PRINT_LOG(loglevel, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ switch (loglevel){\
+ case L_ASSERT:\
+ {\
+ ALOG_ASSERT("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_ERROR:\
+ {\
+ ALOGE("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_WARN:\
+ {\
+ ALOGW("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_INFO:\
+ {\
+ ALOGI("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_DEBUG:\
+ {\
+ ALOGD("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_VERBOSE:\
+ {\
+ ALOGV("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ }\
+ }\
+ } while (0)
+
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, fmt, ##args)
+
+#define TRC(f) ALOGD("%s", __func__)
+
+#elif defined(__TIZEN_OS__)
+
+#include <dlog/dlog.h>
+
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ dlog_print(DLOG_DEBUG, fmt "\n", ##args);\
+ printf(fmt "\n", ##args);
+ fflush(stdout);\
+ }\
+ } while (0)
+
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, "[ASSERT]: ", fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, "[ERROR]: ", fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, "[WARNING]: ", fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, "[INFO]: ", fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, "[DEBUG]: ", fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, "[VERBOSE]: ", fmt, ##args)
+
+//#elif defined(__LINUX_OS__)
+#else
+#include <stdio.h>
+
+char time_buff[64];
+int mnldinf_get_time_str(char* buf, int len);
+
+#ifndef gettid
+#include <unistd.h>
+#include <sys/syscall.h>
+#define gettid() syscall(__NR_gettid)
+#define getpid() syscall(__NR_getpid)
+#endif
+#if 1
+
+//#define PRINT_LOG_SAMPLE
+#ifndef PRINT_LOG_SAMPLE
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ mnldinf_get_time_str(time_buff, sizeof(time_buff));\
+ printf("%ld %ld [%s]" LOG_TAG tag "%s %s %d " fmt "\n",\
+ getpid(), gettid(),time_buff, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ fflush(stdout);\
+ }\
+ } while (0)
+#else
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ printf("%ld %ld " LOG_TAG tag fmt "\n",\
+ getpid(), gettid(), ##args);\
+ fflush(stdout);\
+ }\
+ } while (0)
+#endif
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, "[ASSERT]: ", fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, "[ERROR]: ", fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, "[WARNING]: ", fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, "[INFO]: ", fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, "[DEBUG]: ", fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, "[VERBOSE]: ", fmt, ##args)
+#else
+#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); }
+
+#endif
+#define TRC(f) ((void)0)
+
+#define PRINT_SIZE(type) do { \
+ LOGD("sizeof %s:%lu", #type, sizeof(type)); \
+} while(0)
+
+#define crash_with_log() {\
+ LOGE("crash_with_log() %s %s() line=%d", __FILE__, __FUNCTION__, __LINE__);\
+ exit(1);\
+}
+
+#endif
+
+#endif
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_utility.h b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_utility.h
new file mode 100755
index 0000000..9b6d74b
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/inc/mnldinf_utility.h
@@ -0,0 +1,197 @@
+#ifndef __MNLDINF_UTILITY_H__
+#define __MNLDINF_UTILITY_H__
+
+#include <time.h>
+#include <stdint.h>
+#include <pthread.h>
+
+#include "mnldinf_log.h"
+#include "mnldinf_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************
+* Basic Utilities
+**************************************************/
+#define MTK_GPS_NVRAM 0
+
+#define INVALID_TIMERID ((timer_t)-1)
+
+#define DUMP_BYTES_PER_LINE 16
+#define DUMP_MAX_PRINT_LINE 10
+
+#define MNLDINF_DUMP_MEM(addr, len) do{\
+ int i = 0, j = 0;\
+ char print_buf[DUMP_BYTES_PER_LINE*5+1] = {0};\
+ unsigned int print_len = len;\
+ if(len > DUMP_MAX_PRINT_LINE*DUMP_BYTES_PER_LINE) {\
+ print_len = DUMP_MAX_PRINT_LINE*DUMP_BYTES_PER_LINE;\
+ }\
+ LOGD(">>>>>DUMP_START(addr:%p, len:%d, print_len:%ud)<<<<<", addr, len,print_len);\
+ for(i = 0; i < print_len; i+=DUMP_BYTES_PER_LINE) {\
+ memset(print_buf, 0, sizeof(print_buf));\
+ for(j=0;j<DUMP_BYTES_PER_LINE;j++) {\
+ sprintf(&print_buf[j*5], "0x%02x ", ((char *)addr)[i*DUMP_BYTES_PER_LINE+j]);\
+ print_buf[DUMP_BYTES_PER_LINE*5] = '\0';\
+ }\
+ LOGD("[%3d]:%s", i/DUMP_BYTES_PER_LINE, print_buf);\
+ }\
+ LOGD("<<<<<DUMP_STOP>>>>>");\
+}while(0)
+
+void mnldinf_msleep(int interval);
+
+#define MNLD_STRNCPY(dst,src,size) do{\
+ strncpy((char *)(dst), (char *)(src), (size - 1));\
+ (dst)[size - 1] = '\0';\
+ }while(0)
+
+#define MNLD_SPRINTF(buf,fmt,...) do{\
+ if(sprintf((char *)(buf), fmt,##__VA_ARGS__) < 0){\
+ LOGE("sprintf error occurred");\
+ }\
+ }while(0)
+
+#define MNLD_SNPRINTF(buf,len,fmt,...) do{\
+ if(snprintf((char *)(buf), len, fmt,##__VA_ARGS__) < 0){\
+ LOGE("snprintf error occurred");\
+ }\
+ }while(0)
+
+#define MNLD_VSNPRINTF(buf,len,fmt,...) do{\
+ if(vsnprintf((char *)(buf), len, fmt,##__VA_ARGS__) < 0){\
+ LOGE("vsnprintf error occurred");\
+ }\
+ }while(0)
+
+#define MNLD_FRINTF(buf,fmt,...) do{\
+ if(fprintf(buf, fmt,##__VA_ARGS__) < 0){\
+ LOGE("fprintf error occurred");\
+ }\
+ }while(0)
+
+#define MNLDINF_MSG_HEAD_LEN (3*sizeof(int))
+
+//Cycle buffer
+typedef struct cyclical_buffer // Cyclical buffer
+{
+ char *next_write; // next position to write to
+ char *next_read; // next position to read from
+ char *start_buffer; // start of buffer
+ char *end_buffer; // end of buffer + 1
+ int buffer_size;
+} cyclical_buffer_t;
+
+//Cmd record and dump
+#define GPS_HAL_TIME_STR_LEN 25
+#define GPS_HAL_CMD_RECORD_NUM 10
+#define GPS_HAL_CMD_MONITER_TIMEOUT (3*1000)
+
+typedef struct {
+ char enter_time[GPS_HAL_TIME_STR_LEN];
+ char exit_time[GPS_HAL_TIME_STR_LEN];
+ time_t exec_time;
+ mnl2hal_cmd cmd;
+} gps_cmd_record;
+
+/*************************************************
+* Timer
+**************************************************/
+typedef void (* timer_callback)();
+
+
+// in millisecond
+time_t mnldinf_get_tick();
+
+// in millisecond
+time_t mnldinf_get_time_in_millisecond();
+
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int mnldinf_epoll_add_fd(int epfd, int fd);
+
+// -1 failed
+int mnldinf_epoll_add_fd2(int epfd, int fd, uint32_t events);
+
+// -1 failed
+int mnldinf_epoll_del_fd(int epfd, int fd);
+
+int mnldinf_epoll_mod_fd(int epfd, int fd, uint32_t events);
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int mnldinf_socket_bind_udp(const char* path);
+
+// -1 means failure
+int mnldinf_socket_set_blocking(int fd, int blocking);
+
+// -1 means failure
+int mnldinf_safe_sendto(const char* path, const char* buff, int len);
+
+// -1 means failure
+int mnldinf_safe_recvfrom(int fd, char* buff, int len);
+
+// -1 means failure
+int mnldinf_start_timer(timer_t timerid, int milliseconds);
+
+// -1 means failure
+int mnldinf_stop_timer(timer_t timerid);
+
+// -1 means failure
+timer_t mnldinf_init_timer(timer_callback cb);
+
+// -1 means failure
+int mnldinf_deinit_timer(timer_t timerid);
+
+/*************************************************
+* Cycle buffer
+**************************************************/
+void mnldinf_buffer_initialize(cyclical_buffer_t *buffer, char *buffer_body, unsigned int buffer_size);
+int mnldinf_put_msg_to_cycle(cyclical_buffer_t *cyc_buffer, char *buff, int len);
+int mnldinf_get_one_msg(cyclical_buffer_t *cyc_buffer, char *buff);
+
+
+/*************************************************
+* Socket
+**************************************************/
+int mnldinf_tcp_send(int fd, const char* buff, int len);
+int mnldinf_socket_tcp_server_bind_local(bool abstract, const char* name);
+int mnldinf_socket_tcp_server_new_connect(int serverfd);
+int mnldinf_socket_tcp_client_connect_local(bool abstract, const char* name);
+int mnldinf_socket_udp_server_bind_local(bool abstract, const char* name);
+int mnldinf_socket_udp_client_create_local(bool abstract, const char* name);
+bool mnldinf_socket_udp_exist_local(bool abstract, const char* name);
+int mnldinf_safe_recv(int fd, char* buff, int len);
+
+//------------------------------------------------------
+//Linux wake lock
+
+#define MNLDINF_WAKE_LOCK_ID "mnldinf_wakelock"
+//delay to do wake_unlock to ensure the msg can be deliveried to other process
+#define MNLDINF_WAKE_LOCK_TIMEOUT (5 * 1000)
+//Timer refresh latency, to protect timer update too often in short time
+#define MNLDINF_WAKE_LOCK_LATENCY (1 * 1000)
+
+typedef struct {
+ bool wake_lock_acquired;
+ timer_t unlock_timer;
+ pthread_mutex_t mutex;
+ time_t time_last_refresh;
+} wake_lock_ctx;
+
+void mnldinf_wake_lock_init();
+void mnldinf_wake_lock_deinit();
+void mnldinf_wake_lock_take();
+void mnldinf_wake_lock_give();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_basic.c b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_basic.c
new file mode 100755
index 0000000..4b903b6
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_basic.c
@@ -0,0 +1,368 @@
+#include "mnldinf_basic.h"
+#include "mnldinf_utility.h"
+#include "mnldinf_data_coder.h"
+#include "mnldinf_log.h"
+#include "errno.h"
+
+//int log_dbg_level = mnldinf_LOG_LEVEL;
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnldinf_basic"
+#endif
+#ifndef MIN
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#endif
+
+char g_mnldinf_basic_msg_buf[HAL_MNL_BUFF_SIZE_SND*2] = {0};
+cyclical_buffer_t g_mnldinf_basic_cbuffer; // io - cyclic buffer
+mnldinf_basic_client_cap g_mnldinf_basic_client_cap;
+volatile bool g_mnldinf_basic_cap_setted = false;
+gnss_data meas_data;
+
+#define DUMP_BASIC_CLIENT_CAP(cap) do {\
+ LOGD("[%s]:mnldinf_basic_client_cap size:%lu, gnss_support=%d", __func__, sizeof(mnldinf_basic_client_cap), (cap)->support_gnss);\
+} while(0)
+
+#define DUMP_BASIC_SERVER_CAP(cap) do {\
+ LOGD("[%s]:mnldinf_basic_server_cap size:%lu, gnss_support=%d", __func__, sizeof(mnldinf_basic_server_cap), (cap)->support_gnss);\
+} while(0)
+
+static gps_cmd_record basic_cmd_list[GPS_HAL_CMD_RECORD_NUM];
+static int basic_cmd_rcd_idx = 0;
+static time_t basic_enter_time_ms = 0;
+static timer_t basic_cmd_moniter_timer = INVALID_TIMERID;
+static int basic_last_record_idx = 0xFF;
+
+void mnldinf_basic_cmd_enter_record(mnl2hal_cmd cmd) {
+ int ret = 0;
+ /*Clear parameters before setting*/
+ memset(basic_cmd_list[basic_cmd_rcd_idx].enter_time, 0, GPS_HAL_TIME_STR_LEN);
+ memset(basic_cmd_list[basic_cmd_rcd_idx].exit_time, 0, GPS_HAL_TIME_STR_LEN);
+ basic_cmd_list[basic_cmd_rcd_idx].cmd = 0;
+ basic_cmd_list[basic_cmd_rcd_idx].exec_time = 0;
+
+ basic_last_record_idx = 0xFF; //Print all history command
+ basic_enter_time_ms = mnldinf_get_time_in_millisecond();
+ ret = mnldinf_get_time_str(basic_cmd_list[basic_cmd_rcd_idx].enter_time, GPS_HAL_TIME_STR_LEN);
+ if(ret == -1) {
+ LOGW("mnldinf_get_time_str fail(%s)", strerror(errno));
+ }
+ basic_cmd_list[basic_cmd_rcd_idx].cmd = cmd;
+
+ ret = mnldinf_start_timer(basic_cmd_moniter_timer, GPS_HAL_CMD_MONITER_TIMEOUT);
+ if(ret == -1) {
+ LOGW("start_timer fail(%s)", strerror(errno));
+ }
+}
+
+void mnldinf_basic_cmd_exit_record(mnl2hal_cmd cmd) {
+ if(cmd == basic_cmd_list[basic_cmd_rcd_idx].cmd) {
+ int ret = 0;
+ ret = mnldinf_get_time_str(basic_cmd_list[basic_cmd_rcd_idx].exit_time, GPS_HAL_TIME_STR_LEN);
+ if(ret == -1) {
+ LOGW("mnldinf_get_time_str fail(%s)", strerror(errno));
+ }
+ basic_cmd_list[basic_cmd_rcd_idx].exec_time = mnldinf_get_time_in_millisecond() - basic_enter_time_ms;
+ basic_cmd_rcd_idx++;
+ basic_cmd_rcd_idx = basic_cmd_rcd_idx%GPS_HAL_CMD_RECORD_NUM; //Over-write oldest recording
+ ret = mnldinf_stop_timer(basic_cmd_moniter_timer);
+ if(ret == -1) {
+ LOGW("mnldinf_stop_timer fail(%s)", strerror(errno));
+ }
+ } else {
+ LOGW("cmd not matched:enter->%d, exit->%d", basic_cmd_list[basic_cmd_rcd_idx].cmd, cmd);
+ }
+}
+
+void mnldinf_basic_cmd_list_dump(void) {
+ int print_idx = 0;
+ int cur_rcd = basic_cmd_rcd_idx;
+ int print_more = 0;
+ int empty_cnt = 0;
+
+ if(basic_last_record_idx != cur_rcd) {
+ print_more = 1;
+ basic_last_record_idx = cur_rcd;
+ }
+
+ LOGW("Dump GPS HAL command record:");
+ for(print_idx = 0; print_idx < GPS_HAL_CMD_RECORD_NUM; print_idx++){
+ if(basic_cmd_list[print_idx].cmd != 0) { //Valid cmd
+ if(print_idx == cur_rcd) {
+ LOGW("[%2d]%s:%3d << Current command(%lld)", print_idx, basic_cmd_list[print_idx].enter_time, basic_cmd_list[print_idx].cmd, (long long)(mnldinf_get_time_in_millisecond() - basic_enter_time_ms ));
+ } else {
+ if(print_more) {
+ LOGW("[%2d]%s~%s(%lld):%3d", print_idx, basic_cmd_list[print_idx].enter_time, basic_cmd_list[print_idx].exit_time, (long long)basic_cmd_list[print_idx].exec_time, basic_cmd_list[print_idx].cmd );
+ }
+ }
+ } else {
+ empty_cnt++;
+ }
+ }
+ if(empty_cnt) {
+ LOGW("empty_cnt:%d", empty_cnt);
+ }
+}
+
+void mnldinf_basic_cmd_list_init(void) {
+ memset(basic_cmd_list, 0, sizeof(basic_cmd_list));
+ basic_cmd_rcd_idx = 0;
+ basic_enter_time_ms = 0;
+ basic_last_record_idx = 0xFF;
+
+ basic_cmd_moniter_timer = mnldinf_init_timer(mnldinf_basic_cmd_list_dump);
+}
+
+//Tell server the support capability of mnld basic interface
+int mnldinf_basic_client_capability_update(int fd) {
+ //LOGI("mnldinf_basic_client_capability_update, fd:%d", fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ if(g_mnldinf_basic_cap_setted == false) {
+ LOGD("mnldinf_basic_client_capability_update, set as default.");
+ memset(&g_mnldinf_basic_client_cap, 0, sizeof(mnldinf_basic_client_cap));
+ g_mnldinf_basic_client_cap.support_gnss = 1;
+ }
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_BASIC_CAP_SYNC);
+ mnldinf_put_binary(buff, &offset, (char *)&g_mnldinf_basic_client_cap, (int)sizeof(mnldinf_basic_client_cap));
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+void mnldinf_basic_capability_config(int fd, mnldinf_basic_client_cap *cap) {
+ if(cap == NULL) {
+ LOGE("NULL cap !!!!fd:%d", fd);
+ return;
+ }
+ //DUMP_BASIC_CLIENT_CAP(cap);
+ memset(&g_mnldinf_basic_client_cap, 0, sizeof(mnldinf_basic_client_cap));
+ memcpy(&g_mnldinf_basic_client_cap, cap, sizeof(mnldinf_basic_client_cap));
+ g_mnldinf_basic_cap_setted = true;
+ if(-1 == mnldinf_basic_client_capability_update(fd)) {
+ LOGE("mnldinf_basic_capability_config fail!!!");
+ }
+}
+
+int mnldinf_basic_gnss_init(int fd) {
+ LOGI("mnldinf_basic_gnss_init, fd:%d", fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_INIT);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_basic_gnss_start(int fd) {
+ LOGI("mnldinf_basic_gnss_start, fd:%d", fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_START);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+int mnldinf_basic_gnss_stop(int fd) {
+ LOGI("mnldinf_basic_gnss_stop, fd:%d", fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_STOP);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_basic_gnss_cleanup(int fd) {
+ LOGI("mnldinf_basic_gnss_cleanup, fd:%d", fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_CLEANUP);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_basic_gnss_measurement_enable(int fd, bool enabled) {
+ LOGD("enabled=%d, fd:%d", enabled, fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_MEASUREMENT);
+ mnldinf_put_int(buff, &offset, enabled);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+void mnldinf_dump_gnss_sv_info(gnss_sv_info sv) {
+ unsigned int i = 0;
+ LOGD("[dump_gnss_sv_info], sv_num:%d", sv.num_svs);
+ for(i = 0; i < sv.num_svs; i++) {
+ LOGD("SV[%d], cons:%d, Cn0dBHz:%f, elev:%f, azim:%f, flags:%d, cf:%f"
+ , sv.sv_list[i].svid, sv.sv_list[i].constellation, sv.sv_list[i].c_n0_dbhz, sv.sv_list[i].elevation
+ , sv.sv_list[i].azimuth, sv.sv_list[i].flags, sv.sv_list[i].carrier_frequency);
+ }
+}
+
+// -1 means failure
+int mnldinf_basic_cmd_hdlr(int fd, mnldinf_basic* hdlr) {
+ char buff[HAL_MNL_BUFF_SIZE_SND] = {0};
+ char buff_read[HAL_MNL_BUFF_SIZE_SND] = {0};
+ int offset = 0;
+ int ver;
+ mnl2hal_cmd cmd;
+ int read_len;
+ int ret = 0;
+ int msg_len = 0;
+
+ read_len = mnldinf_safe_recv(fd, buff_read, sizeof(buff_read));
+ if (read_len <= 0) {
+ close(fd);
+ if(hdlr->mnldinf_connection_broken) {
+ LOGW("Connection broken...");
+ hdlr->mnldinf_connection_broken();
+ }
+ LOGE("mnldinf_basic_cmd_hdlr() mnldinf_safe_recvfrom() failed read_len=%d, %s", read_len, strerror(errno));
+ return -1;
+ }
+
+ mnldinf_put_msg_to_cycle(&g_mnldinf_basic_cbuffer, buff_read, read_len);
+
+ while(mnldinf_get_one_msg(&g_mnldinf_basic_cbuffer, buff) > 0) {
+ offset = 0;
+ msg_len = mnldinf_get_int(buff, &offset, sizeof(buff)); //Get message length
+ UNUSED(msg_len);
+ ver = mnldinf_get_int(buff, &offset, sizeof(buff));
+ UNUSED(ver);
+ cmd = mnldinf_get_int(buff, &offset, sizeof(buff));
+ mnldinf_basic_cmd_enter_record(cmd);
+ //LOGD("cmd:%d, msg_len:%d, ver:%d", cmd, msg_len, ver);
+ switch (cmd) {
+ case MNL2HAL_LOCATION: {
+ if (hdlr->mnldinf_location) {
+ gps_location location;
+ memset(&location, 0, sizeof(location));
+ mnldinf_get_binary(buff, &offset, (char*)&location, sizeof(buff), sizeof(gps_location));
+ hdlr->mnldinf_location(location);
+ } else {
+ LOGE("mnl2hal_hdlr() location is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_GPS_STATUS: {
+ if (hdlr->mnldinf_gnss_status) {
+ gps_status status;
+ mnldinf_get_binary(buff, &offset, (char*)&status, sizeof(buff), sizeof(gps_status));
+ hdlr->mnldinf_gnss_status(status);
+ } else {
+ LOGE("mnl2hal_hdlr() gps_status is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_GPS_SV: {
+ if (hdlr->mnldinf_gnss_sv) {
+ gnss_sv_info sv;
+ memset(&sv, 0, sizeof(sv));
+ mnldinf_get_binary(buff, &offset, (char*)&sv, sizeof(buff), sizeof(gnss_sv_info));
+ //mnldinf_dump_gnss_sv_info(sv);
+ hdlr->mnldinf_gnss_sv(sv);
+ } else {
+ LOGE("mnl2hal_hdlr() gps_sv is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_NMEA: {
+ if (hdlr->mnldinf_nmea) {
+ int64_t timestamp = mnldinf_get_long(buff, &offset, sizeof(buff));
+ char* nmea = mnldinf_get_string(buff, &offset, sizeof(buff));
+ int used_length = nmea - buff;
+ int max_length = sizeof(buff) - used_length;
+ int length = mnldinf_get_int(buff, &offset, sizeof(buff));
+ length = MIN(length,max_length);
+ hdlr->mnldinf_nmea(timestamp, nmea, length);
+ } else {
+ LOGE("mnl2hal_hdlr() nmea is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_GNSS_MEASUREMENTS: {
+ if (hdlr->mnldinf_gnss_measurements) {
+ memset(&meas_data, 0, sizeof(meas_data));
+ mnldinf_get_binary(buff, &offset, (char*)&meas_data, sizeof(buff), sizeof(gnss_data));
+ hdlr->mnldinf_gnss_measurements(&meas_data);
+ } else {
+ LOGE("mnl2hal_hdlr() gnss_measurements is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_BASIC_CAP_SYNC: {
+ if(hdlr->mnldinf_capability_update) {
+ mnldinf_basic_server_cap cap;
+ memset(&cap, 0, sizeof(cap));
+ mnldinf_get_binary(buff, &offset, (char *)&cap, sizeof(buff), sizeof(cap));
+ //DUMP_BASIC_SERVER_CAP(&cap);
+ hdlr->mnldinf_capability_update(&cap);
+ } else {
+ LOGE("mnl2hal_hdlr() mnldinf_capability_update is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_NMEA_DONE: {
+ if(hdlr->mnldinf_nmea_done) {
+ hdlr->mnldinf_nmea_done();
+ } else {
+ LOGE("mnl2hal_hdlr() MNL2HAL_BASIC_CAP_SYNC is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ default: {
+ LOGE("mnl2hal_hdlr() unknown cmd=%d", cmd);
+ ret = -1;
+ break;
+ }
+ }
+
+ mnldinf_basic_cmd_exit_record(cmd);
+ }
+
+ return ret;
+}
+
+void mnldinf_basic_structure_size_dump(void) {
+ PRINT_SIZE(mnldinf_basic_client_cap);
+ PRINT_SIZE(gps_location);
+ PRINT_SIZE(gps_status);
+ PRINT_SIZE(gnss_sv_info);
+ PRINT_SIZE(gnss_data);
+ PRINT_SIZE(mnldinf_basic_server_cap);
+}
+
+int mnldinf_basic_register(char *client_name) {
+ int fd = -1;
+
+ fd = mnldinf_socket_tcp_client_connect_local(true, MNLDINF_BASIC_TCP);
+ //LOGD("New client:[%s], fd:%d", client_name, fd);
+ //mnldinf_basic_structure_size_dump();
+
+ mnldinf_basic_cmd_list_init();
+
+ mnldinf_socket_set_blocking(fd, 0); //Set as none-blocking
+ mnldinf_buffer_initialize(&g_mnldinf_basic_cbuffer, g_mnldinf_basic_msg_buf, sizeof(g_mnldinf_basic_msg_buf));
+
+ return fd;
+}
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_data_coder.c b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_data_coder.c
new file mode 100755
index 0000000..6628011
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_data_coder.c
@@ -0,0 +1,154 @@
+#include <string.h>
+
+#ifndef MAX
+#define MAX(A,B) ((A)>(B)?(A):(B))
+#endif
+#ifndef MIN
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#endif
+
+//===============================================================
+// get
+char mnldinf_get_byte(char* buff, int* offset, int src_len) {
+ char ret = 0;
+ if (*offset >= 0 && *offset < src_len) {
+ ret = buff[*offset];
+ *offset += 1;
+ }
+ return ret;
+}
+
+short mnldinf_get_short(char* buff, int* offset, int src_len) {
+ short ret = 0;
+ ret |= mnldinf_get_byte(buff, offset, src_len) & 0xff;
+ ret |= (mnldinf_get_byte(buff, offset, src_len) << 8);
+ return ret;
+}
+
+int mnldinf_get_int(char* buff, int* offset, int src_len) {
+ int ret = 0;
+ ret |= mnldinf_get_short(buff, offset, src_len) & 0xffff;
+ ret |= (mnldinf_get_short(buff, offset, src_len) << 16);
+ return ret;
+}
+
+long long mnldinf_get_long(char* buff, int* offset, int src_len) {
+ long long ret = 0;
+ ret |= mnldinf_get_int(buff, offset, src_len) & 0xffffffffL;
+ ret |= ((long long)mnldinf_get_int(buff, offset, src_len) << 32);
+ return ret;
+}
+
+float mnldinf_get_float(char* buff, int* offset, int src_len) {
+ float ret;
+ int tmp = mnldinf_get_int(buff, offset, src_len);
+ ret = *((float*)&tmp);
+ return ret;
+}
+
+double mnldinf_get_double(char* buff, int* offset, int src_len) {
+ double ret;
+ long long tmp = mnldinf_get_long(buff, offset, src_len);
+ ret = *((double*)&tmp);
+ return ret;
+}
+
+char* mnldinf_get_string(char* buff, int* offset, int src_len) {
+ char ret = mnldinf_get_byte(buff, offset, src_len);
+ if (ret == 0) {
+ return NULL;
+ } else {
+ char* p = NULL;
+ int len = mnldinf_get_int(buff, offset, src_len);
+ if (*offset < 0 || *offset >= src_len) {
+ *offset = 0;
+ }
+ if ((len > src_len - *offset) || len < 0) {
+ len = src_len - *offset;
+ }
+ if (len <= 0) {
+ return NULL;
+ }
+ p = &buff[*offset];
+ p[len-1] = 0;
+ *offset += len;
+ return p;
+ }
+}
+
+char* mnldinf_get_string2(char* buff, int* offset, int src_len) {
+ char* output = mnldinf_get_string(buff, offset, src_len);
+ if (output == NULL) {
+ return "";
+ } else {
+ return output;
+ }
+}
+
+int mnldinf_get_binary(char* buff, int* offset, char* output, int src_len, int des_len) {
+ int len = 0;
+ if (*offset >= 0 && *offset <= src_len) {
+ len = mnldinf_get_int(buff, offset, src_len);
+ if (len > MIN((src_len-(*offset)), des_len)) {
+ len = MIN((src_len-(*offset)), des_len);
+ }
+ if (len > 0) {
+ memcpy(output, &buff[*offset], len);
+ *offset += len;
+ }
+ }
+ return len;
+}
+
+//===============================================================
+// put
+void mnldinf_put_byte(char* buff, int* offset, const char input) {
+ *((char*)&buff[*offset]) = input;
+ *offset += 1;
+}
+
+void mnldinf_put_short(char* buff, int* offset, const short input) {
+ mnldinf_put_byte(buff, offset, input & 0xff);
+ mnldinf_put_byte(buff, offset, (input >> 8) & 0xff);
+}
+
+void mnldinf_put_int(char* buff, int* offset, const int input) {
+ mnldinf_put_short(buff, offset, input & 0xffff);
+ mnldinf_put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void mnldinf_put_long(char* buff, int* offset, const long long input) {
+ mnldinf_put_int(buff, offset, input & 0xffffffffL);
+ mnldinf_put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void mnldinf_put_float(char* buff, int* offset, const float input) {
+ int* data = (int*)&input;
+ mnldinf_put_int(buff, offset, *data);
+}
+
+void mnldinf_put_double(char* buff, int* offset, const double input) {
+ long long* data = (long long*)&input;
+ mnldinf_put_long(buff, offset, *data);
+}
+
+void mnldinf_put_string(char* buff, int* offset, const char* input) {
+ if (input == NULL) {
+ mnldinf_put_byte(buff, offset, 0);
+ } else {
+ int len = strlen(input) + 1;
+ mnldinf_put_byte(buff, offset, 1);
+ mnldinf_put_int(buff, offset, len);
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+ }
+}
+
+void mnldinf_put_binary(char* buff, int* offset, const char* input, const int len) {
+ mnldinf_put_int(buff, offset, len);
+ if (len > 0) {
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+ }
+}
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_ext.c b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_ext.c
new file mode 100755
index 0000000..b93ef29
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_ext.c
@@ -0,0 +1,702 @@
+#include "mnldinf_ext.h"
+#include "mnldinf_utility.h"
+#include "mnldinf_data_coder.h"
+#include "mnldinf_log.h"
+#include "errno.h"
+
+//int log_dbg_level = mnldinf_LOG_LEVEL;
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnldinf_ext"
+#endif
+
+//static float report_time_interval = 0;
+char g_mnldinf_ext_msg_buf[HAL_MNL_BUFF_SIZE_SND*2] = {0};
+cyclical_buffer_t g_mnldinf_ext_cbuffer; // io - cyclic buffer
+mnldinf_ext_client_cap g_mnldinf_ext_client_cap;
+bool g_mnldinf_ext_cap_setted = false;
+
+#define DUMP_EXT_CLIENT_CAP(cap) do {\
+ LOGD("[%s]:mnldinf_ext_client_cap size:%lu, gnss_support=%d", __func__, sizeof(mnldinf_ext_client_cap), (cap)->support_gnss);\
+} while(0)
+
+#define DUMP_EXT_SERVER_CAP(cap) do {\
+ LOGD("[%s]:mnldinf_ext_server_cap size:%lu, gnss_support=%d", __func__, sizeof(mnldinf_ext_server_cap), (cap)->support_gnss);\
+} while(0)
+
+static gps_cmd_record ext_cmd_list[GPS_HAL_CMD_RECORD_NUM];
+static int ext_cmd_rcd_idx = 0;
+static time_t ext_enter_time_ms = 0;
+static timer_t ext_cmd_moniter_timer = INVALID_TIMERID;
+static int ext_last_record_idx = 0xFF;
+
+void mnldinf_ext_cmd_enter_record(mnl2hal_cmd cmd) {
+ int ret = 0;
+ /*Clear parameters before setting*/
+ memset(ext_cmd_list[ext_cmd_rcd_idx].enter_time, 0, GPS_HAL_TIME_STR_LEN);
+ memset(ext_cmd_list[ext_cmd_rcd_idx].exit_time, 0, GPS_HAL_TIME_STR_LEN);
+ ext_cmd_list[ext_cmd_rcd_idx].cmd = 0;
+ ext_cmd_list[ext_cmd_rcd_idx].exec_time = 0;
+
+ ext_last_record_idx = 0xFF; //Print all history command
+ ext_enter_time_ms = mnldinf_get_time_in_millisecond();
+ ret = mnldinf_get_time_str(ext_cmd_list[ext_cmd_rcd_idx].enter_time, GPS_HAL_TIME_STR_LEN);
+ if(ret == -1) {
+ LOGW("mnldinf_get_time_str fail(%s)", strerror(errno));
+ }
+ ext_cmd_list[ext_cmd_rcd_idx].cmd = cmd;
+
+ ret = mnldinf_start_timer(ext_cmd_moniter_timer, GPS_HAL_CMD_MONITER_TIMEOUT);
+ if(ret == -1) {
+ LOGW("start_timer fail(%s)", strerror(errno));
+ }
+}
+
+void mnldinf_ext_cmd_exit_record(mnl2hal_cmd cmd) {
+ if(cmd == ext_cmd_list[ext_cmd_rcd_idx].cmd) {
+ int ret = 0;
+ ret = mnldinf_get_time_str(ext_cmd_list[ext_cmd_rcd_idx].exit_time, GPS_HAL_TIME_STR_LEN);
+ if(ret == -1) {
+ LOGW("mnldinf_get_time_str fail(%s)", strerror(errno));
+ }
+ ext_cmd_list[ext_cmd_rcd_idx].exec_time = mnldinf_get_time_in_millisecond() - ext_enter_time_ms;
+ ext_cmd_rcd_idx++;
+ ext_cmd_rcd_idx = ext_cmd_rcd_idx%GPS_HAL_CMD_RECORD_NUM; //Over-write oldest recording
+ ret = mnldinf_stop_timer(ext_cmd_moniter_timer);
+ if(ret == -1) {
+ LOGW("mnldinf_stop_timer fail(%s)", strerror(errno));
+ }
+ } else {
+ LOGW("cmd not matched:enter->%d, exit->%d", ext_cmd_list[ext_cmd_rcd_idx].cmd, cmd);
+ }
+}
+
+void mnldinf_ext_cmd_list_dump(void) {
+ int print_idx = 0;
+ int cur_rcd = ext_cmd_rcd_idx;
+ int print_more = 0;
+ int empty_cnt = 0;
+
+ if(ext_last_record_idx != cur_rcd) {
+ print_more = 1;
+ ext_last_record_idx = cur_rcd;
+ }
+
+ LOGW("Dump GPS HAL command record:");
+ for(print_idx = 0; print_idx < GPS_HAL_CMD_RECORD_NUM; print_idx++){
+ if(ext_cmd_list[print_idx].cmd != 0) { //Valid cmd
+ if(print_idx == cur_rcd) {
+ LOGW("[%2d]%s:%3d << Current command(%lld)", print_idx, ext_cmd_list[print_idx].enter_time, ext_cmd_list[print_idx].cmd, (long long)(mnldinf_get_time_in_millisecond() - ext_enter_time_ms ));
+ } else {
+ if(print_more) {
+ LOGW("[%2d]%s~%s(%lld):%3d", print_idx, ext_cmd_list[print_idx].enter_time, ext_cmd_list[print_idx].exit_time, (long long)ext_cmd_list[print_idx].exec_time, ext_cmd_list[print_idx].cmd );
+ }
+ }
+ } else {
+ empty_cnt++;
+ }
+ }
+ if(empty_cnt) {
+ LOGW("empty_cnt:%d", empty_cnt);
+ }
+}
+
+void mnldinf_ext_cmd_list_init(void) {
+ memset(ext_cmd_list, 0, sizeof(ext_cmd_list));
+ ext_cmd_rcd_idx = 0;
+ ext_enter_time_ms = 0;
+ ext_last_record_idx = 0xFF;
+
+ ext_cmd_moniter_timer = mnldinf_init_timer(mnldinf_ext_cmd_list_dump);
+}
+
+//Tell server the support capability of mnld extension interface
+int mnldinf_ext_capability_update(int fd) {
+ //LOGI("mnldinf_ext_capability_update, fd:%d", fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ if(g_mnldinf_ext_cap_setted == false) {
+ LOGD("mnldinf_ext_capability_update, set as default.");
+ memset(&g_mnldinf_ext_client_cap, 0, sizeof(mnldinf_ext_client_cap));
+ g_mnldinf_ext_client_cap.support_gnss = 1;
+ }
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_EXT_CAP_SYNC);
+ mnldinf_put_binary(buff, &offset, (char *)&g_mnldinf_ext_client_cap, (int)sizeof(mnldinf_ext_client_cap));
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+void mnldinf_ext_capability_config(int fd, mnldinf_ext_client_cap *cap) {
+ if(cap == NULL) {
+ LOGE("NULL cap !!!!fd:%d", fd);
+ return;
+ }
+ //DUMP_EXT_CLIENT_CAP(cap);
+ memset(&g_mnldinf_ext_client_cap, 0, sizeof(mnldinf_ext_client_cap));
+ memcpy(&g_mnldinf_ext_client_cap, cap, sizeof(mnldinf_ext_client_cap));
+ g_mnldinf_ext_cap_setted = true;
+ if(-1 == mnldinf_ext_capability_update(fd)) {
+ LOGE("mnldinf_ext_capability_config fail");
+ }
+}
+
+int mnldinf_ext_gnss_inject_time(int fd, int64_t time, int64_t time_reference, int uncertainty) {
+ /*LOGD("mnldinf_ext_gnss_inject_time time=%zd time_reference=%zd uncertainty=%d",
+ time, time_reference, uncertainty);*/
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_INJECT_TIME);
+ mnldinf_put_long(buff, &offset, time);
+ mnldinf_put_long(buff, &offset, time_reference);
+ mnldinf_put_int(buff, &offset, uncertainty);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_gnss_inject_location(int fd, double lat, double lng, float acc) {
+ // LOGD("mnldinf_ext_gnss_inject_location lat,lng %f,%f acc=%f", lat, lng, acc);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_INJECT_LOCATION);
+ mnldinf_put_double(buff, &offset, lat);
+ mnldinf_put_double(buff, &offset, lng);
+ mnldinf_put_float(buff, &offset, acc);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_gnss_delete_aiding_data(int fd, gnss_delete_flag flags) {
+ LOGD("flag=0x%x", flags);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_DELETE_AIDING_DATA);
+ mnldinf_put_int(buff, &offset, flags);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_gnss_set_position_mode(int fd, gps_pos_mode mode) {
+ LOGD("mode=%d", mode);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_SET_POSITION_MODE);
+ mnldinf_put_int(buff, &offset, mode);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_data_conn_open(int fd, const char* apn) {
+ LOGD("apn=[%s]", apn);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_DATA_CONN_OPEN);
+ mnldinf_put_string(buff, &offset, apn);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_data_conn_open_with_apn_ip_type(int fd, uint64_t network_handle, const char* apn, apn_ip_type ip_type) {
+ LOGD("apn=[%s] ip_type=%d",
+ apn, ip_type);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_DATA_CONN_OPEN_WITH_APN_IP_TYPE);
+ mnldinf_put_long(buff, &offset, network_handle);
+ mnldinf_put_string(buff, &offset, apn);
+ mnldinf_put_int(buff, &offset, ip_type);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_data_conn_closed(int fd) {
+ LOGD("mnldinf_ext_data_conn_closed");
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_DATA_CONN_CLOSED);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_data_conn_failed(int fd) {
+ LOGD("mnldinf_ext_data_conn_failed");
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_DATA_CONN_FAILED);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_set_server(int fd, agps_type type, const char* hostname, int port) {
+ LOGD("type=%d hostname=[%s] port=%d",
+ type, hostname, port);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_SET_SERVER);
+ mnldinf_put_int(buff, &offset, type);
+ mnldinf_put_string(buff, &offset, hostname);
+ mnldinf_put_int(buff, &offset, port);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+ return 0;
+}
+
+int mnldinf_ext_set_ref_location(int fd, cell_type type, int mcc, int mnc, int lac, int cid) {
+ LOGD("ype=%d mcc=%d mnc=%d lac=%d cid=%d",
+ type, mcc, mnc, lac, cid);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_SET_REF_LOCATION);
+ mnldinf_put_int(buff, &offset, type);
+ mnldinf_put_int(buff, &offset, mcc);
+ mnldinf_put_int(buff, &offset, mnc);
+ mnldinf_put_int(buff, &offset, lac);
+ mnldinf_put_int(buff, &offset, cid);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_set_id(int fd, agps_id_type type, const char* setid) {
+ LOGD("type=%d setid=[%s]", type, setid);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_SET_ID);
+ mnldinf_put_int(buff, &offset, type);
+ mnldinf_put_string(buff, &offset, setid);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+
+int mnldinf_ext_ni_message(int fd, char* msg, int len) {
+ LOGD("len=%d", len);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_NI_MESSAGE);
+ mnldinf_put_binary(buff, &offset, msg, len);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_send_pmtk(int fd, char* msg, int len) {
+ LOGD("len=%d", len);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_SEND_PMTK);
+ mnldinf_put_binary(buff, &offset, msg, len);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_ni_respond(int fd, int notif_id, ni_user_response_type user_response) {
+ LOGD("notif_id=%d user_response=%d",
+ notif_id, user_response);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_NI_RESPOND);
+ mnldinf_put_int(buff, &offset, notif_id);
+ mnldinf_put_int(buff, &offset, user_response);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_update_network_state(int fd, uint64_t network_handle, bool is_connected,
+ uint16_t capabilities, const char* apn) {
+ LOGD("connected=%d capabilities=%d apn=[%s]",
+ is_connected, capabilities, apn);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_UPDATE_NETWORK_STATE);
+ mnldinf_put_long(buff, &offset, network_handle);
+ mnldinf_put_byte(buff, &offset, is_connected);
+ mnldinf_put_short(buff, &offset, capabilities);
+ mnldinf_put_string(buff, &offset, apn);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_update_network_availability(int fd, int available, const char* apn) {
+ LOGD("available=%d apn=[%s]",
+ available, apn);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_UPDATE_NETWORK_AVAILABILITY);
+ mnldinf_put_int(buff, &offset, available);
+ mnldinf_put_string(buff, &offset, apn);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_gnss_navigation_msg_enable(int fd, bool enabled) {
+ LOGD("enabled=%d", enabled);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_NAVIGATION);
+ mnldinf_put_int(buff, &offset, enabled);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_set_vzw_debug(int fd, bool enabled) {
+ LOGD("enabled = %d\n", enabled);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_VZW_DEBUG);
+ mnldinf_put_int(buff, &offset, enabled);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_update_gnss_config(int fd, const char* config_data, int length) {
+ LOGD("data length:%d\n", length);
+ int offset = 0;
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GNSS_CONFIG);
+ mnldinf_put_int(buff, &offset, length);
+ mnldinf_put_string(buff, &offset, config_data);
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_gnss_full_tracking_enable(int fd, bool enable) {
+ LOGD("full tracking enable:%d\n", enable);
+ int offset = 0;
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_FULL_TRACKING);
+ mnldinf_put_int(buff, &offset, enable);
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_epo_enable(int fd, epo_bitmap epo_cfg) {
+ LOGD("mnldinf_ext_epo_enable:0x%x\n", epo_cfg);
+ int offset = 0;
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_EPO_ENABLE);
+ mnldinf_put_int(buff, &offset, epo_cfg);
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_set_sv_blacklist(int fd, long long* blacklist, int32_t size) {
+ LOGD("hal2mnl_setBlacklist, size:%d, first SVID:0x%llx\n", size, *blacklist);
+ int offset = 0;
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_SV_BLACKLIST);
+ mnldinf_put_int(buff, &offset, size);
+ mnldinf_put_binary(buff, &offset, (const char*)blacklist, sizeof(long long)*size);
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_set_correction(int fd, measurement_corrections* corrections) {
+ LOGD("hal2mnl_set_correction\n");
+ int offset = 0;
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_CORRECTION);
+ mnldinf_put_binary(buff, &offset, (const char*)corrections, sizeof(measurement_corrections));
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_set_nfw_access(int fd, char* proxy_apps, int32_t length) {
+ LOGD("mnldinf_ext_set_nfw_access, proxy_apps:%s, len:%d\n", proxy_apps, length);
+ int offset = 0;
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_NFW_ACCESS);
+ mnldinf_put_int(buff, &offset, length);
+ mnldinf_put_string(buff, &offset, proxy_apps);
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+int mnldinf_ext_set_ttff_acc(int fd, ttff_acc acc_mode) {
+ LOGD("set TTFF acc:%d\n", acc_mode);
+ int offset = 0;
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_SET_TTFF_ACC);
+ mnldinf_put_int(buff, &offset, acc_mode);
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+// -1 means failure
+int mnldinf_ext_cmd_hdlr(int fd, mnldinf_ext* hdlr) {
+ char buff[HAL_MNL_BUFF_SIZE_SND] = {0};
+ char buff_read[HAL_MNL_BUFF_SIZE_SND] = {0};
+ int offset = 0;
+ int ver;
+ mnl2hal_cmd cmd;
+ int read_len;
+ int ret = 0;
+ int msg_len = 0;
+
+ read_len = mnldinf_safe_recv(fd, buff_read, sizeof(buff_read));
+ if (read_len <= 0) {
+ close(fd);
+ if(hdlr->mnldinf_connection_broken) {
+ LOGW("Connection broken......");
+ hdlr->mnldinf_connection_broken();
+ }
+ LOGE("mnldinf_ext_cmd_hdlr() mnldinf_safe_recvfrom() failed read_len=%d, %s", read_len, strerror(errno));
+ return -1;
+ }
+
+ mnldinf_put_msg_to_cycle(&g_mnldinf_ext_cbuffer, buff_read, read_len);
+
+ while(mnldinf_get_one_msg(&g_mnldinf_ext_cbuffer, buff) > 0) {
+ offset = 0;
+
+ msg_len = mnldinf_get_int(buff, &offset, sizeof(buff)); //Get message length
+ UNUSED(msg_len);
+ ver = mnldinf_get_int(buff, &offset, sizeof(buff));
+ UNUSED(ver);
+ cmd = mnldinf_get_int(buff, &offset, sizeof(buff));
+ //LOGD("CMD:%d(0x%x)", cmd, cmd);
+ mnldinf_ext_cmd_enter_record(cmd);
+ switch (cmd) {
+ case MNL2HAL_REQUEST_WAKELOCK: {
+ if (hdlr->mnldinf_request_wakelock) {
+ LOGD("request_wakelock");
+ hdlr->mnldinf_request_wakelock();
+ } else {
+ LOGE("mnl2hal_hdlr() request_wakelock is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_RELEASE_WAKELOCK: {
+ if (hdlr->mnldinf_release_wakelock) {
+ hdlr->mnldinf_release_wakelock();
+ } else {
+ LOGE("mnl2hal_hdlr() release_wakelock is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_REQUEST_UTC_TIME: {
+ if (hdlr->mnldinf_request_utc_time) {
+ hdlr->mnldinf_request_utc_time();
+ } else {
+ LOGE("mnl2hal_hdlr() request_utc_time is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_REQUEST_DATA_CONN: {
+ if (hdlr->mnldinf_request_data_conn) {
+ struct sockaddr_storage addr;
+ agps_type type;
+ mnldinf_get_binary(buff, &offset, (char*)&addr, sizeof(buff), sizeof(addr));
+ type = mnldinf_get_int(buff, &offset, sizeof(buff));
+ hdlr->mnldinf_request_data_conn(&addr, type);
+ } else {
+ LOGE("mnl2hal_hdlr() request_data_conn is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_RELEASE_DATA_CONN: {
+ if (hdlr->mnldinf_release_data_conn) {
+ hdlr->mnldinf_release_data_conn();
+ } else {
+ LOGE("mnl2hal_hdlr() release_data_conn is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_REQUEST_NI_NOTIFY: {
+ if (hdlr->mnldinf_request_ni_notify) {
+ int session_id = mnldinf_get_int(buff, &offset, sizeof(buff));
+ agps_notify_type type = mnldinf_get_int(buff, &offset, sizeof(buff));
+ char* requestor_id = mnldinf_get_string(buff, &offset, sizeof(buff));
+ char* client_name = mnldinf_get_string(buff, &offset, sizeof(buff));
+ ni_encoding_type requestor_id_encoding = mnldinf_get_int(buff, &offset, sizeof(buff));
+ ni_encoding_type client_name_encoding = mnldinf_get_int(buff, &offset, sizeof(buff));
+ agps_ni_type ni_type = mnldinf_get_int(buff, &offset, sizeof(buff));
+ hdlr->mnldinf_request_ni_notify(session_id, ni_type, type, requestor_id, client_name,
+ requestor_id_encoding, client_name_encoding);
+ } else {
+ LOGE("mnl2hal_hdlr() request_ni_notify is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_REQUEST_SET_ID: {
+ if (hdlr->mnldinf_request_set_id) {
+ request_setid flags = mnldinf_get_int(buff, &offset, sizeof(buff));
+ hdlr->mnldinf_request_set_id(flags);
+ } else {
+ LOGE("mnl2hal_hdlr() request_set_id is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_REQUEST_REF_LOC: {
+ if (hdlr->mnldinf_request_ref_loc) {
+ request_refloc flags = mnldinf_get_int(buff, &offset, sizeof(buff));
+ hdlr->mnldinf_request_ref_loc(flags);
+ } else {
+ LOGE("mnl2hal_hdlr() request_ref_loc is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_VZW_DEBUG_OUTPUT: {
+ if (hdlr->mnldinf_output_vzw_debug) {
+ char* str = mnldinf_get_string(buff, &offset, sizeof(buff));
+ hdlr->mnldinf_output_vzw_debug(str);
+ } else {
+ LOGE("mnl2hal_hdlr() output_vzw_debug is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_UPDATE_GNSS_NAME: {
+ if (hdlr->mnldinf_update_gnss_name) {
+ int length = mnldinf_get_int(buff, &offset, sizeof(buff));
+ char* name = mnldinf_get_string(buff, &offset, sizeof(buff));
+ hdlr->mnldinf_update_gnss_name(name, length);
+ } else {
+ LOGE("mnl2hal_hdlr() update_gnss_name is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_REQUEST_NLP: {
+ if (hdlr->mnldinf_request_nlp) {
+ bool independent_from_gnss = mnldinf_get_byte(buff, &offset, sizeof(buff));
+ bool is_user_emergency = mnldinf_get_byte(buff, &offset, sizeof(buff));
+ hdlr->mnldinf_request_nlp(independent_from_gnss, is_user_emergency);
+ } else {
+ LOGE("mnl2hal_hdlr() update_gnss_name is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_GNSS_NAVIGATION: {
+ if (hdlr->mnldinf_gnss_navigation_msg) {
+ gnss_nav_msg msg;
+ memset(&msg, 0, sizeof(msg));
+ mnldinf_get_binary(buff, &offset, (char*)&msg, sizeof(buff), sizeof(gnss_nav_msg));
+ hdlr->mnldinf_gnss_navigation_msg(&msg);
+ } else {
+ LOGE("mnl2hal_hdlr() gnss_navigation is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_NFW_NOTIFY: {
+ if (hdlr->mnldinf_nfw_access_notify) {
+ mnldinf_nfw_notification nfw_notify;
+ memset(&nfw_notify, 0, sizeof(mnldinf_nfw_notification));
+ mnldinf_get_binary(buff, &offset, (char*)&nfw_notify, sizeof(buff), sizeof(mnldinf_nfw_notification));
+ hdlr->mnldinf_nfw_access_notify(&nfw_notify);
+ } else {
+ LOGE("mnldinf_nfw_access_notify() is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_EXT_CAP_SYNC: {
+ if(hdlr->mnldinf_capability_update) {
+ mnldinf_ext_server_cap cap;
+ memset(&cap, 0, sizeof(cap));
+ mnldinf_get_binary(buff, &offset, (char *)&cap, sizeof(buff), sizeof(cap));
+ //DUMP_EXT_SERVER_CAP(&cap);
+ hdlr->mnldinf_capability_update(&cap);
+ } else {
+ LOGE("mnldinf_capability_update() is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_AGPS_LOCATION: {
+ if (hdlr->mnldinf_agps_location_update) {
+ mnldinf_agps_location location;
+ memset(&location, 0, sizeof(location));
+ mnldinf_get_binary(buff, &offset, (char*)&location, sizeof(buff), sizeof(mnldinf_agps_location));
+ hdlr->mnldinf_agps_location_update(location);
+ } else {
+ LOGE("mnl2hal_hdlr() location is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ default: {
+ LOGE("mnl2hal_hdlr() unknown cmd=%d", cmd);
+ ret = -1;
+ break;
+ }
+ }
+ mnldinf_ext_cmd_exit_record(cmd);
+ }
+
+ return ret;
+}
+
+void mnldinf_ext_structure_size_dump(void) {
+ PRINT_SIZE(gnss_nav_msg);
+ PRINT_SIZE(mnldinf_nfw_notification);
+ PRINT_SIZE(mnldinf_ext_server_cap);
+ PRINT_SIZE(measurement_corrections);
+ PRINT_SIZE(mnldinf_ext_client_cap);
+}
+
+int mnldinf_ext_register(char *client_name) {
+ int fd = -1;
+
+ fd = mnldinf_socket_tcp_client_connect_local(true, MNLDINF_EXT_TCP);
+ //LOGD("New client:[%s], fd:%d", client_name, fd);
+ //mnldinf_ext_structure_size_dump();
+
+ mnldinf_socket_set_blocking(fd, 0); //Set as non-blocking
+ mnldinf_buffer_initialize(&g_mnldinf_ext_cbuffer, g_mnldinf_ext_msg_buf, sizeof(g_mnldinf_ext_msg_buf));
+
+ mnldinf_ext_cmd_list_init();
+ return fd;
+}
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_log.c b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_log.c
new file mode 100755
index 0000000..7dfc898
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_log.c
@@ -0,0 +1,112 @@
+/*
+* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2017. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*/
+#include <sys/time.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+#include <memory.h>
+
+#include "mnldinf_log.h"
+
+int log_dbg_level = mnldinf_LOG_LEVEL;
+
+//#if defined(__LINUX_OS__)
+#if !defined(__ANDROID_OS__)
+// -1 means failure
+int mnldinf_get_time_str(char* buf, int len) {
+ time_t now = time(NULL);
+ struct tm tm_utc;
+ time_t time_utc;
+
+ gmtime_r(&now, &tm_utc);
+ time_utc = mktime(&tm_utc);
+
+ memset(buf, 0, len);
+ sprintf(buf, "%s", ctime(&time_utc));
+
+ buf[strlen(buf)-1] = '\0'; //Remove '\n'
+
+ return 0;
+}
+#endif
+
+int set_log_level(int *dst_level, int src_level)
+{
+#if defined(__ANDROID_OS__)
+
+ ALOGI("Current debug level=%d", *dst_level);
+
+ if (src_level < L_VERBOSE || src_level > L_SUPPRESS)
+ {
+ ALOGE("Invalid debug level, level=%d", src_level);
+ ALOGE(" [level] -");
+ ALOGE(" QUIET = 6");
+ ALOGE(" ASSERT = 5");
+ ALOGE(" ERROR = 4");
+ ALOGE(" WARNING = 3");
+ ALOGE(" INFO = 2");
+ ALOGE(" DEBUG = 1");
+ ALOGE(" LOGALL = 0");
+ return -1;
+ }
+
+ *dst_level = src_level;
+
+ ALOGI("New debug level=%d", *dst_level);
+
+//#elif defined(__LINUX_OS__)
+#else
+ printf("Current debug level=%d\n", *dst_level);
+
+ if (src_level < L_VERBOSE || src_level > L_SUPPRESS)
+ {
+ printf("Invalid debug level, level=%d\n", src_level);
+ printf(" [level] -\n");
+ printf(" QUIET = 6\n");
+ printf(" ASSERT = 5\n");
+ printf(" ERROR = 4\n");
+ printf(" WARNING = 3\n");
+ printf(" INFO = 2\n");
+ printf(" DEBUG = 1\n");
+ printf(" LOGALL = 0\n");
+ return -1;
+ }
+
+ *dst_level = src_level;
+
+ printf("New debug level=%d\n", *dst_level);
+
+#endif
+ return 0;
+}
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_utility.c b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_utility.c
new file mode 100755
index 0000000..08723eb
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/src/mnldinf_utility.c
@@ -0,0 +1,821 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h> // usleep
+#include <sys/socket.h>
+#include <string.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 <stdbool.h>
+
+#include "mnldinf_utility.h"
+#include "mnldinf_log.h"
+#include "mnldinf_common.h"
+#include "mnldinf_data_coder.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mtk_lbs_utility"
+#endif
+#if 0
+#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 LOGD
+#endif
+void mnldinf_msleep(int interval) {
+ usleep(interval * 1000);
+}
+
+// in millisecond
+time_t mnldinf_get_tick() {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
+ LOGE("clock_gettime failed reason=[%s]", strerror(errno));
+ return -1;
+ }
+ return (ts.tv_sec*1000) + (ts.tv_nsec/1000000);
+}
+
+// in millisecond
+time_t mnldinf_get_time_in_millisecond() {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+ LOGE("mnldinf_get_time_in_millisecond failed reason=[%s]", strerror(errno));
+ return -1;
+ }
+ return ((long long)ts.tv_sec*1000) + ((long long)ts.tv_nsec/1000000);
+}
+
+//#ifdef __LINUX_OS__
+#if !defined(__ANDROID_OS__)
+/*************************************************
+* Timer
+**************************************************/
+// -1 means failure
+timer_t mnldinf_init_timer_id(timer_callback cb, int id) {
+ struct sigevent sevp;
+ timer_t timerid;
+
+ memset(&sevp, 0, sizeof(sevp));
+ sevp.sigev_value.sival_int = id;
+ sevp.sigev_notify = SIGEV_THREAD;
+ sevp.sigev_notify_function = cb;
+
+ if (timer_create(CLOCK_MONOTONIC, &sevp, &timerid) == -1) {
+ LOGE("timer_create failed reason=[%s]", strerror(errno));
+ return INVALID_TIMERID;
+ }
+ //LOGD("timerid init:%lu", (unsigned long)timerid);
+ return timerid;
+}
+
+// -1 means failure
+timer_t mnldinf_init_timer(timer_callback cb) {
+ return mnldinf_init_timer_id(cb, 0);
+}
+
+// -1 means failure
+int mnldinf_start_timer(timer_t timerid, int milliseconds) {
+ if(timerid != INVALID_TIMERID) {
+ struct itimerspec expire;
+ expire.it_interval.tv_sec = 0;
+ expire.it_interval.tv_nsec = 0;
+ expire.it_value.tv_sec = milliseconds/1000;
+ expire.it_value.tv_nsec = (milliseconds%1000)*1000000;
+ return timer_settime(timerid, 0, &expire, NULL);
+ } else {
+ LOGE("invalid timerid:%lu", (unsigned long)timerid);
+ return -1;
+ }
+}
+
+// -1 means failure
+int mnldinf_stop_timer(timer_t timerid) {
+ return mnldinf_start_timer(timerid, 0);
+}
+
+// -1 means failure
+int mnldinf_deinit_timer(timer_t timerid) {
+ LOGD("timerid deinit:%lu", (unsigned long)timerid);
+ if(timerid != INVALID_TIMERID) {
+ if (timer_delete(timerid) == -1) {
+ LOGE("timer_delete error:%s", strerror(errno));
+ return -1;
+ }
+ } else {
+ LOGE("invalid timerid:%lu", (unsigned long)timerid);
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int mnldinf_epoll_add_fd(int epfd, int fd) {
+ struct epoll_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.data.fd = fd;
+ ev.events = EPOLLIN;
+ // 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("mnldinf_epoll_add_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+ strerror(errno), errno, epfd, fd);
+ return -1;
+ }
+ return 0;
+}
+
+// -1 failed
+int mnldinf_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("mnldinf_epoll_add_fd2() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+ strerror(errno), errno, epfd, fd);
+ return -1;
+ }
+ return 0;
+}
+
+int mnldinf_epoll_del_fd(int epfd, int fd) {
+ struct epoll_event ev;
+ int ret;
+
+ if (epfd == -1)
+ return -1;
+
+ ev.events = EPOLLIN;
+ ev.data.fd = fd;
+ do {
+ ret = epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev);
+ } while (ret < 0 && errno == EINTR);
+ return ret;
+}
+
+// -1 failed
+int mnldinf_epoll_mod_fd(int epfd, int fd, uint32_t events) {
+ struct epoll_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.data.fd = fd;
+ ev.events = events;
+ if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1) {
+ LOGE("mnldinf_epoll_mod_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+ strerror(errno), errno, epfd, fd);
+ return -1;
+ }
+ return 0;
+}
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int mnldinf_socket_bind_udp(const char* path) {
+ int fd;
+ struct sockaddr_un addr;
+
+ fd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ LOGE("mnldinf_socket_bind_udp() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ LOGD("fd=%d,path=%s\n", 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(path);
+
+ if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ LOGE("mnldinf_socket_bind_udp() bind() failed path=[%s] reason=[%s]%d",
+ addr.sun_path+1, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }else
+ LOGI("bind ok path=[%s]", addr.sun_path+1);
+ return fd;
+}
+
+// -1 means failure
+int mnldinf_socket_set_blocking(int fd, int blocking) {
+ if (fd < 0) {
+ LOGE("mnldinf_socket_set_blocking() invalid fd=%d", fd);
+ return -1;
+ }
+
+ int flags = fcntl(fd, F_GETFL, 0);
+ if (flags == -1) {
+ LOGE("mnldinf_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;
+}
+
+// -1 means failure
+int mnldinf_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("mnldinf_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) {
+ LOGE("errno==EINTR\n");
+ continue;
+ }
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ LOGE("errno==EAGAIN\n");
+ continue;
+ }
+ }
+ LOGE("mnldinf_safe_sendto() sendto() failed path=[%s] ret=%d reason=[%s]%d",
+ path, ret, strerror(errno), errno);
+ break;
+ }
+
+ close(fd);
+ return ret;
+}
+
+// -1 means failure
+int mnldinf_safe_recvfrom(int fd, char* buff, int len) {
+ int ret = 0;
+ int retry = 10;
+ 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;
+ }
+
+ while ((ret = recvfrom(fd, buff, len, 0,
+ NULL, NULL)) == -1) {
+ LOGW("mnldinf_safe_recvfrom() ret=%d len=%d", ret, len);
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("mnldinf_safe_recvfrom() recvfrom() failed reason=[%s]%d",
+ strerror(errno), errno);
+ break;
+ }
+ return ret;
+}
+
+/*
+------------------------
+| Length | Message Body |
+------------------------
+*/
+// -1 means failure
+int mnldinf_tcp_send(int fd, const char* buff, int len) {
+ char buff_send[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ mnldinf_put_binary(buff_send, &offset, buff, len); //Put length to the head
+
+ int ret = write(fd, buff_send, offset);
+ if(ret == -1) {
+ LOGE(" write() failed, reason=[%s]%d", strerror(errno), errno);
+ }
+
+ //LOGD("send %d, ret %d", len, ret);
+ return ret;
+}
+
+int mnldinf_safe_recv(int fd, char* buff, int len) {
+ int ret = 0;
+ int retry = 10;
+
+ while ((ret = read(fd, buff, len)) == -1) {
+ LOGW("mnldinf_safe_recvfrom() ret=%d len=%d", ret, len);
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("mnldinf_safe_recvfrom() recvfrom() failed reason=[%s]%d",
+ strerror(errno), errno);
+ break;
+ }
+ return ret;
+}
+
+
+/******************************************************************************
+* Socket
+******************************************************************************/
+
+//-1 means fail or serverfd is returned
+int mnldinf_socket_tcp_server_bind_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 {
+ MNLD_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ if(unlink(addr.sun_path) == -1) {
+ LOGW("mnldinf_socket_tcp_server_bind_local() unlink() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(fd == -1) {
+ LOGE("mnldinf_socket_tcp_server_bind_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(bind(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("mnldinf_socket_tcp_server_bind_local() bind() failed, abstruct=%d name=[%s] reason=[%s]%d",
+ abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ if(listen(fd, 5) == -1) {
+ LOGW("mnldinf_socket_tcp_server_bind_local() listen() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ return fd;
+}
+
+//-1 means fail or new clientfd is returned
+int mnldinf_socket_tcp_server_new_connect(int serverfd) {
+ int newfd;
+ struct sockaddr_in addr;
+ socklen_t len = sizeof(addr);
+
+ newfd = accept(serverfd, (struct sockaddr*)&addr, &len);
+ if(newfd == -1) {
+ LOGE("mnldinf_socket_tcp_server_new_connect() accept() failed, serverfd=%d reason=[%s]%d",
+ serverfd, strerror(errno), errno);
+ return -1;
+ }
+ return newfd;
+}
+
+//-1 means fail or serverfd is returned
+int mnldinf_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 {
+ MNLD_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ if(unlink(addr.sun_path) == -1) {
+ LOGW("mnldinf_socket_tcp_client_connect_local() unlink() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(fd == -1) {
+ LOGE("mnldinf_socket_tcp_client_connect_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(connect(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("mnldinf_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;
+}
+
+
+//-1 means fail or serverfd is returned
+int mnldinf_socket_udp_server_bind_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 {
+ MNLD_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ if(unlink(addr.sun_path) == -1) {
+ LOGW("mnldinf_socket_udp_server_bind_local() unlink() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ LOGE("mnldinf_socket_udp_server_bind_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(bind(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("mnldinf_socket_udp_server_bind_local() bind() failed, abstract=%d name=[%s] reason=[%s]%d",
+ abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+//-1 means fail or clientfd is returned
+int mnldinf_socket_udp_client_create_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 {
+ MNLD_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ LOGE("mnldinf_socket_udp_client_create_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(connect(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("mnldinf_socket_udp_client_create_local() connect() failed, abstract=%d name=[%s] reason=[%s]%d",
+ abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+bool mnldinf_socket_udp_exist_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 {
+ MNLD_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ LOGE("socket_udp_is_bind_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return false;
+ }
+ if(connect(fd, (struct sockaddr*)&addr, size) == -1) {
+ close(fd);
+ return false;
+ }
+ close(fd);
+ return true;
+
+}
+
+void mnldinf_buffer_initialize(cyclical_buffer_t *buffer, char *buffer_body, unsigned int buffer_size) {
+ // Set up buffer manipulation pointers
+ // end_buffer points to the next byte after the buffer
+ buffer->start_buffer = buffer_body;
+ 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 mnldinf_put_msg_to_cycle(cyclical_buffer_t *cyc_buffer, char *buff, int len) {
+ int i;
+#ifdef MNLDINF_DUMP_CMD_RAW
+ LOGD("mnldinf_put_msg_to_cycle:%d", len);
+#endif
+ for (i = 0; i < len; i++)
+ {
+ *(cyc_buffer->next_write++) = buff[i];
+ if (cyc_buffer->next_write == cyc_buffer->end_buffer){
+ cyc_buffer->next_write = cyc_buffer->start_buffer;
+ }
+
+ if (cyc_buffer->next_write == cyc_buffer->next_read){
+ #ifdef MNLDINF_DUMP_CMD_RAW
+ LOGE("mnldinf_put_msg_to_cycle buffer full!\r\n");
+ #endif
+ return -1;
+ }
+ }
+
+ return 0;
+}
+/******************************************
+Get one message from cycle buffer
+******************************************/
+int mnldinf_get_one_msg(cyclical_buffer_t *cyc_buffer, char *buff) {
+ char *next_write, *next_read;
+ int data_size, i, header_len;
+ char buffer[HAL_MNL_BUFF_SIZE_SND] = {0};
+ int data_len = 0;
+ int return_len = 0;
+
+ next_write = cyc_buffer->next_write;
+ next_read = cyc_buffer->next_read;
+ if (cyc_buffer->next_read == next_write)
+ {
+ //buffer empty
+ return -1;
+ }
+
+ header_len = sizeof(int);
+ /*Compute data length*/
+ if (cyc_buffer->next_read < next_write)
+ {
+ data_size = (unsigned long)next_write - (unsigned long)cyc_buffer->next_read;
+ }
+ else
+ {
+ data_size = (unsigned long)cyc_buffer->end_buffer - (unsigned long)cyc_buffer->next_read +
+ (unsigned long)next_write - (unsigned long)cyc_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 == cyc_buffer->end_buffer){
+ next_read = cyc_buffer->start_buffer;
+ }
+ }
+
+ memcpy(&data_len, buffer, sizeof(int));
+ #ifdef MNLDINF_DUMP_CMD_RAW
+ LOGD("data len:%d, header len:%d", data_len, header_len);
+ #endif
+ if (data_len <= data_size) {
+ for (i = 0; i < (data_len + header_len); i++)
+ {
+ buff[i] = *(cyc_buffer->next_read++);
+ #ifdef MNLDINF_DUMP_CMD_RAW
+ LOGD("0x%x", buff[i]);
+ #endif
+ return_len++;
+ if (cyc_buffer->next_read == cyc_buffer->end_buffer){
+ cyc_buffer->next_read = cyc_buffer->start_buffer;
+ }
+ }
+ }
+ else {
+ LOGD("func:%s, line:%d, no enough data", __func__, __LINE__);
+ //no enough data
+ return -2;
+ }
+
+ }
+ else
+ {
+ LOGD("func:%s, line:%d, no enough data", __func__, __LINE__);
+ //no enough data
+ return -2;
+ }
+
+ return return_len;
+}
+
+wake_lock_ctx wlock_ctx;
+
+void mnldinf_wake_lock() {
+ int fd = open("/sys/power/wake_lock", O_RDWR | O_NONBLOCK);
+ if(fd == -1) {
+ LOGE("open() failed, reason=[%s]%d", strerror(errno), errno);
+ return;
+ }
+
+ int ret = write(fd, MNLDINF_WAKE_LOCK_ID, strlen(MNLDINF_WAKE_LOCK_ID));
+ if(ret == -1) {
+ LOGE("write() failed id=[%s], reason=[%s]%d", MNLDINF_WAKE_LOCK_ID, strerror(errno), errno);
+ close(fd);
+ return;
+ }
+
+ close(fd);
+
+ return;
+}
+
+void mnldinf_wake_unlock() {
+ int fd = open("/sys/power/wake_unlock", O_RDWR | O_NONBLOCK);
+ if(fd == -1) {
+ LOGE("open() failed, reason=[%s]%d", strerror(errno), errno);
+ return;
+ }
+
+ int ret = write(fd, MNLDINF_WAKE_LOCK_ID, strlen(MNLDINF_WAKE_LOCK_ID));
+ if(ret == -1) {
+ LOGE("write() failed id=[%s], reason=[%s]%d", MNLDINF_WAKE_LOCK_ID, strerror(errno), errno);
+ close(fd);
+ return;
+ }
+
+ close(fd);
+
+ return;
+}
+
+int mnldinf_wakeup_mutex_lock() {
+ int ret = pthread_mutex_lock(&wlock_ctx.mutex);
+ if(ret != 0) {
+ LOGE("pthread_mutex_lock() failed, reason=[%s]%d", strerror(ret), ret);
+ }
+
+ return ret;
+}
+
+int mnldinf_wakeup_mutex_unlock() {
+ int ret = pthread_mutex_unlock(&wlock_ctx.mutex);
+ if(ret != 0) {
+ LOGE("pthread_mutex_unlock() failed, reason=[%s]%d", strerror(ret), ret);
+ }
+
+ return ret;
+}
+
+void mnldinf_wake_lock_take() {
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+ time_t time_cur = 0;
+ time_cur = mnldinf_get_time_in_millisecond();
+
+ if(time_cur > (wlock_ctx.time_last_refresh + MNLDINF_WAKE_LOCK_LATENCY)) {
+ int mutex_ret = 0;
+ mnldinf_stop_timer(wlock_ctx.unlock_timer);
+ mutex_ret = mnldinf_wakeup_mutex_lock();
+ if(wlock_ctx.wake_lock_acquired == false) {
+ wlock_ctx.wake_lock_acquired = true;
+ mnldinf_wake_lock();
+ }
+ if(mutex_ret == 0) {
+ mnldinf_wakeup_mutex_unlock();
+ }
+ }
+#endif
+}
+
+void mnldinf_wake_lock_give() {
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+ time_t time_cur = 0;
+ //delay to do wake_unlock to ensure the msg can be deliveried to other process
+ time_cur = mnldinf_get_time_in_millisecond();
+ if(time_cur > (wlock_ctx.time_last_refresh + MNLDINF_WAKE_LOCK_LATENCY)) { //Only refresh timer when over latency time
+ mnldinf_start_timer(wlock_ctx.unlock_timer, MNLDINF_WAKE_LOCK_TIMEOUT);
+ wlock_ctx.time_last_refresh = mnldinf_get_time_in_millisecond();
+ }
+#endif
+}
+
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+static void mnldinf_timer_wake_unlock_routine(int id) {
+ int mutex_ret = 0;
+ //do not use the internal msg or it will cause infinite loop in epoll_wait
+ mutex_ret = mnldinf_wakeup_mutex_lock();
+ if(wlock_ctx.wake_lock_acquired == true) {
+ wlock_ctx.wake_lock_acquired = false;
+ mnldinf_wake_unlock();
+ }
+ if(mutex_ret == 0) {
+ mnldinf_wakeup_mutex_unlock();
+ }
+}
+#endif
+
+void mnldinf_wake_lock_init() {
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+ int ret = 0;
+ int read_len = 0;
+ char buff_read[HAL_MNL_BUFF_SIZE] = {0};
+
+ int fd = open("/sys/power/wake_lock", O_RDWR | O_NONBLOCK);
+ if(fd == -1) {
+ LOGE("open() failed, reason=[%s]%d", strerror(errno), errno);
+ return;
+ }
+
+ read_len = read(fd, buff_read, sizeof(buff_read)-1);
+ buff_read[HAL_MNL_BUFF_SIZE -1] = 0;
+ if(read_len >= strlen(MNLDINF_WAKE_LOCK_ID) && strstr(buff_read, MNLDINF_WAKE_LOCK_ID) != NULL) {
+ mnldinf_wake_unlock();
+ }
+ LOGD("wake_lock:[%s]", buff_read);
+ close(fd);
+
+ memset(&wlock_ctx, 0, sizeof(wlock_ctx));
+ wlock_ctx.wake_lock_acquired = false;
+ wlock_ctx.unlock_timer = mnldinf_init_timer(mnldinf_timer_wake_unlock_routine);
+ if(wlock_ctx.unlock_timer == INVALID_TIMERID) {
+ LOGE("init_timer(mnldinf_timer_wake_unlock_routine, 0) failed");
+ exit(1);
+ }
+
+ ret = pthread_mutex_init(&wlock_ctx.mutex, NULL);
+ if(ret != 0) {
+ LOGE("pthread_mutex_init() failed, reason=[%s]%d", strerror(errno), errno);
+ exit(1);
+ }
+#endif
+}
+
+void mnldinf_wake_lock_deinit() {
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+ int read_len = 0;
+ char buff_read[HAL_MNL_BUFF_SIZE] = {0};
+
+ int fd = open("/sys/power/wake_lock", O_RDWR | O_NONBLOCK);
+ if(fd == -1) {
+ LOGE("open() failed, reason=[%s]%d", strerror(errno), errno);
+ return;
+ }
+
+ read_len = read(fd, buff_read, sizeof(buff_read)-1);
+ buff_read[HAL_MNL_BUFF_SIZE -1] = 0;
+ if(read_len >= strlen(MNLDINF_WAKE_LOCK_ID) && strstr(buff_read, MNLDINF_WAKE_LOCK_ID) != NULL) {
+ mnldinf_wake_unlock();
+ }
+ LOGD("wake_lock:[%s]", buff_read);
+ close(fd);
+ mnldinf_deinit_timer(wlock_ctx.unlock_timer);
+ wlock_ctx.unlock_timer = INVALID_TIMERID;
+ pthread_mutex_destroy(&wlock_ctx.mutex);
+#endif
+}
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mnldinf/test/Makefile b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/test/Makefile
new file mode 100755
index 0000000..2778181
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/test/Makefile
@@ -0,0 +1,53 @@
+CC=gcc
+CXX=g++
+
+FLAGS=\
+ -g \
+ -Wall \
+ -D __COMPILE_OPTION__ \
+ -D __LINUX_OS__ \
+
+# -m32 \
+
+CPPFLAGS=\
+ -std=c++11 \
+
+INCLUDE=\
+ -I./ \
+ -I../inc/ \
+
+LIBS=\
+ -ldl \
+ -lrt \
+ -lpthread \
+
+CXXSRC=\
+
+CSRC=\
+ mnldinf_client.c \
+ ../src/mnldinf_data_coder.c \
+ ../src/mnldinf_basic.c \
+ ../src/mnldinf_ext.c \
+ ../src/mnldinf_log.c \
+ ../src/mnldinf_utility.c
+
+EXECUTABLE=mnldinf_test
+COBJS=$(CSRC:.c=.o)
+CXXOBJS=$(CXXSRC:.cpp=.o)
+
+all: $(EXECUTABLE)
+
+$(EXECUTABLE): $(COBJS) $(CXXOBJS)
+ $(CC) $(COBJS) $(CXXOBJS) $(LIBS) $(FLAGS) $(CPPFLAGS) -o $@
+
+%.o : %.c
+ $(CC) -c $(FLAGS) $(INCLUDE) -o $@ $<
+
+%.o : %.cpp
+ $(CC) -c $(FLAGS) $(INCLUDE) $(CPPFLAGS) -o $@ $<
+
+.PHONY: clean
+clean:
+ rm -f $(EXECUTABLE) rm -rf *.o
+ rm -rf $(COBJS)
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mnldinf/test/mnldinf_client.c b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/test/mnldinf_client.c
new file mode 100644
index 0000000..c1293f0
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/test/mnldinf_client.c
@@ -0,0 +1,337 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <sys/epoll.h> //epoll
+
+#include "mnldinf_ext.h"
+#include "mnldinf_basic.h"
+
+#include "mnldinf_utility.h"
+#include "mnldinf_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnldinftest"
+#endif
+#define MNLD_TEST "mnldinf_test"
+
+#define MAX_EPOLL_EVENT 10
+
+int mnldinf_basic_fd = -1;
+int mnldinf_ext_fd = -1;
+
+//=========================================================
+
+void dump_gps_location(gps_location location) {
+ LOGD("[dump_gps_location]flags:%d, lat:%f, lng:%f, alt:%f, speed:%f, bearing:%f, h_accuracy:%f, v_acc:%f, s_acc:%f, b_acc:%f, timestamp:%ld, pdop:%.2f, hdop:%.2f, vdop:%.2f"
+ , location.flags, location.lat, location.lng, location.alt, location.speed, location.bearing
+ , location.h_accuracy, location.v_accuracy, location.s_accuracy, location.b_accuracy, location.timestamp
+ , location.pdop, location.hdop, location.vdop);
+}
+
+void dump_gnss_sv_info(gnss_sv_info sv) {
+ unsigned int i = 0;
+ LOGD("[dump_gnss_sv_info], sv_num:%d", sv.num_svs);
+ for(i = 0; i < sv.num_svs; i++) {
+ LOGD("SV[%d], cons:%d, Cn0dBHz:%f, elev:%f, azim:%f, flags:%d, cf:%f"
+ , sv.sv_list[i].svid, sv.sv_list[i].constellation, sv.sv_list[i].c_n0_dbhz, sv.sv_list[i].elevation
+ , sv.sv_list[i].azimuth, sv.sv_list[i].flags, sv.sv_list[i].carrier_frequency);
+ }
+}
+
+static void update_location(gps_location location) {
+ LOGD("");
+ dump_gps_location(location);
+}
+
+static void update_gps_status(gps_status status) {
+ LOGD("status=%d", status);
+}
+
+static void update_gps_sv(gnss_sv_info sv) {
+ LOGD("");
+ dump_gnss_sv_info(sv);
+}
+
+#define MNLD_TEST_CMD_CNT_MAX 5
+#define GPS_DELETE_EPHEMERIS 0x0001
+#define GPS_DELETE_ALMANAC 0x0002
+#define GPS_DELETE_POSITION 0x0004
+#define GPS_DELETE_TIME 0x0008
+#define GPS_DELETE_IONO 0x0010
+#define GPS_DELETE_UTC 0x0020
+#define GPS_DELETE_HEALTH 0x0040
+#define GPS_DELETE_SVDIR 0x0080
+#define GPS_DELETE_SVSTEER 0x0100
+#define GPS_DELETE_SADATA 0x0200
+#define GPS_DELETE_RTI 0x0400
+#define GPS_DELETE_CELLDB_INFO 0x8000
+#define GPS_DELETE_ALL 0xFFFF
+
+#define DUMP_BASIC_CAP(cap) do {\
+ LOGD("[%s]:gnss_support=%d", __func__, (cap)->support_gnss);\
+} while(0)
+
+#define DUMP_EXT_CAP(cap) do {\
+ LOGD("[%s]:gnss_support=%d", __func__, (cap)->support_gnss);\
+} while(0)
+
+static void update_nmea(int64_t timestamp, const char* nmea, int length) {
+ static int nmea_cnt = 100;
+ static int test_cnt = 1024;
+ /*LOGD("timestamp=%ld nmea=[%s] length=%d",
+ timestamp, nmea, length);*/
+ if(test_cnt > 0 && nmea_cnt-- == 0 && mnldinf_basic_fd > 0) {
+ if(test_cnt-- >= 0) {
+ mnldinf_basic_gnss_stop(mnldinf_basic_fd);
+ mnldinf_basic_gnss_cleanup(mnldinf_basic_fd);
+ LOGD("GPS restart cnt(%d)", 1024-test_cnt);
+
+ switch(test_cnt%4) {
+ case 0: //Hot
+ mnldinf_ext_gnss_delete_aiding_data(mnldinf_ext_fd, GPS_DELETE_RTI);
+ break;
+ case 1: //Warm
+ mnldinf_ext_gnss_delete_aiding_data(mnldinf_ext_fd, GPS_DELETE_EPHEMERIS);
+ break;
+ case 2: //Cold
+ mnldinf_ext_gnss_delete_aiding_data(mnldinf_ext_fd, GPS_DELETE_EPHEMERIS |
+ GPS_DELETE_POSITION | GPS_DELETE_TIME | GPS_DELETE_IONO |
+ GPS_DELETE_UTC | GPS_DELETE_HEALTH);
+ break;
+ case 3: //Full
+ mnldinf_ext_gnss_delete_aiding_data(mnldinf_ext_fd, GPS_DELETE_ALL);
+ break;
+ default:
+ mnldinf_ext_gnss_delete_aiding_data(mnldinf_ext_fd, GPS_DELETE_RTI);
+ break;
+ }
+ mnldinf_basic_gnss_init(mnldinf_basic_fd);
+ mnldinf_basic_gnss_start(mnldinf_basic_fd);
+
+ mnldinf_ext_set_ttff_acc(mnldinf_ext_fd, test_cnt%3);
+ nmea_cnt = 100; //Reset nmea_cnt
+ }
+ }
+}
+
+static void update_nmea_done(void) {
+ LOGD("NMEA Done!!!");
+}
+
+static void update_gnss_measurements(gnss_data *data) {
+ LOGD("");
+ //dump_gnss_data(data);
+}
+
+static void basic_capability_update(mnldinf_basic_server_cap *cap) {
+ mnldinf_basic_server_cap basic_server_cap;
+ mnldinf_basic_client_cap basic_client_cap = {
+ .support_gnss = true,
+ };
+
+ memcpy(&basic_server_cap, cap, sizeof(mnldinf_basic_server_cap));
+ mnldinf_basic_capability_config(mnldinf_basic_fd, &basic_client_cap);
+ DUMP_BASIC_CAP(&basic_client_cap);
+}
+
+static void ext_capability_update(mnldinf_ext_server_cap *cap) {
+ mnldinf_ext_server_cap ext_server_cap;
+ mnldinf_ext_client_cap ext_client_cap = {
+ .support_gnss = true,
+ };
+
+ memcpy(&ext_server_cap, cap, sizeof(mnldinf_ext_server_cap));
+ mnldinf_ext_capability_config(mnldinf_ext_fd, &ext_client_cap);
+ DUMP_EXT_CAP(&ext_client_cap);
+}
+
+static void update_gnss_navigation(gnss_nav_msg *msg) {
+ LOGD("");
+ //dump_gnss_nav_msg(msg);
+}
+
+static void request_wakelock() {
+ LOGD("");
+}
+static void release_wakelock() {
+ LOGD("");
+}
+static void request_utc_time() {
+ LOGD("");
+}
+static void request_data_conn(struct sockaddr_storage* addr, agps_type type) {
+ LOGD("");
+}
+static void release_data_conn() {
+ LOGD("");
+}
+static void request_ni_notify(int session_id, agps_ni_type ni_type, agps_notify_type type, const char* requestor_id,
+ const char* client_name, ni_encoding_type requestor_id_encoding,
+ ni_encoding_type client_name_encoding) {
+ /*LOGD(" session_id=%d type=%d requestor_id=[%s] client_name=[%s] requestor_id_encoding=%d client_name_encoding=%d",
+ session_id, type, requestor_id, client_name, requestor_id_encoding, client_name_encoding);*/
+ LOGD("");
+}
+static void request_set_id(request_setid flags) {
+ //LOGD(" flags=0x%x", flags);
+ LOGD("");
+}
+static void request_ref_loc(request_refloc flags) {
+ //LOGD(" flags=0x%x", flags);
+ LOGD("");
+}
+static void output_vzw_debug(const char* str) {
+ LOGD("");
+}
+
+static void update_gnss_name(const char* name, int length) {
+ LOGD("length=%d, name=%s", length, name);
+ LOGD("");
+}
+
+static void request_nlp(bool independent_from_gnss, bool is_user_emergency) {
+ LOGD("request nlp[%d], emergency:%d", independent_from_gnss, is_user_emergency);
+}
+
+void mnldtest_nfw_access_notify(mnldinf_nfw_notification nfw_notify) {
+ LOGD("");
+}
+
+void mnldtest_basic_connection_broken() {
+ LOGD("");
+}
+
+void mnldtest_ext_connection_broken() {
+ LOGD("");
+}
+
+void mnldtest_ext_agps_location_update(mnldinf_agps_location location){
+ LOGD("lat:%f, lng:%f, %lld, type:%d", location.latitude, location.longitude, location.timestamp, location.type);
+}
+
+static mnldinf_ext mnldinf_ext_cbs = {
+ mnldtest_ext_connection_broken,
+ request_wakelock,
+ release_wakelock,
+
+ request_utc_time,
+ request_nlp,
+ request_ni_notify,
+ request_data_conn,
+ release_data_conn,
+
+ request_set_id,
+ request_ref_loc,
+ output_vzw_debug,
+
+ update_gnss_name,
+ update_gnss_navigation,
+ mnldtest_nfw_access_notify,
+ ext_capability_update,
+ mnldtest_ext_agps_location_update,
+};
+
+static mnldinf_basic mnldinf_basic_cbs = {
+ mnldtest_basic_connection_broken,
+ update_location,
+ update_gps_status,
+ update_gps_sv,
+ update_nmea,
+ update_nmea_done,
+ update_gnss_measurements,
+ basic_capability_update,
+};
+
+static void mnld_client_stdin_hdlr(int fd) {
+
+}
+
+int main() {
+ LOGD("mnld interface start, version 1.00");
+
+ mnldinf_basic_fd = mnldinf_basic_register(MNLD_TEST);
+ if(mnldinf_basic_fd == -1) {
+ LOGE("mnldinf_basic_register failed: %s", strerror(errno));
+ exit(1);
+ }
+
+ mnldinf_ext_fd = mnldinf_ext_register(MNLD_TEST);
+ if(mnldinf_ext_fd == -1) {
+ LOGE("mnldinf_ext_register failed: %s", strerror(errno));
+ exit(1);
+ }
+
+ struct epoll_event events[MAX_EPOLL_EVENT];
+ int epfd = epoll_create(MAX_EPOLL_EVENT);
+ if(epfd == -1) {
+ LOGE("epoll_create() failed");
+ exit(1);
+ }
+
+ mnldinf_epoll_add_fd(epfd, mnldinf_basic_fd);
+ mnldinf_epoll_add_fd(epfd, mnldinf_ext_fd);
+
+ mnldinf_epoll_add_fd(epfd, STDIN_FILENO);
+
+ mnldinf_basic_gnss_init(mnldinf_basic_fd);
+
+ mnldinf_basic_gnss_start(mnldinf_basic_fd);
+ mnldinf_basic_gnss_measurement_enable(mnldinf_basic_fd, 1);
+ mnldinf_ext_epo_enable(mnldinf_ext_fd, 0x1);
+ long long sv_bl = 0xFAFA;
+ mnldinf_ext_set_sv_blacklist(mnldinf_ext_fd, &sv_bl, 16);
+
+ while(true) {
+ int i, n;
+ LOGD("wait event");
+ n = epoll_wait(epfd, events, MAX_EPOLL_EVENT, -1);
+ if(n == -1) {
+ if(errno == EINTR) {
+ continue;
+ } else {
+ LOGE("epoll_wait() failed reason=[%s]%d", strerror(errno), errno);
+ crash_with_log();
+ }
+ }
+
+ for(i = 0; i < n; i++) {
+ int fd = events[i].data.fd;
+ if(fd == mnldinf_basic_fd) {
+ if(events[i].events & EPOLLIN) {
+ LOGD("basic hdlr");
+ mnldinf_basic_cmd_hdlr(fd, &mnldinf_basic_cbs);
+ }
+ } else if(fd == mnldinf_ext_fd) {
+ if(events[i].events & EPOLLIN) {
+ LOGD("ext hdlr");
+ mnldinf_ext_cmd_hdlr(fd, &mnldinf_ext_cbs);
+ }
+ } else if(fd == STDIN_FILENO) {
+ if(events[i].events & EPOLLIN) {
+ mnld_client_stdin_hdlr(fd);
+ goto exit;
+ }
+ } else {
+ LOGE("unexpected fd=%d coming", fd);
+ crash_with_log();
+ }
+ }
+
+ }
+exit:
+ close(epfd);
+ close(mnldinf_basic_fd);
+ close(mnldinf_ext_fd);
+ return 0;
+}
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mnldinf/test/mnldinf_test.h b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/test/mnldinf_test.h
new file mode 100644
index 0000000..eb0de93
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mnldinf/test/mnldinf_test.h
@@ -0,0 +1,81 @@
+#ifndef __MNLD_TEST_H__
+#define __MNLD_TEST_H__
+
+#include"hal_mnl_interface_common.h"
+#include"gps_mtk.h"
+
+#define MNLD_TEST_CMD_OPEN "start"
+#define MNLD_TEST_CMD_CLOSE "stop"
+#define MNLD_TEST_CMD_NETWORK "network"
+#define MNLD_TEST_NETWORK_WIFI "wifi"
+#define MNLD_TEST_NETWORK_MOBILE "mobile"
+#define MNLD_TEST_NETWORK_ROAMING "roaming"
+#define MNLD_TEST_NETWORK_DISABLE "disable"
+
+#define MNL_VER_LEN 52
+#define MNL_UTC_TIME_LEN 11
+#define MNLD_TEST_TTFF_SESSION_BEGIN
+
+typedef enum{
+ MNLD_TEST_ACTION_UNKNOWN = -1,
+ MNLD_TEST_ACTION_GNSS_OPEN,
+ MNLD_TEST_ACTION_GNSS_CLOSE,
+ MNLD_TEST_ACTION_SET_NETWORK,
+ MNLD_TEST_ACTION_MAX
+} MNLD_TEST_ACTION;
+
+typedef enum{
+ MNLD_TEST_RESTART_TYPE_UNKNOWN = -1,
+ MNLD_TEST_RESTART_TYPE_HOT,
+ MNLD_TEST_RESTART_TYPE_WARM,
+ MNLD_TEST_RESTART_TYPE_COLD,
+ MNLD_TEST_RESTART_TYPE_FULL,
+ MNLD_TEST_RESTART_TYPE_MAX
+} MNLD_TEST_RESTART_TYPE;
+
+typedef enum{
+ CURR = 0,
+ MIN = 1,
+ MAX = 2,
+ MEAN = 3,
+ TTFF_NUM
+}MNLD_TEST_TTFF;
+
+typedef struct {
+ char chip_ver[12];
+ char mnl_ver[MNL_VER_LEN];
+ char clk_type;
+ char clk_buff;
+ int ttff[TTFF_NUM];//time-to-first_fix in ms
+ int fix_type;
+ GpsLocation_ext location;
+ char utc_time[MNL_UTC_TIME_LEN];
+}mnld_test_result;
+
+typedef struct{
+ char type_int;
+ char type_str[10];
+}clock_type;
+
+#define MNLD_TEST_CMD_CNT_MAX 5
+#define GPS_DELETE_EPHEMERIS 0x0001
+#define GPS_DELETE_ALMANAC 0x0002
+#define GPS_DELETE_POSITION 0x0004
+#define GPS_DELETE_TIME 0x0008
+#define GPS_DELETE_IONO 0x0010
+#define GPS_DELETE_UTC 0x0020
+#define GPS_DELETE_HEALTH 0x0040
+#define GPS_DELETE_SVDIR 0x0080
+#define GPS_DELETE_SVSTEER 0x0100
+#define GPS_DELETE_SADATA 0x0200
+#define GPS_DELETE_RTI 0x0400
+#define GPS_DELETE_CELLDB_INFO 0x8000
+#define GPS_DELETE_ALL 0xFFFF
+
+GpsCallbacks_ext* mnld_test__get_gps_callbacks(void);
+//GpsInterface* gps_device__get_gps_interface(struct gps_device_t* device);
+
+void mnld_test_show_test_result(mnld_test_result* result);
+void mnld_test_get_mnl_ver(void);
+
+#endif //__MNLD_TEST_H__
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mtk_agps_test_case.c b/src/connectivity/agps/2.0/lbs_em/src/mtk_agps_test_case.c
new file mode 100755
index 0000000..bfe938a
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mtk_agps_test_case.c
@@ -0,0 +1,657 @@
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h> //usleep
+#include <sys/socket.h>
+#include <string.h>
+#include <fcntl.h>
+#include <arpa/inet.h> //inet_addr
+#include <sys/un.h> //struct sockaddr_un
+#include <sys/epoll.h>
+#include <poll.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <openssl/ssl.h>
+#include <pthread.h>
+#include <semaphore.h>
+
+#include "data_coder.h"
+#include "agps_interface.h"
+//#include "hal2mnl_interface.h"
+//#include "mnl2hal_interface.h"
+#include "mtk_lbs_utility.h"
+
+#ifdef LOGD
+#undef LOGD
+#endif
+#ifdef LOGE
+#undef LOGE
+#endif
+#define LOGD(...) { printf(__VA_ARGS__); fflush(stdout); }
+#define LOGE(...) { printf("\E[1;31;40m"); printf(__VA_ARGS__); printf("\E[0m"); fflush(stdout); }
+
+//------------------------- Utils --------------------------------
+// 2 file, 1 folder, 0 not exist
+static int is_path_exist(const char* path) {
+ struct stat s;
+ int err = stat(path, &s);
+ if(-1 == err) {
+ if(ENOENT == errno) {
+ // does not exist
+ return 0;
+ } else {
+ // perror("stat");
+ return 0;
+ }
+ } else {
+ if(S_ISDIR(s.st_mode)) {
+ // it's a dir
+ return 1;
+ } else {
+ // it's a file
+ return 2;
+ }
+ }
+ return 0;
+}
+
+//-1 failure
+int create_file(char* path) {
+ FILE* fp = NULL;
+ fp = fopen(path, "w");
+ if(fp == NULL) {
+ LOGE("create_file fopen failure reason=[%s]\n", strerror(errno));
+ return -1;
+ }
+ fclose(fp);
+ return 0;
+}
+
+//-1 failure
+int delete_file(char* path) {
+ return remove(path);
+}
+
+// 0 timed out, -1 failure, others there is a input message
+static int poll_wait(int fd, int timeout) {
+ struct pollfd poll_fd[1];
+ int ret;
+
+ memset(poll_fd, 0, sizeof(poll_fd));
+ poll_fd[0].fd = fd;
+ poll_fd[0].events = POLLIN;
+ poll_fd[0].revents = 0;
+
+ ret = poll(poll_fd, 1, timeout);
+ if(ret > 0) {
+ if(poll_fd[0].revents & POLLIN ||
+ poll_fd[0].revents & POLLERR) {
+ ret = 1 << 0;
+ }
+ }
+ return ret;
+}
+
+static const char* get_ssl_info_where_string(int where) {
+ switch(where) {
+ case SSL_CB_LOOP:
+ return "LOOP";
+ case SSL_CB_EXIT:
+ return "EXIT";
+ case SSL_CB_READ:
+ return "READ";
+ case SSL_CB_WRITE:
+ return "WRITE";
+ case SSL_CB_ALERT:
+ return "ALERT";
+ case SSL_CB_READ_ALERT:
+ return "READ_ALERT";
+ case SSL_CB_WRITE_ALERT:
+ return "WRITE_ALERT";
+ case SSL_CB_ACCEPT_LOOP:
+ return "ACCEPT_LOOP";
+ case SSL_CB_ACCEPT_EXIT:
+ return "ACCEPT_EXIT";
+ case SSL_CB_CONNECT_LOOP:
+ return "CONNECT_LOOP";
+ case SSL_CB_CONNECT_EXIT:
+ return "CONNECT_EXIT";
+ case SSL_CB_HANDSHAKE_START:
+ return "HANDSHAKE_START";
+ case SSL_CB_HANDSHAKE_DONE:
+ return "HANDSHAKE_DONE";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static const char* get_ssl_error_string(int ret) {
+ switch(ret) {
+ case SSL_ERROR_NONE:
+ return "WANT_NONE";
+ case SSL_ERROR_ZERO_RETURN:
+ return "WANT_ZERO_RETURN";
+ case SSL_ERROR_WANT_READ:
+ return "WANT_READ";
+ case SSL_ERROR_WANT_WRITE:
+ return "WANT_WRITE";
+ case SSL_ERROR_WANT_CONNECT:
+ return "WANT_CONNECT";
+ case SSL_ERROR_WANT_ACCEPT:
+ return "WANT_ACCEPT";
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ return "WANT_X509_LOOKUP";
+ case SSL_ERROR_SYSCALL:
+ return "SYSCALL";
+ case SSL_ERROR_SSL:
+ return "SSL";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static const char* get_ssl_error_string2(const SSL* ssl, int ret) {
+ int err = SSL_get_error(ssl, ret);
+ return get_ssl_error_string(err);
+}
+
+static int mtk_socket_connect_network_ipv4(struct sockaddr_in* addr) {
+ int port = ntohs(addr->sin_port);
+ char ip_str[64] = {0};
+ inet_ntop(AF_INET, &(addr->sin_addr), ip_str, sizeof(ip_str));
+ int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (fd < 0) {
+ LOGE("mtk_socket_connect_network_ipv4() socket() failed reason=[%s]%d\n",
+ strerror(errno), errno);
+ return -1;
+ }
+ //SOCK_LOGD("mtk_socket_connect_network_ipv4() IPv4=[%s] port=[%d]", ip_str, port);
+ if (connect(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
+ LOGE("mtk_socket_connect_network_ipv4() connect() failed reason=[%s]%d for host=[%s] port=[%d]\n",
+ strerror(errno), errno, ip_str, port);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+//-1 means failure
+static int mtk_socket_connect_network_ipv6(struct sockaddr_in6* addr) {
+ int port = ntohs(addr->sin6_port);
+ int fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ if (fd < 0) {
+ LOGE("mtk_socket_connect_network_ipv6() socket() failed reason=[%s]%d\n",
+ strerror(errno), errno);
+ return -1;
+ }
+ //unsigned char* ipv6_addr = addr->sin6_addr.s6_addr;
+ //SOCK_LOGD("mtk_socket_connect_network_ipv6() IPv6=[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x] port=[%d]",
+ // ipv6_addr[0], ipv6_addr[1], ipv6_addr[2], ipv6_addr[3], ipv6_addr[4], ipv6_addr[5], ipv6_addr[6], ipv6_addr[7],
+ // ipv6_addr[8], ipv6_addr[9], ipv6_addr[10], ipv6_addr[11], ipv6_addr[12], ipv6_addr[13], ipv6_addr[14], ipv6_addr[15],
+ // port);
+ if (connect(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
+ LOGE("mtk_socket_connect_network_ipv6() connect() failed reason=[%s]%d for port=[%d]\n",
+ strerror(errno), errno, port);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+// return fd, -1 means failure
+static int mtk_socket_connect_network(const char* host, int port) {
+ int fd = 0;
+ struct addrinfo hints;
+ struct addrinfo *result;
+ struct addrinfo *rp;
+ int ret;
+ char port_str[11] = {0};
+ sprintf(port_str, "%u", port);
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6, AF_UNSPEC, AF_INET, AF_INET6
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_ADDRCONFIG; // check local system
+ hints.ai_protocol = IPPROTO_TCP;
+ ret = getaddrinfo(host, port_str, &hints, &result);
+ if(ret != 0) {
+ LOGE("mtk_socket_connect_network() getaddrinfo() failure reason=[%s] %d\n",
+ gai_strerror(ret), ret);
+ return -1;
+ }
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+ if(rp->ai_family == AF_INET) {
+ ret = mtk_socket_connect_network_ipv4((struct sockaddr_in*)rp->ai_addr);
+ if(ret >= 0) {
+ fd = ret;
+ break;
+ }
+ }
+ if(rp->ai_family == AF_INET6) {
+ ret = mtk_socket_connect_network_ipv6((struct sockaddr_in6*)rp->ai_addr);
+ if(ret >= 0) {
+ fd = ret;
+ break;
+ }
+ }
+ }
+ freeaddrinfo(result);
+ if(ret >= 0) {
+ return fd;
+ } else {
+ return -1;
+ }
+}
+
+//------------------------- Test Case Implementation --------------------------------
+#define AGPS_TEST_CASE_VERSION "1.00"
+#define SUPL_RAW_ENABLED "/data/agps_supl/supl_raw_enabled"
+#define MNLD_PATH "/usr/bin/mnld" //for MT2735 change, mnld0
+#define AGPSD_PATH "/usr/bin/mtk_agpsd"
+#define LBS_EM_PATH "/usr/bin/lbs_em_tool" //for MT2735 change, mtk_lbs_em_tool
+#define SUPL_SERVER_FQDN "supl.google.com"
+#define SUPL_SERVER_PORT 7275
+#define SUPL_SERVER_TLS 1
+#define GPS_DELETE_ALL 0xFFFF
+#define MNLD_POLL_TIMEOUT 5000
+#define AGPS_PROCESS_TIMEOUT (20 * 1000)
+#define AGPS_TLS_TIMEOUT (10 * 1000)
+
+#define SHOW_RESULT(is_continue_on_fail, error_count) {\
+ if(error_count > 0) {\
+ LOGD("Result [");\
+ LOGE("FAIL");\
+ LOGD("]\n");\
+ if(is_continue_on_fail) {\
+ error_count = 0; \
+ } else {\
+ goto exit;\
+ }\
+ } else {\
+ LOGD("Result [");\
+ printf("\E[1;32;40m");\
+ LOGD("SUCCESS");\
+ printf("\E[0m");\
+ LOGD("]\n");\
+ }\
+}
+#if 0
+// 1 is success, 0 need to wait the next message, -1 read process is failure
+static int read_and_check_sv_status(int fd) {
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ int ver;
+ mnl2hal_cmd cmd;
+ int read_len;
+ int ret = 0;
+
+ read_len = safe_recvfrom(fd, buff, sizeof(buff));
+ if (read_len <= 0) {
+ LOGE(" mnl2hal_hdlr() safe_recvfrom() failed read_len=%d\n", read_len);
+ return -1;
+ }
+ ver = get_int(buff, &offset);
+ UNUSED(ver);
+ cmd = get_int(buff, &offset);
+
+ if(cmd == MNL2HAL_GPS_SV) {
+ gnss_sv_info sv;
+ get_binary(buff, &offset, (char*)&sv);
+ LOGD(" read sv num=[%d]\n", sv.num_svs);
+ if(sv.num_svs >= 3) {
+ ret = 1;
+ }
+ }
+ return ret;
+}
+
+// return error_count
+static int test_case_gps_started(int is_continue_on_fail) {
+ int ret = 0;
+ int error_count = 0;
+
+ //---------------------------------------------------------
+ LOGD("5. Create MNL 2 HAL Interface\n");
+ int mnl_fd = create_mnl2hal_fd();
+ if(mnl_fd < 0) {
+ LOGE(" MNL 2 HAL Interface is not available, please check this issue with GPS team\n");
+ error_count++;
+ }
+
+ SHOW_RESULT(is_continue_on_fail, error_count);
+
+ //---------------------------------------------------------
+ LOGD("6. Monitor GPS and AGPS flow\n");
+ long long start_time = get_tick();
+ while(1) {
+ ret = poll_wait(mnl_fd, MNLD_POLL_TIMEOUT);
+ if(ret <= 0) {
+ LOGE(" No message sent from MNLD after starting GPS, please check this issue with GPS team\n");
+ error_count++;
+ break;
+ }
+ ret = read_and_check_sv_status(mnl_fd);
+ if(ret == 1) {
+ break;
+ } else if(ret < 0) {
+ LOGE(" The message sent from MNLD is incorrect, please check this issue with GPS team\n");
+ error_count++;
+ break;
+ }
+ long long time_used = get_tick() - start_time;
+ if(time_used >= AGPS_PROCESS_TIMEOUT) {
+ LOGE(" Cannot detect AGPS status with %d seconds, please check this issue with GPS/AGPS team\n",
+ AGPS_PROCESS_TIMEOUT / 1000);
+ error_count++;
+ break;
+ }
+ }
+
+ SHOW_RESULT(is_continue_on_fail, error_count);
+exit:
+ if(mnl_fd >= 0) {
+ close(mnl_fd);
+ }
+ return error_count;
+}
+#endif
+static void ssl_info_callback(const SSL *ssl, int where, int ret) {
+ if(ret == -1) {
+ int err = SSL_get_error(ssl, ret);
+ if(err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) {
+ LOGE(" ssl_info_callback() where=[%s] ssl_error=[%s] SSL_state=[%s]\n",
+ get_ssl_info_where_string(where), get_ssl_error_string2(ssl, ret),
+ SSL_state_string_long(ssl));
+ }
+ }
+}
+
+// 1 means success, 0 means failure
+static int ssl_cert_verify(X509_STORE_CTX *x509_ctx, void *arg) {
+ return 1;
+}
+
+static sem_t g_sem;
+static SSL* g_ssl;
+static int g_tls_result = 0; // 1 success, 0 fail
+
+static void* tls_event_thread(void *arg) {
+ #define MAX_EPOLL_EVENT 50
+ struct epoll_event events[MAX_EPOLL_EVENT];
+ long long start_time = get_tick();
+ int fd = *((int*)arg);
+ int epfd = epoll_create(MAX_EPOLL_EVENT);
+ if(epfd == -1) {
+ LOGE(" tls_event_thread() epoll_create() fail, reason=[%s]%d\n",
+ strerror(errno), errno);
+ goto exit;
+ }
+ epoll_add_fd3(epfd, fd);
+ g_tls_result = 0;
+
+ while(1) {
+ int i;
+ int n;
+
+ n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , 1000);
+ if(n == -1) {
+ if(errno == EINTR) {
+ continue;
+ } else {
+ LOGE(" tls_event_thread() epoll_wait() fail, reason=[%s]%d\n",
+ strerror(errno), errno);
+ break;
+ }
+ }
+
+ for(i = 0; i < n; i++) {
+ if(events[i].data.fd == fd && events[i].events & EPOLLIN) {
+ int ret = SSL_connect(g_ssl);
+ if(ret == 1) {
+ g_tls_result = 1;
+ goto exit;
+ } else if(ret == 0) {
+ goto exit;
+ }
+ }
+ }
+
+ long long time_used = get_tick() - start_time;
+ if(time_used >= AGPS_TLS_TIMEOUT) {
+ break;
+ }
+
+ }
+
+exit:
+ sem_post(&g_sem);
+ return 0;
+}
+
+// return < 0 means failure
+static int test_case_tls_handshaking(int fd) {
+ socket_set_blocking2(fd, 0);
+ SSL_library_init();
+
+ const SSL_METHOD* method = SSLv23_client_method();
+ SSL_CTX* ctx = SSL_CTX_new(method);
+ long option = SSL_CTX_get_options(ctx);
+ option = option & ~(SSL_OP_NO_SSLv2 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2);
+ option |= (SSL_OP_NO_SSLv2 | SSL_OP_NO_TLSv1_2);
+ SSL_CTX_set_options(ctx, option);
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL);
+ SSL_CTX_set_info_callback(ctx, ssl_info_callback);
+ SSL_CTX_set_cert_verify_callback(ctx, ssl_cert_verify, NULL);
+
+ g_ssl = SSL_new(ctx);
+ BIO *sbio = BIO_new_socket(fd, BIO_NOCLOSE);
+ SSL_set_bio(g_ssl, sbio, sbio);
+
+ pthread_t pthread1;
+ pthread_create(&pthread1, NULL, tls_event_thread, &fd);
+ msleep2(500);
+
+ int ret = SSL_connect(g_ssl);
+ if(ret == 1) {
+ //success
+ ret = 0;
+ goto exit;
+ } else if(ret < 0) {
+ int err = SSL_get_error(g_ssl, ret);
+ if(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
+ //create a thread for TLS handshaking
+ if(sem_init(&g_sem, 0, 0) == -1) {
+ LOGE(" sem_init() fail, reason=[%s], please check this issue with System team\n",
+ strerror(errno));
+ ret = -1;
+ goto exit;
+ }
+ sem_wait(&g_sem);
+ if(sem_destroy(&g_sem) == -1) {
+ LOGE(" sem_destroy() fail, reason=[%s], please check this issue with System team\n",
+ strerror(errno));
+ ret = -2;
+ goto exit;
+ }
+ if(g_tls_result == 1) {
+ ret = 0;
+ } else {
+ ret = -3;
+ }
+ goto exit;
+ } else {
+ //error 1
+ LOGE(" SSL_connect() failed reason=[%s]%d\n",
+ get_ssl_error_string(err), err);
+ ret = -4;
+ goto exit;
+ }
+ } else {
+ //error 2
+ LOGE(" SSL_connect() fail, reason=[%s], please check whether SUPL server is available by Tester\n",
+ get_ssl_error_string2(g_ssl, ret));
+ ret = -5;
+ goto exit;
+ }
+exit:
+ SSL_free(g_ssl);
+ SSL_CTX_free(ctx);
+ return ret;
+}
+
+// return error_count
+static int agps_test_case(int is_continue_on_fail, const char* host, int port, int tls) {
+ int ret = 0;
+ int error_count = 0;
+
+ LOGD("agps_test_case version=[%s] is_continue_on_fail=[%d] host=[%s] port=[%d] tls=[%d]\n",
+ AGPS_TEST_CASE_VERSION, is_continue_on_fail, host, port, tls);
+ create_file(SUPL_RAW_ENABLED);
+ //---------------------------------------------------------
+ LOGD("1. Check existance of [GPS Service], [AGPS Service] and [LBS EM Tool]\n");
+ ret = is_path_exist(MNLD_PATH);
+ if(ret != 2) {
+ LOGE(" [MNLD] does not exist under=[%s], please check this issue with GPS team\n",
+ MNLD_PATH);
+ error_count++;
+ }
+
+ ret = is_path_exist(AGPSD_PATH);
+ if(ret != 2) {
+ LOGE(" [AGPSD] does not exist under=[%s], please check this issue with AGPS team\n",
+ AGPSD_PATH);
+ error_count++;
+ }
+
+ ret = is_path_exist(LBS_EM_PATH);
+ if(ret != 2) {
+ LOGE(" [LBS EM Tool] does not exist under=[%s], please check this issue with AGPS team\n",
+ LBS_EM_PATH);
+ //error_count++; // optional checking, no need to set error_count
+ }
+
+ SHOW_RESULT(is_continue_on_fail, error_count);
+
+ //---------------------------------------------------------
+ // change AGPS Settings
+ set_agps_enabled(1);
+ set_protocol(AGPS_INTF_AGPS_PROTOCOL_UP);
+ set_cdma_pref(AGPS_INTF_CDMA_PREFERRED_WCDMA);
+ set_up_pref_method(AGPS_INTF_PREF_METHOD_MSB);
+ set_pos_technology_msb(1);
+ set_supl_version(2);
+ set_tls_version(AGPS_INTF_TLS_VERSION_1_1);
+ set_supl_profile(host, port, tls);
+
+ //---------------------------------------------------------
+ LOGD("2. Check Network Connection State with Server FQDN=[%s] port=[%d]\n", host, port);
+
+ ret = mtk_socket_connect_network(host, port);
+ if(ret < 0) {
+ LOGE(" Cannot connect to SUPL Server=[%s] with port=[%d], please check whether Network connection is available by Tester\n",
+ host, port);
+ error_count++;
+ } else {
+ if(tls) {
+ LOGD("2.1 Start TLS Handshaking\n");
+ if(test_case_tls_handshaking(ret) < 0) {
+ LOGE(" TLS Handshaking fail, please check SUPL Server is available by Tester\n");
+ error_count++;
+ }
+ }
+ }
+ close(ret);
+
+ SHOW_RESULT(is_continue_on_fail, error_count);
+
+#if 0 //mt2735 agps test not support below step.
+ //---------------------------------------------------------
+ LOGD("3. Do GPS Delete Aiding Data\n");
+ ret = hal2mnl_gps_delete_aiding_data(GPS_DELETE_ALL);
+ if(ret < 0) {
+ LOGE(" hal2mnl_gps_delete_aiding_data() Fail, please check this issue with GPS team\n");
+ error_count++;
+ }
+
+ SHOW_RESULT(is_continue_on_fail, error_count);
+
+ //---------------------------------------------------------
+ LOGD("4. Start GPS\n");
+ ret = hal2mnl_gps_init();
+ if(ret < 0) {
+ LOGE(" hal2mnl_gps_init() Fail, please check this issue with GPS team\n");
+ error_count++;
+ }
+ ret = hal2mnl_gps_start();
+ if(ret < 0) {
+ LOGE(" hal2mnl_gps_start() Fail, please check this issue with GPS team\n");
+ error_count++;
+ }
+
+ SHOW_RESULT(is_continue_on_fail, error_count);
+
+ //---------------------------------------------------------
+ test_case_gps_started(is_continue_on_fail);
+
+ //---------------------------------------------------------
+ LOGD("7. Stop GPS\n");
+ ret = hal2mnl_gps_stop();
+ if(ret < 0) {
+ LOGE(" hal2mnl_gps_stop() Fail, please check this issue with GPS team\n");
+ error_count++;
+ }
+
+ SHOW_RESULT(is_continue_on_fail, error_count);
+
+ //---------------------------------------------------------
+ LOGD("8. Cleanup GPS\n");
+ ret = hal2mnl_gps_cleanup();
+ if(ret < 0) {
+ LOGE(" hal2mnl_gps_cleanup() Fail, please check this issue with GPS team\n");
+ error_count++;
+ }
+
+ SHOW_RESULT(is_continue_on_fail, error_count);
+#endif
+
+exit:
+ // release all resouce here
+ delete_file(SUPL_RAW_ENABLED);
+ return error_count;
+}
+
+int main(int argc, char** argv) {
+ char host[128] = SUPL_SERVER_FQDN;
+ int port = SUPL_SERVER_PORT;
+ int tls = SUPL_SERVER_TLS;
+ int is_continue_on_fail = 0;
+
+ if(argc >= 2) {
+ is_continue_on_fail = atoi(argv[1]);
+ if(is_continue_on_fail) {
+ is_continue_on_fail = 1;
+ }
+ }
+
+ if(argc >= 3) {
+ strcpy(host, argv[2]);
+ }
+ if(argc >= 4) {
+ int tmp = atoi(argv[3]);
+ if(tmp != 0) {
+ port = tmp;
+ }
+ }
+ if(argc >= 5) {
+ tls = atoi(argv[4]);
+ if(tls) {
+ tls = 1;
+ }
+ }
+ return agps_test_case(is_continue_on_fail, host, port, tls);
+}
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_client.c b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_client.c
new file mode 100755
index 0000000..e11025f
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_client.c
@@ -0,0 +1,689 @@
+#include "mtk_gnss_at_command.h"
+#include "mtk_gnss_at_client.h"
+#include "mtk_gnss_at_log.h"
+
+bool mtk_at_send_gnss_start_request(int fd) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_start_request(buff, sizeof(buff));
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_stop_request(int fd) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_stop_request(buff, sizeof(buff));
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_host_reset_notify(int fd) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_host_reset_notify(buff, sizeof(buff));
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_status_request(int fd) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_status_request(buff, sizeof(buff));
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_enable_set(int fd, bool enabled) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_enable_set(buff, sizeof(buff), enabled);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_ni_enable_set(int fd, bool enabled) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_ni_enable_set(buff, sizeof(buff), enabled);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_agps_mode_set(int fd, mtk_gnss_agps_mode* mode) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_agps_mode_set(buff, sizeof(buff), mode);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_supl_version_set(int fd, int maj, int min, int ser_ind) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_supl_version_set(buff, sizeof(buff), maj, min, ser_ind);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_supl_addr_set(int fd, const char* addr, int port, bool tls_enabled) {
+ char buff[512] = {0};
+ mtk_at_gen_gnss_supl_addr_set(buff, sizeof(buff), addr, port, tls_enabled);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_delete_aiding_data_request(int fd, mtk_gnss_aiding_data* flags) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_delete_aiding_data_request(buff, sizeof(buff), flags);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_ni_notify_response(int fd, int id, mtk_gnss_ni_response_type response) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_ni_notify_response(buff, sizeof(buff), id, response);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_ref_location_response(int fd, int age, double lat, double lng, float acc) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_ref_location_response(buff, sizeof(buff), age, lat, lng, acc);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_ref_time_response(int fd, long long time, int uncertainty) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_ref_time_response(buff, sizeof(buff), time, uncertainty);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_nmea_config_set(int fd, bool enabled) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_nmea_config_set(buff, sizeof(buff), enabled);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_ttff_qop_set(int fd, int mode) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_ttff_qop_set(buff, sizeof(buff), mode);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_loopback_request(int fd, const char* msg) {
+ char buff[5000] = {0};
+ mtk_at_gen_gnss_loopback_request(buff, sizeof(buff), msg);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_cert_set(int fd, mtk_gnss_cert* cert) {
+ char buff[2000] = {0};
+ mtk_at_gen_gnss_cert_set(buff, sizeof(buff), cert);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_cert_name_request(int fd) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_cert_name_request(buff, sizeof(buff));
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_cert_delete_request(int fd, const char* name) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_cert_delete_request(buff, sizeof(buff), name);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_cert_delete_all_request(int fd) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_cert_delete_all_request(buff, sizeof(buff));
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_geo_max_num_request(int fd) {
+ char buff[64] = {0};
+ mtk_at_gen_geo_max_num_request(buff, sizeof(buff));
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_geo_add_circle_request(int fd, mtk_geo_add_circle* circle) {
+ char buff[128] = {0};
+ mtk_at_gen_geo_add_circle_request(buff, sizeof(buff), circle);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_geo_delete_request(int fd, int id) {
+ char buff[64] = {0};
+ mtk_at_gen_geo_delete_request(buff, sizeof(buff), id);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_geo_delete_all_request(int fd) {
+ char buff[64] = {0};
+ mtk_at_gen_geo_delete_all_request(buff, sizeof(buff));
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_test_request(int fd, int num1, int num2, double d1, double d2, const char* str1, const char* str2) {
+ char buff[3000] = {0};
+ mtk_at_gen_test_request(buff, sizeof(buff), num1, num2, d1, d2, str1, str2);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+static bool mtk_at_is_ok_parser(const char* at_cmd) {
+ char ok[] = "\r\nOK\r\n";
+ if(strcmp(at_cmd, ok) == 0) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static bool mtk_at_is_error_parser(const char* at_cmd) {
+ char error[] = "\r\nERROR\r\n";
+ if(strcmp(at_cmd, error) == 0) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static bool mtk_at_ok_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ if(callbacks->_mtk_at_result) {
+ callbacks->_mtk_at_result(fd, true, at_cmd);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_error_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ if(callbacks->_mtk_at_result) {
+ callbacks->_mtk_at_result(fd, false, at_cmd);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_nmea_notify_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ char nmea[512] = {0};
+ if(!mtk_at_parse_string(&at_cmd, nmea, sizeof(nmea))) {
+ LOGE("MTK_GNSS_AT_NMEA failed 1");
+ return false;
+ }
+
+ if(callbacks->_mtk_at_gnss_nmea_notify) {
+ callbacks->_mtk_at_gnss_nmea_notify(fd, nmea);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_nmea_end_notify_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ if(callbacks->_mtk_at_gnss_nmea_end_notify) {
+ callbacks->_mtk_at_gnss_nmea_end_notify(fd);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_satellite_notify_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ mtk_gnss_satellite_list list;
+ memset(&list, 0, sizeof(list));
+
+ if(!mtk_at_parse_int32(&at_cmd, &list.num)) {
+ LOGE("MTK_GNSS_AT_SATELLITE failed 1");
+ return false;
+ }
+ if(list.num > 64) {
+ LOGE("MTK_GNSS_AT_SATELLITE failed 2, num=%d > 64", list.num);
+ return false;
+ }
+
+ bool decode_ok = true;
+ int i = 0;
+ for(i = 0; i < list.num; i++) {
+ if(!mtk_at_parse_int32(&at_cmd, &list.satellites[i].svid)) {
+ LOGE("MTK_GNSS_AT_SATELLITE failed 3 i=%d", i);
+ decode_ok = false;
+ return false;
+ }
+ if(!mtk_at_parse_int32(&at_cmd, &list.satellites[i].constellation)) {
+ LOGE("MTK_GNSS_AT_SATELLITE failed 4 i=%d", i);
+ decode_ok = false;
+ return false;
+ }
+ if(!mtk_at_parse_float(&at_cmd, &list.satellites[i].cn0)) {
+ LOGE("MTK_GNSS_AT_SATELLITE failed 5 i=%d", i);
+ decode_ok = false;
+ return false;
+ }
+ if(!mtk_at_parse_float(&at_cmd, &list.satellites[i].elevation)) {
+ LOGE("MTK_GNSS_AT_SATELLITE failed 6 i=%d", i);
+ decode_ok = false;
+ return false;
+ }
+ if(!mtk_at_parse_float(&at_cmd, &list.satellites[i].azimuth)) {
+ LOGE("MTK_GNSS_AT_SATELLITE failed 7 i=%d", i);
+ decode_ok = false;
+ return false;
+ }
+ if(!mtk_at_parse_int32(&at_cmd, &list.satellites[i].flags)) {
+ LOGE("MTK_GNSS_AT_SATELLITE failed 8 i=%d", i);
+ decode_ok = false;
+ return false;
+ }
+ if(!mtk_at_parse_float(&at_cmd, &list.satellites[i].carrier_frequency)) {
+ LOGE("MTK_GNSS_AT_SATELLITE failed 9 i=%d", i);
+ decode_ok = false;
+ return false;
+ }
+ }
+
+ if(decode_ok) {
+ if(callbacks->_mtk_at_gnss_satellite_notify) {
+ callbacks->_mtk_at_gnss_satellite_notify(fd, &list);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_location_notify_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ mtk_gnss_location location;
+ memset(&location, 0, sizeof(location));
+ location.lat_valid = mtk_at_parse_double(&at_cmd, &location.lat);
+ location.lng_valid = mtk_at_parse_double(&at_cmd, &location.lng);
+ location.alt_valid = mtk_at_parse_float(&at_cmd, &location.alt);
+ location.speed_valid = mtk_at_parse_float(&at_cmd, &location.speed);
+ location.bearing_valid = mtk_at_parse_float(&at_cmd, &location.bearing);
+ location.h_acc_valid = mtk_at_parse_float(&at_cmd, &location.h_acc);
+ location.v_acc_valid = mtk_at_parse_float(&at_cmd, &location.v_acc);
+ location.s_acc_valid = mtk_at_parse_float(&at_cmd, &location.s_acc);
+ location.b_acc_valid = mtk_at_parse_float(&at_cmd, &location.b_acc);
+ location.timestamp_valid = mtk_at_parse_int64(&at_cmd, &location.timestamp);
+ location.date_time_valid = mtk_at_parse_string(&at_cmd, location.date_time, sizeof(location.date_time));
+ location.pdop_valid = mtk_at_parse_float(&at_cmd, &location.pdop);
+ location.hdop_valid = mtk_at_parse_float(&at_cmd, &location.hdop);
+ location.vdop_valid = mtk_at_parse_float(&at_cmd, &location.vdop);
+
+ if(callbacks->_mtk_at_gnss_location_notify) {
+ callbacks->_mtk_at_gnss_location_notify(fd, &location);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+
+}
+
+static bool mtk_at_gnss_agnss_location_notify_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ mtk_agnss_location location;
+ memset(&location, 0, sizeof(location));
+ mtk_at_parse_double(&at_cmd, &location.lat);
+ mtk_at_parse_double(&at_cmd, &location.lng);
+ location.alt_valid = mtk_at_parse_float(&at_cmd, &location.alt);
+ location.speed_valid = mtk_at_parse_float(&at_cmd, &location.speed);
+ location.bearing_valid = mtk_at_parse_float(&at_cmd, &location.bearing);
+ location.h_acc_valid = mtk_at_parse_float(&at_cmd, &location.h_acc);
+ location.timestamp_valid = mtk_at_parse_int64(&at_cmd, &location.timestamp);
+ location.date_time_valid = mtk_at_parse_string(&at_cmd, location.date_time, sizeof(location.date_time));
+ location.type_valid = mtk_at_parse_int32(&at_cmd, &location.type);
+
+ if(callbacks->_mtk_at_gnss_agnss_location_notify) {
+ callbacks->_mtk_at_gnss_agnss_location_notify(fd, &location);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_reset_notify_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ char reason[1024] = {0};
+ mtk_at_parse_string(&at_cmd, reason, sizeof(reason));
+ if(callbacks->_mtk_at_gnss_device_reset_notify) {
+ callbacks->_mtk_at_gnss_device_reset_notify(fd, reason);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_status_response_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ mtk_gnss_status status;
+ memset(&status, 0, sizeof(status));
+ mtk_at_parse_bool(&at_cmd, &status.gnss_status);
+ mtk_at_parse_bool(&at_cmd, &status.ni_status);
+ mtk_at_parse_int32(&at_cmd, &status.supl_maj_ver);
+ mtk_at_parse_int32(&at_cmd, &status.supl_min_ver);
+ mtk_at_parse_string(&at_cmd, status.gnss_version, sizeof(status.gnss_version));
+ mtk_at_parse_string(&at_cmd, status.agps_version, sizeof(status.agps_version));
+ mtk_at_parse_int32(&at_cmd, &status.supl_ser_ind);
+ mtk_at_parse_string(&at_cmd, status.supl_addr, sizeof(status.supl_addr));
+ mtk_at_parse_int32(&at_cmd, &status.supl_port);
+ mtk_at_parse_bool(&at_cmd, &status.supl_tls_enabled);
+ status.imsi_valid = mtk_at_parse_string(&at_cmd, status.imsi, sizeof(status.imsi));
+ status.num_digital_mnc_in_imsi_valid = mtk_at_parse_int32(&at_cmd, &status.num_digital_mnc_in_imsi);
+
+ if(callbacks->_mtk_at_gnss_status_response) {
+ callbacks->_mtk_at_gnss_status_response(fd, &status);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_ni_notify_request_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ mtk_gnss_ni_notify notify;
+ memset(¬ify, 0, sizeof(notify));
+ mtk_at_parse_int32(&at_cmd, ¬ify.id);
+ mtk_at_parse_int32(&at_cmd, ¬ify.type);
+ mtk_at_parse_int32(&at_cmd, ¬ify.notify_type);
+ mtk_at_parse_string(&at_cmd, notify.request_id, sizeof(notify.request_id));
+ mtk_at_parse_int32(&at_cmd, ¬ify.request_id_encode_type);
+ mtk_at_parse_string(&at_cmd, notify.text, sizeof(notify.text));
+ mtk_at_parse_int32(&at_cmd, ¬ify.text_encode_type);
+
+ if(callbacks->_mtk_at_gnss_ni_notify_request) {
+ callbacks->_mtk_at_gnss_ni_notify_request(fd, ¬ify);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_ref_loc_request_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ if(callbacks->_mtk_at_gnss_ref_location_request) {
+ callbacks->_mtk_at_gnss_ref_location_request(fd);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_ref_time_request_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ if(callbacks->_mtk_at_gnss_ref_time_request) {
+ callbacks->_mtk_at_gnss_ref_time_request(fd);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_loopback_response_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ char buff[5000] = {0};
+ mtk_at_parse_string(&at_cmd, buff, sizeof(buff));
+
+ if(callbacks->_mtk_at_gnss_loopback_response) {
+ callbacks->_mtk_at_gnss_loopback_response(fd, buff);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_cert_name_response_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ mtk_gnss_cert_name_list list;
+ memset(&list, 0, sizeof(list));
+
+ bool ret = mtk_at_parse_string(&at_cmd, list.names[0], sizeof(list.names[0]));
+ while(ret) {
+ list.num++;
+ ret = mtk_at_parse_string(&at_cmd, list.names[list.num], sizeof(list.names[0]));
+ }
+
+ if(callbacks->_mtk_at_gnss_cert_name_response) {
+ callbacks->_mtk_at_gnss_cert_name_response(fd, &list);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_geo_max_num_response_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ int num = 0;
+ mtk_at_parse_int32(&at_cmd, &num);
+ if(callbacks->_mtk_at_geo_max_num_response) {
+ callbacks->_mtk_at_geo_max_num_response(fd, num);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_geo_add_circle_response_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ mtk_geo_fence_create_state state = MTK_GEO_FENCE_CREATE_STATE_ERROR;
+ int id = -1;
+ mtk_at_parse_int32(&at_cmd, &state);
+ mtk_at_parse_int32(&at_cmd, &id);
+ if(callbacks->_mtk_at_geo_add_circle_response) {
+ callbacks->_mtk_at_geo_add_circle_response(fd, state, id);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_geo_alert_notify_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ mtk_geo_alert_notify notify;
+ memset(¬ify, 0, sizeof(notify));
+ mtk_at_parse_int32(&at_cmd, ¬ify.id);
+ mtk_at_parse_int32(&at_cmd, ¬ify.state);
+ mtk_at_parse_double(&at_cmd, ¬ify.lat);
+ mtk_at_parse_double(&at_cmd, ¬ify.lng);
+ mtk_at_parse_double(&at_cmd, ¬ify.alt);
+ mtk_at_parse_double(&at_cmd, ¬ify.speed);
+ mtk_at_parse_double(&at_cmd, ¬ify.heading);
+ mtk_at_parse_int32(&at_cmd, ¬ify.hacc);
+ mtk_at_parse_int32(&at_cmd, ¬ify.h_err_maj);
+ mtk_at_parse_int32(&at_cmd, ¬ify.h_err_min);
+ mtk_at_parse_int32(&at_cmd, ¬ify.h_err_angle);
+ mtk_at_parse_int32(&at_cmd, ¬ify.h_confidence);
+ mtk_at_parse_float(&at_cmd, ¬ify.pdop);
+ mtk_at_parse_float(&at_cmd, ¬ify.hdop);
+ mtk_at_parse_float(&at_cmd, ¬ify.vdop);
+ if(callbacks->_mtk_at_geo_alert_notify) {
+ callbacks->_mtk_at_geo_alert_notify(fd, ¬ify);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_geo_track_notify_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ mtk_geo_track_state state = MTK_GEO_TRACK_STATE_FAILURE;
+ char date_time[128] = {0};
+ mtk_at_parse_int32(&at_cmd, &state);
+ mtk_at_parse_string(&at_cmd, date_time, sizeof(date_time));
+ if(callbacks->_mtk_at_geo_track_notify) {
+ callbacks->_mtk_at_geo_track_notify(fd, state, date_time);
+ return true;
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+bool mtk_at_client_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks) {
+ assert(at_cmd != NULL);
+ assert(callbacks != NULL);
+ const char* at_cmd_bkup = at_cmd;
+
+ //LOGD("mtk_at_client_parser() fd=[%d] at_cmd=[%s]", fd, at_cmd);
+
+ bool ret = true;
+ if(mtk_at_is_ok_parser(at_cmd)) {
+ ret = mtk_at_ok_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_is_error_parser(at_cmd)) {
+ ret = mtk_at_error_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_NMEA_NTF)) {
+ ret = mtk_at_gnss_nmea_notify_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_NMEA_END_NTF)) {
+ ret = mtk_at_gnss_nmea_end_notify_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_SATELLITE_NTF)) {
+ ret = mtk_at_gnss_satellite_notify_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_LOCATION_NTF)) {
+ ret = mtk_at_gnss_location_notify_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_AGPS_LOCATION_NTF)) {
+ ret = mtk_at_gnss_agnss_location_notify_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_GNSS_RESET_NTF)) {
+ ret = mtk_at_gnss_reset_notify_parser(fd, at_cmd, callbacks);
+ } else if (mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_STATUS_RSP)) {
+ ret = mtk_at_gnss_status_response_parser(fd, at_cmd, callbacks);
+ } else if (mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_NI_NOTIFY_REQ)) {
+ ret = mtk_at_gnss_ni_notify_request_parser(fd, at_cmd, callbacks);
+ } else if (mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_REF_LOC_REQ)) {
+ ret = mtk_at_gnss_ref_loc_request_parser(fd, at_cmd, callbacks);
+ } else if (mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_REF_TIME_REQ)) {
+ ret = mtk_at_gnss_ref_time_request_parser(fd, at_cmd, callbacks);
+ } else if (mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_LOOPBACK_RSP)) {
+ ret = mtk_at_gnss_loopback_response_parser(fd, at_cmd, callbacks);
+ } else if (mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_CERT_NAME_RSP)) {
+ ret = mtk_at_gnss_cert_name_response_parser(fd, at_cmd, callbacks);
+ } else if (mtk_at_parse_cmd(&at_cmd, MTK_AT_GEOFENCE_MAX_NUM_RSP)) {
+ ret = mtk_at_geo_max_num_response_parser(fd, at_cmd, callbacks);
+ } else if (mtk_at_parse_cmd(&at_cmd, MTK_AT_GEOFENCE_ADD_CIRCLE_RSP)) {
+ ret = mtk_at_geo_add_circle_response_parser(fd, at_cmd, callbacks);
+ } else if (mtk_at_parse_cmd(&at_cmd, MTK_AT_GEOFENCE_ALERT_NTF)) {
+ ret = mtk_at_geo_alert_notify_parser(fd, at_cmd, callbacks);
+ } else if (mtk_at_parse_cmd(&at_cmd, MTK_AT_GEOFENCE_TRACK_NTF)) {
+ ret = mtk_at_geo_track_notify_parser(fd, at_cmd, callbacks);
+ } else {
+ LOGW("unhandled at_cmd=[%s]", at_cmd_bkup);
+ return false;
+ }
+
+ if(!ret) {
+ LOGW("wrong at_cmd=[%s]", at_cmd_bkup);
+ }
+
+ return ret;
+}
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_client.h b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_client.h
new file mode 100755
index 0000000..0d75caa
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_client.h
@@ -0,0 +1,72 @@
+#ifndef __MTK_GNSS_AT_CLIENT_H__
+#define __MTK_GNSS_AT_CLIENT_H__
+
+#include "mtk_gnss_at_struct.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//GNSS
+bool mtk_at_send_gnss_start_request(int fd);
+bool mtk_at_send_gnss_stop_request(int fd);
+bool mtk_at_send_gnss_host_reset_notify(int fd);
+bool mtk_at_send_gnss_status_request(int fd);
+bool mtk_at_send_gnss_enable_set(int fd, bool enabled);
+bool mtk_at_send_gnss_ni_enable_set(int fd, bool enabled);
+bool mtk_at_send_gnss_agps_mode_set(int fd, mtk_gnss_agps_mode* mode);
+bool mtk_at_send_gnss_supl_version_set(int fd, int maj, int min, int ser_ind);
+bool mtk_at_send_gnss_supl_addr_set(int fd, const char* addr, int port, bool tls_enabled);
+bool mtk_at_send_gnss_delete_aiding_data_request(int fd, mtk_gnss_aiding_data* flags);
+bool mtk_at_send_gnss_ni_notify_response(int fd, int id, mtk_gnss_ni_response_type response);
+bool mtk_at_send_gnss_ref_location_response(int fd, int age, double lat, double lng, float acc);
+bool mtk_at_send_gnss_ref_time_response(int fd, long long time, int uncertainty);
+bool mtk_at_send_gnss_nmea_config_set(int fd, bool enabled);
+bool mtk_at_send_gnss_ttff_qop_set(int fd, int mode);
+bool mtk_at_send_gnss_loopback_request(int fd, const char* msg);
+bool mtk_at_send_gnss_cert_set(int fd, mtk_gnss_cert* cert);
+bool mtk_at_send_gnss_cert_name_request(int fd);
+bool mtk_at_send_gnss_cert_delete_request(int fd, const char* name);
+bool mtk_at_send_gnss_cert_delete_all_request(int fd);
+//Geofence
+bool mtk_at_send_geo_max_num_request(int fd);
+bool mtk_at_send_geo_add_circle_request(int fd, mtk_geo_add_circle* circle);
+bool mtk_at_send_geo_delete_request(int fd, int id);
+bool mtk_at_send_geo_delete_all_request(int fd);
+//Test
+bool mtk_at_send_test_request(int fd, int num1, int num2, double d1, double d2, const char* str1, const char* str2);
+
+
+typedef struct {
+ void (*_mtk_at_result) (int fd, bool is_ok, const char* msg);
+ void (*_mtk_at_gnss_nmea_notify) (int fd, const char* nmea);
+ void (*_mtk_at_gnss_nmea_end_notify) (int fd);
+ void (*_mtk_at_gnss_satellite_notify) (int fd, mtk_gnss_satellite_list* list);
+ void (*_mtk_at_gnss_location_notify) (int fd, mtk_gnss_location* location);
+ void (*_mtk_at_gnss_agnss_location_notify) (int fd, mtk_agnss_location* location);
+ void (*_mtk_at_gnss_device_reset_notify) (int fd, const char* reason);
+ void (*_mtk_at_gnss_status_response) (int fd, mtk_gnss_status* status);
+ void (*_mtk_at_gnss_ni_notify_request) (int fd, mtk_gnss_ni_notify* notify);
+ void (*_mtk_at_gnss_ref_location_request) (int fd);
+ void (*_mtk_at_gnss_ref_time_request) (int fd);
+ void (*_mtk_at_gnss_loopback_response) (int fd, const char* msg);
+ void (*_mtk_at_gnss_cert_name_response) (int fd, mtk_gnss_cert_name_list* list);
+ void (*_mtk_at_geo_max_num_response) (int fd, int num);
+ void (*_mtk_at_geo_add_circle_response) (int fd, mtk_geo_fence_create_state state, int id);
+ void (*_mtk_at_geo_alert_notify) (int fd, mtk_geo_alert_notify* notify);
+ void (*_mtk_at_geo_track_notify) (int fd, mtk_geo_track_state state, const char* date_time);
+} mtk_gnss_at_client_callbacks;
+
+/**
+ fd: will be forwarded to callbacks directly
+ at_cmd: single AT command with \r\n at the end of at command
+ callbacks: your handlers
+ */
+bool mtk_at_client_parser(int fd, const char* at_cmd, mtk_gnss_at_client_callbacks* callbacks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_command.h b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_command.h
new file mode 100755
index 0000000..71cb483
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_command.h
@@ -0,0 +1,1131 @@
+#ifndef __MTK_GNSS_AT_COMMAND_H__
+#define __MTK_GNSS_AT_COMMAND_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+MTK GNSS AT Command
+ensure that you have at least 3456 bytes of buffer size for sending and receiving one AT command
+
+[Users]
+1. GNSS Adaptor
+2. LBS EM
+3. Host GNSS auto test tool
+
+[Documents]
+LBS Customer Release Notes
+
+[Version History]
+001: first version
+002: add MTK_AT_GNSS_AGPS_LOCATION_NTF
+*/
+#define MTK_AT_GNSS_VERSION = "002"
+
+
+/*
+AT+ELCSSTART=\r\n
+
+[Description]
+turn on GNSS engine and start reporting NMEA, Location and satellite in 1 Hz.
+please be noted this AT command could add more arguments in the future, please make sure your AT command parser can support it.
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+if GNSS is already started and the host sends AT+ELCSSTART again, the device will return OK to the host.
+ */
+#define MTK_AT_GNSS_START_REQ "AT+ELCSSTART"
+
+
+/*
+AT+ELCSSTOP=\r\n
+
+[Description]
+turn off GNSS engine and stop reporting NMEA, Location and satellite in 1 Hz.
+please be noted this AT command could add more arguments in the future, please make sure your AT command parser can support it.
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+if GNSS is already stopped and the host sends AT+ELCSSTOP again, the device will return OK to the host.
+*/
+#define MTK_AT_GNSS_STOP_REQ "AT+ELCSSTOP"
+
+
+/*
+\r\n+ELCSNMEA: <nmea_string>\r\n
+
+[Description]
+this is an unsolicited response and report in 1 Hz while GNSS is on.
+report NMEA is default enabled. If you want to disable it, please use AT+ELCSCFGNMEA to disable it before starting GNSS.
+please be noted that calling read() API once can only get one +ELCSNMEA AT command, you need to call multiple read() to get all NMEA per second.
+
+[Parameters]
+<nmea_string> (string)
+ one NMEA sentence
+
+[Example]
+\r\n+ELCSNMEA: "$GNGGA,000344.011,2503.4068,N,12134.4490,E,0,0,,134.8,M,15.2,M,,*54"\r\n
+\r\n+ELCSNMEA: "$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30"\r\n
+\r\n+ELCSNMEA: "$GLGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*2C"\r\n
+\r\n+ELCSNMEA: "$GPGSV,1,1,0*49"\r\n
+\r\n+ELCSNMEA: "$GLGSV,1,1,0*55"\r\n
+\r\n+ELCSNMEA: "$GNRMC,000344.011,V,2503.4068,N,12134.4490,E,0.000,0.00,010110,,,N*58"\r\n
+\r\n+ELCSNMEA: "$GNVTG,0.00,T,,M,0.000,N,0.000,K,N*2C"\r\n
+\r\n+ELCSNMEAEND\r\n
+*/
+#define MTK_AT_GNSS_NMEA_NTF "\r\n+ELCSNMEA"
+
+
+/*
+\r\n+ELCSNMEAEND\r\n
+
+[Description]
+to indicate the end of last NMEA sentence
+
+[Parameters]
+none
+
+[Example]
+\r\n+ELCSNMEA: "$GNGGA,000344.011,2503.4068,N,12134.4490,E,0,0,,134.8,M,15.2,M,,*54"\r\n
+\r\n+ELCSNMEA: "$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30"\r\n
+\r\n+ELCSNMEA: "$GLGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*2C"\r\n
+\r\n+ELCSNMEA: "$GPGSV,1,1,0*49"\r\n
+\r\n+ELCSNMEA: "$GLGSV,1,1,0*55"\r\n
+\r\n+ELCSNMEA: "$GNRMC,000344.011,V,2503.4068,N,12134.4490,E,0.000,0.00,010110,,,N*58"\r\n
+\r\n+ELCSNMEA: "$GNVTG,0.00,T,,M,0.000,N,0.000,K,N*2C"\r\n
+\r\n+ELCSNMEAEND\r\n
+*/
+#define MTK_AT_GNSS_NMEA_END_NTF "\r\n+ELCSNMEAEND"
+
+/*
+\r\n+ELCSSAT: <num>,[<svid>,<constellation>,<cn0>,<elevation>,<azimuth>,<flags>,<carrier_frequency>(repeat num times)]\r\n
+
+[Description]
+this is an unsolicited response and report in 1 Hz while GNSS is on.
+please be noted this AT command could add more arguments in the future, please make sure your AT command parser can support it.
+
+[Parameters]
+<num> (int)
+ Number of satellite in this AT command (1~64)
+<svid> (int)
+<constellation> (int)
+ GPS=1
+ SBAS=2
+ GLONASS=3
+ QZSS=4
+ BEIDOU=5
+ Galileo=6
+ IRNSS=7
+<cn0> (float by using %.2f)
+ 0~60
+<elevation> (float by using %.2f)
+ 0~90
+<azimuth> (float by using %.2f)
+ 0~360
+<flags> (int)
+ indicate the extra info of this satellite
+ None=0x00
+ Has_ephemeris=0x01
+ Has_almance=0x02
+ Used_in_fix=0x04
+<carrier_frequency> (float by using %.2f)
+ Carrier frequency of the signal tracked in MHz. GPS central frequency for L1 = 1575.45 MHz or L5 = 1176.45 MHz.
+
+[Example]
+\r\n+ELCSSAT: 2,1,1,40.00,10.00,20.00,7,1575.45,2,3,50.00,20.00,30.00,1,1176.45\r\n
+ num=2
+ svid=1, constellation=GPS=1, cn0=40.00, elevation=10.00, azimuth=20.00, flag=has_ephemeris + has_almance + user_in_fix=7, carrier_requency=1575.45
+ svid=2, constellation=GLONASS=3, cn0=50.00, elevation=20.00, azimuth=30.00, flag=has_ephemeris=1, carrier_requency=1176.45
+*/
+#define MTK_AT_GNSS_SATELLITE_NTF "\r\n+ELCSSAT"
+
+
+/*
+\r\n+ELCSLOC: <lat>,<lng>,<alt>,<speed>,<bearing>,<h_acc>,<v_acc>,<s_acc>,<b_acc>,<timestamp>,<date_time>,<pdop>,<hdop>,<vdop>\r\n
+
+[Description]
+this is an unsolicited response and report in 1 Hz while GNSS is on and the location is calculated by GNSS.
+Please be noted this AT command could add more arguments in the future, please make sure your AT command parser can support it.
+
+[Parameters]
+<lat> (double by using %.6f)
+ in degrees, WGS84 coordinate system.
+<lng> (double by using %.6f)
+ In degrees, WGS84 coordinate system.
+<alt> (could be empty, float by using %.2f)
+ in meters with respect to sea level.
+<speed> (could be empty, float by using %.2f)
+ meters per second.
+<bearing> (could be empty, float by using %.2f)
+ in degrees.
+<h_acc> (could be empty, float by using %.2f)
+ Represents expected horizontal position accuracy, radial, in meters (68% confidence).
+<v_acc> (could be empty, float by using %.2f)
+ Represents expected vertical position accuracy in meters (68% confidence).
+<s_acc> (could be empty, float by using %.2f)
+ Represents expected speed accuracy in meter per seconds (68% confidence).
+<b_acc> (could be empty, float by using %.2f)
+ Represents expected bearing accuracy in degrees (68% confidence).
+<timestamp> (int64_t)
+ Milliseconds since January 1, 1970.
+<date_time> (string)
+ convert timestamp to human readable format. ex: 2019/11/13,10:17:10, max. to 31 characters
+<pdop> (could be empty, float by using %.2f)
+ Satellite-based positions with a dilution of precision (DOP) value of 0 or a DOP value higher than 10 may be filtered by the GNSS adapter.
+<hdop> (could be empty, float by using %.2f)
+ Horizontal dilution of precision (HDOP)
+<vdop> (could be empty, float by using %.2f)
+ Vertical dilution of precision (VDOP).
+
+[Example]
+\r\n+ELCSLOC: -77.508333,164.754167,10.00,20.00,30.00,40.00,50.00,60.00,70.00,0,"1970/1/1,00:00:00",1.00,2.00,3.00\r\n
+ Latitude=-77.508333, Longitude=164.754167
+ alt=10.00
+ bear=20.00
+ speed=30.00
+ h_acc=40.00
+ v_acc=50.00
+ s_acc=60.00
+ b_acc=70.00
+ timestamp=0
+ timestamp="1970/1/1,00:00:00"
+ pdop=1.00
+ hdop=2.00
+ vdop=3.00
+
+\r\n+ELCSLOC: -77.508333,164.754167,,,,,,,,1000,"1970/1/1,00:00:01",,,\r\n
+ Latitude=-77.508333, Longitude=164.754167
+ alt=unknown
+ bear=unknown
+ h_acc=unknown
+ v_acc=unknown
+ s_acc=unknown
+ b_acc=unknown
+ timestamp=1000
+ timestamp="1970/1/1,00:00:01"
+ pdop=unknown
+ hdop=unknown
+ vdop=unknown
+*/
+#define MTK_AT_GNSS_LOCATION_NTF "\r\n+ELCSLOC"
+
+
+/*
+\r\n+ELCSAGPSLOC: <lat>,<lng>,<alt>,<speed>,<bearing>,<h_acc>,<timestamp>,<date_time>,<type>\r\n
+
+[Description]
+this is an unsolicited response for non-GNSS location (ex: AFLT, SUPL Reference Location, ...etc.) while GNSS session is ongoing.
+Please be noted this AT command could add more arguments in the future, please make sure your AT command parser can support it.
+
+[Parameters]
+<lat> (double by using %.6f)
+ in degrees, WGS84 coordinate system.
+<lng> (double by using %.6f)
+ In degrees, WGS84 coordinate system.
+<alt> (could be empty, float by using %.2f)
+ in meters above the WGS 84 ellipsoid
+<speed> (could be empty, float by using %.2f)
+ meters per second.
+<bearing> (could be empty, float by using %.2f)
+ in degrees.
+<h_acc> (could be empty, float by using %.2f)
+ Represents expected horizontal position accuracy, radial, in meters (68% confidence).
+<timestamp> (could be empty, int64_t)
+ Milliseconds since January 1, 1970.
+<date_time> (could be empty, string)
+ convert timestamp to human readable format. ex: 2019/11/13,10:17:10, max. to 31 characters
+<type> (int)
+ AFLT=0
+ CDMA_CELL=1
+ CP_MOLR=2
+ SUPL_END=3
+ SUPL_REFERENCE_LOCATION=4
+ CP_REFERENCE_LOCATION=5
+
+[Example]
+\r\n+ELCSAGPSLOC: 77.508333,164.754167,10.00,20.00,30.00,40.00,31536000000,"1971/01/01,00:00:00",4\r\n
+ Latitude=-77.508333, Longitude=164.754167
+ alt=10.00
+ bear=20.00
+ speed=30.00
+ h_acc=40.00
+ timestamp=31536000000
+ timestamp="1971/1/1,00:00:00"
+ type=SUPL_REFERENCE_LOCATION=4
+*/
+#define MTK_AT_GNSS_AGPS_LOCATION_NTF "\r\n+ELCSAGPSLOC"
+
+
+/*
+\r\n+ELCSREFLOCREQ\r\n
+
+[Description]
+this is an unsolicited response if GNSS lacks the reference location and issue this AT command to the host when GPS is starting,
+and if there is no 3D fix for more than 300 sec, the AT command will be issued again.
+if the host cannot get the valid reference location, the host can simply ignore this message and no need to reply anything.
+*/
+#define MTK_AT_GNSS_REF_LOC_REQ "\r\n+ELCSREFLOCREQ"
+
+
+/*
+AT+ELCSREFLOCRSP=<age>,<lat>,<lng>,<acc>\r\n
+
+[Description]
+to reply +ELCSREFLOCREQ.
+the host updates the reference location to GNSS to improve GNSS performance in some circumstance.
+only use this AT command when GNSS is started or this command will be ignored by GNSS.
+
+[Parameters]
+<age> (int)
+ Indicates how long the position has been aged in seconds
+<lat> (double by using %.6f)
+ latitude in degrees, WGS84 coordinate system.
+<lng> (double by using %.6f)
+ longitude in degrees, WGS84 coordinate system.
+<acc> (float by using %.2f)
+ Represents expected horizontal position accuracy, radial, in meters (68% confidence).
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+
+[Example]
+AT+ELCSREFLOCRSP=60,-77.508333,164.754167,30.00\r\n
+ age=60 s
+ Latitude=-77.508333, Longitude=164.754167
+ acc=30.00 m
+*/
+#define MTK_AT_GNSS_REF_LOC_RSP "AT+ELCSREFLOCRSP"
+
+
+/*
+\r\n+ELCSREFTIMEREQ\r\n
+
+[Description]
+this is an unsolicited response if GNSS lacks the reference time and only issue this AT command to the host once when GPS is starting.
+if the host cannot get the valid reference time, the host can simply ignore this message and no need to reply anything.
+*/
+#define MTK_AT_GNSS_REF_TIME_REQ "\r\n+ELCSREFTIMEREQ"
+
+
+/*
+AT+ELCSREFTIMERSP=<time>,<uncertainty>\r\n
+
+[Description]
+to reply +ELCSREFTIMEREQ.
+the host updates the reference time to GNSS to improve GNSS performance in some circumstance.
+only use this AT command when GNSS is started or this command will be ignored by GNSS.
+
+[Parameters]
+<time> (int64_t)
+ Milliseconds since January 1, 1970.
+<uncertainty> (int)
+ Uncertainty in milliseconds.
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+
+[Example]
+AT+ELCSREFTIMERSP=0,1000\r\n
+ time=1970/1/1,00:00:00=0
+ uncertainty=1000 ms
+*/
+#define MTK_AT_GNSS_REF_TIME_RSP "AT+ELCSREFTIMERSP"
+
+
+/*
+AT+ELCSHOSTRST\r\n
+
+[Description]
+to notify the device that host has been reboot, GNSS will close all ongoing sessions and enter the idle mode at the device side.
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+*/
+#define MTK_AT_GNSS_HOST_RESET_NTF "AT+ELCSHOSTRST"
+
+
+/*
+\r\n+ELCSGNSSRST: <reason_msg>\r\n
+
+[Description]
+this is an unsolicited response while GNSS has been reboot due to some problems happens (ex: software assert).
+to notify the host that GNSS has been reboot and need the host to restart the session if GNSS related sessions are ongoing.
+
+[Parameters]
+<reason_msg> (string)
+ the reason of sending this AT command
+
+[Example]
+\r\n+ELCSGNSSRST: "GNSS adaptor reboot done"\r\n
+ scenario 1: GNSS adaptor starts at the boot up time, itÂ’s a normal case.
+ scenario 2: GNSS adaptor is crash and re-started done, itÂ’s an error case.
+
+\r\n+ELCSGNSSRST: "MNLD exception happen and reconnection done"\r\n
+ scenario 1: MNLD is crash and GNSS adaptor re-connect to MNLD done, itÂ’s an error case.
+*/
+#define MTK_AT_GNSS_GNSS_RESET_NTF "\r\n+ELCSGNSSRST"
+
+
+/*
+AT+ELCSSTATUS?\r\n
+
+[Description]
+ask GNSS capability.
+
+[Return]
+\r\n+ELCSSTATUS...\r\n
+\r\nOK\r\n or \r\nERROR\r\n
+*/
+#define MTK_AT_GNSS_STATUS_REQ "AT+ELCSSTATUS?"
+
+
+/*
+\r\n+ELCSSTATUS: <gnss_status>,<ni_status>,<supl_maj_ver>,<supl_min_ver>,<gnss_version>,<agps_version>,<supl_ser_ind>,<supl_addr>,<supl_port>,<supl_tls_enabled>,<imsi>,<num_digital_mnc_in_imsi>\r\n
+
+[Description]
+reply AT+ELCSSTATUS to provide GNSS capability.
+please be noted this AT command could add more arguments in the future, please make sure your AT command parser can support it.
+
+[Parameters]
+<gnss_status> (int)
+ 0=disabled
+ 1=enabled
+<ni_status> (int)
+ 0=disabled
+ 1=enabled
+<supl_maj_ver> (int)
+ SUPL major version
+<supl_min_ver> (int)
+ SUPL minor version
+<gnss_version> (string)
+ the version of MNLD + libmnl.so, max. to 255 characters.
+<agps_version> (string)
+ the version of AGPSD, max. to 127 characters.
+<supl_ser_ind> (int)
+ SUPL service indicator version
+<supl_addr> (string)
+ can be FQDN (ex: supl.xxxx.com) or IPv4 address (ex: 111.222.1.2) or IPv6 address, max. to 127 characters.
+<supl_port> (int)
+ SUPL server port (ex: 7275)
+<supl_tls_enabled> (int)
+ 0=SUPL TLS enabled
+ 1=SUPL TLS disabled
+<imsi> (could be empty, string)
+ provide the IMSI if available.
+ the max string size is 32.
+<num_digital_mnc_in_imsi> (could be empty, int)
+ provide the number of digital for MNC in IMSI if available.
+
+[Example]
+\r\n+ELCSSTATUS: 1,0,2,0,"MTK_MNLD_5_0_0_19080901,MNL_VER_19112002ALPS05_6.00_99","3.255",0,"supl.xxx.com",7275,1,"3100121234567890",3\r\n
+ gnss_status=ON
+ ni_status=OFF
+ SUPL 2.0
+ mnld_version="MTK_MNLD_5_0_0_19080901,MNL_VER_19112002ALPS05_6.00_99"
+ agps_version="3.255"
+ supl_ser_ind=0
+ supl_addr="supl.xxx.com"
+ supl_port=7275
+ supl_tle_enabled=1
+ imsi="3100121234567890"
+ num_digital_mnc_in_imsi=3
+
+\r\n+ELCSSTATUS: 1,0,2,0,"MTK_MNLD_5_0_0_19080901,MNL_VER_19112002ALPS05_6.00_99","3.255",0,"supl.xxx.com",7275,1,,\r\n
+ gnss_status=ON
+ ni_status=OFF
+ SUPL 2.0
+ mnld_version="MTK_MNLD_5_0_0_19080901,MNL_VER_19112002ALPS05_6.00_99"
+ agps_version="3.255"
+ supl_ser_ind=0
+ supl_addr="supl.xxx.com"
+ supl_port=7275
+ supl_tle_enabled=1
+ imsi=not available
+ num_digital_mnc_in_imsi=not available
+*/
+#define MTK_AT_GNSS_STATUS_RSP "\r\n+ELCSSTATUS"
+
+
+/*
+AT+ELCSGNSSENABLE=<enabled>\r\n
+
+[Description]
+to set GNSS status.
+the changed value is persistent even reboot the device.
+
+[Parameters]
+<enabled> (int)
+ 0=disabled
+ 1=enabled
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+*/
+#define MTK_AT_GNSS_GNSS_ENABLE_SET "AT+ELCSGNSSENABLE"
+
+
+/*
+AT+ELCSNIENABLE=<enabled>\r\n
+
+[Description]
+to set NI allowed configuration.
+the changed value is persistent even reboot the device.
+
+[Parameters]
+<enabled> (int)
+ 0=disabled
+ 1=enabled
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+*/
+#define MTK_AT_GNSS_NI_ENABLE_SET "AT+ELCSNIENABLE"
+
+
+/*
+AT+ELCSAGPSMODE=[<msa>],[<msb>],[<mss>],[<cid>],[<aflt>],[<otdoa>],[<supl_pref_method>],[<supl>],[<epo>]\r\n
+
+[Description]
+to set AGNSS operation mode.
+the changed value is persistent even reboot the device.
+
+[Parameters]
+<msa> (int)
+ 0=disabled
+ 1=enabled
+<msb> (int)
+ 0=disabled
+ 1=enabled
+<mss> (int)
+ 0=disabled
+ 1=enabled
+<cid> (int)
+ 0=disabled
+ 1=enabled
+<aflt> (int)
+ 0=disabled
+ 1=enabled
+<otdoa> (int)
+ 0=disabled
+ 1=enabled
+<supl_pref_method> (int)
+ 0=SET Assisted Preferred
+ 1=SET Based Preferred
+ 2=no Preference
+<supl> (int)
+ 0=disable SUPL including SET initiated and Network Initiated
+ 1=enable SUPL including SET initiated and Network Initiated
+<epo> (int)
+ 0=disable EPO and QEPO including download procedure and used by GPS algo. for next GNSS session
+ 1=enable EPO and QEPO including download procedure and used by GPS algo. for next GNSS session
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+
+[Example]
+AT+ELCSAGPSMODE=1,1,1,0,0,0,2
+set MSA, MSB, MSS to enabled
+set CID, AFLT, OTDOA to disabled
+set supl_pref_method to "no Preference"
+
+AT+ELCSAGPSMODE=,,,,,,1
+set supl_pref_method to SET Based Preferred
+others are not changed
+*/
+#define MTK_AT_GNSS_AGPS_MODE_SET "AT+ELCSAGPSMODE"
+
+
+/*
+AT+ELCSSUPLVER=<maj_ver>,<min_ver>,<ser_ind>\r\n
+
+[Description]
+to set SUPL version.
+the changed value is persistent even reboot the device.
+
+[Parameters]
+<maj_ver> (int)
+ SUPL major version
+<min_ver> (int)
+ SUPL minor version
+<ser_ind> (int)
+ SUPL service indicator version
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+*/
+#define MTK_AT_GNSS_SUPL_VERSION_SET "AT+ELCSSUPLVER"
+
+
+/*
+AT+ELCSSUPLADDR=<addr>,<port>,<tls_enable>\r\n
+
+[Description]
+to set SUPL SLP address.
+the changed value is persistent even reboot the device.
+
+[Parameters]
+<addr> (string)
+ can be FQDN (ex: supl.xxxx.com) or IPv4 address (ex: 111.222.1.2) or IPv6 address, max. to 127 characters.
+<port> (int)
+ SUPL server port (ex: 7275)
+<tls_enable> (int)
+ 0=disabled
+ 1=enabled
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+*/
+#define MTK_AT_GNSS_SUPL_ADDRESS_SET "AT+ELCSSUPLADDR"
+
+
+/*
+AT+ELCSDELAIDING=[<eph>,<alm>,<pos>,<time>,<iono>,<utc>,<svdir>,<rti>,<celldb>]\r\n
+
+[Description]
+to delete GNSS aiding data.
+please be noted this AT command could add more arguments in the future, please make sure your AT command parser can support it.
+if no parameter (ex: AT+ELCSDELAIDING=\r\n), it means to delete all aiding data.
+
+[Parameters]
+<eph> (int)
+ 0=don't delete ephemeris
+ 1=delete ephemeris
+<alm> (int)
+ 0=don' delete almanac
+ 1=delete almanac
+<pos> (int)
+ 0=don't delete position
+ 1=delete position
+<time> (int)
+ 0=don't delete time
+ 1=delete time
+<iono> (int)
+ 0=don't delete iono
+ 1=delete iono
+<utc> (int)
+ 0=don't delete UTC
+ 1=delete UTC
+<svdir> (int)
+ 0=don't delete SVDIR
+ 1=delete SVDIR
+<rti> (int)
+ 0=don't delete RTI
+ 1=delete RTI
+<celldb> (int)
+ 0=don't delete cell database info
+ 1=delete cell database info
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+*/
+#define MTK_AT_GNSS_DELETE_AIDING_REQ "AT+ELCSDELAIDING"
+
+
+/*
+AT+ELCSNMEACFG=<enable>\r\n
+
+[Description]
+to configure NMEA related settings.
+the NMEA report is default enabled.
+
+[Parameters]
+<enable> (int)
+ 0: disable reporting NMEA strings via +ELCSNMEA while GPS is ON
+ 1: enable reporting NMEA strings via +ELCSNMEA while GPS is ON
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+*/
+#define MTK_AT_GNSS_NMEA_CFG_SET "AT+ELCSNMEACFG"
+
+
+/*
+AT+ELCSTTFFQOP=<mode>\r\n
+
+[Description]
+to configure the Quality of Position (QoP) for first fix location.
+The position accuracy (1-sigma) will be around 3000m/200m/50m (mode=0/1/2) at open sky environment.
+the changed value is persistent even reboot the device.
+
+[Parameters]
+<mode> (int)
+ 0: quick response time, low Accuracy
+ 1: medium response time, medium Accuracy
+ 2: slow response time, high Accuracy
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+*/
+#define MTK_AT_GNSS_TTFF_QOP_SET "AT+ELCSTTFFQOP"
+
+
+/*
+\r\n+ELCSNINTF: <id>,<type>,<notify_type>,<requestor_id>,<requestor_id_encode_type>,<text>,<text_encode_type>\r\n
+
+[Description]
+this is an unsolicited response while Network Initiated is coming and request to show UI for user.
+GNSS requests the host to show NI notification/verification for user.
+
+[Parameters]
+<id> (int)
+<type> (int)
+ 1=voice
+ 2=SUPL
+ 3=CP
+ 4=Emergency SUPL
+<notify_type> (int)
+ 0=none
+ 1=notification only
+ 2=notification and verification, allowed if no answer
+ 3=notification and verification, denied if no answer
+ 4=privacy override
+<requestor_id> (string)
+ max. to 1023 characters
+<requestor_id_encode_type> (int)
+ 0=none
+ 1=GSM7
+ 2=UTF8
+ 3=UCS2
+<text> (string)
+ max. to 1023 characters
+<text_encode_type> (int)
+ 0=none
+ 1=GSM7
+ 2=UTF8
+ 3=UCS2
+
+[Example]
+\r\n+ELCSNINTF: 1,2,1,"4875676F526571756573746F72",2,"4875676F436C69656E74",2\r\n
+ id=1
+ type=SUPL=2
+ notify_type=notification only=1
+ requestor_id="HugoRequestor"=4875676F526571756573746F72 (UTF8 hex string)
+ requestor_id_encode_type=UTF8=2
+ text="HugoClient"=4875676F436C69656E74 (UTF8 hex string)
+ text_encode_type=UTF8=2
+
+\r\n+ELCSNINTF: 2,3,3,"FEFF004800750067006F0052006500710075006500730074006F0072",3,"FEFF004800750067006F0043006C00690065006E0074",3\r\n
+ id=2
+ type=CP=3
+ notify_type=notification and verification, denied if no answer=3
+ requestor_id="HugoRequestor"="FEFF004800750067006F0052006500710075006500730074006F0072" (UCS2 hex string)
+ requestor_id_encode_type=UCS2=3
+ text="HugoClient"="FEFF004800750067006F0043006C00690065006E0074" (UCS2 hex string)
+ text_encode_type=UCS2=3
+*/
+#define MTK_AT_GNSS_NI_NOTIFY_REQ "\r\n+ELCSNINTF"
+
+
+/*
+AT+ELCSNIRSP=<id>,<response>\r\n
+
+[Description]
+to reply +ELCSNINTF.
+the host updates user response for NI notification.
+
+[Parameters]
+<id> (int)
+<response> (int)
+ 1=accept
+ 2=deny
+ 3=no response
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+*/
+#define MTK_AT_GNSS_NI_NOTIFY_RSP "AT+ELCSNIRSP"
+
+
+/*
+AT+ELCSLOOPBACK=<msg>\r\n
+
+[Description]
+this is loopback testing command to ensure the channel between the host and the device is ok or not.
+
+[Parameters]
+<msg> (string)
+ testing message
+
+[Return]
+\r\n+ELCSLOOPBACK...\r\n
+\r\nOK\r\n or \r\nERROR\r\n
+
+[Example]
+AT+ELCSLOOPBACK="hello world"\r\n
+\r\n+ELCSLOOPBACK: "hello world"\r\n
+\r\nOK\r\n
+*/
+#define MTK_AT_GNSS_LOOPBACK_REQ "AT+ELCSLOOPBACK"
+
+
+/*
+\r\n+ELCSLOOPBACK: <msg>\r\n
+
+[Description]
+reply for AT+ELCSLOOPBACK sent by the host.
+
+[Parameters]
+<msg> (string)
+ this message is copied from AT+ELCSLOOPBACK
+*/
+#define MTK_AT_GNSS_LOOPBACK_RSP "\r\n+ELCSLOOPBACK"
+
+
+/*
+AT+ELCSCERT=<total_message_length>,<seq_no>,<cert_name>,<cert_data>\r\n
+
+[Description]
+for host to inject the SUPL certificate to the device.
+the injected certificates are persistent even reboot the device.
+the maximum number of injected certificate cannot be over 10, you can use AT+ELCSCERTDEL/AT+ELCSCERTDELALL to delete the unused certificate.
+
+[Parameters]
+<total_message_length> (int)
+ The total size of the certificate to be received from 1-64000 bytes
+<seq_no> (int)
+ The sequence number of the segment from 1-64
+<cert_name> (string)
+ name of the certificate of max 128 chars acceptable chars: []()-._0-9a-zA-Z including the space
+<cert_data> (string)
+ certificate data in PEM format (Base64) of max 1000 chars, if certificate is more than 1000 char, it should be split into multiple AT commands with sequence number.
+
+[Example]
+AT+ELCSCERT=2000,1,"DigiCert Global Root CA","ggEBAJEVOQMB..."\r\n
+\r\nOK\r\n
+AT+ELCSCERT=2000,2,"DigiCert Global Root CA","G2f7Shz5CmBb..."\r\n
+\r\nOK\r\n
+*/
+#define MTK_AT_GNSS_CERT_SET "AT+ELCSCERT"
+
+
+/*
+AT+ELCSCERT?\r\n
+
+[Description]
+for host to query the injected certificate name list.
+
+[Example]
+case 1: there is NO injected certificate in the device.
+AT+ELCSCERT?\r\n
+\r\n+ELCSCERT: \r\n
+\r\nOK\r\n
+
+case 1: there is one injected certificate in the device.
+AT+ELCSCERT?
+\r\n+ELCSCERT: "cert 1"\r\n
+\r\nOK\r\n
+
+case 2: there are three injected certificate in the device.
+AT+ELCSCERT?
+\r\n+ELCSCERT: "cert 1","cert 2","cert 3"\r\n
+\r\nOK\r\n
+*/
+#define MTK_AT_GNSS_CERT_NAME_REQ "AT+ELCSCERT?"
+
+
+/*
+\r\n+ELCSCERT: [<cert_name>,[<cert_name>,...]...]\r\n
+
+[Description]
+reply AT+ELCSCERT? to provide the injected certificate name list.
+
+[Parameters]
+<cert_name> (string)
+ name of the certificate of max 128 chars
+*/
+#define MTK_AT_GNSS_CERT_NAME_RSP "\r\n+ELCSCERT"
+
+
+/*
+AT+ELCSCERTDEL=<cert_name>\r\n
+
+[Description]
+to delete the specific injected certificate from the device.
+
+[Parameters]
+<cert_name> (string)
+ name of the certificate of max 128 chars
+
+[Return]
+case 1: if the certificate exists and delete successful
+\r\nOK\r\n
+
+case 2: if the certificate does not exist or delete failed
+\r\nERROR\r\n
+*/
+#define MTK_AT_GNSS_CERT_DEL_REQ "AT+ELCSCERTDEL"
+
+
+/*
+AT+ELCSCERTDELALL\r\n
+
+[Description]
+to delete all injected certificate from the device.
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+*/
+#define MTK_AT_GNSS_CERT_DEL_ALL_REQ "AT+ELCSCERTDELALL"
+
+
+/*
+AT+EGEOMAX?\r\n
+
+[Description]
+Query for maximum fence supported
+
+[Return]
+\r\n+EGEOMAX...\r\n
+\r\nOK\r\n or \r\nERROR\r\n
+*/
+#define MTK_AT_GEOFENCE_MAX_NUM_REQ "AT+EGEOMAX?"
+
+
+/*
+\r\n+EGEOMAX: <maxfence>\r\n
+
+[Description]
+return maximum supported fence
+
+[Exmaple]
+\r\n+EGEOMAX: 100\r\n
+ maxfence = 100
+*/
+#define MTK_AT_GEOFENCE_MAX_NUM_RSP "\r\n+EGEOMAX"
+
+
+/*
+AT+EGEOADDCIRCLE=<AlertTypes>,<InitialState>,<lat1>,<lon1>,<radius>,<unknowntimerms>\r\n
+
+[Description]
+Create a geofence, given the fence initial state, fence type, fence descriptions (latitude,longitude, radius), and its initial condition
+
+[Parameter]
+<AlertTypes> (int)
+ GNSS_GEOFENCEALERTTYPE_ENTRY = (1<<0)
+ GNSS_GEOFENCEALERTTYPE_EXIT = (1<<1)
+<InitialState> (int)
+ GNSS_GeofenceState_Unknown = 0
+ GNSS_GeofenceState_Entered = 1
+ GNSS_GeofenceState_Exited = 2
+<lat1> (double by using %.6f)
+ in degree, valid range from -180.000000 to +180.000000, NaN indicates unavailable, WGS84 coordinate system
+<lon1> (double by using %.6f)
+ in degree, valid range from -90.000000 to +90.000000, NaN indicates unavailable, WGS84 coordinate system
+<radius> (double by using %.6f)
+ in meters
+<unknowntimerms> (int)
+ The time limit after which the UNCERTAIN transition should be triggered. This paramter is defined in milliseconds. Range <0~100000> milliseconds
+
+[Return]
+\r\n+EGEOADDCIRCLE...\r\n
+\r\nOK\r\n or \r\nERROR\r\n
+
+[Example]
+AT+EGEOADDCIRCLE=3,0,24.123456,121.012345,200.000000,10000\r\n
+ AlertTypes = 3, alert for both geofence entry and exit
+ InitialState = GNSS_GeofenceState_Unknown
+ lat1 = 24.123456 deg
+ lon1 = 121.012345 deg
+ radius = 200.000000 meters
+ unknowntimerms = 10000milliseconds
+*/
+#define MTK_AT_GEOFENCE_ADD_CIRCLE_REQ "AT+EGEOADDCIRCLE"
+
+
+/*
+\r\n+EGEOADDCIRCLE: <createstatus>[,<id>]\r\n
+
+[Description]
+Response from gnss service when a new geofence is created
+
+[Parameter]
+<createstatus> (int)
+ success = 0
+ error = -1
+ insufficient_memory = -2
+ too many fences = -3
+<id> (int)
+ geofence id generated by gnss service if add fence success
+
+[Example]
+\r\n+EGEOADDCIRCLE: 0,1\r\n
+ createstatus = success
+ id = 1
+
+\r\n+EGEOADDCIRCLE: -1\r\n
+ createstatus = failed
+*/
+#define MTK_AT_GEOFENCE_ADD_CIRCLE_RSP "\r\n+EGEOADDCIRCLE"
+
+
+/*
+AT+EGEODEL=<id>\r\n
+[Description]
+delete existing geofence
+
+[Parameter]
+<id> (int)
+ geofence id generated by gnss service
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+
+[Example]
+AT+EGEODEL=1\r\n
+ delete fence which id is 1
+*/
+#define MTK_AT_GEOFENCE_DEL_REQ "AT+EGEODEL"
+
+
+/*
+AT+EGEODELALL=\r\n
+
+[Description]
+delete all existing geofence
+
+[Return]
+\r\nOK\r\n or \r\nERROR\r\n
+*/
+#define MTK_AT_GEOFENCE_DEL_ALL_REQ "AT+EGEODELALL"
+
+
+/*
+\r\n+EGEORESP: <id>,<state>,<lat>,<lon>,<alt>,<speed>,<heading>,<HACC>,<HErrMajorAxis>,<HErrMinorAxis>,<HErrAngle>,<HorConf>,<PDOP>,<HDOP>,<VDOP>\r\n
+
+[Description]
+Alert from gnss service to notify a geofence breach
+
+[Parameter]
+<id> (int)
+ geofence id generated by gnss service
+<state> (int)
+ GNSS_GeofenceState_Unknown = 0, when gnss service isn't confident enough that the user is either enter or exit the Geofence
+ GNSS_GeofenceState_Entered = 1, when gnss service has 95% confident that the user is inside the geofence
+ GNSS_GeofenceState_Exited = 2, when gnss service has 95% confident that the user is outside the geofence
+<lat> (double by using %.6f)
+ in degree, valid range from -180.000000 to +180.000000, NaN indicates unavailable, WGS84 coordinate system
+<lon> (double by using %.6f)
+ in degree, valid range from -180.000000 to +180.000000, NaN indicates unavailable, WGS84 coordinate system
+<alt> (double by using %.2f)
+ in meters with respect to sea level
+<speed> (double by using %.2f)
+ in m/s, zero or positive value, NaN indicates unavailable
+<heading> (double by using %.2f)
+ in degrees,valid range from 0 to 360. zero indicates true north, NaN indicates unavailable
+<HACC> (int)
+ Represents expected horizontal position accuracy, radial, in meters (68% confidence).
+<HErrMajorAxis> (int)
+ in meters
+<HErrMinorAxis> (int)
+ in meters
+<HErrAngle> (int)
+ in degree, valid range from 0 to 360, NaN indicates unavailable
+<HorConf> (int)
+ horizontal confidence horizontal confidence in meter with 1-sigma accuracy
+<PDOP> (float by using %.2f)
+ position dilution of precision
+<HDOP> (float by using %.2f)
+ horizontal dilution of precision
+<VDOP> (float by using %.2f)
+ vertical dilution of precision
+
+[Example]
+\r\n+EGEORESP: 1,1,24.125465,121.365496,100.23,1.23,3.54,3,6,2,6,3,2.52,1.32,2.12\r\n
+ id = 1
+ state = GNSS_GeofenceState_Entered
+ lat = 24.125465 deg
+ lon = 121.365496 deg
+ altitude = 100.23 meters
+ speed = 1.23 m/s
+ heading = 3.54 degree
+ HACC = 3 meters
+ Horizontal error major axis = 6 meters
+ Horizontal error minor axis = 2 meters
+ Horizontal error angle = 6 deg
+ Horizontal confidence = 3 meters
+ PDOP = 2.52
+ HDOP = 1.32
+ VDOOP = 2.12
+
+\r\n+EGEORESP: 1,0,24.125465,121.365496,100.23,1.23,3.54,100,100,100,6,3,10.23,10.32,12.12\r\n
+ if less than 95% confident that the user is either inside or outside the fence, gnss service will consider the particular fence is in unknown state
+ response of the unknown state will be sent after the expiry of unknowntimerms.
+ id = 1
+ state = GNSS_GeofenceState_Unknown
+ lat = 24.125465 deg
+ lon = 121.365496 deg
+ altitude = 100.23 meters
+ speed = 1.23 m/s
+ heading = 3.54 degree
+ HACC = 100 meters
+ Horizontal error major axis = 100 meters
+ Horizontal error minor axis = 100 meters
+ Horizontal error angle = 6 deg
+ Horizontal confidence = 3 meters
+ PDOP = 10.23
+ HDOP = 10.32
+ VDOOP = 12.12
+*/
+#define MTK_AT_GEOFENCE_ALERT_NTF "\r\n+EGEORESP"
+
+
+/*
+\r\n+EGEOTRACK: <status>,<date_time>\r\n
+
+[Description]
+notification of any changes in tracking status while tracking a set of previously created geofences
+
+[Parameter]
+<status> (int)
+ GNSS service tracking OK = 0
+ GNSS service tracking failure = -1
+<date_time> (string)
+ UTC time in human readable format. ex: 2019/11/13,10:17:10
+
+[Example]
+\r\n+EGEOTRACK: 0,"2019/12/1,21:06:23"\r\n
+ status = tracking OK
+ date_time = 2019/12/1,21:06:23
+*/
+#define MTK_AT_GEOFENCE_TRACK_NTF "\r\n+EGEOTRACK"
+
+
+/*
+AT+ELCSTEST=<test_num1>,<test_num2>,<test_double1>,<test_double2>,<test_str1>,<test_str2>\r\n
+
+[Description]
+This is a test command and should be used in end product
+
+[Parameter]
+<test_num1> (int)
+<test_num2> (int)
+<test_double1> (double by using %.6f)
+<test_double2> (double by using %.6f)
+<test_str1> (string)
+<test_str2> (string)
+
+[Return]
+OK\r\n or ERROR\r\n
+
+[Example]
+AT+ETEST: 1,0,0,0,"",""\r\n
+cause GNSS Adaptor crash immediately
+
+AT+ETEST: 2,10,0,0,"hello",""\r\n
+delay 10 seconds and then send +ELCSLOOPBACK: "hello"\r\n to the host for PCIe wake up testing
+please note that +ELCSLOOPBACK: "hello"\r\n will be sent to all available channels (ex: PCIe, USB, ...etc.)
+
+AT+ETEST: 3,5,0,0,"world",""\r\n
+send +ELCSLOOPBACK: "world"\r\n to the host for 5 times
+*/
+#define MTK_AT_TEST_REQ "AT+ELCSTEST"
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_log.h b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_log.h
new file mode 100755
index 0000000..bc4ef94
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_log.h
@@ -0,0 +1,60 @@
+#ifndef __MTK_GNSS_AT_LOG_H__
+#define __MTK_GNSS_AT_LOG_H__
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h> //uint64_t, int64_t
+#include <unistd.h> //usleep
+#include <stdlib.h> //exit
+#include <string.h> //strerror()
+#include <errno.h>
+#include <sys/time.h> //gettimeofday, localtime
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LOGD(...) {\
+ struct timeval tv;\
+ struct timezone tz;\
+ struct tm* tm;\
+ gettimeofday(&tv, &tz);\
+ tm = localtime(&tv.tv_sec);\
+ printf("%04d/%02d/%02d %02d:%02d:%02d.%03d ",\
+ tm->tm_year+ 1900, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour,\
+ tm->tm_min, tm->tm_sec, (int)(tv.tv_usec/1000));\
+ printf("[GNSS AT][D] %s() %d ", __FUNCTION__, __LINE__); printf(__VA_ARGS__); printf("\n"); fflush(stdout); }
+#define LOGW(...) {\
+ struct timeval tv;\
+ struct timezone tz;\
+ struct tm* tm;\
+ gettimeofday(&tv, &tz);\
+ tm = localtime(&tv.tv_sec);\
+ printf("%04d/%02d/%02d %02d:%02d:%02d.%03d ",\
+ tm->tm_year+ 1900, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour,\
+ tm->tm_min, tm->tm_sec, (int)(tv.tv_usec/1000));\
+ printf("\E[1;35;40m"); printf("[GNSS AT][W] %s() %d ", __FUNCTION__, __LINE__); printf(__VA_ARGS__); printf("\E[0m"); printf("\n"); fflush(stdout); }
+#define LOGE(...) {\
+ struct timeval tv;\
+ struct timezone tz;\
+ struct tm* tm;\
+ gettimeofday(&tv, &tz);\
+ tm = localtime(&tv.tv_sec);\
+ printf("%04d/%02d/%02d %02d:%02d:%02d.%03d ",\
+ tm->tm_year+ 1900, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour,\
+ tm->tm_min, tm->tm_sec, (int)(tv.tv_usec/1000));\
+ printf("\E[1;31;40m"); printf("[GNSS AT][E] %s() %d ", __FUNCTION__, __LINE__); printf(__VA_ARGS__); printf("\E[0m"); printf("\n"); fflush(stdout); }
+
+#define assert(expr) {\
+ if(!(expr)) {\
+ LOGE("assert(%s) failed, %s %s() line=%d", #expr, __FILE__, __FUNCTION__, __LINE__);\
+ exit(1);\
+ }\
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __UTILS_H__
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_server.c b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_server.c
new file mode 100755
index 0000000..9d504b9
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_server.c
@@ -0,0 +1,694 @@
+#include "mtk_gnss_at_command.h"
+#include "mtk_gnss_at_server.h"
+#include "mtk_gnss_at_log.h"
+
+bool mtk_at_send_ok(int fd) {
+ char buff[] = "\r\nOK\r\n";
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_error(int fd) {
+ char buff[] = "\r\nERROR\r\n";
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_nmea_notify(int fd, const char* nmea) {
+ char buff[512] = {0};
+ int len = strlen(nmea);
+ if(len > 500) {
+ LOGE("nmea len=[%d] > 500", len);
+ return false;
+ }
+ mtk_at_gen_gnss_nmea_notify(buff, sizeof(buff), nmea);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_nmea_end_notify(int fd) {
+ char buff[64] = {0};
+ mtk_at_gen_gnss_nmea_end_notify(buff, sizeof(buff));
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_satellite_notify(int fd, mtk_gnss_satellite_list* list) {
+ char buff[3000] = {0};
+ if(list->num > 64) {
+ LOGE("list num=[%d] > 64", list->num);
+ return false;
+ }
+ mtk_at_gen_gnss_satellite_notify(buff, sizeof(buff), list);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_location_notify(int fd, mtk_gnss_location* location) {
+ char buff[256] = {0};
+ mtk_at_gen_gnss_location_notify(buff, sizeof(buff), location);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_agnss_location_notify(int fd, mtk_agnss_location* location) {
+ char buff[256] = {0};
+ mtk_at_gen_agnss_location_notify(buff, sizeof(buff), location);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+
+bool mtk_at_send_gnss_device_reset_notify(int fd, const char* reason) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_device_reset_notify(buff, sizeof(buff), reason);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_status_response(int fd, mtk_gnss_status* status) {
+ char buff[256] = {0};
+ mtk_at_gen_gnss_status_response(buff, sizeof(buff), status);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_ni_notify_request(int fd, mtk_gnss_ni_notify* notify) {
+ char buff[3072] = {0};
+ mtk_at_gen_gnss_ni_notify_request(buff, sizeof(buff), notify);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_ref_location_request(int fd) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_ref_location_request(buff, sizeof(buff));
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_ref_time_request(int fd) {
+ char buff[128] = {0};
+ mtk_at_gen_gnss_ref_time_request(buff, sizeof(buff));
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_loopback_response(int fd, const char* msg) {
+ char buff[5000] = {0};
+ mtk_at_gen_gnss_loopback_response(buff, sizeof(buff), msg);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_gnss_cert_name_response(int fd, mtk_gnss_cert_name_list* list) {
+ char buff[3000] = {0};
+ mtk_at_gen_gnss_cert_name_response(buff, sizeof(buff), list);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_geo_max_num_response(int fd, int num) {
+ char buff[64] = {0};
+ mtk_at_gen_geo_max_num_response(buff, sizeof(buff), num);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_geo_add_circle_response(int fd, mtk_geo_fence_create_state state, int id) {
+ char buff[64] = {0};
+ if(state > MTK_GEO_FENCE_CREATE_STATE_SUCCESS) {
+ LOGE("unexpected state=[%d] (<= 0)", state);
+ }
+ mtk_at_gen_geo_add_circle_response(buff, sizeof(buff), state, id);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_geo_alert_notify(int fd, mtk_geo_alert_notify* notify) {
+ char buff[256] = {0};
+ if(notify->state < MTK_GEO_STATE_UNKNOWN || notify->state > MTK_GEO_STATE_EXITED) {
+ LOGE("unexpected state=[%d] (0~2)", notify->state);
+ return false;
+ }
+ mtk_at_gen_geo_alert_notify(buff, sizeof(buff), notify);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_at_send_geo_track_notify(int fd, mtk_geo_track_state state, const char* date_time) {
+ char buff[128] = {0};
+ if(state != MTK_GEO_TRACK_STATE_OK && state != MTK_GEO_TRACK_STATE_FAILURE) {
+ LOGE("unexpected state=[%d] (0, -1)", state);
+ return false;
+ }
+ int len = strlen(date_time);
+ if(len > 120) {
+ LOGE("unexpected date_time len=[%d] (< 120)", len);
+ return false;
+ }
+ mtk_at_gen_geo_track_notify(buff, sizeof(buff), state, date_time);
+ int ret = write(fd, buff, strlen(buff));
+ if(ret == -1) {
+ LOGE("write() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+static bool mtk_at_gnss_start_request_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ if(callbacks->_mtk_at_gnss_start_request) {
+ return callbacks->_mtk_at_gnss_start_request(fd);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_stop_request_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ if(callbacks->_mtk_at_gnss_stop_request) {
+ return callbacks->_mtk_at_gnss_stop_request(fd);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_host_reset_notify_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ if(callbacks->_mtk_at_gnss_host_reset_notify) {
+ return callbacks->_mtk_at_gnss_host_reset_notify(fd);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_status_request_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ if(callbacks->_mtk_at_gnss_status_request) {
+ return callbacks->_mtk_at_gnss_status_request(fd);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_enable_set_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ bool enabled = 0;
+ mtk_at_parse_bool(&at_cmd, &enabled);
+ if(callbacks->_mtk_at_gnss_enable_set) {
+ return callbacks->_mtk_at_gnss_enable_set(fd, enabled);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_ni_enable_set_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ bool enabled = 0;
+ mtk_at_parse_bool(&at_cmd, &enabled);
+ if(callbacks->_mtk_at_gnss_ni_enable_set) {
+ return callbacks->_mtk_at_gnss_ni_enable_set(fd, enabled);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_agps_mode_set_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ mtk_gnss_agps_mode mode;
+ memset(&mode, 0, sizeof(mode));
+ mode.msa_valid = mtk_at_parse_bool(&at_cmd, &mode.msa);
+ mode.msb_valid = mtk_at_parse_bool(&at_cmd, &mode.msb);
+ mode.mss_valid = mtk_at_parse_bool(&at_cmd, &mode.mss);
+ mode.cid_valid = mtk_at_parse_bool(&at_cmd, &mode.cid);
+ mode.aflt_valid = mtk_at_parse_bool(&at_cmd, &mode.aflt);
+ mode.otdoa_valid = mtk_at_parse_bool(&at_cmd, &mode.otdoa);
+ mode.supl_pref_method_valid = mtk_at_parse_int32(&at_cmd, &mode.supl_pref_method);
+ mode.supl_valid = mtk_at_parse_bool(&at_cmd, &mode.supl);
+ mode.epo_valid = mtk_at_parse_bool(&at_cmd, &mode.epo);
+ if(mode.supl_pref_method < MTK_GNSS_SUPL_PREF_METHOD_MSA || mode.supl_pref_method > MTK_GNSS_SUPL_PREF_METHOD_NO_PREF) {
+ LOGE("unexpected supl_pref_method=[%d] (0~2)", mode.supl_pref_method);
+ return false;
+ }
+ if(callbacks->_mtk_at_gnss_agps_mode_set) {
+ return callbacks->_mtk_at_gnss_agps_mode_set(fd, &mode);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_supl_version_set_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ int maj = 0;
+ int min = 0;
+ int ser_ind = 0;
+ mtk_at_parse_int32(&at_cmd, &maj);
+ if(maj < 0) {
+ LOGE("unexpected SUPL major version=[%d] (> 0)", maj);
+ return false;
+ }
+ mtk_at_parse_int32(&at_cmd, &min);
+ if(min < 0) {
+ LOGE("unexpected SUPL minor version=[%d] (> 0)", min);
+ return false;
+ }
+ mtk_at_parse_int32(&at_cmd, &ser_ind);
+ if(ser_ind < 0) {
+ LOGE("unexpected SUPL minor version=[%d] (> 0)", ser_ind);
+ return false;
+ }
+ if(callbacks->_mtk_at_gnss_supl_version_set) {
+ return callbacks->_mtk_at_gnss_supl_version_set(fd, maj, min, ser_ind);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_supl_addr_set_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ char addr[128] = {0};
+ int port = 0;
+ bool tls_enabled = 0;
+ if(!mtk_at_parse_string(&at_cmd, addr, sizeof(addr))) {
+ LOGE("parse address failed");
+ return false;
+ }
+ mtk_at_parse_int32(&at_cmd, &port);
+ if(port < 0 || port > 65535) {
+ LOGE("unexpected port=[%d] (0~65535)", port);
+ return false;
+ }
+ mtk_at_parse_bool(&at_cmd, &tls_enabled);
+ if(callbacks->_mtk_at_gnss_supl_addr_set) {
+ return callbacks->_mtk_at_gnss_supl_addr_set(fd, addr, port, tls_enabled);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_delete_aiding_request_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ mtk_gnss_aiding_data flags;
+ memset(&flags, 0, sizeof(flags));
+
+ if(mtk_at_parse_comma_num(at_cmd) > 0) {
+ mtk_at_parse_bool(&at_cmd, &flags.eph);
+ mtk_at_parse_bool(&at_cmd, &flags.alm);
+ mtk_at_parse_bool(&at_cmd, &flags.pos);
+ mtk_at_parse_bool(&at_cmd, &flags.time);
+ mtk_at_parse_bool(&at_cmd, &flags.iono);
+ mtk_at_parse_bool(&at_cmd, &flags.utc);
+ mtk_at_parse_bool(&at_cmd, &flags.svdir);
+ mtk_at_parse_bool(&at_cmd, &flags.rti);
+ mtk_at_parse_bool(&at_cmd, &flags.celldb);
+ } else {
+ flags.all = true;
+ }
+
+ if(callbacks->_mtk_at_gnss_delete_aiding_data_request) {
+ return callbacks->_mtk_at_gnss_delete_aiding_data_request(fd, &flags);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_ni_notify_response_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ int id = 0;
+ mtk_gnss_ni_response_type type = MTK_GNSS_NI_RESPONSE_ACCEPT;
+ mtk_at_parse_int32(&at_cmd, &id);
+ mtk_at_parse_int32(&at_cmd, &type);
+ if(type < MTK_GNSS_NI_RESPONSE_ACCEPT || type > MTK_GNSS_NI_RESPONSE_NORESP) {
+ LOGE("unexpected type=[%d] (1~3)", type);
+ return false;
+ }
+ if(callbacks->_mtk_at_gnss_ni_notify_response) {
+ return callbacks->_mtk_at_gnss_ni_notify_response(fd, id, type);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_ref_location_response_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ int age = 0;
+ double lat = 0;
+ double lng = 0;
+ float acc = 0;
+ mtk_at_parse_int32(&at_cmd, &age);
+ if(age < 0) {
+ LOGE("unexpected age=[%d] (>0)", age);
+ return false;
+ }
+ mtk_at_parse_double(&at_cmd, &lat);
+ mtk_at_parse_double(&at_cmd, &lng);
+ mtk_at_parse_float(&at_cmd, &acc);
+ if(acc < 0) {
+ LOGE(" unexpected acc=[%f] (>0)", acc);
+ return false;
+ }
+ if(callbacks->_mtk_at_gnss_ref_location_response) {
+ return callbacks->_mtk_at_gnss_ref_location_response(fd, age, lat, lng, acc);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_ref_time_response_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ long long time = 0;
+ int uncertainty = 0;
+ mtk_at_parse_int64(&at_cmd, &time);
+ if(time < 0L) {
+ LOGE("unexpected time=[%lld] (> 0)", time);
+ return false;
+ }
+ mtk_at_parse_int32(&at_cmd, &uncertainty);
+ if(uncertainty < 0) {
+ LOGE("unexpected uncertainty=[%d] (> 0)", uncertainty);
+ return false;
+ }
+ if(callbacks->_mtk_at_gnss_ref_time_response) {
+ return callbacks->_mtk_at_gnss_ref_time_response(fd, time, uncertainty);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_nmea_config_set_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ bool enabled = 0;
+ mtk_at_parse_bool(&at_cmd, &enabled);
+ if(callbacks->_mtk_at_gnss_nmea_config_set) {
+ return callbacks->_mtk_at_gnss_nmea_config_set(fd, enabled);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_ttff_qop_set_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ int mode = 0;
+ mtk_at_parse_int32(&at_cmd, &mode);
+ if(callbacks->_mkt_at_gnss_ttff_qop_set) {
+ return callbacks->_mkt_at_gnss_ttff_qop_set(fd, mode);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_loopback_request_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ char msg[5000] = {0};
+ if(!mtk_at_parse_string(&at_cmd, msg, sizeof(msg))) {
+ LOGE("parse msg fail");
+ return false;
+ }
+ if(callbacks->_mtk_at_gnss_loopback_request) {
+ return callbacks->_mtk_at_gnss_loopback_request(fd, msg);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_cert_set_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ mtk_gnss_cert cert;
+ memset(&cert, 0, sizeof(cert));
+
+ if(!mtk_at_parse_int32(&at_cmd, &cert.total_msg_len)) {
+ LOGE("parse total_msg_len failed");
+ return false;
+ }
+ if(!mtk_at_parse_int32(&at_cmd, &cert.seq_no)) {
+ LOGE("parse seq_no failed");
+ return false;
+ }
+ if(!mtk_at_parse_string(&at_cmd, cert.name, sizeof(cert.name))) {
+ LOGE("parse name failed");
+ return false;
+ }
+ if(!mtk_at_parse_string(&at_cmd, cert.data, sizeof(cert.data))) {
+ LOGE("parse data failed");
+ return false;
+ }
+ if(callbacks->_mtk_at_gnss_cert_set) {
+ return callbacks->_mtk_at_gnss_cert_set(fd, &cert);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_cert_name_request_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ if(callbacks->_mtk_at_gnss_cert_name_request) {
+ return callbacks->_mtk_at_gnss_cert_name_request(fd);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_cert_delete_request_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ char name[129] = {0};
+
+ if(!mtk_at_parse_string(&at_cmd, name, sizeof(name))) {
+ LOGE("mtk_at_gnss_cert_delete_request_parser() parse name failed");
+ return false;
+ }
+ if(callbacks->_mtk_at_gnss_cert_delete_request) {
+ return callbacks->_mtk_at_gnss_cert_delete_request(fd, name);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_gnss_cert_delete_all_request_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ if(callbacks->_mtk_at_gnss_cert_delete_all_request) {
+ return callbacks->_mtk_at_gnss_cert_delete_all_request(fd);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_geo_max_num_request_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ if(callbacks->_mtk_at_geo_max_num_request) {
+ return callbacks->_mtk_at_geo_max_num_request(fd);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_geo_add_circle_request_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ mtk_geo_add_circle c;
+ memset(&c, 0, sizeof(c));
+ mtk_at_parse_int32(&at_cmd, &c.alert_type);
+ if(c.alert_type < 1 || c.alert_type > 3) {
+ LOGE("unexpected alert_type=[%d] (1~3)", c.alert_type);
+ return false;
+ }
+ mtk_at_parse_int32(&at_cmd, &c.initial_state);
+ if(c.initial_state < 0 || c.initial_state > 2) {
+ LOGE("unexpected initial_state=[%d] (0~2)", c.initial_state);
+ return false;
+ }
+ mtk_at_parse_double(&at_cmd, &c.lat);
+ mtk_at_parse_double(&at_cmd, &c.lng);
+ mtk_at_parse_double(&at_cmd, &c.radius);
+ if(c.radius < 0) {
+ LOGE("unexpected radius=[%f] (> 0)", c.radius);
+ return false;
+ }
+ mtk_at_parse_int32(&at_cmd, &c.unknowntimerms);
+ if(c.unknowntimerms < 0) {
+ LOGE("unexpected unknowntimerms=[%d] (> 0)", c.unknowntimerms);
+ return false;
+ }
+ if(callbacks->_mtk_at_geo_add_circle_request) {
+ return callbacks->_mtk_at_geo_add_circle_request(fd, &c);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_geo_delete_request_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ int id = 0;
+ mtk_at_parse_int32(&at_cmd, &id);
+ if(callbacks->_mtk_at_geo_delete_request) {
+ return callbacks->_mtk_at_geo_delete_request(fd, id);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_geo_delete_all_request_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ if(callbacks->_mtk_at_geo_delete_all_request) {
+ return callbacks->_mtk_at_geo_delete_all_request(fd);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+static bool mtk_at_test_request_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ int num1 = 0, num2 = 0;
+ double d1 = 0, d2 = 0;
+ char str1[1024] = {0};
+ char str2[1024] = {0};
+ mtk_at_parse_int32(&at_cmd, &num1);
+ mtk_at_parse_int32(&at_cmd, &num2);
+ mtk_at_parse_double(&at_cmd, &d1);
+ mtk_at_parse_double(&at_cmd, &d2);
+ mtk_at_parse_string(&at_cmd, str1, sizeof(str1));
+ mtk_at_parse_string(&at_cmd, str2, sizeof(str2));
+ if(callbacks->_mtk_at_test_request) {
+ return callbacks->_mtk_at_test_request(fd, num1, num2, d1, d2, str1, str2);
+ } else {
+ LOGE("callbacks is NULL");
+ }
+ return false;
+}
+
+bool mtk_at_server_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks) {
+ assert(at_cmd != NULL);
+ assert(callbacks != NULL);
+ const char* at_cmd_bkup = at_cmd;
+
+ //LOGD("mtk_at_server_parser() fd=[%d] at_cmd=[%s]", fd, at_cmd);
+
+ bool ret = true;
+ if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_START_REQ)) {
+ ret = mtk_at_gnss_start_request_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_STOP_REQ)) {
+ ret = mtk_at_gnss_stop_request_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_HOST_RESET_NTF)) {
+ ret = mtk_at_gnss_host_reset_notify_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_STATUS_REQ)) {
+ ret = mtk_at_gnss_status_request_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_GNSS_ENABLE_SET)) {
+ ret = mtk_at_gnss_enable_set_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_NI_ENABLE_SET)) {
+ ret = mtk_at_gnss_ni_enable_set_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_AGPS_MODE_SET)) {
+ ret = mtk_at_gnss_agps_mode_set_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_SUPL_VERSION_SET)) {
+ ret = mtk_at_gnss_supl_version_set_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_SUPL_ADDRESS_SET)) {
+ ret = mtk_at_gnss_supl_addr_set_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_DELETE_AIDING_REQ)) {
+ ret = mtk_at_gnss_delete_aiding_request_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_NI_NOTIFY_RSP)) {
+ ret = mtk_at_gnss_ni_notify_response_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_REF_LOC_RSP)) {
+ ret = mtk_at_gnss_ref_location_response_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_REF_TIME_RSP)) {
+ ret = mtk_at_gnss_ref_time_response_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_NMEA_CFG_SET)) {
+ ret = mtk_at_gnss_nmea_config_set_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_TTFF_QOP_SET)) {
+ ret = mtk_at_gnss_ttff_qop_set_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_LOOPBACK_REQ)) {
+ ret = mtk_at_gnss_loopback_request_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_CERT_SET)) {
+ ret = mtk_at_gnss_cert_set_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_CERT_NAME_REQ)) {
+ ret = mtk_at_gnss_cert_name_request_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_CERT_DEL_REQ)) {
+ ret = mtk_at_gnss_cert_delete_request_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GNSS_CERT_DEL_ALL_REQ)) {
+ ret = mtk_at_gnss_cert_delete_all_request_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GEOFENCE_MAX_NUM_REQ)) {
+ ret = mtk_at_geo_max_num_request_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GEOFENCE_ADD_CIRCLE_REQ)) {
+ ret = mtk_at_geo_add_circle_request_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GEOFENCE_DEL_REQ)) {
+ ret = mtk_at_geo_delete_request_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_GEOFENCE_DEL_ALL_REQ)) {
+ ret = mtk_at_geo_delete_all_request_parser(fd, at_cmd, callbacks);
+ } else if(mtk_at_parse_cmd(&at_cmd, MTK_AT_TEST_REQ)) {
+ ret = mtk_at_test_request_parser(fd, at_cmd, callbacks);
+ } else {
+ LOGW("unknown at_cmd=[%s]", at_cmd_bkup);
+ return false;
+ }
+
+ if(!ret) {
+ LOGW("wrong at_cmd=[%s]", at_cmd_bkup);
+ }
+
+ return ret;
+}
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_server.h b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_server.h
new file mode 100755
index 0000000..d646a85
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_server.h
@@ -0,0 +1,69 @@
+#ifndef __MTK_GNSS_AT_SERVER_H__
+#define __MTK_GNSS_AT_SERVER_H__
+
+#include "mtk_gnss_at_struct.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+//Common
+bool mtk_at_send_ok(int fd);
+bool mtk_at_send_error(int fd);
+//GNSS
+bool mtk_at_send_gnss_nmea_notify(int fd, const char* nmea);
+bool mtk_at_send_gnss_nmea_end_notify(int fd);
+bool mtk_at_send_gnss_satellite_notify(int fd, mtk_gnss_satellite_list* list);
+bool mtk_at_send_gnss_location_notify(int fd, mtk_gnss_location* location);
+bool mtk_at_send_gnss_agnss_location_notify(int fd, mtk_agnss_location* location);
+bool mtk_at_send_gnss_device_reset_notify(int fd, const char* reason);
+bool mtk_at_send_gnss_status_response(int fd, mtk_gnss_status* status);
+bool mtk_at_send_gnss_ni_notify_request(int fd, mtk_gnss_ni_notify* notify);
+bool mtk_at_send_gnss_ref_location_request(int fd);
+bool mtk_at_send_gnss_ref_time_request(int fd);
+bool mtk_at_send_gnss_loopback_response(int fd, const char* msg);
+bool mtk_at_send_gnss_cert_name_response(int fd, mtk_gnss_cert_name_list* list);
+//Geofence
+bool mtk_at_send_geo_max_num_response(int fd, int num);
+bool mtk_at_send_geo_add_circle_response(int fd, mtk_geo_fence_create_state state, int id);
+bool mtk_at_send_geo_alert_notify(int fd, mtk_geo_alert_notify* notify);
+bool mtk_at_send_geo_track_notify(int fd, mtk_geo_track_state state, const char* date_time);
+
+typedef struct {
+ bool (*_mtk_at_gnss_start_request) (int fd);
+ bool (*_mtk_at_gnss_stop_request) (int fd);
+ bool (*_mtk_at_gnss_host_reset_notify) (int fd);
+ bool (*_mtk_at_gnss_status_request) (int fd);
+ bool (*_mtk_at_gnss_enable_set) (int fd, bool enabled);
+ bool (*_mtk_at_gnss_ni_enable_set) (int fd, bool enabled);
+ bool (*_mtk_at_gnss_agps_mode_set) (int fd, mtk_gnss_agps_mode* mode);
+ bool (*_mtk_at_gnss_supl_version_set) (int fd, int maj, int min, int ser_ind);
+ bool (*_mtk_at_gnss_supl_addr_set) (int fd, const char* addr, int port, bool tls_enabled);
+ bool (*_mtk_at_gnss_delete_aiding_data_request) (int fd, mtk_gnss_aiding_data* flags);
+ bool (*_mtk_at_gnss_ni_notify_response) (int fd, int id, mtk_gnss_ni_response_type response);
+ bool (*_mtk_at_gnss_ref_location_response) (int fd, int age, double lat, double lng, float acc);
+ bool (*_mtk_at_gnss_ref_time_response) (int fd, long long time, int uncertainty);
+ bool (*_mtk_at_gnss_nmea_config_set) (int fd, bool enabled);
+ bool (*_mkt_at_gnss_ttff_qop_set) (int fd, int mode);
+ bool (*_mtk_at_gnss_loopback_request) (int fd, const char* msg);
+ bool (*_mtk_at_gnss_cert_set) (int fd, mtk_gnss_cert* cert);
+ bool (*_mtk_at_gnss_cert_name_request) (int fd);
+ bool (*_mtk_at_gnss_cert_delete_request) (int fd, const char* name);
+ bool (*_mtk_at_gnss_cert_delete_all_request) (int fd);
+ bool (*_mtk_at_geo_max_num_request) (int fd);
+ bool (*_mtk_at_geo_add_circle_request) (int fd, mtk_geo_add_circle* circle);
+ bool (*_mtk_at_geo_delete_request) (int fd, int id);
+ bool (*_mtk_at_geo_delete_all_request) (int fd);
+ bool (*_mtk_at_test_request) (int fd, int num1, int num2, double d1, double d2, const char* str1, const char* str2);
+} mtk_gnss_at_server_callbacks;
+
+bool mtk_at_server_parser(int fd, const char* at_cmd, mtk_gnss_at_server_callbacks* callbacks);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_struct.c b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_struct.c
new file mode 100755
index 0000000..0aec50b
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_struct.c
@@ -0,0 +1,781 @@
+#include <ctype.h> // isspace
+#include <time.h>
+#include <sys/time.h>
+#include "mtk_gnss_at_command.h"
+#include "mtk_gnss_at_struct.h"
+#include "mtk_gnss_at_log.h"
+
+static const char* at_lstrip(const char* at_cmd) {
+ assert(at_cmd != NULL);
+
+ char* start = (char*)at_cmd;
+ while(*start && isspace(*start)) {
+ start++;
+ }
+ return start;
+}
+
+bool mtk_at_parse_cmd(const char** at_cmd, const char* target_cmd) {
+ assert(at_cmd != NULL);
+ assert(target_cmd != NULL);
+
+ int len = strlen(target_cmd);
+ if(strncmp(*at_cmd, target_cmd, len) == 0) {
+ char prefix_end = (*at_cmd + len)[0];
+ if(prefix_end == ':' || prefix_end == '=' || prefix_end == '\r' || prefix_end == '\n' ||
+ prefix_end == ' ' || prefix_end == '\t' || prefix_end == '\0') {
+ *at_cmd = at_lstrip(*at_cmd + len + 1);
+ return true;
+ }
+ }
+ return false;
+}
+
+static const char* at_next_param(const char* at_cmd) {
+ assert(at_cmd != NULL);
+
+ char* start = (char*)at_cmd;
+ while(*start && *start != ',') {
+ start++;
+ }
+ if(*start) {
+ start++;
+ }
+ return at_lstrip(start);
+}
+
+int mtk_at_parse_comma_num(const char* at_cmd) {
+ int count = 0;
+ while(*at_cmd) {
+ if(*at_cmd == ',') {
+ count++;
+ }
+ at_cmd++;
+ }
+ return count;
+}
+
+bool mtk_at_parse_string(const char** at_cmd, char* output, int output_size) {
+ assert(at_cmd != NULL);
+ assert(output != NULL);
+ assert(output_size >= 0);
+
+ char* start = (char*)(*at_cmd);
+ char* end = NULL;
+
+ if(*start == ',') {
+ *at_cmd = at_next_param(*at_cmd);
+ return false;
+ }
+
+ while(*start && *start != '"' && *start != ',') {
+ start++;
+ }
+
+ if(*start == 0) {
+ return false;
+ } else if(*start == ',') {
+ *at_cmd = at_next_param(start);
+ return false;
+ } else {
+ start++;
+ end = start;
+ while(*end && *end != '"') {
+ end++;
+ }
+ if(*end == 0) {
+ *at_cmd = end;
+ return false;
+ } else {
+ int len = end - start;
+ if((len + 1) >= output_size) {
+ LOGE("mtk_at_parse_string() len=%d > output_size=%d", len, output_size);
+ return false;
+ } else {
+ strncpy(output, start, len);
+ output[len] = 0;
+ *at_cmd = at_next_param(end);
+ return true;
+ }
+ }
+ }
+ LOGE("mtk_at_parse_string() unexpected flow");
+ return false;
+}
+
+bool mtk_at_parse_bool(const char** at_cmd, bool* output) {
+ int value = 0;
+ int ret = mtk_at_parse_int32(at_cmd, &value);
+ if(ret) {
+ *output = value? true:false;
+ }
+ return ret;
+}
+
+bool mtk_at_parse_int32(const char** at_cmd, int* output) {
+ assert(at_cmd != NULL);
+ assert(output != NULL);
+
+ int ret = sscanf(*at_cmd, "%d", output);
+ if(ret > 0) {
+ *at_cmd = at_next_param((*at_cmd) + 1);
+ return true;
+ }
+ if(**at_cmd) {
+ *at_cmd = at_next_param((*at_cmd));
+ }
+ return false;
+}
+
+bool mtk_at_parse_int64(const char** at_cmd, long long* output) {
+ assert(at_cmd != NULL);
+ assert(output != NULL);
+
+ int ret = sscanf(*at_cmd, "%lld", output);
+ if(ret > 0) {
+ *at_cmd = at_next_param((*at_cmd) + 1);
+ return true;
+ }
+ if(**at_cmd) {
+ *at_cmd = at_next_param((*at_cmd));
+ }
+ return false;
+}
+
+bool mtk_at_parse_float(const char** at_cmd, float* output) {
+ assert(at_cmd != NULL);
+ assert(output != NULL);
+
+ int ret = sscanf(*at_cmd, "%f", output);
+ if(ret > 0) {
+ *at_cmd = at_next_param((*at_cmd) + 1);
+ return true;
+ }
+ if(**at_cmd) {
+ *at_cmd = at_next_param((*at_cmd));
+ }
+ return false;
+}
+
+bool mtk_at_parse_double(const char** at_cmd, double* output) {
+ assert(at_cmd != NULL);
+ assert(output != NULL);
+
+ int ret = sscanf(*at_cmd, "%lf", output);
+ if(ret > 0) {
+ *at_cmd = at_next_param((*at_cmd) + 1);
+ return true;
+ }
+ if(**at_cmd) {
+ *at_cmd = at_next_param((*at_cmd));
+ }
+ return false;
+}
+
+void mtk_at_dump_mtk_gnss_satellite_list(mtk_gnss_satellite_list* list) {
+ assert(list != NULL);
+ LOGD("mtk_at_dump_mtk_gnss_satellite_list() num=%d", list->num);
+ int i = 0;
+ for(i = 0; i < list->num; i++) {
+ LOGD(" i=[%d] svid=[%02d] constellation=[%d] cn0=[%.02f] elevation=[%.02f] azimuth=[%.02f] flags=[0x%x] carrier_frequency=[%.02f]",
+ i, list->satellites[i].svid, list->satellites[i].constellation, list->satellites[i].cn0,
+ list->satellites[i].elevation, list->satellites[i].azimuth, list->satellites[i].flags,
+ list->satellites[i].carrier_frequency);
+ }
+}
+
+void mtk_at_dump_mtk_gnss_location(mtk_gnss_location* l) {
+ assert(l != NULL);
+ LOGD("mtk_at_dump_mtk_gnss_location() lat=[%lf]%d lng=[%lf]%d alt=[%.2f]%d speed=[%.2f]%d bearing=[%.2f]%d h_acc=[%.2f]%d v_acc=[%.2f]%d s_acc=[%.2f]%d "\
+ "b_acc=[%.2f]%d timestamp=[%lld]%d date_time=[%s]%d pdop=[%.2f]%d hdop=[%.2f]%d vdop=[%.2f]%d",
+ l->lat, l->lat_valid, l->lng, l->lng_valid, l->alt, l->alt_valid, l->speed, l->speed_valid, l->bearing, l->bearing_valid,
+ l->h_acc, l->h_acc_valid, l->v_acc, l->v_acc_valid, l->s_acc, l->s_acc_valid, l->b_acc, l->b_acc_valid, l->timestamp, l->timestamp_valid,
+ l->date_time, l->date_time_valid, l->pdop, l->pdop_valid, l->hdop, l->hdop_valid, l->vdop, l->vdop_valid);
+}
+
+void mtk_at_dump_mtk_agnss_location(mtk_agnss_location* l) {
+ assert(l != NULL);
+ LOGD("mtk_at_dump_mtk_agnss_location() lat=[%lf] lng=[%lf] alt[%.2f]%d speed=[%.2f]%d bearing=[%.2f]%d h_acc=[%.2f]%d"\
+ " timestamp=[%lld]%d date_time=[%s]%d type=[%d]%d",
+ l->lat, l->lng, l->alt, l->alt_valid, l->speed, l->speed_valid, l->bearing, l->bearing_valid,
+ l->h_acc, l->h_acc_valid, l->timestamp, l->timestamp_valid, l->date_time, l->date_time_valid, l->type, l->type_valid);
+}
+
+
+void mtk_at_dump_mtk_gnss_status(mtk_gnss_status* status) {
+ assert(status != NULL);
+ LOGD("mtk_at_dump_mtk_gnss_status() gnss_status=[%d] ni_status=[%d] supl_maj_ver=[%d] supl_min_ver=[%d] gnss_version=[%s] agps_version=[%s]"\
+ " supl_ser_ind=[%d] supl_addr=[%s] supl_port=[%d] supl_tls_enabled=[%d] imsi_valid=[%d] imsi=[%s] num_digital_mnc_in_imsi_valid=[%d]"\
+ " num_digital_mnc_in_imsi=[%d]",
+ status->gnss_status, status->ni_status, status->supl_maj_ver, status->supl_min_ver, status->gnss_version, status->agps_version,
+ status->supl_ser_ind, status->supl_addr, status->supl_port, status->supl_tls_enabled, status->imsi_valid, status->imsi,
+ status->num_digital_mnc_in_imsi_valid, status->num_digital_mnc_in_imsi);
+}
+
+void mtk_at_dump_mtk_gnss_agps_mode(mtk_gnss_agps_mode* mode) {
+ assert(mode != NULL);
+ LOGD("mtk_at_dump_mtk_gnss_agps_mode() msa=[%d]%d msb=[%d]%d mss=[%d]%d cid=[%d]%d aflt=[%d]%d otdoa=[%d]%d supl_pref_method=[%d]%d(0=MSA, 1=MSB, 2=NO Pref)"\
+ " supl=[%d]%d epo=[%d]%d",
+ mode->msa, mode->msa_valid, mode->msb, mode->msb_valid, mode->mss, mode->mss_valid, mode->cid, mode->cid_valid, mode->aflt, mode->aflt_valid,
+ mode->otdoa, mode->otdoa_valid, mode->supl_pref_method, mode->supl_pref_method_valid, mode->supl, mode->supl_valid, mode->epo, mode->epo_valid);
+}
+
+void mtk_at_dump_mtk_gnss_aiding_data(mtk_gnss_aiding_data* data) {
+ assert(data != NULL);
+ LOGD("mtk_at_dump_mtk_gnss_aiding_data() all=[%d] eph=[%d] alm=[%d] pos=[%d] time=[%d] iono=[%d] utc=[%d] svdir=[%d] rti=[%d] celldb=[%d]",
+ data->all, data->eph, data->alm, data->pos, data->time, data->iono, data->utc, data->svdir, data->rti, data->celldb);
+}
+
+void mtk_at_dump_mtk_gnss_ni_notify(mtk_gnss_ni_notify* notify) {
+ assert(notify != NULL);
+ LOGD("mtk_at_dump_mtk_gnss_ni_notify() id=[%d] type=[%d] notify_type=[%d] requestor_id=[%s] encode=[%d] text=[%s] encode=[%d]",
+ notify->id, notify->type, notify->notify_type, notify->request_id, notify->request_id_encode_type, notify->text, notify->text_encode_type);
+}
+
+void mtk_at_dump_mtk_gnss_cert(mtk_gnss_cert* cert) {
+ assert(cert != NULL);
+ LOGD("mtk_at_dump_mtk_gnss_cert() total_msg_len=[%d] seq_no=[%d] name=[%s] data=[%s]",
+ cert->total_msg_len, cert->seq_no, cert->name, cert->data);
+}
+
+void mtk_at_dump_mtk_gnss_cert_name_list(mtk_gnss_cert_name_list* list) {
+ assert(list != NULL);
+ int i = 0;
+ LOGD("mtk_at_dump_mtk_gnss_cert_name_list() num=[%d]", list->num);
+ for(i = 0; i < list->num; i++) {
+ LOGD(" i=[%d] name=[%s]", i, list->names[i]);
+ }
+}
+
+void mtk_at_dump_mtk_geo_add_circle(mtk_geo_add_circle* circle) {
+ assert(circle != NULL);
+ LOGD("mtk_at_dump_mtk_geo_add_circle() alert_type=[%d] (1=entry 2=exit) initial_state=[%d] (0=unknown 1=entered 2=exited) lat=[%.6f] lng=[%.6f] radius=[%.2f] unknowntimerms=[%d]",
+ circle->alert_type, circle->initial_state, circle->lat, circle->lng, circle->radius, circle->unknowntimerms);
+}
+
+void mtk_at_dump_mtk_geo_alert_notify(mtk_geo_alert_notify* alert) {
+ assert(alert != NULL);
+ LOGD("mtk_at_dump_mtk_geo_alert_notify() id=[%d] state=[%d] (0=unknown 1=entered 2=exited) lat=[%.6f] lng=[%.6f] alt=[%.2f] speed=[%.2f] "
+ "heading=[%.2f] hacc=[%d] h_err_maj=[%d] h_err_min=[%d] h_err_angle=[%d] h_confidence=[%d] pdop=[%.2f] hdop=[%.2f] vdop=[%.2f]",
+ alert->id, alert->state, alert->lat, alert->lng, alert->alt, alert->speed, alert->heading, alert->hacc,
+ alert->h_err_maj, alert->h_err_min, alert->h_err_angle, alert->h_confidence, alert->pdop, alert->hdop, alert->vdop);
+}
+
+void mtk_at_gen_gnss_start_request(char* at_cmd, int at_cmd_size) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s=\r\n", MTK_AT_GNSS_START_REQ);
+}
+
+void mtk_at_gen_gnss_stop_request(char* at_cmd, int at_cmd_size) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s=\r\n", MTK_AT_GNSS_STOP_REQ);
+}
+
+void mtk_at_gen_gnss_nmea_notify(char* at_cmd, int at_cmd_size, const char* nmea) {
+ assert(nmea != NULL);
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s: \"%s\"\r\n", MTK_AT_GNSS_NMEA_NTF, nmea);
+}
+
+void mtk_at_gen_gnss_nmea_end_notify(char* at_cmd, int at_cmd_size) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s\r\n", MTK_AT_GNSS_NMEA_END_NTF);
+}
+
+void mtk_at_gen_gnss_satellite_notify(char* at_cmd, int at_cmd_size, mtk_gnss_satellite_list* list) {
+ assert(list != NULL);
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ int i = 0;
+
+ at_cmd += sprintf(at_cmd, "%s: %d", MTK_AT_GNSS_SATELLITE_NTF, list->num);
+ for(i = 0; i < list->num; i++) {
+ at_cmd += sprintf(at_cmd, ",%d,%d,%.2f,%.2f,%.2f,%d,%.2f",
+ list->satellites[i].svid, list->satellites[i].constellation, list->satellites[i].cn0,
+ list->satellites[i].elevation, list->satellites[i].azimuth, list->satellites[i].flags,
+ list->satellites[i].carrier_frequency);
+ }
+ at_cmd += sprintf(at_cmd, "\r\n");
+}
+void mtk_at_gen_agnss_location_notify(char* at_cmd, int at_cmd_size, mtk_agnss_location* location) {
+ assert(location != NULL);
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ at_cmd += sprintf(at_cmd, "%s: ", MTK_AT_GNSS_AGPS_LOCATION_NTF);
+ at_cmd += sprintf(at_cmd, "%.6f,", location->lat);
+ at_cmd += sprintf(at_cmd, "%.6f,", location->lng);
+
+ if(location->alt_valid) {
+ at_cmd += sprintf(at_cmd, "%.2f", location->alt);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->speed_valid) {
+ at_cmd += sprintf(at_cmd, "%.2f", location->speed);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->bearing_valid) {
+ at_cmd += sprintf(at_cmd, "%.2f", location->bearing);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->h_acc_valid) {
+ at_cmd += sprintf(at_cmd, "%.2f", location->h_acc);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->timestamp_valid) {
+ at_cmd += sprintf(at_cmd, "%lld", location->timestamp);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->timestamp_valid) {
+ struct timeval tv;
+ struct tm *tm;
+ tv.tv_sec = location->timestamp / 1000;
+ tm = gmtime(&tv.tv_sec);
+
+ location->date_time_valid = true;
+ sprintf(location->date_time, "%04d/%02d/%02d,%02d:%02d:%02d",
+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
+ at_cmd += sprintf(at_cmd, "\"%s\"", location->date_time);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->type_valid) {
+ at_cmd += sprintf(at_cmd, "%d", location->type);
+ }
+ at_cmd += sprintf(at_cmd, "\r\n");
+}
+
+void mtk_at_gen_gnss_location_notify(char* at_cmd, int at_cmd_size, mtk_gnss_location* location) {
+ assert(location != NULL);
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ at_cmd += sprintf(at_cmd, "%s: ", MTK_AT_GNSS_LOCATION_NTF);
+
+ if(location->lat_valid) {
+ at_cmd += sprintf(at_cmd, "%.6f", location->lat);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->lng_valid) {
+ at_cmd += sprintf(at_cmd, "%.6f", location->lng);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->alt_valid) {
+ at_cmd += sprintf(at_cmd, "%.2f", location->alt);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->speed_valid) {
+ at_cmd += sprintf(at_cmd, "%.2f", location->speed);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->bearing_valid) {
+ at_cmd += sprintf(at_cmd, "%.2f", location->bearing);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->h_acc_valid) {
+ at_cmd += sprintf(at_cmd, "%.2f", location->h_acc);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->v_acc_valid) {
+ at_cmd += sprintf(at_cmd, "%.2f", location->v_acc);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->s_acc_valid) {
+ at_cmd += sprintf(at_cmd, "%.2f", location->s_acc);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->b_acc_valid) {
+ at_cmd += sprintf(at_cmd, "%.2f", location->b_acc);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->timestamp_valid) {
+ at_cmd += sprintf(at_cmd, "%lld", location->timestamp);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->timestamp_valid) {
+ struct timeval tv;
+ struct tm *tm;
+ tv.tv_sec = location->timestamp / 1000;
+ tm = gmtime(&tv.tv_sec);
+
+ location->date_time_valid = true;
+ sprintf(location->date_time, "%04d/%02d/%02d,%02d:%02d:%02d",
+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
+ at_cmd += sprintf(at_cmd, "\"%s\"", location->date_time);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->pdop_valid) {
+ at_cmd += sprintf(at_cmd, "%.2f", location->pdop);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->hdop_valid) {
+ at_cmd += sprintf(at_cmd, "%.2f", location->hdop);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(location->vdop_valid) {
+ at_cmd += sprintf(at_cmd, "%.2f", location->vdop);
+ }
+ at_cmd += sprintf(at_cmd, "\r\n");
+}
+
+void mtk_at_gen_gnss_host_reset_notify(char* at_cmd, int at_cmd_size) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s\r\n", MTK_AT_GNSS_HOST_RESET_NTF);
+}
+
+void mtk_at_gen_gnss_device_reset_notify(char* at_cmd, int at_cmd_size, const char* reason) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s: \"%s\"\r\n", MTK_AT_GNSS_GNSS_RESET_NTF, reason);
+}
+
+void mtk_at_gen_gnss_status_request(char* at_cmd, int at_cmd_size) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s\r\n", MTK_AT_GNSS_STATUS_REQ);
+}
+
+void mtk_at_gen_gnss_status_response(char* at_cmd, int at_cmd_size, mtk_gnss_status* status) {
+ assert(status != NULL);
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ at_cmd += sprintf(at_cmd, "%s: %d,%d,%d,%d,\"%s\",\"%s\",%d,\"%s\",%d,%d", MTK_AT_GNSS_STATUS_RSP,
+ status->gnss_status, status->ni_status, status->supl_maj_ver, status->supl_min_ver,
+ status->gnss_version, status->agps_version, status->supl_ser_ind, status->supl_addr,
+ status->supl_port, status->supl_tls_enabled);
+
+ at_cmd += sprintf(at_cmd, ",");
+ if(status->imsi_valid) {
+ at_cmd += sprintf(at_cmd, "\"%s\"", status->imsi);
+ }
+
+ at_cmd += sprintf(at_cmd, ",");
+ if(status->num_digital_mnc_in_imsi_valid) {
+ at_cmd += sprintf(at_cmd, "%d", status->num_digital_mnc_in_imsi);
+ }
+
+ at_cmd += sprintf(at_cmd, "\r\n");
+}
+
+void mtk_at_gen_gnss_enable_set(char* at_cmd, int at_cmd_size, bool enabled) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s=%d\r\n", MTK_AT_GNSS_GNSS_ENABLE_SET, enabled);
+}
+
+void mtk_at_gen_gnss_ni_enable_set(char* at_cmd, int at_cmd_size, bool enabled) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s=%d\r\n", MTK_AT_GNSS_NI_ENABLE_SET, enabled);
+}
+
+void mtk_at_gen_gnss_agps_mode_set(char* at_cmd, int at_cmd_size, mtk_gnss_agps_mode* mode) {
+ assert(mode != NULL);
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ at_cmd += sprintf(at_cmd, "%s=", MTK_AT_GNSS_AGPS_MODE_SET);
+ if(mode->msa_valid) {
+ at_cmd += sprintf(at_cmd, "%d", mode->msa);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(mode->msb_valid) {
+ at_cmd += sprintf(at_cmd, "%d", mode->msb);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(mode->mss_valid) {
+ at_cmd += sprintf(at_cmd, "%d", mode->mss);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(mode->cid_valid) {
+ at_cmd += sprintf(at_cmd, "%d", mode->cid);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(mode->aflt_valid) {
+ at_cmd += sprintf(at_cmd, "%d", mode->aflt);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(mode->otdoa_valid) {
+ at_cmd += sprintf(at_cmd, "%d", mode->otdoa);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(mode->supl_pref_method_valid) {
+ at_cmd += sprintf(at_cmd, "%d", mode->supl_pref_method);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(mode->supl_valid) {
+ at_cmd += sprintf(at_cmd, "%d", mode->supl);
+ }
+ at_cmd += sprintf(at_cmd, ",");
+
+ if(mode->epo_valid) {
+ at_cmd += sprintf(at_cmd, "%d", mode->epo);
+ }
+
+ at_cmd += sprintf(at_cmd, "\r\n");
+}
+
+void mtk_at_gen_gnss_supl_version_set(char* at_cmd, int at_cmd_size, int maj, int min, int ser_ind) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s=%d,%d,%d\r\n", MTK_AT_GNSS_SUPL_VERSION_SET, maj, min, ser_ind);
+}
+
+void mtk_at_gen_gnss_supl_addr_set(char* at_cmd, int at_cmd_size, const char* addr, int port, bool tls_enabled) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+ assert(addr != NULL);
+
+ sprintf(at_cmd, "%s=\"%s\",%d,%d\r\n", MTK_AT_GNSS_SUPL_ADDRESS_SET, addr, port, tls_enabled);
+}
+
+void mtk_at_gen_gnss_delete_aiding_data_request(char* at_cmd, int at_cmd_size, mtk_gnss_aiding_data* flags) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+ assert(flags != NULL);
+
+ if(flags->all) {
+ sprintf(at_cmd, "%s=\r\n", MTK_AT_GNSS_DELETE_AIDING_REQ);
+ } else {
+ sprintf(at_cmd, "%s=%d,%d,%d,%d,%d,%d,%d,%d,%d\r\n", MTK_AT_GNSS_DELETE_AIDING_REQ,
+ flags->eph, flags->alm, flags->pos, flags->time, flags->iono, flags->utc, flags->svdir,
+ flags->rti, flags->celldb);
+ }
+}
+
+void mtk_at_gen_gnss_ni_notify_request(char* at_cmd, int at_cmd_size, mtk_gnss_ni_notify* notify) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+ assert(notify != NULL);
+
+ sprintf(at_cmd, "%s: %d,%d,%d,\"%s\",%d,\"%s\",%d\r\n", MTK_AT_GNSS_NI_NOTIFY_REQ,
+ notify->id, notify->type, notify->notify_type, notify->request_id, notify->request_id_encode_type,
+ notify->text, notify->text_encode_type);
+}
+
+void mtk_at_gen_gnss_ni_notify_response(char* at_cmd, int at_cmd_size, int id, mtk_gnss_ni_response_type response) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s=%d,%d\r\n", MTK_AT_GNSS_NI_NOTIFY_RSP, id, response);
+}
+
+void mtk_at_gen_gnss_ref_location_request(char* at_cmd, int at_cmd_size) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s\r\n", MTK_AT_GNSS_REF_LOC_REQ);
+}
+
+void mtk_at_gen_gnss_ref_location_response(char* at_cmd, int at_cmd_size, int age, double lat, double lng, float acc) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s=%d,%.6f,%.6f,%.2f\r\n", MTK_AT_GNSS_REF_LOC_RSP, age, lat, lng, acc);
+}
+
+void mtk_at_gen_gnss_ref_time_request(char* at_cmd, int at_cmd_size) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s\r\n", MTK_AT_GNSS_REF_TIME_REQ);
+}
+
+void mtk_at_gen_gnss_ref_time_response(char* at_cmd, int at_cmd_size, long long time, int uncertainty) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s=%lld,%d\r\n", MTK_AT_GNSS_REF_TIME_RSP, time, uncertainty);
+}
+
+void mtk_at_gen_gnss_nmea_config_set(char* at_cmd, int at_cmd_size, bool enabled) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s=%d\r\n", MTK_AT_GNSS_NMEA_CFG_SET, enabled);
+}
+
+void mtk_at_gen_gnss_ttff_qop_set(char* at_cmd, int at_cmd_size, int mode) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s=%d\r\n", MTK_AT_GNSS_TTFF_QOP_SET, mode);
+}
+
+void mtk_at_gen_gnss_loopback_request(char* at_cmd, int at_cmd_size, const char* msg) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+ assert(msg != NULL);
+
+ sprintf(at_cmd, "%s=\"%s\"\r\n", MTK_AT_GNSS_LOOPBACK_REQ, msg);
+}
+
+void mtk_at_gen_gnss_loopback_response(char* at_cmd, int at_cmd_size, const char* msg) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+ assert(msg != NULL);
+
+ sprintf(at_cmd, "%s=\"%s\"\r\n", MTK_AT_GNSS_LOOPBACK_RSP, msg);
+}
+
+void mtk_at_gen_gnss_cert_set(char* at_cmd, int at_cmd_size, mtk_gnss_cert* cert) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+ assert(cert != NULL);
+
+ sprintf(at_cmd, "%s=%d,%d,\"%s\",\"%s\"\r\n", MTK_AT_GNSS_CERT_SET, cert->total_msg_len, cert->seq_no, cert->name, cert->data);
+}
+
+void mtk_at_gen_gnss_cert_name_request(char* at_cmd, int at_cmd_size) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s\r\n", MTK_AT_GNSS_CERT_NAME_REQ);
+}
+
+void mtk_at_gen_gnss_cert_name_response(char* at_cmd, int at_cmd_size, mtk_gnss_cert_name_list* list) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+ assert(list != NULL);
+
+ int i = 0;
+ at_cmd += sprintf(at_cmd, "%s: ", MTK_AT_GNSS_CERT_NAME_RSP);
+ for(i = 0; i < list->num; i++) {
+ at_cmd += sprintf(at_cmd, "\"%s\",", list->names[i]);
+ }
+ at_cmd--;
+ at_cmd += sprintf(at_cmd, "\r\n");
+}
+
+void mtk_at_gen_gnss_cert_delete_request(char* at_cmd, int at_cmd_size, const char* name) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+ assert(name != NULL);
+
+ sprintf(at_cmd, "%s=\"%s\"\r\n", MTK_AT_GNSS_CERT_DEL_REQ, name);
+}
+
+void mtk_at_gen_gnss_cert_delete_all_request(char* at_cmd, int at_cmd_size) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s\r\n", MTK_AT_GNSS_CERT_DEL_ALL_REQ);
+}
+
+void mtk_at_gen_geo_max_num_request(char* at_cmd, int at_cmd_size) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s\r\n", MTK_AT_GEOFENCE_MAX_NUM_REQ);
+}
+
+void mtk_at_gen_geo_max_num_response(char* at_cmd, int at_cmd_size, int num) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s: %d\r\n", MTK_AT_GEOFENCE_MAX_NUM_RSP, num);
+}
+
+void mtk_at_gen_geo_add_circle_request(char* at_cmd, int at_cmd_size, mtk_geo_add_circle* circle) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+ assert(circle != NULL);
+
+ sprintf(at_cmd, "%s=%d,%d,%.6f,%.6f,%.6f,%d\r\n", MTK_AT_GEOFENCE_ADD_CIRCLE_REQ,
+ circle->alert_type, circle->initial_state, circle->lat, circle->lng, circle->radius, circle->unknowntimerms);
+}
+
+void mtk_at_gen_geo_add_circle_response(char* at_cmd, int at_cmd_size, mtk_geo_fence_create_state state, int id) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ if(state == MTK_GEO_FENCE_CREATE_STATE_SUCCESS) {
+ sprintf(at_cmd, "%s: %d,%d\r\n", MTK_AT_GEOFENCE_ADD_CIRCLE_RSP, state, id);
+ } else {
+ sprintf(at_cmd, "%s: %d\r\n", MTK_AT_GEOFENCE_ADD_CIRCLE_RSP, state);
+ }
+}
+
+void mtk_at_gen_geo_delete_request(char* at_cmd, int at_cmd_size, int id) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s=%d\r\n", MTK_AT_GEOFENCE_DEL_REQ, id);
+}
+
+void mtk_at_gen_geo_delete_all_request(char* at_cmd, int at_cmd_size) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+
+ sprintf(at_cmd, "%s=\r\n", MTK_AT_GEOFENCE_DEL_ALL_REQ);
+}
+
+void mtk_at_gen_geo_alert_notify(char* at_cmd, int at_cmd_size, mtk_geo_alert_notify* notify) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+ assert(notify != NULL);
+
+ sprintf(at_cmd, "%s: %d,%d,%.6f,%.6f,%.2f,%.2f,%.2f,%d,%d,%d,%d,%d,%.2f,%.2f,%.2f\r\n", MTK_AT_GEOFENCE_ALERT_NTF,
+ notify->id, notify->state, notify->lat, notify->lng, notify->alt, notify->speed, notify->heading,
+ notify->hacc, notify->h_err_maj, notify->h_err_min, notify->h_err_angle, notify->h_confidence, notify->pdop, notify->hdop, notify->vdop);
+}
+
+void mtk_at_gen_geo_track_notify(char* at_cmd, int at_cmd_size, mtk_geo_track_state state, const char* date_time) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+ assert(date_time != NULL);
+
+ sprintf(at_cmd, "%s: %d,\"%s\"\r\n", MTK_AT_GEOFENCE_TRACK_NTF, state, date_time);
+}
+
+void mtk_at_gen_test_request(char* at_cmd, int at_cmd_size, int num1, int num2, double d1, double d2, const char* str1, const char* str2) {
+ assert(at_cmd != NULL);
+ assert(at_cmd_size > 0);
+ assert(str1 != NULL);
+ assert(str2 != NULL);
+
+ sprintf(at_cmd, "%s=%d,%d,%.6f,%.6f,\"%s\",\"%s\"\r\n", MTK_AT_TEST_REQ, num1, num2, d1, d2, str1, str2);
+}
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_struct.h b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_struct.h
new file mode 100755
index 0000000..c813ac6
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mtk_gnss_at_command/mtk_gnss_at_struct.h
@@ -0,0 +1,338 @@
+#ifndef __MTK_GNSS_AT_STRUCT_H__
+#define __MTK_GNSS_AT_STRUCT_H__
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int mtk_gnss_sv_flags;
+#define MTK_GNSS_AT_SV_FLAGS_NONE 0x00
+#define MTK_GNSS_AT_SV_FLAGS_HAS_EPHEMERIS_DATA 0x01
+#define MTK_GNSS_AT_SV_FLAGS_HAS_ALMANAC_DATA 0x02
+#define MTK_GNSS_AT_SV_FLAGS_USED_IN_FIX 0x04
+
+typedef int mtk_gnss_constellation;
+#define MTK_GNSS_CONSTELLATION_UNKNOWN 0
+#define MTK_GNSS_CONSTELLATION_GPS 1
+#define MTK_GNSS_CONSTELLATION_SBAS 2
+#define MTK_GNSS_CONSTELLATION_GLONASS 3
+#define MTK_GNSS_CONSTELLATION_QZSS 4
+#define MTK_GNSS_CONSTELLATION_BEIDOU 5
+#define MTK_GNSS_CONSTELLATION_GALILEO 6
+#define MTK_GNSS_CONSTELLATION_IRNSS 7
+
+typedef int mtk_gnss_ni_type;
+#define MTK_GNSS_NI_TYPE_VOICE 1
+#define MTK_GNSS_NI_TYPE_UMTS_SUPL 2
+#define MTK_GNSS_NI_TYPE_UMTS_CTRL_PLANE 3
+#define MTK_GNSS_NI_TYPE_EMERGENCY_SUPL 4
+
+typedef int mtk_gnss_ni_notify_type;
+#define MTK_GNSS_NI_NOTIFY_TYPE_NONE 0
+#define MTK_GNSS_NI_NOTIFY_TYPE_NOTIFY_ONLY 1
+#define MTK_GNSS_NI_NOTIFY_TYPE_NOTIFY_ALLOW_NO_ANSWER 2
+#define MTK_GNSS_NI_NOTIFY_TYPE_NOTIFY_DENY_NO_ANSWER 3
+#define MTK_GNSS_NI_NOTIFY_TYPE_PRIVACY 4
+
+typedef int mtk_gnss_ni_encoding_type;
+#define MTK_GNSS_NI_ENCODING_TYPE_NONE 0
+#define MTK_GNSS_NI_ENCODING_TYPE_GSM7 1
+#define MTK_GNSS_NI_ENCODING_TYPE_UTF8 2
+#define MTK_GNSS_NI_ENCODING_TYPE_UCS2 3
+
+typedef int mtk_gnss_ni_response_type;
+#define MTK_GNSS_NI_RESPONSE_ACCEPT 1
+#define MTK_GNSS_NI_RESPONSE_DENY 2
+#define MTK_GNSS_NI_RESPONSE_NORESP 3
+
+typedef int mtk_gnss_supl_pref_method;
+#define MTK_GNSS_SUPL_PREF_METHOD_MSA 0
+#define MTK_GNSS_SUPL_PREF_METHOD_MSB 1
+#define MTK_GNSS_SUPL_PREF_METHOD_NO_PREF 2
+
+typedef int mtk_geo_alert_type;
+#define MTK_GEO_ALERT_TYPE_ENTRY (1 << 0)
+#define MTK_GEO_ALERT_TYPE_EXIT (1 << 1)
+
+typedef int mtk_geo_state;
+#define MTK_GEO_STATE_UNKNOWN 0
+#define MTK_GEO_STATE_ENTERED 1
+#define MTK_GEO_STATE_EXITED 2
+
+typedef int mtk_geo_fence_create_state;
+#define MTK_GEO_FENCE_CREATE_STATE_SUCCESS 0
+#define MTK_GEO_FENCE_CREATE_STATE_ERROR -1
+#define MTK_GEO_FENCE_CREATE_STATE_INSUFFICIENT_MEMORY -2
+#define MTK_GEO_FENCE_CREATE_STATE_TOO_MANY_FENCE -3
+
+typedef int mtk_geo_track_state;
+#define MTK_GEO_TRACK_STATE_OK 0
+#define MTK_GEO_TRACK_STATE_FAILURE -1
+
+typedef int mtk_agps_location_type;
+#define MTK_AGPS_LOCATION_TYPE_AFLT 0
+#define MTK_AGPS_LOCATION_TYPE_CDMA_CELL 1
+#define MTK_AGPS_LOCATION_TYPE_CP_MOLR 2
+#define MTK_AGPS_LOCATION_TYPE_SUPL_END 3
+#define MTK_AGPS_LOCATION_TYPE_SUPL_REF_LOC 4
+#define MTK_AGPS_LOCATION_TYPE_CP_REF_LOC 5
+
+typedef struct {
+ int svid;
+ mtk_gnss_constellation constellation;
+ float cn0;
+ float elevation;
+ float azimuth;
+ mtk_gnss_sv_flags flags; // indicate the extra info of this satellite
+ float carrier_frequency; // Carrier frequency of the signal tracked in MHz. GPS central frequency for L1 = 1575.45 MHz or L5 = 1176.45 MHz
+} mtk_gnss_satellite;
+
+typedef struct {
+ int num;
+ mtk_gnss_satellite satellites[64];
+} mtk_gnss_satellite_list; // 1796 Bytes
+
+
+typedef struct {
+ bool lat_valid;
+ double lat;
+
+ bool lng_valid;
+ double lng;
+
+ bool alt_valid;
+ float alt;
+
+ bool speed_valid;
+ float speed;
+
+ bool bearing_valid;
+ float bearing;
+
+ bool h_acc_valid;
+ float h_acc;
+
+ bool v_acc_valid;
+ float v_acc;
+
+ bool s_acc_valid;
+ float s_acc;
+
+ bool b_acc_valid;
+ float b_acc;
+
+ bool timestamp_valid;
+ long long timestamp;
+
+ bool date_time_valid; //auto assign by mtk_at_gen_gnss_location_notify()
+ char date_time[32]; //auto assign by mtk_at_gen_gnss_location_notify()
+
+ bool pdop_valid;
+ float pdop;
+
+ bool hdop_valid;
+ float hdop;
+
+ bool vdop_valid;
+ float vdop;
+} mtk_gnss_location;
+
+typedef struct {
+ double lat;
+ double lng;
+
+ bool alt_valid;
+ float alt;
+
+ bool speed_valid;
+ float speed;
+
+ bool bearing_valid;
+ float bearing;
+
+ bool h_acc_valid;
+ float h_acc;
+
+ bool timestamp_valid;
+ long long timestamp;
+
+ bool date_time_valid; //auto assign by mtk_at_gen_gnss_location_notify()
+ char date_time[32]; //auto assign by mtk_at_gen_gnss_location_notify()
+
+ bool type_valid;
+ mtk_agps_location_type type;
+} mtk_agnss_location;
+
+typedef struct {
+ bool gnss_status;
+ bool ni_status;
+ int supl_maj_ver;
+ int supl_min_ver;
+ char gnss_version[256];
+ char agps_version[128];
+ int supl_ser_ind;
+ char supl_addr[128];
+ int supl_port;
+ bool supl_tls_enabled;
+ bool imsi_valid;
+ char imsi[32];
+ bool num_digital_mnc_in_imsi_valid;
+ int num_digital_mnc_in_imsi;
+} mtk_gnss_status;
+
+typedef struct {
+ bool msa_valid;
+ bool msa;
+ bool msb_valid;
+ bool msb;
+ bool mss_valid;
+ bool mss;
+ bool cid_valid;
+ bool cid;
+ bool aflt_valid;
+ bool aflt;
+ bool otdoa_valid;
+ bool otdoa;
+ bool supl_pref_method_valid;
+ mtk_gnss_supl_pref_method supl_pref_method;
+ bool supl_valid;
+ bool supl;
+ bool epo_valid;
+ bool epo;
+} mtk_gnss_agps_mode;
+
+typedef struct {
+ bool all;
+ bool eph;
+ bool alm;
+ bool pos;
+ bool time;
+ bool iono;
+ bool utc;
+ bool svdir;
+ bool rti;
+ bool celldb;
+} mtk_gnss_aiding_data;
+
+typedef struct {
+ int id;
+ mtk_gnss_ni_type type;
+ mtk_gnss_ni_notify_type notify_type;
+ char request_id[1024];
+ mtk_gnss_ni_encoding_type request_id_encode_type;
+ char text[1024];
+ mtk_gnss_ni_encoding_type text_encode_type;
+} mtk_gnss_ni_notify;
+
+typedef struct {
+ int total_msg_len;
+ int seq_no;
+ char name[128];
+ char data[1024];
+} mtk_gnss_cert;
+
+typedef struct {
+ int num;
+ char names[10][128];
+} mtk_gnss_cert_name_list;
+
+typedef struct {
+ mtk_geo_alert_type alert_type;
+ mtk_geo_state initial_state;
+ double lat;
+ double lng;
+ double radius; //in meters
+ int unknowntimerms; //in milliseconds. Range <0~100000> milliseconds
+} mtk_geo_add_circle;
+
+typedef struct {
+ int id;
+ mtk_geo_state state;
+ double lat;
+ double lng;
+ double alt;
+ double speed;
+ double heading;
+ int hacc; //horizontal position accuracy, radial, in meters (68% confidence)
+ int h_err_maj; //in meters
+ int h_err_min; //in meters
+ int h_err_angle; //in degree
+ int h_confidence; //horizontal confidence of the position
+ float pdop;
+ float hdop;
+ float vdop;
+} mtk_geo_alert_notify;
+
+
+bool mtk_at_parse_cmd(const char** at_cmd, const char* target_cmd);
+int mtk_at_parse_comma_num(const char* at_cmd);
+bool mtk_at_parse_string(const char** at_cmd, char* output, int output_size);
+bool mtk_at_parse_bool(const char** at_cmd, bool* output);
+bool mtk_at_parse_int32(const char** at_cmd, int* output);
+bool mtk_at_parse_int64(const char** at_cmd, long long* output);
+bool mtk_at_parse_float(const char** at_cmd, float* output);
+bool mtk_at_parse_double(const char** at_cmd, double* output);
+
+void mtk_at_dump_mtk_gnss_satellite_list(mtk_gnss_satellite_list* list);
+void mtk_at_dump_mtk_gnss_location(mtk_gnss_location* location);
+void mtk_at_dump_mtk_agnss_location(mtk_agnss_location* location);
+void mtk_at_dump_mtk_gnss_status(mtk_gnss_status* status);
+void mtk_at_dump_mtk_gnss_agps_mode(mtk_gnss_agps_mode* mode);
+void mtk_at_dump_mtk_gnss_aiding_data(mtk_gnss_aiding_data* aiding_data);
+void mtk_at_dump_mtk_gnss_ni_notify(mtk_gnss_ni_notify* notify);
+void mtk_at_dump_mtk_gnss_cert(mtk_gnss_cert* cert);
+void mtk_at_dump_mtk_gnss_cert_name_list(mtk_gnss_cert_name_list* list);
+void mtk_at_dump_mtk_geo_add_circle(mtk_geo_add_circle* circle);
+void mtk_at_dump_mtk_geo_alert_notify(mtk_geo_alert_notify* alert);
+
+void mtk_at_gen_gnss_start_request(char* at_cmd, int at_cmd_size);
+void mtk_at_gen_gnss_stop_request(char* at_cmd, int at_cmd_size);
+void mtk_at_gen_gnss_nmea_notify(char* at_cmd, int at_cmd_size, const char* nmea);
+void mtk_at_gen_gnss_nmea_end_notify(char* at_cmd, int at_cmd_size);
+void mtk_at_gen_gnss_satellite_notify(char* at_cmd, int at_cmd_size, mtk_gnss_satellite_list* list);
+void mtk_at_gen_gnss_location_notify(char* at_cmd, int at_cmd_size, mtk_gnss_location* location);
+void mtk_at_gen_agnss_location_notify(char* at_cmd, int at_cmd_size, mtk_agnss_location* location);
+void mtk_at_gen_gnss_host_reset_notify(char* at_cmd, int at_cmd_size);
+void mtk_at_gen_gnss_device_reset_notify(char* at_cmd, int at_cmd_size, const char* reason);
+void mtk_at_gen_gnss_status_request(char* at_cmd, int at_cmd_size);
+void mtk_at_gen_gnss_status_response(char* at_cmd, int at_cmd_size, mtk_gnss_status* status);
+void mtk_at_gen_gnss_enable_set(char* at_cmd, int at_cmd_size, bool enabled);
+void mtk_at_gen_gnss_ni_enable_set(char* at_cmd, int at_cmd_size, bool enabled);
+void mtk_at_gen_gnss_agps_mode_set(char* at_cmd, int at_cmd_size, mtk_gnss_agps_mode* mode);
+void mtk_at_gen_gnss_supl_version_set(char* at_cmd, int at_cmd_size, int maj, int min, int ser_ind);
+void mtk_at_gen_gnss_supl_addr_set(char* at_cmd, int at_cmd_size, const char* addr, int port, bool tls_enabled);
+void mtk_at_gen_gnss_delete_aiding_data_request(char* at_cmd, int at_cmd_size, mtk_gnss_aiding_data* flags);
+void mtk_at_gen_gnss_ni_notify_request(char* at_cmd, int at_cmd_size, mtk_gnss_ni_notify* notify);
+void mtk_at_gen_gnss_ni_notify_response(char* at_cmd, int at_cmd_size, int id, mtk_gnss_ni_response_type response);
+void mtk_at_gen_gnss_ref_location_request(char* at_cmd, int at_cmd_size);
+void mtk_at_gen_gnss_ref_location_response(char* at_cmd, int at_cmd_size, int age, double lat, double lng, float acc);
+void mtk_at_gen_gnss_ref_time_request(char* at_cmd, int at_cmd_size);
+void mtk_at_gen_gnss_ref_time_response(char* at_cmd, int at_cmd_size, long long time, int uncertainty);
+void mtk_at_gen_gnss_nmea_config_set(char* at_cmd, int at_cmd_size, bool enabled);
+void mtk_at_gen_gnss_ttff_qop_set(char* at_cmd, int at_cmd_size, int mode);
+void mtk_at_gen_gnss_loopback_request(char* at_cmd, int at_cmd_size, const char* msg);
+void mtk_at_gen_gnss_loopback_response(char* at_cmd, int at_cmd_size, const char* msg);
+void mtk_at_gen_gnss_cert_set(char* at_cmd, int at_cmd_size, mtk_gnss_cert* cert);
+void mtk_at_gen_gnss_cert_name_request(char* at_cmd, int at_cmd_size);
+void mtk_at_gen_gnss_cert_name_response(char* at_cmd, int at_cmd_size, mtk_gnss_cert_name_list* list);
+void mtk_at_gen_gnss_cert_delete_request(char* at_cmd, int at_cmd_size, const char* name);
+void mtk_at_gen_gnss_cert_delete_all_request(char* at_cmd, int at_cmd_size);
+void mtk_at_gen_geo_max_num_request(char* at_cmd, int at_cmd_size);
+void mtk_at_gen_geo_max_num_response(char* at_cmd, int at_cmd_size, int num);
+void mtk_at_gen_geo_add_circle_request(char* at_cmd, int at_cmd_size, mtk_geo_add_circle* circle);
+void mtk_at_gen_geo_add_circle_response(char* at_cmd, int at_cmd_size, mtk_geo_fence_create_state state, int id);
+void mtk_at_gen_geo_delete_request(char* at_cmd, int at_cmd_size, int id);
+void mtk_at_gen_geo_delete_all_request(char* at_cmd, int at_cmd_size);
+void mtk_at_gen_geo_alert_notify(char* at_cmd, int at_cmd_size, mtk_geo_alert_notify* notify);
+void mtk_at_gen_geo_track_notify(char* at_cmd, int at_cmd_size, mtk_geo_track_state state, const char* date_time);
+void mtk_at_gen_test_request(char* at_cmd, int at_cmd_size, int num1, int num2, double d1, double d2, const char* str1, const char* str2);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mtk_tree/inc/mtk_tree.h b/src/connectivity/agps/2.0/lbs_em/src/mtk_tree/inc/mtk_tree.h
new file mode 100755
index 0000000..7d18f58
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mtk_tree/inc/mtk_tree.h
@@ -0,0 +1,48 @@
+#ifndef __MTK_TREE_H__
+#define __MTK_TREE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*traversal_handler)();
+
+typedef struct _tree_child {
+ struct _tree_child* next_child;
+ int id;
+ struct _tree_node* child;
+} tree_child;
+
+typedef struct _tree_node {
+ struct _tree_node* parent;
+ tree_child children_header;
+ traversal_handler handler;
+} tree_node;
+
+void tree_init(tree_node* root, traversal_handler handler);
+tree_node* tree_add_child(tree_node* node, int id, traversal_handler handler);
+void tree_remove_children(tree_node* node);
+int tree_children_size(tree_node* node);
+tree_node* tree_get_node(tree_node* node, int id);
+void tree_dump(tree_node* node);
+
+typedef struct _traversal_path {
+ struct _traversal_path* previous;
+ struct _traversal_path* next;
+ int path_id;
+} traversal_path;
+
+void traversal_path_init(traversal_path* header);
+void traversal_path_go(traversal_path* header, int next_path_id);
+void traversal_path_back(traversal_path* header);
+void traversal_path_cleanup(traversal_path* header);
+void traversal_path_dump(traversal_path* header);
+
+int tree_traversal(tree_node* root, traversal_path* header);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/mtk_tree/src/mtk_tree.c b/src/connectivity/agps/2.0/lbs_em/src/mtk_tree/src/mtk_tree.c
new file mode 100755
index 0000000..4f440d3
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/mtk_tree/src/mtk_tree.c
@@ -0,0 +1,150 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mtk_tree.h"
+
+void tree_init(tree_node* root, traversal_handler handler) {
+ root->parent = NULL;
+ root->children_header.id = 0;
+ root->children_header.child = NULL;
+ root->children_header.next_child = NULL;
+ root->handler = handler;
+}
+
+tree_node* tree_add_child(tree_node* node, int id, traversal_handler handler) {
+ tree_child* c = &node->children_header;
+ while(c->next_child != NULL) {
+ c = c->next_child;
+ }
+ c->next_child = (tree_child*)malloc(sizeof(tree_child));
+
+ c = c->next_child;
+ c->next_child = NULL;
+ c->id = id;
+ c->child = (tree_node*)malloc(sizeof(tree_node));
+
+ tree_node* n = c->child;
+ n->parent = node;
+ n->children_header.id = 0;
+ n->children_header.child = NULL;
+ n->children_header.next_child = NULL;
+ n->handler = handler;
+ return n;
+}
+
+void tree_remove_children(tree_node* node) {
+ tree_child* c = node->children_header.next_child;
+ while(c != NULL) {
+ tree_remove_children(c->child);
+ free(c->child);
+ tree_child* c2 = c;
+ c = c->next_child;
+ free(c2);
+ }
+ node->children_header.next_child = NULL;
+}
+
+tree_node* tree_get_node(tree_node* node, int id) {
+ tree_child* c = node->children_header.next_child;
+ while(c != NULL) {
+ if(c->id == id) {
+ return c->child;
+ }
+ c = c->next_child;
+ }
+ return NULL;
+}
+
+int tree_children_size(tree_node* node) {
+ int i = 0;
+ tree_child* c = node->children_header.next_child;
+ while(c != NULL) {
+ i++;
+ c = c->next_child;
+ }
+ return i;
+}
+
+void tree_dump(tree_node* node) {
+ int size = tree_children_size(node);
+ printf("parent=[%p] me=[%p] handler=[%p] size=[%d]\n",
+ node->parent, node, node->handler, size);
+ tree_child* c = node->children_header.next_child;
+ while(c != NULL) {
+ size = tree_children_size(c->child);
+ printf(" id=[%d] size=[%d] child_ptr=[%p] next_child=[%p]\n", c->id, size, c->child, c->next_child);
+ c = c->next_child;
+ }
+}
+
+void traversal_path_init(traversal_path* header) {
+ header->previous = NULL;
+ header->next = NULL;
+ header->path_id = 0;
+}
+
+void traversal_path_go(traversal_path* header, int next_path_id) {
+ traversal_path* p = header;
+ while(p->next != NULL) {
+ p = p->next;
+ }
+ p->next = (traversal_path*)malloc(sizeof(traversal_path));
+ p->next->previous = p;
+ p = p->next;
+ p->next = NULL;
+ p->path_id = next_path_id;
+}
+
+void traversal_path_back(traversal_path* header) {
+ if(header->next == NULL) {
+ //no element, do nothing
+ return;
+ }
+ traversal_path* p = header;
+ while(p->next != NULL) {
+ p = p->next;
+ }
+ p->previous->next = NULL;
+ free(p);
+}
+
+void traversal_path_cleanup(traversal_path* header) {
+ if(header->next == NULL) {
+ //no element, do nothing
+ return;
+ }
+ traversal_path* p = header->next;
+ while(p != NULL) {
+ traversal_path* p2 = p;
+ p = p->next;
+ free(p2);
+ }
+ header->next = NULL;
+}
+
+void traversal_path_dump(traversal_path* header) {
+ traversal_path* p = header;
+ int i = 0;
+ printf("traversal_path_dump()\n");
+ while(p->next != NULL) {
+ p = p->next;
+ i++;
+ printf(" index=[%02d] path_id=[%d]\n", i, p->path_id);
+ }
+}
+
+// -1 means traversal is going to a unknown handler
+int tree_traversal(tree_node* root, traversal_path* header) {
+ tree_node* n = root;
+ traversal_path* p = header;
+ while(p->next != NULL) {
+ p = p->next;
+ n = tree_get_node(n, p->path_id);
+ if(n == NULL) {
+ return -1;
+ }
+ }
+ n->handler();
+ return 0;
+}
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/nlp/inc/MtkNlp.h b/src/connectivity/agps/2.0/lbs_em/src/nlp/inc/MtkNlp.h
new file mode 100755
index 0000000..e7d16df
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/nlp/inc/MtkNlp.h
@@ -0,0 +1,325 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __MtkNlp_H__
+#define __MtkNlp_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NLP_SERVICE_CHANNEL "mtk_nlp_service_socket"
+
+#define MTK_NLP_PROTOCOL_TYPE 300
+#define MTK_NLP_BUFF_SIZE 65
+
+/**
+ * Definition of location source that NLP service generates the location.
+ * This parameter indicates the positioning technologies involved in calculating position.
+ */
+typedef short MtkNlpLocationSource;
+/**
+ * Assisted-GNSS.
+ */
+#define MTKNLP_LOCATION_SOURCE_AGNSS 0x01
+/**
+ * Sensors including gyroscope and accelerometer sensors.
+ */
+#define MTKNLP_LOCATION_SOURCE_SENSOR 0x02
+/**
+ * E-CID on LTE.
+ */
+#define MTKNLP_LOCATION_SOURCE_ECIDLTE 0x04
+/**
+ * E-CID on GSM.
+ */
+#define MTKNLP_LOCATION_SOURCE_ECIDGSM 0x08
+/**
+ * E-CID on UMTS.
+ */
+#define MTKNLP_LOCATION_SOURCE_ECIDUMTS 0x10
+/**
+ * WLAN AP.
+ */
+#define MTKNLP_LOCATION_SOURCE_WLANAP 0x20
+/**
+ * Short Range Node Positioning.
+ */
+#define MTKNLP_LOCATION_SOURCE_SRN 0x40
+/**
+ * E-CID on 5G NR.
+ */
+#define MTKNLP_LOCATION_SOURCE_ECIDNR 0x80
+
+
+/**
+ * This is an MtkNlp interface between NlpCleint and NlpService
+ * version 1 for init development
+ */
+typedef enum {
+ /**
+ * Request NLP location updates. NLP applications request NLP service start to return locations.
+ * param min_interval: minimum time interval between location updates, in milliseconds. NLP service
+ * would do its best to return locations according to this interval parameter.
+ */
+ MTK_NLP_START_LOCATION_UPDATES = 0,
+ /**
+ * Stop NLP location updates.
+ */
+ MTK_NLP_STOP_LOCATION_UPDATES = 1,
+ /**
+ * Get last cached location from NLP service. After this function is called, NLP application
+ * may wait for fd epoll events to parse the returned location. NLP service may not return
+ * the location, if NLP service doesn't have cached location.
+ */
+ MTK_NLP_GET_LAST_LOCATION = 2,
+ /**
+ * Request single NLP location update. After this function is called, NLP application may
+ * wait for fd epoll events to parse the returned location.
+ */
+ MTK_NLP_GET_SINGLE_UPDATE = 3,
+ /**
+ * Nlp Service send location to Nlp client
+ */
+ MTK_NLP_PROVIDE_LOCATION = 4,
+} MtkNlp_message_id;
+
+
+typedef struct {
+ /**
+ * UTC time of this fix, in milliseconds since January 1, 1970
+ */
+ int64_t time;
+
+ /**
+ * The time of this fix, in elapsed real-time nanosecond since system boot.
+ */
+ int64_t elapsed_real_time_nanos;
+
+ /**
+ * Represents latitude in degrees.
+ */
+ double latitude;
+
+ /**
+ * Represents longitude in degrees.
+ */
+ double longitude;
+
+ /**
+ * Flag to indicate altitude field is valid.
+ */
+ bool altitude_valid;
+
+ /**
+ * Represents altitude in meters above the WGS 84 reference ellipsoid.
+ */
+ double altitude;
+
+ /**
+ * Flag to indicate horizontal_accuracy field is valid.
+ */
+ bool horizontal_accuracy_valid;
+
+ /**
+ * The estimated horizontal accuracy of this location, radial, in meters.
+ * We define horizontal accuracy as the radius of 68% confidence. In other words, if you draw
+ * a circle centered at this location's latitude and longitude, and with a radius equal to the
+ * accuracy, then there is a 68% probability that the true location is inside the circle.
+ * In the case where the underlying distribution is assumed Gaussian normal, this would be
+ * considered 1 standard deviation.
+ */
+ float horizontal_accuracy;
+
+ /**
+ * Flag to indicate vertical_accuracy field is valid.
+ */
+ bool vertical_accuracy_valid;
+
+ /**
+ * The estimated vertical accuracy of this location, in meters.
+ * We define vertical accuracy at 68% confidence, within which there is a 68% probability
+ * of finding the true altitude. In the case where the underlying distribution is assumed
+ * Gaussian normal, this would be considered 1 standard deviation.
+ */
+ float vertical_accuracy;
+
+ /**
+ * Flag to indicate location_source field is valid.
+ */
+ bool location_source_valid;
+
+ /**
+ * location source bit array for MtkNlpImplLocationSource.
+ */
+ int location_source;
+
+} MtkNlp_location;
+
+typedef struct {
+ /**
+ * Flag to indicate location_source field is valid.
+ */
+ bool nlp_location_valid;
+
+ /**
+ * Decoded location data structure.
+ */
+ MtkNlp_location nlp_location;
+
+} MtkNlp_decoded_location;
+
+
+// MtkNlp_location
+void MtkNlp_location_dump(MtkNlp_location* data);
+void MtkNlp_location_array_dump(MtkNlp_location data[], int size);
+
+void MtkNlp_location_init(MtkNlp_location* output);
+void MtkNlp_location_array_init(MtkNlp_location output[], int max_size);
+
+bool MtkNlp_location_is_equal(MtkNlp_location* data1, MtkNlp_location* data2);
+bool MtkNlp_location_array_is_equal(MtkNlp_location data1[], int size1, MtkNlp_location data2[], int size2);
+
+bool MtkNlp_location_encode(char* buff, int* offset, MtkNlp_location* data);
+bool MtkNlp_location_array_encode(char* buff, int* offset, MtkNlp_location data[], int size);
+
+void MtkNlp_location_decode(char* buff, int* offset, MtkNlp_location* output);
+int MtkNlp_location_array_decode(char* buff, int* offset, MtkNlp_location output[], int max_size);
+
+// MtkNlp_decoded_location
+void MtkNlp_decoded_location_dump(MtkNlp_decoded_location* data);
+void MtkNlp_decoded_location_array_dump(MtkNlp_decoded_location data[], int size);
+
+void MtkNlp_decoded_location_init(MtkNlp_decoded_location* output);
+void MtkNlp_decoded_location_array_init(MtkNlp_decoded_location output[], int max_size);
+
+bool MtkNlp_decoded_location_is_equal(MtkNlp_decoded_location* data1, MtkNlp_decoded_location* data2);
+bool MtkNlp_decoded_location_array_is_equal(MtkNlp_decoded_location data1[], int size1, MtkNlp_decoded_location data2[], int size2);
+
+bool MtkNlp_decoded_location_encode(char* buff, int* offset, MtkNlp_decoded_location* data);
+bool MtkNlp_decoded_location_array_encode(char* buff, int* offset, MtkNlp_decoded_location data[], int size);
+
+void MtkNlp_decoded_location_decode(char* buff, int* offset, MtkNlp_decoded_location* output);
+int MtkNlp_decoded_location_array_decode(char* buff, int* offset, MtkNlp_decoded_location output[], int max_size);
+
+// Sender
+/**
+ * Request NLP location updates. NLP applications request NLP service start to return locations.
+ * If the caller application no longer need NLP updates, it should call
+ * MtkNlp_stop_location_updates() to stop the location updates to avoid power consumption.
+ * Because network positioning function will provide the third party package with WiFi scan results
+ * and Cell Info, it may disclose the user's location information to NLP vendor. The application
+ * calls this API should get user grant or in emergency call cases.
+ * param client_fd: client_fd is used to receive messages from NLP service.
+ * param min_interval: minimum time interval between location updates, in milliseconds. NLP service
+ * would do its best to return locations according to this interval parameter.
+ * return value: true indicates the message is successfully sent, false means failed to send.
+ */
+bool MtkNlp_start_location_updates(mtk_socket_fd* client_fd, int min_interval);
+
+/**
+ * Stop NLP location updates.
+ * param client_fd: client_fd is used to receive messages from NLP service.
+ * return value: true indicates the message is successfully sent, false means failed to send.
+ */
+bool MtkNlp_stop_location_updates(mtk_socket_fd* client_fd);
+
+/**
+ * Get last cached location from NLP service. After this function is called, NLP application
+ * may wait for fd epoll events to parse the returned location. NLP service may not return
+ * the location, if NLP service doesn't have cached location.
+ * param client_fd: client_fd is used to receive messages from NLP service.
+ * return value: true indicates the message is successfully sent, false means failed to send.
+ */
+bool MtkNlp_get_last_location(mtk_socket_fd* client_fd);
+
+/**
+ * Request single NLP location update. After this function is called, NLP application may
+ * wait for fd epoll events to parse the returned location. NLP request session will be finished
+ * after a location is reported. If NLP service failed to report location, the caller application
+ * should call MtkNlp_stop_location_updates() to stop the request to avoid power consumption.
+ * Because network positioning function will provide the third party package with WiFi scan results
+ * and Cell Info, it may disclose the user's location information to NLP vendor. The application
+ * calls this API should get user grant or in emergency call cases.
+ * param client_fd: client_fd is used to receive messages from NLP service.
+ * return value: true indicates the message is successfully sent, false means failed to send.
+ */
+bool MtkNlp_get_single_update(mtk_socket_fd* client_fd);
+
+/**
+ * NlP Service send location to NlP client
+ * param client_fd: client_fd is used to receive messages from NLP service.
+ * param dec_loc: NLP Service reported location data structure.
+ * return value: true indicates the message is successfully sent, false means failed to send.
+ */
+bool MtkNlp_provide_location(mtk_socket_fd* client_fd, MtkNlp_decoded_location* dec_loc);
+
+// Receiver
+typedef struct {
+ /**
+ * Request NLP location updates. NLP applications request NLP service start to return locations.
+ * param min_interval: minimum time interval between location updates, in milliseconds. NLP service
+ * would do its best to return locations according to this interval parameter.
+ */
+ void (*MtkNlp_start_location_updates_handler) (int fd, int min_interval);
+ /**
+ * Stop NLP location updates.
+ */
+ void (*MtkNlp_stop_location_updates_handler) (int fd);
+ /**
+ * Get last cached location from NLP service. After this function is called, NLP application
+ * may wait for fd epoll events to parse the returned location. NLP service may not return
+ * the location, if NLP service doesn't have cached location.
+ */
+ void (*MtkNlp_get_last_location_handler) (int fd);
+ /**
+ * Request single NLP location update. After this function is called, NLP application may
+ * wait for fd epoll events to parse the returned location.
+ */
+ void (*MtkNlp_get_single_update_handler) (int fd);
+ /**
+ * Nlp Service send location to Nlp client
+ */
+ void (*MtkNlp_provide_location_handler) (MtkNlp_decoded_location* dec_loc);
+} MtkNlp_callbacks;
+
+bool MtkNlp_receiver_decode(int fd, char* _buff,
+ MtkNlp_decoded_location *decLoc, MtkNlp_callbacks* callbacks);
+
+
+//////////////////////////// Client Interface /////////////////////////////////
+
+/**
+ * Create a fd and connect to NLP service. NLP applications may add this fd to epoll events.
+ * Once an event is triggered on this fd, NLP applications can call mtknlp_read_and_decode()
+ * to get locations.
+ * return fd if successfully connect to NLP service, -1 means fail.
+ */
+int MtkNlp_get_fd();
+
+/**
+ * Release fd. When a NLP application doesn't need any NLP location from NLP service,
+ * fd can be released by this API.
+ */
+void MtkNlp_release_fd(int fd);
+
+
+/**
+ * When NLP application detects epoll event on fd, NLP application should call this function.
+ * This is a helper function to read the raw data and decode the raw data as MtkNlp_decoded_location.
+ * param fd: fd is used to receive messages from NLP service.
+ * param buff: received data from NLP service.
+ * return value: a decoded location data structure is returned. NLP application should check the
+ * nlp_location_valid flag in MtkNlpDecodedLocation. If the flag is false it indicates the
+ * message is parsing fail, and no nlp location is correctly parsed from NLP service.
+ */
+MtkNlp_decoded_location MtkNlp_receiver_decode_location(int fd, char* buff);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/nlp/src/MtkNlp.c b/src/connectivity/agps/2.0/lbs_em/src/nlp/src/MtkNlp.c
new file mode 100755
index 0000000..6302fde
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/nlp/src/MtkNlp.c
@@ -0,0 +1,477 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "MtkNlp.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_socket_data_coder.h"
+
+// MtkNlp_location
+void MtkNlp_location_dump(MtkNlp_location* data) {
+ SOCK_LOGD("MtkNlp_location_dump()");
+ SOCK_LOGD(" time=[%lld]", data->time);
+ SOCK_LOGD(" elapsed_real_time_nanos=[%lld]", data->elapsed_real_time_nanos);
+ SOCK_LOGD(" latitude=[%f]", data->latitude);
+ SOCK_LOGD(" longitude=[%f]", data->longitude);
+ SOCK_LOGD(" altitude_valid=[%d]", data->altitude_valid);
+ SOCK_LOGD(" altitude=[%f]", data->altitude);
+ SOCK_LOGD(" horizontal_accuracy_valid=[%d]", data->horizontal_accuracy_valid);
+ SOCK_LOGD(" horizontal_accuracy=[%f]", data->horizontal_accuracy);
+ SOCK_LOGD(" vertical_accuracy_valid=[%d]", data->vertical_accuracy_valid);
+ SOCK_LOGD(" vertical_accuracy=[%f]", data->vertical_accuracy);
+ SOCK_LOGD(" location_source_valid=[%d]", data->location_source_valid);
+ SOCK_LOGD(" location_source=[%d]", data->location_source);
+}
+void MtkNlp_location_array_dump(MtkNlp_location data[], int size) {
+ int i = 0;
+ SOCK_LOGD("MtkNlp_location_array_dump() size=[%d]", size);
+ for(i = 0; i < size; i++) {
+ MtkNlp_location_dump(&data[i]);
+ }
+}
+
+void MtkNlp_location_init(MtkNlp_location* output) {
+ output->time = 0;
+ output->elapsed_real_time_nanos = 0;
+ output->latitude = 0;
+ output->longitude = 0;
+ output->altitude_valid = 0;
+ output->altitude = 0;
+ output->horizontal_accuracy_valid = 0;
+ output->horizontal_accuracy = 0;
+ output->vertical_accuracy_valid = 0;
+ output->vertical_accuracy = 0;
+ output->location_source_valid = 0;
+ output->location_source = 0;
+}
+void MtkNlp_location_array_init(MtkNlp_location output[], int max_size) {
+ int i = 0;
+ for(i = 0; i < max_size; i++) {
+ MtkNlp_location_init(&output[i]);
+ }
+}
+
+bool MtkNlp_location_is_equal(MtkNlp_location* data1, MtkNlp_location* data2) {
+ if(data1->time != data2->time) return false;
+ if(data1->elapsed_real_time_nanos != data2->elapsed_real_time_nanos) return false;
+ if(data1->latitude != data2->latitude) return false;
+ if(data1->longitude != data2->longitude) return false;
+ if(data1->altitude_valid != data2->altitude_valid) return false;
+ if(data1->altitude != data2->altitude) return false;
+ if(data1->horizontal_accuracy_valid != data2->horizontal_accuracy_valid) return false;
+ if(data1->horizontal_accuracy != data2->horizontal_accuracy) return false;
+ if(data1->vertical_accuracy_valid != data2->vertical_accuracy_valid) return false;
+ if(data1->vertical_accuracy != data2->vertical_accuracy) return false;
+ if(data1->location_source_valid != data2->location_source_valid) return false;
+ if(data1->location_source != data2->location_source) return false;
+ return true;
+}
+bool MtkNlp_location_array_is_equal(MtkNlp_location data1[], int size1, MtkNlp_location data2[], int size2) {
+ int i = 0;
+ if(size1 != size2) return false;
+ for(i = 0; i < size1; i++) {
+ if(!MtkNlp_location_is_equal(&data1[i], &data2[i])) return false;
+ }
+ return true;
+}
+
+bool MtkNlp_location_encode(char* buff, int* offset, MtkNlp_location* data) {
+ mtk_socket_put_int64_t(buff, offset, data->time);
+ mtk_socket_put_int64_t(buff, offset, data->elapsed_real_time_nanos);
+ mtk_socket_put_double(buff, offset, data->latitude);
+ mtk_socket_put_double(buff, offset, data->longitude);
+ mtk_socket_put_bool(buff, offset, data->altitude_valid);
+ mtk_socket_put_double(buff, offset, data->altitude);
+ mtk_socket_put_bool(buff, offset, data->horizontal_accuracy_valid);
+ mtk_socket_put_float(buff, offset, data->horizontal_accuracy);
+ mtk_socket_put_bool(buff, offset, data->vertical_accuracy_valid);
+ mtk_socket_put_float(buff, offset, data->vertical_accuracy);
+ mtk_socket_put_bool(buff, offset, data->location_source_valid);
+ mtk_socket_put_int(buff, offset, data->location_source);
+ return true;
+}
+bool MtkNlp_location_array_encode(char* buff, int* offset, MtkNlp_location data[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ if(!MtkNlp_location_encode(buff, offset, &data[i])) {
+ SOCK_LOGE("MtkNlp_location_array_encode() MtkNlp_location_encode() failed at i=%d", i);
+ return false;
+ }
+ }
+ return true;
+}
+
+void MtkNlp_location_decode(char* buff, int* offset, MtkNlp_location* output) {
+ output->time = mtk_socket_get_int64_t(buff, offset);
+ output->elapsed_real_time_nanos = mtk_socket_get_int64_t(buff, offset);
+ output->latitude = mtk_socket_get_double(buff, offset);
+ output->longitude = mtk_socket_get_double(buff, offset);
+ output->altitude_valid = mtk_socket_get_bool(buff, offset);
+ output->altitude = mtk_socket_get_double(buff, offset);
+ output->horizontal_accuracy_valid = mtk_socket_get_bool(buff, offset);
+ output->horizontal_accuracy = mtk_socket_get_float(buff, offset);
+ output->vertical_accuracy_valid = mtk_socket_get_bool(buff, offset);
+ output->vertical_accuracy = mtk_socket_get_float(buff, offset);
+ output->location_source_valid = mtk_socket_get_bool(buff, offset);
+ output->location_source = mtk_socket_get_int(buff, offset);
+}
+int MtkNlp_location_array_decode(char* buff, int* offset, MtkNlp_location output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ if(i < max_size) {
+ MtkNlp_location_decode(buff, offset, &output[i]);
+ } else {
+ MtkNlp_location data;
+ MtkNlp_location_decode(buff, offset, &data);
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+// MtkNlp_decoded_location
+void MtkNlp_decoded_location_dump(MtkNlp_decoded_location* data) {
+ SOCK_LOGD("MtkNlp_decoded_location_dump()");
+ SOCK_LOGD(" nlp_location_valid=[%d]", data->nlp_location_valid);
+ MtkNlp_location_dump(&data->nlp_location);
+}
+void MtkNlp_decoded_location_array_dump(MtkNlp_decoded_location data[], int size) {
+ int i = 0;
+ SOCK_LOGD("MtkNlp_decoded_location_array_dump() size=[%d]", size);
+ for(i = 0; i < size; i++) {
+ MtkNlp_decoded_location_dump(&data[i]);
+ }
+}
+
+void MtkNlp_decoded_location_init(MtkNlp_decoded_location* output) {
+ output->nlp_location_valid = 0;
+ MtkNlp_location_init(&output->nlp_location);
+}
+void MtkNlp_decoded_location_array_init(MtkNlp_decoded_location output[], int max_size) {
+ int i = 0;
+ for(i = 0; i < max_size; i++) {
+ MtkNlp_decoded_location_init(&output[i]);
+ }
+}
+
+bool MtkNlp_decoded_location_is_equal(MtkNlp_decoded_location* data1, MtkNlp_decoded_location* data2) {
+ if(data1->nlp_location_valid != data2->nlp_location_valid) return false;
+ if(!MtkNlp_location_is_equal(&data1->nlp_location, &data2->nlp_location)) return false;
+ return true;
+}
+bool MtkNlp_decoded_location_array_is_equal(MtkNlp_decoded_location data1[], int size1, MtkNlp_decoded_location data2[], int size2) {
+ int i = 0;
+ if(size1 != size2) return false;
+ for(i = 0; i < size1; i++) {
+ if(!MtkNlp_decoded_location_is_equal(&data1[i], &data2[i])) return false;
+ }
+ return true;
+}
+
+bool MtkNlp_decoded_location_encode(char* buff, int* offset, MtkNlp_decoded_location* data) {
+ mtk_socket_put_bool(buff, offset, data->nlp_location_valid);
+ if(!MtkNlp_location_encode(buff, offset, &data->nlp_location)) {
+ SOCK_LOGE("MtkNlp_decoded_location_encode() MtkNlp_location_encode() failed");
+ return false;
+ }
+ return true;
+}
+bool MtkNlp_decoded_location_array_encode(char* buff, int* offset, MtkNlp_decoded_location data[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ if(!MtkNlp_decoded_location_encode(buff, offset, &data[i])) {
+ SOCK_LOGE("MtkNlp_decoded_location_array_encode() MtkNlp_decoded_location_encode() failed at i=%d", i);
+ return false;
+ }
+ }
+ return true;
+}
+
+void MtkNlp_decoded_location_decode(char* buff, int* offset, MtkNlp_decoded_location* output) {
+ output->nlp_location_valid = mtk_socket_get_bool(buff, offset);
+ MtkNlp_location_decode(buff, offset, &output->nlp_location);
+}
+int MtkNlp_decoded_location_array_decode(char* buff, int* offset, MtkNlp_decoded_location output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ if(i < max_size) {
+ MtkNlp_decoded_location_decode(buff, offset, &output[i]);
+ } else {
+ MtkNlp_decoded_location data;
+ MtkNlp_decoded_location_decode(buff, offset, &data);
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+// Sender
+/**
+ * Request NLP location updates. NLP applications request NLP service start to return locations.
+ * If the caller application no longer need NLP updates, it should call
+ * MtkNlp_stop_location_updates() to stop the location updates to avoid power consumption.
+ * Because network positioning function will provide the third party package with WiFi scan results
+ * and Cell Info, it may disclose the user's location information to NLP vendor. The application
+ * calls this API should get user grant or in emergency call cases.
+ * param client_fd: client_fd is used to receive messages from NLP service.
+ * param min_interval: minimum time interval between location updates, in milliseconds. NLP service
+ * would do its best to return locations according to this interval parameter.
+ */
+bool MtkNlp_start_location_updates(mtk_socket_fd* client_fd, int min_interval) {
+ LOGD("mtknlp_start_location_updates, fd:%d", client_fd->fd);
+ pthread_mutex_lock(&client_fd->mutex);
+ /*if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("MtkNlp_start_location_request() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }*/
+ int _ret;
+ char _buff[MTK_NLP_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, MTK_NLP_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, MTK_NLP_START_LOCATION_UPDATES);
+ mtk_socket_put_int(_buff, &_offset, min_interval);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("MtkNlp_start_location_request() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ //mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+/**
+ * Stop NLP location updates.
+ * param client_fd: client_fd is used to receive messages from NLP service.
+ * return value: true indicates the message is successfully sent, false means failed to send.
+ */
+bool MtkNlp_stop_location_updates(mtk_socket_fd* client_fd) {
+ LOGD("mtknlp_stop_location_updates, fd:%d", client_fd->fd);
+ pthread_mutex_lock(&client_fd->mutex);
+ /*if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("MtkNlp_stop_location_request() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }*/
+ int _ret;
+ char _buff[MTK_NLP_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, MTK_NLP_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, MTK_NLP_STOP_LOCATION_UPDATES);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("MtkNlp_stop_location_request() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ //mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+/**
+ * Get last cached location from NLP service. After this function is called, NLP application
+ * may wait for fd epoll events to parse the returned location. NLP service may not return
+ * the location, if NLP service doesn't have cached location.
+ * param client_fd: client_fd is used to receive messages from NLP service.
+ * return value: true indicates the message is successfully sent, false means failed to send.
+ */
+bool MtkNlp_get_last_location(mtk_socket_fd* client_fd) {
+ LOGD("mtknlp_stop_location_updates, fd:%d", client_fd->fd);
+ pthread_mutex_lock(&client_fd->mutex);
+ /*if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("MtkNlp_get_last_location() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }*/
+ int _ret;
+ char _buff[MTK_NLP_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, MTK_NLP_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, MTK_NLP_GET_LAST_LOCATION);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("MtkNlp_get_last_location() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ //mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+/**
+ * Request single NLP location update. After this function is called, NLP application may
+ * wait for fd epoll events to parse the returned location. NLP request session will be finished
+ * after a location is reported. If NLP service failed to report location, the caller application
+ * should call MtkNlp_stop_location_updates() to stop the request to avoid power consumption.
+ * Because network positioning function will provide the third party package with WiFi scan results
+ * and Cell Info, it may disclose the user's location information to NLP vendor. The application
+ * calls this API should get user grant or in emergency call cases.
+ * param client_fd: client_fd is used to receive messages from NLP service.
+ * return value: true indicates the message is successfully sent, false means failed to send.
+ */
+bool MtkNlp_get_single_update(mtk_socket_fd* client_fd) {
+ LOGD("mtknlp_stop_location_updates, fd:%d", client_fd->fd);
+ pthread_mutex_lock(&client_fd->mutex);
+ /*if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("MtkNlp_get_single_update() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }*/
+ int _ret;
+ char _buff[MTK_NLP_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, MTK_NLP_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, MTK_NLP_GET_SINGLE_UPDATE);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("MtkNlp_get_single_update() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ //mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+/**
+ * NlP Service send location to NlP client
+ * param client_fd: client_fd is used to receive messages from NLP service.
+ * param dec_loc: NLP Service reported location data structure.
+ * return value: true indicates the message is successfully sent, false means failed to send.
+ */
+bool MtkNlp_provide_location(mtk_socket_fd* client_fd, MtkNlp_decoded_location* dec_loc) {
+ pthread_mutex_lock(&client_fd->mutex);
+ /*if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("MtkNlp_provide_location() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }*/
+ int _ret;
+ char _buff[MTK_NLP_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, MTK_NLP_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, MTK_NLP_PROVIDE_LOCATION);
+ if(!MtkNlp_decoded_location_encode(_buff, &_offset, dec_loc)) {
+ SOCK_LOGE("MtkNlp_provide_location() MtkNlp_decoded_location_encode() fail on dec_loc");
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("MtkNlp_provide_location() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ //mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+// Receiver
+bool MtkNlp_receiver_decode(int fd, char* _buff,
+ MtkNlp_decoded_location *dec_loc, MtkNlp_callbacks* callbacks) {
+ int _ret = 0;
+ int _offset = 0;
+ _ret = mtk_socket_get_int(_buff, &_offset);
+ if(_ret != MTK_NLP_PROTOCOL_TYPE) {
+ SOCK_LOGE("MtkNlp_receiver_decode() protocol_type=[%d] is not equals to [%d]",
+ _ret, MTK_NLP_PROTOCOL_TYPE);
+ return false;
+ }
+ _ret = mtk_socket_get_int(_buff, &_offset);
+ switch(_ret) {
+ case MTK_NLP_START_LOCATION_UPDATES: {
+ if(callbacks->MtkNlp_start_location_updates_handler == NULL) {
+ SOCK_LOGE("MtkNlp_receiver_decode() MtkNlp_start_location_request_handler() is NULL");
+ return false;
+ }
+ int min_interval = mtk_socket_get_int(_buff, &_offset);
+ callbacks->MtkNlp_start_location_updates_handler(fd, min_interval);
+ break;
+ }
+ case MTK_NLP_STOP_LOCATION_UPDATES: {
+ if(callbacks->MtkNlp_stop_location_updates_handler == NULL) {
+ SOCK_LOGE("MtkNlp_receiver_decode() MtkNlp_stop_location_request_handler() is NULL");
+ return false;
+ }
+ callbacks->MtkNlp_stop_location_updates_handler(fd);
+ break;
+ }
+ case MTK_NLP_GET_LAST_LOCATION: {
+ if(callbacks->MtkNlp_get_last_location_handler == NULL) {
+ SOCK_LOGE("MtkNlp_receiver_decode() MtkNlp_get_last_location_handler() is NULL");
+ return false;
+ }
+ callbacks->MtkNlp_get_last_location_handler(fd);
+ break;
+ }
+ case MTK_NLP_GET_SINGLE_UPDATE: {
+ if(callbacks->MtkNlp_get_single_update_handler == NULL) {
+ SOCK_LOGE("MtkNlp_receiver_decode() MtkNlp_get_single_update_handler() is NULL");
+ return false;
+ }
+ callbacks->MtkNlp_get_single_update_handler(fd);
+ break;
+ }
+ case MTK_NLP_PROVIDE_LOCATION: {
+ /*if(callbacks->MtkNlp_provide_location_handler == NULL) {
+ SOCK_LOGE("MtkNlp_receiver_decode() MtkNlp_provide_location_handler() is NULL");
+ return false;
+ }*/
+ //MtkNlp_decoded_location dec_loc;
+ MtkNlp_decoded_location_decode(_buff, &_offset, dec_loc);
+ //callbacks->MtkNlp_provide_location_handler(dec_loc);
+ break;
+ }
+ default: {
+ SOCK_LOGE("MtkNlp_receiver_decode() unknown msgId=[%d]", _ret);
+ return false;
+ }
+ }
+ return true;
+}
+
+
+
+int MtkNlp_get_fd() {
+
+ int fd = socket_tcp_client_connect_local(true, NLP_SERVICE_CHANNEL);
+ if(fd < 0) {
+ LOGE("mtk_socket_tcp_connect_local() failed");
+ return -1;
+ }
+ return fd;
+}
+
+void MtkNlp_release_fd(int fd) {
+ close(fd);
+}
+
+
+MtkNlp_decoded_location MtkNlp_receiver_decode_location(int fd, char* buff) {
+ MtkNlp_decoded_location decLoc;
+
+ decLoc.nlp_location_valid = false;
+ MtkNlp_receiver_decode(fd, buff, (MtkNlp_decoded_location*)&decLoc, NULL);
+ return decLoc;
+}
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/utility/inc/mtk_lbs_utility.h b/src/connectivity/agps/2.0/lbs_em/src/utility/inc/mtk_lbs_utility.h
new file mode 100755
index 0000000..629874a
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/utility/inc/mtk_lbs_utility.h
@@ -0,0 +1,138 @@
+#ifndef __MTK_LBS_UTILITY_H__
+#define __MTK_LBS_UTILITY_H__
+
+#include <time.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************
+* Basic Utilities
+**************************************************/
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+void tag_log(int type, const char* tag, const char *fmt, ...);
+
+#ifdef LOGD
+#undef LOGD
+#endif
+#ifdef LOGW
+#undef LOGW
+#endif
+#ifdef LOGE
+#undef LOGE
+#endif
+//#define LOGD(...) tag_log(0, "DBG: ", __VA_ARGS__);
+//#define LOGW(...) tag_log(0, "WRN: ", __VA_ARGS__);
+//#define LOGE(...) tag_log(1, "ERR: ", __VA_ARGS__);
+
+#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 LBS_STRNCPY(dst,src,size) do{\
+ strncpy((char *)(dst), (src), (size - 1));\
+ (dst)[size - 1] = '\0';\
+ }while(0)
+
+void msleep2(int interval);
+
+// in millisecond
+time_t get_tick();
+
+// in millisecond
+time_t get_time_in_millisecond();
+
+/******************************************************************************
+* Timer
+******************************************************************************/
+typedef void (*timer_routine) (int id);
+//-1 means fail or timerid is returned
+
+//NULL means fail or timerid is returned
+timer_t timer_init(timer_routine cb, int id);
+bool timer_deinit(timer_t timerid);
+
+bool timer_start(timer_t timerid, int milliseconds);
+bool timer_stop(timer_t timerid);
+
+//-1 means fail or the remaining time is returned
+int64_t timer_get_remaining_time(timer_t timerid);
+
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int epoll_add_fd3(int epfd, int fd);
+
+// -1 failed
+int epoll_add_fd2(int epfd, int fd, uint32_t events);
+
+// -1 failed
+bool epoll_add_fd(int epfd, int fd, int events);
+
+// -1 failed
+int epoll_del_fd(int epfd, int fd);
+
+int epoll_mod_fd(int epfd, int fd, uint32_t events);
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int socket_bind_udp(const char* path);
+
+// -1 means failure
+int socket_set_blocking2(int fd, int blocking);
+
+// -1 means failure
+int safe_sendto(const char* path, const char* buff, int len);
+
+// -1 means failure
+int safe_recvfrom(int fd, char* buff, int len);
+
+//-1 means fail or clientfd is returned
+int socket_tcp_client_connect_local(bool abstract, const char* name);
+
+//-1 means fail or serverfd is returned
+int socket_udp_server_bind_local(bool abstract, const char* name);
+
+//-1 means fail or clientfd is returned
+int socket_udp_client_create_local(bool abstract, const char* name);
+
+void dump_buff(const char* data, int len);
+
+
+/******************************************************************************
+* Utils
+******************************************************************************/
+#define assert(expr) {\
+ if(!(expr)) {\
+ LOGE("assert(%s) failed, %s %s() line=%d", #expr, __FILE__, __FUNCTION__, __LINE__);\
+ exit(1);\
+ }\
+\
+}
+
+#define crash_with_log() {\
+ LOGE("crash_with_log() %s %s() line=%d", __FILE__, __FUNCTION__, __LINE__);\
+ exit(1);\
+}
+
+#define crash_with_log_0(file, function, line) {\
+ LOGE("crash_with_log() %s %s() line=%d", file, function, line);\
+ exit(1);\
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/agps/2.0/lbs_em/src/utility/inc/mtk_socket_data_coder.h b/src/connectivity/agps/2.0/lbs_em/src/utility/inc/mtk_socket_data_coder.h
new file mode 100755
index 0000000..2420afc
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/utility/inc/mtk_socket_data_coder.h
@@ -0,0 +1,51 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __MTK_SOCKET_DATA_CODER_H__
+#define __MTK_SOCKET_DATA_CODER_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool mtk_socket_get_bool(char* buff, int* offset);
+char mtk_socket_get_char(char* buff, int* offset);
+short mtk_socket_get_short(char* buff, int* offset);
+int mtk_socket_get_int(char* buff, int* offset);
+int64_t mtk_socket_get_int64_t(char* buff, int* offset);
+float mtk_socket_get_float(char* buff, int* offset);
+double mtk_socket_get_double(char* buff, int* offset);
+int mtk_socket_get_string(char* buff, int* offset, char* output, int max_size);
+int mtk_socket_get_bool_array(char* buff, int* offset, bool output[], int max_size);
+int mtk_socket_get_char_array(char* buff, int* offset, char output[], int max_size);
+int mtk_socket_get_short_array(char* buff, int* offset, short output[], int max_size);
+int mtk_socket_get_int_array(char* buff, int* offset, int output[], int max_size);
+int mtk_socket_get_int64_t_array(char* buff, int* offset, int64_t output[], int max_size);
+int mtk_socket_get_float_array(char* buff, int* offset, float output[], int max_size);
+int mtk_socket_get_double_array(char* buff, int* offset, double output[], int max_size);
+int mtk_socket_get_string_array(char* buff, int* offset, strings output, int max_size1, int max_size2);
+
+void mtk_socket_put_bool(char* buff, int* offset, bool input);
+void mtk_socket_put_char(char* buff, int* offset, char input);
+void mtk_socket_put_short(char* buff, int* offset, short input);
+void mtk_socket_put_int(char* buff, int* offset, int input);
+void mtk_socket_put_int64_t(char* buff, int* offset, int64_t input);
+void mtk_socket_put_float(char* buff, int* offset, float input);
+void mtk_socket_put_double(char* buff, int* offset, double input);
+void mtk_socket_put_string(char* buff, int* offset, const char* input);
+void mtk_socket_put_bool_array(char* buff, int* offset, bool input[], int size);
+void mtk_socket_put_char_array(char* buff, int* offset, char input[], int size);
+void mtk_socket_put_short_array(char* buff, int* offset, short input[], int size);
+void mtk_socket_put_int_array(char* buff, int* offset, int input[], int size);
+void mtk_socket_put_int64_t_array(char* buff, int* offset, int64_t input[], int size);
+void mtk_socket_put_float_array(char* buff, int* offset, float input[], int size);
+void mtk_socket_put_double_array(char* buff, int* offset, double input[], int size);
+void mtk_socket_put_string_array(char* buff, int* offset, strings input, int size1, int size2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/utility/inc/mtk_socket_utils.h b/src/connectivity/agps/2.0/lbs_em/src/utility/inc/mtk_socket_utils.h
new file mode 100755
index 0000000..7c08287
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/utility/inc/mtk_socket_utils.h
@@ -0,0 +1,252 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __MTK_SOCKET_UTILS_H__
+#define __MTK_SOCKET_UTILS_H__
+
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define strings void*
+
+typedef enum {
+ SOCK_NS_ABSTRACT = 0,
+ SOCK_NS_FILESYSTEM = 1,
+} mtk_socket_namespace;
+
+typedef struct {
+ int fd;
+ bool is_local;
+ pthread_mutex_t mutex;
+
+ // Network
+ char* host;
+ int port;
+
+ // Local
+ char* path;
+ mtk_socket_namespace namesapce;
+} mtk_socket_fd;
+
+void _mtk_socket_log(int type, const char *fmt, ...);
+
+#define SOCK_LOGD(...) _mtk_socket_log(0, __VA_ARGS__);
+#define SOCK_LOGE(...) _mtk_socket_log(1, __VA_ARGS__);
+
+//-1 means failure
+int mtk_socket_server_bind_network(int port);
+//-1 means failure
+int mtk_socket_server_bind_network_ipv6(int port);
+//-1 means failure
+int mtk_socket_server_bind_local(const char* path, mtk_socket_namespace sock_namespace);
+//-1 means fail or serverfd is returned
+int socket_tcp_server_bind_local(bool abstract, const char* name);
+//-1 means fail or new clientfd is returned
+int socket_tcp_server_new_connect(int serverfd);
+
+void mtk_socket_client_init_network(mtk_socket_fd* sock_fd, const char* host, int port);
+void mtk_socket_client_init_local(mtk_socket_fd* sock_fd, const char* path, mtk_socket_namespace sock_namespace);
+
+void mtk_socket_client_cleanup(mtk_socket_fd* sock_fd);
+
+bool mtk_socket_client_connect(mtk_socket_fd* sock_fd);
+void mtk_socket_client_close(mtk_socket_fd* sock_fd);
+
+//-1 means failure
+int mtk_socket_read(int fd, char* buff, int len);
+
+//-1 means failure
+int mtk_socket_write(int fd, void* buff, int len);
+
+// <= 0 means no data received
+int mtk_socket_poll(int fd, int timeout);
+
+
+void mtk_socket_buff_dump(const char* buff, int len);
+
+bool mtk_socket_string_is_equal(char* data1, char* data2);
+bool mtk_socket_string_array_is_equal(strings data1, int data1_size, strings data2, int data2_size, int string_size);
+void mtk_socket_string_array_dump(strings input, int size1, int size2);
+
+bool mtk_socket_bool_array_is_equal(bool data1[], int data1_size, bool data2[], int data2_size);
+void mtk_socket_bool_array_dump(bool input[], int size);
+
+bool mtk_socket_char_array_is_equal(char data1[], int data1_size, char data2[], int data2_size);
+void mtk_socket_char_array_dump(char input[], int size);
+
+bool mtk_socket_short_array_is_equal(short data1[], int data1_size, short data2[], int data2_size);
+void mtk_socket_short_array_dump(short input[], int size);
+
+bool mtk_socket_int_array_is_equal(int data1[], int data1_size, int data2[], int data2_size);
+void mtk_socket_int_array_dump(int input[], int size);
+
+bool mtk_socket_int64_t_array_is_equal(int64_t data1[], int data1_size, int64_t data2[], int data2_size);
+void mtk_socket_int64_t_array_dump(int64_t input[], int size);
+
+bool mtk_socket_float_array_is_equal(float data1[], int data1_size, float data2[], int data2_size);
+void mtk_socket_float_array_dump(float input[], int size);
+
+bool mtk_socket_double_array_is_equal(double data1[], int data1_size, double data2[], int data2_size);
+void mtk_socket_double_array_dump(double input[], int size);
+
+bool mtk_socket_expected_bool(char* buff, int* offset, bool expected_value, const char* func, int line);
+bool mtk_socket_expected_char(char* buff, int* offset, char expected_value, const char* func, int line);
+bool mtk_socket_expected_short(char* buff, int* offset, short expected_value, const char* func, int line);
+bool mtk_socket_expected_int(char* buff, int* offset, int expected_value, const char* func, int line);
+bool mtk_socket_expected_int64_t(char* buff, int* offset, int64_t expected_value, const char* func, int line);
+bool mtk_socket_expected_float(char* buff, int* offset, float expected_value, const char* func, int line);
+bool mtk_socket_expected_double(char* buff, int* offset, double expected_value, const char* func, int line);
+bool mtk_socket_expected_string(char* buff, int* offset, const char* expected_value, int max_size, const char* func, int line);
+
+#define ASSERT_EQUAL_INT(d1, d2) \
+{\
+ int _d1 = d1;\
+ int _d2 = d2;\
+ if(_d1 != _d2) {\
+ SOCK_LOGE("%s():%d ASSERT_EQUAL_INT() failed, d1=[%d], d2=[%d]",\
+ __func__, __LINE__, _d1, _d2);\
+ return false;\
+ }\
+}
+
+#define EXPECTED_BOOL(buff, offset, expected_value) \
+{\
+ if(!mtk_socket_expected_bool(buff, offset, expected_value, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_CHAR(buff, offset, expected_value) \
+{\
+ if(!mtk_socket_expected_char(buff, offset, expected_value, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_SHORT(buff, offset, expected_value) \
+{\
+ if(!mtk_socket_expected_short(buff, offset, expected_value, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_INT(buff, offset, expected_value) \
+{\
+ if(!mtk_socket_expected_int(buff, offset, expected_value, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_INT64_T(buff, offset, expected_value) \
+{\
+ if(!mtk_socket_expected_int64_t(buff, offset, expected_value, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_FLOAT(buff, offset, expected_value) \
+{\
+ if(!mtk_socket_expected_float(buff, offset, expected_value, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_DOUBLE(buff, offset, expected_value) \
+{\
+ if(!mtk_socket_expected_double(buff, offset, expected_value, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_STRING(buff, offset, expected_value, max_size) \
+{\
+ if(!mtk_socket_expected_string(buff, offset, expected_value, max_size, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_STRUCT(buff, offset, expected_value, struct_name) \
+{\
+ struct_name _tmp;\
+ struct_name##_decode(buff, offset, &_tmp);\
+ if(!struct_name##_is_equal(&_tmp, expected_value)) {\
+ SOCK_LOGE("%s():%d EXPECTED_STRUCT() %s_is_equal() fail", __func__, __LINE__, #struct_name);\
+ SOCK_LOGE(" ============= read ===============");\
+ struct_name##_dump(&_tmp);\
+ SOCK_LOGE(" ============= expected ===============");\
+ struct_name##_dump(expected_value);\
+ return false;\
+ }\
+}
+
+#define EXPECTED_ARRAY(buff, offset, expected_num, expected_value, type, max_size) \
+{\
+ type _tmp[max_size] = {0};\
+ int _tmp_num = mtk_socket_get_##type##_array(buff, offset, _tmp, max_size);\
+ if(!mtk_socket_##type##_array_is_equal(expected_value, expected_num, _tmp, _tmp_num)) {\
+ SOCK_LOGE("%s():%d expected_%s_array() fail", __func__, __LINE__, #type);\
+ SOCK_LOGE(" ============= read ===============");\
+ mtk_socket_##type##_array_dump(_tmp, _tmp_num);\
+ SOCK_LOGE(" ============= expected ===============");\
+ mtk_socket_##type##_array_dump(expected_value, expected_num);\
+ return false;\
+ }\
+}
+
+#define EXPECTED_STRING_ARRAY(buff, offset, expected_num, expected_value, max_size1, max_size2) \
+{\
+ char _tmp[max_size1][max_size2];\
+ int _tmp_num = mtk_socket_get_string_array(buff, offset, _tmp, max_size1, max_size2);\
+ if(!mtk_socket_string_array_is_equal(expected_value, expected_num, _tmp, _tmp_num, max_size2)) {\
+ SOCK_LOGE("%s():%d expected_string_array() fail", __func__, __LINE__);\
+ SOCK_LOGE(" ============= read ===============");\
+ mtk_socket_string_array_dump(_tmp, _tmp_num, max_size2);\
+ SOCK_LOGE(" ============= expected ===============");\
+ mtk_socket_string_array_dump(expected_value, expected_num, max_size2);\
+ return false;\
+ }\
+}
+
+#define EXPECTED_STRUCT_ARRAY(buff, offset, expected_num, expected_value, type, max_size) \
+{\
+ type _tmp[max_size];\
+ int _tmp_num = type##_array_decode(buff, offset, _tmp, max_size);\
+ if(!type##_array_is_equal(expected_value, expected_num, _tmp, _tmp_num)) {\
+ SOCK_LOGE("%s():%d expected_%s_array() fail", __func__, __LINE__, #type);\
+ SOCK_LOGE(" ============= read ===============");\
+ type##_array_dump(_tmp, _tmp_num);\
+ SOCK_LOGE(" ============= expected ===============");\
+ type##_array_dump(expected_value, expected_num);\
+ return false;\
+ }\
+}
+
+#define ASSERT_LESS_EQUAL_THAN(d1, d2) \
+{\
+ if(d1 > d2) {\
+ SOCK_LOGE("%s():%d ASSERT_LESS_EQUAL_THAN() fail, %s=[%d] > [%d]", __func__, __LINE__, #d1, d1, d2);\
+ return false;\
+ }\
+}
+
+#define ASSERT_LESS_EQUAL_THAN_FOR_MSG(d1, d2) \
+{\
+ if(d1 > d2) {\
+ SOCK_LOGE("%s():%d ASSERT_LESS_EQUAL_THAN_FOR_MSG() fail, %s=[%d] > [%d]", __func__, __LINE__, #d1, d1, d2);\
+ mtk_socket_client_close(client_fd);\
+ pthread_mutex_unlock(&client_fd->mutex);\
+ return false;\
+ }\
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/utility/src/mtk_lbs_utility.c b/src/connectivity/agps/2.0/lbs_em/src/utility/src/mtk_lbs_utility.c
new file mode 100755
index 0000000..e0a2b89
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/utility/src/mtk_lbs_utility.c
@@ -0,0 +1,501 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h> // usleep
+#include <sys/socket.h>
+#include <string.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>
+
+#if defined(__ANDROID_OS__)
+#include <cutils/log.h> // Android log
+#endif
+
+#include "mtk_lbs_utility.h"
+
+
+// -1 means failure
+/*static int get_time_str(char* buf, int len) {
+ struct timeval tv;
+ struct timezone tz;
+ struct tm *tm;
+
+ gettimeofday(&tv, &tz);
+ tm = localtime(&tv.tv_sec);
+
+ memset(buf, 0, len);
+ sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d.%03d",
+ tm->tm_year + 1900, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min,
+ tm->tm_sec, (int)(tv.tv_usec / 1000));
+
+ return 0;
+}*/
+
+/*************************************************
+* Basic Utilities
+**************************************************/
+void tag_log(int type, const char* tag, const char *fmt, ...) {
+ char out_buf[1100] = {0};
+ char buf[1024] = {0};
+ va_list ap;
+#if defined(__ANDROID_OS__)
+ int prio = 0;
+#endif
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ sprintf(out_buf, "%s %s", tag, buf);
+
+#if defined(__ANDROID_OS__)
+ if (type == 0) {
+ prio = ANDROID_LOG_DEBUG;
+ } else {
+ prio = ANDROID_LOG_ERROR;
+ }
+ __android_log_print(prio, "lbs", "%s", out_buf);
+#else
+/* ignore time buffer
+ char time_buf[64] = {0};
+ UNUSED(type);
+ UNUSED(prio);
+ get_time_str(time_buf, sizeof(time_buf));
+
+ printf("%s %s\n", time_buf, out_buf);
+ */
+ printf("%s\n", out_buf);
+#endif
+}
+
+void msleep2(int interval) {
+ usleep(interval * 1000);
+}
+
+// in millisecond
+time_t get_tick() {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
+ LOGE("clock_gettime failed reason=[%s]", strerror(errno));
+ return -1;
+ }
+ return (ts.tv_sec*1000) + (ts.tv_nsec/1000000);
+}
+
+// in millisecond
+time_t get_time_in_millisecond() {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+ LOGE("get_time_in_millisecond failed reason=[%s]", strerror(errno));
+ return -1;
+ }
+ return ((long long)ts.tv_sec*1000) + ((long long)ts.tv_nsec/1000000);
+}
+
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int epoll_add_fd3(int epfd, int fd) {
+ struct epoll_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.data.fd = fd;
+ ev.events = EPOLLIN;
+ // 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_fd3() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+ strerror(errno), errno, epfd, fd);
+ return -1;
+ }
+ return 0;
+}
+
+// -1 failed
+int 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;
+}
+
+bool epoll_add_fd(int epfd, int fd, int events) {
+ struct epoll_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.data.fd = fd;
+ ev.events = events;
+ //don't set fd to edge trigger due to event lost when multiple events coming together
+ //level trigger can avoid above issue
+ //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_ctl() failed, epfd=%d fd=%d events=0x%x reason=[%s]%d",
+ epfd, fd, events, strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+int epoll_del_fd(int epfd, int fd) {
+ struct epoll_event ev;
+ int ret;
+
+ if (epfd == -1)
+ return -1;
+
+ ev.events = EPOLLIN;
+ ev.data.fd = fd;
+ do {
+ ret = epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev);
+ } while (ret < 0 && errno == EINTR);
+ return ret;
+}
+
+// -1 failed
+int epoll_mod_fd(int epfd, int fd, uint32_t events) {
+ struct epoll_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.data.fd = fd;
+ ev.events = events;
+ if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1) {
+ LOGE("epoll_mod_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+ strerror(errno), errno, epfd, fd);
+ return -1;
+ }
+ return 0;
+}
+
+/******************************************************************************
+* Timer
+******************************************************************************/
+
+//NULL means fail or timerid is returned
+timer_t timer_init(timer_routine cb, int id) {
+ struct sigevent sevp;
+ timer_t timerid;
+
+ memset(&sevp, 0, sizeof(sevp));
+ sevp.sigev_value.sival_int = id;
+ sevp.sigev_notify = SIGEV_THREAD;
+ sevp.sigev_notify_function = (void*)cb;
+
+ if(timer_create(CLOCK_BOOTTIME, &sevp, &timerid) == -1) {
+ LOGE("timer_init() timer_create() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return NULL;
+ }
+ return timerid;
+}
+
+bool timer_deinit(timer_t timerid) {
+ if(timer_delete(timerid) == -1) {
+ LOGE("timer_deinit() timer_delete() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool timer_start(timer_t timerid, int milliseconds) {
+ struct itimerspec expire;
+ expire.it_interval.tv_sec = 0;
+ expire.it_interval.tv_nsec = 0;
+ expire.it_value.tv_sec = milliseconds/1000;
+ expire.it_value.tv_nsec = (milliseconds%1000)*1000000;
+ if(timer_settime(timerid, 0, &expire, NULL) == -1) {
+ LOGE("timer_start() timer_settime() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool timer_stop(timer_t timerid) {
+ return timer_start(timerid, 0);
+}
+
+//-1 means fail or the remaining time is returned
+int64_t timer_get_remaining_time(timer_t timerid) {
+ struct itimerspec ts;
+ if(timer_gettime(timerid, &ts) == -1) {
+ LOGE("timer_get_remaining_time() timer_gettime() failed, reason=[%s]%d", strerror(errno), errno);
+ return -1;
+ }
+ return ((int64_t)ts.it_value.tv_sec * 1000 + ts.it_value.tv_nsec / 1000000);
+}
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int 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;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, path, strlen(path));
+ 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 socket_set_blocking2(int fd, int blocking) {
+ if (fd < 0) {
+ LOGE("socket_set_blocking2() invalid fd=%d", fd);
+ return -1;
+ }
+
+ int flags = fcntl(fd, F_GETFL, 0);
+ if (flags == -1) {
+ LOGE("socket_set_blocking2() 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;
+}
+
+// -1 means failure
+int 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;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, path, strlen(path));
+ 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;
+}
+
+// -1 means failure
+int safe_recvfrom(int fd, char* buff, int len) {
+ int ret = 0;
+ int retry = 10;
+
+ while ((ret = recvfrom(fd, buff, len, 0,
+ NULL, NULL)) == -1) {
+ LOGW("safe_recvfrom() ret=%d len=%d", ret, len);
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("safe_recvfrom() recvfrom() failed reason=[%s]%d",
+ strerror(errno), errno);
+ break;
+ }
+ return ret;
+}
+
+
+//-1 means fail or clientfd is returned
+int 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 {
+ LBS_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ }
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(fd == -1) {
+ LOGE("socket_tcp_client_connect_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(connect(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("socket_tcp_client_connect_local() connect() failed, abstract=%d name=[%s] reason=[%s]%d",
+ abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+//-1 means fail or serverfd is returned
+int socket_udp_server_bind_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 {
+ LBS_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ if(unlink(addr.sun_path) == -1) {
+ LOGW("socket_udp_server_bind_local() unlink() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ LOGE("socket_udp_server_bind_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(bind(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("socket_udp_server_bind_local() bind() failed, abstract=%d name=[%s] reason=[%s]%d",
+ abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+//-1 means fail or clientfd is returned
+int socket_udp_client_create_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 {
+ LBS_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ LOGE("socket_udp_client_create_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(connect(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("socket_udp_client_create_local() connect() failed, abstract=%d name=[%s] reason=[%s]%d",
+ abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+bool socket_udp_exist_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 {
+ LBS_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ LOGE("socket_udp_is_bind_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return false;
+ }
+ if(connect(fd, (struct sockaddr*)&addr, size) == -1) {
+ close(fd);
+ return false;
+ }
+ close(fd);
+ return true;
+
+}
+
+void dump_buff(const char* data, int len) {
+ int i = 0;
+ int offset = 0;
+ char buff[1024] = {0};
+
+ LOGD("len=%d", len);
+
+ for(i = 0; i < len; i++) {
+
+ if(i%16 == 0) {
+ sprintf(buff + offset, "%04x0 ", i/16);
+ offset += 6;
+ }
+
+ sprintf(buff + offset, "%02x ", data[i]&0xff);
+ offset += 3;
+
+ if(i%16 == 15) {
+ LOGD(" %s ", buff);
+
+ memset(buff, 0, sizeof(buff));
+ offset = 0;
+ }
+ }
+ if(offset > 0) {
+ LOGD(" %s ", buff);
+ }
+}
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/utility/src/mtk_socket_data_coder.c b/src/connectivity/agps/2.0/lbs_em/src/utility/src/mtk_socket_data_coder.c
new file mode 100755
index 0000000..00d346a
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/utility/src/mtk_socket_data_coder.c
@@ -0,0 +1,257 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include "mtk_socket_data_coder.h"
+
+bool mtk_socket_get_bool(char* buff, int* offset) {
+ bool ret = (mtk_socket_get_char(buff, offset) == 0)? false : true;
+ return ret;
+}
+
+char mtk_socket_get_char(char* buff, int* offset) {
+ char ret = buff[*offset];
+ *offset += 1;
+ return ret;
+}
+
+short mtk_socket_get_short(char* buff, int* offset) {
+ short ret = 0;
+ ret |= mtk_socket_get_char(buff, offset) & 0xff;
+ ret |= (mtk_socket_get_char(buff, offset) << 8);
+ return ret;
+}
+
+int mtk_socket_get_int(char* buff, int* offset) {
+ int ret = 0;
+ ret |= mtk_socket_get_short(buff, offset) & 0xffff;
+ ret |= (mtk_socket_get_short(buff, offset) << 16);
+ return ret;
+}
+
+int64_t mtk_socket_get_int64_t(char* buff, int* offset) {
+ int64_t ret = 0;
+ ret |= mtk_socket_get_int(buff, offset) & 0xffffffffL;
+ ret |= ((int64_t)mtk_socket_get_int(buff, offset) << 32);
+ return ret;
+}
+
+float mtk_socket_get_float(char* buff, int* offset) {
+ float ret;
+ int tmp = mtk_socket_get_int(buff, offset);
+ ret = *((float*)&tmp);
+ return ret;
+}
+
+double mtk_socket_get_double(char* buff, int* offset) {
+ double ret;
+ int64_t tmp = mtk_socket_get_int64_t(buff, offset);
+ ret = *((double*)&tmp);
+ return ret;
+}
+
+int mtk_socket_get_string(char* buff, int* offset, char* output, int max_size) {
+ int size = mtk_socket_get_int(buff, offset);
+ memset(output, 0, max_size);
+ memcpy(output, &buff[*offset], (size > max_size)? max_size : size);
+ output[max_size - 1] = 0;
+ *offset += size;
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_bool_array(char* buff, int* offset, bool output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ bool data = mtk_socket_get_bool(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_char_array(char* buff, int* offset, char output[], int max_size) {
+ int size = mtk_socket_get_int(buff, offset);
+ memcpy(output, &buff[*offset], (size > max_size)? max_size : size);
+ *offset += size;
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_short_array(char* buff, int* offset, short output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ short data = mtk_socket_get_short(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_int_array(char* buff, int* offset, int output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ int data = mtk_socket_get_int(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_int64_t_array(char* buff, int* offset, int64_t output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ int64_t data = mtk_socket_get_int64_t(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_float_array(char* buff, int* offset, float output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ float data = mtk_socket_get_float(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_double_array(char* buff, int* offset, double output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ double data = mtk_socket_get_double(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_string_array(char* buff, int* offset, strings output, int max_size1, int max_size2) {
+ int i = 0;
+ int size1 = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size1; i++) {
+ if(i < max_size1) {
+ mtk_socket_get_string(buff, offset, output, max_size2);
+ output = (char*)output + max_size2;
+ } else {
+ char tmp[max_size2];
+ mtk_socket_get_string(buff, offset, tmp, max_size2);
+ }
+ }
+ return (size1 > max_size1)? max_size1 : size1;
+}
+
+void mtk_socket_put_bool(char* buff, int* offset, bool input) {
+ mtk_socket_put_char(buff, offset, input);
+}
+
+void mtk_socket_put_char(char* buff, int* offset, char input) {
+ *((char*)&buff[*offset]) = input;
+ *offset += 1;
+}
+
+void mtk_socket_put_short(char* buff, int* offset, short input) {
+ mtk_socket_put_char(buff, offset, input & 0xff);
+ mtk_socket_put_char(buff, offset, (input >> 8) & 0xff);
+}
+
+void mtk_socket_put_int(char* buff, int* offset, int input) {
+ mtk_socket_put_short(buff, offset, input & 0xffff);
+ mtk_socket_put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void mtk_socket_put_int64_t(char* buff, int* offset, int64_t input) {
+ mtk_socket_put_int(buff, offset, input & 0xffffffffL);
+ mtk_socket_put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void mtk_socket_put_float(char* buff, int* offset, float input) {
+ int* data = (int*)&input;
+ mtk_socket_put_int(buff, offset, *data);
+}
+
+void mtk_socket_put_double(char* buff, int* offset, double input) {
+ int64_t* data = (int64_t*)&input;
+ mtk_socket_put_int64_t(buff, offset, *data);
+}
+
+void mtk_socket_put_string(char* buff, int* offset, const char* input) {
+ int len = strlen(input);
+ mtk_socket_put_int(buff, offset, len);
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+}
+
+void mtk_socket_put_bool_array(char* buff, int* offset, bool input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_bool(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_char_array(char* buff, int* offset, char input[], int size) {
+ mtk_socket_put_int(buff, offset, size);
+ memcpy(&buff[*offset], input, size);
+ *offset += size;
+}
+
+void mtk_socket_put_short_array(char* buff, int* offset, short input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_short(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_int_array(char* buff, int* offset, int input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_int(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_int64_t_array(char* buff, int* offset, int64_t input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_int64_t(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_float_array(char* buff, int* offset, float input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_float(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_double_array(char* buff, int* offset, double input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_double(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_string_array(char* buff, int* offset, strings input, int size1, int size2) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size1);
+ for(i = 0; i < size1; i++) {
+ mtk_socket_put_string(buff, offset, (char*)input);
+ input = (char*)input + size2;
+ }
+}
+
+
diff --git a/src/connectivity/agps/2.0/lbs_em/src/utility/src/mtk_socket_utils.c b/src/connectivity/agps/2.0/lbs_em/src/utility/src/mtk_socket_utils.c
new file mode 100755
index 0000000..3da3419
--- /dev/null
+++ b/src/connectivity/agps/2.0/lbs_em/src/utility/src/mtk_socket_utils.c
@@ -0,0 +1,725 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include "mtk_socket_utils.h"
+#include "mtk_socket_data_coder.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h> //usleep
+#include <sys/socket.h>
+#include <string.h>
+#include <fcntl.h>
+#include <arpa/inet.h> //inet_addr
+#include <sys/un.h> //struct sockaddr_un
+#include <sys/epoll.h>
+#include <poll.h>
+#include <sys/types.h>
+#include <netdb.h>
+
+#if defined(__ANDROID_OS__)
+#include <log/log.h> // Android log
+
+#define ANDROID_LOG_TAG "mtk_socket"
+#endif
+
+#define NETLINK_ROUTE 0
+
+static char *safe_strncpy(char *dest, const char *src, size_t n) {
+ if (dest && n > 0) {
+ dest[0] = '\0';
+ strncat(dest, src, --n);
+ }
+ return dest;
+}
+
+#if !defined(__ANDROID_OS__)
+//-1 means failure
+static int get_time_str(char* buff, int len) {
+ struct timeval tv;
+ struct timezone tz;
+ struct tm *tm;
+
+ gettimeofday(&tv, &tz);
+ tm = localtime(&tv.tv_sec);
+
+ memset(buff, 0, len);
+ sprintf(buff, "%04d/%02d/%02d %02d:%02d:%02d.%03d",
+ tm->tm_year + 1900, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min,
+ tm->tm_sec, (int)(tv.tv_usec / 1000));
+
+ return 0;
+}
+#endif
+
+void _mtk_socket_log(int type, const char *fmt, ...) {
+ char buff[1024] = {0};
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(buff, sizeof(buff), fmt, ap);
+ va_end(ap);
+
+#if defined(__ANDROID_OS__)
+ if(type == 0) {
+ __android_log_print(ANDROID_LOG_DEBUG, ANDROID_LOG_TAG, "%s", buff);
+ } else {
+ __android_log_print(ANDROID_LOG_ERROR, ANDROID_LOG_TAG, "ERR: %s", buff);
+ }
+#else
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ if(type == 0) {
+ printf("%s %s\n", time_buff, buff);
+ } else {
+ printf("%s ERR: %s\n", time_buff, buff);
+ }
+ fflush(stdout);
+#endif
+}
+
+//-1 means failure
+int mtk_socket_server_bind_network(int port) {
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0) {
+ SOCK_LOGE("mtk_socket_server_bind_network() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+ SOCK_LOGE("mtk_socket_server_bind_network() bind() failed reason=[%s]%d for port=[%d]",
+ strerror(errno), errno, port);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+//-1 means failure
+int mtk_socket_server_bind_network_ipv6(int port) {
+ struct sockaddr_in6 addr;
+ memset(&addr, 0, sizeof(addr));
+ int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0) {
+ SOCK_LOGE("mtk_socket_server_bind_network_ipv6() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ addr.sin6_family = AF_INET6;
+ addr.sin6_port = htons(port);
+ addr.sin6_addr = in6addr_any;
+ if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+ SOCK_LOGE("mtk_socket_server_bind_network_ipv6() bind() failed reason=[%s]%d for port=[%d]",
+ strerror(errno), errno, port);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+//-1 means failure
+int mtk_socket_server_bind_local(const char* path, mtk_socket_namespace sock_namespace) {
+ int size;
+ struct sockaddr_un addr;
+ int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ SOCK_LOGE("mtk_socket_server_bind_local() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ size = strlen(path) + offsetof(struct sockaddr_un, sun_path) + 1;
+ if(sock_namespace == SOCK_NS_ABSTRACT) {
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, path, strlen(path));
+ } else if(sock_namespace == SOCK_NS_FILESYSTEM) {
+ safe_strncpy(addr.sun_path, path, sizeof(addr.sun_path));
+ unlink(addr.sun_path);
+ } else {
+ SOCK_LOGE("mtk_socket_server_bind_local() unknown namespace=[%d]", sock_namespace);
+ close(fd);
+ return -1;
+ }
+ if (bind(fd, (struct sockaddr *)&addr, size) == -1) {
+ SOCK_LOGE("mtk_socket_server_bind_local() bind() failed reason=[%s]%d for path=[%s]",
+ strerror(errno), errno, path);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+//-1 means fail or serverfd is returned
+int socket_tcp_server_bind_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 {
+ safe_strncpy(addr.sun_path, name, sizeof(addr.sun_path));
+ if(unlink(addr.sun_path) == -1) {
+ SOCK_LOGE("socket_tcp_server_bind_local() unlink() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(fd == -1) {
+ SOCK_LOGE("socket_tcp_server_bind_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(bind(fd, (struct sockaddr*)&addr, size) == -1) {
+ SOCK_LOGE("socket_tcp_server_bind_local() bind() failed, abstruct=%d name=[%s] reason=[%s]%d",
+ abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ if(listen(fd, 5) == -1) {
+ SOCK_LOGE("socket_tcp_server_bind_local() listen() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ return fd;
+}
+
+//-1 means fail or new clientfd is returned
+int socket_tcp_server_new_connect(int serverfd) {
+ int newfd;
+ struct sockaddr_in addr;
+ socklen_t len = sizeof(addr);
+
+ newfd = accept(serverfd, (struct sockaddr*)&addr, &len);
+ if(newfd == -1) {
+ SOCK_LOGE("socket_tcp_server_new_connect() accept() failed, serverfd=%d reason=[%s]%d",
+ serverfd, strerror(errno), errno);
+ return -1;
+ }
+ return newfd;
+}
+
+
+void mtk_socket_client_init_network(mtk_socket_fd* sock_fd, const char* host, int port) {
+ int len = strlen(host);
+ memset(sock_fd, 0, sizeof(*sock_fd));
+ sock_fd->fd = -1;
+ sock_fd->is_local = false;
+ pthread_mutex_init(&sock_fd->mutex, NULL);
+ sock_fd->host = malloc(len + 1);
+ safe_strncpy(sock_fd->host, host, len + 1);
+ sock_fd->port = port;
+}
+
+void mtk_socket_client_init_local(mtk_socket_fd* sock_fd, const char* path, mtk_socket_namespace sock_namespace) {
+ int len = strlen(path);
+ memset(sock_fd, 0, sizeof(*sock_fd));
+ sock_fd->fd = -1;
+ sock_fd->is_local = true;
+ pthread_mutex_init(&sock_fd->mutex, NULL);
+ sock_fd->path = malloc(len + 1);
+ safe_strncpy(sock_fd->path, path, len + 1);
+ sock_fd->namesapce = sock_namespace;
+}
+
+void mtk_socket_client_cleanup(mtk_socket_fd* sock_fd) {
+ mtk_socket_client_close(sock_fd);
+ if(sock_fd->host) {
+ free(sock_fd->host);
+ sock_fd->host = NULL;
+ }
+ if(sock_fd->path) {
+ free(sock_fd->path);
+ sock_fd->path = NULL;
+ }
+}
+
+static bool mtk_socket_connect_local(mtk_socket_fd* sock_fd) {
+ int size;
+ struct sockaddr_un addr;
+ int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ SOCK_LOGE("mtk_socket_connect_local() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return false;
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_LOCAL;
+ size = strlen(sock_fd->path) + offsetof(struct sockaddr_un, sun_path) + 1;
+ if(sock_fd->namesapce == SOCK_NS_ABSTRACT) {
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, sock_fd->path, strlen(sock_fd->path));
+ } else if(sock_fd->namesapce == SOCK_NS_FILESYSTEM) {
+ safe_strncpy(addr.sun_path, sock_fd->path, sizeof(addr.sun_path));
+ } else {
+ SOCK_LOGE("mtk_socket_connect_local() unknown namespace=[%d]", sock_fd->namesapce);
+ close(fd);
+ return false;
+ }
+ if (connect(fd, (struct sockaddr *)&addr, size) < 0) {
+ SOCK_LOGE("mtk_socket_connect_local() connect() failed reason=[%s]%d for path=[%s]",
+ strerror(errno), errno, sock_fd->path);
+ close(fd);
+ return false;
+ }
+ sock_fd->fd = fd;
+ return true;
+}
+
+static int mtk_socket_connect_network_ipv4(struct sockaddr_in* addr) {
+ int port = ntohs(addr->sin_port);
+ char ip_str[64] = {0};
+ inet_ntop(AF_INET, &(addr->sin_addr), ip_str, sizeof(ip_str));
+ int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0) {
+ SOCK_LOGE("mtk_socket_connect_network_ipv4() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ //SOCK_LOGD("mtk_socket_connect_network_ipv4() IPv4=[%s] port=[%d]", ip_str, port);
+ if (connect(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
+ SOCK_LOGE("mtk_socket_connect_network_ipv4() connect() failed reason=[%s]%d for host=[%s] port=[%d]",
+ strerror(errno), errno, ip_str, port);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+//-1 means failure
+static int mtk_socket_connect_network_ipv6(struct sockaddr_in6* addr) {
+ int port = ntohs(addr->sin6_port);
+ int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0) {
+ SOCK_LOGE("mtk_socket_connect_network_ipv6() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ //unsigned char* ipv6_addr = addr->sin6_addr.s6_addr;
+ //SOCK_LOGD("mtk_socket_connect_network_ipv6() IPv6=[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x] port=[%d]",
+ // ipv6_addr[0], ipv6_addr[1], ipv6_addr[2], ipv6_addr[3], ipv6_addr[4], ipv6_addr[5], ipv6_addr[6], ipv6_addr[7],
+ // ipv6_addr[8], ipv6_addr[9], ipv6_addr[10], ipv6_addr[11], ipv6_addr[12], ipv6_addr[13], ipv6_addr[14], ipv6_addr[15],
+ // port);
+ if (connect(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
+ SOCK_LOGE("mtk_socket_connect_network_ipv6() connect() failed reason=[%s]%d for port=[%d]",
+ strerror(errno), errno, port);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+static bool mtk_socket_connect_network(mtk_socket_fd* sock_fd) {
+ struct addrinfo hints;
+ struct addrinfo *result;
+ struct addrinfo *rp;
+ int ret;
+ char port_str[11] = {0};
+ sprintf(port_str, "%u", sock_fd->port);
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6, AF_UNSPEC, AF_INET, AF_INET6
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_ADDRCONFIG; // check local system
+ hints.ai_protocol = IPPROTO_UDP;
+ ret = getaddrinfo(sock_fd->host, port_str, &hints, &result);
+ if(ret != 0) {
+ SOCK_LOGE("mtk_socket_connect_network() getaddrinfo() failure reason=[%s] %d\n",
+ gai_strerror(ret), ret);
+ return false;
+ }
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+ if(rp->ai_family == AF_INET) {
+ ret = mtk_socket_connect_network_ipv4((struct sockaddr_in*)rp->ai_addr);
+ if(ret >= 0) {
+ sock_fd->fd = ret;
+ break;
+ }
+ }
+ if(rp->ai_family == AF_INET6) {
+ ret = mtk_socket_connect_network_ipv6((struct sockaddr_in6*)rp->ai_addr);
+ if(ret >= 0) {
+ sock_fd->fd = ret;
+ break;
+ }
+ }
+ }
+ freeaddrinfo(result);
+ if(ret >= 0) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool mtk_socket_client_connect(mtk_socket_fd* sock_fd) {
+ if(sock_fd->is_local) {
+ return mtk_socket_connect_local(sock_fd);
+ } else {
+ return mtk_socket_connect_network(sock_fd);
+ }
+}
+
+void mtk_socket_client_close(mtk_socket_fd* sock_fd) {
+ if(sock_fd->fd >= 0) {
+ close(sock_fd->fd);
+ sock_fd->fd = -1;
+ }
+}
+
+//-1 means failure
+int mtk_socket_read(int fd, char* buff, int len) {
+ int n, retry = 10;
+ if(fd < 0 || buff == NULL || len < 0) {
+ SOCK_LOGE("mtk_socket_read() invalid params fd=[%d] buff=[%p] len=[%d]", fd, buff, len);
+ return -1;
+ }
+ if(len == 0) {
+ return 0;
+ }
+ while((n = read(fd, buff, len)) < 0) {
+ if(errno == EINTR) continue;
+ if(errno == EAGAIN) {
+ if(retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ goto exit;
+ }
+ goto exit;
+ }
+ return n;
+exit:
+ SOCK_LOGE("mtk_socket_read() read() failed, fd=[%d] len=[%d] errno=[%s]%d",
+ fd, len, strerror(errno), errno);
+ return -1;
+}
+
+//-1 means failure
+int mtk_socket_write(int fd, void* buff, int len) {
+ int n, retry = 10;
+ if(fd < 0 || buff == NULL || len < 0) {
+ SOCK_LOGE("mtk_socket_write() invalid params fd=[%d] buff=[%p] len=[%d]", fd, buff, len);
+ return -1;
+ }
+ while((n = write(fd, buff, len)) != len) {
+ if(errno == EINTR) continue;
+ if(errno == EAGAIN) {
+ if(retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ goto exit;
+ }
+ goto exit;
+ }
+ return n;
+exit:
+ SOCK_LOGE("mtk_socket_write() write() failed, fd=[%d] len=[%d] errno=[%s]%d\n",
+ fd, len, strerror(errno), errno);
+ return -1;
+}
+
+// <= 0 means no data received
+int mtk_socket_poll(int fd, int timeout) {
+ struct pollfd poll_fd[1];
+ int ret = 0;
+ memset(poll_fd, 0, sizeof(poll_fd));
+ poll_fd[0].fd = fd;
+ poll_fd[0].events = POLLIN;
+ poll_fd[0].revents = 0;
+
+ ret = poll(poll_fd, 1, timeout);
+ if(ret > 0) {
+ if(poll_fd[0].revents & POLLIN ||
+ poll_fd[0].revents & POLLERR) {
+ ret = 1 << 0;
+ }
+ }
+ return ret;
+}
+
+void mtk_socket_buff_dump(const char* buff, int len) {
+ int i = 0;
+ char tmp[512] = {0};
+ SOCK_LOGD("mtk_socket_buff_dump len=%d", len);
+ for(i = 0; i < len; i++) {
+ if((i % 16 == 0) && (i != 0)) {
+ SOCK_LOGD(" %s", tmp);
+ memset(tmp, 0, sizeof(tmp));
+ }
+ sprintf(tmp + ((i % 16) * 3), "%02x ", buff[i] & 0xff);
+ }
+ if(i > 0) {
+ SOCK_LOGD(" %s", tmp);
+ }
+}
+
+bool mtk_socket_string_is_equal(char* data1, char* data2) {
+ return (strcmp(data1, data2) == 0)? true : false;
+}
+
+bool mtk_socket_bool_array_is_equal(bool data1[], int data1_size, bool data2[], int data2_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(data1[i] != data2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool mtk_socket_char_array_is_equal(char data1[], int data1_size, char data2[], int data2_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(data1[i] != data2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool mtk_socket_short_array_is_equal(short data1[], int data1_size, short data2[], int data2_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(data1[i] != data2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool mtk_socket_int_array_is_equal(int data1[], int data1_size, int data2[], int data2_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(data1[i] != data2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool mtk_socket_int64_t_array_is_equal(int64_t data1[], int data1_size, int64_t data2[], int data2_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(data1[i] != data2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool mtk_socket_float_array_is_equal(float data1[], int data1_size, float data2[], int data2_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(data1[i] != data2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool mtk_socket_double_array_is_equal(double data1[], int data1_size, double data2[], int data2_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(data1[i] != data2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool mtk_socket_string_array_is_equal(strings data1, int data1_size, strings data2, int data2_size, int string_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(!mtk_socket_string_is_equal(data1, data2)) {
+ return false;
+ }
+ data1 = (char*)data1 + string_size;
+ data2 = (char*)data2 + string_size;
+ }
+ return true;
+}
+
+void mtk_socket_bool_array_dump(bool input[], int size) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_bool_array_dump size=%d", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%d]", i, input[i]);
+ }
+}
+
+void mtk_socket_char_array_dump(char input[], int size) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_char_array_dump size=%d", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%d]", i, input[i] & 0xff);
+ }
+}
+
+void mtk_socket_short_array_dump(short input[], int size) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_short_array_dump size=%d", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%d]", i, input[i] & 0xffff);
+ }
+}
+
+void mtk_socket_int_array_dump(int input[], int size) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_int_array_dump size=%d", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%d]", i, input[i]);
+ }
+}
+
+void mtk_socket_int64_t_array_dump(int64_t input[], int size) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_int64_t_array_dump size=%d", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%lld]", i, (long long)input[i]);
+ }
+}
+
+void mtk_socket_float_array_dump(float input[], int size) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_float_array_dump size=%d", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%f]", i, input[i]);
+ }
+}
+
+void mtk_socket_double_array_dump(double input[], int size) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_double_array_dump size=%d", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%f]", i, input[i]);
+ }
+}
+
+void mtk_socket_string_array_dump(strings input, int size1, int size2) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_string_array_dump size1=%d size2=%d", size1, size2);
+ for(i = 0; i < size1; i++) {
+ SOCK_LOGD(" i=[%d] data=[%s]", i, (char*)input);
+ input = (char*)input + size2;
+ }
+}
+
+bool mtk_socket_expected_bool(char* buff, int* offset, bool expected_value, const char* func, int line) {
+ bool value = mtk_socket_get_bool(buff, offset);
+ if(value != expected_value) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_bool() failed, read=[%d], expected=[%d]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_socket_expected_char(char* buff, int* offset, char expected_value, const char* func, int line) {
+ char value = mtk_socket_get_char(buff, offset);
+ if(value != expected_value) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_char() failed, read=[%d], expected=[%d]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_socket_expected_short(char* buff, int* offset, short expected_value, const char* func, int line) {
+ short value = mtk_socket_get_short(buff, offset);
+ if(value != expected_value) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_short() failed, read=[%d], expected=[%d]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_socket_expected_int(char* buff, int* offset, int expected_value, const char* func, int line) {
+ int value = mtk_socket_get_int(buff, offset);
+ if(value != expected_value) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_int() failed, read=[%d], expected=[%d]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_socket_expected_int64_t(char* buff, int* offset, int64_t expected_value, const char* func, int line) {
+ int64_t value = mtk_socket_get_int64_t(buff, offset);
+ if(value != expected_value) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_int64_t() failed, read=[%lld], expected=[%lld]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_socket_expected_float(char* buff, int* offset, float expected_value, const char* func, int line) {
+ float value = mtk_socket_get_float(buff, offset);
+ if(value != expected_value) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_float() failed, read=[%f], expected=[%f]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_socket_expected_double(char* buff, int* offset, double expected_value, const char* func, int line) {
+ double value = mtk_socket_get_double(buff, offset);
+ if(value != expected_value) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_double() failed, read=[%f], expected=[%f]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_socket_expected_string(char* buff, int* offset, const char* expected_value, int max_size, const char* func, int line) {
+ char value[max_size];
+ mtk_socket_get_string(buff, offset, value, sizeof(value));
+ if(strcmp(value, expected_value) != 0) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_string() failed, read=[%s], expected=[%s]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
diff --git a/src/connectivity/gps/2.0/Makefile b/src/connectivity/gps/2.0/Makefile
new file mode 100644
index 0000000..a81c513
--- /dev/null
+++ b/src/connectivity/gps/2.0/Makefile
@@ -0,0 +1,26 @@
+SUBDIRS := \
+ mtk_mnld \
+ gps_hal \
+ gnss_test \
+ gpslog \
+
+TARGET := \
+ gps_hal/libgnsshal.so \
+ mtk_mnld/mnld \
+ gnss_test/mnld_test \
+ gpslog/gpslog \
+
+all:${TARGET}
+.PHONY : all
+${TARGET}:$(SUBDIRS)
+ @echo $(SUBDIRS)
+
+$(SUBDIRS):
+ make -C $@
+.PHONY : $(SUBDIRS)
+
+.PHONY : clean
+clean:
+ for dir in $(SUBDIRS);\
+ do $(MAKE) -C $$dir clean||exit 1;\
+ done
diff --git a/src/connectivity/gps/2.0/NOTICE b/src/connectivity/gps/2.0/NOTICE
new file mode 100644
index 0000000..ea1cac7
--- /dev/null
+++ b/src/connectivity/gps/2.0/NOTICE
@@ -0,0 +1,207 @@
+Copyright (C) 2010 The Android Open Source Project
+MediaTek Inc. (C) [2008]. All rights reserved.
+MediaTek Inc.(C) [2008]. All rights reserved.
+Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2010 The Android Open Source Project
+Copyright (C) 2010 The Android Open Source Project
+Copyright (C) 2006 The Android Open Source Project
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+Copyright (C) 1998 - 2013, Daniel Stenberg,
+Copyright (C) 1998 - 2008, Daniel Stenberg,
+Copyright (C) 1998 - 2014, Daniel Stenberg,
+Copyright (C) 1998 - 2015, Daniel Stenberg,
+
+Curl License
+Copyright (c) 1996 - 2003, Daniel Stenberg, <daniel@haxx.se>.
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software for any purposewith or without fee is hereby granted,
+provided that the above copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USEOR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to
+promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder.
+
diff --git a/src/connectivity/gps/2.0/geofenceinf_example/geofence.h b/src/connectivity/gps/2.0/geofenceinf_example/geofence.h
new file mode 100755
index 0000000..f4c5d09
--- /dev/null
+++ b/src/connectivity/gps/2.0/geofenceinf_example/geofence.h
@@ -0,0 +1,178 @@
+#ifndef __GEOFENCE_H__
+#define __GEOFENCE_H__
+
+#pragma pack(push)
+#pragma pack(4)
+
+typedef struct {
+ bool geofence_support;
+}mtk_geofence_client_capability;
+
+typedef struct {
+ bool geofence_support;
+}mtk_geofence_server_capability;
+
+typedef enum {
+ GEOFENCE_CLIENT_CAP,//geofence client capability
+ INIT_GEOFENCE,//Reserved
+ ADD_GEOFENCE_AREA,
+ PAUSE_GEOFENCE,//Reserved
+ RESUME_GEOFENCE,//Reserved
+ REMOVE_GEOFENCE,
+ RECOVER_GEOFENCE,//Reserved
+ CLEAR_GEOFENCE,
+ QUERY_GEOFENCE_NUM
+} mtk_geofence_command;
+
+typedef enum {
+ GEOFENCE_UNKNOWN = 0,
+ GEOFENCE_ENTERED = 1,
+ GEOFENCE_EXITED = 2,
+} mtk_geofence_status;
+
+typedef int mtk_monitor_transition;
+#define MTK_GEOFENCE_ENTER 0x01
+#define MTK_GEOFENCE_EXIT 0x02
+#define MTK_GEOFENCE_UNCERTAIN 0x04//Reserved
+
+typedef struct mtk_geofence_area {
+ double latitude;
+ double longitude;
+ double radius;
+ int latest_state; /*current state(mtk_geofence_status), most cases is GEOFENCE_UNKNOWN*/
+ mtk_monitor_transition monitor_transition; /*bitwise , MTK_GEOFENCE_EXIT/MTK_GEOFENCE_ENTER/MTK_GEOFENCE_UNCERTAIN*/
+ int unknown_timer;/*The time limit after which the UNCERTAIN transition should be triggered. This paramter is defined in milliseconds.*/
+} mtk_geofence_property;
+
+typedef struct mtk_geofence_alert {
+ int id;
+ int alert_state;//mtk_geofence_status
+ double latitude;
+ double longitude;
+ double altitude;
+ double speed;
+ double heading;
+ int h_acc;
+ int h_err_majoraxis;
+ int h_err_minoraxis;
+ int h_err_angle;
+ int hor_conf;
+ double pdop;
+ double hdop;
+ double vdop;
+}mtk_geofence_alert;
+
+typedef struct mtk_gnss_tracking_status {
+ int status; //GNSS service tracking OK = 0,GNSS service tracking failure = -1
+ int year;
+ int month;
+ int day;
+ int hour;
+ int minute;
+ int second;
+}mtk_gnss_tracking_status;
+
+typedef struct {
+ void (*geofence_connection_broken)();
+ void (*geofence_fence_alert_callback)(mtk_geofence_alert *ptr);
+ void (*geofence_tracking_status_callback)(mtk_gnss_tracking_status *ptr);
+ void (*geofence_capability_update)(mtk_geofence_server_capability *cap);
+}mtk_geofence_callback;
+
+#define MTK_GFC_SUCCESS (0)
+#define MTK_GFC_ERROR (-1)
+
+#pragma pack(pop)
+
+/*****************************************************************************
+ * FUNCTION
+ * geofenceinf_add_geofence
+ * DESCRIPTION
+ * add one geofence
+ * PARAMETERS
+ * fence: fence detail information
+ * RETURNS
+ * Success: geofence id, >=1
+ * Fail: -1, create fence fail. -2, insufficient_memory. -3,too many fences
+ *****************************************************************************/
+int geofenceinf_add_geofence(mtk_geofence_property *fence);
+
+/*****************************************************************************
+ * FUNCTION
+ * geofenceinf_remove_geofence
+ * DESCRIPTION
+ * romve one geofence
+ * PARAMETERS
+ * geofence_id: geofence id
+ * RETURNS
+ * MTK_GFC_ERROR
+ * MTK_GFC_SUCCESS
+ *****************************************************************************/
+int geofenceinf_remove_geofence(const int geofence_id) ;
+
+/*****************************************************************************
+ * FUNCTION
+ * geofenceinf_clear_geofences
+ * DESCRIPTION
+ * clear all geofences
+ * PARAMETERS
+ * RETURNS
+ * MTK_GFC_ERROR
+ * MTK_GFC_SUCCESS
+ *****************************************************************************/
+int geofenceinf_clear_geofences(void) ;
+
+/*****************************************************************************
+ * FUNCTION
+ * geofenceinf_query_geofences_num
+ * DESCRIPTION
+ * query geofence numbers that geofence feature support
+ * PARAMETERS
+ * RETURNS
+ * MTK_GFC_ERROR(-1)
+ * number: geofence numbers, >= 1
+ *****************************************************************************/
+int geofenceinf_query_geofences_num(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * geofenceinf_client_register
+ * DESCRIPTION
+ * register geofence client
+ * PARAMETERS
+ * name: client name
+ * mtk_geofence_callback *callback: data messsage callback function
+ * RETURNS
+ * MTK_GFC_ERROR(-1), means error
+ * fd:file descriptor
+ *****************************************************************************/
+int geofenceinf_client_register(const char* name, mtk_geofence_callback *callback);
+
+/*****************************************************************************
+ * FUNCTION
+ * geofenceinf_client_capability_config
+ * DESCRIPTION
+ * config client capability, and send to geofence server
+ * PARAMETERS
+ * cap: client capability
+ * RETURNS
+ * MTK_GFC_ERROR
+ * MTK_GFC_SUCCESS
+ *****************************************************************************/
+int geofenceinf_client_capability_config(mtk_geofence_client_capability *cap);
+
+/*****************************************************************************
+ * FUNCTION
+ * mnl2geofence_hdlr
+ * DESCRIPTION
+ * mnl to geofence adaptor handle function
+ * PARAMETERS
+ * fd:file descriptor
+ * mtk_geofence_callback *callback: data messsage callback function
+ * RETURNS
+ * MTK_GFC_ERROR
+ * MTK_GFC_SUCCESS
+ *****************************************************************************/
+int mnl2geofence_hdlr (int fd, mtk_geofence_callback *callback);
+
+#endif
diff --git a/src/connectivity/gps/2.0/geofenceinf_example/geofence_adapt_mock.c b/src/connectivity/gps/2.0/geofenceinf_example/geofence_adapt_mock.c
new file mode 100755
index 0000000..6e78755
--- /dev/null
+++ b/src/connectivity/gps/2.0/geofenceinf_example/geofence_adapt_mock.c
@@ -0,0 +1,699 @@
+#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"
+
+#define GEOFENCEADP_VERSION "2.02"
+
+#define GEOFENCE_USER_NAME "mtk_geofence_adaptor"
+//---------------------------------- channel -------------------------------------------
+// LBS EM (client) <-> GNSS ADP (server)
+
+#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); }
+
+//--------------------------------------------------------------------------------------------------------
+#define MNLD_STRNCPY(dst,src,size) do{\
+ strncpy((char *)(dst), (src), (size - 1));\
+ (dst)[size - 1] = '\0';\
+ }while(0)
+
+timer_t g_handler_timer;
+
+int tcp_client_fd;
+int epfd;
+char std_in_buff[1024];
+
+typedef void (*timer_routine) (int id);
+
+void msleep(int interval) {
+ usleep(interval * 1000);
+}
+
+// in millisecond
+time_t get_tick() {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
+ LOGE("clock_gettime failed reason=[%s]", strerror(errno));
+ return -1;
+ }
+ return (ts.tv_sec*1000) + (ts.tv_nsec/1000000);
+}
+
+// in millisecond
+time_t get_time_in_millisecond() {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+ LOGE("get_time_in_millisecond failed reason=[%s]", strerror(errno));
+ return -1;
+ }
+ return ((long long)ts.tv_sec*1000) + ((long long)ts.tv_nsec/1000000);
+}
+
+/*************************************************
+* Timer
+**************************************************/
+// -1 means failure
+//NULL means fail or timerid is returned
+timer_t timer_init(timer_routine cb, int id) {
+ struct sigevent sevp;
+ timer_t timerid;
+
+ memset(&sevp, 0, sizeof(sevp));
+ sevp.sigev_value.sival_int = id;
+ sevp.sigev_notify = SIGEV_THREAD;
+ sevp.sigev_notify_function = (void*)cb;
+
+ if(timer_create(CLOCK_BOOTTIME, &sevp, &timerid) == -1) {
+ LOGE("timer_init() timer_create() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return NULL;
+ }
+ return timerid;
+}
+
+bool timer_deinit(timer_t timerid) {
+ if(timer_delete(timerid) == -1) {
+ LOGE("timer_deinit() timer_delete() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool timer_start(timer_t timerid, int milliseconds) {
+ struct itimerspec expire;
+ expire.it_interval.tv_sec = 0;
+ expire.it_interval.tv_nsec = 0;
+ expire.it_value.tv_sec = milliseconds/1000;
+ expire.it_value.tv_nsec = (milliseconds%1000)*1000000;
+ if(timer_settime(timerid, 0, &expire, NULL) == -1) {
+ LOGE("timer_start() timer_settime() failed, reason=[%s]%d", strerror(errno), errno);
+ return false;
+ }
+ return true;
+}
+
+bool timer_stop(timer_t timerid) {
+ return timer_start(timerid, 0);
+}
+
+//-1 means fail or the remaining time is returned
+int64_t timer_get_remaining_time(timer_t timerid) {
+ struct itimerspec ts;
+ if(timer_gettime(timerid, &ts) == -1) {
+ LOGE("timer_get_remaining_time() timer_gettime() failed, reason=[%s]%d", strerror(errno), errno);
+ return -1;
+ }
+ return ((int64_t)ts.it_value.tv_sec * 1000 + ts.it_value.tv_nsec / 1000000);
+}
+
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int epoll_add_fd(int epfd, int fd) {
+ struct epoll_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.data.fd = fd;
+ ev.events = EPOLLIN;
+ // 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_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+ strerror(errno), errno, epfd, fd);
+ return -1;
+ }
+ return 0;
+}
+
+// -1 failed
+int 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 epoll_del_fd(int epfd, int fd) {
+ struct epoll_event ev;
+ int ret;
+
+ if (epfd == -1)
+ return -1;
+
+ ev.events = EPOLLIN;
+ ev.data.fd = fd;
+ do {
+ ret = epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev);
+ } while (ret < 0 && errno == EINTR);
+ return ret;
+}
+
+// -1 failed
+int epoll_mod_fd(int epfd, int fd, uint32_t events) {
+ struct epoll_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.data.fd = fd;
+ ev.events = events;
+ if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1) {
+ LOGE("epoll_mod_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+ strerror(errno), errno, epfd, fd);
+ return -1;
+ }
+ return 0;
+}
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int 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\n", 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(path);
+
+ if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ LOGE("socket_bind_udp() bind() failed path=[%s] reason=[%s]%d",
+ addr.sun_path+1, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }else
+ LOGI("bind ok path=[%s]", addr.sun_path+1);
+ return fd;
+}
+
+// -1 means failure
+int socket_set_blocking(int fd, int blocking) {
+ if (fd < 0) {
+ LOGE("socket_set_blocking() invalid fd=%d", fd);
+ return -1;
+ }
+
+ int flags = fcntl(fd, F_GETFL, 0);
+ if (flags == -1) {
+ LOGE("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;
+}
+
+// -1 means failure
+int 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) {
+ LOGE("errno==EINTR\n");
+ continue;
+ }
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ LOGE("errno==EAGAIN\n");
+ continue;
+ }
+ }
+ LOGE("safe_sendto() sendto() failed path=[%s] ret=%d reason=[%s]%d",
+ path, ret, strerror(errno), errno);
+ break;
+ }
+
+ close(fd);
+ return ret;
+}
+
+// -1 means failure
+int safe_recvfrom(int fd, char* buff, int len) {
+ int ret = 0;
+ int retry = 10;
+ 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;
+ }
+
+ while ((ret = recvfrom(fd, buff, len, 0,
+ NULL, NULL)) == -1) {
+ LOGW("safe_recvfrom() ret=%d len=%d", ret, len);
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("safe_recvfrom() recvfrom() failed reason=[%s]%d",
+ strerror(errno), errno);
+ break;
+ }
+ return ret;
+}
+
+/******************************************************************************
+* Socket
+******************************************************************************/
+
+//-1 means fail or serverfd is returned
+int socket_tcp_server_bind_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("socket_tcp_server_bind_local() unlink() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(fd == -1) {
+ LOGE("socket_tcp_server_bind_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(bind(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("socket_tcp_server_bind_local() bind() failed, abstruct=%d name=[%s] reason=[%s]%d",
+ abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ if(listen(fd, 5) == -1) {
+ LOGW("socket_tcp_server_bind_local() listen() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ return fd;
+}
+
+//-1 means fail or new clientfd is returned
+int socket_tcp_server_new_connect(int serverfd) {
+ int newfd;
+ struct sockaddr_in addr;
+ socklen_t len = sizeof(addr);
+
+ newfd = accept(serverfd, (struct sockaddr*)&addr, &len);
+ if(newfd == -1) {
+ LOGE("socket_tcp_server_new_connect() accept() failed, serverfd=%d reason=[%s]%d",
+ serverfd, strerror(errno), errno);
+ return -1;
+ }
+ return newfd;
+}
+
+//-1 means fail or serverfd is returned
+int 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("socket_tcp_client_connect_local() unlink() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(fd == -1) {
+ LOGE("socket_tcp_client_connect_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(connect(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("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;
+}
+
+
+//-1 means fail or serverfd is returned
+int socket_udp_server_bind_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("socket_udp_server_bind_local() unlink() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ LOGE("socket_udp_server_bind_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(bind(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("socket_udp_server_bind_local() bind() failed, abstract=%d name=[%s] reason=[%s]%d",
+ abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+//-1 means fail or clientfd is returned
+int socket_udp_client_create_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));
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ LOGE("socket_udp_client_create_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(connect(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("socket_udp_client_create_local() connect() failed, abstract=%d name=[%s] reason=[%s]%d",
+ abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+bool socket_udp_exist_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));
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ LOGE("socket_udp_is_bind_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return false;
+ }
+ if(connect(fd, (struct sockaddr*)&addr, size) == -1) {
+ close(fd);
+ return false;
+ }
+ close(fd);
+ return true;
+
+}
+
+void geofenceadp_timer_handler_protection(int id) {
+ LOGE("geofenceadp_timer_handler_protection() timeout");
+}
+
+void geofenceadp_add_geofence(void)
+{
+ mtk_geofence_property fence;
+ int fence_id;
+ memset(&fence, 0, sizeof(fence));
+ fence.latitude = 24.123456;
+ fence.longitude = 121.012345;
+ fence.radius = 200.0;
+ fence.latest_state = GEOFENCE_UNKNOWN;
+ fence.monitor_transition = MTK_GEOFENCE_ENTER;
+ fence.unknown_timer = 100000;
+ fence_id = geofenceinf_add_geofence(&fence);
+ LOGD("geofenceadp_add_geofence success id=%d", fence_id);
+}
+
+void geofenceadp_delete_geofence(int id)
+{
+ if (geofenceinf_remove_geofence(id) < 0){
+ LOGE("geofenceadp_delete_geofence fail:%d", id);
+ } else {
+ LOGD("geofenceadp_delete_geofence success:%d", id);
+ }
+}
+
+void geofenceadp_clear_geofence(void)
+{
+ if (geofenceinf_clear_geofences() < 0){
+ LOGE("geofenceadp_clear_geofence fail");
+ } else {
+ LOGD("geofenceadp_clear_geofence success");
+ }
+}
+
+void geofenceadp_query_geofence_num(void)
+{
+ int fence_num;
+ fence_num = geofenceinf_query_geofences_num();
+ LOGD("geofenceadp_query_geofence_num success number=%d", fence_num);
+}
+
+void geofenceadp_std_handler_process(char *buffer) {
+ char buff[1024];
+
+ MNLD_STRNCPY(buff, buffer, sizeof(buff));
+ if (strncmp(buff, "addfence", strlen("addfence")) == 0){
+ geofenceadp_add_geofence();
+ } else if (strncmp(buff, "clearfence", strlen("clearfence")) == 0){
+ geofenceadp_clear_geofence();
+ } else if (strncmp(buff, "queryfence", strlen("queryfence")) == 0){
+ geofenceadp_query_geofence_num();
+ } else if (strncmp(buff, "delfence", strlen("delfence")) == 0){
+ int id;
+ id = atoi(&buff[9]);
+ geofenceadp_delete_geofence(id);
+ }
+}
+
+void geofenceadp_connection_broken()
+{
+ LOGD("geofenceadp_connection_broken");
+}
+
+void geofenceadp_fence_alert(mtk_geofence_alert *alert)
+{
+ LOGD("geofenceadp_fence_alert");
+}
+
+void geofenceadp_tracking_status(mtk_gnss_tracking_status *status)
+{
+ LOGD("geofenceadp_tracking_status");
+}
+
+void geofenceadp_capability_update(mtk_geofence_server_capability *cap)
+{
+ LOGD("geofenceadp_capability_update server capability update");
+}
+
+static mtk_geofence_callback geofence_callbacks = {
+ geofenceadp_connection_broken,
+ geofenceadp_fence_alert,
+ geofenceadp_tracking_status,
+ geofenceadp_capability_update
+};
+
+
+//--------------------------------------------------------------------------------------------------------
+
+void geofenceadp_epoll_client_disconnect_server(int fd) {
+ LOGD("geofenceadp_epoll_client_disconnect_server fd=%d", fd);
+ epoll_del_fd(epfd, fd);
+}
+
+int geofenceadp_epoll_stdin_hdlr(int fd) {
+ char buff[2048] = {0};
+ int ret = read(fd, buff, sizeof(buff));
+ if(ret == -1) {
+ LOGE("STDIN read() failed, fd=%d reason=[%s]%d", fd, strerror(errno), errno);
+ return -1;
+ }
+ LOGD("stdin has data [%s]", buff);
+ geofenceadp_std_handler_process(buff);
+
+ return 0;
+}
+
+void geofencedp_mock_start() {
+ LOGD("gnssadp_mock_start() ver=%s", GEOFENCEADP_VERSION);
+
+ //memset(&client_ctx, 0, sizeof(geofence_client_ctx));
+
+ tcp_client_fd = geofenceinf_client_register(GEOFENCE_USER_NAME, &geofence_callbacks);
+ if(tcp_client_fd == -1) {
+ LOGE("socket_tcp_client_connect_local(true, GEOFENCEADP_MNL_SOCKET) failed");
+ exit(1);
+ } else {
+ mtk_geofence_client_capability client_cap;
+ client_cap.geofence_support = true;
+ geofenceinf_client_capability_config(&client_cap);
+ }
+ g_handler_timer = timer_init(geofenceadp_timer_handler_protection, 0);
+
+ #define MAX_EPOLL_EVENT 10
+ struct epoll_event events[MAX_EPOLL_EVENT];
+ epfd = epoll_create(MAX_EPOLL_EVENT);
+ if(epfd == -1) {
+ LOGE("epoll_create() failed");
+ exit(1);
+ }
+
+ epoll_add_fd2(epfd, STDIN_FILENO, EPOLLIN);
+ epoll_add_fd2(epfd, tcp_client_fd, EPOLLIN);
+
+ while(true) {
+ int i, n;
+ n = epoll_wait(epfd, events, MAX_EPOLL_EVENT, -1);
+ if(n == -1) {
+ if(errno == EINTR) {
+ continue;
+ } else {
+ LOGE("epoll_wait() failed reason=[%s]%d", strerror(errno), errno);
+ exit(1);
+ }
+ }
+
+ for(i = 0; i < n; i++) {
+ int fd = events[i].data.fd;
+ timer_start(g_handler_timer, 30 * 1000);
+ if(fd == STDIN_FILENO) {
+ if(events[i].events & EPOLLIN) {
+ if (geofenceadp_epoll_stdin_hdlr(fd) == -1){
+ goto exit;
+ }
+ }
+ } else if(fd == tcp_client_fd) {
+ if(events[i].events & EPOLLIN) {
+ mnl2geofence_hdlr(fd, &geofence_callbacks);
+ }
+ } else {
+ LOGE("unexpected fd=%d coming", fd);
+ }
+ timer_stop(g_handler_timer);
+ }
+ }
+
+exit:
+ close(epfd);
+ close(tcp_client_fd);
+ timer_deinit(g_handler_timer);
+}
+
+int main() {
+ geofencedp_mock_start();
+ return 0;
+}
+
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;
+}
diff --git a/src/connectivity/gps/2.0/gnss_test/LICENSE b/src/connectivity/gps/2.0/gnss_test/LICENSE
new file mode 100644
index 0000000..77f59ed
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/src/connectivity/gps/2.0/gnss_test/Makefile b/src/connectivity/gps/2.0/gnss_test/Makefile
new file mode 100644
index 0000000..faf2872
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/Makefile
@@ -0,0 +1,80 @@
+#CC=gcc
+#CXX=g++
+
+SOURCE_DIR=..
+GPS_HAL_PATH=$(SOURCE_DIR)/gps_hal/
+
+ifneq ($(findstring __LIBMNL_SIMULATOR__, $(CFLAG)),)
+ USR_LIB_DIR=$(GPS_HAL_PATH)
+else
+ USR_LIB_DIR=/usr/lib/
+endif
+
+FLAGS=\
+ -g \
+ -Wall \
+ -fPIC \
+ -D__COMPILE_OPTION__ \
+ -D__LINUX_OS__ \
+
+# -m32 \
+
+CPPFLAGS=\
+ -std=c++11 \
+
+INCLUDE=\
+ -Imnld_client/inc \
+ -Imnld_fm/inc \
+ -I../gps_hal/inc \
+ -I../gps_hal/inc/hardware \
+ -I../gps_hal/mnldinf/inc \
+
+LIBS=\
+ -ldl \
+ -lrt \
+ -lpthread \
+ -lgnsshal \
+ -L$(GPS_HAL_PATH) \
+ -Wl,-rpath $(USR_LIB_DIR)
+
+$(warning libs=$(LIBS))
+
+CXXSRC=\
+
+CSRC_mnld_test=\
+ mnld_client/src/mnld_client.c \
+ mnld_client/src/mnld_client_gps_cb.c
+
+CSRC_fm_gnss=\
+ mnld_fm/src/mnld_fm.c \
+ mnld_fm/src/mnld_fm_gps_cb.c
+
+EXECUTABLE=mnld_test fm_gnss
+
+COBJS=$(CSRC:.c=.o)
+CXXOBJS=$(CXXSRC:.cpp=.o)
+
+all: $(EXECUTABLE)
+
+$(warning $(patsubst %.c,%.o,$(CSRC_mnld_test))...........................................)
+
+mnld_test: $(patsubst %.c,%.o,$(CSRC_mnld_test))
+ $(CC) $^ --sysroot=$(BB_SYSROOT_ADD) -I$(BB_SYSROOT_ADD)/usr/include/gps_hal $(LIBS) $(FLAGS) $(CPPFLAGS) -o $@
+
+fm_gnss: $(patsubst %.c,%.o,$(CSRC_fm_gnss))
+ $(CC) $^ --sysroot=$(BB_SYSROOT_ADD) -I$(BB_SYSROOT_ADD)/usr/include/gps_hal $(LIBS) $(FLAGS) $(CPPFLAGS) -o $@
+
+%.o : %.c
+ $(CC) -c $(FLAGS) -I$(BB_SYSROOT_ADD)/usr/include/gps_hal $(INCLUDE) -o $@ $^
+
+%.o : %.cpp
+ $(CC) -c $(FLAGS) $(INCLUDE) $(CPPFLAGS) -o $@ $^
+
+.PHONY: install clean
+install:
+ install -d $(DESTDIR)/${bindir}
+ install -m 0755 $(EXECUTABLE) $(DESTDIR)/${bindir}
+
+clean:
+ rm -f $(EXECUTABLE) rm -rf *.o
+ find ./ -name *.o | xargs rm -rf
diff --git a/src/connectivity/gps/2.0/gnss_test/atci_test/Makefile b/src/connectivity/gps/2.0/gnss_test/atci_test/Makefile
new file mode 100644
index 0000000..ee70192
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/atci_test/Makefile
@@ -0,0 +1,51 @@
+CC=gcc
+CXX=g++
+
+FLAGS=\
+ -g \
+ -Wall \
+ -D __COMPILE_OPTION__ \
+ -D __LINUX_OS__ \
+
+# -m32 \
+
+CPPFLAGS=\
+ -std=c++11 \
+
+INCLUDE=\
+ -I./utility/inc/ \
+
+LIBS=\
+ -ldl \
+ -lrt \
+ -lpthread \
+
+CXXSRC=\
+
+CSRC=\
+ gnss_atci_test.c \
+ ./utility/src/gnss_atci_data_coder.c \
+ ./utility/src/gnss_atci_utility.c \
+ ./utility/src/gnss_atci_log.c \
+ ./utility/src/gnss_atci_socket_data_coder.c \
+ ./utility/src/gnss_atci_socket_utils.c
+
+EXECUTABLE=gnss_atci_test
+COBJS=$(CSRC:.c=.o)
+CXXOBJS=$(CXXSRC:.cpp=.o)
+
+all: $(EXECUTABLE)
+
+$(EXECUTABLE): $(COBJS) $(CXXOBJS)
+ $(CC) $(COBJS) $(CXXOBJS) $(LIBS) $(FLAGS) $(CPPFLAGS) -o $@
+
+%.o : %.c
+ $(CC) -c $(FLAGS) $(INCLUDE) -o $@ $<
+
+%.o : %.cpp
+ $(CC) -c $(FLAGS) $(INCLUDE) $(CPPFLAGS) -o $@ $<
+
+.PHONY: clean
+clean:
+ rm -f $(EXECUTABLE) rm -rf *.o
+ rm -rf $(COBJS)
\ No newline at end of file
diff --git a/src/connectivity/gps/2.0/gnss_test/atci_test/gnss_atci_test.c b/src/connectivity/gps/2.0/gnss_test/atci_test/gnss_atci_test.c
new file mode 100644
index 0000000..02f5955
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/atci_test/gnss_atci_test.c
@@ -0,0 +1,179 @@
+#include <stdio.h> /* Standard input/output definitions */
+#include <stdbool.h> /* Standard bool true/false definitions */
+#include <string.h> /* String function definitions */
+#include <unistd.h> /* UNIX standard function definitions */
+#include <fcntl.h> /* File control definitions */
+#include <errno.h> /* Error number definitions */
+#include <termios.h> /* POSIX terminal control definitions */
+#include <time.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/epoll.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <strings.h>
+#include <semaphore.h>
+
+#include "gnss_atci_log.h"
+#include "gnss_atci_utility.h"
+#include "gnss_atci_socket_utils.h"
+#include "gnss_atci_socket_data_coder.h"
+
+#define GNSS_ATCI_UDP_ADDR "/data/server"
+
+#define PRINT_TITLE(...) { printf("\E[0;30;43m"); printf(__VA_ARGS__); printf("\E[0m"); fflush(stdout); }
+#define PRINT_RAW(...) { printf(__VA_ARGS__); fflush(stdout);}
+
+#define GNSS_ATCI_INTERFACE_BUFF_SIZE (80*1024)
+#define GNSS_ATCI_PATH_SIZE (256)
+
+typedef enum {
+ GNSS_ATCI_OPEN_LOG = 0,
+ GNSS_ATCI_CLOSE_LOG = 1,
+ GNSS_ATCI_WRITE_LOG = 2,
+} gnss_atci_msg_id;
+
+typedef struct {
+ char* sock_addr;
+}log_db;
+
+log_db gnss_atci_db;
+
+typedef struct {
+ bool (*create_logfile)(const char* path);
+ bool (*write_logdata)(char* data, int len);
+ bool (*close_logfile)();
+} gnss_atci_inf;
+
+static bool gnss_atci_handle_open_logfile(const char* file_name) {
+ time_t tm;
+ struct tm *p = NULL;
+ char full_file_name[256] = {0};
+
+ if (time(&tm)==((time_t)-1)) {
+ LOGE("time() fail(%s)!!\r\n", strerror(errno));
+ }
+ p = localtime(&tm);
+
+ if(p == NULL) {
+ LOGE("Get localtime fail:[%s]%d", strerror(errno), errno);
+ return false;
+ }
+
+ snprintf(full_file_name, sizeof(full_file_name), "%s_%04d_%02d%02d_%02d%02d%02d", file_name,
+ 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday,
+ p->tm_hour, p->tm_min, p->tm_sec);
+
+ PRINT_RAW("\r\n==============GPSLog start, %s=============\r\n", full_file_name);
+ return true;
+}
+
+static bool gnss_atci_handle_write_logdata(char* data, int len) {
+ PRINT_RAW("%s", data);
+ return true;
+}
+
+static bool gnss_atci_handle_close_logfile() {
+ PRINT_RAW("\r\n==============GPSLog end=============\r\n");
+ return true;
+}
+
+static gnss_atci_inf gnss_atci_handler_interface = {
+ gnss_atci_handle_open_logfile,
+ gnss_atci_handle_write_logdata,
+ gnss_atci_handle_close_logfile
+};
+
+char gnss_atci_buff[GNSS_ATCI_INTERFACE_BUFF_SIZE] = {0};
+
+static bool gnss_atci_hdlr(int fd, gnss_atci_inf* hdlr) {
+ int offset = 0;
+
+ gnss_atci_msg_id cmd;
+ int ptype;
+ int log_type;
+ int read_len = 0;
+ bool ret = true;
+
+ if (NULL == hdlr) {
+ LOGE("gnss_atci_hdlr, hdlr not valid");
+ return false;
+ }
+
+ if (fd < 0) {
+ LOGE("gnss_atci_hdlr, fd not valid");
+ return false;
+ }
+ memset(gnss_atci_buff, 0, sizeof(gnss_atci_buff));
+ read_len = gnss_atci_safe_recvfrom(fd, gnss_atci_buff, sizeof(gnss_atci_buff)-1);
+ if (read_len <= 0) {
+ LOGE("gnss_atci_hdlr() gnss_atci_safe_recv() failed read_len=%d", read_len);
+ return false;
+ }
+
+ hdlr->write_logdata(gnss_atci_buff, strlen(gnss_atci_buff));
+
+ return ret;
+}
+
+#define GNSS_AT_CMD "AT%GNSS=fm"
+
+int main(int argc, char** argv) {
+ #define EPOLL_MAX_NUM 4
+ int sock_fd = -1;
+ int i = 0;
+ int n = 0;
+ int epfd = epoll_create(EPOLL_MAX_NUM);
+ struct epoll_event events[EPOLL_MAX_NUM];
+
+ sock_fd = gnss_atci_socket_create(GNSS_ATCI_UDP_ADDR, SOCK_NS_ABSTRACT);
+
+ if (sock_fd < 0) {
+ LOGE("gnss_atci_write_thread create sock_fd failed, reason=[%s]", strerror(errno));
+ return 0;
+ }
+
+ if(argc >= 2) {
+ gnss_atci_send(sock_fd, argv[1], strlen(argv[1]));
+ //safe_sendto(GNSS_ATCI_UDP_ADDR, argv[1], strlen(argv[1]));
+ } else {
+ gnss_atci_send(sock_fd, GNSS_AT_CMD, strlen(GNSS_AT_CMD));
+ // safe_sendto(GNSS_ATCI_UDP_ADDR, GNSS_AT_CMD, strlen(GNSS_AT_CMD));
+ }
+
+ if (gnss_atci_epoll_add_fd(epfd, sock_fd) == -1) {
+ LOGE("gnss_atci_write_thread failed for fd_hal failed, reason=[%s]", strerror(errno));
+ return 0;
+ }
+
+ while (1) {
+ n = epoll_wait(epfd, events, EPOLL_MAX_NUM , -1);
+ if (-1 == n) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ LOGE("gnss_atci_write_thread epoll_wait failure reason=[%s]", strerror(errno));
+ return 0;
+ }
+ }
+ for (i = 0; i < n; i++) {
+ if (events[i].data.fd == sock_fd) {
+ if (events[i].events & EPOLLIN) {
+ if (!gnss_atci_hdlr(sock_fd, &gnss_atci_handler_interface)) {
+ LOGE("gnss_atci_hdlr failure reason=[%s]", strerror(errno));
+ }
+ }
+ } else {
+ LOGE("mnld_main_thread() unknown sock_fd=%d", events[i].data.fd);
+ }
+ }
+ }
+ LOGE("gnss_atci_write_thread exit");
+ return 0;
+}
diff --git a/src/connectivity/gps/2.0/gnss_test/atci_test/utility/inc/gnss_atci_log.h b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/inc/gnss_atci_log.h
new file mode 100644
index 0000000..f9acb29
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/inc/gnss_atci_log.h
@@ -0,0 +1,194 @@
+/*
+* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2017. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*/
+#ifndef MTK_MNLD_LOG_H
+#define MTK_MNLD_LOG_H
+
+/**
+ * @enum LOG_LEVEL
+ * @brief Define Log Level
+ */
+typedef enum {
+ L_VERBOSE = 0, L_DEBUG, L_INFO, L_WARN, L_ERROR, L_ASSERT, L_SUPPRESS
+} LOG_LEVEL;
+
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+#ifdef LOGD
+#undef LOGD
+#endif
+#ifdef LOGW
+#undef LOGW
+#endif
+#ifdef LOGE
+#undef LOGE
+#endif
+
+#ifndef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "gpslog"
+#endif
+
+#include <string.h>
+
+int set_log_level(int *dst_level, int src_level);
+#define LOG_IS_ENABLED(level) (L_DEBUG <= level)
+
+#define FILE_NAME(x) strrchr(x, '/')?strrchr(x, '/') + 1 : x
+
+#if defined(__ANDROID_OS__)
+
+//#define ANDROID_MNLD_PROP_SUPPORT 1
+
+#include <cutils/sockets.h>
+#include <log/log.h> /*logging in logcat*/
+#include <cutils/android_filesystem_config.h>
+#if defined(__ANDROID_OS__)
+#include <cutils/properties.h>
+#endif
+
+#include "mtk_prop_util.h"
+
+#define PRINT_LOG(loglevel, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ switch (loglevel){\
+ case L_ASSERT:\
+ {\
+ ALOG_ASSERT("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_ERROR:\
+ {\
+ ALOGE("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_WARN:\
+ {\
+ ALOGW("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_INFO:\
+ {\
+ ALOGI("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_DEBUG:\
+ {\
+ ALOGD("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_VERBOSE:\
+ {\
+ ALOGV("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ }\
+ }\
+ } while (0)
+
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, fmt, ##args)
+
+#define TRC(f) ALOGD("%s", __func__)
+
+#elif defined(__LINUX_OS__)
+
+#include <stdio.h>
+//#define ANDROID_MNLD_PROP_SUPPORT 0
+
+
+char time_buff[64];
+int get_time_str(char* buf, int len);
+
+#ifndef gettid
+#include <unistd.h>
+#include <sys/syscall.h>
+#define gettid() syscall(__NR_gettid)
+#define getpid() syscall(__NR_getpid)
+#endif
+
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ get_time_str(time_buff, sizeof(time_buff));\
+ printf("%ld %ld [%s]" LOG_TAG tag "%s %s %d " fmt "\n",\
+ getpid(), gettid(),time_buff, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ fflush(stdout);\
+ }\
+ } while (0)
+
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, "[ASSERT]: ", fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, "[ERROR]: ", fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, "[WARNING]: ", fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, "[INFO]: ", fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, "[DEBUG]: ", fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, "[VERBOSE]: ", fmt, ##args)
+
+#define TRC(f) ((void)0)
+
+#elif defined(__TIZEN_OS__)
+
+#include <dlog/dlog.h>
+
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ dlog_print(DLOG_DEBUG, fmt "\n", ##args);\
+ printf(fmt "\n", ##args);
+ fflush(stdout);\
+ }\
+ } while (0)
+
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, "[ASSERT]: ", fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, "[ERROR]: ", fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, "[WARNING]: ", fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, "[INFO]: ", fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, "[DEBUG]: ", fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, "[VERBOSE]: ", fmt, ##args)
+
+#endif
+#define CONFIG_GPS_ENG_LOAD
+#ifdef CONFIG_GPS_ENG_LOAD
+#define LOGD_ENG(fmt, arg ...) LOGD( fmt, ##arg)
+#else
+#define LOGD_ENG(fmt, arg ...) NULL
+#endif
+
+#endif
diff --git a/src/connectivity/gps/2.0/gnss_test/atci_test/utility/inc/gnss_atci_socket_data_coder.h b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/inc/gnss_atci_socket_data_coder.h
new file mode 100644
index 0000000..7f069a4
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/inc/gnss_atci_socket_data_coder.h
@@ -0,0 +1,52 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __DATA_CODER_H__
+#define __DATA_CODER_H__
+
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool mtk_socket_get_bool(char* buff, int* offset);
+char mtk_socket_get_char(char* buff, int* offset);
+short mtk_socket_get_short(char* buff, int* offset);
+int gnss_atci_socket_get_int(char* buff, int* offset);
+int64_t mtk_socket_get_int64_t(char* buff, int* offset);
+float mtk_socket_get_float(char* buff, int* offset);
+double mtk_socket_get_double(char* buff, int* offset);
+int gnss_atci_socket_get_string(char* buff, int* offset, char* output, int max_size);
+int mtk_socket_get_bool_array(char* buff, int* offset, bool output[], int max_size);
+int mtk_socket_get_char_array(char* buff, int* offset, char output[], int max_size);
+int mtk_socket_get_short_array(char* buff, int* offset, short output[], int max_size);
+int mtk_socket_get_int_array(char* buff, int* offset, int output[], int max_size);
+int mtk_socket_get_int64_t_array(char* buff, int* offset, int64_t output[], int max_size);
+int mtk_socket_get_float_array(char* buff, int* offset, float output[], int max_size);
+int mtk_socket_get_double_array(char* buff, int* offset, double output[], int max_size);
+int mtk_socket_get_string_array(char* buff, int* offset, void* output, int max_size1, int max_size2);
+
+void mtk_socket_put_bool(char* buff, int* offset, bool input);
+void mtk_socket_put_char(char* buff, int* offset, char input);
+void mtk_socket_put_short(char* buff, int* offset, short input);
+void mtk_socket_put_int(char* buff, int* offset, int input);
+void mtk_socket_put_int64_t(char* buff, int* offset, int64_t input);
+void mtk_socket_put_float(char* buff, int* offset, float input);
+void mtk_socket_put_double(char* buff, int* offset, double input);
+void mtk_socket_put_string(char* buff, int* offset, const char* input);
+void mtk_socket_put_bool_array(char* buff, int* offset, bool input[], int size);
+void mtk_socket_put_char_array(char* buff, int* offset, char input[], int size);
+void mtk_socket_put_short_array(char* buff, int* offset, short input[], int size);
+void mtk_socket_put_int_array(char* buff, int* offset, int input[], int size);
+void mtk_socket_put_int64_t_array(char* buff, int* offset, int64_t input[], int size);
+void mtk_socket_put_float_array(char* buff, int* offset, float input[], int size);
+void mtk_socket_put_double_array(char* buff, int* offset, double input[], int size);
+void mtk_socket_put_string_array(char* buff, int* offset, void* input, int size1, int size2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/gnss_test/atci_test/utility/inc/gnss_atci_socket_utils.h b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/inc/gnss_atci_socket_utils.h
new file mode 100644
index 0000000..c47109f
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/inc/gnss_atci_socket_utils.h
@@ -0,0 +1,41 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __MTK_SOCKET_UTILS_H__
+#define __MTK_SOCKET_UTILS_H__
+
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <pthread.h>
+
+#include "gnss_atci_log.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ SOCK_NS_ABSTRACT = 0,
+ SOCK_NS_FILESYSTEM = 1,
+} mtk_socket_namespace;
+
+
+#define SOCK_LOGD(fmt, arg ...) LOGD(fmt, ##arg)
+#define SOCK_LOGW(fmt, arg ...) LOGW( fmt, ##arg)
+#define SOCK_LOGE(fmt, arg ...) LOGE(fmt, ##arg)
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int gnss_atci_socket_server_bind_local(const char* path, mtk_socket_namespace sock_namespace);
+int gnss_atci_safe_recv(int fd, char* buff, int len);
+void gnss_atci_send(int fd, const char* ack, int len);
+int gnss_atci_socket_create(const char* path, mtk_socket_namespace sock_namespace);
+int safe_sendto(const char* path, const char* buff, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/gnss_test/atci_test/utility/inc/gnss_atci_utility.h b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/inc/gnss_atci_utility.h
new file mode 100644
index 0000000..651a78d
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/inc/gnss_atci_utility.h
@@ -0,0 +1,74 @@
+#ifndef __MTK_LBS_UTILITY_H__
+#define __MTK_LBS_UTILITY_H__
+
+#include <time.h>
+#include <sys/time.h>
+#include <stdint.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdbool.h> /* Standard bool true/false definitions */
+
+#include "gnss_atci_log.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************
+* Basic Utilities
+**************************************************/
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+#define DUMP_BYTES_PER_LINE 16
+#define DUMP_MAX_PRINT_LINE 10
+
+#define GPSLOG_DUMP_MEM(addr, len) do{\
+ int i = 0, j = 0;\
+ char print_buf[DUMP_BYTES_PER_LINE*5+1] = {0};\
+ unsigned int print_len = len;\
+ if(len > DUMP_MAX_PRINT_LINE*DUMP_BYTES_PER_LINE) {\
+ print_len = DUMP_MAX_PRINT_LINE*DUMP_BYTES_PER_LINE;\
+ }\
+ LOGD(">>>>>DUMP_START(addr:%p, len:%d, print_len:%ud)<<<<<", addr, len,print_len);\
+ for(i = 0; i < print_len; i+=DUMP_BYTES_PER_LINE) {\
+ memset(print_buf, 0, sizeof(print_buf));\
+ for(j=0;j<DUMP_BYTES_PER_LINE;j++) {\
+ sprintf(&print_buf[j*5], "0x%02x ", ((char *)addr)[i*DUMP_BYTES_PER_LINE+j]);\
+ print_buf[DUMP_BYTES_PER_LINE*5] = '\0';\
+ }\
+ LOGD("[%3d]:%s", i/DUMP_BYTES_PER_LINE, print_buf);\
+ }\
+ LOGD("<<<<<DUMP_STOP>>>>>");\
+}while(0)
+
+
+#define MNLD_STRNCPY(dst,src,size) do{\
+ strncpy((char *)(dst), (src), (size - 1));\
+ (dst)[size - 1] = '\0';\
+ }while(0)
+
+// -1 means failure
+int gnss_atci_block_here();
+
+//exit block_here() and process will exit and restart
+void gnss_atci_block_exit(void);
+
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int gnss_atci_epoll_add_fd(int epfd, int fd);
+
+
+/*************************************************
+* string operation
+**************************************************/
+char *safe_strncpy(char *dest, const char *src, size_t n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_data_coder.c b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_data_coder.c
new file mode 100644
index 0000000..ab67b38
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_data_coder.c
@@ -0,0 +1,154 @@
+#include <string.h>
+
+#ifndef MAX
+#define MAX(A,B) ((A)>(B)?(A):(B))
+#endif
+#ifndef MIN
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#endif
+
+//===============================================================
+// get
+char get_byte(char* buff, int* offset, int src_len) {
+ char ret = 0;
+ if (*offset >= 0 && *offset < src_len) {
+ ret = buff[*offset];
+ *offset += 1;
+ }
+ return ret;
+}
+
+short get_short(char* buff, int* offset, int src_len) {
+ short ret = 0;
+ ret |= get_byte(buff, offset, src_len) & 0xff;
+ ret |= (get_byte(buff, offset, src_len) << 8);
+ return ret;
+}
+
+int get_int(char* buff, int* offset, int src_len) {
+ int ret = 0;
+ ret |= get_short(buff, offset, src_len) & 0xffff;
+ ret |= (get_short(buff, offset, src_len) << 16);
+ return ret;
+}
+
+long long get_long(char* buff, int* offset, int src_len) {
+ long long ret = 0;
+ ret |= get_int(buff, offset, src_len) & 0xffffffffL;
+ ret |= ((long long)get_int(buff, offset, src_len) << 32);
+ return ret;
+}
+
+float get_float(char* buff, int* offset, int src_len) {
+ float ret;
+ int tmp = get_int(buff, offset, src_len);
+ ret = *((float*)&tmp);
+ return ret;
+}
+
+double get_double(char* buff, int* offset, int src_len) {
+ double ret;
+ long long tmp = get_long(buff, offset, src_len);
+ ret = *((double*)&tmp);
+ return ret;
+}
+
+char* get_string(char* buff, int* offset, int src_len) {
+ char ret = get_byte(buff, offset, src_len);
+ if (ret == 0) {
+ return NULL;
+ } else {
+ char* p = NULL;
+ int len = get_int(buff, offset, src_len);
+ if (*offset < 0 || *offset >= src_len) {
+ *offset = 0;
+ }
+ if ((len > src_len - *offset) || len < 0) {
+ len = src_len - *offset;
+ }
+ if (len <= 0) {
+ return NULL;
+ }
+ p = &buff[*offset];
+ p[len-1] = 0;
+ *offset += len;
+ return p;
+ }
+}
+
+char* get_string2(char* buff, int* offset, int src_len) {
+ char* output = get_string(buff, offset, src_len);
+ if (output == NULL) {
+ return "";
+ } else {
+ return output;
+ }
+}
+
+int get_binary(char* buff, int* offset, char* output, int src_len, int des_len) {
+ int len = 0;
+ if (*offset >= 0 && *offset <= src_len) {
+ len = get_int(buff, offset, src_len);
+ if (len > MIN((src_len-(*offset)), des_len)) {
+ len = MIN((src_len-(*offset)), des_len);
+ }
+ if (len > 0) {
+ memcpy(output, &buff[*offset], len);
+ *offset += len;
+ }
+ }
+ return len;
+}
+
+//===============================================================
+// put
+void put_byte(char* buff, int* offset, const char input) {
+ *((char*)&buff[*offset]) = input;
+ *offset += 1;
+}
+
+void put_short(char* buff, int* offset, const short input) {
+ put_byte(buff, offset, input & 0xff);
+ put_byte(buff, offset, (input >> 8) & 0xff);
+}
+
+void put_int(char* buff, int* offset, const int input) {
+ put_short(buff, offset, input & 0xffff);
+ put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void put_long(char* buff, int* offset, const long long input) {
+ put_int(buff, offset, input & 0xffffffffL);
+ put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void put_float(char* buff, int* offset, const float input) {
+ int* data = (int*)&input;
+ put_int(buff, offset, *data);
+}
+
+void put_double(char* buff, int* offset, const double input) {
+ long long* data = (long long*)&input;
+ put_long(buff, offset, *data);
+}
+
+void put_string(char* buff, int* offset, const char* input) {
+ if (input == NULL) {
+ put_byte(buff, offset, 0);
+ } else {
+ int len = strlen(input) + 1;
+ put_byte(buff, offset, 1);
+ put_int(buff, offset, len);
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+ }
+}
+
+void put_binary(char* buff, int* offset, const char* input, const int len) {
+ put_int(buff, offset, len);
+ if (len > 0) {
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+ }
+}
+
diff --git a/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_log.c b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_log.c
new file mode 100644
index 0000000..6e0a0d3
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_log.c
@@ -0,0 +1,125 @@
+/*
+* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2017. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*/
+#include <sys/time.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+#include <memory.h>
+
+#include "gnss_atci_log.h"
+
+#if defined(__LINUX_OS__)
+// -1 means failure
+int get_time_str(char* buf, int len) {
+#if 0 //Fix build error
+ struct timeval tv;
+ struct timezone tz;
+ struct tm *tm;
+
+ gettimeofday(&tv, &tz);
+ tm = localtime(&tv.tv_sec);
+
+ memset(buf, 0, len);
+ sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d.%03d",
+ tm->tm_year + 1900, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min,
+ tm->tm_sec, (int)(tv.tv_usec / 1000));
+
+ return 0;
+#else
+ time_t now = time(NULL);
+ struct tm tm_utc;
+ time_t time_utc;
+
+ gmtime_r(&now, &tm_utc);
+ time_utc = mktime(&tm_utc);
+
+ memset(buf, 0, len);
+ sprintf(buf, "%s", ctime(&time_utc));
+
+ buf[strlen(buf)-1] = '\0'; //Remove '\n'
+
+ return 0;
+#endif
+}
+#endif
+
+int set_log_level(int *dst_level, int src_level)
+{
+#if defined(__ANDROID_OS__)
+
+ ALOGI("Current debug level=%d", *dst_level);
+
+ if (src_level < L_VERBOSE || src_level > L_SUPPRESS)
+ {
+ ALOGE("Invalid debug level, level=%d", src_level);
+ ALOGE(" [level] -");
+ ALOGE(" QUIET = 6");
+ ALOGE(" ASSERT = 5");
+ ALOGE(" ERROR = 4");
+ ALOGE(" WARNING = 3");
+ ALOGE(" INFO = 2");
+ ALOGE(" DEBUG = 1");
+ ALOGE(" LOGALL = 0");
+ return -1;
+ }
+
+ *dst_level = src_level;
+
+ ALOGI("New debug level=%d", *dst_level);
+
+#elif defined(__LINUX_OS__)
+
+ printf("Current debug level=%d\n", *dst_level);
+
+ if (src_level < L_VERBOSE || src_level > L_SUPPRESS)
+ {
+ printf("Invalid debug level, level=%d", src_level);
+ printf(" [level] -");
+ printf(" QUIET = 6");
+ printf(" ASSERT = 5");
+ printf(" ERROR = 4");
+ printf(" WARNING = 3");
+ printf(" INFO = 2");
+ printf(" DEBUG = 1");
+ printf(" LOGALL = 0");
+ return -1;
+ }
+
+ *dst_level = src_level;
+
+ printf("New debug level=%d\n", *dst_level);
+
+#endif
+ return 0;
+}
diff --git a/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_socket_data_coder.c b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_socket_data_coder.c
new file mode 100644
index 0000000..a310d28
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_socket_data_coder.c
@@ -0,0 +1,256 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include "gnss_atci_socket_data_coder.h"
+
+bool mtk_socket_get_bool(char* buff, int* offset) {
+ bool ret = (mtk_socket_get_char(buff, offset) == 0)? false : true;
+ return ret;
+}
+
+char mtk_socket_get_char(char* buff, int* offset) {
+ char ret = buff[*offset];
+ *offset += 1;
+ return ret;
+}
+
+short mtk_socket_get_short(char* buff, int* offset) {
+ short ret = 0;
+ ret |= mtk_socket_get_char(buff, offset) & 0xff;
+ ret |= (mtk_socket_get_char(buff, offset) << 8);
+ return ret;
+}
+
+int gnss_atci_socket_get_int(char* buff, int* offset) {
+ int ret = 0;
+ ret |= mtk_socket_get_short(buff, offset) & 0xffff;
+ ret |= (mtk_socket_get_short(buff, offset) << 16);
+ return ret;
+}
+
+int64_t mtk_socket_get_int64_t(char* buff, int* offset) {
+ int64_t ret = 0;
+ ret |= gnss_atci_socket_get_int(buff, offset) & 0xffffffffL;
+ ret |= ((int64_t)gnss_atci_socket_get_int(buff, offset) << 32);
+ return ret;
+}
+
+float mtk_socket_get_float(char* buff, int* offset) {
+ float ret;
+ int tmp = gnss_atci_socket_get_int(buff, offset);
+ ret = *((float*)&tmp);
+ return ret;
+}
+
+double mtk_socket_get_double(char* buff, int* offset) {
+ double ret;
+ int64_t tmp = mtk_socket_get_int64_t(buff, offset);
+ ret = *((double*)&tmp);
+ return ret;
+}
+
+int gnss_atci_socket_get_string(char* buff, int* offset, char* output, int max_size) {
+ int size = gnss_atci_socket_get_int(buff, offset);
+ memset(output, 0, max_size);
+ memcpy(output, &buff[*offset], (size > max_size)? max_size : size);
+ output[max_size - 1] = 0;
+ *offset += size;
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_bool_array(char* buff, int* offset, bool output[], int max_size) {
+ int i = 0;
+ int size = gnss_atci_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ bool data = mtk_socket_get_bool(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_char_array(char* buff, int* offset, char output[], int max_size) {
+ int size = gnss_atci_socket_get_int(buff, offset);
+ memcpy(output, &buff[*offset], (size > max_size)? max_size : size);
+ *offset += size;
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_short_array(char* buff, int* offset, short output[], int max_size) {
+ int i = 0;
+ int size = gnss_atci_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ short data = mtk_socket_get_short(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_int_array(char* buff, int* offset, int output[], int max_size) {
+ int i = 0;
+ int size = gnss_atci_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ int data = gnss_atci_socket_get_int(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_int64_t_array(char* buff, int* offset, int64_t output[], int max_size) {
+ int i = 0;
+ int size = gnss_atci_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ int64_t data = mtk_socket_get_int64_t(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_float_array(char* buff, int* offset, float output[], int max_size) {
+ int i = 0;
+ int size = gnss_atci_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ float data = mtk_socket_get_float(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_double_array(char* buff, int* offset, double output[], int max_size) {
+ int i = 0;
+ int size = gnss_atci_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ double data = mtk_socket_get_double(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_string_array(char* buff, int* offset, void* output, int max_size1, int max_size2) {
+ int i = 0;
+ int size1 = gnss_atci_socket_get_int(buff, offset);
+ for(i = 0; i < size1; i++) {
+ if(i < max_size1) {
+ gnss_atci_socket_get_string(buff, offset, output, max_size2);
+ output = (char*)output + max_size2;
+ } else {
+ char tmp[max_size2];
+ gnss_atci_socket_get_string(buff, offset, tmp, max_size2);
+ }
+ }
+ return (size1 > max_size1)? max_size1 : size1;
+}
+
+void mtk_socket_put_bool(char* buff, int* offset, bool input) {
+ mtk_socket_put_char(buff, offset, input);
+}
+
+void mtk_socket_put_char(char* buff, int* offset, char input) {
+ *((char*)&buff[*offset]) = input;
+ *offset += 1;
+}
+
+void mtk_socket_put_short(char* buff, int* offset, short input) {
+ mtk_socket_put_char(buff, offset, input & 0xff);
+ mtk_socket_put_char(buff, offset, (input >> 8) & 0xff);
+}
+
+void mtk_socket_put_int(char* buff, int* offset, int input) {
+ mtk_socket_put_short(buff, offset, input & 0xffff);
+ mtk_socket_put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void mtk_socket_put_int64_t(char* buff, int* offset, int64_t input) {
+ mtk_socket_put_int(buff, offset, input & 0xffffffffL);
+ mtk_socket_put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void mtk_socket_put_float(char* buff, int* offset, float input) {
+ int* data = (int*)&input;
+ mtk_socket_put_int(buff, offset, *data);
+}
+
+void mtk_socket_put_double(char* buff, int* offset, double input) {
+ int64_t* data = (int64_t*)&input;
+ mtk_socket_put_int64_t(buff, offset, *data);
+}
+
+void mtk_socket_put_string(char* buff, int* offset, const char* input) {
+ int len = strlen(input);
+ mtk_socket_put_int(buff, offset, len);
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+}
+
+void mtk_socket_put_bool_array(char* buff, int* offset, bool input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_bool(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_char_array(char* buff, int* offset, char input[], int size) {
+ mtk_socket_put_int(buff, offset, size);
+ memcpy(&buff[*offset], input, size);
+ *offset += size;
+}
+
+void mtk_socket_put_short_array(char* buff, int* offset, short input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_short(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_int_array(char* buff, int* offset, int input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_int(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_int64_t_array(char* buff, int* offset, int64_t input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_int64_t(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_float_array(char* buff, int* offset, float input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_float(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_double_array(char* buff, int* offset, double input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_double(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_string_array(char* buff, int* offset, void* input, int size1, int size2) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size1);
+ for(i = 0; i < size1; i++) {
+ mtk_socket_put_string(buff, offset, (char*)input);
+ input = (char*)input + size2;
+ }
+}
+
diff --git a/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_socket_utils.c b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_socket_utils.c
new file mode 100644
index 0000000..699cd37
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_socket_utils.c
@@ -0,0 +1,214 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include "gnss_atci_socket_utils.h"
+#include "gnss_atci_socket_data_coder.h"
+#include "gnss_atci_utility.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h> //usleep
+#include <sys/socket.h>
+#include <string.h>
+#include <fcntl.h>
+#include <arpa/inet.h> //inet_addr
+#include <sys/un.h> //struct sockaddr_un
+#include <sys/epoll.h>
+#include <poll.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <inttypes.h>
+
+#if defined(__ANDROID_OS__)
+#include <cutils/log.h> // Android log
+
+#define ANDROID_LOG_TAG "mtk_socket"
+#endif
+
+char *safe_strncpy(char *dest, const char *src, size_t n) {
+ if (dest && n > 0) {
+ // Use strncat for performance because strncpy will always fill n bytes in dest
+ dest[0] = '\0'; // Let dest be an empty string
+ strncat(dest, src, --n); // n-1 because strncat may fill n+1 bytes
+ }
+ return dest;
+}
+
+struct sockaddr_un sock_addr;
+void gnss_atci_send(int fd, const char* ack, int len) {
+ int ret = 0;
+ int retry = 10;
+ while ((ret = sendto(fd, ack, len, 0,
+ (const struct sockaddr *)&sock_addr, sizeof(sock_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",
+ ret, strerror(errno), errno);
+ break;
+ }
+
+}
+
+//-1 means failure
+int gnss_atci_socket_server_bind_local(const char* path, mtk_socket_namespace sock_namespace) {
+ int size;
+ struct sockaddr_un addr;
+ //int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ int fd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ LOGE("mtk_socket_server_bind_local() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ size = strlen(path) + offsetof(struct sockaddr_un, sun_path) + 1;
+ if(sock_namespace == SOCK_NS_ABSTRACT) {
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, path, strlen(path));
+ } else if(sock_namespace == SOCK_NS_FILESYSTEM) {
+ safe_strncpy(addr.sun_path, path, sizeof(addr.sun_path));
+ unlink(addr.sun_path);
+ } else {
+ LOGE("mtk_socket_server_bind_local() unknown namespace=[%d]", sock_namespace);
+ close(fd);
+ return -1;
+ }
+ if (bind(fd, (struct sockaddr *)&addr, size) == -1) {
+ LOGE("mtk_socket_server_bind_local() bind() failed reason=[%s]%d for path=[%s]",
+ strerror(errno), errno, path);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+//-1 means failure
+int gnss_atci_socket_create(const char* path, mtk_socket_namespace sock_namespace) {
+ 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(&sock_addr, 0, sizeof(sock_addr));
+ sock_addr.sun_path[0] = 0;
+ MNLD_STRNCPY(sock_addr.sun_path + 1, path,sizeof(sock_addr.sun_path) - 1);
+ sock_addr.sun_family = AF_UNIX;
+
+ return fd;
+}
+
+int 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;
+}
+
+
+// -1 means failure
+int gnss_atci_safe_recvfrom(int fd, char* buff, int len) {
+ int ret = 0;
+ int retry = 10;
+
+ 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);
+ }
+
+ while ((ret = recvfrom(fd, buff, len, 0,
+ (const struct sockaddr *)&sock_addr, sizeof(sock_addr))) == -1) {
+ LOGW("gnss_atci_safe_recvfrom() ret=%d len=%d", ret, len);
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("gnss_atci_safe_recvfrom() recvfrom() failed reason=[%s]%d",
+ strerror(errno), errno);
+ break;
+ }
+ return ret;
+}
+
+int gnss_atci_safe_recv(int fd, char* buff, int len) {
+ int ret = 0;
+ int retry = 10;
+
+ while ((ret = read(fd, buff, len)) == -1) {
+ LOGW("mnldinf_safe_recvfrom() ret=%d len=%d", ret, len);
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("mnldinf_safe_recvfrom() recvfrom() failed reason=[%s]%d",
+ strerror(errno), errno);
+ break;
+ }
+ return ret;
+}
+
diff --git a/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_utility.c b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_utility.c
new file mode 100644
index 0000000..b0401bd
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/atci_test/utility/src/gnss_atci_utility.c
@@ -0,0 +1,75 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h> // usleep
+#include <sys/socket.h>
+#include <string.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 <sys/syscall.h>
+
+#if defined(__ANDROID_OS__)
+#include <cutils/log.h> // Android log
+#endif
+#include "gnss_atci_log.h"
+
+#include "gnss_atci_utility.h"
+//#include "gnss_atci_socket_utils.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "gnss_atci_utility"
+
+sem_t g_mnld_exit_sem;
+
+// -1 means failure
+int gnss_atci_block_here() {
+ if (sem_init(&g_mnld_exit_sem, 0, 0) == -1) {
+ LOGE("block_here() sem_init failure reason=%s\n", strerror(errno));
+ return -1;
+ }
+ sem_wait(&g_mnld_exit_sem);
+ if (sem_destroy(&g_mnld_exit_sem) == -1) {
+ LOGE("block_here() sem_destroy reason=%s\n", strerror(errno));
+ }
+ return 0;
+}
+
+void gnss_atci_block_exit(void) {
+ if(sem_post(&g_mnld_exit_sem) == -1) {
+ LOGE("sem_post failed");
+ _exit(0);
+ }
+}
+
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int gnss_atci_epoll_add_fd(int epfd, int fd) {
+ struct epoll_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.data.fd = fd;
+ ev.events = EPOLLIN;
+ // 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("gnss_atci_epoll_add_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+ strerror(errno), errno, epfd, fd);
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/connectivity/gps/2.0/gnss_test/make_gnss_test.sh b/src/connectivity/gps/2.0/gnss_test/make_gnss_test.sh
new file mode 100755
index 0000000..f057150
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/make_gnss_test.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+make clean && make CFLAG=-D__LIBMNL_SIMULATOR__ 2>&1 |tee build.log
diff --git a/src/connectivity/gps/2.0/gnss_test/mnld_client/inc/mnld_test.h b/src/connectivity/gps/2.0/gnss_test/mnld_client/inc/mnld_test.h
new file mode 100644
index 0000000..a49ba31
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/mnld_client/inc/mnld_test.h
@@ -0,0 +1,82 @@
+#ifndef __MNLD_TEST_H__
+#define __MNLD_TEST_H__
+
+#include"hal_mnl_interface_common.h"
+#include"hardware/gps_mtk.h"
+
+#define MNLD_TEST_CMD_OPEN "start"
+#define MNLD_TEST_CMD_CLOSE "stop"
+#define MNLD_TEST_CMD_NETWORK "network"
+#define MNLD_TEST_NETWORK_WIFI "wifi"
+#define MNLD_TEST_NETWORK_MOBILE "mobile"
+#define MNLD_TEST_NETWORK_ROAMING "roaming"
+#define MNLD_TEST_NETWORK_DISABLE "disable"
+
+#define MNL_VER_LEN 52
+#define MNL_UTC_TIME_LEN 11
+#define MNLD_TEST_TTFF_SESSION_BEGIN
+
+typedef enum{
+ MNLD_TEST_ACTION_UNKNOWN = -1,
+ MNLD_TEST_ACTION_GNSS_OPEN,
+ MNLD_TEST_ACTION_GNSS_CLOSE,
+ MNLD_TEST_ACTION_SET_NETWORK,
+ MNLD_TEST_ACTION_MAX
+} MNLD_TEST_ACTION;
+
+typedef enum{
+ MNLD_TEST_RESTART_TYPE_UNKNOWN = -1,
+ MNLD_TEST_RESTART_TYPE_HOT,
+ MNLD_TEST_RESTART_TYPE_WARM,
+ MNLD_TEST_RESTART_TYPE_COLD,
+ MNLD_TEST_RESTART_TYPE_FULL,
+ MNLD_TEST_RESTART_TYPE_MAX
+} MNLD_TEST_RESTART_TYPE;
+
+typedef enum{
+ CURR = 0,
+ MIN = 1,
+ MAX = 2,
+ MEAN = 3,
+ TTFF_NUM
+}MNLD_TEST_TTFF;
+
+typedef struct {
+ char chip_ver[12];
+ char mnl_ver[MNL_VER_LEN];
+ char clk_type;
+ char clk_buff;
+ int ttff[TTFF_NUM];//time-to-first_fix in ms
+ int fix_type;
+ GpsLocation_ext location;
+ char utc_time[MNL_UTC_TIME_LEN];
+}mnld_test_result;
+
+typedef struct{
+ char type_int;
+ char type_str[10];
+}clock_type;
+
+#define MNLD_TEST_CMD_CNT_MAX 5
+#define GPS_DELETE_EPHEMERIS 0x0001
+#define GPS_DELETE_ALMANAC 0x0002
+#define GPS_DELETE_POSITION 0x0004
+#define GPS_DELETE_TIME 0x0008
+#define GPS_DELETE_IONO 0x0010
+#define GPS_DELETE_UTC 0x0020
+#define GPS_DELETE_HEALTH 0x0040
+#define GPS_DELETE_SVDIR 0x0080
+#define GPS_DELETE_SVSTEER 0x0100
+#define GPS_DELETE_SADATA 0x0200
+#define GPS_DELETE_RTI 0x0400
+#define GPS_DELETE_CELLDB_INFO 0x8000
+#define GPS_DELETE_ALL 0xFFFF
+
+
+GpsCallbacks_ext* mnld_test__get_gps_callbacks(void);
+//GpsInterface* gps_device__get_gps_interface(struct gps_device_t* device);
+
+void mnld_test_show_test_result(mnld_test_result* result);
+void mnld_test_get_mnl_ver(void);
+
+#endif //__MNLD_TEST_H__
diff --git a/src/connectivity/gps/2.0/gnss_test/mnld_client/src/mnld_client.c b/src/connectivity/gps/2.0/gnss_test/mnld_client/src/mnld_client.c
new file mode 100644
index 0000000..8030a1b
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/mnld_client/src/mnld_client.c
@@ -0,0 +1,647 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <semaphore.h>
+#include "hal2mnl_interface.h"
+#include "hardware/gps_mtk.h"
+#include "mnld_test.h"
+#include "mtk_lbs_utility.h"
+#include "mnldinf_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnldtest"
+#endif
+int log_dbg_level = L_VERBOSE;
+
+#ifdef CONFIG_GPS_MT3303
+#define MNLD_TEST_CHIP_VER "MT3303"
+#else
+#define MNLD_TEST_CHIP_VER "MT6880"
+#endif
+#define MNLD_TEST_MNL_VER mnld_test_mnl_ver
+#define MNLD_TEST_CLOCK_TYPE 0xFF
+#define MNLD_TEST_CLOCK_BUFF 2
+
+/*Socket port nubmer*/
+#define PORT 7000
+/*The max length of socket receive buffer*/
+#define MNL_TEST_REC_BUFF_LEN 2048
+
+#define MNL_TEST_MNL_VER_PMTK "$PMTK705"
+#define mnld_test_printf printf
+
+GpsCallbacks_ext* mnld_test_cbs = NULL;
+GpsInterface_ext* mnld_test_gpsinfs = NULL;
+
+
+int valid_ttff_cnt = 0;
+int valid_ttff_sum = 0;
+
+int mnld_test_session_end = 0;
+int mnld_test_ttff = 0;
+int mnld_test_restart_cnt = 0;
+int mnld_test_restart_time = 0;
+int mnld_test_restart_interval = 0;
+
+int mnld_test_network_type = NETWORK_TYPE_WIFI;
+int mnld_test_network_on = 0;
+int mnld_test_network_roaming = 0;
+
+timer_t mnld_test_restart_timer = INVALID_TIMERID;
+MNLD_TEST_RESTART_TYPE mnld_test_restart_type = MNLD_TEST_RESTART_TYPE_HOT;
+struct timespec mnld_test_gnss_open_tm;
+char mnld_test_mnl_ver[MNL_VER_LEN];
+extern mnld_test_result mnld_test_result_body;
+
+extern struct gps_device_t_ext linux_gps_device; //This symbol defined in libgnsshal.so
+
+clock_type mnld_test_clock_type[] = {
+ {0xFE,"Co-Clock"},
+ {0xFF,"TCXO"}
+};
+
+#define MNLD_TEST_NETWORK_TYPE_STR_LEN 8
+const char mnld_test_network_type_str[][MNLD_TEST_NETWORK_TYPE_STR_LEN] = {
+ {"mobile"},
+ {"wifi"}
+};
+
+void mnld_test_show_help(void)
+{
+ mnld_test_printf("MNLD client test :\r\n");
+ mnld_test_printf("------------------------------------------------------------------------------\r\n");
+ mnld_test_printf("The command to start GNSS test:\r\n");
+ mnld_test_printf("\tmnld_test start [start type] [restart times] [restart interval]\r\n");
+ mnld_test_printf("\t\t[start type]: \r\n\t\th/H: hot start;\r\n\t\tw/W: Warm start;\r\n\t\tc/C: Cold start;\r\n\t\tf/F: Full start\r\n");
+ mnld_test_printf("\t\t[restart times]: integer value, range is 0-1000, default is 0(no restart, always on). \r\n");
+ mnld_test_printf("\t\t[restart interval]: integer value, range is 0-3600, the unit is second; the default value is 60\r\n");
+ mnld_test_printf("------------------------------------------------------------------------------\r\n");
+ mnld_test_printf("The command to stop GNSS test:\r\n");
+ mnld_test_printf("\tCtrl+C or kill -9 `pidof mnld_test`\r\n");
+ mnld_test_printf("------------------------------------------------------------------------------\r\n");
+ mnld_test_printf("The command to update network status:\r\n");
+ mnld_test_printf("\tmnld_test network [type] [roaming]\r\n");
+ mnld_test_printf("\t[type]: wifi, mobile, disable\r\n");
+ mnld_test_printf("\t[roaming]: roaming, the mobile network is in roaming state\r\n");
+}
+
+/*
+Function:mnld_test_socket_open
+Description:open and connect a INET socket by given port number
+Param:[IN] port, the port number of socket
+Param:[OUT] fd, the socket fd
+Return:NULL -- some thing is incorrect; Other value -- open and connect sokcet successfully
+*/
+int mnld_test_socket_open(int port)
+{
+ struct sockaddr_in servaddr;
+ int socketfd = 0;
+
+ if((socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ LOGE("Create socket error:%d,%s\n", errno, strerror(errno));
+ return socketfd;
+ }
+
+ memset(&servaddr, 0, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_port = htons(port);
+ servaddr.sin_addr.s_addr = INADDR_ANY;
+
+ if( connect(socketfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0 )
+ {
+ LOGE("connect error:%d,%s\n", errno, strerror(errno));
+ close(socketfd);
+ return -1;
+ }
+
+ return(socketfd);
+}
+
+#ifdef CONFIG_GPS_MT3303
+void mnld_test_get_mnl_ver(void )
+{
+ LOGI("GNSS chip is 3303, there is no MNL.");
+ MNLD_STRNCPY(mnld_test_mnl_ver, "GNSS chip is 3303,there is no MNL", sizeof(mnld_test_mnl_ver));
+}
+#else
+#ifdef MTK_ADR_SUPPORT
+void mnld_test_get_mnl_ver(void )
+{
+ LOGI("ADR has used the port 7000, the mnl version is static.");
+ MNLD_STRNCPY(mnld_test_mnl_ver, "MNL_VER_18070301ALPS05_5.5U_25", sizeof(mnld_test_mnl_ver));
+}
+#else
+void mnld_test_get_mnl_ver(void )
+{
+ int sock_fd = 0;
+ int rec_len = 0;
+ char rec_buff[MNL_TEST_REC_BUFF_LEN+1] = {0};
+ char *mnl_ver_addr = NULL;
+ int got_mnl_ver = 0;
+ int retry_cnt = 0;
+
+ if((sock_fd = mnld_test_socket_open(PORT)) < 0 )
+ {
+ LOGE("Socket open error\n");
+ MNLD_STRNCPY(mnld_test_mnl_ver, "UNKNOWN", sizeof(mnld_test_mnl_ver));
+ } else {
+ char *outbuff = "$PMTK605*31\r\n";
+ int cmd_sent = 0;
+ do{
+ // if((cmd_sent == 0) && send(sock_fd,outbuff,strlen(outbuff)+1, 0) == -1)
+ if((cmd_sent == 0) && hal2mnl_send_pmtk(outbuff,strlen(outbuff)) == -1)
+ {
+ cmd_sent = 0;
+ LOGE("Socket send error(%s)\n",strerror(errno));
+ } else {
+ cmd_sent = 1;
+ if((rec_len = recv(sock_fd, rec_buff, MNL_TEST_REC_BUFF_LEN, 0)) < 0)
+ {
+ LOGE("Recieve error(%d):%s\n",errno, strerror(errno));
+ usleep(20000);
+ } else {
+ rec_buff[rec_len] = '\0';
+ LOGD("RCV[len:%d]:[%s]\n", rec_len, rec_buff);
+ mnl_ver_addr = strstr(rec_buff, "MNL_VER");
+ if( mnl_ver_addr != NULL) {
+ MNLD_STRNCPY(mnld_test_mnl_ver, mnl_ver_addr, MNL_VER_LEN);
+ //LOGE("MNL Version1:[%s], %d", mnld_test_mnl_ver, strlen(mnld_test_mnl_ver));
+ mnld_test_mnl_ver[strlen("MNL_VER_20071303ALPS05_6.10_99,5,10")] = '\0'; // Remove tail
+ //LOGD("MNL Version2:[%s], %d", mnld_test_mnl_ver, strlen(mnld_test_mnl_ver));
+ got_mnl_ver = 1;
+ }
+ }
+ }
+ if(retry_cnt ++ >= 100)
+ {
+ LOGE("Get mnl version fail\r\n");
+ MNLD_STRNCPY(mnld_test_mnl_ver, "UNKNOWN", sizeof(mnld_test_mnl_ver));
+ break;
+ }
+ }while(!got_mnl_ver);
+
+ LOGD("close socket fd\n");
+ close(sock_fd);
+ }
+}
+#endif
+#endif
+
+void mnld_test_open_gnss(MNLD_TEST_RESTART_TYPE restart_type, GpsInterface_ext* gps_interface, GpsCallbacks_ext* gps_cbs)
+{
+ GpsCallbacks_ext* cbs = gps_cbs;
+ GpsInterface_ext* gpsinterface = gps_interface;
+ unsigned int delete_flags = 0;
+ switch(restart_type) {
+ case MNLD_TEST_RESTART_TYPE_HOT:
+ LOGD("Hot Start\n");
+ //hal2mnl_gps_delete_aiding_data(GPS_DELETE_RTI);
+ delete_flags = GPS_DELETE_RTI;
+ break;
+ case MNLD_TEST_RESTART_TYPE_WARM:
+ LOGD("Warm Start\n");
+ //hal2mnl_gps_delete_aiding_data(GPS_DELETE_EPHEMERIS);
+ delete_flags = GPS_DELETE_EPHEMERIS;
+ break;
+ case MNLD_TEST_RESTART_TYPE_COLD:
+ LOGD("Cold Start\n");
+ /*hal2mnl_gps_delete_aiding_data(GPS_DELETE_EPHEMERIS |
+ GPS_DELETE_POSITION | GPS_DELETE_TIME | GPS_DELETE_IONO |
+ GPS_DELETE_UTC | GPS_DELETE_HEALTH);*/
+ delete_flags = GPS_DELETE_EPHEMERIS |
+ GPS_DELETE_POSITION | GPS_DELETE_TIME | GPS_DELETE_IONO |
+ GPS_DELETE_UTC | GPS_DELETE_HEALTH;
+ break;
+ case MNLD_TEST_RESTART_TYPE_FULL:
+ LOGD("Full Start\n");
+ //hal2mnl_gps_delete_aiding_data(GPS_DELETE_ALL);
+ delete_flags = GPS_DELETE_ALL;
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]\n", restart_type);
+ return;
+ }
+ if(gpsinterface != NULL && cbs != NULL)
+ {
+ gpsinterface->init(cbs);
+ //hal2mnl_update_network_state(1,NETWORK_TYPE_WIFI,0,"NULL");
+ //hal2mnl_update_network_state(mnld_test_network_on,mnld_test_network_type,mnld_test_network_roaming,"NULL");
+ gpsinterface->start();
+ gpsinterface->delete_aiding_data(delete_flags);
+ memset(&(mnld_test_result_body.location),0,sizeof(GpsLocation));
+ mnld_test_result_body.fix_type = 0;
+ mnld_test_ttff = 0;
+ mnld_test_session_end = 0;
+ // usleep(500000);
+ // mnld_test_connect_mnl();
+ #ifndef MNLD_TEST_TTFF_SESSION_BEGIN
+ if(clock_gettime(CLOCK_BOOTTIME,&mnld_test_gnss_open_tm) == -1)
+ {
+ LOGE("Fail to get time(%s).",strerror(errno));
+ }
+ #endif
+ }else{
+ LOGE("param error:%p, %p",gpsinterface, cbs);
+ }
+}
+
+void mnld_test_close_gnss(GpsInterface_ext* gps_interface)
+{
+ GpsInterface_ext* gpsinterface = gps_interface;
+// gpsinterface = gps_device__get_gps_interface("mnld_test stop");
+ if(gpsinterface != NULL)
+ {
+ gpsinterface->stop();
+ gpsinterface->cleanup();
+ }else{
+ LOGE("[%s]param error\r\n",__func__);
+ }
+}
+
+void mnld_test_update_network(GpsInterface_ext* gps_interface, GpsCallbacks_ext* gps_cbs)
+{
+ GpsCallbacks_ext* cbs = gps_cbs;
+ GpsInterface_ext* gpsinterface = gps_interface;
+ int ret = 0;
+
+ if(gpsinterface != NULL && cbs != NULL) {
+ NetworkCapability network_cap = 0;
+ if(mnld_test_network_type == NETWORK_TYPE_WIFI) {
+ network_cap |= NOT_METERED;
+ }
+
+ if(!mnld_test_network_roaming) {
+ network_cap |= NOT_ROAMING;
+ }
+
+ gpsinterface->init(cbs);
+ ret = hal2mnl_update_network_state(0, mnld_test_network_on, network_cap, "NULL");
+ if(-1 == ret) {
+ LOGE("Network set fail!\r\n");
+ }else{
+ LOGD("Network set successfully! type: %s,on:%d,roaming:%d\r\n",mnld_test_network_type_str[mnld_test_network_type],mnld_test_network_on,mnld_test_network_roaming);
+ }
+ gpsinterface->cleanup();
+ } else {
+ LOGE("[%s]param error\r\n",__func__);
+ }
+}
+
+MNLD_TEST_RESTART_TYPE mnld_test_get_restart_type(char type_char)
+{
+ MNLD_TEST_RESTART_TYPE restart_type = MNLD_TEST_RESTART_TYPE_UNKNOWN;
+ switch(type_char)
+ {
+ case 'H':
+ case 'h':
+ restart_type = MNLD_TEST_RESTART_TYPE_HOT;
+ break;
+
+ case 'W':
+ case 'w':
+ restart_type = MNLD_TEST_RESTART_TYPE_WARM;
+ break;
+
+ case 'C':
+ case 'c':
+ restart_type = MNLD_TEST_RESTART_TYPE_COLD;
+ break;
+
+ case 'F':
+ case 'f':
+ restart_type = MNLD_TEST_RESTART_TYPE_FULL;
+ break;
+
+ default :
+ LOGE("Restart type error, use default hot start!\r\n");
+ restart_type = MNLD_TEST_RESTART_TYPE_UNKNOWN;
+ break;
+
+ }
+ return restart_type;
+}
+
+void mnld_test_gnss_restart(void)
+{
+ int retry_cnt = 0;
+ if(mnld_test_restart_cnt < mnld_test_restart_time)
+ {
+ mnld_test_restart_cnt++;
+ mnld_test_close_gnss(mnld_test_gpsinfs);
+ while(!mnld_test_session_end)
+ {
+ if(retry_cnt++>500)
+ {
+ LOGW("[%s] wait gnss close timeout\r\n",__func__);
+ break;
+ }
+ usleep(10000);
+ }
+ mnld_test_open_gnss(mnld_test_restart_type,mnld_test_gpsinfs,mnld_test_cbs);
+ mnldinf_start_timer(mnld_test_restart_timer,mnld_test_restart_interval*1000);
+ }else{
+ mnldinf_stop_timer(mnld_test_restart_timer);
+ }
+}
+
+char* mnld_test_get_clock_type_str(int clock_type_int)
+{
+ int i = 0;
+ int len = sizeof(mnld_test_clock_type)/sizeof(clock_type);
+
+ for(i=0;i<len;i++)
+ {
+ if(clock_type_int == mnld_test_clock_type[i].type_int)
+ {
+ break;
+ }
+ }
+
+ if(i < len)
+ {
+ return(mnld_test_clock_type[i].type_str);
+ }else{
+ return("Unknown");
+ }
+}
+
+void mnld_test_show_test_result(mnld_test_result* result)
+{
+ if(NULL != result)
+ {
+ memcpy(result->chip_ver,MNLD_TEST_CHIP_VER,sizeof(MNLD_TEST_CHIP_VER));
+ memcpy(result->mnl_ver,MNLD_TEST_MNL_VER,strlen(MNLD_TEST_MNL_VER));
+ result->clk_type = MNLD_TEST_CLOCK_TYPE;
+ result->clk_buff = MNLD_TEST_CLOCK_BUFF;
+
+ //system("clear");
+ LOGD("---------------------------------------------");
+ LOGD("Chip:%s",result->chip_ver);
+ LOGD("MNL Version:%s",result->mnl_ver);
+ //LOGD("Clock Type:%s",mnld_test_get_clock_type_str(result->clk_type));
+ //LOGD("Clock Buffer:%d",result->clk_buff);
+ LOGD("---------------------------------------------");
+ if(result->ttff[CURR] == 0)
+ {
+ LOGD("TTFF: - ");
+ }else{
+ LOGD("TTFF: %d ms",result->ttff[CURR]);
+ }
+
+ if(result->ttff[MIN] == 0)
+ {
+ LOGD("TTFF min: - ");
+ }else{
+ LOGD("TTFF min: %d ms",result->ttff[MIN]);
+ }
+
+ if(result->ttff[MAX] == 0)
+ {
+ LOGD("TTFF max: - ");
+ }else{
+ LOGD("TTFF max: %d ms",result->ttff[MAX]);
+ }
+
+ if(result->ttff[MEAN] == 0)
+ {
+ LOGD("TTFF mean: - ");
+ }else{
+ LOGD("TTFF mean: %d ms",result->ttff[MEAN]);
+ }
+ LOGD("---------------------------------------------");
+ LOGD("Fix Type: %d",result->fix_type);
+ LOGD("Flags: 0x%x",result->location.legacyLocation.flags);
+ LOGD("Latitude: %.10lf",result->location.legacyLocation.latitude);
+ LOGD("Longtitude: %.10lf",result->location.legacyLocation.longitude);
+ LOGD("Altitude: %.10lf",result->location.legacyLocation.altitude);
+ LOGD("Speed: %fm/s",result->location.legacyLocation.speed);
+ LOGD("Bearing: %f",result->location.legacyLocation.bearing);
+// LOGD("Time stamp: %d",result->location.timestamp);
+ LOGD("Accuracy: %fm",result->location.horizontalAccuracyMeters);
+ //LOGD("verticalAccuracyMeters: %f",result->location.verticalAccuracyMeters);
+ //LOGD("speedAccuracyMetersPerSecond: %f",result->location.speedAccuracyMetersPerSecond);
+ //LOGD("bearingAccuracyDegrees: %f",result->location.bearingAccuracyDegrees);
+ LOGD("Utc time: %s",result->utc_time);
+ LOGD("---------------------------------------------");
+ LOGD("GNSS testing(%d).",mnld_test_restart_cnt);
+ }
+}
+
+sem_t g_mnld_test_exit_sem;
+
+// -1 means failure
+int mnld_test_block_here() {
+ if (sem_init(&g_mnld_test_exit_sem, 0, 0) == -1) {
+ LOGE("mnld_test_block_here() sem_init failure reason=%s\n", strerror(errno));
+ return -1;
+ }
+ sem_wait(&g_mnld_test_exit_sem);
+ if (sem_destroy(&g_mnld_test_exit_sem) == -1) {
+ LOGE("mnld_test_block_here() sem_destroy reason=%s\n", strerror(errno));
+ }
+ LOGW("mnld_test exit blocking...");
+ return 0;
+}
+
+void mnld_test_block_exit(void) {
+ LOGW("mnld_test exiting....");
+ if(sem_post(&g_mnld_test_exit_sem) == -1) {
+ LOGE("sem_post failed");
+ _exit(0);
+ }
+}
+void daemon_sighlr(int signo)
+{
+ if ((signo == SIGUSR1) || (signo == SIGINT) || (signo == SIGTERM) ||((signo == SIGKILL))) {
+ LOGD("catch signal:%d, stop mnld_test\n", signo);
+ mnld_test_close_gnss(mnld_test_gpsinfs);
+ mnld_test_block_exit();
+ }
+ else if (signo == SIGPIPE || signo == SIGTTIN)
+ LOGD("catch signal:%d, ignore\n", signo);;
+}
+
+int main(int argc, char** argv)
+{
+ struct sigaction actions;
+
+ actions.sa_handler = daemon_sighlr;
+ sigemptyset(&actions.sa_mask);
+ actions.sa_flags = 0;
+ sigaction(SIGUSR1, &actions, NULL);
+ sigaction(SIGINT, &actions, NULL);
+ sigaction(SIGTTIN, &actions, NULL);
+ sigaction(SIGKILL, &actions, NULL);
+ sigaction(SIGTERM, &actions, NULL);
+
+ LOGD("func:%s, line:%d", __func__, __LINE__);
+ int exit_flag = 0;
+ int index = 0;
+ struct gps_device_t_ext *gpsdev = NULL;
+ MNLD_TEST_ACTION action = MNLD_TEST_ACTION_UNKNOWN;
+
+ //Show the recieved command
+ for(index=0; index<argc; index++)
+ {
+ mnld_test_printf("%s ",argv[index]);
+ }
+ mnld_test_printf("\r\n");
+
+ if(argc >= 2 && argc <= MNLD_TEST_CMD_CNT_MAX)
+ {
+ if(!strncmp(argv[1], MNLD_TEST_CMD_OPEN, strlen(MNLD_TEST_CMD_OPEN)))//Open GNSS
+ {
+ action = MNLD_TEST_ACTION_GNSS_OPEN;
+ //re-init restart parameters
+ mnld_test_restart_time = 0;
+ mnld_test_restart_interval = 60;//Default is 60s
+ mnld_test_restart_type = MNLD_TEST_RESTART_TYPE_HOT;
+
+ switch(argc)
+ {
+ case 5://No break
+ mnld_test_restart_interval = atoi(&argv[4][0]);
+ case 4://No break
+ mnld_test_restart_time = atoi(&argv[3][0]);
+ case 3://No break
+ mnld_test_restart_type = mnld_test_get_restart_type(argv[2][0]);
+ case 2://No break
+ case 1://No break
+ default:
+ break;
+ }
+ LOGD("mnld_test start.\r\n");
+ if(mnld_test_restart_time > 1000)
+ {
+ LOGE("The max value of restart time is 1000, %d is over this range\r\n",mnld_test_restart_time);
+ mnld_test_restart_time = 1000;
+ }
+
+ if(mnld_test_restart_interval > 3600)
+ {
+ LOGE("The max value of restart interval is 3600s(1h), %d is over this range\r\n",mnld_test_restart_interval);
+ mnld_test_restart_interval = 3600;
+ }
+
+ if(mnld_test_restart_time <= 0)//No restart
+ {
+ mnld_test_restart_interval = 0;
+ }
+ LOGD("restart_time:%d, restart_interval:%ds,restart_type:%d\r\n",mnld_test_restart_time,mnld_test_restart_interval,mnld_test_restart_type);
+ exit_flag = 0;
+ }else if(!strncmp(argv[1],MNLD_TEST_CMD_CLOSE, strlen(MNLD_TEST_CMD_CLOSE))){//Close GNSS
+ action = MNLD_TEST_ACTION_GNSS_CLOSE;
+ LOGD("mnld_test stop.\r\n");
+ exit_flag = 0;
+ }else if(!strncmp(argv[1], MNLD_TEST_CMD_NETWORK, strlen(MNLD_TEST_CMD_NETWORK))){
+ LOGD("mnld_test set network.\r\n");
+ exit_flag = 0;
+ if(argc == 3)
+ {
+ if(!strncmp(argv[2], MNLD_TEST_NETWORK_WIFI, strlen(MNLD_TEST_NETWORK_WIFI)))
+ {
+ mnld_test_network_type = NETWORK_TYPE_WIFI;
+ mnld_test_network_on = 1;
+ mnld_test_network_roaming = 0;
+ }else if(!strncmp(argv[2],MNLD_TEST_NETWORK_MOBILE, strlen(MNLD_TEST_NETWORK_MOBILE))){
+ mnld_test_network_type = NETWORK_TYPE_MOBILE;
+ mnld_test_network_on = 1;
+ mnld_test_network_roaming = 0;
+ }else if(!strncmp(argv[2],MNLD_TEST_NETWORK_DISABLE, strlen(MNLD_TEST_NETWORK_DISABLE))) {
+ mnld_test_network_type = NETWORK_TYPE_WIFI;
+ mnld_test_network_on = 0;
+ mnld_test_network_roaming = 0;
+ }else{
+ LOGW("Network set fail!Unknown command!(%d)\r\n", argc);
+ mnld_test_show_help();
+ exit_flag = 1;
+ }
+ }else if(argc == 4){
+ if(!strncmp(argv[2],MNLD_TEST_NETWORK_MOBILE, strlen(MNLD_TEST_NETWORK_MOBILE)) && !strncmp(argv[3],MNLD_TEST_NETWORK_ROAMING, strlen(MNLD_TEST_NETWORK_ROAMING)))
+ {
+ mnld_test_network_type = NETWORK_TYPE_MOBILE;
+ mnld_test_network_on = 1;
+ mnld_test_network_roaming = 1;
+ }else{
+ LOGW("Network set fail!Unknown command!(%d)\r\n", argc);
+ mnld_test_show_help();
+ exit_flag = 1;
+ }
+ }else{
+ LOGW("Network set fail! Error cmd count(%d).\r\n",argc);
+ mnld_test_show_help();
+ exit_flag = 1;
+ }
+
+ LOGD("network, type:%s, on:%d, roaming:%d.\r\n",mnld_test_network_type_str[mnld_test_network_type], mnld_test_network_on, mnld_test_network_roaming);
+ action = MNLD_TEST_ACTION_SET_NETWORK;
+ }else{
+ LOGE("Unknown command!\r\n");
+ mnld_test_show_help();
+ exit_flag = 1;
+ }
+ }else{
+ LOGE("Unknown command!\r\n");
+ mnld_test_show_help();
+ exit_flag = 1;
+ }
+
+ if(!exit_flag)
+ {
+ gpsdev = &linux_gps_device;
+
+ mnld_test_gpsinfs = (GpsInterface_ext*)gpsdev->get_gps_interface(gpsdev);
+
+ mnld_test_cbs = mnld_test__get_gps_callbacks();//&mnld_test_gps_callbacks;
+ switch(action)
+ {
+ case MNLD_TEST_ACTION_GNSS_OPEN: {
+ valid_ttff_cnt = 0;
+ valid_ttff_sum = 0;
+
+ memset(&mnld_test_result_body,0,sizeof(mnld_test_result));
+ mnld_test_open_gnss(mnld_test_restart_type,mnld_test_gpsinfs,mnld_test_cbs);
+ //system("clear");
+ if(mnld_test_restart_interval != 0)
+ {
+ mnld_test_restart_timer = mnldinf_init_timer(mnld_test_gnss_restart);
+ mnldinf_start_timer(mnld_test_restart_timer,mnld_test_restart_interval*1000);
+ }
+ exit_flag = 1;
+ mnld_test_block_here();
+ break;
+ }
+ case MNLD_TEST_ACTION_GNSS_CLOSE: {
+ system("killall mnld_test"); //Cleanup and stop GPS in SIGTERM handler
+
+ exit_flag = 1;
+ break;
+ }
+ case MNLD_TEST_ACTION_SET_NETWORK: {
+ mnld_test_update_network(mnld_test_gpsinfs, mnld_test_cbs);
+
+ exit_flag = 1;
+ break;
+ }
+ default: {
+ LOGW("Unknown action(%d)\r\n",action);
+ mnld_test_show_help();
+ break;
+ }
+ }
+
+ }
+ return 0;
+}
diff --git a/src/connectivity/gps/2.0/gnss_test/mnld_client/src/mnld_client_gps_cb.c b/src/connectivity/gps/2.0/gnss_test/mnld_client/src/mnld_client_gps_cb.c
new file mode 100644
index 0000000..6cb021d
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/mnld_client/src/mnld_client_gps_cb.c
@@ -0,0 +1,256 @@
+#include<pthread.h>
+#include<stdio.h>
+#include<unistd.h>
+#include<errno.h>
+#include<string.h>
+
+#include"mnld_test.h"
+#include"mtk_lbs_utility.h"
+#include "mnldinf_log.h"
+
+extern struct timespec mnld_test_gnss_open_tm;
+extern int mnld_test_ttff;
+extern int mnld_test_session_end;
+GpsLocation_ext location_rslt;
+mnld_test_result mnld_test_result_body;
+extern char mnld_test_mnl_ver[MNL_VER_LEN];
+
+#define MNLD_TEST_CB_DBG 0
+
+#if MNLD_TEST_CB_DBG
+#define CB_DBG LOGD
+#else
+//empty
+#define CB_DBG(...) do {} while(0)
+#endif
+void mnld_test_gps_location_callback(GpsLocation_ext* location)
+{
+ if(location->legacyLocation.size == sizeof(GpsLocation_ext))
+ {
+ CB_DBG("===============Update Location Info==================");
+ CB_DBG("flags:0x%x", location->legacyLocation.flags);
+ CB_DBG("latitude:%.10lf", location->legacyLocation.latitude);
+ CB_DBG("longitude:%.10lf", location->legacyLocation.longitude);
+ CB_DBG("altitude:%.10lf", location->legacyLocation.altitude);
+ CB_DBG("speed:%f", location->legacyLocation.speed);
+ CB_DBG("bearing:%f", location->legacyLocation.bearing);
+ CB_DBG("timestamp:%ld", location->legacyLocation.timestamp);
+ CB_DBG("horizontalAccuracyMeters:%f", location->horizontalAccuracyMeters);
+ CB_DBG("verticalAccuracyMeters:%f", location->verticalAccuracyMeters);
+ CB_DBG("speedAccuracyMetersPerSecond:%f", location->speedAccuracyMetersPerSecond);
+ CB_DBG("bearingAccuracyDegrees:%f", location->bearingAccuracyDegrees);
+ memset(&(mnld_test_result_body.location), 0, sizeof(GpsLocation_ext));
+ memcpy(&(mnld_test_result_body.location), location, sizeof(GpsLocation_ext));
+ }else {
+ LOGE("GpsLocation_ext size is wrong");
+ }
+}
+
+void mnld_test_gps_status_callback(GpsStatus* status)
+{
+ if(status->size == sizeof(GpsStatus))
+ {
+ CB_DBG("GPS Status:%d", status->status);
+ if(status->status == GPS_STATUS_SESSION_BEGIN)
+ {
+ mnld_test_ttff = 0;
+ mnld_test_session_end = 0;
+// usleep(500000);
+ mnld_test_get_mnl_ver();
+ #ifdef MNLD_TEST_TTFF_SESSION_BEGIN
+ if(clock_gettime(CLOCK_BOOTTIME,&mnld_test_gnss_open_tm) == -1)
+ {
+ LOGE("Fail to get time(%s).", strerror(errno));
+ }
+ #endif
+ }
+
+ if(status->status == GPS_STATUS_SESSION_END)
+ {
+ mnld_test_session_end = 1;
+ }
+ }else{
+ LOGE("size error!");
+ }
+}
+
+void mnld_test_gps_sv_status_callback(GpsSvStatus* sv_info)
+{
+ CB_DBG("gps sv status");
+}
+
+#define NMEA_GGA "GGA"
+#define NMEA_GSA "GSA"
+#define NMEA_ACC "ACCURACY"
+extern int valid_ttff_cnt;
+extern int valid_ttff_sum;
+void mnld_test_gps_nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
+{
+ CB_DBG("NMEA report at %ld",timestamp);
+
+ //$GPGSA,A,3,...
+ if( strncmp(nmea+3,NMEA_GSA,strlen(NMEA_GSA)) == 0 )
+ {
+ mnld_test_result_body.fix_type = *(nmea+9) - '0';
+ if(mnld_test_result_body.fix_type == 1)
+ {
+ mnld_test_result_body.fix_type = 0;
+ }
+
+ if((mnld_test_ttff == 0) && mnld_test_result_body.fix_type != 0)
+ {
+ struct timespec fix_tm;
+
+ if(clock_gettime(CLOCK_BOOTTIME,&fix_tm) == -1)
+ {
+ mnld_test_result_body.ttff[CURR] = 0;
+ LOGE("[%s]Fail to get time(%s)\r\n",__func__,strerror(errno));
+ }else{
+ // CB_DBG("Flags:0x%x,start time:%ds,%dns; ttff time:%ds,%dns\r\n",mnld_test_result_body.location.flags,mnld_test_gnss_open_tm.tv_sec,mnld_test_gnss_open_tm.tv_nsec,fix_tm.tv_sec,fix_tm.tv_nsec);
+ mnld_test_ttff = (fix_tm.tv_sec-mnld_test_gnss_open_tm.tv_sec)*1000+((fix_tm.tv_nsec-mnld_test_gnss_open_tm.tv_nsec)/1000000);
+ mnld_test_result_body.ttff[CURR] = mnld_test_ttff;
+ valid_ttff_cnt++;
+ valid_ttff_sum+=mnld_test_result_body.ttff[CURR];
+
+ mnld_test_result_body.ttff[MEAN] = valid_ttff_sum/valid_ttff_cnt;
+ //Find the MIN TTFF
+ if((mnld_test_result_body.ttff[MIN] == 0 ) || (mnld_test_result_body.ttff[MIN] > mnld_test_result_body.ttff[CURR]))
+ {
+ mnld_test_result_body.ttff[MIN] = mnld_test_result_body.ttff[CURR];
+ }
+ // Find the MAX TTFF
+ if(mnld_test_result_body.ttff[MAX] < mnld_test_result_body.ttff[CURR])
+ {
+ mnld_test_result_body.ttff[MAX] = mnld_test_result_body.ttff[CURR];
+ }
+ CB_DBG("TTFF:%dms",mnld_test_ttff);
+ }
+
+ }else{
+ mnld_test_result_body.ttff[CURR] = mnld_test_ttff;
+ }
+ }
+
+ if(mnld_test_result_body.fix_type != 0)
+ {
+ //GNGGA,hhmmss.mss,...
+ if(strncmp(nmea+3,NMEA_GGA,strlen(NMEA_GGA)) == 0)
+ {
+ strncpy(mnld_test_result_body.utc_time, nmea+7, MNL_UTC_TIME_LEN);
+ mnld_test_result_body.utc_time[MNL_UTC_TIME_LEN-1] = '\0';
+ }
+ }else{
+ memset(mnld_test_result_body.utc_time, 0, MNL_UTC_TIME_LEN);
+ mnld_test_result_body.utc_time[0] = '-';
+ }
+
+ if(strncmp(nmea+3,NMEA_ACC,strlen(NMEA_ACC)) == 0)
+ {
+ mnld_test_result_body.location.legacyLocation.timestamp = timestamp;
+ mnld_test_show_test_result(&mnld_test_result_body);
+ }
+
+}
+
+void mnld_test_gps_set_capabilities(uint32_t capabilities)
+{
+
+ CB_DBG("gps set capabilities");
+}
+
+void mnld_test_gps_acquire_wakelock(void)
+{
+
+ CB_DBG("gps acquire wakelock");
+}
+
+void mnld_test_gps_release_wakelock(void)
+{
+
+ CB_DBG("gps release wakelock");
+}
+
+void mnld_test_gps_request_utc_time(void)
+{
+
+ CB_DBG("gps request utc time");
+}
+
+void mnld_test_set_system_info_cb(const GnssSystemInfo* info)
+{
+ CB_DBG("set system info");
+}
+
+void mnld_test_gnss_sv_status_cb(GnssSvStatus_ext* sv_info)
+{
+ CB_DBG("gnss sv status");
+}
+
+pthread_t mnld_test_gps_create_thread(const char* name, void (*start)(void *), void* arg)
+{
+ pthread_t ntid = 0;
+ int ret = 0;
+
+ ret = pthread_create(&ntid, NULL, (void *(*)(void *))start, arg);
+
+ if(ret != 0)
+ {
+ LOGE("thread %s create fail(%s)!", name, strerror(errno));
+ ntid = 0;
+ }else{
+ CB_DBG("tread %s create success!", name);
+ }
+
+ return ntid;
+}
+
+void mnld_test_gnss_set_name_cb(const char* name, int length)
+{
+ char *mnl_ver_addr = NULL;
+
+ if(name != NULL && strlen(name) <= length //Have valid input
+ && strlen(mnld_test_mnl_ver) <= strlen("MNL_VER_default")) { //Haven't got mnld_test_mnl_ver
+ mnl_ver_addr = strstr(name, "MNL_VER");
+ CB_DBG("gnss set name:%s", name);
+ if(mnl_ver_addr != NULL) {
+ MNLD_STRNCPY(mnld_test_mnl_ver, mnl_ver_addr, sizeof(mnld_test_mnl_ver));
+ CB_DBG("[%s]", mnld_test_mnl_ver);
+ } else {
+ CB_DBG("Don't find MNL version!!!");
+ }
+ } else {
+ LOGW("error param:%p, %d", name, length);
+ }
+}
+
+void mnld_test_gnss_request_location_cb(bool independentFromGnss, bool isUserEmergency)
+{
+ CB_DBG("gnss request location");
+}
+
+void mnld_test_agnss_location_callback(GpsLocation_ext* location) {
+ CB_DBG("Get agps location");
+}
+
+GpsCallbacks_ext mnld_test_gps_callbacks = {
+ .size = sizeof(GpsCallbacks_ext),
+ .location_cb = mnld_test_gps_location_callback,
+ .status_cb = mnld_test_gps_status_callback,
+ .sv_status_cb = mnld_test_gps_sv_status_callback,
+ .nmea_cb = mnld_test_gps_nmea_callback,
+ .set_capabilities_cb = mnld_test_gps_set_capabilities,
+ .acquire_wakelock_cb = mnld_test_gps_acquire_wakelock,
+ .release_wakelock_cb = mnld_test_gps_release_wakelock,
+ .create_thread_cb = mnld_test_gps_create_thread,
+ .request_utc_time_cb = mnld_test_gps_request_utc_time,
+ .set_system_info_cb = mnld_test_set_system_info_cb,
+ .gnss_sv_status_cb = mnld_test_gnss_sv_status_cb,
+ .set_name_cb = mnld_test_gnss_set_name_cb,
+ .request_location_cb = mnld_test_gnss_request_location_cb,
+ .agps_location_cb = mnld_test_agnss_location_callback,
+};
+
+GpsCallbacks_ext* mnld_test__get_gps_callbacks(void)
+{
+ return &mnld_test_gps_callbacks;
+}
diff --git a/src/connectivity/gps/2.0/gnss_test/mnld_fm/inc/mnld_fm.h b/src/connectivity/gps/2.0/gnss_test/mnld_fm/inc/mnld_fm.h
new file mode 100644
index 0000000..12de6fd
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/mnld_fm/inc/mnld_fm.h
@@ -0,0 +1,50 @@
+#ifndef __MNLD_FM_H__
+#define __MNLD_FM_H__
+
+#include"hal_mnl_interface_common.h"
+#include"hardware/gps_mtk.h"
+
+typedef enum{
+ MNLD_FM_TEST_OPEN = 0,
+ MNLD_FM_TEST_OPENED,
+ MNLD_FM_TEST_ENGINE_STARTED,
+ MNLD_FM_TEST_SV_SEARCHED,
+ MNLD_FM_TEST_STAGE_MAX
+} MNLD_FM_TEST_STAGE;
+
+typedef struct {
+ int sv_num;
+ int sv_list[GNSS_MAX_SVS];
+ MNLD_FM_TEST_STAGE test_stage;
+}mnld_fm_test_result;
+
+typedef enum{
+ MNLD_FM_RESTART_TYPE_UNKNOWN = -1,
+ MNLD_FM_RESTART_TYPE_HOT,
+ MNLD_FM_RESTART_TYPE_WARM,
+ MNLD_FM_RESTART_TYPE_COLD,
+ MNLD_FM_RESTART_TYPE_FULL,
+ MNLD_FM_RESTART_TYPE_MAX
+} MNLD_FM_RESTART_TYPE;
+
+
+#define MNLD_FM_CMD_CNT_MIN 1
+#define MNLD_FM_CMD_CNT_MAX 2
+#define GPS_DELETE_EPHEMERIS 0x0001
+#define GPS_DELETE_ALMANAC 0x0002
+#define GPS_DELETE_POSITION 0x0004
+#define GPS_DELETE_TIME 0x0008
+#define GPS_DELETE_IONO 0x0010
+#define GPS_DELETE_UTC 0x0020
+#define GPS_DELETE_HEALTH 0x0040
+#define GPS_DELETE_SVDIR 0x0080
+#define GPS_DELETE_SVSTEER 0x0100
+#define GPS_DELETE_SADATA 0x0200
+#define GPS_DELETE_RTI 0x0400
+#define GPS_DELETE_CELLDB_INFO 0x8000
+#define GPS_DELETE_ALL 0xFFFF
+
+GpsCallbacks_ext* mnld_fm__get_gps_callbacks(void);
+//GpsInterface* gps_device__get_gps_interface(struct gps_device_t* device);
+
+#endif //__MNLD_FM_H__
diff --git a/src/connectivity/gps/2.0/gnss_test/mnld_fm/src/mnld_fm.c b/src/connectivity/gps/2.0/gnss_test/mnld_fm/src/mnld_fm.c
new file mode 100644
index 0000000..4e838d4
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/mnld_fm/src/mnld_fm.c
@@ -0,0 +1,196 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include "hal2mnl_interface.h"
+#include "mnld_fm.h"
+#include "mtk_lbs_utility.h"
+#include "mnldinf_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnldfm"
+#endif
+
+int log_dbg_level = L_VERBOSE;
+
+GpsCallbacks_ext* mnld_fm_cbs = NULL;
+GpsInterface_ext* mnld_fm_gpsinfs = NULL;
+
+timer_t mnld_fm_test_timer = 0;
+MNLD_FM_RESTART_TYPE mnld_fm_restart_type = MNLD_FM_RESTART_TYPE_HOT;
+extern mnld_fm_test_result mnld_fm_test_result_body;
+int mnld_fm_test_timeout = 0;
+int mnld_fm_test_wait_time = 10;//wait time , second
+
+extern struct gps_device_t_ext linux_gps_device; //This symbol defined in libgnsshal.so
+
+void mnld_fm_show_help(void)
+{
+ printf("MNLD factory mode test :\r\n");
+ printf("------------------------------------------------------------------------------\r\n");
+ printf("For GNSS factory mode test or HW check.\r\n");
+ printf("------------------------------------------------------------------------------\r\n");
+ printf("The command to start MNLD factory mode test:\r\n");
+ printf("\tfm_gnss\r\n");
+}
+
+void mnld_fm_open_gnss(MNLD_FM_RESTART_TYPE restart_type, GpsInterface_ext* gps_interface, GpsCallbacks_ext* gps_cbs)
+{
+ GpsCallbacks_ext* cbs = gps_cbs;
+ GpsInterface_ext* GpsInterface_ext = gps_interface;
+
+ switch(restart_type) {
+ case MNLD_FM_RESTART_TYPE_HOT:
+ LOGD("Hot Start\n");
+ hal2mnl_gps_delete_aiding_data(GPS_DELETE_RTI);
+ break;
+ case MNLD_FM_RESTART_TYPE_WARM:
+ LOGD("Warm Start\n");
+ hal2mnl_gps_delete_aiding_data(GPS_DELETE_EPHEMERIS);
+ break;
+ case MNLD_FM_RESTART_TYPE_COLD:
+ LOGD("Cold Start\n");
+ hal2mnl_gps_delete_aiding_data(GPS_DELETE_EPHEMERIS |
+ GPS_DELETE_POSITION | GPS_DELETE_TIME | GPS_DELETE_IONO |
+ GPS_DELETE_UTC | GPS_DELETE_HEALTH);
+ break;
+ case MNLD_FM_RESTART_TYPE_FULL:
+ LOGD("Full Start\n");
+ hal2mnl_gps_delete_aiding_data(GPS_DELETE_ALL);
+ break;
+ default:
+ LOGE("ERR: read unhandled value=[%d]\n", restart_type);
+ return;
+ }
+
+ if(GpsInterface_ext != NULL && cbs != NULL)
+ {
+ GpsInterface_ext->init(cbs);
+ //hal2mnl_update_network_state(1,NETWORK_TYPE_WIFI,0,"NULL");
+ //hal2mnl_update_network_state(mnld_fm_network_on,mnld_fm_network_type,mnld_fm_network_roaming,"NULL");
+ GpsInterface_ext->start();
+ }else{
+ LOGE("param error:%p, %p\r\n",GpsInterface_ext, cbs);
+ }
+}
+
+void mnld_fm_close_gnss(GpsInterface_ext* gps_interface)
+{
+ GpsInterface_ext* GpsInterface_ext = gps_interface;
+// GpsInterface_ext = gps_device__get_gps_interface("mnld_fm stop");
+ if(GpsInterface_ext != NULL)
+ {
+ GpsInterface_ext->cleanup();
+ GpsInterface_ext->stop();
+ }else{
+ LOGE("param error");
+ }
+
+}
+
+void mnld_fm_test_timeout_hdlr(void)
+{
+ mnld_fm_test_timeout = 1;
+}
+
+int main(int argc, char** argv)
+{
+ int exit_flag = 0;
+ int wait_time = 0;
+ int idx = 0;
+ struct gps_device_t_ext *gpsdev = NULL;
+
+ //Show the recieved command
+ for(idx=0; idx<argc; idx++)
+ {
+ printf("%s ",argv[idx]);
+ }
+ printf("\r\n");
+
+ if(argc == MNLD_FM_CMD_CNT_MIN)
+ {
+ exit_flag = 0;
+ }else{
+ LOGE("Unknown command!");
+ mnld_fm_show_help();
+ exit_flag = 1;
+ }
+
+ if(!exit_flag)
+ {
+ gpsdev = &linux_gps_device;
+
+ mnld_fm_gpsinfs = (GpsInterface_ext*)gpsdev->get_gps_interface(gpsdev);
+
+ mnld_fm_cbs = mnld_fm__get_gps_callbacks();//&mnld_fm_gps_callbacks;
+ mnld_fm_test_result_body.test_stage = MNLD_FM_TEST_OPEN;
+ mnld_fm_test_result_body.sv_num = 0;
+ memset(mnld_fm_test_result_body.sv_list, 0, sizeof(mnld_fm_test_result_body.sv_list));
+ mnld_fm_test_timeout = 0;
+
+ mnld_fm_open_gnss(mnld_fm_restart_type,mnld_fm_gpsinfs,mnld_fm_cbs);
+ if (mnld_fm_test_result_body.test_stage < MNLD_FM_TEST_OPENED) { //Resolve timing issue, if stage value is bigger than opend no need to set to opened any more
+ mnld_fm_test_result_body.test_stage = MNLD_FM_TEST_OPENED;
+ }
+ //system("clear");
+ LOGD("GNSS opened for factory mode testing...");
+ // mnld_fm_test_timer = init_timer(mnld_fm_test_timeout_hdlr);
+ // start_timer(mnld_fm_test_timer,mnld_fm_restart_interval*1000);
+ do{
+ usleep(1000);
+ wait_time++;
+ if(wait_time >= mnld_fm_test_wait_time*1000)
+ {
+ mnld_fm_test_timeout = 1;
+ LOGW("GNSS factory mode test timeout...");
+ break;
+ }
+ }while(mnld_fm_test_result_body.sv_num < 2);
+ system("clear");
+ LOGD("GNSS factory mode test stage:%d, sv num:%d!",mnld_fm_test_result_body.test_stage, mnld_fm_test_result_body.sv_num);
+ if(mnld_fm_test_result_body.sv_num >= 2 /*&& mnld_fm_test_result_body.test_stage >= MNLD_FM_TEST_SV_SEARCHED*/)
+ {
+ printf("GNSS factory mode test PASS!\r\nSearched %d satellites:",mnld_fm_test_result_body.sv_num);
+ for(idx=0; idx<mnld_fm_test_result_body.sv_num; idx++)
+ {
+ printf(" %d",mnld_fm_test_result_body.sv_list[idx]);
+ }
+ printf("\r\n");
+ exit_flag = 1;
+ }else{
+ switch(mnld_fm_test_result_body.test_stage)
+ {
+ case MNLD_FM_TEST_OPEN:
+ printf("GNSS factory mode test open FAIL!");
+ break;
+ case MNLD_FM_TEST_OPENED:
+ printf("GNSS factory mode test engine start FAIL!");
+ break;
+ case MNLD_FM_TEST_ENGINE_STARTED:
+ printf("GNSS factory mode test sv search FAIL(sv num:%d)!",mnld_fm_test_result_body.sv_num);
+ break;
+ case MNLD_FM_TEST_SV_SEARCHED:
+ printf("GNSS factory mode test sv search FAIL(sv num:%d)!",mnld_fm_test_result_body.sv_num);
+ break;
+ default:
+ printf("GNSS factory mode test FAIL(stage:%d, sv num:%d)!",mnld_fm_test_result_body.test_stage, mnld_fm_test_result_body.sv_num);
+ break;
+ }
+ }
+ printf("Test Time: %dms",wait_time);
+ mnld_fm_close_gnss(mnld_fm_gpsinfs);
+ exit_flag = 1;
+
+ }
+ return 0;
+}
diff --git a/src/connectivity/gps/2.0/gnss_test/mnld_fm/src/mnld_fm_gps_cb.c b/src/connectivity/gps/2.0/gnss_test/mnld_fm/src/mnld_fm_gps_cb.c
new file mode 100644
index 0000000..a7b70fa
--- /dev/null
+++ b/src/connectivity/gps/2.0/gnss_test/mnld_fm/src/mnld_fm_gps_cb.c
@@ -0,0 +1,178 @@
+#include<pthread.h>
+#include<stdio.h>
+#include<unistd.h>
+#include<errno.h>
+#include<string.h>
+
+#include"mnld_fm.h"
+#include"mtk_lbs_utility.h"
+#include "mnldinf_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnld_fm_test"
+#endif
+
+mnld_fm_test_result mnld_fm_test_result_body;
+
+void mnld_fm_gps_location_callback(GpsLocation_ext* location)
+{
+
+// memset(&result,0,sizeof(mnld_fm_result));
+ if(location->legacyLocation.size == sizeof(GpsLocation_ext))
+ {
+ LOGD("===============Update Location Info==================");
+ LOGD("flags:0x%x", location->legacyLocation.flags);
+ LOGD("latitude:%.10lf", location->legacyLocation.latitude);
+ LOGD("longitude:%.10lf", location->legacyLocation.longitude);
+ LOGD("altitude:%.10lf", location->legacyLocation.altitude);
+ LOGD("speed:%f", location->legacyLocation.speed);
+ LOGD("bearing:%f", location->legacyLocation.bearing);
+ LOGD("timestamp:%ld", location->legacyLocation.timestamp);
+ LOGD("horizontalAccuracyMeters:%f", location->horizontalAccuracyMeters);
+ LOGD("verticalAccuracyMeters:%f", location->verticalAccuracyMeters);
+ LOGD("speedAccuracyMetersPerSecond:%f", location->speedAccuracyMetersPerSecond);
+ LOGD("bearingAccuracyDegrees:%f", location->bearingAccuracyDegrees);
+ }else {
+ LOGE("GpsLocation_ext size is wrong");
+ }
+}
+
+void mnld_fm_gps_status_callback(GpsStatus* status)
+{
+ if(status->size == sizeof(GpsStatus))
+ {
+ LOGD("GPS Status:%d\r\n", status->status);
+ if(status->status == GPS_STATUS_SESSION_BEGIN)
+ {
+ mnld_fm_test_result_body.test_stage = MNLD_FM_TEST_ENGINE_STARTED;
+ }
+
+ }else{
+ LOGE("size error!");
+ }
+}
+
+void mnld_fm_gps_sv_status_callback(GpsSvStatus* sv_info)
+{
+ int idx = 0;
+ mnld_fm_test_result_body.test_stage = MNLD_FM_TEST_SV_SEARCHED;
+ for(idx=0; idx < sv_info->num_svs; idx++)
+ {
+ mnld_fm_test_result_body.sv_list[idx] = sv_info->sv_list[idx].prn;
+ }
+ mnld_fm_test_result_body.sv_num = sv_info->num_svs;
+ LOGD("%d",mnld_fm_test_result_body.sv_num);
+}
+
+void mnld_fm_gps_nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
+{
+// LOGD("%d",timestamp);
+}
+
+void mnld_fm_gps_set_capabilities(uint32_t capabilities)
+{
+
+ LOGD("gps set capabilities");
+}
+
+void mnld_fm_gps_acquire_wakelock(void)
+{
+
+ LOGD("gps acquire wakelock");
+}
+
+void mnld_fm_gps_release_wakelock(void)
+{
+
+ LOGD("gps release wakelock");
+}
+
+void mnld_fm_gps_request_utc_time(void)
+{
+
+ LOGD("gps request utc time");
+}
+
+void mnld_fm_set_system_info_cb(const GnssSystemInfo* info)
+{
+ LOGD("set system info");
+}
+
+#define BEIDOU_SVID_OFFSET 200
+#define GALILEO_SVID_OFFSET 300
+#define GLNOASS_SVID_OFFSET 64
+void mnld_fm_gnss_sv_status_cb(GnssSvStatus_ext* sv_info)
+{
+ int idx = 0;
+ mnld_fm_test_result_body.test_stage = MNLD_FM_TEST_SV_SEARCHED;
+ for(idx=0; idx < sv_info->num_svs; idx++)
+ {
+ mnld_fm_test_result_body.sv_list[idx] = sv_info->gnss_sv_list[idx].legacySvInfo.svid;
+ if(sv_info->gnss_sv_list[idx].legacySvInfo.constellation == GNSS_CONSTELLATION_BEIDOU) {
+ mnld_fm_test_result_body.sv_list[idx] += BEIDOU_SVID_OFFSET;
+ } else if(sv_info->gnss_sv_list[idx].legacySvInfo.constellation == GNSS_CONSTELLATION_GALILEO) {
+ mnld_fm_test_result_body.sv_list[idx] += GALILEO_SVID_OFFSET;
+ } else if(sv_info->gnss_sv_list[idx].legacySvInfo.constellation == GNSS_CONSTELLATION_GLONASS) {
+ mnld_fm_test_result_body.sv_list[idx] += GLNOASS_SVID_OFFSET;
+ }
+ }
+ mnld_fm_test_result_body.sv_num = sv_info->num_svs;
+ LOGD("%d",mnld_fm_test_result_body.sv_num);
+}
+
+
+pthread_t mnld_fm_gps_create_thread(const char* name, void (*start)(void *), void* arg)
+{
+ pthread_t ntid = 0;
+ int ret = 0;
+
+ ret = pthread_create(&ntid, NULL, (void *(*)(void *))start, arg);
+
+ if(ret != 0)
+ {
+ LOGE("thread %s create fail(%s)!\r\n", name, strerror(errno));
+ ntid = 0;
+ }else{
+ LOGD("tread %s create success!\r\n", name);
+ }
+
+ return ntid;
+}
+
+void mnld_fm_gnss_set_name_cb(const char* name, int length)
+{
+ LOGD("gnss set name");
+}
+
+void mnld_fm_gnss_request_location_cb(bool independentFromGnss, bool isUserEmergency)
+{
+ LOGD("gnss request location");
+}
+
+void mnld_fm_agnss_location_callback(GpsLocation_ext* location) {
+ LOGD("Get agps location");
+}
+
+GpsCallbacks_ext mnld_fm_gps_callbacks = {
+ .size = sizeof(GpsCallbacks_ext),
+ .location_cb = mnld_fm_gps_location_callback,
+ .status_cb = mnld_fm_gps_status_callback,
+ .sv_status_cb = mnld_fm_gps_sv_status_callback,
+ .nmea_cb = mnld_fm_gps_nmea_callback,
+ .set_capabilities_cb = mnld_fm_gps_set_capabilities,
+ .acquire_wakelock_cb = mnld_fm_gps_acquire_wakelock,
+ .release_wakelock_cb = mnld_fm_gps_release_wakelock,
+ .create_thread_cb = mnld_fm_gps_create_thread,
+ .request_utc_time_cb = mnld_fm_gps_request_utc_time,
+ .set_system_info_cb = mnld_fm_set_system_info_cb,
+ .gnss_sv_status_cb = mnld_fm_gnss_sv_status_cb,
+ .set_name_cb = mnld_fm_gnss_set_name_cb,
+ .request_location_cb = mnld_fm_gnss_request_location_cb,
+ .agps_location_cb = mnld_fm_agnss_location_callback,
+};
+
+GpsCallbacks_ext* mnld_fm__get_gps_callbacks(void)
+{
+ return &mnld_fm_gps_callbacks;
+}
diff --git a/src/connectivity/gps/2.0/gps_hal/Android.mk b/src/connectivity/gps/2.0/gps_hal/Android.mk
new file mode 100644
index 0000000..6091543
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/Android.mk
@@ -0,0 +1,79 @@
+# Copyright Statement:
+#
+# This software/firmware and related documentation ("MediaTek Software") are
+# protected under relevant copyright laws. The information contained herein
+# is confidential and proprietary to MediaTek Inc. and/or its licensors.
+# Without the prior written permission of MediaTek inc. and/or its licensors,
+# any reproduction, modification, use or disclosure of MediaTek Software,
+# and information contained herein, in whole or in part, shall be strictly prohibited.
+#
+# MediaTek Inc. (C) 2016. All rights reserved.
+#
+# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+
+ifeq ($(BOARD_GPS_LIBRARIES), true)
+LOCAL_PATH := $(call my-dir)
+
+# HAL module implemenation, not prelinked and stored in
+# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libcutils \
+ libhardware
+
+LOCAL_HEADER_LIBRARIES := libcutils_headers
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/inc \
+ $(LOCAL_PATH)/inc/hardware \
+
+LOCAL_SRC_FILES += \
+ src/hal2mnl_interface.c \
+ src/hal_mnl_interface_common.c \
+ src/data_coder.c \
+ src/mtk_lbs_utility.c \
+ src/agpsinf.c \
+ src/gpshal.c \
+ src/gpshal_worker.c \
+ src/gfchal_mnl_interface.c \
+ src/geofenceinf.c \
+
+ifeq ($(MTK_GPS_CHIP),MTK_GPS_MT3337)
+LOCAL_SRC_FILES += \
+ src/gpsinf3337.c
+else
+LOCAL_SRC_FILES += \
+ src/gpsinf.c
+endif
+
+LOCAL_MODULE := gps.default
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_TAGS := optional
+
+include $(MTK_SHARED_LIBRARY)
+endif
diff --git a/src/connectivity/gps/2.0/gps_hal/MTK_LICENSE b/src/connectivity/gps/2.0/gps_hal/MTK_LICENSE
new file mode 100644
index 0000000..901b162
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/MTK_LICENSE
@@ -0,0 +1,35 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein
+is confidential and proprietary to MediaTek Inc. and/or its licensors.
+Without the prior written permission of MediaTek inc. and/or its licensors,
+any reproduction, modification, use or disclosure of MediaTek Software,
+and information contained herein, in whole or in part, shall be strictly prohibited.
+
+MediaTek Inc. (C) 2018. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+
+The following software/firmware and/or related documentation ("MediaTek Software")
+have been modified by MediaTek Inc. All revisions are subject to any receiver's
+applicable license agreements with MediaTek Inc.
+
+
diff --git a/src/connectivity/gps/2.0/gps_hal/Makefile b/src/connectivity/gps/2.0/gps_hal/Makefile
new file mode 100644
index 0000000..e98743a
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/Makefile
@@ -0,0 +1,67 @@
+#CC=gcc
+#CXX=g++
+
+FLAGS=$(CFLAG)
+
+FLAGS+=\
+ -g \
+ -Wall \
+ -fPIC \
+ -shared \
+ -D__COMPILE_OPTION__ \
+ -D__LINUX_OS__ \
+ -fPIC \
+
+# -m32 \
+
+CPPFLAGS=\
+ -std=c++11 \
+
+INCLUDE=\
+ -I./inc/ \
+ -I./inc/hardware \
+ -I./mnldinf/inc/ \
+
+LIBS=\
+ -ldl \
+ -lrt \
+ -lpthread \
+
+CXXSRC=\
+
+CSRC=\
+ mnldinf/src/mnldinf_data_coder.c \
+ mnldinf/src/mnldinf_basic.c \
+ mnldinf/src/mnldinf_ext.c \
+ mnldinf/src/mnldinf_log.c \
+ mnldinf/src/mnldinf_utility.c \
+ src/hal2mnl_interface.c \
+ src/agpsinf.c \
+ src/gpshal.c \
+ src/gpshal_worker.c \
+ src/gpsinf.c
+
+EXECUTABLE=libgnsshal.so
+COBJS=$(CSRC:.c=.o)
+CXXOBJS=$(CXXSRC:.cpp=.o)
+
+all: $(EXECUTABLE)
+
+$(EXECUTABLE): $(COBJS) $(CXXOBJS)
+ $(CC) --sysroot=$(BB_SYSROOT_ADD) $(COBJS) $(CXXOBJS) $(LIBS) $(FLAGS) $(CPPFLAGS) -o $@
+
+%.o : %.c
+ $(CC) -c $(FLAGS) $(INCLUDE) -o $@ $<
+
+%.o : %.cpp
+ $(CC) -c $(FLAGS) $(INCLUDE) $(CPPFLAGS) -o $@ $<
+
+.PHONY: install clean
+install:
+ install -d $(DESTDIR)/${libdir}
+ install -m 0755 $(EXECUTABLE) $(DESTDIR)/${libdir}
+
+clean:
+ rm -f $(EXECUTABLE) rm -rf *.o
+ find ./ -name *.o | xargs rm -rf
+
diff --git a/src/connectivity/gps/2.0/gps_hal/NOTICE b/src/connectivity/gps/2.0/gps_hal/NOTICE
new file mode 100644
index 0000000..c46827a
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/NOTICE
@@ -0,0 +1,212 @@
+This MediaTek software package contains software with the following notices and under the following licenses:
+
+==============================================================================================================
+
+Copyright (c) 2005-2008, The Android Open Source Project
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+
+
+
+Copyright (c) 2005-2008, The Android Open Source Project
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other materials provided with the distribution.
+ * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+
diff --git a/src/connectivity/gps/2.0/gps_hal/README b/src/connectivity/gps/2.0/gps_hal/README
new file mode 100644
index 0000000..92f6303
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/README
@@ -0,0 +1,44 @@
+This directory contains GPS HAL layer code.
+
+WHAT IT DOES?
+=============
+It provide GPS interfaces for gps provider on frameworks,which allow init/open/close/cleanup gps
+when mnld daemon is launched.
+
+HOW IT WAS BUILT?
+==================
+
+It needs the following libs from AOSP:
+1. libc.so
+2. libcutils
+3. libnetutils
+4. libhardware
+5. libandroid_runtime
+6. libnativehelper
+7. libcrypto
+8. libssl
+9. libz
+
+and the following libs from MediaTek:
+1. liblog.so
+2. libepos.a
+3. libcurl
+
+All source/dependency modules of this module are already put in
+'vendor/mediatek/libs' folder.
+
+
+HOW TO USE IT?
+==============
+
+Files in this directory is used to
+generate a library which's name is 'gps.mtxxxx.so'
+
+
+gps.mtxxxx
+mtxxxx means chip platform name,
+The lib 'gps.mtxxxx' is loaded by system_server,
+GPS Location provider will call gps_module_methods API, if system_server is launched.
+
+All the source code of this library were written by MediaTek co..
+
diff --git a/src/connectivity/gps/2.0/gps_hal/inc/data_coder.h b/src/connectivity/gps/2.0/gps_hal/inc/data_coder.h
new file mode 100644
index 0000000..5060eb6
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/inc/data_coder.h
@@ -0,0 +1,7 @@
+#ifndef __DATA_CODER_H__
+#define __DATA_CODER_H__
+
+#include "mnldinf_data_coder.h"
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/gps_hal/inc/gpshal.h b/src/connectivity/gps/2.0/gps_hal/inc/gpshal.h
new file mode 100644
index 0000000..ee4ec44
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/inc/gpshal.h
@@ -0,0 +1,111 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#ifndef __GPS_HAL_H__
+#define __GPS_HAL_H__
+
+#include "hardware/gps_mtk.h"
+#include <pthread.h>
+
+#ifndef __unused
+#define __unused
+#endif
+
+//=========================================================
+
+#define MAX_EPOLL_EVENT 50
+#define GNSS_NAME_LEN (255)
+
+//=========================================================
+
+typedef enum { // state order is important
+ GPSHAL_STATE_UNKNOWN,
+ GPSHAL_STATE_RESOURCE,
+ GPSHAL_STATE_CLEANUP,
+ GPSHAL_STATE_INIT, // == STOP
+ GPSHAL_STATE_STOP, // == INIT
+ GPSHAL_STATE_START
+} gpshal_state;
+
+typedef struct {
+ int fd_mnl2hal_basic;
+ int fd_mnl2hal_ext;
+ int fd_worker_epoll;
+ pthread_t thd_worker;
+
+ pthread_mutex_t mutex_gps_state_intent;
+ gpshal_state gps_state_intent; // what we want
+ gpshal_state gps_state; // what we are, but we may fail to change it
+ int gps_cap;
+ char gps_name[GNSS_NAME_LEN];
+ char proxy_apps[HAL_NFW_USER_NUM_MAX*HAL_NFW_USER_NAME_LEN]; //NFW user app list
+
+ GpsCallbacks_ext* gps_cbs;
+ AGpsCallbacks* agps_cbs;
+ GpsNiCallbacks* gpsni_cbs;
+ AGpsRilCallbacks* agpsril_cbs;
+ GpsMeasurementCallbacks_ext* meas_cbs;
+ MeasurementCorrectionCallbacks_ext* meas_correct_cbs;
+ GnssVisibilityControlCallback_ext* visibility_control_cbs;
+ GpsNavigationMessageCallbacks* navimsg_cbs;
+ GpsGeofenceCallbacks* geofence_cbs;
+ VzwDebugCallbacks* vzw_debug_cbs;
+ timer_t mnl_retry_timer;
+} gpshal_context_t;
+
+//=========================================================
+
+extern gpshal_context_t g_gpshal_ctx;
+extern const AGpsInterface_ext mtk_agps_inf;
+extern const GpsNiInterface mtk_gps_ni_inf;
+extern const AGpsRilInterface_ext mtk_agps_ril_inf;
+
+//=========================================================
+
+extern const char* gpshal_state_to_string(gpshal_state state);
+
+extern int gpshal_gpscbs_save(GpsCallbacks_ext* src);
+
+extern void gpshal_set_gps_state_intent(gpshal_state newState);
+
+extern void gpshal2mnl_gps_init();
+extern void gpshal2mnl_gps_start();
+extern void gpshal2mnl_gps_stop();
+extern void gpshal2mnl_gps_cleanup();
+
+extern void gpshal_worker_thread(void *arg);
+
+extern void gpshal_mnl_retry_routine(void);
+
+#endif // __GPS_HAL_DEBUG_H__
diff --git a/src/connectivity/gps/2.0/gps_hal/inc/gpshal_param_check.h b/src/connectivity/gps/2.0/gps_hal/inc/gpshal_param_check.h
new file mode 100644
index 0000000..c87ec98
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/inc/gpshal_param_check.h
@@ -0,0 +1,91 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef __GPS_HAL_PARAM_CHECK_H__
+#define __GPS_HAL_PARAM_CHECK_H__
+
+#include <string.h>
+
+#if 0 != PARAM_CHECK // PARAM_CHECK is enabled
+ #define GPS_HW_MODULE_OPEN__CHECK_PARAM \
+ do { \
+ if (&HAL_MODULE_INFO_SYM != module) { \
+ ALOGT("-: Bad module object"); \
+ return -1; /* Fail: any non-zero value */ \
+ } else if (NULL == id || strcmp(id, HAL_MODULE_INFO_SYM.id)) { \
+ ALOGT("-: Bad id"); \
+ return -2; \
+ } else if (NULL == device) { \
+ ALOGT("-: Bad device"); \
+ return -3; \
+ } \
+ } while (0)
+ #define GPS_DEVICE__GET_GPS_INTERFACE__CHECK_PARAM \
+ do { \
+ if (NULL == device || \
+ &HAL_MODULE_INFO_SYM != device->common.module || \
+ gps_device__get_gps_interface != device->get_gps_interface) { \
+ ALOGT("-: Bad device object"); \
+ return NULL; \
+ } \
+ } while (0)
+#elif !defined(NDEBUG) // assert() is effective
+ #define GPS_HW_MODULE_OPEN__CHECK_PARAM \
+ do { \
+ assert(&HAL_MODULE_INFO_SYM == module); \
+ assert(NULL != id); \
+ assert(NULL != device); \
+ assert(0 == strcmp(id, HAL_MODULE_INFO_SYM.id)); \
+ } while (0)
+ #define GPS_DEVICE__GET_GPS_INTERFACE__CHECK_PARAM \
+ do { \
+ assert(NULL != device); \
+ assert(&HAL_MODULE_INFO_SYM == device->common.module); \
+ assert(gps_device__get_gps_interface == device->get_gps_interface); \
+ } while (0)
+#else
+ // PARAM_CHECK is disabled
+ // And assert() is not effective
+ #define GPS_HW_MODULE_OPEN__CHECK_PARAM \
+ do { \
+ UNUSED(module); \
+ UNUSED(id); \
+ } while (0)
+ #define GPS_DEVICE__GET_GPS_INTERFACE__CHECK_PARAM \
+ UNUSED(device)
+#endif
+
+
+#endif // __GPS_HAL_PARAM_CHECK_H__
\ No newline at end of file
diff --git a/src/connectivity/gps/2.0/gps_hal/inc/hal2mnl_interface.h b/src/connectivity/gps/2.0/gps_hal/inc/hal2mnl_interface.h
new file mode 100644
index 0000000..183acce
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/inc/hal2mnl_interface.h
@@ -0,0 +1,63 @@
+#ifndef __HAL2MNL_INTERFACE_H__
+#define __HAL2MNL_INTERFACE_H__
+
+#include "hal_mnl_interface_common.h"
+#include "hardware/gps_mtk.h"
+#include "mnldinf_basic.h"
+#include "mnldinf_ext.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int hal2mnl_hal_reboot();
+
+int hal2mnl_gps_init();
+int hal2mnl_gps_start();
+int hal2mnl_gps_stop();
+int hal2mnl_gps_cleanup();
+
+int hal2mnl_gps_inject_time(int64_t time, int64_t time_reference, int uncertainty);
+int hal2mnl_gps_inject_location(double lat, double lng, float acc);
+int hal2mnl_gps_delete_aiding_data(int flags);
+int hal2mnl_gps_set_position_mode(gps_pos_mode mode, gps_pos_recurrence recurrence,
+ int min_interval, int preferred_acc, int preferred_time, bool lowPowerMode);
+
+int hal2mnl_data_conn_open(const char* apn);
+int hal2mnl_data_conn_open_with_apn_ip_type(uint64_t networkHandle, const char* apn, apn_ip_type ip_type);
+int hal2mnl_data_conn_closed();
+int hal2mnl_data_conn_failed();
+
+int hal2mnl_set_server(agps_type type, const char* hostname, int port);
+int hal2mnl_set_ref_location(cell_type type, int mcc, int mnc, int lac, int cid);
+int hal2mnl_set_id(agps_id_type type, const char* setid);
+
+int hal2mnl_ni_message(char* msg, int len);
+int hal2mnl_ni_respond(int notif_id, ni_user_response_type user_response);
+
+int hal2mnl_update_network_state(uint64_t networkHandle, bool isConnected,
+ uint16_t capabilities, const char* apn);
+int hal2mnl_update_network_availability(int available, const char* apn);
+
+int hal2mnl_set_gps_measurement(bool enabled, bool enableFullTracking);
+int hal2mnl_set_gps_navigation(bool enabled);
+
+int hal2mnl_set_vzw_debug(bool enabled);
+int hal2mnl_update_gnss_config(const char* config_data, int length);
+int hal2mnl_setBlacklist(long long* blacklist, int32_t size);
+int hal2mnl_set_correction(MeasurementCorrections* corrections);
+int hal2mnl_set_nfw_access(char* proxy_apps, int32_t length);
+int hal2mnl_send_pmtk(char* msg, int len);
+
+// -1 means failure
+int create_mnl2hal_fd_basic();
+
+// -1 means failure
+int create_mnl2hal_fd_ext();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/gps_hal/inc/hal_mnl_interface_common.h b/src/connectivity/gps/2.0/gps_hal/inc/hal_mnl_interface_common.h
new file mode 100644
index 0000000..8d76046
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/inc/hal_mnl_interface_common.h
@@ -0,0 +1,12 @@
+#ifndef __HAL_MNL_INTERFACE_COMMON_H__
+#define __HAL_MNL_INTERFACE_COMMON_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+
+#include "mnldinf_common.h"
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/gps_hal/inc/hardware/gps.h b/src/connectivity/gps/2.0/gps_hal/inc/hardware/gps.h
new file mode 100644
index 0000000..ac749c1
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/inc/hardware/gps.h
@@ -0,0 +1,2238 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_H
+
+#ifdef __LINUX_OS__
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+
+__BEGIN_DECLS
+
+#ifndef u_char
+#define u_char unsigned char
+#endif
+
+/*
+ * Enums defined in HIDL in hardware/interfaces are auto-generated and present
+ * in gnss-base.h.
+ */
+
+/* for compatibility */
+
+/*#define GPS_REQUEST_AGPS_DATA_CONN GNSS_REQUEST_AGNSS_DATA_CONN
+#define GPS_RELEASE_AGPS_DATA_CONN GNSS_RELEASE_AGNSS_DATA_CONN
+#define GPS_AGPS_DATA_CONNECTED GNSS_AGNSS_DATA_CONNECTED
+#define GPS_AGPS_DATA_CONN_DONE GNSS_AGNSS_DATA_CONN_DONE
+#define GPS_AGPS_DATA_CONN_FAILED GNSS_AGNSS_DATA_CONN_FAILED
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_MMS AGPS_RIL_NETWORK_TYPE_MMS
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL AGPS_RIL_NETWORK_TYPE_SUPL
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN AGPS_RIL_NETWORK_TYPE_DUN
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI AGPS_RIL_NETWORK_TYPE_HIPRI
+#define AGPS_RIL_NETWORK_TTYPE_WIMAX AGPS_RIL_NETWORK_TYPE_WIMAX
+#define GNSS_MULTIPATH_INDICATOR_NOT_PRESENT GNSS_MULTIPATH_INDICATIOR_NOT_PRESENT
+#define AGPS_SETID_TYPE_MSISDN AGPS_SETID_TYPE_MSISDM
+#define GPS_MEASUREMENT_OPERATION_SUCCESS GPS_MEASUREMENT_SUCCESS
+#define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS GPS_NAVIGATION_MESSAGE_SUCCESS
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L1CA
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L2CNAV
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L5CNAV
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2 GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_CNAV2
+#define GPS_LOCATION_HAS_ACCURACY GPS_LOCATION_HAS_HORIZONTAL_ACCURACY
+*/
+/**
+ * The id of this module
+ */
+#define GPS_HARDWARE_MODULE_ID "gps"
+
+#define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS 0
+#define GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT -100
+#define GPS_NAVIGATION_MESSAGE_ERROR_GENERIC -101
+
+/** Milliseconds since January 1, 1970 */
+typedef int64_t GpsUtcTime;
+
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GPS_MAX_SVS 32
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GNSS_MAX_SVS 64
+
+/** Maximum number of Measurements in gps_measurement_callback(). */
+#define GPS_MAX_MEASUREMENT 32
+
+/** Maximum number of Measurements in gnss_measurement_callback(). */
+#define GNSS_MAX_MEASUREMENT 64
+
+/** Requested operational mode for GPS operation. */
+typedef uint32_t GpsPositionMode;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** Mode for running GPS standalone (no assistance). */
+#define GPS_POSITION_MODE_STANDALONE 0
+/** AGPS MS-Based mode. */
+#define GPS_POSITION_MODE_MS_BASED 1
+/**
+ * AGPS MS-Assisted mode. This mode is not maintained by the platform anymore.
+ * It is strongly recommended to use GPS_POSITION_MODE_MS_BASED instead.
+ */
+#define GPS_POSITION_MODE_MS_ASSISTED 2
+
+/** Requested recurrence mode for GPS operation. */
+typedef uint32_t GpsPositionRecurrence;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** Receive GPS fixes on a recurring basis at a specified period. */
+#define GPS_POSITION_RECURRENCE_PERIODIC 0
+/** Request a single shot GPS fix. */
+#define GPS_POSITION_RECURRENCE_SINGLE 1
+
+/** GPS status event values. */
+typedef uint16_t GpsStatusValue;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** GPS status unknown. */
+#define GPS_STATUS_NONE 0
+/** GPS has begun navigating. */
+#define GPS_STATUS_SESSION_BEGIN 1
+/** GPS has stopped navigating. */
+#define GPS_STATUS_SESSION_END 2
+/** GPS has powered on but is not navigating. */
+#define GPS_STATUS_ENGINE_ON 3
+/** GPS is powered off. */
+#define GPS_STATUS_ENGINE_OFF 4
+
+/** Flags to indicate which values are valid in a GpsLocation. */
+typedef uint16_t GpsLocationFlags;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** GpsLocation has valid latitude and longitude. */
+#define GPS_LOCATION_HAS_LAT_LONG 0x0001
+/** GpsLocation has valid altitude. */
+#define GPS_LOCATION_HAS_ALTITUDE 0x0002
+/** GpsLocation has valid speed. */
+#define GPS_LOCATION_HAS_SPEED 0x0004
+/** GpsLocation has valid bearing. */
+#define GPS_LOCATION_HAS_BEARING 0x0008
+/** GpsLocation has valid accuracy. */
+#define GPS_LOCATION_HAS_ACCURACY 0x0010
+
+/**
+ * GPS HAL schedules fixes for GPS_POSITION_RECURRENCE_PERIODIC mode. If this is
+ * not set, then the framework will use 1000ms for min_interval and will start
+ * and call start() and stop() to schedule the GPS.
+ */
+#define GPS_CAPABILITY_SCHEDULING (1 << 0)
+/** GPS supports MS-Based AGPS mode */
+#define GPS_CAPABILITY_MSB (1 << 1)
+/** GPS supports MS-Assisted AGPS mode */
+#define GPS_CAPABILITY_MSA (1 << 2)
+/** GPS supports single-shot fixes */
+#define GPS_CAPABILITY_SINGLE_SHOT (1 << 3)
+/** GPS supports on demand time injection */
+#define GPS_CAPABILITY_ON_DEMAND_TIME (1 << 4)
+/** GPS supports Geofencing */
+#define GPS_CAPABILITY_GEOFENCING (1 << 5)
+/** GPS supports Measurements. */
+#define GPS_CAPABILITY_MEASUREMENTS (1 << 6)
+/** GPS supports Navigation Messages */
+#define GPS_CAPABILITY_NAV_MESSAGES (1 << 7)
+
+/**
+ * Flags used to specify which aiding data to delete when calling
+ * delete_aiding_data().
+ */
+typedef uint16_t GpsAidingData;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+#define GPS_DELETE_EPHEMERIS 0x0001
+#define GPS_DELETE_ALMANAC 0x0002
+#define GPS_DELETE_POSITION 0x0004
+#define GPS_DELETE_TIME 0x0008
+#define GPS_DELETE_IONO 0x0010
+#define GPS_DELETE_UTC 0x0020
+#define GPS_DELETE_HEALTH 0x0040
+#define GPS_DELETE_SVDIR 0x0080
+#define GPS_DELETE_SVSTEER 0x0100
+#define GPS_DELETE_SADATA 0x0200
+#define GPS_DELETE_RTI 0x0400
+#define GPS_DELETE_CELLDB_INFO 0x8000
+#define GPS_DELETE_ALL 0xFFFF
+
+/** AGPS type */
+typedef uint16_t AGpsType;
+#define AGPS_TYPE_SUPL 1
+#define AGPS_TYPE_C2K 2
+
+typedef uint16_t AGpsSetIDType;
+#define AGPS_SETID_TYPE_NONE 0
+#define AGPS_SETID_TYPE_IMSI 1
+#define AGPS_SETID_TYPE_MSISDN 2
+
+typedef uint16_t ApnIpType;
+#define APN_IP_INVALID 0
+#define APN_IP_IPV4 1
+#define APN_IP_IPV6 2
+#define APN_IP_IPV4V6 3
+
+/**
+ * String length constants
+ */
+#define GPS_NI_SHORT_STRING_MAXLEN 256
+#define GPS_NI_LONG_STRING_MAXLEN 2048
+
+/**
+ * GpsNiType constants
+ */
+typedef uint32_t GpsNiType;
+#define GPS_NI_TYPE_VOICE 1
+#define GPS_NI_TYPE_UMTS_SUPL 2
+#define GPS_NI_TYPE_UMTS_CTRL_PLANE 3
+
+/**
+ * GpsNiNotifyFlags constants
+ */
+typedef uint32_t GpsNiNotifyFlags;
+/** NI requires notification */
+#define GPS_NI_NEED_NOTIFY 0x0001
+/** NI requires verification */
+#define GPS_NI_NEED_VERIFY 0x0002
+/** NI requires privacy override, no notification/minimal trace */
+#define GPS_NI_PRIVACY_OVERRIDE 0x0004
+
+/**
+ * GPS NI responses, used to define the response in
+ * NI structures
+ */
+typedef int GpsUserResponseType;
+#define GPS_NI_RESPONSE_ACCEPT 1
+#define GPS_NI_RESPONSE_DENY 2
+#define GPS_NI_RESPONSE_NORESP 3
+
+/**
+ * NI data encoding scheme
+ */
+typedef int GpsNiEncodingType;
+#define GPS_ENC_NONE 0
+#define GPS_ENC_SUPL_GSM_DEFAULT 1
+#define GPS_ENC_SUPL_UTF8 2
+#define GPS_ENC_SUPL_UCS2 3
+#define GPS_ENC_UNKNOWN -1
+
+/** AGPS status event values. */
+typedef uint16_t AGpsStatusValue;
+/** GPS requests data connection for AGPS. */
+#define GPS_REQUEST_AGPS_DATA_CONN 1
+/** GPS releases the AGPS data connection. */
+#define GPS_RELEASE_AGPS_DATA_CONN 2
+/** AGPS data connection initiated */
+#define GPS_AGPS_DATA_CONNECTED 3
+/** AGPS data connection completed */
+#define GPS_AGPS_DATA_CONN_DONE 4
+/** AGPS data connection failed */
+#define GPS_AGPS_DATA_CONN_FAILED 5
+
+typedef uint16_t AGpsRefLocationType;
+#define AGPS_REF_LOCATION_TYPE_GSM_CELLID 1
+#define AGPS_REF_LOCATION_TYPE_UMTS_CELLID 2
+#define AGPS_REF_LOCATION_TYPE_MAC 3
+#define AGPS_REF_LOCATION_TYPE_LTE_CELLID 4
+
+/* Deprecated, to be removed in the next Android release. */
+#define AGPS_REG_LOCATION_TYPE_MAC 3
+
+/** Network types for update_network_state "type" parameter */
+#define AGPS_RIL_NETWORK_TYPE_MOBILE 0
+#define AGPS_RIL_NETWORK_TYPE_WIFI 1
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_MMS 2
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL 3
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN 4
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI 5
+#define AGPS_RIL_NETWORK_TTYPE_WIMAX 6
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsClockFlags;
+#define GPS_CLOCK_HAS_LEAP_SECOND (1<<0)
+#define GPS_CLOCK_HAS_TIME_UNCERTAINTY (1<<1)
+#define GPS_CLOCK_HAS_FULL_BIAS (1<<2)
+#define GPS_CLOCK_HAS_BIAS (1<<3)
+#define GPS_CLOCK_HAS_BIAS_UNCERTAINTY (1<<4)
+#define GPS_CLOCK_HAS_DRIFT (1<<5)
+#define GPS_CLOCK_HAS_DRIFT_UNCERTAINTY (1<<6)
+
+/**
+ * Flags to indicate what fields in GnssClock are valid.
+ */
+typedef uint16_t GnssClockFlags;
+/** A valid 'leap second' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_LEAP_SECOND (1<<0)
+/** A valid 'time uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_TIME_UNCERTAINTY (1<<1)
+/** A valid 'full bias' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_FULL_BIAS (1<<2)
+/** A valid 'bias' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_BIAS (1<<3)
+/** A valid 'bias uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_BIAS_UNCERTAINTY (1<<4)
+/** A valid 'drift' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_DRIFT (1<<5)
+/** A valid 'drift uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY (1<<6)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsClockType;
+#define GPS_CLOCK_TYPE_UNKNOWN 0
+#define GPS_CLOCK_TYPE_LOCAL_HW_TIME 1
+#define GPS_CLOCK_TYPE_GPS_TIME 2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint32_t GpsMeasurementFlags;
+#define GPS_MEASUREMENT_HAS_SNR (1<<0)
+#define GPS_MEASUREMENT_HAS_ELEVATION (1<<1)
+#define GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY (1<<2)
+#define GPS_MEASUREMENT_HAS_AZIMUTH (1<<3)
+#define GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY (1<<4)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE (1<<5)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY (1<<6)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE (1<<7)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY (1<<8)
+#define GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9)
+#define GPS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12)
+#define GPS_MEASUREMENT_HAS_BIT_NUMBER (1<<13)
+#define GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT (1<<14)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT (1<<15)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY (1<<16)
+#define GPS_MEASUREMENT_HAS_USED_IN_FIX (1<<17)
+#define GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE (1<<18)
+
+/**
+ * Flags to indicate what fields in GnssMeasurement are valid.
+ */
+typedef uint32_t GnssMeasurementFlags;
+/** A valid 'snr' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_SNR (1<<0)
+/** A valid 'carrier frequency' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9)
+/** A valid 'carrier cycles' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10)
+/** A valid 'carrier phase' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11)
+/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsLossOfLock;
+#define GPS_LOSS_OF_LOCK_UNKNOWN 0
+#define GPS_LOSS_OF_LOCK_OK 1
+#define GPS_LOSS_OF_LOCK_CYCLE_SLIP 2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. Use GnssMultipathIndicator instead.
+ */
+typedef uint8_t GpsMultipathIndicator;
+#define GPS_MULTIPATH_INDICATOR_UNKNOWN 0
+#define GPS_MULTIPATH_INDICATOR_DETECTED 1
+#define GPS_MULTIPATH_INDICATOR_NOT_USED 2
+
+/**
+ * Enumeration of available values for the GNSS Measurement's multipath
+ * indicator.
+ */
+typedef uint8_t GnssMultipathIndicator;
+/** The indicator is not available or unknown. */
+#define GNSS_MULTIPATH_INDICATOR_UNKNOWN 0
+/** The measurement is indicated to be affected by multipath. */
+#define GNSS_MULTIPATH_INDICATOR_PRESENT 1
+/** The measurement is indicated to be not affected by multipath. */
+#define GNSS_MULTIPATH_INDICATOR_NOT_PRESENT 2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsMeasurementState;
+#define GPS_MEASUREMENT_STATE_UNKNOWN 0
+#define GPS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define GPS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define GPS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define GPS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+#define GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4)
+
+/**
+ * Flags indicating the GNSS measurement state.
+ *
+ * The expected behavior here is for GPS HAL to set all the flags that applies.
+ * For example, if the state for a satellite is only C/A code locked and bit
+ * synchronized, and there is still millisecond ambiguity, the state should be
+ * set as:
+ *
+ * GNSS_MEASUREMENT_STATE_CODE_LOCK | GNSS_MEASUREMENT_STATE_BIT_SYNC |
+ * GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS
+ *
+ * If GNSS is still searching for a satellite, the corresponding state should be
+ * set to GNSS_MEASUREMENT_STATE_UNKNOWN(0).
+ */
+typedef uint32_t GnssMeasurementState;
+#define GNSS_MEASUREMENT_STATE_UNKNOWN 0
+#define GNSS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define GNSS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define GNSS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+#define GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4)
+#define GNSS_MEASUREMENT_STATE_SYMBOL_SYNC (1<<5)
+#define GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC (1<<6)
+#define GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED (1<<7)
+#define GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC (1<<8)
+#define GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC (1<<9)
+#define GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK (1<<10)
+#define GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK (1<<11)
+#define GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC (1<<12)
+#define GNSS_MEASUREMENT_STATE_SBAS_SYNC (1<<13)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsAccumulatedDeltaRangeState;
+#define GPS_ADR_STATE_UNKNOWN 0
+#define GPS_ADR_STATE_VALID (1<<0)
+#define GPS_ADR_STATE_RESET (1<<1)
+#define GPS_ADR_STATE_CYCLE_SLIP (1<<2)
+
+/**
+ * Flags indicating the Accumulated Delta Range's states.
+ */
+typedef uint16_t GnssAccumulatedDeltaRangeState;
+#define GNSS_ADR_STATE_UNKNOWN 0
+#define GNSS_ADR_STATE_VALID (1<<0)
+#define GNSS_ADR_STATE_RESET (1<<1)
+#define GNSS_ADR_STATE_CYCLE_SLIP (1<<2)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsNavigationMessageType;
+#define GPS_NAVIGATION_MESSAGE_TYPE_UNKNOWN 0
+#define GPS_NAVIGATION_MESSAGE_TYPE_L1CA 1
+#define GPS_NAVIGATION_MESSAGE_TYPE_L2CNAV 2
+#define GPS_NAVIGATION_MESSAGE_TYPE_L5CNAV 3
+#define GPS_NAVIGATION_MESSAGE_TYPE_CNAV2 4
+
+/**
+ * Enumeration of available values to indicate the GNSS Navigation message
+ * types.
+ *
+ * For convenience, first byte is the GnssConstellationType on which that signal
+ * is typically transmitted
+ */
+typedef int16_t GnssNavigationMessageType;
+
+#define GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN 0
+/** GPS L1 C/A message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA 0x0101
+/** GPS L2-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV 0x0102
+/** GPS L5-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV 0x0103
+/** GPS CNAV-2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2 0x0104
+/** Glonass L1 CA message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA 0x0301
+/** Beidou D1 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1 0x0501
+/** Beidou D2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2 0x0502
+/** Galileo I/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I 0x0601
+/** Galileo F/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F 0x0602
+
+/**
+ * Status of Navigation Message
+ * When a message is received properly without any parity error in its navigation words, the
+ * status should be set to NAV_MESSAGE_STATUS_PARITY_PASSED. But if a message is received
+ * with words that failed parity check, but GPS is able to correct those words, the status
+ * should be set to NAV_MESSAGE_STATUS_PARITY_REBUILT.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+typedef uint16_t NavigationMessageStatus;
+#define NAV_MESSAGE_STATUS_UNKNOWN 0
+#define NAV_MESSAGE_STATUS_PARITY_PASSED (1<<0)
+#define NAV_MESSAGE_STATUS_PARITY_REBUILT (1<<1)
+
+/* This constant is deprecated, and will be removed in the next release. */
+#define NAV_MESSAGE_STATUS_UNKONW 0
+
+/**
+ * Flags that indicate information about the satellite
+ */
+typedef uint8_t GnssSvFlags;
+#define GNSS_SV_FLAGS_NONE 0
+#define GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA (1 << 0)
+#define GNSS_SV_FLAGS_HAS_ALMANAC_DATA (1 << 1)
+#define GNSS_SV_FLAGS_USED_IN_FIX (1 << 2)
+
+/**
+ * Constellation type of GnssSvInfo
+ */
+typedef uint8_t GnssConstellationType;
+#define GNSS_CONSTELLATION_UNKNOWN 0
+#define GNSS_CONSTELLATION_GPS 1
+#define GNSS_CONSTELLATION_SBAS 2
+#define GNSS_CONSTELLATION_GLONASS 3
+#define GNSS_CONSTELLATION_QZSS 4
+#define GNSS_CONSTELLATION_BEIDOU 5
+#define GNSS_CONSTELLATION_GALILEO 6
+
+/**
+ * Name for the GPS XTRA interface.
+ */
+#define GPS_XTRA_INTERFACE "gps-xtra"
+
+/**
+ * Name for the GPS DEBUG interface.
+ */
+#define GPS_DEBUG_INTERFACE "gps-debug"
+
+/**
+ * Name for the AGPS interface.
+ */
+#define AGPS_INTERFACE "agps"
+
+/**
+ * Name of the Supl Certificate interface.
+ */
+#define SUPL_CERTIFICATE_INTERFACE "supl-certificate"
+
+/**
+ * Name for NI interface
+ */
+#define GPS_NI_INTERFACE "gps-ni"
+
+/**
+ * Name for the AGPS-RIL interface.
+ */
+#define AGPS_RIL_INTERFACE "agps_ril"
+
+/**
+ * Name for the GPS_Geofencing interface.
+ */
+#define GPS_GEOFENCING_INTERFACE "gps_geofencing"
+
+/**
+ * Name of the GPS Measurements interface.
+ */
+#define GPS_MEASUREMENT_INTERFACE "gps_measurement"
+
+/**
+ * Name of the GPS navigation message interface.
+ */
+#define GPS_NAVIGATION_MESSAGE_INTERFACE "gps_navigation_message"
+
+/**
+ * Name of the GNSS/GPS configuration interface.
+ */
+#define GNSS_CONFIGURATION_INTERFACE "gnss_configuration"
+
+/** Represents a location. */
+typedef struct {
+ /** set to sizeof(GpsLocation) */
+ size_t size;
+ /** Contains GpsLocationFlags bits. */
+ uint16_t flags;
+ /** Represents latitude in degrees. */
+ double latitude;
+ /** Represents longitude in degrees. */
+ double longitude;
+ /**
+ * Represents altitude in meters above the WGS 84 reference ellipsoid.
+ */
+ double altitude;
+ /** Represents speed in meters per second. */
+ float speed;
+ /** Represents heading in degrees. */
+ float bearing;
+ /** Represents expected accuracy in meters. */
+ float accuracy;
+ /** Timestamp for the location fix. */
+ GpsUtcTime timestamp;
+} GpsLocation;
+
+/** Represents the status. */
+typedef struct {
+ /** set to sizeof(GpsStatus) */
+ size_t size;
+ GpsStatusValue status;
+} GpsStatus;
+
+/**
+ * Legacy struct to represents SV information.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssSvInfo instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsSvInfo) */
+ size_t size;
+ /** Pseudo-random number for the SV. */
+ int prn;
+ /** Signal to noise ratio. */
+ float snr;
+ /** Elevation of SV in degrees. */
+ float elevation;
+ /** Azimuth of SV in degrees. */
+ float azimuth;
+} GpsSvInfo;
+
+typedef struct {
+ /** set to sizeof(GnssSvInfo) */
+ size_t size;
+
+ /**
+ * Pseudo-random number for the SV, or FCN/OSN number for Glonass. The
+ * distinction is made by looking at constellation field. Values should be
+ * in the range of:
+ *
+ * - GPS: 1-32
+ * - SBAS: 120-151, 183-192
+ * - GLONASS: 1-24, the orbital slot number (OSN), if known. Or, if not:
+ * 93-106, the frequency channel number (FCN) (-7 to +6) offset by + 100
+ * i.e. report an FCN of -7 as 93, FCN of 0 as 100, and FCN of +6 as 106.
+ * - QZSS: 193-200
+ * - Galileo: 1-36
+ * - Beidou: 1-37
+ */
+ int16_t svid;
+
+ /**
+ * Defines the constellation of the given SV. Value should be one of those
+ * GNSS_CONSTELLATION_* constants
+ */
+ GnssConstellationType constellation;
+
+ /**
+ * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+ * It contains the measured C/N0 value for the signal at the antenna port.
+ *
+ * This is a mandatory value.
+ */
+ float c_n0_dbhz;
+
+ /** Elevation of SV in degrees. */
+ float elevation;
+
+ /** Azimuth of SV in degrees. */
+ float azimuth;
+
+ /**
+ * Contains additional data about the given SV. Value should be one of those
+ * GNSS_SV_FLAGS_* constants
+ */
+ GnssSvFlags flags;
+
+} GnssSvInfo;
+
+/**
+ * Legacy struct to represents SV status.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssSvStatus instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsSvStatus) */
+ size_t size;
+ int num_svs;
+ GpsSvInfo sv_list[GPS_MAX_SVS];
+ uint32_t ephemeris_mask;
+ uint32_t almanac_mask;
+ uint32_t used_in_fix_mask;
+} GpsSvStatus;
+
+/**
+ * Represents SV status.
+ */
+typedef struct {
+ /** set to sizeof(GnssSvStatus) */
+ size_t size;
+
+ /** Number of GPS SVs currently visible, refers to the SVs stored in sv_list */
+ int num_svs;
+ /**
+ * Pointer to an array of SVs information for all GNSS constellations,
+ * except GPS, which is reported using sv_list
+ */
+ GnssSvInfo gnss_sv_list[GNSS_MAX_SVS];
+
+} GnssSvStatus;
+
+/* CellID for 2G, 3G and LTE, used in AGPS. */
+typedef struct {
+ AGpsRefLocationType type;
+ /** Mobile Country Code. */
+ uint16_t mcc;
+ /** Mobile Network Code .*/
+ uint16_t mnc;
+ /** Location Area Code in 2G, 3G and LTE. In 3G lac is discarded. In LTE,
+ * lac is populated with tac, to ensure that we don't break old clients that
+ * might rely in the old (wrong) behavior.
+ */
+ uint16_t lac;
+ /** Cell id in 2G. Utran Cell id in 3G. Cell Global Id EUTRA in LTE. */
+ uint32_t cid;
+ /** Tracking Area Code in LTE. */
+ uint16_t tac;
+ /** Physical Cell id in LTE (not used in 2G and 3G) */
+ uint16_t pcid;
+} AGpsRefLocationCellID;
+
+typedef struct {
+ uint8_t mac[6];
+} AGpsRefLocationMac;
+
+/** Represents ref locations */
+typedef struct {
+ AGpsRefLocationType type;
+ union {
+ AGpsRefLocationCellID cellID;
+ AGpsRefLocationMac mac;
+ } u;
+} AGpsRefLocation;
+
+/**
+ * Callback with location information. Can only be called from a thread created
+ * by create_thread_cb.
+ */
+typedef void (* gps_location_callback)(GpsLocation* location);
+
+/**
+ * Callback with status information. Can only be called from a thread created by
+ * create_thread_cb.
+ */
+typedef void (* gps_status_callback)(GpsStatus* status);
+
+/**
+ * Legacy callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_sv_status_callback() instead.
+ */
+typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info);
+
+/**
+ * Callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* gnss_sv_status_callback)(GnssSvStatus* sv_info);
+
+/**
+ * Callback for reporting NMEA sentences. Can only be called from a thread
+ * created by create_thread_cb.
+ */
+typedef void (* gps_nmea_callback)(GpsUtcTime timestamp, const char* nmea, int length);
+
+/**
+ * Callback to inform framework of the GPS engine's capabilities. Capability
+ * parameter is a bit field of GPS_CAPABILITY_* flags.
+ */
+typedef void (* gps_set_capabilities)(uint32_t capabilities);
+
+/**
+ * Callback utility for acquiring the GPS wakelock. This can be used to prevent
+ * the CPU from suspending while handling GPS events.
+ */
+typedef void (* gps_acquire_wakelock)();
+
+/** Callback utility for releasing the GPS wakelock. */
+typedef void (* gps_release_wakelock)();
+
+/** Callback for requesting NTP time */
+typedef void (* gps_request_utc_time)();
+
+/**
+ * Callback for creating a thread that can call into the Java framework code.
+ * This must be used to create any threads that report events up to the
+ * framework.
+ */
+typedef pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg);
+
+/**
+ * Provides information about how new the underlying GPS/GNSS hardware and
+ * software is.
+ *
+ * This information will be available for Android Test Applications. If a GPS
+ * HAL does not provide this information, it will be considered "2015 or
+ * earlier".
+ *
+ * If a GPS HAL does provide this information, then newer years will need to
+ * meet newer CTS standards. E.g. if the date are 2016 or above, then N+ level
+ * GpsMeasurement support will be verified.
+ */
+typedef struct {
+ /** Set to sizeof(GnssSystemInfo) */
+ size_t size;
+ /* year in which the last update was made to the underlying hardware/firmware
+ * used to capture GNSS signals, e.g. 2016 */
+ uint16_t year_of_hw;
+} GnssSystemInfo;
+
+/**
+ * Callback to inform framework of the engine's hardware version information.
+ */
+typedef void (*gnss_set_system_info)(const GnssSystemInfo* info);
+
+/** New GPS callback structure. */
+typedef struct {
+ /** set to sizeof(GpsCallbacks) */
+ size_t size;
+ gps_location_callback location_cb;
+ gps_status_callback status_cb;
+ gps_sv_status_callback sv_status_cb;
+ gps_nmea_callback nmea_cb;
+ gps_set_capabilities set_capabilities_cb;
+ gps_acquire_wakelock acquire_wakelock_cb;
+ gps_release_wakelock release_wakelock_cb;
+ gps_create_thread create_thread_cb;
+ gps_request_utc_time request_utc_time_cb;
+
+ gnss_set_system_info set_system_info_cb;
+ gnss_sv_status_callback gnss_sv_status_cb;
+} GpsCallbacks;
+
+/** Represents the standard GPS interface. */
+typedef struct {
+ /** set to sizeof(GpsInterface) */
+ size_t size;
+ /**
+ * Opens the interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ int (*init)( GpsCallbacks* callbacks );
+
+ /** Starts navigating. */
+ int (*start)( void );
+
+ /** Stops navigating. */
+ int (*stop)( void );
+
+ /** Closes the interface. */
+ void (*cleanup)( void );
+
+ /** Injects the current time. */
+ int (*inject_time)(GpsUtcTime time, int64_t timeReference,
+ int uncertainty);
+
+ /**
+ * Injects current location from another location provider (typically cell
+ * ID). Latitude and longitude are measured in degrees expected accuracy is
+ * measured in meters
+ */
+ int (*inject_location)(double latitude, double longitude, float accuracy);
+
+ /**
+ * Specifies that the next call to start will not use the
+ * information defined in the flags. GPS_DELETE_ALL is passed for
+ * a cold start.
+ */
+ void (*delete_aiding_data)(GpsAidingData flags);
+
+ /**
+ * min_interval represents the time between fixes in milliseconds.
+ * preferred_accuracy represents the requested fix accuracy in meters.
+ * preferred_time represents the requested time to first fix in milliseconds.
+ *
+ * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASED
+ * or GPS_POSITION_MODE_STANDALONE.
+ * It is allowed by the platform (and it is recommended) to fallback to
+ * GPS_POSITION_MODE_MS_BASED if GPS_POSITION_MODE_MS_ASSISTED is passed in, and
+ * GPS_POSITION_MODE_MS_BASED is supported.
+ */
+ int (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+ uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
+
+ /** Get a pointer to extension information. */
+ const void* (*get_extension)(const char* name);
+} GpsInterface;
+
+/**
+ * Callback to request the client to download XTRA data. The client should
+ * download XTRA data and inject it by calling inject_xtra_data(). Can only be
+ * called from a thread created by create_thread_cb.
+ */
+typedef void (* gps_xtra_download_request)();
+
+/** Callback structure for the XTRA interface. */
+typedef struct {
+ gps_xtra_download_request download_request_cb;
+ gps_create_thread create_thread_cb;
+} GpsXtraCallbacks;
+
+/** Extended interface for XTRA support. */
+typedef struct {
+ /** set to sizeof(GpsXtraInterface) */
+ size_t size;
+ /**
+ * Opens the XTRA interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ int (*init)( GpsXtraCallbacks* callbacks );
+ /** Injects XTRA data into the GPS. */
+ int (*inject_xtra_data)( char* data, int length );
+} GpsXtraInterface;
+
+/** Extended interface for DEBUG support. */
+typedef struct {
+ /** set to sizeof(GpsDebugInterface) */
+ size_t size;
+
+ /**
+ * This function should return any information that the native
+ * implementation wishes to include in a bugreport.
+ */
+ size_t (*get_internal_state)(char* buffer, size_t bufferSize);
+} GpsDebugInterface;
+
+/*
+ * Represents the status of AGPS augmented to support IPv4 and IPv6.
+ */
+typedef struct {
+ /** set to sizeof(AGpsStatus) */
+ size_t size;
+
+ AGpsType type;
+ AGpsStatusValue status;
+
+ /**
+ * Must be set to a valid IPv4 address if the field 'addr' contains an IPv4
+ * address, or set to INADDR_NONE otherwise.
+ */
+ uint32_t ipaddr;
+
+ /**
+ * Must contain the IPv4 (AF_INET) or IPv6 (AF_INET6) address to report.
+ * Any other value of addr.ss_family will be rejected.
+ */
+ struct sockaddr_storage addr;
+} AGpsStatus;
+
+/**
+ * Callback with AGPS status information. Can only be called from a thread
+ * created by create_thread_cb.
+ */
+typedef void (* agps_status_callback)(AGpsStatus* status);
+
+/** Callback structure for the AGPS interface. */
+typedef struct {
+ agps_status_callback status_cb;
+ gps_create_thread create_thread_cb;
+} AGpsCallbacks;
+
+/**
+ * Extended interface for AGPS support, it is augmented to enable to pass
+ * extra APN data.
+ */
+typedef struct {
+ /** set to sizeof(AGpsInterface) */
+ size_t size;
+
+ /**
+ * Opens the AGPS interface and provides the callback routines to the
+ * implementation of this interface.
+ */
+ void (*init)(AGpsCallbacks* callbacks);
+ /**
+ * Deprecated.
+ * If the HAL supports AGpsInterface_v2 this API will not be used, see
+ * data_conn_open_with_apn_ip_type for more information.
+ */
+ int (*data_conn_open)(const char* apn);
+ /**
+ * Notifies that the AGPS data connection has been closed.
+ */
+ int (*data_conn_closed)();
+ /**
+ * Notifies that a data connection is not available for AGPS.
+ */
+ int (*data_conn_failed)();
+ /**
+ * Sets the hostname and port for the AGPS server.
+ */
+ int (*set_server)(AGpsType type, const char* hostname, int port);
+
+ /**
+ * Notifies that a data connection is available and sets the name of the
+ * APN, and its IP type, to be used for SUPL connections.
+ */
+ int (*data_conn_open_with_apn_ip_type)(
+ const char* apn,
+ ApnIpType apnIpType);
+} AGpsInterface;
+
+/** Error codes associated with certificate operations */
+#define AGPS_CERTIFICATE_OPERATION_SUCCESS 0
+#define AGPS_CERTIFICATE_ERROR_GENERIC -100
+#define AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES -101
+
+/** A data structure that represents an X.509 certificate using DER encoding */
+typedef struct {
+ size_t length;
+ u_char* data;
+} DerEncodedCertificate;
+
+/**
+ * A type definition for SHA1 Fingerprints used to identify X.509 Certificates
+ * The Fingerprint is a digest of the DER Certificate that uniquely identifies it.
+ */
+typedef struct {
+ u_char data[20];
+} Sha1CertificateFingerprint;
+
+/** AGPS Interface to handle SUPL certificate operations */
+typedef struct {
+ /** set to sizeof(SuplCertificateInterface) */
+ size_t size;
+
+ /**
+ * Installs a set of Certificates used for SUPL connections to the AGPS server.
+ * If needed the HAL should find out internally any certificates that need to be removed to
+ * accommodate the certificates to install.
+ * The certificates installed represent a full set of valid certificates needed to connect to
+ * AGPS SUPL servers.
+ * The list of certificates is required, and all must be available at the same time, when trying
+ * to establish a connection with the AGPS Server.
+ *
+ * Parameters:
+ * certificates - A pointer to an array of DER encoded certificates that are need to be
+ * installed in the HAL.
+ * length - The number of certificates to install.
+ * Returns:
+ * AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully
+ * AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES if the HAL cannot store the number of
+ * certificates attempted to be installed, the state of the certificates stored should
+ * remain the same as before on this error case.
+ *
+ * IMPORTANT:
+ * If needed the HAL should find out internally the set of certificates that need to be
+ * removed to accommodate the certificates to install.
+ */
+ int (*install_certificates) ( const DerEncodedCertificate* certificates, size_t length );
+
+ /**
+ * Notifies the HAL that a list of certificates used for SUPL connections are revoked. It is
+ * expected that the given set of certificates is removed from the internal store of the HAL.
+ *
+ * Parameters:
+ * fingerprints - A pointer to an array of SHA1 Fingerprints to identify the set of
+ * certificates to revoke.
+ * length - The number of fingerprints provided.
+ * Returns:
+ * AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully.
+ *
+ * IMPORTANT:
+ * If any of the certificates provided (through its fingerprint) is not known by the HAL,
+ * it should be ignored and continue revoking/deleting the rest of them.
+ */
+ int (*revoke_certificates) ( const Sha1CertificateFingerprint* fingerprints, size_t length );
+} SuplCertificateInterface;
+
+/** Represents an NI request */
+typedef struct {
+ /** set to sizeof(GpsNiNotification) */
+ size_t size;
+
+ /**
+ * An ID generated by HAL to associate NI notifications and UI
+ * responses
+ */
+ int notification_id;
+
+ /**
+ * An NI type used to distinguish different categories of NI
+ * events, such as GPS_NI_TYPE_VOICE, GPS_NI_TYPE_UMTS_SUPL, ...
+ */
+ GpsNiType ni_type;
+
+ /**
+ * Notification/verification options, combinations of GpsNiNotifyFlags constants
+ */
+ GpsNiNotifyFlags notify_flags;
+
+ /**
+ * Timeout period to wait for user response.
+ * Set to 0 for no time out limit.
+ */
+ int timeout;
+
+ /**
+ * Default response when time out.
+ */
+ GpsUserResponseType default_response;
+
+ /**
+ * Requestor ID
+ */
+ char requestor_id[GPS_NI_SHORT_STRING_MAXLEN];
+
+ /**
+ * Notification message. It can also be used to store client_id in some cases
+ */
+ char text[GPS_NI_LONG_STRING_MAXLEN];
+
+ /**
+ * Client name decoding scheme
+ */
+ GpsNiEncodingType requestor_id_encoding;
+
+ /**
+ * Client name decoding scheme
+ */
+ GpsNiEncodingType text_encoding;
+
+ /**
+ * A pointer to extra data. Format:
+ * key_1 = value_1
+ * key_2 = value_2
+ */
+ char extras[GPS_NI_LONG_STRING_MAXLEN];
+
+} GpsNiNotification;
+
+/**
+ * Callback with NI notification. Can only be called from a thread created by
+ * create_thread_cb.
+ */
+typedef void (*gps_ni_notify_callback)(GpsNiNotification *notification);
+
+/** GPS NI callback structure. */
+typedef struct
+{
+ /**
+ * Sends the notification request from HAL to GPSLocationProvider.
+ */
+ gps_ni_notify_callback notify_cb;
+ gps_create_thread create_thread_cb;
+} GpsNiCallbacks;
+
+/**
+ * Extended interface for Network-initiated (NI) support.
+ */
+typedef struct
+{
+ /** set to sizeof(GpsNiInterface) */
+ size_t size;
+
+ /** Registers the callbacks for HAL to use. */
+ void (*init) (GpsNiCallbacks *callbacks);
+
+ /** Sends a response to HAL. */
+ void (*respond) (int notif_id, GpsUserResponseType user_response);
+} GpsNiInterface;
+
+#if defined(__ANDROID_OS__)
+struct gps_device_t {
+ struct hw_device_t common;
+
+ /**
+ * Set the provided lights to the provided values.
+ *
+ * Returns: 0 on succes, error code on failure.
+ */
+ const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);
+};
+#elif defined(__LINUX_OS__)
+struct gps_device_t {
+ const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);
+};
+#endif
+
+#define AGPS_RIL_REQUEST_REFLOC_CELLID (1<<0L)
+#define AGPS_RIL_REQUEST_REFLOC_MAC (1<<1L)
+
+typedef void (*agps_ril_request_set_id)(uint32_t flags);
+typedef void (*agps_ril_request_ref_loc)(uint32_t flags);
+
+typedef struct {
+ agps_ril_request_set_id request_setid;
+ agps_ril_request_ref_loc request_refloc;
+ gps_create_thread create_thread_cb;
+} AGpsRilCallbacks;
+
+/** Extended interface for AGPS_RIL support. */
+typedef struct {
+ /** set to sizeof(AGpsRilInterface) */
+ size_t size;
+ /**
+ * Opens the AGPS interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ void (*init)( AGpsRilCallbacks* callbacks );
+
+ /**
+ * Sets the reference location.
+ */
+ void (*set_ref_location) (const AGpsRefLocation *agps_reflocation, size_t sz_struct);
+ /**
+ * Sets the set ID.
+ */
+ void (*set_set_id) (AGpsSetIDType type, const char* setid);
+
+ /**
+ * Send network initiated message.
+ */
+ void (*ni_message) (uint8_t *msg, size_t len);
+
+ /**
+ * Notify GPS of network status changes.
+ * These parameters match values in the android.net.NetworkInfo class.
+ */
+ void (*update_network_state) (int connected, int type, int roaming, const char* extra_info);
+
+ /**
+ * Notify GPS of network status changes.
+ * These parameters match values in the android.net.NetworkInfo class.
+ */
+ void (*update_network_availability) (int avaiable, const char* apn);
+} AGpsRilInterface;
+
+/**
+ * GPS Geofence.
+ * There are 3 states associated with a Geofence: Inside, Outside, Unknown.
+ * There are 3 transitions: ENTERED, EXITED, UNCERTAIN.
+ *
+ * An example state diagram with confidence level: 95% and Unknown time limit
+ * set as 30 secs is shown below. (confidence level and Unknown time limit are
+ * explained latter)
+ * ____________________________
+ * | Unknown (30 secs) |
+ * """"""""""""""""""""""""""""
+ * ^ | | ^
+ * UNCERTAIN| |ENTERED EXITED| |UNCERTAIN
+ * | v v |
+ * ________ EXITED _________
+ * | Inside | -----------> | Outside |
+ * | | <----------- | |
+ * """""""" ENTERED """""""""
+ *
+ * Inside state: We are 95% confident that the user is inside the geofence.
+ * Outside state: We are 95% confident that the user is outside the geofence
+ * Unknown state: Rest of the time.
+ *
+ * The Unknown state is better explained with an example:
+ *
+ * __________
+ * | c|
+ * | ___ | _______
+ * | |a| | | b |
+ * | """ | """""""
+ * | |
+ * """"""""""
+ * In the diagram above, "a" and "b" are 2 geofences and "c" is the accuracy
+ * circle reported by the GPS subsystem. Now with regard to "b", the system is
+ * confident that the user is outside. But with regard to "a" is not confident
+ * whether it is inside or outside the geofence. If the accuracy remains the
+ * same for a sufficient period of time, the UNCERTAIN transition would be
+ * triggered with the state set to Unknown. If the accuracy improves later, an
+ * appropriate transition should be triggered. This "sufficient period of time"
+ * is defined by the parameter in the add_geofence_area API.
+ * In other words, Unknown state can be interpreted as a state in which the
+ * GPS subsystem isn't confident enough that the user is either inside or
+ * outside the Geofence. It moves to Unknown state only after the expiry of the
+ * timeout.
+ *
+ * The geofence callback needs to be triggered for the ENTERED and EXITED
+ * transitions, when the GPS system is confident that the user has entered
+ * (Inside state) or exited (Outside state) the Geofence. An implementation
+ * which uses a value of 95% as the confidence is recommended. The callback
+ * should be triggered only for the transitions requested by the
+ * add_geofence_area call.
+ *
+ * Even though the diagram and explanation talks about states and transitions,
+ * the callee is only interested in the transistions. The states are mentioned
+ * here for illustrative purposes.
+ *
+ * Startup Scenario: When the device boots up, if an application adds geofences,
+ * and then we get an accurate GPS location fix, it needs to trigger the
+ * appropriate (ENTERED or EXITED) transition for every Geofence it knows about.
+ * By default, all the Geofences will be in the Unknown state.
+ *
+ * When the GPS system is unavailable, gps_geofence_status_callback should be
+ * called to inform the upper layers of the same. Similarly, when it becomes
+ * available the callback should be called. This is a global state while the
+ * UNKNOWN transition described above is per geofence.
+ *
+ * An important aspect to note is that users of this API (framework), will use
+ * other subsystems like wifi, sensors, cell to handle Unknown case and
+ * hopefully provide a definitive state transition to the third party
+ * application. GPS Geofence will just be a signal indicating what the GPS
+ * subsystem knows about the Geofence.
+ *
+ */
+#define GPS_GEOFENCE_ENTERED (1<<0L)
+#define GPS_GEOFENCE_EXITED (1<<1L)
+#define GPS_GEOFENCE_UNCERTAIN (1<<2L)
+
+#define GPS_GEOFENCE_UNAVAILABLE (1<<0L)
+#define GPS_GEOFENCE_AVAILABLE (1<<1L)
+
+#define GPS_GEOFENCE_OPERATION_SUCCESS 0
+#define GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES -100
+#define GPS_GEOFENCE_ERROR_ID_EXISTS -101
+#define GPS_GEOFENCE_ERROR_ID_UNKNOWN -102
+#define GPS_GEOFENCE_ERROR_INVALID_TRANSITION -103
+#define GPS_GEOFENCE_ERROR_GENERIC -149
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ * geofence_id - The id associated with the add_geofence_area.
+ * location - The current GPS location.
+ * transition - Can be one of GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED,
+ * GPS_GEOFENCE_UNCERTAIN.
+ * timestamp - Timestamp when the transition was detected.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the GPS
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*gps_geofence_transition_callback) (int32_t geofence_id, GpsLocation* location,
+ int32_t transition, GpsUtcTime timestamp);
+
+/**
+ * The callback associated with the availability of the GPS system for geofencing
+ * monitoring. If the GPS system determines that it cannot monitor geofences
+ * because of lack of reliability or unavailability of the GPS signals, it will
+ * call this callback with GPS_GEOFENCE_UNAVAILABLE parameter.
+ *
+ * Parameters:
+ * status - GPS_GEOFENCE_UNAVAILABLE or GPS_GEOFENCE_AVAILABLE.
+ * last_location - Last known location.
+ */
+typedef void (*gps_geofence_status_callback) (int32_t status, GpsLocation* last_location);
+
+/**
+ * The callback associated with the add_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ * GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES - geofence limit has been reached.
+ * GPS_GEOFENCE_ERROR_ID_EXISTS - geofence with id already exists
+ * GPS_GEOFENCE_ERROR_INVALID_TRANSITION - the monitorTransition contains an
+ * invalid transition
+ * GPS_GEOFENCE_ERROR_GENERIC - for other errors.
+ */
+typedef void (*gps_geofence_add_callback) (int32_t geofence_id, int32_t status);
+
+/**
+ * The callback associated with the remove_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ * GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ * GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_remove_callback) (int32_t geofence_id, int32_t status);
+
+
+/**
+ * The callback associated with the pause_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ * GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ * GPS_GEOFENCE_ERROR_INVALID_TRANSITION -
+ * when monitor_transitions is invalid
+ * GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_pause_callback) (int32_t geofence_id, int32_t status);
+
+/**
+ * The callback associated with the resume_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ * GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ * GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_resume_callback) (int32_t geofence_id, int32_t status);
+
+typedef struct {
+ gps_geofence_transition_callback geofence_transition_callback;
+ gps_geofence_status_callback geofence_status_callback;
+ gps_geofence_add_callback geofence_add_callback;
+ gps_geofence_remove_callback geofence_remove_callback;
+ gps_geofence_pause_callback geofence_pause_callback;
+ gps_geofence_resume_callback geofence_resume_callback;
+ gps_create_thread create_thread_cb;
+} GpsGeofenceCallbacks;
+
+/** Extended interface for GPS_Geofencing support */
+typedef struct {
+ /** set to sizeof(GpsGeofencingInterface) */
+ size_t size;
+
+ /**
+ * Opens the geofence interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ void (*init)( GpsGeofenceCallbacks* callbacks );
+
+ /**
+ * Add a geofence area. This api currently supports circular geofences.
+ * Parameters:
+ * geofence_id - The id for the geofence. If a geofence with this id
+ * already exists, an error value (GPS_GEOFENCE_ERROR_ID_EXISTS)
+ * should be returned.
+ * latitude, longtitude, radius_meters - The lat, long and radius
+ * (in meters) for the geofence
+ * last_transition - The current state of the geofence. For example, if
+ * the system already knows that the user is inside the geofence,
+ * this will be set to GPS_GEOFENCE_ENTERED. In most cases, it
+ * will be GPS_GEOFENCE_UNCERTAIN.
+ * monitor_transition - Which transitions to monitor. Bitwise OR of
+ * GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+ * GPS_GEOFENCE_UNCERTAIN.
+ * notification_responsiveness_ms - Defines the best-effort description
+ * of how soon should the callback be called when the transition
+ * associated with the Geofence is triggered. For instance, if set
+ * to 1000 millseconds with GPS_GEOFENCE_ENTERED, the callback
+ * should be called 1000 milliseconds within entering the geofence.
+ * This parameter is defined in milliseconds.
+ * NOTE: This is not to be confused with the rate that the GPS is
+ * polled at. It is acceptable to dynamically vary the rate of
+ * sampling the GPS for power-saving reasons; thus the rate of
+ * sampling may be faster or slower than this.
+ * unknown_timer_ms - The time limit after which the UNCERTAIN transition
+ * should be triggered. This parameter is defined in milliseconds.
+ * See above for a detailed explanation.
+ */
+ void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude,
+ double radius_meters, int last_transition, int monitor_transitions,
+ int notification_responsiveness_ms, int unknown_timer_ms);
+
+ /**
+ * Pause monitoring a particular geofence.
+ * Parameters:
+ * geofence_id - The id for the geofence.
+ */
+ void (*pause_geofence) (int32_t geofence_id);
+
+ /**
+ * Resume monitoring a particular geofence.
+ * Parameters:
+ * geofence_id - The id for the geofence.
+ * monitor_transitions - Which transitions to monitor. Bitwise OR of
+ * GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+ * GPS_GEOFENCE_UNCERTAIN.
+ * This supersedes the value associated provided in the
+ * add_geofence_area call.
+ */
+ void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+ /**
+ * Remove a geofence area. After the function returns, no notifications
+ * should be sent.
+ * Parameter:
+ * geofence_id - The id for the geofence.
+ */
+ void (*remove_geofence_area) (int32_t geofence_id);
+} GpsGeofencingInterface;
+
+/**
+ * Legacy struct to represent an estimate of the GPS clock time.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssClock instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsClock) */
+ size_t size;
+ GpsClockFlags flags;
+ int16_t leap_second;
+ GpsClockType type;
+ int64_t time_ns;
+ double time_uncertainty_ns;
+ int64_t full_bias_ns;
+ double bias_ns;
+ double bias_uncertainty_ns;
+ double drift_nsps;
+ double drift_uncertainty_nsps;
+} GpsClock;
+
+/**
+ * Represents an estimate of the GPS clock time.
+ */
+typedef struct {
+ /** set to sizeof(GnssClock) */
+ size_t size;
+
+ /**
+ * A set of flags indicating the validity of the fields in this data
+ * structure.
+ */
+ GnssClockFlags flags;
+
+ /**
+ * Leap second data.
+ * The sign of the value is defined by the following equation:
+ * utc_time_ns = time_ns - (full_bias_ns + bias_ns) - leap_second *
+ * 1,000,000,000
+ *
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_LEAP_SECOND.
+ */
+ int16_t leap_second;
+
+ /**
+ * The GNSS receiver internal clock value. This is the local hardware clock
+ * value.
+ *
+ * For local hardware clock, this value is expected to be monotonically
+ * increasing while the hardware clock remains power on. (For the case of a
+ * HW clock that is not continuously on, see the
+ * hw_clock_discontinuity_count field). The receiver's estimate of GPS time
+ * can be derived by substracting the sum of full_bias_ns and bias_ns (when
+ * available) from this value.
+ *
+ * This GPS time is expected to be the best estimate of current GPS time
+ * that GNSS receiver can achieve.
+ *
+ * Sub-nanosecond accuracy can be provided by means of the 'bias_ns' field.
+ * The value contains the 'time uncertainty' in it.
+ *
+ * This field is mandatory.
+ */
+ int64_t time_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_CLOCK_HAS_TIME_UNCERTAINTY. This value is effectively zero (it is
+ * the reference local clock, by which all other times and time
+ * uncertainties are measured.) (And thus this field can be not provided,
+ * per GNSS_CLOCK_HAS_TIME_UNCERTAINTY flag, or provided & set to 0.)
+ */
+ double time_uncertainty_ns;
+
+ /**
+ * The difference between hardware clock ('time' field) inside GPS receiver
+ * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
+ *
+ * The sign of the value is defined by the following equation:
+ * local estimate of GPS time = time_ns - (full_bias_ns + bias_ns)
+ *
+ * This value is mandatory if the receiver has estimated GPS time. If the
+ * computed time is for a non-GPS constellation, the time offset of that
+ * constellation to GPS has to be applied to fill this value. The error
+ * estimate for the sum of this and the bias_ns is the bias_uncertainty_ns,
+ * and the caller is responsible for using this uncertainty (it can be very
+ * large before the GPS time has been solved for.) If the data is available
+ * 'flags' must contain GNSS_CLOCK_HAS_FULL_BIAS.
+ */
+ int64_t full_bias_ns;
+
+ /**
+ * Sub-nanosecond bias.
+ * The error estimate for the sum of this and the full_bias_ns is the
+ * bias_uncertainty_ns
+ *
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_BIAS. If GPS
+ * has computed a position fix. This value is mandatory if the receiver has
+ * estimated GPS time.
+ */
+ double bias_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the local estimate of GPS time (clock
+ * bias) in nanoseconds. The uncertainty is represented as an absolute
+ * (single sided) value.
+ *
+ * If the data is available 'flags' must contain
+ * GNSS_CLOCK_HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+ * has estimated GPS time.
+ */
+ double bias_uncertainty_ns;
+
+ /**
+ * The clock's drift in nanoseconds (per second).
+ *
+ * A positive value means that the frequency is higher than the nominal
+ * frequency, and that the (full_bias_ns + bias_ns) is growing more positive
+ * over time.
+ *
+ * The value contains the 'drift uncertainty' in it.
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_DRIFT.
+ *
+ * This value is mandatory if the receiver has estimated GNSS time
+ */
+ double drift_nsps;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available 'flags' must contain
+ * GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY. If GPS has computed a position fix this
+ * field is mandatory and must be populated.
+ */
+ double drift_uncertainty_nsps;
+
+ /**
+ * When there are any discontinuities in the HW clock, this field is
+ * mandatory.
+ *
+ * A "discontinuity" is meant to cover the case of a switch from one source
+ * of clock to another. A single free-running crystal oscillator (XO)
+ * should generally not have any discontinuities, and this can be set and
+ * left at 0.
+ *
+ * If, however, the time_ns value (HW clock) is derived from a composite of
+ * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+ * restarted, then this value shall be incremented each time a discontinuity
+ * occurs. (E.g. this value may start at zero at device boot-up and
+ * increment each time there is a change in clock continuity. In the
+ * unlikely event that this value reaches full scale, rollover (not
+ * clamping) is required, such that this value continues to change, during
+ * subsequent discontinuity events.)
+ *
+ * While this number stays the same, between GnssClock reports, it can be
+ * safely assumed that the time_ns value has been running continuously, e.g.
+ * derived from a single, high quality clock (XO like, or better, that's
+ * typically used during continuous GNSS signal sampling.)
+ *
+ * It is expected, esp. during periods where there are few GNSS signals
+ * available, that the HW clock be discontinuity-free as long as possible,
+ * as this avoids the need to use (waste) a GNSS measurement to fully
+ * re-solve for the GPS clock bias and drift, when using the accompanying
+ * measurements, from consecutive GnssData reports.
+ */
+ uint32_t hw_clock_discontinuity_count;
+
+} GnssClock;
+
+/**
+ * Legacy struct to represent a GPS Measurement, it contains raw and computed
+ * information.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssMeasurement instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsMeasurement) */
+ size_t size;
+ GpsMeasurementFlags flags;
+ int8_t prn;
+ double time_offset_ns;
+ GpsMeasurementState state;
+ int64_t received_gps_tow_ns;
+ int64_t received_gps_tow_uncertainty_ns;
+ double c_n0_dbhz;
+ double pseudorange_rate_mps;
+ double pseudorange_rate_uncertainty_mps;
+ GpsAccumulatedDeltaRangeState accumulated_delta_range_state;
+ double accumulated_delta_range_m;
+ double accumulated_delta_range_uncertainty_m;
+ double pseudorange_m;
+ double pseudorange_uncertainty_m;
+ double code_phase_chips;
+ double code_phase_uncertainty_chips;
+ float carrier_frequency_hz;
+ int64_t carrier_cycles;
+ double carrier_phase;
+ double carrier_phase_uncertainty;
+ GpsLossOfLock loss_of_lock;
+ int32_t bit_number;
+ int16_t time_from_last_bit_ms;
+ double doppler_shift_hz;
+ double doppler_shift_uncertainty_hz;
+ GpsMultipathIndicator multipath_indicator;
+ double snr_db;
+ double elevation_deg;
+ double elevation_uncertainty_deg;
+ double azimuth_deg;
+ double azimuth_uncertainty_deg;
+ bool used_in_fix;
+} GpsMeasurement;
+
+/**
+ * Represents a GNSS Measurement, it contains raw and computed information.
+ *
+ * Independence - All signal measurement information (e.g. sv_time,
+ * pseudorange_rate, multipath_indicator) reported in this struct should be
+ * based on GNSS signal measurements only. You may not synthesize measurements
+ * by calculating or reporting expected measurements based on known or estimated
+ * position, velocity, or time.
+ */
+typedef struct {
+ /** set to sizeof(GpsMeasurement) */
+ size_t size;
+
+ /** A set of flags indicating the validity of the fields in this data structure. */
+ GnssMeasurementFlags flags;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ * This is a mandatory value.
+ */
+ int16_t svid;
+
+ /**
+ * Defines the constellation of the given SV. Value should be one of those
+ * GNSS_CONSTELLATION_* constants
+ */
+ GnssConstellationType constellation;
+
+ /**
+ * Time offset at which the measurement was taken in nanoseconds.
+ * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+ * interpreted in the same way as indicated by GpsClock::type.
+ *
+ * The sign of time_offset_ns is given by the following equation:
+ * measurement time = GpsClock::time_ns + time_offset_ns
+ *
+ * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+ * This is a mandatory value.
+ */
+ double time_offset_ns;
+
+ /**
+ * Per satellite sync state. It represents the current sync state for the associated satellite.
+ * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+ *
+ * This is a mandatory value.
+ */
+ GnssMeasurementState state;
+
+ /**
+ * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+ * Ensure that this field is independent (see comment at top of
+ * GnssMeasurement struct.)
+ *
+ * For GPS & QZSS, this is:
+ * Received GPS Time-of-Week at the measurement time, in nanoseconds.
+ * The value is relative to the beginning of the current GPS week.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range
+ * for this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync : [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe sync : [ 0 6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * TOW decoded : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * Note well: if there is any ambiguity in integer millisecond,
+ * GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+ *
+ * This value must be populated if 'state' != GNSS_MEASUREMENT_STATE_UNKNOWN.
+ *
+ * For Glonass, this is:
+ * Received Glonass time of day, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 10ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+ * Bit sync : [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * String sync : [ 0 2s ] : GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC is set
+ * Time of day : [ 0 1day ] : GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED is set
+ *
+ * For Beidou, this is:
+ * Received Beidou time of week, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync (D2): [ 0 2ms ] : GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC is set
+ * Bit sync (D1): [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe (D2): [ 0 0.6s ] : GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC is set
+ * Subframe (D1): [ 0 6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * Time of week : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * For Galileo, this is:
+ * Received Galileo time of week, at the measurement time in nanoseconds.
+ *
+ * E1BC code lock : [ 0 4ms ] : GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK is set
+ * E1C 2nd code lock: [ 0 100ms ] :
+ * GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is set
+ *
+ * E1B page : [ 0 2s ] : GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC is set
+ * Time of week: [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * For SBAS, this is:
+ * Received SBAS time, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite,
+ * valid range for this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 2ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+ * Message : [ 0 1s ] : GNSS_MEASUREMENT_STATE_SBAS_SYNC is set
+ */
+ int64_t received_sv_time_in_ns;
+
+ /**
+ * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+ *
+ * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+ */
+ int64_t received_sv_time_uncertainty_in_ns;
+
+ /**
+ * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+ * It contains the measured C/N0 value for the signal at the antenna port.
+ *
+ * This is a mandatory value.
+ */
+ double c_n0_dbhz;
+
+ /**
+ * Pseudorange rate at the timestamp in m/s. The correction of a given
+ * Pseudorange Rate value includes corrections for receiver and satellite
+ * clock frequency errors. Ensure that this field is independent (see
+ * comment at top of GnssMeasurement struct.)
+ *
+ * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
+ * 'drift' field as well (When providing the uncorrected pseudorange rate, do not apply the
+ * corrections described above.)
+ *
+ * The value includes the 'pseudorange rate uncertainty' in it.
+ * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler
+ * shift' is given by the equation:
+ * pseudorange rate = -k * doppler shift (where k is a constant)
+ *
+ * This should be the most accurate pseudorange rate available, based on
+ * fresh signal measurements from this channel.
+ *
+ * It is mandatory that this value be provided at typical carrier phase PRR
+ * quality (few cm/sec per second of uncertainty, or better) - when signals
+ * are sufficiently strong & stable, e.g. signals from a GPS simulator at >=
+ * 35 dB-Hz.
+ */
+ double pseudorange_rate_mps;
+
+ /**
+ * 1-Sigma uncertainty of the pseudorange_rate_mps.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * This is a mandatory value.
+ */
+ double pseudorange_rate_uncertainty_mps;
+
+ /**
+ * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+ * (indicating loss of lock).
+ *
+ * This is a mandatory value.
+ */
+ GnssAccumulatedDeltaRangeState accumulated_delta_range_state;
+
+ /**
+ * Accumulated delta range since the last channel reset in meters.
+ * A positive value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+ * is given by the equation:
+ * accumulated delta range = -k * carrier phase (where k is a constant)
+ *
+ * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ * However, it is expected that the data is only accurate when:
+ * 'accumulated delta range state' == GPS_ADR_STATE_VALID.
+ */
+ double accumulated_delta_range_m;
+
+ /**
+ * 1-Sigma uncertainty of the accumulated delta range in meters.
+ * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ */
+ double accumulated_delta_range_uncertainty_m;
+
+ /**
+ * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+ * If the field is not set, the carrier frequency is assumed to be L1.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+ */
+ float carrier_frequency_hz;
+
+ /**
+ * The number of full carrier cycles between the satellite and the receiver.
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * Indications of possible cycle slips and resets in the accumulation of
+ * this value can be inferred from the accumulated_delta_range_state flags.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
+ */
+ int64_t carrier_cycles;
+
+ /**
+ * The RF phase detected by the receiver, in the range [0.0, 1.0].
+ * This is usually the fractional part of the complete carrier phase measurement.
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'carrier-phase uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_PHASE.
+ */
+ double carrier_phase;
+
+ /**
+ * 1-Sigma uncertainty of the carrier-phase.
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+ */
+ double carrier_phase_uncertainty;
+
+ /**
+ * An enumeration that indicates the 'multipath' state of the event.
+ *
+ * The multipath Indicator is intended to report the presence of overlapping
+ * signals that manifest as distorted correlation peaks.
+ *
+ * - if there is a distorted correlation peak shape, report that multipath
+ * is GNSS_MULTIPATH_INDICATOR_PRESENT.
+ * - if there is not a distorted correlation peak shape, report
+ * GNSS_MULTIPATH_INDICATOR_NOT_PRESENT
+ * - if signals are too weak to discern this information, report
+ * GNSS_MULTIPATH_INDICATOR_UNKNOWN
+ *
+ * Example: when doing the standardized overlapping Multipath Performance
+ * test (3GPP TS 34.171) the Multipath indicator should report
+ * GNSS_MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+ * contain multipath, and GNSS_MULTIPATH_INDICATOR_NOT_PRESENT for those
+ * signals that are tracked and do not contain multipath.
+ */
+ GnssMultipathIndicator multipath_indicator;
+
+ /**
+ * Signal-to-noise ratio at correlator output in dB.
+ * If the data is available, 'flags' must contain GNSS_MEASUREMENT_HAS_SNR.
+ * This is the power ratio of the "correlation peak height above the
+ * observed noise floor" to "the noise RMS".
+ */
+ double snr_db;
+} GnssMeasurement;
+
+/**
+ * Legacy struct to represents a reading of GPS measurements.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssData instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsData) */
+ size_t size;
+ size_t measurement_count;
+ GpsMeasurement measurements[GPS_MAX_MEASUREMENT];
+
+ /** The GPS clock time reading. */
+ GpsClock clock;
+} GpsData;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+ /** set to sizeof(GnssData) */
+ size_t size;
+
+ /** Number of measurements. */
+ size_t measurement_count;
+
+ /** The array of measurements. */
+ GnssMeasurement measurements[GNSS_MAX_MEASUREMENT];
+
+ /** The GPS clock time reading. */
+ GnssClock clock;
+} GnssData;
+
+/**
+ * The legacy callback for to report measurements from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_measurement_callback() instead.
+ *
+ * Parameters:
+ * data - A data structure containing the measurements.
+ */
+typedef void (*gps_measurement_callback) (GpsData* data);
+
+/**
+ * The callback for to report measurements from the HAL.
+ *
+ * Parameters:
+ * data - A data structure containing the measurements.
+ */
+typedef void (*gnss_measurement_callback) (GnssData* data);
+
+typedef struct {
+ /** set to sizeof(GpsMeasurementCallbacks) */
+ size_t size;
+ gps_measurement_callback measurement_callback;
+ gnss_measurement_callback gnss_measurement_callback;
+} GpsMeasurementCallbacks;
+
+/**
+ * Extended interface for GPS Measurements support.
+ */
+typedef struct {
+ /** Set to sizeof(GpsMeasurementInterface) */
+ size_t size;
+
+ /**
+ * Initializes the interface and registers the callback routines with the HAL.
+ * After a successful call to 'init' the HAL must begin to provide updates at its own phase.
+ *
+ * Status:
+ * GPS_MEASUREMENT_OPERATION_SUCCESS
+ * GPS_MEASUREMENT_ERROR_ALREADY_INIT - if a callback has already been registered without a
+ * corresponding call to 'close'
+ * GPS_MEASUREMENT_ERROR_GENERIC - if any other error occurred, it is expected that the HAL
+ * will not generate any updates upon returning this error code.
+ */
+ int (*init) (GpsMeasurementCallbacks* callbacks);
+
+ /**
+ * Stops updates from the HAL, and unregisters the callback routines.
+ * After a call to stop, the previously registered callbacks must be considered invalid by the
+ * HAL.
+ * If stop is invoked without a previous 'init', this function should perform no work.
+ */
+ void (*close) ();
+
+} GpsMeasurementInterface;
+
+/**
+ * Legacy struct to represents a GPS navigation message (or a fragment of it).
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssNavigationMessage instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsNavigationMessage) */
+ size_t size;
+ int8_t prn;
+ GpsNavigationMessageType type;
+ NavigationMessageStatus status;
+ int16_t message_id;
+ int16_t submessage_id;
+ size_t data_length;
+ uint8_t* data;
+} GpsNavigationMessage;
+
+/** Represents a GPS navigation message (or a fragment of it). */
+typedef struct {
+ /** set to sizeof(GnssNavigationMessage) */
+ size_t size;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ * This is a mandatory value.
+ */
+ int16_t svid;
+
+ /**
+ * The type of message contained in the structure.
+ * This is a mandatory value.
+ */
+ GnssNavigationMessageType type;
+
+ /**
+ * The status of the received navigation message.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+ NavigationMessageStatus status;
+
+ /**
+ * Message identifier. It provides an index so the complete Navigation
+ * Message can be assembled.
+ *
+ * - For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+ * id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+ * does not contain a 'frame id' and this value can be set to -1.)
+ *
+ * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+ *
+ * - For BeiDou D1, this refers to the frame number in the range of 1-24
+ *
+ * - For Beidou D2, this refers to the frame number, in the range of 1-120
+ *
+ * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+ * number, in the range of 1-12
+ *
+ * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+ * number in the range of 1-24
+ */
+ int16_t message_id;
+
+ /**
+ * Sub-message identifier. If required by the message 'type', this value
+ * contains a sub-index within the current message (or frame) that is being
+ * transmitted.
+ *
+ * - For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to
+ * the subframe number of the navigation message, in the range of 1-5.
+ *
+ * - For Glonass L1 C/A, this refers to the String number, in the range from
+ * 1-15
+ *
+ * - For Galileo F/NAV, this refers to the page type in the range 1-6
+ *
+ * - For Galileo I/NAV, this refers to the word type in the range 1-10+
+ */
+ int16_t submessage_id;
+
+ /**
+ * The length of the data (in bytes) contained in the current message.
+ * If this value is different from zero, 'data' must point to an array of the same size.
+ * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+ *
+ * This is a mandatory value.
+ */
+ size_t data_length;
+
+ /**
+ * The data of the reported GPS message. The bytes (or words) specified
+ * using big endian format (MSB first).
+ *
+ * - For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+ * words. Each word (30 bits) should be fit into the last 30 bits in a
+ * 4-byte word (skip B31 and B32), with MSB first, for a total of 40
+ * bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
+ *
+ * - For Glonass L1 C/A, each string contains 85 data bits, including the
+ * checksum. These bits should be fit into 11 bytes, with MSB first (skip
+ * B86-B88), covering a time period of 2 seconds.
+ *
+ * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+ * excluded). Each word should be fit into 30-bytes, with MSB first (skip
+ * B239, B240), covering a time period of 10 seconds.
+ *
+ * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+ * a total of 2x114 = 228 bits, (sync & tail excluded) that should be fit
+ * into 29 bytes, with MSB first (skip B229-B232).
+ */
+ uint8_t* data;
+
+} GnssNavigationMessage;
+
+/**
+ * The legacy callback to report an available fragment of a GPS navigation
+ * messages from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_navigation_message_callback() instead.
+ *
+ * Parameters:
+ * message - The GPS navigation submessage/subframe representation.
+ */
+typedef void (*gps_navigation_message_callback) (GpsNavigationMessage* message);
+
+/**
+ * The callback to report an available fragment of a GPS navigation messages from the HAL.
+ *
+ * Parameters:
+ * message - The GPS navigation submessage/subframe representation.
+ */
+typedef void (*gnss_navigation_message_callback) (GnssNavigationMessage* message);
+
+typedef struct {
+ /** set to sizeof(GpsNavigationMessageCallbacks) */
+ size_t size;
+ gps_navigation_message_callback navigation_message_callback;
+ gnss_navigation_message_callback gnss_navigation_message_callback;
+} GpsNavigationMessageCallbacks;
+
+/**
+ * Extended interface for GPS navigation message reporting support.
+ */
+typedef struct {
+ /** Set to sizeof(GpsNavigationMessageInterface) */
+ size_t size;
+
+ /**
+ * Initializes the interface and registers the callback routines with the HAL.
+ * After a successful call to 'init' the HAL must begin to provide updates as they become
+ * available.
+ *
+ * Status:
+ * GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS
+ * GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT - if a callback has already been registered
+ * without a corresponding call to 'close'.
+ * GPS_NAVIGATION_MESSAGE_ERROR_GENERIC - if any other error occurred, it is expected that
+ * the HAL will not generate any updates upon returning this error code.
+ */
+ int (*init) (GpsNavigationMessageCallbacks* callbacks);
+
+ /**
+ * Stops updates from the HAL, and unregisters the callback routines.
+ * After a call to stop, the previously registered callbacks must be considered invalid by the
+ * HAL.
+ * If stop is invoked without a previous 'init', this function should perform no work.
+ */
+ void (*close) ();
+
+} GpsNavigationMessageInterface;
+
+/**
+ * Interface for passing GNSS configuration contents from platform to HAL.
+ */
+typedef struct {
+ /** Set to sizeof(GnssConfigurationInterface) */
+ size_t size;
+
+ /**
+ * Deliver GNSS configuration contents to HAL.
+ * Parameters:
+ * config_data - a pointer to a char array which holds what usually is expected from
+ file(/etc/gps.conf), i.e., a sequence of UTF8 strings separated by '\n'.
+ * length - total number of UTF8 characters in configuraiton data.
+ *
+ * IMPORTANT:
+ * GPS HAL should expect this function can be called multiple times. And it may be
+ * called even when GpsLocationProvider is already constructed and enabled. GPS HAL
+ * should maintain the existing requests for various callback regardless the change
+ * in configuration data.
+ */
+ void (*configuration_update) (const char* config_data, int32_t length);
+} GnssConfigurationInterface;
+
+__END_DECLS
+
+#endif
+
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_H */
+
diff --git a/src/connectivity/gps/2.0/gps_hal/inc/hardware/gps_internal.h b/src/connectivity/gps/2.0/gps_hal/inc/hardware/gps_internal.h
new file mode 100644
index 0000000..67a16e8
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/inc/hardware/gps_internal.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H
+
+#ifdef __LINUX_OS__
+//#include <hardware/gps.h>
+#include "gps.h"
+
+/****************************************************************************
+ * This file contains legacy structs that are deprecated/retired from gps.h *
+ ****************************************************************************/
+
+__BEGIN_DECLS
+
+/**
+ * Legacy GPS callback structure.
+ * Deprecated, to be removed in the next Android release.
+ * Use GpsCallbacks instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsCallbacks_v1) */
+ size_t size;
+ gps_location_callback location_cb;
+ gps_status_callback status_cb;
+ gps_sv_status_callback sv_status_cb;
+ gps_nmea_callback nmea_cb;
+ gps_set_capabilities set_capabilities_cb;
+ gps_acquire_wakelock acquire_wakelock_cb;
+ gps_release_wakelock release_wakelock_cb;
+ gps_create_thread create_thread_cb;
+ gps_request_utc_time request_utc_time_cb;
+} GpsCallbacks_v1;
+
+#pragma pack(push,4)
+// We need to keep the alignment of this data structure to 4-bytes, to ensure that in 64-bit
+// environments the size of this legacy definition does not collide with _v2. Implementations should
+// be using _v2 and _v3, so it's OK to pay the 'unaligned' penalty in 64-bit if an old
+// implementation is still in use.
+
+/**
+ * Legacy struct to represent the status of AGPS.
+ */
+typedef struct {
+ /** set to sizeof(AGpsStatus_v1) */
+ size_t size;
+ AGpsType type;
+ AGpsStatusValue status;
+} AGpsStatus_v1;
+
+#pragma pack(pop)
+
+/**
+ * Legacy struct to represent the status of AGPS augmented with a IPv4 address
+ * field.
+ */
+typedef struct {
+ /** set to sizeof(AGpsStatus_v2) */
+ size_t size;
+ AGpsType type;
+ AGpsStatusValue status;
+
+ /*-------------------- New fields in _v2 --------------------*/
+
+ uint32_t ipaddr;
+} AGpsStatus_v2;
+
+/**
+ * Legacy extended interface for AGPS support.
+ * See AGpsInterface_v2 for more information.
+ */
+typedef struct {
+ /** set to sizeof(AGpsInterface_v1) */
+ size_t size;
+ void (*init)( AGpsCallbacks* callbacks );
+ int (*data_conn_open)( const char* apn );
+ int (*data_conn_closed)();
+ int (*data_conn_failed)();
+ int (*set_server)( AGpsType type, const char* hostname, int port );
+} AGpsInterface_v1;
+
+__END_DECLS
+
+#endif
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H */
diff --git a/src/connectivity/gps/2.0/gps_hal/inc/hardware/gps_mtk.h b/src/connectivity/gps/2.0/gps_hal/inc/hardware/gps_mtk.h
new file mode 100644
index 0000000..f672617
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/inc/hardware/gps_mtk.h
@@ -0,0 +1,1519 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_MTK_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_MTK_H
+
+#if defined (__ANDROID_OS__)
+#include <hardware/gps_internal.h>
+#elif defined (__LINUX_OS__)
+#include "gps_internal.h"
+#endif
+
+__BEGIN_DECLS
+
+// MTK extended GpsAidingData values.
+#define GPS_DELETE_HOT_STILL 0x2000
+#define GPS_DELETE_EPO 0x4000
+#define MTK_MAX_SV_COUNT 181
+
+// ====================vzw debug screen API =================
+/**
+ * Name for the VZW debug interface.
+ */
+#define VZW_DEBUG_INTERFACE "vzw-debug"
+
+#define VZW_DEBUG_STRING_MAXLEN 200
+
+#define HAL_NFW_USER_NUM_MAX (10)
+#define HAL_NFW_USER_NAME_LEN (64)
+
+
+/** Represents data of VzwDebugData. */
+typedef struct {
+ /** set to sizeof(VzwDebugData) */
+ size_t size;
+
+ char vzw_msg_data[VZW_DEBUG_STRING_MAXLEN];
+} VzwDebugData;
+
+
+typedef void (* vzw_debug_callback)(VzwDebugData* vzw_message);
+
+/** Callback structure for the Vzw debug interface. */
+typedef struct {
+ vzw_debug_callback vzw_debug_cb;
+} VzwDebugCallbacks;
+
+
+/** Extended interface for VZW DEBUG support. */
+typedef struct {
+ /** set to sizeof(VzwDebugInterface) */
+ size_t size;
+
+ /** Registers the callbacks for Vzw debug message. */
+ int (*init)( VzwDebugCallbacks* callbacks );
+
+ /** Set Vzw debug screen enable/disable **/
+ void (*set_vzw_debug_screen)(bool enabled);
+} VzwDebugInterface;
+
+////////////////////// GNSS HIDL v1.0 ////////////////////////////
+
+enum { // ElapsedRealtimeFlags : uint16_t {
+ /** A valid timestampNs is stored in the data structure. */
+ HAS_TIMESTAMP_NS = 1 << 0,
+ /** A valid timeUncertaintyNs is stored in the data structure. */
+ HAS_TIME_UNCERTAINTY_NS = 1 << 1,
+};
+typedef uint16_t ElapsedRealtimeFlags;
+
+typedef struct {
+ /**
+ * A set of flags indicating the validity of each field in this data structure.
+ *
+ * Fields may have invalid information in them, if not marked as valid by the
+ * corresponding bit in flags.
+ */
+ uint16_t flags;
+
+ /**
+ * Estimate of the elapsed time since boot value for the corresponding event in nanoseconds.
+ */
+ uint64_t timestampNs;
+
+ /**
+ * Estimate of the relative precision of the alignment of this SystemClock
+ * timestamp, with the reported measurements in nanoseconds (68% confidence).
+ */
+ uint64_t timeUncertaintyNs;
+}ElapsedRealtime ;
+
+typedef unsigned int loc_type;
+#define MTK_LOC_TYPE_AGPS_AFLT 0 // From C2K AFLT flow
+#define MTK_LOC_TYPE_AGPS_CDMA_CELL 1 // From C2K Cell
+#define MTK_LOC_TYPE_AGPS_MOLR_BEGIN_RSP 2 // For CP MOLR after UE provides MSA result, the network will send CISS_FACILITY to provide UE a MSA location. Refer to 3GPP TS37.571-2 7.2.2.2
+#define MTK_LOC_TYPE_AGPS_SUPL_END 3 // From the SUPL END in a supl session. It may be the result of MSA, E-CID, OTDOA, or their hybrid.
+#define MTK_LOC_TYPE_AGPS_SUPL_REF_LOC 4 // For Reference Location assistance data in SUPL flow (equivalent to PMTK713 in SUPL flow)
+#define MTK_LOC_TYPE_AGPS_CP_REF_LOC 5 // For Reference Location assistance data in CP AGPS flow (equivalent to PMTK713 in CP AGPS flow)
+#define MTK_LOC_TYPE_GNSS_STANDALONE 0xfe // GNSS Standalone
+#define MTK_LOC_TYPE_GNSS_UNKNOWN 0xff // Unknown
+
+/** Represents a location. */
+typedef struct {
+ GpsLocation legacyLocation;
+ /**
+ * Represents expected horizontal position accuracy, radial, in meters
+ * (68% confidence).
+ */
+ float horizontalAccuracyMeters;
+
+ /**
+ * Represents expected vertical position accuracy in meters
+ * (68% confidence).
+ */
+ float verticalAccuracyMeters;
+
+ /**
+ * Represents expected speed accuracy in meter per seconds
+ * (68% confidence).
+ */
+ float speedAccuracyMetersPerSecond;
+
+ /**
+ * Represents expected bearing accuracy in degrees
+ * (68% confidence).
+ */
+ float bearingAccuracyDegrees;
+
+ /// v2.0
+ ElapsedRealtime elapsedRealtime;
+
+ loc_type type;
+} GpsLocation_ext;
+
+
+typedef struct {
+ GnssSvInfo legacySvInfo;
+
+ /// v1.0 ///
+ float carrier_frequency;
+
+ /// v2.1 ///
+ double basebandCN0DbHz;
+
+} GnssSvInfo_ext;
+
+/**
+ * Represents SV status.
+ */
+typedef struct {
+ /** set to sizeof(GnssSvStatus) */
+ size_t size;
+
+ /** Number of GPS SVs currently visible, refers to the SVs stored in sv_list */
+ int num_svs;
+ /**
+ * Pointer to an array of SVs information for all GNSS constellations,
+ * except GPS, which is reported using sv_list
+ */
+ GnssSvInfo_ext gnss_sv_list[MTK_MAX_SV_COUNT];
+
+} GnssSvStatus_ext;
+
+/**
+ * Callback with location information. Can only be called from a thread created
+ * by create_thread_cb.
+ */
+typedef void (* gps_location_ext_callback)(GpsLocation_ext* location);
+
+/**
+ * Callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* gnss_sv_status_ext_callback)(GnssSvStatus_ext* sv_info);
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ * geofence_id - The id associated with the add_geofence_area.
+ * location - The current GPS location.
+ * transition - Can be one of GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED,
+ * GPS_GEOFENCE_UNCERTAIN.
+ * timestamp - Timestamp when the transition was detected.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the GPS
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*gps_geofence_transition_ext_callback) (int32_t geofence_id,
+ GpsLocation_ext* location, int32_t transition, GpsUtcTime timestamp);
+
+/**
+ * The callback associated with the availability of the GPS system for geofencing
+ * monitoring. If the GPS system determines that it cannot monitor geofences
+ * because of lack of reliability or unavailability of the GPS signals, it will
+ * call this callback with GPS_GEOFENCE_UNAVAILABLE parameter.
+ *
+ * Parameters:
+ * status - GPS_GEOFENCE_UNAVAILABLE or GPS_GEOFENCE_AVAILABLE.
+ * last_location - Last known location.
+ */
+typedef void (*gps_geofence_status_ext_callback) (int32_t status,
+ GpsLocation_ext* last_location);
+
+typedef struct {
+ gps_geofence_transition_ext_callback geofence_transition_callback;
+ gps_geofence_status_ext_callback geofence_status_callback;
+ gps_geofence_add_callback geofence_add_callback;
+ gps_geofence_remove_callback geofence_remove_callback;
+ gps_geofence_pause_callback geofence_pause_callback;
+ gps_geofence_resume_callback geofence_resume_callback;
+ gps_create_thread create_thread_cb;
+} GpsGeofenceCallbacks_ext;
+
+/** Extended interface for GPS_Geofencing support */
+typedef struct {
+ /** set to sizeof(GpsGeofencingInterface) */
+ size_t size;
+
+ /**
+ * Opens the geofence interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ void (*init)( GpsGeofenceCallbacks_ext* callbacks );
+
+ /**
+ * Add a geofence area. This api currently supports circular geofences.
+ * Parameters:
+ * geofence_id - The id for the geofence. If a geofence with this id
+ * already exists, an error value (GPS_GEOFENCE_ERROR_ID_EXISTS)
+ * should be returned.
+ * latitude, longtitude, radius_meters - The lat, long and radius
+ * (in meters) for the geofence
+ * last_transition - The current state of the geofence. For example, if
+ * the system already knows that the user is inside the geofence,
+ * this will be set to GPS_GEOFENCE_ENTERED. In most cases, it
+ * will be GPS_GEOFENCE_UNCERTAIN.
+ * monitor_transition - Which transitions to monitor. Bitwise OR of
+ * GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+ * GPS_GEOFENCE_UNCERTAIN.
+ * notification_responsiveness_ms - Defines the best-effort description
+ * of how soon should the callback be called when the transition
+ * associated with the Geofence is triggered. For instance, if set
+ * to 1000 millseconds with GPS_GEOFENCE_ENTERED, the callback
+ * should be called 1000 milliseconds within entering the geofence.
+ * This parameter is defined in milliseconds.
+ * NOTE: This is not to be confused with the rate that the GPS is
+ * polled at. It is acceptable to dynamically vary the rate of
+ * sampling the GPS for power-saving reasons; thus the rate of
+ * sampling may be faster or slower than this.
+ * unknown_timer_ms - The time limit after which the UNCERTAIN transition
+ * should be triggered. This parameter is defined in milliseconds.
+ * See above for a detailed explanation.
+ */
+ void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude,
+ double radius_meters, int last_transition, int monitor_transitions,
+ int notification_responsiveness_ms, int unknown_timer_ms);
+
+ /**
+ * Pause monitoring a particular geofence.
+ * Parameters:
+ * geofence_id - The id for the geofence.
+ */
+ void (*pause_geofence) (int32_t geofence_id);
+
+ /**
+ * Resume monitoring a particular geofence.
+ * Parameters:
+ * geofence_id - The id for the geofence.
+ * monitor_transitions - Which transitions to monitor. Bitwise OR of
+ * GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+ * GPS_GEOFENCE_UNCERTAIN.
+ * This supersedes the value associated provided in the
+ * add_geofence_area call.
+ */
+ void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+ /**
+ * Remove a geofence area. After the function returns, no notifications
+ * should be sent.
+ * Parameter:
+ * geofence_id - The id for the geofence.
+ */
+ void (*remove_geofence_area) (int32_t geofence_id);
+} GpsGeofencingInterface_ext;
+
+enum {
+ STATE_UNKNOWN = 0,
+ STATE_CODE_LOCK = 1 << 0,
+ STATE_BIT_SYNC = 1 << 1,
+ STATE_SUBFRAME_SYNC = 1 << 2,
+ STATE_TOW_DECODED = 1 << 3,
+ STATE_MSEC_AMBIGUOUS = 1 << 4,
+ STATE_SYMBOL_SYNC = 1 << 5,
+ STATE_GLO_STRING_SYNC = 1 << 6,
+ STATE_GLO_TOD_DECODED = 1 << 7,
+ STATE_BDS_D2_BIT_SYNC = 1 << 8,
+ STATE_BDS_D2_SUBFRAME_SYNC = 1 << 9,
+ STATE_GAL_E1BC_CODE_LOCK = 1 << 10,
+ STATE_GAL_E1C_2ND_CODE_LOCK = 1 << 11,
+ STATE_GAL_E1B_PAGE_SYNC = 1 << 12,
+ STATE_SBAS_SYNC = 1 << 13,
+ STATE_TOW_KNOWN = 1 << 14,
+ STATE_GLO_TOD_KNOWN = 1 << 15,
+ STATE_2ND_CODE_LOCK = 1 << 16,
+};
+//typedef uint32_t GnssMeasurementState;
+
+/// extension to GnssConstellationType;
+enum {
+ /** Indian Regional Navigation Satellite System. */
+ GNSS_CONSTELLATION_IRNSS = 7,
+ GNSS_CONSTELLATION_SIZE = 8,
+};
+//typedef uint8_t GnssConstellationType;
+
+typedef struct {
+ GnssMeasurement legacyMeasurement;
+
+ /**
+ * Automatic gain control (AGC) level. AGC acts as a variable gain
+ * amplifier adjusting the power of the incoming signal. The AGC level
+ * may be used to indicate potential interference. When AGC is at a
+ * nominal level, this value must be set as 0. Higher gain (and/or lower
+ * input power) must be output as a positive number. Hence in cases of
+ * strong jamming, in the band of this signal, this value must go more
+ * negative.
+ *
+ * Note: Different hardware designs (e.g. antenna, pre-amplification, or
+ * other RF HW components) may also affect the typical output of of this
+ * value on any given hardware design in an open sky test - the
+ * important aspect of this output is that changes in this value are
+ * indicative of changes on input signal power in the frequency band for
+ * this measurement.
+ */
+ /// v1.1
+ double agc_level_db;
+
+ /// v2.0
+ char codeType[8];
+ // uint32_t state; direct use original field
+ //GnssConstellationType constellation; direct use original field
+
+ /// v2.1
+ //GnssMeasurementFlags flags; directly use original field
+
+ /**
+ * The full inter-signal bias (ISB) in nanoseconds.
+ *
+ * This value is the sum of the estimated receiver-side and the space-segment-side
+ * inter-system bias, inter-frequency bias and inter-code bias, including
+ *
+ * - Receiver inter-constellation bias (with respect to the constellation in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Receiver inter-frequency bias (with respect to the carrier frequency in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Receiver inter-code bias (with respect to the code type in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPS-UTC Time Offset
+ * (TauGps), BDS-GLO Time Offset (BGTO)) (with respect to the constellation in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Group delay (e.g., Total Group Delay (TGD))
+ * - Satellite inter-frequency bias (GLO only) (with respect to the carrier frequency in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Satellite inter-code bias (e.g., Differential Code Bias (DCB)) (with respect to the
+ * code type in GnssClock.referenceSignalTypeForIsb)
+ *
+ * If a component of the above is already compensated in the provided
+ * GnssMeasurement.receivedSvTimeInNs, then it must not be included in the reported full
+ * ISB.
+ *
+ * The value does not include the inter-frequency Ionospheric bias.
+ *
+ * The full ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
+ */
+ double fullInterSignalBiasNs;
+
+ /**
+ * 1-sigma uncertainty associated with the full inter-signal bias in nanoseconds.
+ */
+ double fullInterSignalBiasUncertaintyNs;
+
+ /**
+ * The satellite inter-signal bias in nanoseconds.
+ *
+ * This value is the satellite-and-control-segment-side inter-system (different from the
+ * constellation in GnssClock.referenceSignalTypeForIsb) bias and inter-frequency (different
+ * from the carrier frequency in GnssClock.referenceSignalTypeForIsb) bias, including:
+ *
+ * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPT-UTC Time Offset (TauGps),
+ * BDS-GLO Time Offset (BGTO))
+ * - Group delay (e.g., Total Group Delay (TGD))
+ * - Satellite inter-signal bias, which includes satellite inter-frequency bias (GLO only),
+ * and satellite inter-code bias (e.g., Differential Code Bias (DCB)).
+ *
+ * The receiver ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
+ */
+ double satelliteInterSignalBiasNs;
+
+ /**
+ * 1-sigma uncertainty associated with the satellite inter-signal bias in nanoseconds.
+ */
+ double satelliteInterSignalBiasUncertaintyNs;
+
+ /**
+ * Baseband Carrier-to-noise density in dB-Hz, typically in the range [0, 63]. It contains
+ * the measured C/N0 value for the signal measured at the baseband.
+ *
+ * This is typically a few dB weaker than the value estimated for C/N0 at the antenna port,
+ * which is reported in cN0DbHz.
+ *
+ * If a signal has separate components (e.g. Pilot and Data channels) and the receiver only
+ * processes one of the components, then the reported basebandCN0DbHz reflects only the
+ * component that is processed.
+ *
+ * This value is mandatory.
+ */
+ double basebandCN0DbHz;
+
+} GnssMeasurement_ext;
+
+typedef struct {
+ GnssConstellationType constellation;
+ double carrierFrequencyHz;
+ char codeType[8];
+} GnssSignalType;
+
+typedef struct {
+ GnssClock legacyClock;
+ GnssSignalType referenceSignalTypeForIsb;
+} GnssClock_ext;
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+ /** set to sizeof(GnssData) */
+ size_t size;
+
+ /** Number of measurements. */
+ size_t measurement_count;
+
+ /** The array of measurements. */
+ GnssMeasurement_ext measurements[MTK_MAX_SV_COUNT];
+
+ /** The GPS clock time reading. */
+ /// v2.1
+ GnssClock_ext clock;
+
+ /// v2.0
+ ElapsedRealtime elapsedRealtime;
+} GnssData_ext;
+
+/**
+ * The callback for to report measurements from the HAL.
+ *
+ * Parameters:
+ * data - A data structure containing the measurements.
+ */
+typedef void (*gnss_measurement_ext_callback) (GnssData_ext* data);
+
+typedef struct {
+ /** set to sizeof(GpsMeasurementCallbacks) */
+ size_t size;
+ gps_measurement_callback measurement_callback;
+ gnss_measurement_ext_callback gnss_measurement_callback;
+} GpsMeasurementCallbacks_ext;
+
+
+/////// Gnss debug ////
+
+/** Milliseconds since January 1, 1970 */
+typedef int64_t GnssUtcTime;
+
+typedef enum {
+ /** Ephemeris is known for this satellite. */
+ EPHEMERIS,
+ /**
+ * Ephemeris is not known, but Almanac (approximate location) is known.
+ */
+ ALMANAC_ONLY,
+ /**
+ * Both ephemeris & almanac are not known (e.g. during a cold start
+ * blind search.)
+ */
+ NOT_AVAILABLE
+} SatelliteEphemerisType;
+
+typedef enum {
+ /**
+ * The ephemeris (or almanac only) information was demodulated from the
+ * signal received on the device
+ */
+ DEMODULATED,
+ /**
+ * The ephemeris (or almanac only) information was received from a SUPL
+ * server.
+ */
+ SUPL_PROVIDED,
+ /**
+ * The ephemeris (or almanac only) information was provided by another
+ * server.
+ */
+ OTHER_SERVER_PROVIDED,
+ /**
+ * The ephemeris (or almanac only) information was provided by another
+ * method, e.g. injected via a local debug tool, from build defaults
+ * (e.g. almanac), or is from a satellite
+ * with SatelliteEphemerisType::NOT_AVAILABLE.
+ */
+ OTHER
+} SatelliteEphemerisSource;
+
+typedef enum {
+ /** The ephemeris is known good. */
+ GOOD,
+ /** The ephemeris is known bad. */
+ BAD,
+ /** The ephemeris is unknown to be good or bad. */
+ UNKNOWN
+} SatelliteEphemerisHealth;
+
+/**
+ * Provides the current best known position from any
+ * source (GNSS or injected assistance).
+ */
+typedef struct {
+ /**
+ * Validity of the data in this struct. False only if no
+ * latitude/longitude information is known.
+ */
+ bool valid;
+ /** Latitude expressed in degrees */
+ double latitudeDegrees;
+ /** Longitude expressed in degrees */
+ double longitudeDegrees;
+ /** Altitude above ellipsoid expressed in meters */
+ float altitudeMeters;
+ /** Represents horizontal speed in meters per second. */
+ float speedMetersPerSec;
+ /** Represents heading in degrees. */
+ float bearingDegrees;
+ /**
+ * Estimated horizontal accuracy of position expressed in meters,
+ * radial, 68% confidence.
+ */
+ double horizontalAccuracyMeters;
+ /**
+ * Estimated vertical accuracy of position expressed in meters, with
+ * 68% confidence.
+ */
+ double verticalAccuracyMeters;
+ /**
+ * Estimated speed accuracy in meters per second with 68% confidence.
+ */
+ double speedAccuracyMetersPerSecond;
+ /**
+ * estimated bearing accuracy degrees with 68% confidence.
+ */
+ double bearingAccuracyDegrees;
+ /**
+ * Time duration before this report that this position information was
+ * valid. This can, for example, be a previous injected location with
+ * an age potentially thousands of seconds old, or
+ * extrapolated to the current time (with appropriately increased
+ * accuracy estimates), with a (near) zero age.
+ */
+ float ageSeconds;
+} PositionDebug;
+
+/**
+ * Provides the current best known UTC time estimate.
+ * If no fresh information is available, e.g. after a delete all,
+ * then whatever the effective defaults are on the device must be
+ * provided (e.g. Jan. 1, 2017, with an uncertainty of 5 years) expressed
+ * in the specified units.
+ */
+typedef struct {
+ /** UTC time estimate. */
+ GnssUtcTime timeEstimate;
+ /** 68% error estimate in time. */
+ float timeUncertaintyNs;
+ /**
+ * 68% error estimate in local clock drift,
+ * in nanoseconds per second (also known as parts per billion - ppb.)
+ */
+ float frequencyUncertaintyNsPerSec;
+} TimeDebug;
+
+/**
+ * Provides a single satellite info that has decoded navigation data.
+ */
+typedef struct {
+ /** Satellite vehicle ID number */
+ int16_t svid;
+ /** Defines the constellation type of the given SV. */
+ GnssConstellationType constellation;
+
+ /**
+ * Defines the standard broadcast ephemeris or almanac availability for
+ * the satellite. To report status of predicted orbit and clock
+ * information, see the serverPrediction fields below.
+ */
+ SatelliteEphemerisType ephemerisType;
+ /** Defines the ephemeris source of the satellite. */
+ SatelliteEphemerisSource ephemerisSource;
+ /**
+ * Defines whether the satellite is known healthy
+ * (safe for use in location calculation.)
+ */
+ SatelliteEphemerisHealth ephemerisHealth;
+ /**
+ * Time duration from this report (current time), minus the
+ * effective time of the ephemeris source (e.g. TOE, TOA.)
+ * Set to 0 when ephemerisType is NOT_AVAILABLE.
+ */
+ float ephemerisAgeSeconds;
+
+ /**
+ * True if a server has provided a predicted orbit and clock model for
+ * this satellite.
+ */
+ bool serverPredictionIsAvailable;
+ /**
+ * Time duration from this report (current time) minus the time of the
+ * start of the server predicted information. For example, a 1 day
+ * old prediction would be reported as 86400 seconds here.
+ */
+ float serverPredictionAgeSeconds;
+} SatelliteData;
+
+/**
+ * Provides a set of debug information that is filled by the GNSS chipset
+ * when the method getDebugData() is invoked.
+ */
+typedef struct {
+ /** Current best known position. */
+ PositionDebug position;
+ /** Current best know time estimate */
+ TimeDebug time;
+ /**
+ * Provides a list of the available satellite data, for all
+ * satellites and constellations the device can track,
+ * including GnssConstellationType UNKNOWN.
+ */
+ SatelliteData satelliteDataArray[MTK_MAX_SV_COUNT];
+} DebugData;
+
+
+/** Extended interface for DEBUG support. */
+typedef struct {
+ /** set to sizeof(GpsDebugInterface) */
+ size_t size;
+
+ /**
+ * This function should return any information that the native
+ * implementation wishes to include in a bugreport.
+ */
+ // size_t (*get_internal_state)(char* buffer, size_t bufferSize);
+ /// v1.0 ///
+ bool (*get_internal_state)(DebugData* debugData);
+} GpsDebugInterface_ext;
+
+
+////////////////////// GNSS HIDL v1.1 ////////////////////////////
+
+/**
+ * Callback for reporting driver name information.
+ */
+typedef void (* gnss_set_name_callback)(const char* name, int length);
+
+/**
+ * Callback for requesting framework NLP or Fused location injection.
+ */
+typedef void (* gnss_request_location_callback)(bool independentFromGnss, bool isUserEmergency);
+
+/** New GPS callback structure. */
+typedef struct {
+ /** set to sizeof(GpsCallbacks) */
+ size_t size;
+ gps_location_ext_callback location_cb;
+ gps_status_callback status_cb;
+ gps_sv_status_callback sv_status_cb;
+ gps_nmea_callback nmea_cb;
+ gps_set_capabilities set_capabilities_cb;
+ gps_acquire_wakelock acquire_wakelock_cb;
+ gps_release_wakelock release_wakelock_cb;
+ gps_create_thread create_thread_cb;
+ gps_request_utc_time request_utc_time_cb;
+
+ gnss_set_system_info set_system_info_cb;
+ gnss_sv_status_ext_callback gnss_sv_status_cb;
+
+ /////v1.1////
+ gnss_set_name_callback set_name_cb;
+ ///// v2.0 ///
+ gnss_request_location_callback request_location_cb;
+
+ gps_location_ext_callback agps_location_cb;
+} GpsCallbacks_ext;
+
+
+/** Represents the standard GPS interface. */
+typedef struct {
+ /** set to sizeof(GpsInterface) */
+ size_t size;
+ /**
+ * Opens the interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ /// v1.0 ///
+// int (*init)( GpsCallbacks* callbacks );
+ /// v1.1 ///
+ int (*init)( GpsCallbacks_ext* callbacks );
+
+ /** Starts navigating. */
+ int (*start)( void );
+
+ /** Stops navigating. */
+ int (*stop)( void );
+
+ /** Closes the interface. */
+ void (*cleanup)( void );
+
+ /** Injects the current time. */
+ int (*inject_time)(GpsUtcTime time, int64_t timeReference,
+ int uncertainty);
+
+ /**
+ * Injects current location from another location provider (typically cell
+ * ID). Latitude and longitude are measured in degrees expected accuracy is
+ * measured in meters
+ */
+ int (*inject_location)(double latitude, double longitude, float accuracy);
+
+ /**
+ * Specifies that the next call to start will not use the
+ * information defined in the flags. GPS_DELETE_ALL is passed for
+ * a cold start.
+ */
+ void (*delete_aiding_data)(GpsAidingData flags);
+
+ /**
+ * min_interval represents the time between fixes in milliseconds.
+ * preferred_accuracy represents the requested fix accuracy in meters.
+ * preferred_time represents the requested time to first fix in milliseconds.
+ *
+ * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASED
+ * or GPS_POSITION_MODE_STANDALONE.
+ * It is allowed by the platform (and it is recommended) to fallback to
+ * GPS_POSITION_MODE_MS_BASED if GPS_POSITION_MODE_MS_ASSISTED is passed in, and
+ * GPS_POSITION_MODE_MS_BASED is supported.
+ */
+ /// v1.0 ///
+// int (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+// uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
+ /// v1.1 ///
+ int (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+ uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time,
+ bool lowPowerMode);
+
+
+ /** Get a pointer to extension information. */
+ const void* (*get_extension)(const char* name);
+
+ /// v1.1 ///
+ int (*inject_fused_location)(double latitude, double longitude, float accuracy);
+
+} GpsInterface_ext;
+
+
+/**
+ * Extended interface for GPS Measurements support.
+ */
+typedef struct {
+ /** Set to sizeof(GpsMeasurementInterface_ext) */
+ size_t size;
+
+ /**
+ * Initializes the interface and registers the callback routines with the HAL.
+ * After a successful call to 'init' the HAL must begin to provide updates at its own phase.
+ *
+ * Status:
+ * GPS_MEASUREMENT_OPERATION_SUCCESS
+ * GPS_MEASUREMENT_ERROR_ALREADY_INIT - if a callback has already been registered without a
+ * corresponding call to 'close'
+ * GPS_MEASUREMENT_ERROR_GENERIC - if any other error occurred, it is expected that the HAL
+ * will not generate any updates upon returning this error code.
+ */
+ /// v1.0 ///
+// int (*init) (GpsMeasurementCallbacks* callbacks);
+ /// v1.1 ///
+ int (*init) (GpsMeasurementCallbacks_ext* callbacks, bool enableFullTracking);
+
+ /**
+ * Stops updates from the HAL, and unregisters the callback routines.
+ * After a call to stop, the previously registered callbacks must be considered invalid by the
+ * HAL.
+ * If stop is invoked without a previous 'init', this function should perform no work.
+ */
+ void (*close) ();
+
+} GpsMeasurementInterface_ext;
+
+
+/**
+ * Interface for passing GNSS configuration contents from platform to HAL.
+ */
+typedef struct {
+ /** Set to sizeof(GnssConfigurationInterface) */
+ size_t size;
+
+ /**
+ * Deliver GNSS configuration contents to HAL.
+ * Parameters:
+ * config_data - a pointer to a char array which holds what usually is expected from
+ file(/etc/gps.conf), i.e., a sequence of UTF8 strings separated by '\n'.
+ * length - total number of UTF8 characters in configuraiton data.
+ *
+ * IMPORTANT:
+ * GPS HAL should expect this function can be called multiple times. And it may be
+ * called even when GpsLocationProvider is already constructed and enabled. GPS HAL
+ * should maintain the existing requests for various callback regardless the change
+ * in configuration data.
+ */
+ void (*configuration_update) (const char* config_data, int32_t length);
+
+ //// v1.1 ////
+ void (*set_black_list) (long long* blacklist, int32_t size);
+
+ //// v2.0 ////
+ void (*set_es_extension_sec) (uint32_t emergencyExtensionSeconds);
+} GnssConfigurationInterface_ext;
+
+////////////////////// GNSS HIDL v2.0 ////////////////////////////
+
+#define STRING_MAXLEN 256
+
+/**
+ * Name for the GNSS measurement correction interface.
+ */
+#define GNSS_MEASUREMENT_CORRECTION_INTERFACE "gnss_measurement_correction"
+
+/**
+ * Name for the GNSS visibility control interface.
+ */
+#define GNSS_VISIBILITY_CONTROL_INTERFACE "gnss_visiblity_control"
+
+//// GNSS capabilities extension
+enum {
+ /** GNSS supports low power mode */
+ GPS_CAPABILITY_LOW_POWER_MODE = 1 << 8,
+ /** GNSS supports blacklisting satellites */
+ GPS_CAPABILITY_SATELLITE_BLACKLIST = 1 << 9,
+ /** GNSS supports measurement corrections */
+ MEASUREMENT_CORRECTIONS = 1 << 10,
+ /** GNSS supports measurement corrections */
+ ANTENNA_INFO = 1 << 11
+};
+typedef uint32_t GnssCapabilities;
+
+enum {
+ // SUPL = 1, // already defined
+ // C2K = 2, // already defined
+ AGPS_TYPE_SUPL_EIMS = 3,
+ AGPS_TYPE_SUPL_IMS = 4,
+};
+typedef uint8_t AGnssType;
+
+enum {
+ /** GNSS requests data connection for AGNSS. */
+ REQUEST_AGNSS_DATA_CONN = 1,
+ /** GNSS releases the AGNSS data connection. */
+ RELEASE_AGNSS_DATA_CONN = 2,
+ /** AGNSS data connection initiated */
+ AGNSS_DATA_CONNECTED = 3,
+ /** AGNSS data connection completed */
+ AGNSS_DATA_CONN_DONE = 4,
+ /** AGNSS data connection failed */
+ AGNSS_DATA_CONN_FAILED = 5
+};
+typedef uint8_t AGnssStatusValue;
+
+/**
+ * Extended interface for AGPS support, it is augmented to enable to pass
+ * extra APN data.
+ */
+typedef struct {
+ /** set to sizeof(AGpsInterface) */
+ size_t size;
+
+ /**
+ * Opens the AGPS interface and provides the callback routines to the
+ * implementation of this interface.
+ */
+ void (*init)(AGpsCallbacks* callbacks);
+ /**
+ * Deprecated.
+ * If the HAL supports AGpsInterface_v2 this API will not be used, see
+ * data_conn_open_with_apn_ip_type for more information.
+ */
+ int (*data_conn_open)(const char* apn);
+ /**
+ * Notifies that the AGPS data connection has been closed.
+ */
+ int (*data_conn_closed)();
+ /**
+ * Notifies that a data connection is not available for AGPS.
+ */
+ int (*data_conn_failed)();
+ /**
+ * Sets the hostname and port for the AGPS server.
+ */
+ int (*set_server)(AGpsType type, const char* hostname, int port);
+
+ /**
+ * Notifies that a data connection is available and sets the name of the
+ * APN, and its IP type, to be used for SUPL connections.
+ */
+ int (*data_conn_open_with_apn_ip_type)(
+ uint64_t networkHandle,
+ const char* apn,
+ ApnIpType apnIpType);
+} AGpsInterface_ext;
+
+/** Flags to indicate capabilities of the network */
+enum { //NetworkCapability : uint16_t {
+ /** Network is not metered. */
+ NOT_METERED = 1 << 0,
+ /** Network is not roaming. */
+ NOT_ROAMING = 1 << 1
+};
+typedef uint16_t NetworkCapability;
+
+
+/** Extended interface for AGPS_RIL support. */
+typedef struct {
+ /** set to sizeof(AGpsRilInterface_ext) */
+ size_t size;
+ /**
+ * Opens the AGPS interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ void (*init)( AGpsRilCallbacks* callbacks );
+
+ /**
+ * Sets the reference location.
+ */
+ void (*set_ref_location) (const AGpsRefLocation *agps_reflocation, size_t sz_struct);
+ /**
+ * Sets the set ID.
+ */
+ void (*set_set_id) (AGpsSetIDType type, const char* setid);
+
+ /**
+ * Send network initiated message.
+ */
+ void (*ni_message) (uint8_t *msg, size_t len);
+
+ /**
+ * Notify GPS of network status changes.
+ * These parameters match values in the android.net.NetworkInfo class.
+ */
+ //// v2.0 ///
+ void (*update_network_state_ext) (uint64_t networkHandle, bool isConnected,
+ uint16_t capabilities, const char* apn);
+
+ /**
+ * Notify GPS of network status changes.
+ * These parameters match values in the android.net.NetworkInfo class.
+ */
+ void (*update_network_availability) (int avaiable, const char* apn);
+} AGpsRilInterface_ext;
+
+
+/** Bit mask to indicate which values are valid in a SingleSatCorrection object. */
+enum { //GnssSingleSatCorrectionFlags : uint16_t {
+ /** GnssSingleSatCorrectionFlags has valid satellite-is-line-of-sight-probability field. */
+ HAS_SAT_IS_LOS_PROBABILITY = 0x0001,
+ /** GnssSingleSatCorrectionFlags has valid Excess Path Length field. */
+ HAS_EXCESS_PATH_LENGTH = 0x0002,
+ /** GnssSingleSatCorrectionFlags has valid Excess Path Length Uncertainty field. */
+ HAS_EXCESS_PATH_LENGTH_UNC = 0x0004,
+ /** GnssSingleSatCorrectionFlags has valid Reflecting Plane field. */
+ HAS_REFLECTING_PLANE = 0x0008
+};
+typedef uint16_t GnssSingleSatCorrectionFlags;
+
+/**
+ * A struct containing the characteristics of the reflecting plane that the satellite signal has
+ * bounced from.
+ *
+ * The value is only valid if HAS_REFLECTING_PLANE flag is set. An invalid reflecting plane
+ * means either reflection planes serving is not supported or the satellite signal has gone
+ * through multiple reflections.
+ */
+typedef struct {
+ /** Represents latitude of the reflecting plane in degrees. */
+ double latitudeDegrees;
+
+ /** Represents longitude of the reflecting plane in degrees. */
+ double longitudeDegrees;
+
+ /**
+ * Represents altitude of the reflecting point in the plane in meters above the WGS 84 reference
+ * ellipsoid.
+ */
+ double altitudeMeters;
+
+ /** Represents azimuth clockwise from north of the reflecting plane in degrees. */
+ double azimuthDegrees;
+} ReflectingPlane ;
+
+
+typedef struct {
+
+ /** Contains GnssSingleSatCorrectionFlags bits. */
+ uint16_t singleSatCorrectionFlags;
+
+ /**
+ * Defines the constellation of the given satellite.
+ */
+ GnssConstellationType constellation;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ */
+ uint16_t svid;
+
+ /**
+ * Carrier frequency of the signal to be corrected, for example it can be the
+ * GPS center frequency for L1 = 1,575,420,000 Hz, varying GLO channels, etc.
+ *
+ * For a receiver with capabilities to track multiple frequencies for the same satellite,
+ * multiple corrections for the same satellite may be provided.
+ */
+ float carrierFrequencyHz;
+
+ /**
+ * The probability that the satellite is estimated to be in Line-of-Sight condition at the given
+ * location.
+ */
+ float probSatIsLos;
+
+ /**
+ * Excess path length to be subtracted from pseudorange before using it in calculating location.
+ *
+ * Note this value is NOT to be used to adjust the GnssMeasurementCallback outputs.
+ */
+ float excessPathLengthMeters;
+
+ /** Error estimate (1-sigma) for the Excess path length estimate */
+ float excessPathLengthUncertaintyMeters;
+
+ /**
+ * Defines the reflecting plane characteristics such as location and azimuth
+ *
+ * The value is only valid if HAS_REFLECTING_PLANE flag is set. An invalid reflecting plane
+ * means either reflection planes serving is not supported or the satellite signal has gone
+ * through multiple reflections.
+ */
+ ReflectingPlane reflectingPlane;
+}SingleSatCorrection;
+
+/**
+ * A struct containing a set of measurement corrections for all used GNSS satellites at the location
+ * specified by latitudeDegrees, longitudeDegrees, altitudeMeters and at the time of week specified
+ * toaGpsNanosecondsOfWeek
+ */
+typedef struct {
+ /** Represents latitude in degrees at which the corrections are computed.. */
+ double latitudeDegrees;
+
+ /** Represents longitude in degrees at which the corrections are computed.. */
+ double longitudeDegrees;
+
+ /**
+ * Represents altitude in meters above the WGS 84 reference ellipsoid at which the corrections
+ * are computed.
+ */
+ double altitudeMeters;
+
+ /**
+ * Represents the horizontal uncertainty (68% confidence) in meters on the device position at
+ * which the corrections are provided.
+ *
+ * This value is useful for example to judge how accurate the provided corrections are.
+ */
+ double horizontalPositionUncertaintyMeters;
+
+ /**
+ * Represents the vertical uncertainty (68% confidence) in meters on the device position at
+ * which the corrections are provided.
+ *
+ * This value is useful for example to judge how accurate the provided corrections are.
+ */
+ double verticalPositionUncertaintyMeters;
+
+ /** Time Of Applicability, GPS time of week in nanoseconds. */
+ uint64_t toaGpsNanosecondsOfWeek;
+
+ /** Number of singleSatCorrection */
+ size_t num_satCorrection;
+
+ /**
+ * A set of SingleSatCorrection each containing measurement corrections for a satellite in view
+ */
+ SingleSatCorrection satCorrections[MTK_MAX_SV_COUNT];
+
+ /// v1.1
+ /*** Boolean indicating if environment bearing is available. */
+ bool hasEnvironmentBearing;
+ float environmentBearingDegrees;
+ float environmentBearingUncertaintyDegrees;
+ /// directly use original field
+ //SingleSatCorrection satCorrections[MTK_MAX_SV_COUNT];
+} MeasurementCorrections;
+
+
+enum { //MeasurementCorrectionCapabilities : uint32_t {
+ /** GNSS supports line-of-sight satellite identification measurement corrections */
+ LOS_SATS = 1 << 0,
+ /** GNSS supports per satellite excess-path-length measurement corrections */
+ EXCESS_PATH_LENGTH = 1 << 1,
+ /** GNSS supports reflecting planes measurement corrections */
+ REFLECTING_PLANE = 1 << 2
+};
+typedef uint32_t MeasurementCorrectionCapabilities;
+
+
+/**
+ * Callback to inform framework the measurement correction specific capabilities of the GNSS
+ * HAL implementation.
+ *
+ * The GNSS HAL must call this method immediately after the framework opens the measurement
+ * corrections interface.
+ *
+ * @param capabilities Supported measurement corrections capabilities. It is mandatory to
+ * support either LOS_STATS or EXCESS_PATH_LENGTH capability.
+ *
+ */
+typedef void (*meac_set_capabilities_cb) (uint32_t capabilities);
+
+typedef struct {
+ /** set to sizeof(GpsMeasurementCorrectionCallbacks) */
+ size_t size;
+ meac_set_capabilities_cb set_capabilities_cb;
+} MeasurementCorrectionCallbacks_ext;
+
+
+
+typedef struct {
+
+ /** Set to sizeof(GpsMeasurementCorrectionInterface) */
+ size_t size;
+
+ bool (*meac_set_callback) (MeasurementCorrectionCallbacks_ext* callbacks);
+
+ bool (*meac_set_corrections) (MeasurementCorrections* corrections);
+
+}MeasurementCorrectionInterface;
+
+
+/**
+ * Protocol stack that is requesting the non-framework location information.
+ */
+enum {
+ /** Cellular control plane requests */
+ CTRL_PLANE = 0,
+ /** All types of SUPL requests */
+ SUPL = 1,
+
+ /** All types of requests from IMS */
+ IMS = 10,
+ /** All types of requests from SIM */
+ SIM = 11,
+
+ /** Requests from other protocol stacks */
+ OTHER_PROTOCOL_STACK = 100
+};
+typedef uint8_t NfwProtocolStack;
+
+/*
+ * Entity that is requesting/receiving the location information.
+ */
+enum { //NfwRequestor : uint8_t {
+ /** Wireless service provider */
+ CARRIER = 0,
+ /** Device manufacturer */
+ OEM = 10,
+ /** Modem chipset vendor */
+ MODEM_CHIPSET_VENDOR = 11,
+ /** GNSS chipset vendor */
+ GNSS_CHIPSET_VENDOR = 12,
+ /** Other chipset vendor */
+ OTHER_CHIPSET_VENDOR = 13,
+ /** Automobile client */
+ AUTOMOBILE_CLIENT = 20,
+ /** Other sources */
+ OTHER_REQUESTOR = 100
+ };
+typedef uint8_t NfwRequestor;
+
+/**
+ * GNSS response type for non-framework location requests.
+ */
+enum {//NfwResponseType : uint8_t {
+ /** Request rejected because framework has not given permission for this use case */
+ REJECTED = 0,
+
+ /** Request accepted but could not provide location because of a failure */
+ ACCEPTED_NO_LOCATION_PROVIDED = 1,
+
+ /** Request accepted and location provided */
+ ACCEPTED_LOCATION_PROVIDED = 2,
+};
+typedef uint8_t NfwResponseType;
+
+/**
+ * Represents a non-framework location information request/response notification.
+ */
+typedef struct {
+ /**
+ * Package name of the Android proxy application representing the non-framework
+ * entity that requested location. Set to empty string if unknown.
+ */
+ char proxyAppPackageName[STRING_MAXLEN];
+
+ /** Protocol stack that initiated the non-framework location request. */
+ NfwProtocolStack protocolStack;
+
+ /**
+ * Name of the protocol stack if protocolStack field is set to OTHER_PROTOCOL_STACK.
+ * Otherwise, set to empty string.
+ *
+ * This field is opaque to the framework and used for logging purposes.
+ */
+ char otherProtocolStackName[STRING_MAXLEN];
+
+ /** Source initiating/receiving the location information. */
+ NfwRequestor requestor;
+
+ /**
+ * Identity of the endpoint receiving the location information. For example, carrier
+ * name, OEM name, SUPL SLP/E-SLP FQDN, chipset vendor name, etc.
+ *
+ * This field is opaque to the framework and used for logging purposes.
+ */
+ char requestorId[STRING_MAXLEN];
+
+ /** Indicates whether location information was provided for this request. */
+ NfwResponseType responseType;
+
+ /** Is the device in user initiated emergency session. */
+ bool inEmergencyMode;
+
+ /** Is cached location provided */
+ bool isCachedLocation;
+} NfwNotification;
+
+/**
+ * Callback to report a non-framework delivered location.
+ *
+ * The GNSS HAL implementation must call this method to notify the framework whenever
+ * a non-framework location request is made to the GNSS HAL.
+ *
+ * Non-framework entities like low power sensor hubs that request location from GNSS and
+ * only pass location information through Android framework controls are exempt from this
+ * power-spending reporting. However, low power sensor hubs or other chipsets which may send
+ * the location information to anywhere other than Android framework (which provides user
+ * visibility and control), must report location information use through this API whenever
+ * location information (or events driven by that location such as "home" location detection)
+ * leaves the domain of that low power chipset.
+ *
+ * To avoid overly spamming the framework, high speed location reporting of the exact same
+ * type may be throttled to report location at a lower rate than the actual report rate, as
+ * long as the location is reported with a latency of no more than the larger of 5 seconds,
+ * or the next the Android processor awake time. For example, if an Automotive client is
+ * getting location information from the GNSS location system at 20Hz, this method may be
+ * called at 1Hz. As another example, if a low power processor is getting location from the
+ * GNSS chipset, and the Android processor is asleep, the notification to the Android HAL may
+ * be delayed until the next wake of the Android processor.
+ *
+ * @param notification Non-framework delivered location request/response description.
+ */
+typedef void (*vc_nfw_notify_cb) (NfwNotification notification);
+
+/**
+ * Tells if the device is currently in an emergency session.
+ *
+ * Emergency session is defined as the device being actively in a user initiated emergency
+ * call or in post emergency call extension time period.
+ *
+ * If the GNSS HAL implementation cannot determine if the device is in emergency session
+ * mode, it must call this method to confirm that the device is in emergency session before
+ * serving network initiated emergency SUPL and Control Plane location requests.
+ *
+ * @return success True if the framework determines that the device is in emergency session.
+ */
+typedef bool (*vc_is_in_emergency_session) ();
+
+typedef struct {
+ /** set to sizeof(GpsMeasurementCorrectionCallbacks) */
+ size_t size;
+ vc_nfw_notify_cb nfw_notify_cb;
+ vc_is_in_emergency_session is_in_emergency_session;
+} GnssVisibilityControlCallback_ext;
+
+
+
+typedef struct {
+
+ /** Set to sizeof(GnssVisibilityControlInterface) */
+ size_t size;
+
+ /**
+ * Registers the callback for HAL implementation to use.
+ *
+ * @param callback Handle to IGnssVisibilityControlCallback interface.
+ */
+ bool (*vc_set_callback) (GnssVisibilityControlCallback_ext* callbacks);
+
+ /**
+ * Enables/disables non-framework entity location access permission in the GNSS HAL.
+ *
+ * The framework will call this method to update GNSS HAL implementation every time the
+ * framework user, through the given proxy application(s) and/or device location settings,
+ * explicitly grants/revokes the location access permission for non-framework, non-user
+ * initiated emergency use cases.
+ *
+ * Whenever the user location information is delivered to non-framework entities, the HAL
+ * implementation must call the method IGnssVisibilityControlCallback.nfwNotifyCb() to notify
+ * the framework for user visibility.
+ *
+ * @param proxyApps Full list of package names of proxy Android applications representing
+ * the non-framework location access entities (on/off the device) for which the framework
+ * user has granted non-framework location access permission. The GNSS HAL implementation
+ * must provide location information only to non-framework entities represented by these
+ * proxy applications.
+ *
+ * The package name of the proxy Android application follows the standard Java language
+ * package naming format. For example, com.example.myapp.
+ *
+ * @return success True if the operation was successful.
+ */
+ bool (*vc_enable_nfw_location_access) (const char* proxyApps, int32_t length);
+
+}GnssVisibilityControlInterface;
+
+////////////////////// GNSS HIDL v2.1 ////////////////////////////
+
+/**
+ * Name for the GNSS measurement correction interface.
+ */
+#define GNSS_ANTENNA_INFO_INTERFACE "gnss_antenna_info"
+
+enum { //GnssMeasurementFlags
+ // v1.0
+ /** A valid 'snr' is stored in the data structure. */
+ HAS_SNR = 1 << 0,
+ /** A valid 'carrier frequency' is stored in the data structure. */
+ HAS_CARRIER_FREQUENCY = 1 << 9,
+ /** A valid 'carrier cycles' is stored in the data structure. */
+ HAS_CARRIER_CYCLES = 1 << 10,
+ /** A valid 'carrier phase' is stored in the data structure. */
+ HAS_CARRIER_PHASE = 1 << 11,
+ /** A valid 'carrier phase uncertainty' is stored in the data structure. */
+ HAS_CARRIER_PHASE_UNCERTAINTY = 1 << 12,
+ /** A valid automatic gain control is stored in the data structure. */
+ HAS_AUTOMATIC_GAIN_CONTROL = 1 << 13,
+
+ //v2.1
+ /*** A valid receiver inter-signal bias is stored in the data structure. */
+ HAS_RECEIVER_ISB = 1 << 16,
+ /*** A valid receiver inter-signal bias uncertainty is stored in the data structure. */
+ HAS_RECEIVER_ISB_UNCERTAINTY = 1 << 17,
+ /*** A valid satellite inter-signal bias is stored in the data structure. */
+ HAS_SATELLITE_ISB = 1 << 18,
+ /*** A valid satellite inter-signal bias uncertainty is stored in the data structure. */
+ HAS_SATELLITE_ISB_UNCERTAINTY = 1 << 19,
+};
+
+/**
+ * A row of doubles. This is used to represent a row in a 2D array, which are used to
+ * characterize the phase center variation corrections and signal gain corrections.
+ */
+typedef struct{
+ double row[6];
+} Row;
+
+/**
+ * A point in 3D space, with associated uncertainty.
+ */
+typedef struct {
+ double x;
+ double xUncertainty;
+ double y;
+ double yUncertainty;
+ double z;
+ double zUncertainty;
+} Coord;
+
+typedef struct {
+ /** The carrier frequency in MHz. */
+ double carrierFrequencyMHz;
+
+ /**
+ * Phase center offset (PCO) with associated 1-sigma uncertainty. PCO is defined with
+ * respect to the origin of the Android sensor coordinate system, e.g., center of primary
+ * screen for mobiles - see sensor or form factor documents for details.
+ */
+ Coord phaseCenterOffsetCoordinateMillimeters;
+
+ /**
+ * 2D vectors representing the phase center variation (PCV) corrections, in
+ * millimeters, at regularly spaced azimuthal angle (theta) and zenith angle
+ * (phi). The PCV correction is added to the phase measurement to obtain the
+ * corrected value.*/
+ Row phaseCenterVariationCorrectionMillimeters[3];
+
+ /**
+ * 2D vectors of 1-sigma uncertainty in millimeters associated with the PCV
+ * correction values.
+ *
+ * This field is optional, i.e., an empty vector.
+ */
+ Row phaseCenterVariationCorrectionUncertaintyMillimeters[3];
+
+ /**
+ * 2D vectors representing the signal gain corrections at regularly spaced
+ * azimuthal angle (theta) and zenith angle (phi). The values are calculated or
+ * measured at the antenna feed point without considering the radio and receiver
+ * noise figure and path loss contribution, in dBi, i.e., decibel over isotropic
+ * antenna with the same total power. The signal gain correction is added the
+ * signal gain measurement to obtain the corrected value.*/
+ Row signalGainCorrectionDbi[3];
+
+ /**
+ * 2D vectors of 1-sigma uncertainty in dBi associated with the signal
+ * gain correction values.
+ *
+ * This field is optional, i.e., an empty vector.
+ */
+ Row signalGainCorrectionUncertaintyDbi[3];
+} GnssAntennaInfo_ext;
+
+typedef struct {
+ /** The array of GnssAntennaInfo. */
+ GnssAntennaInfo_ext antennaInfos[2];
+} GnssAntennaInfos_ext;
+
+
+typedef void (*gnss_antenna_info_callback) (GnssAntennaInfos_ext* data);
+
+typedef struct {
+ /** set to sizeof(GnssAntennaInfoCallbacks) */
+ size_t size;
+ gnss_antenna_info_callback antenna_info_callback;
+} GnssAntennaInfoCallbacks;
+
+
+typedef struct {
+ /** Set to sizeof(GnssAntennaInfoInterface) */
+ size_t size;
+
+ int (*setCallback) (GnssAntennaInfoCallbacks* callbacks);
+
+ void (*close) ();
+
+} GnssAntennaInfoInterface;
+
+#if defined (__ANDROID_OS__)
+struct gps_device_t_ext {
+ struct hw_device_t common;
+
+ /**
+ * Set the provided lights to the provided values.
+ *
+ * Returns: 0 on succes, error code on failure.
+ */
+ const GpsInterface_ext* (*get_gps_interface)(struct gps_device_t_ext* dev);
+};
+#elif defined (__LINUX_OS__)
+struct gps_device_t_ext {
+ /**
+ * Set the provided lights to the provided values.
+ *
+ * Returns: 0 on succes, error code on failure.
+ */
+ const GpsInterface_ext* (*get_gps_interface)(struct gps_device_t_ext* dev);
+};
+#endif
+
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_MTK_H */
+
diff --git a/src/connectivity/gps/2.0/gps_hal/inc/mtk_lbs_utility.h b/src/connectivity/gps/2.0/gps_hal/inc/mtk_lbs_utility.h
new file mode 100644
index 0000000..7efa194
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/inc/mtk_lbs_utility.h
@@ -0,0 +1,13 @@
+#ifndef __MTK_LBS_UTILITY_H__
+#define __MTK_LBS_UTILITY_H__
+
+#include <time.h>
+#include <stdint.h>
+#ifdef __ANDROID_OS__
+#include <cutils/sockets.h>
+#include <log/log.h> /*logging in logcat*/
+#endif
+#include "mnldinf_common.h"
+#include "mnldinf_utility.h"
+#include "mnldinf_log.h"
+#endif
diff --git a/src/connectivity/gps/2.0/gps_hal/make_gnsshal.sh b/src/connectivity/gps/2.0/gps_hal/make_gnsshal.sh
new file mode 100755
index 0000000..f057150
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/make_gnsshal.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+make clean && make CFLAG=-D__LIBMNL_SIMULATOR__ 2>&1 |tee build.log
diff --git a/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_basic.h b/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_basic.h
new file mode 100644
index 0000000..c172f4d
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_basic.h
@@ -0,0 +1,43 @@
+#ifndef __MNLDINF_BASIC_INTERFACE_H__
+#define __MNLDINF_BASIC_INTERFACE_H__
+
+#include "mnldinf_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MNLDINF_BASIC_TCP "mnldinf_basic"
+
+typedef struct {
+ void (*mnldinf_connection_broken)();
+ void (*mnldinf_location)(gps_location location);
+ void (*mnldinf_gnss_status)(gps_status status);
+ void (*mnldinf_gnss_sv)(gnss_sv_info sv);
+ void (*mnldinf_nmea)(int64_t timestamp, const char* nmea, int length);
+ void (*mnldinf_nmea_done)(void);
+ void (*mnldinf_gnss_measurements)(gnss_data *data);
+
+ void (*mnldinf_capability_update)(mnldinf_basic_server_cap *cap);
+} mnldinf_basic;
+
+int mnldinf_basic_gnss_init(int fd);
+int mnldinf_basic_gnss_start(int fd);
+int mnldinf_basic_gnss_stop(int fd);
+int mnldinf_basic_gnss_cleanup(int fd);
+
+int mnldinf_basic_gnss_measurement_enable(int fd, bool enable);
+
+// -1 means failure
+int mnldinf_basic_cmd_hdlr(int fd, mnldinf_basic* hdlr);
+
+int mnldinf_basic_register(char *client_name);
+
+void mnldinf_basic_capability_config(int fd, mnldinf_basic_client_cap *cap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_common.h b/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_common.h
new file mode 100644
index 0000000..f1bf7f5
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_common.h
@@ -0,0 +1,1781 @@
+#ifndef __MNLDINF_INTERFACE_COMMON_H__
+#define __MNLDINF_INTERFACE_COMMON_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define HAL_MNL_BUFF_SIZE (10 * 1000)
+#define HAL_MNL_BUFF_SIZE_SND (32 * 1000)
+#define HAL_MNL_INTERFACE_VERSION 1
+
+//======================================================
+// Send to MNLD
+//======================================================
+
+typedef enum {
+ HAL2MNL_HAL_REBOOT = 0,
+ HAL2MNL_GPS_INIT = 101,
+ HAL2MNL_GPS_START = 102,
+ HAL2MNL_GPS_STOP = 103,
+ HAL2MNL_GPS_CLEANUP = 104,
+ HAL2MNL_GPS_INJECT_TIME = 105,
+ HAL2MNL_GPS_INJECT_LOCATION = 106,
+ HAL2MNL_GPS_DELETE_AIDING_DATA = 107,
+ HAL2MNL_GPS_SET_POSITION_MODE = 108,
+ HAL2MNL_DATA_CONN_OPEN = 201,
+ HAL2MNL_DATA_CONN_OPEN_WITH_APN_IP_TYPE = 202,
+ HAL2MNL_DATA_CONN_CLOSED = 203,
+ HAL2MNL_DATA_CONN_FAILED = 204,
+ HAL2MNL_SET_SERVER = 301,
+ HAL2MNL_SET_REF_LOCATION = 302,
+ HAL2MNL_SET_ID = 303,
+ HAL2MNL_NI_MESSAGE = 401,
+ HAL2MNL_NI_RESPOND = 402,
+ HAL2MNL_UPDATE_NETWORK_STATE = 501,
+ HAL2MNL_UPDATE_NETWORK_AVAILABILITY = 502,
+ HAL2MNL_GPS_MEASUREMENT = 601,
+ HAL2MNL_GPS_NAVIGATION = 602,
+ HAL2MNL_VZW_DEBUG = 603,
+ HAL2MNL_GNSS_CONFIG = 604,
+ HAL2MNL_SV_BLACKLIST = 605,
+ HAL2MNL_CORRECTION = 606,
+ HAL2MNL_NFW_ACCESS = 607,
+ HAL2MNL_FULL_TRACKING = 701,
+ HAL2MNL_SEND_PMTK = 702,
+ HAL2MNL_EPO_ENABLE = 703,
+ HAL2MNL_SET_TTFF_ACC = 704,
+ HAL2MNL_BASIC_CAP_SYNC = 705,
+ HAL2MNL_EXT_CAP_SYNC = 706,
+} hal2mnl_cmd;
+
+typedef int gps_pos_mode;
+#define GPS_POS_MODE_STANDALONE 0
+#define GPS_POS_MODE_MSB 1
+
+typedef int gps_pos_recurrence;
+#define GPS_POS_RECURRENCE_PERIODIC 0
+#define GPS_POS_RECURRENCE_SINGLE 1
+
+typedef int ni_user_response_type;
+#define NI_USER_RESPONSE_ACCEPT 1
+#define NI_USER_RESPONSE_DENY 2
+#define NI_USER_RESPONSE_NORESP 3
+
+typedef int cell_type;
+#define CELL_TYPE_GSM 1
+#define CELL_TYPE_UMTS 2
+
+typedef int agps_id_type;
+#define AGPS_ID_TYPE_NONE 0
+#define AGPS_ID_TYPE_IMSI 1
+#define AGPS_ID_TYPE_MSISDN 2
+
+typedef int network_type;
+#define NETWORK_TYPE_MOBILE 0
+#define NETWORK_TYPE_WIFI 1
+#define NETWORK_TYPE_MOBILE_MMS 2
+#define NETWORK_TYPE_MOBILE_SUPL 3
+#define NETWORK_TYPE_MOBILE_DUN 4
+#define NETWORK_TYPE_MOBILE_HIPRI 5
+#define NETWORK_TYPE_WIMAX 6
+
+typedef int apn_ip_type;
+#define MTK_APN_IP_INVALID 0
+#define MTK_APN_IP_IPV4 1
+#define MTK_APN_IP_IPV6 2
+#define MTK_APN_IP_IPV4V6 3
+
+typedef int agps_type;
+#define MTK_AGPS_TYPE_SUPL 1
+#define MTK_AGPS_TYPE_C2K 2
+
+typedef int epo_bitmap;
+#define MTK_EPO_CFG_EPO (1U<<0)
+#define MTK_EPO_CFG_QEPO (1U<<1)
+
+typedef int ttff_acc;
+#define MTK_TTFF_ACC_LOW 0
+#define MTK_TTFF_ACC_MID 1
+#define MTK_TTFF_ACC_HIGH 2
+
+typedef int gnss_delete_flag;
+#define MTK_GNSS_DELETE_EPHEMERIS 0x0001
+#define MTK_GNSS_DELETE_ALMANAC 0x0002
+#define MTK_GNSS_DELETE_POSITION 0x0004
+#define MTK_GNSS_DELETE_TIME 0x0008
+#define MTK_GNSS_DELETE_IONO 0x0010
+#define MTK_GNSS_DELETE_UTC 0x0020
+#define MTK_GNSS_DELETE_HEALTH 0x0040
+#define MTK_GNSS_DELETE_SVDIR 0x0080
+#define MTK_GNSS_DELETE_SVSTEER 0x0100
+#define MTK_GNSS_DELETE_SADATA 0x0200
+#define MTK_GNSS_DELETE_RTI 0x0400
+#define MTK_GNSS_DELETE_CLK 0x0800
+#define MTK_GNSS_DELETE_CELLDB_INFO 0x8000
+#define MTK_GNSS_DELETE_ALL 0xFFFF
+
+//======================================================
+// Receive from MNLD
+//======================================================
+
+typedef enum {
+ MNL2HAL_MNLD_REBOOT = 1,
+ MNL2HAL_LOCATION = 101,
+ MNL2HAL_GPS_STATUS = 102,
+ MNL2HAL_GPS_SV = 103,
+ MNL2HAL_NMEA = 104,
+ MNL2HAL_GPS_CAPABILITIES = 105,
+ MNL2HAL_GPS_MEASUREMENTS = 106,
+ MNL2HAL_GPS_NAVIGATION = 107,
+ MNL2HAL_GNSS_MEASUREMENTS = 108,
+ MNL2HAL_GNSS_NAVIGATION = 109,
+ MNL2HAL_REQUEST_WAKELOCK = 201,
+ MNL2HAL_RELEASE_WAKELOCK = 202,
+ MNL2HAL_REQUEST_UTC_TIME = 301,
+ MNL2HAL_REQUEST_DATA_CONN = 302,
+ MNL2HAL_RELEASE_DATA_CONN = 303,
+ MNL2HAL_REQUEST_NI_NOTIFY = 304,
+ MNL2HAL_REQUEST_SET_ID = 305,
+ MNL2HAL_REQUEST_REF_LOC = 306,
+ MNL2HAL_VZW_DEBUG_OUTPUT = 307,
+ MNL2HAL_UPDATE_GNSS_NAME = 308,
+ MNL2HAL_REQUEST_NLP = 309,
+ MNL2HAL_NFW_NOTIFY = 310,
+ MNL2HAL_BASIC_CAP_SYNC = 311,
+ MNL2HAL_EXT_CAP_SYNC = 312,
+ MNL2HAL_NMEA_DONE = 313,
+ MNL2HAL_AGPS_LOCATION = 314,
+} mnl2hal_cmd;
+
+#define MTK_HAL_GNSS_MAX_SVS (32+7+24+63+36+19+14) //195, GPS+QZSS+Glonass+Beidou+Galileo+SBAS+IRNSS_SV
+#define GPS_MAX_MEASUREMENT 32
+#define MTK_HAL_GNSS_MAX_MEASUREMENT (100)
+
+typedef int gps_location_flags;
+#define MTK_GPS_LOCATION_HAS_LAT_LONG 0x0001
+#define MTK_GPS_LOCATION_HAS_ALT 0x0002
+#define MTK_GPS_LOCATION_HAS_SPEED 0x0004
+#define MTK_GPS_LOCATION_HAS_BEARING 0x0008
+#define MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY 0x0010
+#define MTK_GPS_LOCATION_HAS_VERTICAL_ACCURACY 0x0020
+#define MTK_GPS_LOCATION_HAS_SPEED_ACCURACY 0x0040
+#define MTK_GPS_LOCATION_HAS_BEARING_ACCURACY 0x0080
+#define MTK_GPS_LOCATION_HAS_PDOP 0x0100
+#define MTK_GPS_LOCATION_HAS_HDOP 0x0200
+#define MTK_GPS_LOCATION_HAS_VDOP 0x0400
+
+typedef int gps_capabilites;
+#define GPS_CAP_NONE 0x0010000
+#define GPS_CAP_SCHEDULING 0x0000001
+#define GPS_CAP_MSB 0x0000002
+#define GPS_CAP_MSA 0x0000004
+#define GPS_CAP_SINGLE_SHOT 0x0000008
+#define GPS_CAP_ON_DEMAND_TIME 0x0000010
+#define GPS_CAP_GEOFENCING 0x0000020
+#define GPS_CAP_MEASUREMENTS 0x0000040
+#define GPS_CAP_NAV_MESSAGES 0x0000080
+#define GPS_CAP_LOW_POWER_MODE 0x0000100
+#define GPS_CAP_SATELLITE_BLACKLIST 0x0000200
+#define GPS_CAP_CORRECTION 0x0000400
+#define GPS_CAPABILITY_ANTENNA_INFO 0x0000800
+
+typedef int request_setid;
+#define REQUEST_SETID_IMSI (1<<0L)
+#define REQUEST_SETID_MSISDN (1<<1L)
+
+typedef int request_refloc;
+#define REQUEST_REFLOC_CELLID (1<<0L)
+#define REQUEST_REFLOC_MAC (1<<1L) // not ready
+
+typedef short gps_clock_flags;
+#define GPS_CLK_HAS_LEAP_SECOND (1<<0)
+#define GPS_CLK_HAS_TIME_UNCERTAINTY (1<<1)
+#define GPS_CLK_HAS_FULL_BIAS (1<<2)
+#define GPS_CLK_HAS_BIAS (1<<3)
+#define GPS_CLK_HAS_BIAS_UNCERTAINTY (1<<4)
+#define GPS_CLK_HAS_DRIFT (1<<5)
+#define GPS_CLK_HAS_DRIFT_UNCERTAINTY (1<<6)
+
+typedef char gps_clock_type;
+#define GPS_CLOCK_TYPE_UNKNOWN 0
+#define GPS_CLOCK_TYPE_LOCAL_HW_TIME 1
+#define GPS_CLOCK_TYPE_GPS_TIME 2
+
+typedef int gps_measurement_flags;
+#define GPS_MEASUREMENT_HAS_SNR (1<<0)
+#define GPS_MEASUREMENT_HAS_ELEVATION (1<<1)
+#define GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY (1<<2)
+#define GPS_MEASUREMENT_HAS_AZIMUTH (1<<3)
+#define GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY (1<<4)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE (1<<5)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY (1<<6)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE (1<<7)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY (1<<8)
+#define GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9)
+#define GPS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12)
+#define GPS_MEASUREMENT_HAS_BIT_NUMBER (1<<13)
+#define GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT (1<<14)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT (1<<15)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY (1<<16)
+#define GPS_MEASUREMENT_HAS_USED_IN_FIX (1<<17)
+
+typedef short gps_measurement_state;
+#define GPS_MEASUREMENT_STATE_UNKNOWN 0
+#define GPS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define GPS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define GPS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define GPS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+#define GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4)
+
+typedef short gps_accumulated_delta_range_state;
+#define GPS_ADR_STATE_UNKNOWN 0
+#define GPS_ADR_STATE_VALID (1<<0)
+#define GPS_ADR_STATE_RESET (1<<1)
+#define GPS_ADR_STATE_CYCLE_SLIP (1<<2)
+
+typedef char gps_loss_of_lock;
+#define GPS_LOSS_OF_LOCK_UNKNOWN 0
+#define GPS_LOSS_OF_LOCK_OK 1
+#define GPS_LOSS_OF_LOCK_CYCLE_SLIP 2
+
+typedef char gps_multipath_indicator;
+#define GPS_MULTIPATH_INDICATOR_UNKNOWN 0
+#define GPS_MULTIPATH_INDICATOR_DETECTED 1
+#define GPS_MULTIPATH_INDICATOR_NOT_USED 2
+
+typedef char gps_nav_msg_type;
+#define GPS_NAV_MSG_TYPE_UNKNOWN 0
+#define GPS_NAV_MSG_TYPE_L1CA 1
+#define GPS_NAV_MSG_TYPE_L2CNAV 2
+#define GPS_NAV_MSG_TYPE_L5CNAV 3
+#define GPS_NAV_MSG_TYPE_CNAV2 4
+
+typedef short nav_msg_status;
+#define NAV_MSG_STATUS_UNKONW 0
+#define NAV_MSG_STATUS_PARITY_PASSED (1<<0)
+#define NAV_MSG_STATUS_PARITY_REBUILT (1<<1)
+
+typedef int gps_status;
+#define MTK_GPS_STATUS_SESSION_BEGIN 1
+#define MTK_GPS_STATUS_SESSION_END 2
+#define MTK_GPS_STATUS_SESSION_ENGINE_ON 3
+#define MTK_GPS_STATUS_SESSION_ENGINE_OFF 4
+
+typedef int agps_ni_type;
+#define AGPS_NI_TYPE_VOICE 1
+#define AGPS_NI_TYPE_UMTS_SUPL 2
+#define AGPS_NI_TYPE_UMTS_CTRL_PLANE 3
+#define AGPS_NI_TYPE_EMERGENCY_SUPL 4
+
+typedef int agps_notify_type;
+#define AGPS_NOTIFY_TYPE_NONE 0
+#define AGPS_NOTIFY_TYPE_NOTIFY_ONLY 1
+#define AGPS_NOTIFY_TYPE_NOTIFY_ALLOW_NO_ANSWER 2
+#define AGPS_NOTIFY_TYPE_NOTIFY_DENY_NO_ANSWER 3
+#define AGPS_NOTIFY_TYPE_PRIVACY 4
+
+typedef int ni_encoding_type;
+#define NI_ENCODING_TYPE_NONE 0
+#define NI_ENCODING_TYPE_GSM7 1
+#define NI_ENCODING_TYPE_UTF8 2
+#define NI_ENCODING_TYPE_UCS2 3
+
+/**
+ * Flags that indicate information about the satellite
+ */
+typedef uint8_t gnss_sv_flags;
+#define MTK_GNSS_SV_FLAGS_NONE 0
+#define MTK_GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA (1 << 0)
+#define MTK_GNSS_SV_FLAGS_HAS_ALMANAC_DATA (1 << 1)
+#define MTK_GNSS_SV_FLAGS_USED_IN_FIX (1 << 2)
+
+typedef unsigned int loc_type;
+#define MTK_LOC_TYPE_AGPS_AFLT 0 // From C2K AFLT flow
+#define MTK_LOC_TYPE_AGPS_CDMA_CELL 1 // From C2K Cell
+#define MTK_LOC_TYPE_AGPS_MOLR_BEGIN_RSP 2 // For CP MOLR after UE provides MSA result, the network will send CISS_FACILITY to provide UE a MSA location. Refer to 3GPP TS37.571-2 7.2.2.2
+#define MTK_LOC_TYPE_AGPS_SUPL_END 3 // From the SUPL END in a supl session. It may be the result of MSA, E-CID, OTDOA, or their hybrid.
+#define MTK_LOC_TYPE_AGPS_SUPL_REF_LOC 4 // For Reference Location assistance data in SUPL flow (equivalent to PMTK713 in SUPL flow)
+#define MTK_LOC_TYPE_AGPS_CP_REF_LOC 5 // For Reference Location assistance data in CP AGPS flow (equivalent to PMTK713 in CP AGPS flow)
+#define MTK_LOC_TYPE_GNSS_STANDALONE 0xfe // GNSS Standalone
+#define MTK_LOC_TYPE_GNSS_UNKNOWN 0xff // Unknown
+
+typedef struct {
+ gps_location_flags flags;
+ double lat;
+ double lng;
+ double alt;
+ float speed;
+ float bearing;
+ float h_accuracy; //horizontal
+ float v_accuracy; //vertical
+ float s_accuracy; //spedd
+ float b_accuracy; //bearing
+ int64_t timestamp;
+ float pdop;
+ float hdop;
+ float vdop;
+ loc_type type;
+} gps_location;
+
+typedef struct {
+ int16_t svid;
+ uint8_t constellation;
+ float c_n0_dbhz;
+ float elevation;
+ float azimuth;
+ gnss_sv_flags flags;
+ float carrier_frequency; //Hz
+ double basebandCN0DbHz;
+} gnss_sv;
+
+typedef struct {
+ int num_svs;
+ gnss_sv sv_list[MTK_HAL_GNSS_MAX_SVS];
+} gnss_sv_info;
+
+typedef struct {
+ int prn;
+ bool has_ephemeris_data;
+ bool has_almanac_data;
+ bool used_in_fix;
+} NmeaCash;
+
+typedef uint16_t mtk_hal_navigation_message_status;
+#define MTK_NAV_MESSAGE_STATUS_UNKNOWN 0
+#define MTK_NAV_MESSAGE_STATUS_PARITY_PASSED (1<<0)
+#define MTK_NAV_MESSAGE_STATUS_PARITY_REBUILT (1<<1)
+
+typedef int16_t mtk_hal_gnss_navigation_message_type;
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN 0
+/** GPS L1 C/A message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA 0x0101
+/** GPS L2-CNAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV 0x0102
+/** GPS L5-CNAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV 0x0103
+/** GPS CNAV-2 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2 0x0104
+/** Glonass L1 CA message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA 0x0301
+/** Beidou D1 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1 0x0501
+/** Beidou D2 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2 0x0502
+/** Galileo I/NAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I 0x0601
+/** Galileo F/NAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F 0x0602
+
+typedef uint8_t mtk_hal_gnss_multipath_indicator;
+/** The indicator is not available or unknown. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_UNKNOWN 0
+/** The measurement is indicated to be affected by multipath. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_PRESENT 1
+/** The measurement is indicated to be not affected by multipath. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_NOT_PRESENT 2
+
+typedef uint16_t mtk_hal_gnss_accumulated_delta_range_state;
+#define MTK_GNSS_ADR_STATE_UNKNOWN 0
+#define MTK_GNSS_ADR_STATE_VALID (1<<0)
+#define MTK_GNSS_ADR_STATE_RESET (1<<1)
+#define MTK_GNSS_ADR_STATE_CYCLE_SLIP (1<<2)
+
+typedef uint32_t mtk_hal_gnss_measurement_state;
+#define MTK_GNSS_MEASUREMENT_STATE_UNKNOWN 0
+#define MTK_GNSS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define MTK_GNSS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define MTK_GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define MTK_GNSS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+#define MTK_GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4)
+#define MTK_GNSS_MEASUREMENT_STATE_SYMBOL_SYNC (1<<5)
+#define MTK_GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC (1<<6)
+#define MTK_GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED (1<<7)
+#define MTK_GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC (1<<8)
+#define MTK_GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC (1<<9)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK (1<<10)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK (1<<11)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC (1<<12)
+#define MTK_GNSS_MEASUREMENT_STATE_SBAS_SYNC (1<<13)
+
+typedef uint8_t mtk_hal_gnss_constellation_type;
+#define MTK_GNSS_CONSTELLATION_UNKNOWN 0
+#define MTK_GNSS_CONSTELLATION_GPS 1
+#define MTK_GNSS_CONSTELLATION_SBAS 2
+#define MTK_GNSS_CONSTELLATION_GLONASS 3
+#define MTK_GNSS_CONSTELLATION_QZSS 4
+#define MTK_GNSS_CONSTELLATION_BEIDOU 5
+#define MTK_GNSS_CONSTELLATION_GALILEO 6
+#define MTK_GNSS_CONSTELLATION_IRNSS 7
+
+typedef uint32_t mtk_hal_gnss_measurement_flags;
+/** A valid 'snr' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_SNR (1<<0)
+/** A valid 'carrier frequency' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9)
+/** A valid 'carrier cycles' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10)
+/** A valid 'carrier phase' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11)
+/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12)
+
+typedef uint16_t mtk_hal_gnss_clock_flags;
+/** A valid 'leap second' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_LEAP_SECOND (1<<0)
+/** A valid 'time uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_TIME_UNCERTAINTY (1<<1)
+/** A valid 'full bias' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_FULL_BIAS (1<<2)
+/** A valid 'bias' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_BIAS (1<<3)
+/** A valid 'bias uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_BIAS_UNCERTAINTY (1<<4)
+/** A valid 'drift' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_DRIFT (1<<5)
+/** A valid 'drift uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY (1<<6)
+
+typedef struct {
+ /** A set of flags indicating the validity of the fields in this data structure. */
+ gps_clock_flags flags;
+
+ /**
+ * Leap second data.
+ * The sign of the value is defined by the following equation:
+ * utc_time_ns = time_ns + (full_bias_ns + bias_ns) - leap_second * 1,000,000,000
+ *
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_LEAP_SECOND.
+ */
+ short leap_second;
+
+ /**
+ * Indicates the type of time reported by the 'time_ns' field.
+ */
+ gps_clock_type type;
+
+ /**
+ * The GPS receiver internal clock value. This can be either the local hardware clock value
+ * (GPS_CLOCK_TYPE_LOCAL_HW_TIME), or the current GPS time derived inside GPS receiver
+ * (GPS_CLOCK_TYPE_GPS_TIME). The field 'type' defines the time reported.
+ *
+ * For local hardware clock, this value is expected to be monotonically increasing during
+ * the reporting session. The real GPS time can be derived by compensating the 'full bias'
+ * (when it is available) from this value.
+ *
+ * For GPS time, this value is expected to be the best estimation of current GPS time that GPS
+ * receiver can achieve. Set the 'time uncertainty' appropriately when GPS time is specified.
+ *
+ * Sub-nanosecond accuracy can be provided by means of the 'bias' field.
+ * The value contains the 'time uncertainty' in it.
+ */
+ int64_t time_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * This value should be set if GPS_CLOCK_TYPE_GPS_TIME is set.
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_TIME_UNCERTAINTY.
+ */
+ double time_uncertainty_ns;
+
+ /**
+ * The difference between hardware clock ('time' field) inside GPS receiver and the true GPS
+ * time since 0000Z, January 6, 1980, in nanoseconds.
+ * This value is used if and only if GPS_CLOCK_TYPE_LOCAL_HW_TIME is set, and GPS receiver
+ * has solved the clock for GPS time.
+ * The caller is responsible for using the 'bias uncertainty' field for quality check.
+ *
+ * The sign of the value is defined by the following equation:
+ * true time (GPS time) = time_ns + (full_bias_ns + bias_ns)
+ *
+ * This value contains the 'bias uncertainty' in it.
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_FULL_BIAS.
+
+ */
+ int64_t full_bias_ns;
+
+ /**
+ * Sub-nanosecond bias.
+ * The value contains the 'bias uncertainty' in it.
+ *
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_BIAS.
+ */
+ double bias_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's bias in nanoseconds.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_BIAS_UNCERTAINTY.
+ */
+ double bias_uncertainty_ns;
+
+ /**
+ * The clock's drift in nanoseconds (per second).
+ * A positive value means that the frequency is higher than the nominal frequency.
+ *
+ * The value contains the 'drift uncertainty' in it.
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_DRIFT.
+ *
+ * If GpsMeasurement's 'flags' field contains GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE,
+ * it is encouraged that this field is also provided.
+ */
+ double drift_nsps;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_DRIFT_UNCERTAINTY.
+ */
+ double drift_uncertainty_nsps;
+} gps_clock;
+
+typedef struct {
+ mtk_hal_gnss_constellation_type constellation;
+ double carrierFrequencyHz;
+ uint8_t codeType[8];
+}MTK_GnssSignalType;
+/**
+ * Represents an estimate of the GPS clock time.
+ */
+typedef struct {
+ /**
+ * A set of flags indicating the validity of the fields in this data
+ * structure.
+ */
+ mtk_hal_gnss_clock_flags flags;
+
+ /**
+ * Leap second data.
+ * The sign of the value is defined by the following equation:
+ * utc_time_ns = time_ns - (full_bias_ns + bias_ns) - leap_second *
+ * 1,000,000,000
+ *
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_LEAP_SECOND.
+ */
+ int16_t leap_second;
+
+ /**
+ * The GNSS receiver internal clock value. This is the local hardware clock
+ * value.
+ *
+ * For local hardware clock, this value is expected to be monotonically
+ * increasing while the hardware clock remains power on. (For the case of a
+ * HW clock that is not continuously on, see the
+ * hw_clock_discontinuity_count field). The receiver's estimate of GPS time
+ * can be derived by substracting the sum of full_bias_ns and bias_ns (when
+ * available) from this value.
+ *
+ * This GPS time is expected to be the best estimate of current GPS time
+ * that GNSS receiver can achieve.
+ *
+ * Sub-nanosecond accuracy can be provided by means of the 'bias_ns' field.
+ * The value contains the 'time uncertainty' in it.
+ *
+ * This field is mandatory.
+ */
+ int64_t time_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_CLOCK_HAS_TIME_UNCERTAINTY. This value is effectively zero (it is
+ * the reference local clock, by which all other times and time
+ * uncertainties are measured.) (And thus this field can be not provided,
+ * per GNSS_CLOCK_HAS_TIME_UNCERTAINTY flag, or provided & set to 0.)
+ */
+ double time_uncertainty_ns;
+
+ /**
+ * The difference between hardware clock ('time' field) inside GPS receiver
+ * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
+ *
+ * The sign of the value is defined by the following equation:
+ * local estimate of GPS time = time_ns - (full_bias_ns + bias_ns)
+ *
+ * This value is mandatory if the receiver has estimated GPS time. If the
+ * computed time is for a non-GPS constellation, the time offset of that
+ * constellation to GPS has to be applied to fill this value. The error
+ * estimate for the sum of this and the bias_ns is the bias_uncertainty_ns,
+ * and the caller is responsible for using this uncertainty (it can be very
+ * large before the GPS time has been solved for.) If the data is available
+ * 'flags' must contain GNSS_CLOCK_HAS_FULL_BIAS.
+ */
+ int64_t full_bias_ns;
+
+ /**
+ * Sub-nanosecond bias.
+ * The error estimate for the sum of this and the full_bias_ns is the
+ * bias_uncertainty_ns
+ *
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_BIAS. If GPS
+ * has computed a position fix. This value is mandatory if the receiver has
+ * estimated GPS time.
+ */
+ double bias_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the local estimate of GPS time (clock
+ * bias) in nanoseconds. The uncertainty is represented as an absolute
+ * (single sided) value.
+ *
+ * If the data is available 'flags' must contain
+ * GNSS_CLOCK_HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+ * has estimated GPS time.
+ */
+ double bias_uncertainty_ns;
+
+ /**
+ * The clock's drift in nanoseconds (per second).
+ *
+ * A positive value means that the frequency is higher than the nominal
+ * frequency, and that the (full_bias_ns + bias_ns) is growing more positive
+ * over time.
+ *
+ * The value contains the 'drift uncertainty' in it.
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_DRIFT.
+ *
+ * This value is mandatory if the receiver has estimated GNSS time
+ */
+ double drift_nsps;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available 'flags' must contain
+ * GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY. If GPS has computed a position fix this
+ * field is mandatory and must be populated.
+ */
+ double drift_uncertainty_nsps;
+
+ /**
+ * When there are any discontinuities in the HW clock, this field is
+ * mandatory.
+ *
+ * A "discontinuity" is meant to cover the case of a switch from one source
+ * of clock to another. A single free-running crystal oscillator (XO)
+ * should generally not have any discontinuities, and this can be set and
+ * left at 0.
+ *
+ * If, however, the time_ns value (HW clock) is derived from a composite of
+ * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+ * restarted, then this value shall be incremented each time a discontinuity
+ * occurs. (E.g. this value may start at zero at device boot-up and
+ * increment each time there is a change in clock continuity. In the
+ * unlikely event that this value reaches full scale, rollover (not
+ * clamping) is required, such that this value continues to change, during
+ * subsequent discontinuity events.)
+ *
+ * While this number stays the same, between GnssClock reports, it can be
+ * safely assumed that the time_ns value has been running continuously, e.g.
+ * derived from a single, high quality clock (XO like, or better, that's
+ * typically used during continuous GNSS signal sampling.)
+ *
+ * It is expected, esp. during periods where there are few GNSS signals
+ * available, that the HW clock be discontinuity-free as long as possible,
+ * as this avoids the need to use (waste) a GNSS measurement to fully
+ * re-solve for the GPS clock bias and drift, when using the accompanying
+ * measurements, from consecutive GnssData reports.
+ */
+ uint32_t hw_clock_discontinuity_count;
+ MTK_GnssSignalType referenceSignalTypeForIsb;
+} gnss_clock;
+
+typedef struct {
+ /** A set of flags indicating the validity of the fields in this data structure. */
+ gps_measurement_flags flags;
+
+ /**
+ * Pseudo-random number in the range of [1, 32]
+ * This is a Mandatory value.
+ */
+ int8_t prn;
+
+ /**
+ * Time offset at which the measurement was taken in nanoseconds.
+ * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+ * interpreted in the same way as indicated by GpsClock::type.
+ *
+ * The sign of time_offset_ns is given by the following equation:
+ * measurement time = GpsClock::time_ns + time_offset_ns
+ *
+ * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+ * This is a Mandatory value.
+ */
+ double time_offset_ns;
+
+ /**
+ * Per satellite sync state. It represents the current sync state for the associated satellite.
+ * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+ * This is a Mandatory value.
+ */
+ gps_measurement_state state;
+
+ /**
+ * Received GPS Time-of-Week at the measurement time, in nanoseconds.
+ * The value is relative to the beginning of the current GPS week.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : GPS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : GPS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync : [ 0 20ms ] : GPS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe sync : [ 0 6s ] : GPS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * TOW decoded : [ 0 1week ] : GPS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * However, if there is any ambiguity in integer millisecond,
+ * GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+ * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+ */
+ int64_t received_gps_tow_ns;
+
+ /**
+ * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+ * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+ */
+ int64_t received_gps_tow_uncertainty_ns;
+
+ /**
+ * Carrier-to-noise density in dB-Hz, in the range [0, 63].
+ * It contains the measured C/N0 value for the signal at the antenna input.
+ * This is a Mandatory value.
+ */
+ double c_n0_dbhz;
+
+ /**
+ * Pseudorange rate at the timestamp in m/s.
+ * The value also includes the effects of the receiver clock frequency and satellite clock
+ * frequency errors.
+ *
+ * The value includes the 'pseudorange rate uncertainty' in it.
+ * A positive value indicates that the pseudorange is getting larger.
+ * This is a Mandatory value.
+ */
+ double pseudorange_rate_mps;
+
+ /**
+ * 1-Sigma uncertainty of the pseudurange rate in m/s.
+ * The uncertainty is represented as an absolute (single sided) value.
+ * This is a Mandatory value.
+ */
+ double pseudorange_rate_uncertainty_mps;
+
+ /**
+ * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+ * (indicating loss of lock).
+ * This is a Mandatory value.
+ */
+ gps_accumulated_delta_range_state accumulated_delta_range_state;
+
+ /**
+ * Accumulated delta range since the last channel reset in meters.
+ * A positive value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+ * is given by the equation:
+ * accumulated delta range = -k * carrier phase (where k is a constant)
+ *
+ * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ * However, it is expected that the data is only accurate when:
+ * 'accumulated delta range state' == GPS_ADR_STATE_VALID.
+ */
+ double accumulated_delta_range_m;
+
+ /**
+ * 1-Sigma uncertainty of the accumulated delta range in meters.
+ * The data is available if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ */
+ double accumulated_delta_range_uncertainty_m;
+
+ /**
+ * Best derived Pseudorange by the chip-set, in meters.
+ * The value contains the 'pseudorange uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_PSEUDORANGE.
+ */
+ double pseudorange_m;
+
+ /**
+ * 1-Sigma uncertainty of the pseudorange in meters.
+ * The value contains the 'pseudorange' and 'clock' uncertainty in it.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY.
+ */
+ double pseudorange_uncertainty_m;
+
+ /**
+ * A fraction of the current C/A code cycle, in the range [0.0, 1023.0]
+ * This value contains the time (in Chip units) since the last C/A code cycle (GPS Msec epoch).
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'code-phase uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CODE_PHASE.
+ */
+ double code_phase_chips;
+
+ /**
+ * 1-Sigma uncertainty of the code-phase, in a fraction of chips.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY.
+ */
+ double code_phase_uncertainty_chips;
+
+ /**
+ * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+ * If the field is not set, the carrier frequency is assumed to be L1.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+ */
+ float carrier_frequency_hz;
+
+ /**
+ * The number of full carrier cycles between the satellite and the receiver.
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_CYCLES.
+ */
+ int64_t carrier_cycles;
+
+ /**
+ * The RF phase detected by the receiver, in the range [0.0, 1.0].
+ * This is usually the fractional part of the complete carrier phase measurement.
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'carrier-phase uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_PHASE.
+ */
+ double carrier_phase;
+
+ /**
+ * 1-Sigma uncertainty of the carrier-phase.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+ */
+ double carrier_phase_uncertainty;
+
+ /**
+ * An enumeration that indicates the 'loss of lock' state of the event.
+ */
+ gps_loss_of_lock loss_of_lock;
+
+ /**
+ * The number of GPS bits transmitted since Sat-Sun midnight (GPS week).
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_BIT_NUMBER.
+ */
+ int32_t bit_number;
+
+ /**
+ * The elapsed time since the last received bit in milliseconds, in the range [0, 20]
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT.
+ */
+ int16_t time_from_last_bit_ms;
+
+ /**
+ * Doppler shift in Hz.
+ * A positive value indicates that the SV is moving toward the receiver.
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'doppler shift uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_DOPPLER_SHIFT.
+ */
+ double doppler_shift_hz;
+
+ /**
+ * 1-Sigma uncertainty of the doppler shift in Hz.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY.
+ */
+ double doppler_shift_uncertainty_hz;
+
+ /**
+ * An enumeration that indicates the 'multipath' state of the event.
+ */
+ gps_multipath_indicator multipath_indicator;
+
+ /**
+ * Signal-to-noise ratio in dB.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_SNR.
+ */
+ double snr_db;
+
+ /**
+ * Elevation in degrees, the valid range is [-90, 90].
+ * The value contains the 'elevation uncertainty' in it.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_ELEVATION.
+ */
+ double elevation_deg;
+
+ /**
+ * 1-Sigma uncertainty of the elevation in degrees, the valid range is [0, 90].
+ * The uncertainty is represented as the absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY.
+ */
+ double elevation_uncertainty_deg;
+
+ /**
+ * Azimuth in degrees, in the range [0, 360).
+ * The value contains the 'azimuth uncertainty' in it.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_AZIMUTH.
+ * */
+ double azimuth_deg;
+
+ /**
+ * 1-Sigma uncertainty of the azimuth in degrees, the valid range is [0, 180].
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY.
+ */
+ double azimuth_uncertainty_deg;
+
+ /**
+ * Whether the GPS represented by the measurement was used for computing the most recent fix.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_USED_IN_FIX.
+ */
+ bool used_in_fix;
+} gps_measurement;
+
+/**
+ * Represents a GNSS Measurement, it contains raw and computed information.
+ *
+ * Independence - All signal measurement information (e.g. sv_time,
+ * pseudorange_rate, multipath_indicator) reported in this struct should be
+ * based on GNSS signal measurements only. You may not synthesize measurements
+ * by calculating or reporting expected measurements based on known or estimated
+ * position, velocity, or time.
+ */
+typedef struct {
+ /** A set of flags indicating the validity of the fields in this data structure. */
+ mtk_hal_gnss_measurement_flags flags;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ * This is a mandatory value.
+ */
+ int16_t svid;
+
+ /**
+ * Defines the constellation of the given SV. Value should be one of those
+ * GNSS_CONSTELLATION_* constants
+ */
+ mtk_hal_gnss_constellation_type constellation;
+
+ /**
+ * Time offset at which the measurement was taken in nanoseconds.
+ * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+ * interpreted in the same way as indicated by GpsClock::type.
+ *
+ * The sign of time_offset_ns is given by the following equation:
+ * measurement time = GpsClock::time_ns + time_offset_ns
+ *
+ * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+ * This is a mandatory value.
+ */
+ double time_offset_ns;
+
+ /**
+ * Per satellite sync state. It represents the current sync state for the associated satellite.
+ * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+ *
+ * This is a mandatory value.
+ */
+ mtk_hal_gnss_measurement_state state;
+
+ /**
+ * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+ * Ensure that this field is independent (see comment at top of
+ * GnssMeasurement struct.)
+ *
+ * For GPS & QZSS, this is:
+ * Received GPS Time-of-Week at the measurement time, in nanoseconds.
+ * The value is relative to the beginning of the current GPS week.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range
+ * for this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync : [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe sync : [ 0 6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * TOW decoded : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * Note well: if there is any ambiguity in integer millisecond,
+ * GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+ *
+ * This value must be populated if 'state' != GNSS_MEASUREMENT_STATE_UNKNOWN.
+ *
+ * For Glonass, this is:
+ * Received Glonass time of day, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 10ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+ * Bit sync : [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * String sync : [ 0 2s ] : GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC is set
+ * Time of day : [ 0 1day ] : GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED is set
+ *
+ * For Beidou, this is:
+ * Received Beidou time of week, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync (D2): [ 0 2ms ] : GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC is set
+ * Bit sync (D1): [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe (D2): [ 0 0.6s ] : GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC is set
+ * Subframe (D1): [ 0 6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * Time of week : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * For Galileo, this is:
+ * Received Galileo time of week, at the measurement time in nanoseconds.
+ *
+ * E1BC code lock : [ 0 4ms ] : GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK is set
+ * E1C 2nd code lock: [ 0 100ms ] :
+ * GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is set
+ *
+ * E1B page : [ 0 2s ] : GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC is set
+ * Time of week: [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * For SBAS, this is:
+ * Received SBAS time, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite,
+ * valid range for this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 2ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+ * Message : [ 0 1s ] : GNSS_MEASUREMENT_STATE_SBAS_SYNC is set
+ */
+ int64_t received_sv_time_in_ns;
+
+ /**
+ * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+ *
+ * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+ */
+ int64_t received_sv_time_uncertainty_in_ns;
+
+ /**
+ * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+ * It contains the measured C/N0 value for the signal at the antenna port.
+ *
+ * This is a mandatory value.
+ */
+ double c_n0_dbhz;
+
+ /**
+ * Pseudorange rate at the timestamp in m/s. The correction of a given
+ * Pseudorange Rate value includes corrections for receiver and satellite
+ * clock frequency errors. Ensure that this field is independent (see
+ * comment at top of GnssMeasurement struct.)
+ *
+ * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
+ * 'drift' field as well (When providing the uncorrected pseudorange rate, do not apply the
+ * corrections described above.)
+ *
+ * The value includes the 'pseudorange rate uncertainty' in it.
+ * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler
+ * shift' is given by the equation:
+ * pseudorange rate = -k * doppler shift (where k is a constant)
+ *
+ * This should be the most accurate pseudorange rate available, based on
+ * fresh signal measurements from this channel.
+ *
+ * It is mandatory that this value be provided at typical carrier phase PRR
+ * quality (few cm/sec per second of uncertainty, or better) - when signals
+ * are sufficiently strong & stable, e.g. signals from a GPS simulator at >=
+ * 35 dB-Hz.
+ */
+ double pseudorange_rate_mps;
+
+ /**
+ * 1-Sigma uncertainty of the pseudorange_rate_mps.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * This is a mandatory value.
+ */
+ double pseudorange_rate_uncertainty_mps;
+
+ /**
+ * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+ * (indicating loss of lock).
+ *
+ * This is a mandatory value.
+ */
+ mtk_hal_gnss_accumulated_delta_range_state accumulated_delta_range_state;
+
+ /**
+ * Accumulated delta range since the last channel reset in meters.
+ * A positive value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+ * is given by the equation:
+ * accumulated delta range = -k * carrier phase (where k is a constant)
+ *
+ * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ * However, it is expected that the data is only accurate when:
+ * 'accumulated delta range state' == GPS_ADR_STATE_VALID.
+ */
+ double accumulated_delta_range_m;
+
+ /**
+ * 1-Sigma uncertainty of the accumulated delta range in meters.
+ * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ */
+ double accumulated_delta_range_uncertainty_m;
+
+ /**
+ * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+ * If the field is not set, the carrier frequency is assumed to be L1.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+ */
+ float carrier_frequency_hz;
+
+ /**
+ * The number of full carrier cycles between the satellite and the receiver.
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * Indications of possible cycle slips and resets in the accumulation of
+ * this value can be inferred from the accumulated_delta_range_state flags.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
+ */
+ int64_t carrier_cycles;
+
+ /**
+ * The RF phase detected by the receiver, in the range [0.0, 1.0].
+ * This is usually the fractional part of the complete carrier phase measurement.
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'carrier-phase uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_PHASE.
+ */
+ double carrier_phase;
+
+ /**
+ * 1-Sigma uncertainty of the carrier-phase.
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+ */
+ double carrier_phase_uncertainty;
+
+ /**
+ * An enumeration that indicates the 'multipath' state of the event.
+ *
+ * The multipath Indicator is intended to report the presence of overlapping
+ * signals that manifest as distorted correlation peaks.
+ *
+ * - if there is a distorted correlation peak shape, report that multipath
+ * is GNSS_MULTIPATH_INDICATOR_PRESENT.
+ * - if there is not a distorted correlation peak shape, report
+ * GNSS_MULTIPATH_INDICATOR_NOT_PRESENT
+ * - if signals are too weak to discern this information, report
+ * GNSS_MULTIPATH_INDICATOR_UNKNOWN
+ *
+ * Example: when doing the standardized overlapping Multipath Performance
+ * test (3GPP TS 34.171) the Multipath indicator should report
+ * GNSS_MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+ * contain multipath, and GNSS_MULTIPATH_INDICATOR_NOT_PRESENT for those
+ * signals that are tracked and do not contain multipath.
+ */
+ mtk_hal_gnss_multipath_indicator multipath_indicator;
+
+ /**
+ * Signal-to-noise ratio at correlator output in dB.
+ * If the data is available, 'flags' must contain GNSS_MEASUREMENT_HAS_SNR.
+ * This is the power ratio of the "correlation peak height above the
+ * observed noise floor" to "the noise RMS".
+ */
+ double snr_db;
+ /**
+ * The full inter-signal bias (ISB) in nanoseconds.
+ *
+ * This value is the sum of the estimated receiver-side and the space-segment-side
+ * inter-system bias, inter-frequency bias and inter-code bias, including
+ *
+ * - Receiver inter-constellation bias (with respect to the constellation in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Receiver inter-frequency bias (with respect to the carrier frequency in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Receiver inter-code bias (with respect to the code type in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPS-UTC Time Offset
+ * (TauGps), BDS-GLO Time Offset (BGTO)) (with respect to the constellation in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Group delay (e.g., Total Group Delay (TGD))
+ * - Satellite inter-frequency bias (GLO only) (with respect to the carrier frequency in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Satellite inter-code bias (e.g., Differential Code Bias (DCB)) (with respect to the
+ * code type in GnssClock.referenceSignalTypeForIsb)
+ *
+ * If a component of the above is already compensated in the provided
+ * GnssMeasurement.receivedSvTimeInNs, then it must not be included in the reported full
+ * ISB.
+ *
+ * The value does not include the inter-frequency Ionospheric bias.
+ *
+ * The full ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
+ */
+ double fullInterSignalBiasNs;
+ /**
+ * 1-sigma uncertainty associated with the full inter-signal bias in nanoseconds.
+ */
+ double fullInterSignalBiasUncertaintyNs;
+ /**
+ * The satellite inter-signal bias in nanoseconds.
+ *
+ * This value is the satellite-and-control-segment-side inter-system (different from the
+ * constellation in GnssClock.referenceSignalTypeForIsb) bias and inter-frequency (different
+ * from the carrier frequency in GnssClock.referenceSignalTypeForIsb) bias, including:
+ *
+ * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPT-UTC Time Offset (TauGps),
+ * BDS-GLO Time Offset (BGTO))
+ * - Group delay (e.g., Total Group Delay (TGD))
+ * - Satellite inter-signal bias, which includes satellite inter-frequency bias (GLO only),
+ * and satellite inter-code bias (e.g., Differential Code Bias (DCB)).
+ *
+ * The receiver ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
+ */
+ double satelliteInterSignalBiasNs;
+ /**
+ * 1-sigma uncertainty associated with the satellite inter-signal bias in nanoseconds.
+ */
+ double satelliteInterSignalBiasUncertaintyNs;
+ /**
+ * Baseband Carrier-to-noise density in dB-Hz, typically in the range [0, 63]. It contains
+ * the measured C/N0 value for the signal measured at the baseband.
+ *
+ * This is typically a few dB weaker than the value estimated for C/N0 at the antenna port,
+ * which is reported in cN0DbHz.
+ *
+ * If a signal has separate components (e.g. Pilot and Data channels) and the receiver only
+ * processes one of the components, then the reported basebandCN0DbHz reflects only the
+ * component that is processed.
+ *
+ * This value is mandatory.
+ */
+ double basebandCN0DbHz;
+
+ /**
+ * Automatic gain control (AGC) level. AGC acts as a variable gain
+ * amplifier adjusting the power of the incoming signal. The AGC level
+ * may be used to indicate potential interference. When AGC is at a
+ * nominal level, this value must be set as 0. Higher gain (and/or lower
+ * input power) must be output as a positive number. Hence in cases of
+ * strong jamming, in the band of this signal, this value must go more
+ * negative.
+ */
+ double agc_level_db;
+
+ /// v2.0
+ char code_type[8];
+} gnss_measurement;
+
+typedef struct {
+ /** Number of measurements. */
+ size_t measurement_count;
+
+ /** The array of measurements. */
+ gps_measurement measurements[GPS_MAX_MEASUREMENT];
+
+ /** The GPS clock time reading. */
+ gps_clock clock;
+} gps_data;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+ /** Number of measurements. */
+ size_t measurement_count;
+
+ /** The array of measurements. */
+ gnss_measurement measurements[MTK_HAL_GNSS_MAX_MEASUREMENT];
+
+ /** The GPS clock time reading. */
+ gnss_clock clock;
+} gnss_data;
+
+#define MAX_NAV_DATA_LEN 40
+
+typedef struct {
+ /**
+ * Pseudo-random number in the range of [1, 32]
+ * This is a Mandatory value.
+ */
+ int8_t prn;
+
+ /**
+ * The type of message contained in the structure.
+ * This is a Mandatory value.
+ */
+ gps_nav_msg_type type;
+
+ /**
+ * The status of the received navigation message.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+ nav_msg_status status;
+
+ /**
+ * Message identifier.
+ * It provides an index so the complete Navigation Message can be assembled. i.e. fo L1 C/A
+ * subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message.
+ * Subframe 1, 2, 3 does not contain a 'frame id' and this value can be set to -1.
+ */
+ short message_id;
+
+ /**
+ * Sub-message identifier.
+ * If required by the message 'type', this value contains a sub-index within the current
+ * message (or frame) that is being transmitted.
+ * i.e. for L1 C/A the submessage id corresponds to the sub-frame id of the navigation message.
+ */
+ short submessage_id;
+
+ /**
+ * The length of the data (in bytes) contained in the current message.
+ * If this value is different from zero, 'data' must point to an array of the same size.
+ * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+ * This is a Mandatory value.
+ */
+ size_t data_length;
+
+ /**
+ * The data of the reported GPS message.
+ * The bytes (or words) specified using big endian format (MSB first).
+ *
+ * For L1 C/A, each subframe contains 10 30-bit GPS words. Each GPS word (30 bits) should be
+ * fitted into the last 30 bits in a 4-byte word (skip B31 and B32), with MSB first.
+ */
+ char data[MAX_NAV_DATA_LEN];
+} gps_nav_msg;
+
+/** Represents a GPS navigation message (or a fragment of it). */
+typedef struct {
+ /** set to sizeof(GnssNavigationMessage) */
+ size_t size;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ * This is a mandatory value.
+ */
+ int16_t svid;
+
+ /**
+ * The type of message contained in the structure.
+ * This is a mandatory value.
+ */
+ mtk_hal_gnss_navigation_message_type type;
+
+ /**
+ * The status of the received navigation message.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+ mtk_hal_navigation_message_status status;
+
+ /**
+ * Message identifier. It provides an index so the complete Navigation
+ * Message can be assembled.
+ *
+ * - For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+ * id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+ * does not contain a 'frame id' and this value can be set to -1.)
+ *
+ * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+ *
+ * - For BeiDou D1, this refers to the frame number in the range of 1-24
+ *
+ * - For Beidou D2, this refers to the frame number, in the range of 1-120
+ *
+ * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+ * number, in the range of 1-12
+ *
+ * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+ * number in the range of 1-24
+ */
+ int16_t message_id;
+
+ /**
+ * Sub-message identifier. If required by the message 'type', this value
+ * contains a sub-index within the current message (or frame) that is being
+ * transmitted.
+ *
+ * - For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to
+ * the subframe number of the navigation message, in the range of 1-5.
+ *
+ * - For Glonass L1 C/A, this refers to the String number, in the range from
+ * 1-15
+ *
+ * - For Galileo F/NAV, this refers to the page type in the range 1-6
+ *
+ * - For Galileo I/NAV, this refers to the word type in the range 1-10+
+ */
+ int16_t submessage_id;
+
+ /**
+ * The length of the data (in bytes) contained in the current message.
+ * If this value is different from zero, 'data' must point to an array of the same size.
+ * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+ *
+ * This is a mandatory value.
+ */
+ size_t data_length;
+
+ /**
+ * The data of the reported GPS message. The bytes (or words) specified
+ * using big endian format (MSB first).
+ *
+ * - For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+ * words. Each word (30 bits) should be fit into the last 30 bits in a
+ * 4-byte word (skip B31 and B32), with MSB first, for a total of 40
+ * bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
+ *
+ * - For Glonass L1 C/A, each string contains 85 data bits, including the
+ * checksum. These bits should be fit into 11 bytes, with MSB first (skip
+ * B86-B88), covering a time period of 2 seconds.
+ *
+ * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+ * excluded). Each word should be fit into 30-bytes, with MSB first (skip
+ * B239, B240), covering a time period of 10 seconds.
+ *
+ * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+ * a total of 2x114 = 228 bits, (sync & tail excluded) that should be fit
+ * into 29 bytes, with MSB first (skip B229-B232).
+ */
+ uint8_t data[MAX_NAV_DATA_LEN];
+} gnss_nav_msg;
+
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GNSS_MAX_SVS 64
+
+/**
+ * A struct containing the characteristics of the reflecting plane that the satellite signal has
+ * bounced from.
+ *
+ * The value is only valid if HAS_REFLECTING_PLANE flag is set. An invalid reflecting plane
+ * means either reflection planes serving is not supported or the satellite signal has gone
+ * through multiple reflections.
+ */
+typedef struct {
+ /** Represents latitude of the reflecting plane in degrees. */
+ double latitude_degrees;
+
+ /** Represents longitude of the reflecting plane in degrees. */
+ double longitude_degrees;
+
+ /**
+ * Represents altitude of the reflecting point in the plane in meters above the WGS 84 reference
+ * ellipsoid.
+ */
+ double altitude_meters;
+
+ /** Represents azimuth clockwise from north of the reflecting plane in degrees. */
+ double azimuth_degrees;
+} reflecting_plane ;
+
+typedef struct {
+
+ /** Contains Gnsssingle_sat_correctionFlags bits. */
+ uint16_t single_sat_correctionFlags;
+
+ /**
+ * Defines the constellation of the given satellite.
+ */
+ mtk_hal_gnss_constellation_type constellation;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ */
+ uint16_t svid;
+
+ /**
+ * Carrier frequency of the signal to be corrected, for example it can be the
+ * GPS center frequency for L1 = 1,575,420,000 Hz, varying GLO channels, etc.
+ *
+ * For a receiver with capabilities to track multiple frequencies for the same satellite,
+ * multiple corrections for the same satellite may be provided.
+ */
+ float carrier_frequency_hz;
+
+ /**
+ * The probability that the satellite is estimated to be in Line-of-Sight condition at the given
+ * location.
+ */
+ float prob_satIs_los;
+
+ /**
+ * Excess path length to be subtracted from pseudorange before using it in calculating location.
+ *
+ * Note this value is NOT to be used to adjust the GnssMeasurementCallback outputs.
+ */
+ float excess_path_length_meters;
+
+ /** Error estimate (1-sigma) for the Excess path length estimate */
+ float excess_path_length_uncertainty_meters;
+
+ /**
+ * Defines the reflecting plane characteristics such as location and azimuth
+ *
+ * The value is only valid if HAS_REFLECTING_PLANE flag is set. An invalid reflecting plane
+ * means either reflection planes serving is not supported or the satellite signal has gone
+ * through multiple reflections.
+ */
+ reflecting_plane reflecting_plane;
+}single_sat_correction;
+
+
+/**
+ * A struct containing a set of measurement corrections for all used GNSS satellites at the location
+ * specified by latitude_degrees, longitude_degrees, altitude_meters and at the time of week specified
+ * toa_gps_nanoseconds_of_week
+ */
+typedef struct {
+ /** Represents latitude in degrees at which the corrections are computed.. */
+ double latitude_degrees;
+
+ /** Represents longitude in degrees at which the corrections are computed.. */
+ double longitude_degrees;
+
+ /**
+ * Represents altitude in meters above the WGS 84 reference ellipsoid at which the corrections
+ * are computed.
+ */
+ double altitude_meters;
+
+ /**
+ * Represents the horizontal uncertainty (68% confidence) in meters on the device position at
+ * which the corrections are provided.
+ *
+ * This value is useful for example to judge how accurate the provided corrections are.
+ */
+ double horizontal_position_uncertainty_meters;
+
+ /**
+ * Represents the vertical uncertainty (68% confidence) in meters on the device position at
+ * which the corrections are provided.
+ *
+ * This value is useful for example to judge how accurate the provided corrections are.
+ */
+ double vertical_position_uncertainty_meters;
+
+ /** Time Of Applicability, GPS time of week in nanoseconds. */
+ uint64_t toa_gps_nanoseconds_of_week;
+
+ /** Number of single_sat_correction */
+ size_t num_sat_correction;
+
+ /**
+ * A set of single_sat_correction each containing measurement corrections for a satellite in view
+ */
+ single_sat_correction sat_corrections[GNSS_MAX_SVS];
+} measurement_corrections;
+
+/**
+ * Protocol stack that is requesting the non-framework location information.
+ */
+enum {
+ /** Cellular control plane requests */
+ MNLDINF_CTRL_PLANE = 0,
+ /** All types of SUPL requests */
+ MNLDINF_SUPL = 1,
+
+ /** All types of requests from IMS */
+ MNLDINF_IMS = 10,
+ /** All types of requests from SIM */
+ MNLDINF_SIM = 11,
+
+ /** Requests from other protocol stacks */
+ MNLDINF_OTHER_PROTOCOL_STACK = 100
+};
+typedef uint8_t MNLDINF_NfwProtocolStack;
+
+////////////////////// GNSS HIDL v2.0 ////////////////////////////
+
+#define MNLDINF_STRING_MAXLEN 256
+
+/*
+ * Entity that is requesting/receiving the location information.
+ */
+enum { //mnldinf_nfw_equestor : uint8_t {
+ /** Wireless service provider */
+ MNLDINF_CARRIER = 0,
+ /** Device manufacturer */
+ MNLDINF_OEM = 10,
+ /** Modem chipset vendor */
+ MNLDINF_MODEM_CHIPSET_VENDOR = 11,
+ /** GNSS chipset vendor */
+ MNLDINF_GNSS_CHIPSET_VENDOR = 12,
+ /** Other chipset vendor */
+ MNLDINF_OTHER_CHIPSET_VENDOR = 13,
+ /** Automobile client */
+ MNLDINF_AUTOMOBILE_CLIENT = 20,
+ /** Other sources */
+ MNLDINF_OTHER_REQUESTOR = 100
+ };
+typedef uint8_t mnldinf_nfw_equestor;
+
+/**
+ * GNSS response type for non-framework location requests.
+ */
+enum {//mnldinf_nfw_response_type : uint8_t {
+ /** Request rejected because framework has not given permission for this use case */
+ MNLDINF_REJECTED = 0,
+
+ /** Request accepted but could not provide location because of a failure */
+ MNLDINF_ACCEPTED_NO_LOCATION_PROVIDED = 1,
+
+ /** Request accepted and location provided */
+ MNLDINF_ACCEPTED_LOCATION_PROVIDED = 2,
+};
+typedef uint8_t mnldinf_nfw_response_type;
+
+/**
+ * Represents a non-framework location information request/response notification.
+ */
+typedef struct {
+ /**
+ * Package name of the Android proxy application representing the non-framework
+ * entity that requested location. Set to empty string if unknown.
+ */
+ char proxy_app_package_name[MNLDINF_STRING_MAXLEN];
+
+ /** Protocol stack that initiated the non-framework location request. */
+ MNLDINF_NfwProtocolStack protocol_stack;
+
+ /**
+ * Name of the protocol stack if protocol_stack field is set to OTHER_PROTOCOL_STACK.
+ * Otherwise, set to empty string.
+ *
+ * This field is opaque to the framework and used for logging purposes.
+ */
+ char other_protocol_stack_name[MNLDINF_STRING_MAXLEN];
+
+ /** Source initiating/receiving the location information. */
+ mnldinf_nfw_equestor requestor;
+
+ /**
+ * Identity of the endpoint receiving the location information. For example, carrier
+ * name, OEM name, SUPL SLP/E-SLP FQDN, chipset vendor name, etc.
+ *
+ * This field is opaque to the framework and used for logging purposes.
+ */
+ char requestor_id[MNLDINF_STRING_MAXLEN];
+
+ /** Indicates whether location information was provided for this request. */
+ mnldinf_nfw_response_type response_type;
+
+ /** Is the device in user initiated emergency session. */
+ bool in_emergency_mode;
+
+ /** Is cached location provided */
+ bool is_cached_location;
+} mnldinf_nfw_notification;
+
+/*
+*mnld basic interface support capability.
+*This structure is dedicated for mnld interface's compatibility.
+*MUST upgrade this structure,if Add a new feature or upgrade an uncompatible feature
+*/
+typedef struct {
+ /*An example for initialization version*/
+ bool support_gnss;
+ /**MUST add new support capability to the end**/
+} mnldinf_basic_client_cap;
+
+/*
+*mnld extension interface support capability.
+*This structure is dedicated for mnld interface's compatibility.
+*MUST upgrade this structure,if Add a new feature or upgrade an uncompatible feature
+*/
+typedef struct {
+ /*An example for initialization version*/
+ bool support_gnss;
+ /**MUST add new support capability to the end**/
+} mnldinf_ext_client_cap;
+
+/*
+*mnld server support capability.
+*This structure is dedicated for mnld interface's compatibility.
+*MUST upgrade this structure,if Add a new feature or upgrade an uncompatible feature
+*/
+typedef struct {
+ /*An example for initialization version*/
+ bool support_gnss;
+ /**MUST add new support capability to the end**/
+} mnldinf_basic_server_cap;
+
+/*
+*mnld server support capability.
+*This structure is dedicated for mnld interface's compatibility.
+*MUST upgrade this structure,if Add a new feature or upgrade an uncompatible feature
+*/
+typedef struct {
+ /*An example for initialization version*/
+ bool support_gnss;
+ /**MUST add new support capability to the end**/
+} mnldinf_ext_server_cap;
+
+typedef unsigned int mnldinf_agps_loc_type;
+#define MNLDINF_AGPS_LOC_TYPE_AFLT 0 // From C2K AFLT flow
+#define MNLDINF_AGPS_LOC_TYPE_CDMA_CELL 1 // From C2K Cell
+#define MNLDINF_AGPS_LOC_TYPE_MOLR_BEGIN_RSP 2 // For CP MOLR after UE provides MSA result, the network will send CISS_FACILITY to provide UE a MSA location. Refer to 3GPP TS37.571-2 7.2.2.2
+#define MNLDINF_AGPS_LOC_TYPE_SUPL_END 3 // From the SUPL END in a supl session. It may be the result of MSA, E-CID, OTDOA, or their hybrid.
+#define MNLDINF_AGPS_LOC_TYPE_SUPL_REF_LOC 4 // For Reference Location assistance data in SUPL flow (equivalent to PMTK713 in SUPL flow)
+#define MNLDINF_AGPS_LOC_TYPE_CP_REF_LOC 5 // For Reference Location assistance data in CP AGPS flow (equivalent to PMTK713 in CP AGPS flow)
+#define MNLDINF_AGPS_LOC_TYPE_UNKNOWN 0xff // Unknown
+
+typedef struct {
+ double latitude; // Represents latitude in degrees
+ double longitude; // Represents longitude in degrees
+ char altitude_used; // 0=disabled 1=enabled
+ double altitude; // Represents altitude in meters above the WGS 84 reference
+ char speed_used; // 0=disabled 1=enabled
+ float speed; // Represents speed in meters per second
+ char bearing_used; // 0=disabled 1=enabled
+ float bearing; // Represents heading in degrees
+ char accuracy_used; // 0=disabled 1=enabled
+ float accuracy; // Represents expected accuracy in meters
+ char timestamp_used; // 0=disabled 1=enabled
+ long long timestamp; // Milliseconds since January 1, 1970
+ char type_used; // 0=disabled 1=enabled
+ mnldinf_agps_loc_type type; // Reference location source type
+} mnldinf_agps_location;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_data_coder.h b/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_data_coder.h
new file mode 100644
index 0000000..f534d19
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_data_coder.h
@@ -0,0 +1,32 @@
+#ifndef __MNLDINF_DATA_CODER_H__
+#define __MNLDINF_DATA_CODER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char mnldinf_get_byte(char* buff, int* offset, int src_len);
+short mnldinf_get_short(char* buff, int* offset, int src_len);
+int mnldinf_get_int(char* buff, int* offset, int src_len);
+long long mnldinf_get_long(char* buff, int* offset, int src_len);
+float mnldinf_get_float(char* buff, int* offset, int src_len);
+double mnldinf_get_double(char* buff, int* offset, int src_len);
+char* mnldinf_get_string(char* buff, int* offset, int src_len);
+char* mnldinf_get_string2(char* buff, int* offset, int src_len);
+int mnldinf_get_binary(char* buff, int* offset, char* output, int src_len, int des_len);
+
+void mnldinf_put_byte(char* buff, int* offset, const char input);
+void mnldinf_put_short(char* buff, int* offset, const short input);
+void mnldinf_put_int(char* buff, int* offset, const int input);
+void mnldinf_put_long(char* buff, int* offset, const long long input);
+void mnldinf_put_float(char* buff, int* offset, const float input);
+void mnldinf_put_double(char* buff, int* offset, const double input);
+void mnldinf_put_string(char* buff, int* offset, const char* input);
+void mnldinf_put_binary(char* buff, int* offset, const char* input, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_ext.h b/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_ext.h
new file mode 100644
index 0000000..28d6b89
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_ext.h
@@ -0,0 +1,84 @@
+#ifndef __MNLDINF_EXT_INTERFACE_H__
+#define __MNLDINF_EXT_INTERFACE_H__
+
+#include "mnldinf_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MNLDINF_EXT_TCP "mnldinf_ext"
+
+typedef struct {
+ void (*mnldinf_connection_broken)();
+ void (*mnldinf_request_wakelock)();
+ void (*mnldinf_release_wakelock)();
+
+ void (*mnldinf_request_utc_time)();
+ void (*mnldinf_request_nlp)(bool independent_from_gnss, bool is_user_emergency);
+ void (*mnldinf_request_ni_notify)(int session_id, agps_ni_type ni_type, agps_notify_type type, const char* requestor_id,
+ const char* client_name, ni_encoding_type requestor_id_encoding,
+ ni_encoding_type client_name_encoding);
+
+ void (*mnldinf_request_data_conn)(struct sockaddr_storage* addr, agps_type type);
+ void (*mnldinf_release_data_conn)();
+
+ void (*mnldinf_request_set_id)(request_setid flags);
+ void (*mnldinf_request_ref_loc)(request_refloc flags);
+ void (*mnldinf_output_vzw_debug)(const char* str);
+
+ void (*mnldinf_update_gnss_name)(const char* name, int length);
+
+ void (*mnldinf_gnss_navigation_msg)(gnss_nav_msg *msg);
+ void (*mnldinf_nfw_access_notify)(mnldinf_nfw_notification *nfw_notify);
+ void (*mnldinf_capability_update)(mnldinf_ext_server_cap *cap);
+ void (*mnldinf_agps_location_update)(mnldinf_agps_location location);
+} mnldinf_ext;
+
+int mnldinf_ext_data_conn_open(int fd, const char* apn);
+int mnldinf_ext_data_conn_open_with_apn_ip_type(int fd, uint64_t network_handle, const char* apn, apn_ip_type ip_type);
+int mnldinf_ext_data_conn_closed(int fd);
+int mnldinf_ext_data_conn_failed(int fd);
+
+int mnldinf_ext_set_server(int fd, agps_type type, const char* hostname, int port);
+int mnldinf_ext_set_ref_location(int fd, cell_type type, int mcc, int mnc, int lac, int cid);
+int mnldinf_ext_set_id(int fd, agps_id_type type, const char* setid);
+//OpenWRT can't response
+int mnldinf_ext_update_network_state(int fd, uint64_t network_handle, bool is_connected,
+ uint16_t capabilities, const char* apn);
+
+int mnldinf_ext_update_network_availability(int fd, int available, const char* apn);
+
+int mnldinf_ext_set_vzw_debug(int fd, bool enabled);
+
+int mnldinf_ext_gnss_inject_time(int fd, int64_t time, int64_t time_reference, int uncertainty);
+int mnldinf_ext_gnss_inject_location(int fd, double lat, double lng, float acc);
+int mnldinf_ext_ni_message(int fd, char* msg, int len);
+int mnldinf_ext_ni_respond(int fd, int notif_id, ni_user_response_type user_response);
+
+int mnldinf_ext_gnss_delete_aiding_data(int fd, gnss_delete_flag flags);
+int mnldinf_ext_gnss_set_position_mode(int fd, gps_pos_mode mode);
+int mnldinf_ext_update_gnss_config(int fd, const char* config_data, int length);
+int mnldinf_ext_set_sv_blacklist(int fd, long long* blacklist, int32_t size);
+int mnldinf_ext_send_pmtk(int fd, char* msg, int len);
+
+int mnldinf_ext_gnss_navigation_msg_enable(int fd, bool enable);
+int mnldinf_ext_gnss_full_tracking_enable(int fd, bool enable); //To be implement
+
+int mnldinf_ext_epo_enable(int fd, epo_bitmap epo_cfg);
+int mnldinf_ext_set_nfw_access(int fd, char* proxy_apps, int32_t length);
+int mnldinf_ext_set_correction(int fd, measurement_corrections* corrections);
+int mnldinf_ext_set_ttff_acc(int fd, ttff_acc acc_mode);
+
+// -1 means failure
+int mnldinf_ext_cmd_hdlr(int fd, mnldinf_ext* hdlr);
+
+int mnldinf_ext_register(char *client_name);
+
+void mnldinf_ext_capability_config(int fd, mnldinf_ext_client_cap *cap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_log.h b/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_log.h
new file mode 100644
index 0000000..f78154f
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_log.h
@@ -0,0 +1,228 @@
+/*
+* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2017. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*/
+#ifndef __MNLDINF_LOG_H_
+#define __MNLDINF_LOG_H_
+#include <string.h>
+#include <syslog.h>
+/**
+ * @enum LOG_LEVEL
+ * @brief Define Log Level
+ */
+typedef enum {
+ L_VERBOSE = 0, L_DEBUG, L_INFO, L_WARN, L_ERROR, L_ASSERT, L_SUPPRESS
+} LOG_LEVEL;
+
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+
+#ifndef LOG_TAG
+#define LOG_TAG "gnss_hal"
+#endif
+
+#ifdef LOGA
+#undef LOGA
+#endif
+
+#ifdef LOGE
+#undef LOGE
+#endif
+
+#ifdef LOGW
+#undef LOGW
+#endif
+
+#ifdef LOGI
+#undef LOGI
+#endif
+
+#ifdef LOGD
+#undef LOGD
+#endif
+
+#ifdef LOGV
+#undef LOGV
+#endif
+
+#define mnldinf_LOG_LEVEL L_DEBUG
+int set_log_level(int *dst_level, int src_level);
+
+extern int log_dbg_level;
+#define LOG_IS_ENABLED(level) (log_dbg_level <= level)
+
+#define FILE_NAME(x) strrchr(x, '/')?strrchr(x, '/') + 1 : x
+
+#if defined(__ANDROID_OS__)
+
+#include <cutils/sockets.h>
+#include <log/log.h> /*logging in logcat*/
+#include <cutils/android_filesystem_config.h>
+#include <cutils/properties.h>
+
+#define PRINT_LOG(loglevel, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ switch (loglevel){\
+ case L_ASSERT:\
+ {\
+ ALOG_ASSERT("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_ERROR:\
+ {\
+ ALOGE("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_WARN:\
+ {\
+ ALOGW("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_INFO:\
+ {\
+ ALOGI("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_DEBUG:\
+ {\
+ ALOGD("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_VERBOSE:\
+ {\
+ ALOGV("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ }\
+ }\
+ } while (0)
+
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, fmt, ##args)
+
+#define TRC(f) ALOGD("%s", __func__)
+
+#elif defined(__TIZEN_OS__)
+
+#include <dlog/dlog.h>
+
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ dlog_print(DLOG_DEBUG, fmt "\n", ##args);\
+ printf(fmt "\n", ##args);
+ fflush(stdout);\
+ }\
+ } while (0)
+
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, "[ASSERT]: ", fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, "[ERROR]: ", fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, "[WARNING]: ", fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, "[INFO]: ", fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, "[DEBUG]: ", fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, "[VERBOSE]: ", fmt, ##args)
+
+//#elif defined(__LINUX_OS__)
+#else
+#include <stdio.h>
+
+char time_buff[64];
+int mnldinf_get_time_str(char* buf, int len);
+
+#ifndef gettid
+#include <unistd.h>
+#include <sys/syscall.h>
+#define gettid() syscall(__NR_gettid)
+#define getpid() syscall(__NR_getpid)
+#endif
+#if 1
+
+#define PRINT_LOG_SAMPLE
+#ifndef PRINT_LOG_SAMPLE
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ int syslog_level[] = {LOG_DEBUG, LOG_DEBUG, LOG_DEBUG, LOG_WARNING, LOG_ERR, LOG_ERR, LOG_ERR}; \
+ LOG_LEVEL log_level = loglevel; \
+ if(log_level > L_SUPPRESS) { log_level = L_SUPPRESS; } \
+ if(log_level < L_VERBOSE) { log_level = L_VERBOSE; } \
+ mnldinf_get_time_str(time_buff, sizeof(time_buff));\
+ syslog(syslog_level[log_level], "%ld %ld [%s]" LOG_TAG tag "%s %s %d " fmt "\n",\
+ getpid(), gettid(),time_buff, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ }\
+ } while (0)
+#else
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ int syslog_level[] = {LOG_DEBUG, LOG_DEBUG, LOG_DEBUG, LOG_WARNING, LOG_ERR, LOG_ERR, LOG_ERR}; \
+ LOG_LEVEL log_level = loglevel; \
+ if(log_level > L_SUPPRESS) { log_level = L_SUPPRESS; } \
+ if(log_level < L_VERBOSE) { log_level = L_VERBOSE; } \
+ syslog(syslog_level[log_level], "%ld %ld " LOG_TAG tag fmt "\n",\
+ getpid(), gettid(), ##args);\
+ }\
+ } while (0)
+#endif
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, "[ASSERT]: ", fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, "[ERROR]: ", fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, "[WARNING]: ", fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, "[INFO]: ", fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, "[DEBUG]: ", fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, "[VERBOSE]: ", fmt, ##args)
+#else
+#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); }
+
+#endif
+#define TRC(f) ((void)0)
+
+#define PRINT_SIZE(type) do { \
+ LOGD("sizeof %s:%lu", #type, sizeof(type)); \
+} while(0)
+
+#define crash_with_log() {\
+ LOGE("crash_with_log() %s %s() line=%d", __FILE__, __FUNCTION__, __LINE__);\
+ exit(1);\
+}
+
+#endif
+
+#endif
diff --git a/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_utility.h b/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_utility.h
new file mode 100644
index 0000000..9b6d74b
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/mnldinf/inc/mnldinf_utility.h
@@ -0,0 +1,197 @@
+#ifndef __MNLDINF_UTILITY_H__
+#define __MNLDINF_UTILITY_H__
+
+#include <time.h>
+#include <stdint.h>
+#include <pthread.h>
+
+#include "mnldinf_log.h"
+#include "mnldinf_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************
+* Basic Utilities
+**************************************************/
+#define MTK_GPS_NVRAM 0
+
+#define INVALID_TIMERID ((timer_t)-1)
+
+#define DUMP_BYTES_PER_LINE 16
+#define DUMP_MAX_PRINT_LINE 10
+
+#define MNLDINF_DUMP_MEM(addr, len) do{\
+ int i = 0, j = 0;\
+ char print_buf[DUMP_BYTES_PER_LINE*5+1] = {0};\
+ unsigned int print_len = len;\
+ if(len > DUMP_MAX_PRINT_LINE*DUMP_BYTES_PER_LINE) {\
+ print_len = DUMP_MAX_PRINT_LINE*DUMP_BYTES_PER_LINE;\
+ }\
+ LOGD(">>>>>DUMP_START(addr:%p, len:%d, print_len:%ud)<<<<<", addr, len,print_len);\
+ for(i = 0; i < print_len; i+=DUMP_BYTES_PER_LINE) {\
+ memset(print_buf, 0, sizeof(print_buf));\
+ for(j=0;j<DUMP_BYTES_PER_LINE;j++) {\
+ sprintf(&print_buf[j*5], "0x%02x ", ((char *)addr)[i*DUMP_BYTES_PER_LINE+j]);\
+ print_buf[DUMP_BYTES_PER_LINE*5] = '\0';\
+ }\
+ LOGD("[%3d]:%s", i/DUMP_BYTES_PER_LINE, print_buf);\
+ }\
+ LOGD("<<<<<DUMP_STOP>>>>>");\
+}while(0)
+
+void mnldinf_msleep(int interval);
+
+#define MNLD_STRNCPY(dst,src,size) do{\
+ strncpy((char *)(dst), (char *)(src), (size - 1));\
+ (dst)[size - 1] = '\0';\
+ }while(0)
+
+#define MNLD_SPRINTF(buf,fmt,...) do{\
+ if(sprintf((char *)(buf), fmt,##__VA_ARGS__) < 0){\
+ LOGE("sprintf error occurred");\
+ }\
+ }while(0)
+
+#define MNLD_SNPRINTF(buf,len,fmt,...) do{\
+ if(snprintf((char *)(buf), len, fmt,##__VA_ARGS__) < 0){\
+ LOGE("snprintf error occurred");\
+ }\
+ }while(0)
+
+#define MNLD_VSNPRINTF(buf,len,fmt,...) do{\
+ if(vsnprintf((char *)(buf), len, fmt,##__VA_ARGS__) < 0){\
+ LOGE("vsnprintf error occurred");\
+ }\
+ }while(0)
+
+#define MNLD_FRINTF(buf,fmt,...) do{\
+ if(fprintf(buf, fmt,##__VA_ARGS__) < 0){\
+ LOGE("fprintf error occurred");\
+ }\
+ }while(0)
+
+#define MNLDINF_MSG_HEAD_LEN (3*sizeof(int))
+
+//Cycle buffer
+typedef struct cyclical_buffer // Cyclical buffer
+{
+ char *next_write; // next position to write to
+ char *next_read; // next position to read from
+ char *start_buffer; // start of buffer
+ char *end_buffer; // end of buffer + 1
+ int buffer_size;
+} cyclical_buffer_t;
+
+//Cmd record and dump
+#define GPS_HAL_TIME_STR_LEN 25
+#define GPS_HAL_CMD_RECORD_NUM 10
+#define GPS_HAL_CMD_MONITER_TIMEOUT (3*1000)
+
+typedef struct {
+ char enter_time[GPS_HAL_TIME_STR_LEN];
+ char exit_time[GPS_HAL_TIME_STR_LEN];
+ time_t exec_time;
+ mnl2hal_cmd cmd;
+} gps_cmd_record;
+
+/*************************************************
+* Timer
+**************************************************/
+typedef void (* timer_callback)();
+
+
+// in millisecond
+time_t mnldinf_get_tick();
+
+// in millisecond
+time_t mnldinf_get_time_in_millisecond();
+
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int mnldinf_epoll_add_fd(int epfd, int fd);
+
+// -1 failed
+int mnldinf_epoll_add_fd2(int epfd, int fd, uint32_t events);
+
+// -1 failed
+int mnldinf_epoll_del_fd(int epfd, int fd);
+
+int mnldinf_epoll_mod_fd(int epfd, int fd, uint32_t events);
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int mnldinf_socket_bind_udp(const char* path);
+
+// -1 means failure
+int mnldinf_socket_set_blocking(int fd, int blocking);
+
+// -1 means failure
+int mnldinf_safe_sendto(const char* path, const char* buff, int len);
+
+// -1 means failure
+int mnldinf_safe_recvfrom(int fd, char* buff, int len);
+
+// -1 means failure
+int mnldinf_start_timer(timer_t timerid, int milliseconds);
+
+// -1 means failure
+int mnldinf_stop_timer(timer_t timerid);
+
+// -1 means failure
+timer_t mnldinf_init_timer(timer_callback cb);
+
+// -1 means failure
+int mnldinf_deinit_timer(timer_t timerid);
+
+/*************************************************
+* Cycle buffer
+**************************************************/
+void mnldinf_buffer_initialize(cyclical_buffer_t *buffer, char *buffer_body, unsigned int buffer_size);
+int mnldinf_put_msg_to_cycle(cyclical_buffer_t *cyc_buffer, char *buff, int len);
+int mnldinf_get_one_msg(cyclical_buffer_t *cyc_buffer, char *buff);
+
+
+/*************************************************
+* Socket
+**************************************************/
+int mnldinf_tcp_send(int fd, const char* buff, int len);
+int mnldinf_socket_tcp_server_bind_local(bool abstract, const char* name);
+int mnldinf_socket_tcp_server_new_connect(int serverfd);
+int mnldinf_socket_tcp_client_connect_local(bool abstract, const char* name);
+int mnldinf_socket_udp_server_bind_local(bool abstract, const char* name);
+int mnldinf_socket_udp_client_create_local(bool abstract, const char* name);
+bool mnldinf_socket_udp_exist_local(bool abstract, const char* name);
+int mnldinf_safe_recv(int fd, char* buff, int len);
+
+//------------------------------------------------------
+//Linux wake lock
+
+#define MNLDINF_WAKE_LOCK_ID "mnldinf_wakelock"
+//delay to do wake_unlock to ensure the msg can be deliveried to other process
+#define MNLDINF_WAKE_LOCK_TIMEOUT (5 * 1000)
+//Timer refresh latency, to protect timer update too often in short time
+#define MNLDINF_WAKE_LOCK_LATENCY (1 * 1000)
+
+typedef struct {
+ bool wake_lock_acquired;
+ timer_t unlock_timer;
+ pthread_mutex_t mutex;
+ time_t time_last_refresh;
+} wake_lock_ctx;
+
+void mnldinf_wake_lock_init();
+void mnldinf_wake_lock_deinit();
+void mnldinf_wake_lock_take();
+void mnldinf_wake_lock_give();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_basic.c b/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_basic.c
new file mode 100644
index 0000000..2ee6ac8
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_basic.c
@@ -0,0 +1,371 @@
+#include "mnldinf_basic.h"
+#include "mnldinf_utility.h"
+#include "mnldinf_data_coder.h"
+#include "mnldinf_log.h"
+#include "errno.h"
+
+//int log_dbg_level = mnldinf_LOG_LEVEL;
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnldinf_basic"
+#endif
+#ifndef MIN
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#endif
+
+char g_mnldinf_basic_msg_buf[HAL_MNL_BUFF_SIZE_SND*2] = {0};
+cyclical_buffer_t g_mnldinf_basic_cbuffer; // io - cyclic buffer
+mnldinf_basic_client_cap g_mnldinf_basic_client_cap;
+volatile bool g_mnldinf_basic_cap_setted = false;
+gnss_data meas_data;
+
+#define DUMP_BASIC_CLIENT_CAP(cap) do {\
+ LOGD("[%s]:mnldinf_basic_client_cap size:%lu, gnss_support=%d", __func__, sizeof(mnldinf_basic_client_cap), (cap)->support_gnss);\
+} while(0)
+
+#define DUMP_BASIC_SERVER_CAP(cap) do {\
+ LOGD("[%s]:mnldinf_basic_server_cap size:%lu, gnss_support=%d", __func__, sizeof(mnldinf_basic_server_cap), (cap)->support_gnss);\
+} while(0)
+
+static gps_cmd_record basic_cmd_list[GPS_HAL_CMD_RECORD_NUM];
+static int basic_cmd_rcd_idx = 0;
+static time_t basic_enter_time_ms = 0;
+static timer_t basic_cmd_moniter_timer = INVALID_TIMERID;
+static int basic_last_record_idx = 0xFF;
+
+void mnldinf_basic_cmd_enter_record(mnl2hal_cmd cmd) {
+ int ret = 0;
+ /*Clear parameters before setting*/
+ memset(basic_cmd_list[basic_cmd_rcd_idx].enter_time, 0, GPS_HAL_TIME_STR_LEN);
+ memset(basic_cmd_list[basic_cmd_rcd_idx].exit_time, 0, GPS_HAL_TIME_STR_LEN);
+ basic_cmd_list[basic_cmd_rcd_idx].cmd = 0;
+ basic_cmd_list[basic_cmd_rcd_idx].exec_time = 0;
+
+ basic_last_record_idx = 0xFF; //Print all history command
+ basic_enter_time_ms = mnldinf_get_time_in_millisecond();
+ ret = mnldinf_get_time_str(basic_cmd_list[basic_cmd_rcd_idx].enter_time, GPS_HAL_TIME_STR_LEN);
+ if(ret == -1) {
+ LOGW("mnldinf_get_time_str fail(%s)", strerror(errno));
+ }
+ basic_cmd_list[basic_cmd_rcd_idx].cmd = cmd;
+
+ ret = mnldinf_start_timer(basic_cmd_moniter_timer, GPS_HAL_CMD_MONITER_TIMEOUT);
+ if(ret == -1) {
+ LOGW("start_timer fail(%s)", strerror(errno));
+ }
+}
+
+void mnldinf_basic_cmd_exit_record(mnl2hal_cmd cmd) {
+ if(cmd == basic_cmd_list[basic_cmd_rcd_idx].cmd) {
+ int ret = 0;
+ ret = mnldinf_get_time_str(basic_cmd_list[basic_cmd_rcd_idx].exit_time, GPS_HAL_TIME_STR_LEN);
+ if(ret == -1) {
+ LOGW("mnldinf_get_time_str fail(%s)", strerror(errno));
+ }
+ basic_cmd_list[basic_cmd_rcd_idx].exec_time = mnldinf_get_time_in_millisecond() - basic_enter_time_ms;
+ basic_cmd_rcd_idx++;
+ basic_cmd_rcd_idx = basic_cmd_rcd_idx%GPS_HAL_CMD_RECORD_NUM; //Over-write oldest recording
+ ret = mnldinf_stop_timer(basic_cmd_moniter_timer);
+ if(ret == -1) {
+ LOGW("mnldinf_stop_timer fail(%s)", strerror(errno));
+ }
+ } else {
+ LOGW("cmd not matched:enter->%d, exit->%d", basic_cmd_list[basic_cmd_rcd_idx].cmd, cmd);
+ }
+}
+
+void mnldinf_basic_cmd_list_dump(void) {
+ int print_idx = 0;
+ int cur_rcd = basic_cmd_rcd_idx;
+ int print_more = 0;
+ int empty_cnt = 0;
+
+ if(basic_last_record_idx != cur_rcd) {
+ print_more = 1;
+ basic_last_record_idx = cur_rcd;
+ }
+
+ LOGW("Dump GPS HAL command record:");
+ for(print_idx = 0; print_idx < GPS_HAL_CMD_RECORD_NUM; print_idx++){
+ if(basic_cmd_list[print_idx].cmd != 0) { //Valid cmd
+ if(print_idx == cur_rcd) {
+ LOGW("[%2d]%s:%3d << Current command(%lld)", print_idx, basic_cmd_list[print_idx].enter_time, basic_cmd_list[print_idx].cmd, (long long)(mnldinf_get_time_in_millisecond() - basic_enter_time_ms ));
+ } else {
+ if(print_more) {
+ LOGW("[%2d]%s~%s(%lld):%3d", print_idx, basic_cmd_list[print_idx].enter_time, basic_cmd_list[print_idx].exit_time, (long long)basic_cmd_list[print_idx].exec_time, basic_cmd_list[print_idx].cmd );
+ }
+ }
+ } else {
+ empty_cnt++;
+ }
+ }
+ if(empty_cnt) {
+ LOGW("empty_cnt:%d", empty_cnt);
+ }
+}
+
+void mnldinf_basic_cmd_list_init(void) {
+ memset(basic_cmd_list, 0, sizeof(basic_cmd_list));
+ basic_cmd_rcd_idx = 0;
+ basic_enter_time_ms = 0;
+ basic_last_record_idx = 0xFF;
+
+ basic_cmd_moniter_timer = mnldinf_init_timer(mnldinf_basic_cmd_list_dump);
+}
+
+//Tell server the support capability of mnld basic interface
+int mnldinf_basic_client_capability_update(int fd) {
+ LOGI("mnldinf_basic_client_capability_update, fd:%d", fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ if(g_mnldinf_basic_cap_setted == false) {
+ LOGD("mnldinf_basic_client_capability_update, set as default.");
+ memset(&g_mnldinf_basic_client_cap, 0, sizeof(mnldinf_basic_client_cap));
+ g_mnldinf_basic_client_cap.support_gnss = 1;
+ }
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_BASIC_CAP_SYNC);
+ mnldinf_put_binary(buff, &offset, (char *)&g_mnldinf_basic_client_cap, (int)sizeof(mnldinf_basic_client_cap));
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+void mnldinf_basic_capability_config(int fd, mnldinf_basic_client_cap *cap) {
+ if(cap == NULL) {
+ LOGE("NULL cap !!!!fd:%d", fd);
+ return;
+ }
+ DUMP_BASIC_CLIENT_CAP(cap);
+ memset(&g_mnldinf_basic_client_cap, 0, sizeof(mnldinf_basic_client_cap));
+ memcpy(&g_mnldinf_basic_client_cap, cap, sizeof(mnldinf_basic_client_cap));
+ g_mnldinf_basic_cap_setted = true;
+ if(-1 == mnldinf_basic_client_capability_update(fd)) {
+ LOGE("mnldinf_basic_capability_config fail!!!");
+ }
+}
+
+int mnldinf_basic_gnss_init(int fd) {
+ LOGI("mnldinf_basic_gnss_init, fd:%d", fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_INIT);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_basic_gnss_start(int fd) {
+ LOGI("mnldinf_basic_gnss_start, fd:%d", fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_START);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+int mnldinf_basic_gnss_stop(int fd) {
+ LOGI("mnldinf_basic_gnss_stop, fd:%d", fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_STOP);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_basic_gnss_cleanup(int fd) {
+ LOGI("mnldinf_basic_gnss_cleanup, fd:%d", fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_CLEANUP);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_basic_gnss_measurement_enable(int fd, bool enabled) {
+ LOGD("enabled=%d, fd:%d", enabled, fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_MEASUREMENT);
+ mnldinf_put_int(buff, &offset, enabled);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+void mnldinf_dump_gnss_sv_info(gnss_sv_info sv) {
+ unsigned int i = 0;
+ LOGD("[dump_gnss_sv_info], sv_num:%d", sv.num_svs);
+ for(i = 0; i < sv.num_svs; i++) {
+ LOGD("SV[%d], cons:%d, Cn0dBHz:%f, elev:%f, azim:%f, flags:%d, cf:%f"
+ , sv.sv_list[i].svid, sv.sv_list[i].constellation, sv.sv_list[i].c_n0_dbhz, sv.sv_list[i].elevation
+ , sv.sv_list[i].azimuth, sv.sv_list[i].flags, sv.sv_list[i].carrier_frequency);
+ }
+}
+
+// -1 means failure
+int mnldinf_basic_cmd_hdlr(int fd, mnldinf_basic* hdlr) {
+ char buff[HAL_MNL_BUFF_SIZE_SND] = {0};
+ char buff_read[HAL_MNL_BUFF_SIZE_SND] = {0};
+ int offset = 0;
+ int ver;
+ mnl2hal_cmd cmd;
+ int read_len;
+ int ret = 0;
+ int msg_len = 0;
+
+ read_len = mnldinf_safe_recv(fd, buff_read, sizeof(buff_read));
+ if (read_len <= 0) {
+ close(fd);
+ if(hdlr->mnldinf_connection_broken) {
+ LOGW("Connection broken...");
+ hdlr->mnldinf_connection_broken();
+ }
+ LOGE("mnldinf_basic_cmd_hdlr() mnldinf_safe_recvfrom() failed read_len=%d, %s", read_len, strerror(errno));
+ return -1;
+ }
+
+ mnldinf_put_msg_to_cycle(&g_mnldinf_basic_cbuffer, buff_read, read_len);
+
+ while(mnldinf_get_one_msg(&g_mnldinf_basic_cbuffer, buff) > 0) {
+ offset = 0;
+ msg_len = mnldinf_get_int(buff, &offset, sizeof(buff)); //Get message length
+ UNUSED(msg_len);
+ ver = mnldinf_get_int(buff, &offset, sizeof(buff));
+ UNUSED(ver);
+ cmd = mnldinf_get_int(buff, &offset, sizeof(buff));
+ mnldinf_basic_cmd_enter_record(cmd);
+ //LOGD("cmd:%d, msg_len:%d, ver:%d", cmd, msg_len, ver);
+ switch (cmd) {
+ case MNL2HAL_LOCATION: {
+ if (hdlr->mnldinf_location) {
+ gps_location location;
+ memset(&location, 0, sizeof(location));
+ mnldinf_get_binary(buff, &offset, (char*)&location, sizeof(buff), sizeof(gps_location));
+ hdlr->mnldinf_location(location);
+ } else {
+ LOGE("mnl2hal_hdlr() location is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_GPS_STATUS: {
+ if (hdlr->mnldinf_gnss_status) {
+ gps_status status;
+ memset(&status, 0, sizeof(status));
+ mnldinf_get_binary(buff, &offset, (char*)&status, sizeof(buff), sizeof(gps_status));
+ hdlr->mnldinf_gnss_status(status);
+ } else {
+ LOGE("mnl2hal_hdlr() gps_status is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_GPS_SV: {
+ if (hdlr->mnldinf_gnss_sv) {
+ gnss_sv_info sv;
+ memset(&sv, 0, sizeof(sv));
+ mnldinf_get_binary(buff, &offset, (char*)&sv, sizeof(buff), sizeof(gnss_sv_info));
+ //mnldinf_dump_gnss_sv_info(sv);
+ hdlr->mnldinf_gnss_sv(sv);
+ } else {
+ LOGE("mnl2hal_hdlr() gps_sv is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_NMEA: {
+ if (hdlr->mnldinf_nmea) {
+ int64_t timestamp = mnldinf_get_long(buff, &offset, sizeof(buff));
+ char* nmea = mnldinf_get_string(buff, &offset, sizeof(buff));
+ int used_length = nmea - buff;
+ int max_length = sizeof(buff) - used_length;
+ int length = mnldinf_get_int(buff, &offset, sizeof(buff));
+ length = MIN(length,max_length);
+ hdlr->mnldinf_nmea(timestamp, nmea, length);
+ } else {
+ LOGE("mnl2hal_hdlr() nmea is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_GNSS_MEASUREMENTS: {
+ if (hdlr->mnldinf_gnss_measurements) {
+ memset(&meas_data, 0, sizeof(meas_data));
+ mnldinf_get_binary(buff, &offset, (char*)&meas_data, sizeof(buff), sizeof(gnss_data));
+ hdlr->mnldinf_gnss_measurements(&meas_data);
+ } else {
+ LOGE("mnl2hal_hdlr() gnss_measurements is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_BASIC_CAP_SYNC: {
+ if(hdlr->mnldinf_capability_update) {
+ mnldinf_basic_server_cap cap;
+ memset(&cap, 0, sizeof(cap));
+ mnldinf_get_binary(buff, &offset, (char *)&cap, sizeof(buff), sizeof(cap));
+ DUMP_BASIC_SERVER_CAP(&cap);
+ hdlr->mnldinf_capability_update(&cap);
+ } else {
+ LOGE("mnl2hal_hdlr() mnldinf_capability_update is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_NMEA_DONE: {
+ if(hdlr->mnldinf_nmea_done) {
+ hdlr->mnldinf_nmea_done();
+ } else {
+ LOGE("mnl2hal_hdlr() MNL2HAL_BASIC_CAP_SYNC is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ default: {
+ LOGE("mnl2hal_hdlr() unknown cmd=%d", cmd);
+ ret = -1;
+ break;
+ }
+ }
+
+ mnldinf_basic_cmd_exit_record(cmd);
+ }
+
+ return ret;
+}
+
+void mnldinf_basic_structure_size_dump(void) {
+ PRINT_SIZE(mnldinf_basic_client_cap);
+ PRINT_SIZE(gps_location);
+ PRINT_SIZE(gps_status);
+ PRINT_SIZE(gnss_sv_info);
+ PRINT_SIZE(gnss_data);
+ PRINT_SIZE(mnldinf_basic_server_cap);
+}
+
+int mnldinf_basic_register(char *client_name) {
+ int fd = -1;
+
+ fd = mnldinf_socket_tcp_client_connect_local(true, MNLDINF_BASIC_TCP);
+ LOGD("New client:[%s], fd:%d", client_name, fd);
+ if(-1 != fd) {
+ mnldinf_basic_structure_size_dump();
+
+ mnldinf_basic_cmd_list_init();
+
+ mnldinf_socket_set_blocking(fd, 0); //Set as none-blocking
+ mnldinf_buffer_initialize(&g_mnldinf_basic_cbuffer, g_mnldinf_basic_msg_buf, sizeof(g_mnldinf_basic_msg_buf));
+ }
+
+ return fd;
+}
diff --git a/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_data_coder.c b/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_data_coder.c
new file mode 100644
index 0000000..6628011
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_data_coder.c
@@ -0,0 +1,154 @@
+#include <string.h>
+
+#ifndef MAX
+#define MAX(A,B) ((A)>(B)?(A):(B))
+#endif
+#ifndef MIN
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#endif
+
+//===============================================================
+// get
+char mnldinf_get_byte(char* buff, int* offset, int src_len) {
+ char ret = 0;
+ if (*offset >= 0 && *offset < src_len) {
+ ret = buff[*offset];
+ *offset += 1;
+ }
+ return ret;
+}
+
+short mnldinf_get_short(char* buff, int* offset, int src_len) {
+ short ret = 0;
+ ret |= mnldinf_get_byte(buff, offset, src_len) & 0xff;
+ ret |= (mnldinf_get_byte(buff, offset, src_len) << 8);
+ return ret;
+}
+
+int mnldinf_get_int(char* buff, int* offset, int src_len) {
+ int ret = 0;
+ ret |= mnldinf_get_short(buff, offset, src_len) & 0xffff;
+ ret |= (mnldinf_get_short(buff, offset, src_len) << 16);
+ return ret;
+}
+
+long long mnldinf_get_long(char* buff, int* offset, int src_len) {
+ long long ret = 0;
+ ret |= mnldinf_get_int(buff, offset, src_len) & 0xffffffffL;
+ ret |= ((long long)mnldinf_get_int(buff, offset, src_len) << 32);
+ return ret;
+}
+
+float mnldinf_get_float(char* buff, int* offset, int src_len) {
+ float ret;
+ int tmp = mnldinf_get_int(buff, offset, src_len);
+ ret = *((float*)&tmp);
+ return ret;
+}
+
+double mnldinf_get_double(char* buff, int* offset, int src_len) {
+ double ret;
+ long long tmp = mnldinf_get_long(buff, offset, src_len);
+ ret = *((double*)&tmp);
+ return ret;
+}
+
+char* mnldinf_get_string(char* buff, int* offset, int src_len) {
+ char ret = mnldinf_get_byte(buff, offset, src_len);
+ if (ret == 0) {
+ return NULL;
+ } else {
+ char* p = NULL;
+ int len = mnldinf_get_int(buff, offset, src_len);
+ if (*offset < 0 || *offset >= src_len) {
+ *offset = 0;
+ }
+ if ((len > src_len - *offset) || len < 0) {
+ len = src_len - *offset;
+ }
+ if (len <= 0) {
+ return NULL;
+ }
+ p = &buff[*offset];
+ p[len-1] = 0;
+ *offset += len;
+ return p;
+ }
+}
+
+char* mnldinf_get_string2(char* buff, int* offset, int src_len) {
+ char* output = mnldinf_get_string(buff, offset, src_len);
+ if (output == NULL) {
+ return "";
+ } else {
+ return output;
+ }
+}
+
+int mnldinf_get_binary(char* buff, int* offset, char* output, int src_len, int des_len) {
+ int len = 0;
+ if (*offset >= 0 && *offset <= src_len) {
+ len = mnldinf_get_int(buff, offset, src_len);
+ if (len > MIN((src_len-(*offset)), des_len)) {
+ len = MIN((src_len-(*offset)), des_len);
+ }
+ if (len > 0) {
+ memcpy(output, &buff[*offset], len);
+ *offset += len;
+ }
+ }
+ return len;
+}
+
+//===============================================================
+// put
+void mnldinf_put_byte(char* buff, int* offset, const char input) {
+ *((char*)&buff[*offset]) = input;
+ *offset += 1;
+}
+
+void mnldinf_put_short(char* buff, int* offset, const short input) {
+ mnldinf_put_byte(buff, offset, input & 0xff);
+ mnldinf_put_byte(buff, offset, (input >> 8) & 0xff);
+}
+
+void mnldinf_put_int(char* buff, int* offset, const int input) {
+ mnldinf_put_short(buff, offset, input & 0xffff);
+ mnldinf_put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void mnldinf_put_long(char* buff, int* offset, const long long input) {
+ mnldinf_put_int(buff, offset, input & 0xffffffffL);
+ mnldinf_put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void mnldinf_put_float(char* buff, int* offset, const float input) {
+ int* data = (int*)&input;
+ mnldinf_put_int(buff, offset, *data);
+}
+
+void mnldinf_put_double(char* buff, int* offset, const double input) {
+ long long* data = (long long*)&input;
+ mnldinf_put_long(buff, offset, *data);
+}
+
+void mnldinf_put_string(char* buff, int* offset, const char* input) {
+ if (input == NULL) {
+ mnldinf_put_byte(buff, offset, 0);
+ } else {
+ int len = strlen(input) + 1;
+ mnldinf_put_byte(buff, offset, 1);
+ mnldinf_put_int(buff, offset, len);
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+ }
+}
+
+void mnldinf_put_binary(char* buff, int* offset, const char* input, const int len) {
+ mnldinf_put_int(buff, offset, len);
+ if (len > 0) {
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+ }
+}
+
diff --git a/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_ext.c b/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_ext.c
new file mode 100644
index 0000000..aa6bf45
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_ext.c
@@ -0,0 +1,704 @@
+#include "mnldinf_ext.h"
+#include "mnldinf_utility.h"
+#include "mnldinf_data_coder.h"
+#include "mnldinf_log.h"
+#include "errno.h"
+
+//int log_dbg_level = mnldinf_LOG_LEVEL;
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnldinf_ext"
+#endif
+
+//static float report_time_interval = 0;
+char g_mnldinf_ext_msg_buf[HAL_MNL_BUFF_SIZE_SND*2] = {0};
+cyclical_buffer_t g_mnldinf_ext_cbuffer; // io - cyclic buffer
+mnldinf_ext_client_cap g_mnldinf_ext_client_cap;
+bool g_mnldinf_ext_cap_setted = false;
+
+#define DUMP_EXT_CLIENT_CAP(cap) do {\
+ LOGD("[%s]:mnldinf_ext_client_cap size:%lu, gnss_support=%d", __func__, sizeof(mnldinf_ext_client_cap), (cap)->support_gnss);\
+} while(0)
+
+#define DUMP_EXT_SERVER_CAP(cap) do {\
+ LOGD("[%s]:mnldinf_ext_server_cap size:%lu, gnss_support=%d", __func__, sizeof(mnldinf_ext_server_cap), (cap)->support_gnss);\
+} while(0)
+
+static gps_cmd_record ext_cmd_list[GPS_HAL_CMD_RECORD_NUM];
+static int ext_cmd_rcd_idx = 0;
+static time_t ext_enter_time_ms = 0;
+static timer_t ext_cmd_moniter_timer = INVALID_TIMERID;
+static int ext_last_record_idx = 0xFF;
+
+void mnldinf_ext_cmd_enter_record(mnl2hal_cmd cmd) {
+ int ret = 0;
+ /*Clear parameters before setting*/
+ memset(ext_cmd_list[ext_cmd_rcd_idx].enter_time, 0, GPS_HAL_TIME_STR_LEN);
+ memset(ext_cmd_list[ext_cmd_rcd_idx].exit_time, 0, GPS_HAL_TIME_STR_LEN);
+ ext_cmd_list[ext_cmd_rcd_idx].cmd = 0;
+ ext_cmd_list[ext_cmd_rcd_idx].exec_time = 0;
+
+ ext_last_record_idx = 0xFF; //Print all history command
+ ext_enter_time_ms = mnldinf_get_time_in_millisecond();
+ ret = mnldinf_get_time_str(ext_cmd_list[ext_cmd_rcd_idx].enter_time, GPS_HAL_TIME_STR_LEN);
+ if(ret == -1) {
+ LOGW("mnldinf_get_time_str fail(%s)", strerror(errno));
+ }
+ ext_cmd_list[ext_cmd_rcd_idx].cmd = cmd;
+
+ ret = mnldinf_start_timer(ext_cmd_moniter_timer, GPS_HAL_CMD_MONITER_TIMEOUT);
+ if(ret == -1) {
+ LOGW("start_timer fail(%s)", strerror(errno));
+ }
+}
+
+void mnldinf_ext_cmd_exit_record(mnl2hal_cmd cmd) {
+ if(cmd == ext_cmd_list[ext_cmd_rcd_idx].cmd) {
+ int ret = 0;
+ ret = mnldinf_get_time_str(ext_cmd_list[ext_cmd_rcd_idx].exit_time, GPS_HAL_TIME_STR_LEN);
+ if(ret == -1) {
+ LOGW("mnldinf_get_time_str fail(%s)", strerror(errno));
+ }
+ ext_cmd_list[ext_cmd_rcd_idx].exec_time = mnldinf_get_time_in_millisecond() - ext_enter_time_ms;
+ ext_cmd_rcd_idx++;
+ ext_cmd_rcd_idx = ext_cmd_rcd_idx%GPS_HAL_CMD_RECORD_NUM; //Over-write oldest recording
+ ret = mnldinf_stop_timer(ext_cmd_moniter_timer);
+ if(ret == -1) {
+ LOGW("mnldinf_stop_timer fail(%s)", strerror(errno));
+ }
+ } else {
+ LOGW("cmd not matched:enter->%d, exit->%d", ext_cmd_list[ext_cmd_rcd_idx].cmd, cmd);
+ }
+}
+
+void mnldinf_ext_cmd_list_dump(void) {
+ int print_idx = 0;
+ int cur_rcd = ext_cmd_rcd_idx;
+ int print_more = 0;
+ int empty_cnt = 0;
+
+ if(ext_last_record_idx != cur_rcd) {
+ print_more = 1;
+ ext_last_record_idx = cur_rcd;
+ }
+
+ LOGW("Dump GPS HAL command record:");
+ for(print_idx = 0; print_idx < GPS_HAL_CMD_RECORD_NUM; print_idx++){
+ if(ext_cmd_list[print_idx].cmd != 0) { //Valid cmd
+ if(print_idx == cur_rcd) {
+ LOGW("[%2d]%s:%3d << Current command(%lld)", print_idx, ext_cmd_list[print_idx].enter_time, ext_cmd_list[print_idx].cmd, (long long)(mnldinf_get_time_in_millisecond() - ext_enter_time_ms ));
+ } else {
+ if(print_more) {
+ LOGW("[%2d]%s~%s(%lld):%3d", print_idx, ext_cmd_list[print_idx].enter_time, ext_cmd_list[print_idx].exit_time, (long long)ext_cmd_list[print_idx].exec_time, ext_cmd_list[print_idx].cmd );
+ }
+ }
+ } else {
+ empty_cnt++;
+ }
+ }
+ if(empty_cnt) {
+ LOGW("empty_cnt:%d", empty_cnt);
+ }
+}
+
+void mnldinf_ext_cmd_list_init(void) {
+ memset(ext_cmd_list, 0, sizeof(ext_cmd_list));
+ ext_cmd_rcd_idx = 0;
+ ext_enter_time_ms = 0;
+ ext_last_record_idx = 0xFF;
+
+ ext_cmd_moniter_timer = mnldinf_init_timer(mnldinf_ext_cmd_list_dump);
+}
+
+//Tell server the support capability of mnld extension interface
+int mnldinf_ext_capability_update(int fd) {
+ LOGI("mnldinf_ext_capability_update, fd:%d", fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ if(g_mnldinf_ext_cap_setted == false) {
+ LOGD("mnldinf_ext_capability_update, set as default.");
+ memset(&g_mnldinf_ext_client_cap, 0, sizeof(mnldinf_ext_client_cap));
+ g_mnldinf_ext_client_cap.support_gnss = 1;
+ }
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_EXT_CAP_SYNC);
+ mnldinf_put_binary(buff, &offset, (char *)&g_mnldinf_ext_client_cap, (int)sizeof(mnldinf_ext_client_cap));
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+void mnldinf_ext_capability_config(int fd, mnldinf_ext_client_cap *cap) {
+ if(cap == NULL) {
+ LOGE("NULL cap !!!!fd:%d", fd);
+ return;
+ }
+ DUMP_EXT_CLIENT_CAP(cap);
+ memset(&g_mnldinf_ext_client_cap, 0, sizeof(mnldinf_ext_client_cap));
+ memcpy(&g_mnldinf_ext_client_cap, cap, sizeof(mnldinf_ext_client_cap));
+ g_mnldinf_ext_cap_setted = true;
+ if(-1 == mnldinf_ext_capability_update(fd)) {
+ LOGE("mnldinf_ext_capability_config fail");
+ }
+}
+
+int mnldinf_ext_gnss_inject_time(int fd, int64_t time, int64_t time_reference, int uncertainty) {
+ /*LOGD("mnldinf_ext_gnss_inject_time time=%zd time_reference=%zd uncertainty=%d",
+ time, time_reference, uncertainty);*/
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_INJECT_TIME);
+ mnldinf_put_long(buff, &offset, time);
+ mnldinf_put_long(buff, &offset, time_reference);
+ mnldinf_put_int(buff, &offset, uncertainty);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_gnss_inject_location(int fd, double lat, double lng, float acc) {
+ // LOGD("mnldinf_ext_gnss_inject_location lat,lng %f,%f acc=%f", lat, lng, acc);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_INJECT_LOCATION);
+ mnldinf_put_double(buff, &offset, lat);
+ mnldinf_put_double(buff, &offset, lng);
+ mnldinf_put_float(buff, &offset, acc);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_gnss_delete_aiding_data(int fd, gnss_delete_flag flags) {
+ LOGD("flag=0x%x", flags);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_DELETE_AIDING_DATA);
+ mnldinf_put_int(buff, &offset, flags);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_gnss_set_position_mode(int fd, gps_pos_mode mode) {
+ LOGD("mode=%d", mode);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_SET_POSITION_MODE);
+ mnldinf_put_int(buff, &offset, mode);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_data_conn_open(int fd, const char* apn) {
+ LOGD("apn=[%s]", apn);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_DATA_CONN_OPEN);
+ mnldinf_put_string(buff, &offset, apn);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_data_conn_open_with_apn_ip_type(int fd, uint64_t network_handle, const char* apn, apn_ip_type ip_type) {
+ LOGD("apn=[%s] ip_type=%d",
+ apn, ip_type);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_DATA_CONN_OPEN_WITH_APN_IP_TYPE);
+ mnldinf_put_long(buff, &offset, network_handle);
+ mnldinf_put_string(buff, &offset, apn);
+ mnldinf_put_int(buff, &offset, ip_type);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_data_conn_closed(int fd) {
+ LOGD("mnldinf_ext_data_conn_closed");
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_DATA_CONN_CLOSED);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_data_conn_failed(int fd) {
+ LOGD("mnldinf_ext_data_conn_failed");
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_DATA_CONN_FAILED);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_set_server(int fd, agps_type type, const char* hostname, int port) {
+ LOGD("type=%d hostname=[%s] port=%d",
+ type, hostname, port);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_SET_SERVER);
+ mnldinf_put_int(buff, &offset, type);
+ mnldinf_put_string(buff, &offset, hostname);
+ mnldinf_put_int(buff, &offset, port);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+ return 0;
+}
+
+int mnldinf_ext_set_ref_location(int fd, cell_type type, int mcc, int mnc, int lac, int cid) {
+ LOGD("ype=%d mcc=%d mnc=%d lac=%d cid=%d",
+ type, mcc, mnc, lac, cid);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_SET_REF_LOCATION);
+ mnldinf_put_int(buff, &offset, type);
+ mnldinf_put_int(buff, &offset, mcc);
+ mnldinf_put_int(buff, &offset, mnc);
+ mnldinf_put_int(buff, &offset, lac);
+ mnldinf_put_int(buff, &offset, cid);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_set_id(int fd, agps_id_type type, const char* setid) {
+ LOGD("type=%d setid=[%s]", type, setid);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_SET_ID);
+ mnldinf_put_int(buff, &offset, type);
+ mnldinf_put_string(buff, &offset, setid);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+
+int mnldinf_ext_ni_message(int fd, char* msg, int len) {
+ LOGD("len=%d", len);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_NI_MESSAGE);
+ mnldinf_put_binary(buff, &offset, msg, len);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_send_pmtk(int fd, char* msg, int len) {
+ LOGD("len=%d", len);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_SEND_PMTK);
+ mnldinf_put_binary(buff, &offset, msg, len);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_ni_respond(int fd, int notif_id, ni_user_response_type user_response) {
+ LOGD("notif_id=%d user_response=%d",
+ notif_id, user_response);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_NI_RESPOND);
+ mnldinf_put_int(buff, &offset, notif_id);
+ mnldinf_put_int(buff, &offset, user_response);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_update_network_state(int fd, uint64_t network_handle, bool is_connected,
+ uint16_t capabilities, const char* apn) {
+ LOGD("connected=%d capabilities=%d apn=[%s]",
+ is_connected, capabilities, apn);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_UPDATE_NETWORK_STATE);
+ mnldinf_put_long(buff, &offset, network_handle);
+ mnldinf_put_byte(buff, &offset, is_connected);
+ mnldinf_put_short(buff, &offset, capabilities);
+ mnldinf_put_string(buff, &offset, apn);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_update_network_availability(int fd, int available, const char* apn) {
+ LOGD("available=%d apn=[%s]",
+ available, apn);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_UPDATE_NETWORK_AVAILABILITY);
+ mnldinf_put_int(buff, &offset, available);
+ mnldinf_put_string(buff, &offset, apn);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_gnss_navigation_msg_enable(int fd, bool enabled) {
+ LOGD("enabled=%d", enabled);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GPS_NAVIGATION);
+ mnldinf_put_int(buff, &offset, enabled);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_set_vzw_debug(int fd, bool enabled) {
+ LOGD("enabled = %d\n", enabled);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_VZW_DEBUG);
+ mnldinf_put_int(buff, &offset, enabled);
+
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_update_gnss_config(int fd, const char* config_data, int length) {
+ LOGD("data length:%d\n", length);
+ int offset = 0;
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_GNSS_CONFIG);
+ mnldinf_put_int(buff, &offset, length);
+ mnldinf_put_string(buff, &offset, config_data);
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_gnss_full_tracking_enable(int fd, bool enable) {
+ LOGD("full tracking enable:%d\n", enable);
+ int offset = 0;
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_FULL_TRACKING);
+ mnldinf_put_int(buff, &offset, enable);
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_epo_enable(int fd, epo_bitmap epo_cfg) {
+ LOGD("mnldinf_ext_epo_enable:0x%x\n", epo_cfg);
+ int offset = 0;
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_EPO_ENABLE);
+ mnldinf_put_int(buff, &offset, epo_cfg);
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_set_sv_blacklist(int fd, long long* blacklist, int32_t size) {
+ LOGD("hal2mnl_setBlacklist, size:%d, first SVID:0x%llx\n", size, *blacklist);
+ int offset = 0;
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_SV_BLACKLIST);
+ mnldinf_put_int(buff, &offset, size);
+ mnldinf_put_binary(buff, &offset, (const char*)blacklist, sizeof(long long)*size);
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_set_correction(int fd, measurement_corrections* corrections) {
+ LOGD("hal2mnl_set_correction\n");
+ int offset = 0;
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_CORRECTION);
+ mnldinf_put_binary(buff, &offset, (const char*)corrections, sizeof(measurement_corrections));
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+int mnldinf_ext_set_nfw_access(int fd, char* proxy_apps, int32_t length) {
+ LOGD("mnldinf_ext_set_nfw_access, proxy_apps:%s, len:%d\n", proxy_apps, length);
+ int offset = 0;
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_NFW_ACCESS);
+ mnldinf_put_int(buff, &offset, length);
+ mnldinf_put_string(buff, &offset, proxy_apps);
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+int mnldinf_ext_set_ttff_acc(int fd, ttff_acc acc_mode) {
+ LOGD("set TTFF acc:%d\n", acc_mode);
+ int offset = 0;
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ mnldinf_put_int(buff, &offset, HAL2MNL_SET_TTFF_ACC);
+ mnldinf_put_int(buff, &offset, acc_mode);
+ return mnldinf_tcp_send(fd, buff, offset);
+}
+
+// -1 means failure
+int mnldinf_ext_cmd_hdlr(int fd, mnldinf_ext* hdlr) {
+ char buff[HAL_MNL_BUFF_SIZE_SND] = {0};
+ char buff_read[HAL_MNL_BUFF_SIZE_SND] = {0};
+ int offset = 0;
+ int ver;
+ mnl2hal_cmd cmd;
+ int read_len;
+ int ret = 0;
+ int msg_len = 0;
+
+ read_len = mnldinf_safe_recv(fd, buff_read, sizeof(buff_read));
+ if (read_len <= 0) {
+ close(fd);
+ if(hdlr->mnldinf_connection_broken) {
+ LOGW("Connection broken......");
+ hdlr->mnldinf_connection_broken();
+ }
+ LOGE("mnldinf_ext_cmd_hdlr() mnldinf_safe_recvfrom() failed read_len=%d, %s", read_len, strerror(errno));
+ return -1;
+ }
+
+ mnldinf_put_msg_to_cycle(&g_mnldinf_ext_cbuffer, buff_read, read_len);
+
+ while(mnldinf_get_one_msg(&g_mnldinf_ext_cbuffer, buff) > 0) {
+ offset = 0;
+
+ msg_len = mnldinf_get_int(buff, &offset, sizeof(buff)); //Get message length
+ UNUSED(msg_len);
+ ver = mnldinf_get_int(buff, &offset, sizeof(buff));
+ UNUSED(ver);
+ cmd = mnldinf_get_int(buff, &offset, sizeof(buff));
+ LOGD("CMD:%d(0x%x)", cmd, cmd);
+ mnldinf_ext_cmd_enter_record(cmd);
+ switch (cmd) {
+ case MNL2HAL_REQUEST_WAKELOCK: {
+ if (hdlr->mnldinf_request_wakelock) {
+ LOGD("request_wakelock");
+ hdlr->mnldinf_request_wakelock();
+ } else {
+ LOGE("mnl2hal_hdlr() request_wakelock is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_RELEASE_WAKELOCK: {
+ if (hdlr->mnldinf_release_wakelock) {
+ hdlr->mnldinf_release_wakelock();
+ } else {
+ LOGE("mnl2hal_hdlr() release_wakelock is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_REQUEST_UTC_TIME: {
+ if (hdlr->mnldinf_request_utc_time) {
+ hdlr->mnldinf_request_utc_time();
+ } else {
+ LOGE("mnl2hal_hdlr() request_utc_time is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_REQUEST_DATA_CONN: {
+ if (hdlr->mnldinf_request_data_conn) {
+ struct sockaddr_storage addr;
+ agps_type type;
+ mnldinf_get_binary(buff, &offset, (char*)&addr, sizeof(buff), sizeof(addr));
+ type = mnldinf_get_int(buff, &offset, sizeof(buff));
+ hdlr->mnldinf_request_data_conn(&addr, type);
+ } else {
+ LOGE("mnl2hal_hdlr() request_data_conn is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_RELEASE_DATA_CONN: {
+ if (hdlr->mnldinf_release_data_conn) {
+ hdlr->mnldinf_release_data_conn();
+ } else {
+ LOGE("mnl2hal_hdlr() release_data_conn is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_REQUEST_NI_NOTIFY: {
+ if (hdlr->mnldinf_request_ni_notify) {
+ int session_id = mnldinf_get_int(buff, &offset, sizeof(buff));
+ agps_notify_type type = mnldinf_get_int(buff, &offset, sizeof(buff));
+ char* requestor_id = mnldinf_get_string(buff, &offset, sizeof(buff));
+ char* client_name = mnldinf_get_string(buff, &offset, sizeof(buff));
+ ni_encoding_type requestor_id_encoding = mnldinf_get_int(buff, &offset, sizeof(buff));
+ ni_encoding_type client_name_encoding = mnldinf_get_int(buff, &offset, sizeof(buff));
+ agps_ni_type ni_type = mnldinf_get_int(buff, &offset, sizeof(buff));
+ hdlr->mnldinf_request_ni_notify(session_id, ni_type, type, requestor_id, client_name,
+ requestor_id_encoding, client_name_encoding);
+ } else {
+ LOGE("mnl2hal_hdlr() request_ni_notify is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_REQUEST_SET_ID: {
+ if (hdlr->mnldinf_request_set_id) {
+ request_setid flags = mnldinf_get_int(buff, &offset, sizeof(buff));
+ hdlr->mnldinf_request_set_id(flags);
+ } else {
+ LOGE("mnl2hal_hdlr() request_set_id is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_REQUEST_REF_LOC: {
+ if (hdlr->mnldinf_request_ref_loc) {
+ request_refloc flags = mnldinf_get_int(buff, &offset, sizeof(buff));
+ hdlr->mnldinf_request_ref_loc(flags);
+ } else {
+ LOGE("mnl2hal_hdlr() request_ref_loc is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_VZW_DEBUG_OUTPUT: {
+ if (hdlr->mnldinf_output_vzw_debug) {
+ char* str = mnldinf_get_string(buff, &offset, sizeof(buff));
+ hdlr->mnldinf_output_vzw_debug(str);
+ } else {
+ LOGE("mnl2hal_hdlr() output_vzw_debug is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_UPDATE_GNSS_NAME: {
+ if (hdlr->mnldinf_update_gnss_name) {
+ int length = mnldinf_get_int(buff, &offset, sizeof(buff));
+ char* name = mnldinf_get_string(buff, &offset, sizeof(buff));
+ hdlr->mnldinf_update_gnss_name(name, length);
+ } else {
+ LOGE("mnl2hal_hdlr() update_gnss_name is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_REQUEST_NLP: {
+ if (hdlr->mnldinf_request_nlp) {
+ bool independent_from_gnss = mnldinf_get_byte(buff, &offset, sizeof(buff));
+ bool is_user_emergency = mnldinf_get_byte(buff, &offset, sizeof(buff));
+ hdlr->mnldinf_request_nlp(independent_from_gnss, is_user_emergency);
+ } else {
+ LOGE("mnl2hal_hdlr() update_gnss_name is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_GNSS_NAVIGATION: {
+ if (hdlr->mnldinf_gnss_navigation_msg) {
+ gnss_nav_msg msg;
+ memset(&msg, 0, sizeof(msg));
+ mnldinf_get_binary(buff, &offset, (char*)&msg, sizeof(buff), sizeof(gnss_nav_msg));
+ hdlr->mnldinf_gnss_navigation_msg(&msg);
+ } else {
+ LOGE("mnl2hal_hdlr() gnss_navigation is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_NFW_NOTIFY: {
+ if (hdlr->mnldinf_nfw_access_notify) {
+ mnldinf_nfw_notification nfw_notify;
+ memset(&nfw_notify, 0, sizeof(mnldinf_nfw_notification));
+ mnldinf_get_binary(buff, &offset, (char*)&nfw_notify, sizeof(buff), sizeof(mnldinf_nfw_notification));
+ hdlr->mnldinf_nfw_access_notify(&nfw_notify);
+ } else {
+ LOGE("mnldinf_nfw_access_notify() is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_EXT_CAP_SYNC: {
+ if(hdlr->mnldinf_capability_update) {
+ mnldinf_ext_server_cap cap;
+ memset(&cap, 0, sizeof(cap));
+ mnldinf_get_binary(buff, &offset, (char *)&cap, sizeof(buff), sizeof(cap));
+ DUMP_EXT_SERVER_CAP(&cap);
+ hdlr->mnldinf_capability_update(&cap);
+ } else {
+ LOGE("mnldinf_capability_update() is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case MNL2HAL_AGPS_LOCATION: {
+ if (hdlr->mnldinf_agps_location_update) {
+ mnldinf_agps_location location;
+ memset(&location, 0, sizeof(location));
+ mnldinf_get_binary(buff, &offset, (char*)&location, sizeof(buff), sizeof(mnldinf_agps_location));
+ hdlr->mnldinf_agps_location_update(location);
+ } else {
+ LOGE("mnl2hal_hdlr() location is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ default: {
+ LOGE("mnl2hal_hdlr() unknown cmd=%d", cmd);
+ ret = -1;
+ break;
+ }
+ }
+ mnldinf_ext_cmd_exit_record(cmd);
+ }
+
+ return ret;
+}
+
+void mnldinf_ext_structure_size_dump(void) {
+ PRINT_SIZE(gnss_nav_msg);
+ PRINT_SIZE(mnldinf_nfw_notification);
+ PRINT_SIZE(mnldinf_ext_server_cap);
+ PRINT_SIZE(measurement_corrections);
+ PRINT_SIZE(mnldinf_ext_client_cap);
+}
+
+int mnldinf_ext_register(char *client_name) {
+ int fd = -1;
+
+ fd = mnldinf_socket_tcp_client_connect_local(true, MNLDINF_EXT_TCP);
+ LOGD("New client:[%s], fd:%d", client_name, fd);
+ if(-1 != fd) {
+ mnldinf_ext_structure_size_dump();
+
+ mnldinf_socket_set_blocking(fd, 0); //Set as non-blocking
+ mnldinf_buffer_initialize(&g_mnldinf_ext_cbuffer, g_mnldinf_ext_msg_buf, sizeof(g_mnldinf_ext_msg_buf));
+
+ mnldinf_ext_cmd_list_init();
+ }
+ return fd;
+}
diff --git a/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_log.c b/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_log.c
new file mode 100644
index 0000000..7dfc898
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_log.c
@@ -0,0 +1,112 @@
+/*
+* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2017. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*/
+#include <sys/time.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+#include <memory.h>
+
+#include "mnldinf_log.h"
+
+int log_dbg_level = mnldinf_LOG_LEVEL;
+
+//#if defined(__LINUX_OS__)
+#if !defined(__ANDROID_OS__)
+// -1 means failure
+int mnldinf_get_time_str(char* buf, int len) {
+ time_t now = time(NULL);
+ struct tm tm_utc;
+ time_t time_utc;
+
+ gmtime_r(&now, &tm_utc);
+ time_utc = mktime(&tm_utc);
+
+ memset(buf, 0, len);
+ sprintf(buf, "%s", ctime(&time_utc));
+
+ buf[strlen(buf)-1] = '\0'; //Remove '\n'
+
+ return 0;
+}
+#endif
+
+int set_log_level(int *dst_level, int src_level)
+{
+#if defined(__ANDROID_OS__)
+
+ ALOGI("Current debug level=%d", *dst_level);
+
+ if (src_level < L_VERBOSE || src_level > L_SUPPRESS)
+ {
+ ALOGE("Invalid debug level, level=%d", src_level);
+ ALOGE(" [level] -");
+ ALOGE(" QUIET = 6");
+ ALOGE(" ASSERT = 5");
+ ALOGE(" ERROR = 4");
+ ALOGE(" WARNING = 3");
+ ALOGE(" INFO = 2");
+ ALOGE(" DEBUG = 1");
+ ALOGE(" LOGALL = 0");
+ return -1;
+ }
+
+ *dst_level = src_level;
+
+ ALOGI("New debug level=%d", *dst_level);
+
+//#elif defined(__LINUX_OS__)
+#else
+ printf("Current debug level=%d\n", *dst_level);
+
+ if (src_level < L_VERBOSE || src_level > L_SUPPRESS)
+ {
+ printf("Invalid debug level, level=%d\n", src_level);
+ printf(" [level] -\n");
+ printf(" QUIET = 6\n");
+ printf(" ASSERT = 5\n");
+ printf(" ERROR = 4\n");
+ printf(" WARNING = 3\n");
+ printf(" INFO = 2\n");
+ printf(" DEBUG = 1\n");
+ printf(" LOGALL = 0\n");
+ return -1;
+ }
+
+ *dst_level = src_level;
+
+ printf("New debug level=%d\n", *dst_level);
+
+#endif
+ return 0;
+}
diff --git a/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_utility.c b/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_utility.c
new file mode 100644
index 0000000..3141c69
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/mnldinf/src/mnldinf_utility.c
@@ -0,0 +1,828 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h> // usleep
+#include <sys/socket.h>
+#include <string.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 <stdbool.h>
+
+#include "mnldinf_utility.h"
+#include "mnldinf_log.h"
+#include "mnldinf_common.h"
+#include "mnldinf_data_coder.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mtk_lbs_utility"
+#endif
+#if 0
+#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 LOGD
+#endif
+void mnldinf_msleep(int interval) {
+ usleep(interval * 1000);
+}
+
+// in millisecond
+time_t mnldinf_get_tick() {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
+ LOGE("clock_gettime failed reason=[%s]", strerror(errno));
+ return -1;
+ }
+ return (ts.tv_sec*1000) + (ts.tv_nsec/1000000);
+}
+
+// in millisecond
+time_t mnldinf_get_time_in_millisecond() {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+ LOGE("mnldinf_get_time_in_millisecond failed reason=[%s]", strerror(errno));
+ return -1;
+ }
+ return ((long long)ts.tv_sec*1000) + ((long long)ts.tv_nsec/1000000);
+}
+
+//#ifdef __LINUX_OS__
+#if !defined(__ANDROID_OS__)
+/*************************************************
+* Timer
+**************************************************/
+// -1 means failure
+timer_t mnldinf_init_timer_id(timer_callback cb, int id) {
+ struct sigevent sevp;
+ timer_t timerid;
+
+ memset(&sevp, 0, sizeof(sevp));
+ sevp.sigev_value.sival_int = id;
+ sevp.sigev_notify = SIGEV_THREAD;
+ sevp.sigev_notify_function = cb;
+
+ if (timer_create(CLOCK_MONOTONIC, &sevp, &timerid) == -1) {
+ LOGE("timer_create failed reason=[%s]", strerror(errno));
+ return INVALID_TIMERID;
+ }
+ LOGD("timerid init:%lu", (unsigned long)timerid);
+ return timerid;
+}
+
+// -1 means failure
+timer_t mnldinf_init_timer(timer_callback cb) {
+ return mnldinf_init_timer_id(cb, 0);
+}
+
+// -1 means failure
+int mnldinf_start_timer(timer_t timerid, int milliseconds) {
+ if(timerid != INVALID_TIMERID) {
+ struct itimerspec expire;
+ expire.it_interval.tv_sec = 0;
+ expire.it_interval.tv_nsec = 0;
+ expire.it_value.tv_sec = milliseconds/1000;
+ expire.it_value.tv_nsec = (milliseconds%1000)*1000000;
+ return timer_settime(timerid, 0, &expire, NULL);
+ } else {
+ LOGE("invalid timerid:%lu", (unsigned long)timerid);
+ return -1;
+ }
+}
+
+// -1 means failure
+int mnldinf_stop_timer(timer_t timerid) {
+ return mnldinf_start_timer(timerid, 0);
+}
+
+// -1 means failure
+int mnldinf_deinit_timer(timer_t timerid) {
+ LOGD("timerid deinit:%lu", (unsigned long)timerid);
+ if(timerid != INVALID_TIMERID) {
+ if (timer_delete(timerid) == -1) {
+ LOGE("timer_delete error:%s", strerror(errno));
+ return -1;
+ }
+ } else {
+ LOGE("invalid timerid:%lu", (unsigned long)timerid);
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int mnldinf_epoll_add_fd(int epfd, int fd) {
+ struct epoll_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.data.fd = fd;
+ ev.events = EPOLLIN;
+ // 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("mnldinf_epoll_add_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+ strerror(errno), errno, epfd, fd);
+ return -1;
+ }
+ return 0;
+}
+
+// -1 failed
+int mnldinf_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("mnldinf_epoll_add_fd2() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+ strerror(errno), errno, epfd, fd);
+ return -1;
+ }
+ return 0;
+}
+
+int mnldinf_epoll_del_fd(int epfd, int fd) {
+ struct epoll_event ev;
+ int ret;
+
+ if (epfd == -1)
+ return -1;
+
+ ev.events = EPOLLIN;
+ ev.data.fd = fd;
+ do {
+ ret = epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev);
+ } while (ret < 0 && errno == EINTR);
+ return ret;
+}
+
+// -1 failed
+int mnldinf_epoll_mod_fd(int epfd, int fd, uint32_t events) {
+ struct epoll_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.data.fd = fd;
+ ev.events = events;
+ if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1) {
+ LOGE("mnldinf_epoll_mod_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+ strerror(errno), errno, epfd, fd);
+ return -1;
+ }
+ return 0;
+}
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int mnldinf_socket_bind_udp(const char* path) {
+ int fd;
+ struct sockaddr_un addr;
+
+ fd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ LOGE("mnldinf_socket_bind_udp() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ LOGD("fd=%d,path=%s\n", 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(path);
+
+ if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ LOGE("mnldinf_socket_bind_udp() bind() failed path=[%s] reason=[%s]%d",
+ addr.sun_path+1, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }else
+ LOGI("bind ok path=[%s]", addr.sun_path+1);
+ return fd;
+}
+
+// -1 means failure
+int mnldinf_socket_set_blocking(int fd, int blocking) {
+ if (fd < 0) {
+ LOGE("mnldinf_socket_set_blocking() invalid fd=%d", fd);
+ return -1;
+ }
+
+ int flags = fcntl(fd, F_GETFL, 0);
+ if (flags == -1) {
+ LOGE("mnldinf_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;
+}
+
+// -1 means failure
+int mnldinf_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("mnldinf_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) {
+ LOGE("errno==EINTR\n");
+ continue;
+ }
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ LOGE("errno==EAGAIN\n");
+ continue;
+ }
+ }
+ LOGE("mnldinf_safe_sendto() sendto() failed path=[%s] ret=%d reason=[%s]%d",
+ path, ret, strerror(errno), errno);
+ break;
+ }
+
+ close(fd);
+ return ret;
+}
+
+// -1 means failure
+int mnldinf_safe_recvfrom(int fd, char* buff, int len) {
+ int ret = 0;
+ int retry = 10;
+ 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;
+ }
+
+ while ((ret = recvfrom(fd, buff, len, 0,
+ NULL, NULL)) == -1) {
+ LOGW("mnldinf_safe_recvfrom() ret=%d len=%d", ret, len);
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("mnldinf_safe_recvfrom() recvfrom() failed reason=[%s]%d",
+ strerror(errno), errno);
+ break;
+ }
+ return ret;
+}
+
+/*
+------------------------
+| Length | Message Body |
+------------------------
+*/
+// -1 means failure
+int mnldinf_tcp_send(int fd, const char* buff, int len) {
+ char buff_send[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ if(fd < 0) {
+ LOGE("mnldinf_tcp_send() invalid fd:%d", fd);
+ return -1;
+ }
+
+ mnldinf_put_binary(buff_send, &offset, buff, len); //Put length to the head
+
+ int ret = write(fd, buff_send, offset);
+ if(ret == -1) {
+ LOGE(" write() failed, reason=[%s]%d", strerror(errno), errno);
+ }
+
+ LOGD("send %d, ret %d", len, ret);
+ return ret;
+}
+
+int mnldinf_safe_recv(int fd, char* buff, int len) {
+ int ret = 0;
+ int retry = 10;
+
+ while ((ret = read(fd, buff, len)) == -1) {
+ LOGW("mnldinf_safe_recvfrom() ret=%d len=%d", ret, len);
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("mnldinf_safe_recvfrom() recvfrom() failed reason=[%s]%d",
+ strerror(errno), errno);
+ break;
+ }
+ return ret;
+}
+
+
+/******************************************************************************
+* Socket
+******************************************************************************/
+
+//-1 means fail or serverfd is returned
+int mnldinf_socket_tcp_server_bind_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 {
+ MNLD_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ if(unlink(addr.sun_path) == -1) {
+ LOGW("mnldinf_socket_tcp_server_bind_local() unlink() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(fd == -1) {
+ LOGE("mnldinf_socket_tcp_server_bind_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(bind(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("mnldinf_socket_tcp_server_bind_local() bind() failed, abstruct=%d name=[%s] reason=[%s]%d",
+ abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ if(listen(fd, 5) == -1) {
+ LOGW("mnldinf_socket_tcp_server_bind_local() listen() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ return fd;
+}
+
+//-1 means fail or new clientfd is returned
+int mnldinf_socket_tcp_server_new_connect(int serverfd) {
+ int newfd;
+ struct sockaddr_in addr;
+ socklen_t len = sizeof(addr);
+
+ newfd = accept(serverfd, (struct sockaddr*)&addr, &len);
+ if(newfd == -1) {
+ LOGE("mnldinf_socket_tcp_server_new_connect() accept() failed, serverfd=%d reason=[%s]%d",
+ serverfd, strerror(errno), errno);
+ return -1;
+ }
+ return newfd;
+}
+
+//-1 means fail or serverfd is returned
+int mnldinf_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 {
+ MNLD_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ if(unlink(addr.sun_path) == -1) {
+ LOGW("mnldinf_socket_tcp_client_connect_local() unlink() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(fd == -1) {
+ LOGE("mnldinf_socket_tcp_client_connect_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(connect(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("mnldinf_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;
+}
+
+
+//-1 means fail or serverfd is returned
+int mnldinf_socket_udp_server_bind_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 {
+ MNLD_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ if(unlink(addr.sun_path) == -1) {
+ LOGW("mnldinf_socket_udp_server_bind_local() unlink() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ LOGE("mnldinf_socket_udp_server_bind_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(bind(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("mnldinf_socket_udp_server_bind_local() bind() failed, abstract=%d name=[%s] reason=[%s]%d",
+ abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+//-1 means fail or clientfd is returned
+int mnldinf_socket_udp_client_create_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 {
+ MNLD_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ LOGE("mnldinf_socket_udp_client_create_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(connect(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("mnldinf_socket_udp_client_create_local() connect() failed, abstract=%d name=[%s] reason=[%s]%d",
+ abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+bool mnldinf_socket_udp_exist_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 {
+ MNLD_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ LOGE("socket_udp_is_bind_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return false;
+ }
+ if(connect(fd, (struct sockaddr*)&addr, size) == -1) {
+ close(fd);
+ return false;
+ }
+ close(fd);
+ return true;
+
+}
+
+void mnldinf_buffer_initialize(cyclical_buffer_t *buffer, char *buffer_body, unsigned int buffer_size) {
+ // Set up buffer manipulation pointers
+ // end_buffer points to the next byte after the buffer
+ buffer->start_buffer = buffer_body;
+ 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 mnldinf_put_msg_to_cycle(cyclical_buffer_t *cyc_buffer, char *buff, int len) {
+ int i;
+#ifdef MNLDINF_DUMP_CMD_RAW
+ LOGD("mnldinf_put_msg_to_cycle:%d", len);
+#endif
+ for (i = 0; i < len; i++)
+ {
+ *(cyc_buffer->next_write++) = buff[i];
+ if (cyc_buffer->next_write == cyc_buffer->end_buffer){
+ cyc_buffer->next_write = cyc_buffer->start_buffer;
+ }
+
+ if (cyc_buffer->next_write == cyc_buffer->next_read){
+ #ifdef MNLDINF_DUMP_CMD_RAW
+ LOGE("mnldinf_put_msg_to_cycle buffer full!\r\n");
+ #endif
+ return -1;
+ }
+ }
+
+ return 0;
+}
+/******************************************
+Get one message from cycle buffer
+******************************************/
+int mnldinf_get_one_msg(cyclical_buffer_t *cyc_buffer, char *buff) {
+ char *next_write, *next_read;
+ int data_size, i, header_len;
+ char buffer[HAL_MNL_BUFF_SIZE_SND] = {0};
+ int data_len = 0;
+ int return_len = 0;
+
+ next_write = cyc_buffer->next_write;
+ next_read = cyc_buffer->next_read;
+ if (cyc_buffer->next_read == next_write)
+ {
+ //buffer empty
+ return -1;
+ }
+
+ header_len = sizeof(int);
+ /*Compute data length*/
+ if (cyc_buffer->next_read < next_write)
+ {
+ data_size = (unsigned long)next_write - (unsigned long)cyc_buffer->next_read;
+ }
+ else
+ {
+ data_size = (unsigned long)cyc_buffer->end_buffer - (unsigned long)cyc_buffer->next_read +
+ (unsigned long)next_write - (unsigned long)cyc_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 == cyc_buffer->end_buffer){
+ next_read = cyc_buffer->start_buffer;
+ }
+ }
+
+ memcpy(&data_len, buffer, sizeof(int));
+ #ifdef MNLDINF_DUMP_CMD_RAW
+ LOGD("data len:%d, header len:%d", data_len, header_len);
+ #endif
+ if (data_len <= data_size) {
+ for (i = 0; i < (data_len + header_len); i++)
+ {
+ buff[i] = *(cyc_buffer->next_read++);
+ #ifdef MNLDINF_DUMP_CMD_RAW
+ LOGD("0x%x", buff[i]);
+ #endif
+ return_len++;
+ if (cyc_buffer->next_read == cyc_buffer->end_buffer){
+ cyc_buffer->next_read = cyc_buffer->start_buffer;
+ }
+ }
+ }
+ else {
+ LOGD("func:%s, line:%d, no enough data", __func__, __LINE__);
+ //no enough data
+ return -2;
+ }
+
+ }
+ else
+ {
+ LOGD("func:%s, line:%d, no enough data", __func__, __LINE__);
+ //no enough data
+ return -2;
+ }
+
+ return return_len;
+}
+
+wake_lock_ctx wlock_ctx;
+
+void mnldinf_wake_lock() {
+ int fd = open("/sys/power/wake_lock", O_RDWR | O_NONBLOCK);
+ if(fd == -1) {
+ LOGE("open() failed, reason=[%s]%d", strerror(errno), errno);
+ return;
+ }
+
+ int ret = write(fd, MNLDINF_WAKE_LOCK_ID, strlen(MNLDINF_WAKE_LOCK_ID));
+ if(ret == -1) {
+ LOGE("write() failed id=[%s], reason=[%s]%d", MNLDINF_WAKE_LOCK_ID, strerror(errno), errno);
+ close(fd);
+ return;
+ }
+
+ close(fd);
+
+ return;
+}
+
+void mnldinf_wake_unlock() {
+ int fd = open("/sys/power/wake_unlock", O_RDWR | O_NONBLOCK);
+ if(fd == -1) {
+ LOGE("open() failed, reason=[%s]%d", strerror(errno), errno);
+ return;
+ }
+
+ int ret = write(fd, MNLDINF_WAKE_LOCK_ID, strlen(MNLDINF_WAKE_LOCK_ID));
+ if(ret == -1) {
+ LOGE("write() failed id=[%s], reason=[%s]%d", MNLDINF_WAKE_LOCK_ID, strerror(errno), errno);
+ close(fd);
+ return;
+ }
+
+ close(fd);
+
+ return;
+}
+
+int mnldinf_wakeup_mutex_lock() {
+ int ret = pthread_mutex_lock(&wlock_ctx.mutex);
+ if(ret != 0) {
+ LOGE("pthread_mutex_lock() failed, reason=[%s]%d", strerror(ret), ret);
+ }
+
+ return ret;
+}
+
+int mnldinf_wakeup_mutex_unlock() {
+ int ret = pthread_mutex_unlock(&wlock_ctx.mutex);
+ if(ret != 0) {
+ LOGE("pthread_mutex_unlock() failed, reason=[%s]%d", strerror(ret), ret);
+ }
+
+ return ret;
+}
+
+void mnldinf_wake_lock_take() {
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+ time_t time_cur = 0;
+ time_cur = mnldinf_get_time_in_millisecond();
+
+ if(time_cur > (wlock_ctx.time_last_refresh + MNLDINF_WAKE_LOCK_LATENCY)) {
+ int mutex_ret = 0;
+ mnldinf_stop_timer(wlock_ctx.unlock_timer);
+ mutex_ret = mnldinf_wakeup_mutex_lock();
+ if(wlock_ctx.wake_lock_acquired == false) {
+ wlock_ctx.wake_lock_acquired = true;
+ mnldinf_wake_lock();
+ }
+ if(mutex_ret == 0) {
+ mnldinf_wakeup_mutex_unlock();
+ }
+ }
+#endif
+}
+
+void mnldinf_wake_lock_give() {
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+ time_t time_cur = 0;
+ //delay to do wake_unlock to ensure the msg can be deliveried to other process
+ time_cur = mnldinf_get_time_in_millisecond();
+ if(time_cur > (wlock_ctx.time_last_refresh + MNLDINF_WAKE_LOCK_LATENCY)) { //Only refresh timer when over latency time
+ mnldinf_start_timer(wlock_ctx.unlock_timer, MNLDINF_WAKE_LOCK_TIMEOUT);
+ wlock_ctx.time_last_refresh = mnldinf_get_time_in_millisecond();
+ }
+#endif
+}
+
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+static void mnldinf_timer_wake_unlock_routine(int id) {
+ int mutex_ret = 0;
+ //do not use the internal msg or it will cause infinite loop in epoll_wait
+ mutex_ret = mnldinf_wakeup_mutex_lock();
+ if(wlock_ctx.wake_lock_acquired == true) {
+ wlock_ctx.wake_lock_acquired = false;
+ mnldinf_wake_unlock();
+ }
+ if(mutex_ret == 0) {
+ mnldinf_wakeup_mutex_unlock();
+ }
+}
+#endif
+
+void mnldinf_wake_lock_init() {
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+ int ret = 0;
+ int read_len = 0;
+ char buff_read[HAL_MNL_BUFF_SIZE] = {0};
+
+ int fd = open("/sys/power/wake_lock", O_RDWR | O_NONBLOCK);
+ if(fd == -1) {
+ LOGE("open() failed, reason=[%s]%d", strerror(errno), errno);
+ return;
+ }
+
+ read_len = read(fd, buff_read, sizeof(buff_read)-1);
+ buff_read[HAL_MNL_BUFF_SIZE -1] = 0;
+ if(read_len >= strlen(MNLDINF_WAKE_LOCK_ID) && strstr(buff_read, MNLDINF_WAKE_LOCK_ID) != NULL) {
+ mnldinf_wake_unlock();
+ }
+ LOGD("wake_lock:[%s]", buff_read);
+ close(fd);
+
+ memset(&wlock_ctx, 0, sizeof(wlock_ctx));
+ wlock_ctx.wake_lock_acquired = false;
+ wlock_ctx.unlock_timer = mnldinf_init_timer(mnldinf_timer_wake_unlock_routine);
+ if(wlock_ctx.unlock_timer == INVALID_TIMERID) {
+ LOGE("init_timer(mnldinf_timer_wake_unlock_routine, 0) failed");
+ exit(1);
+ }
+
+ ret = pthread_mutex_init(&wlock_ctx.mutex, NULL);
+ if(ret != 0) {
+ LOGE("pthread_mutex_init() failed, reason=[%s]%d", strerror(errno), errno);
+ exit(1);
+ }
+#endif
+}
+
+void mnldinf_wake_lock_deinit() {
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+ int read_len = 0;
+ char buff_read[HAL_MNL_BUFF_SIZE] = {0};
+ timer_t retry_timer;
+
+ int fd = open("/sys/power/wake_lock", O_RDWR | O_NONBLOCK);
+ if(fd == -1) {
+ LOGE("open() failed, reason=[%s]%d", strerror(errno), errno);
+ return;
+ }
+
+ read_len = read(fd, buff_read, sizeof(buff_read)-1);
+ buff_read[HAL_MNL_BUFF_SIZE -1] = 0;
+ if(read_len >= strlen(MNLDINF_WAKE_LOCK_ID) && strstr(buff_read, MNLDINF_WAKE_LOCK_ID) != NULL) {
+ mnldinf_wake_unlock();
+ }
+ LOGD("wake_lock:[%s]", buff_read);
+ close(fd);
+ retry_timer = wlock_ctx.unlock_timer;
+ wlock_ctx.unlock_timer = INVALID_TIMERID;
+ mnldinf_deinit_timer(retry_timer);
+ pthread_mutex_destroy(&wlock_ctx.mutex);
+#endif
+}
+
diff --git a/src/connectivity/gps/2.0/gps_hal/mnldinf/test/Makefile b/src/connectivity/gps/2.0/gps_hal/mnldinf/test/Makefile
new file mode 100644
index 0000000..2778181
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/mnldinf/test/Makefile
@@ -0,0 +1,53 @@
+CC=gcc
+CXX=g++
+
+FLAGS=\
+ -g \
+ -Wall \
+ -D __COMPILE_OPTION__ \
+ -D __LINUX_OS__ \
+
+# -m32 \
+
+CPPFLAGS=\
+ -std=c++11 \
+
+INCLUDE=\
+ -I./ \
+ -I../inc/ \
+
+LIBS=\
+ -ldl \
+ -lrt \
+ -lpthread \
+
+CXXSRC=\
+
+CSRC=\
+ mnldinf_client.c \
+ ../src/mnldinf_data_coder.c \
+ ../src/mnldinf_basic.c \
+ ../src/mnldinf_ext.c \
+ ../src/mnldinf_log.c \
+ ../src/mnldinf_utility.c
+
+EXECUTABLE=mnldinf_test
+COBJS=$(CSRC:.c=.o)
+CXXOBJS=$(CXXSRC:.cpp=.o)
+
+all: $(EXECUTABLE)
+
+$(EXECUTABLE): $(COBJS) $(CXXOBJS)
+ $(CC) $(COBJS) $(CXXOBJS) $(LIBS) $(FLAGS) $(CPPFLAGS) -o $@
+
+%.o : %.c
+ $(CC) -c $(FLAGS) $(INCLUDE) -o $@ $<
+
+%.o : %.cpp
+ $(CC) -c $(FLAGS) $(INCLUDE) $(CPPFLAGS) -o $@ $<
+
+.PHONY: clean
+clean:
+ rm -f $(EXECUTABLE) rm -rf *.o
+ rm -rf $(COBJS)
+
diff --git a/src/connectivity/gps/2.0/gps_hal/mnldinf/test/mnldinf_client.c b/src/connectivity/gps/2.0/gps_hal/mnldinf/test/mnldinf_client.c
new file mode 100644
index 0000000..c1293f0
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/mnldinf/test/mnldinf_client.c
@@ -0,0 +1,337 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <sys/epoll.h> //epoll
+
+#include "mnldinf_ext.h"
+#include "mnldinf_basic.h"
+
+#include "mnldinf_utility.h"
+#include "mnldinf_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnldinftest"
+#endif
+#define MNLD_TEST "mnldinf_test"
+
+#define MAX_EPOLL_EVENT 10
+
+int mnldinf_basic_fd = -1;
+int mnldinf_ext_fd = -1;
+
+//=========================================================
+
+void dump_gps_location(gps_location location) {
+ LOGD("[dump_gps_location]flags:%d, lat:%f, lng:%f, alt:%f, speed:%f, bearing:%f, h_accuracy:%f, v_acc:%f, s_acc:%f, b_acc:%f, timestamp:%ld, pdop:%.2f, hdop:%.2f, vdop:%.2f"
+ , location.flags, location.lat, location.lng, location.alt, location.speed, location.bearing
+ , location.h_accuracy, location.v_accuracy, location.s_accuracy, location.b_accuracy, location.timestamp
+ , location.pdop, location.hdop, location.vdop);
+}
+
+void dump_gnss_sv_info(gnss_sv_info sv) {
+ unsigned int i = 0;
+ LOGD("[dump_gnss_sv_info], sv_num:%d", sv.num_svs);
+ for(i = 0; i < sv.num_svs; i++) {
+ LOGD("SV[%d], cons:%d, Cn0dBHz:%f, elev:%f, azim:%f, flags:%d, cf:%f"
+ , sv.sv_list[i].svid, sv.sv_list[i].constellation, sv.sv_list[i].c_n0_dbhz, sv.sv_list[i].elevation
+ , sv.sv_list[i].azimuth, sv.sv_list[i].flags, sv.sv_list[i].carrier_frequency);
+ }
+}
+
+static void update_location(gps_location location) {
+ LOGD("");
+ dump_gps_location(location);
+}
+
+static void update_gps_status(gps_status status) {
+ LOGD("status=%d", status);
+}
+
+static void update_gps_sv(gnss_sv_info sv) {
+ LOGD("");
+ dump_gnss_sv_info(sv);
+}
+
+#define MNLD_TEST_CMD_CNT_MAX 5
+#define GPS_DELETE_EPHEMERIS 0x0001
+#define GPS_DELETE_ALMANAC 0x0002
+#define GPS_DELETE_POSITION 0x0004
+#define GPS_DELETE_TIME 0x0008
+#define GPS_DELETE_IONO 0x0010
+#define GPS_DELETE_UTC 0x0020
+#define GPS_DELETE_HEALTH 0x0040
+#define GPS_DELETE_SVDIR 0x0080
+#define GPS_DELETE_SVSTEER 0x0100
+#define GPS_DELETE_SADATA 0x0200
+#define GPS_DELETE_RTI 0x0400
+#define GPS_DELETE_CELLDB_INFO 0x8000
+#define GPS_DELETE_ALL 0xFFFF
+
+#define DUMP_BASIC_CAP(cap) do {\
+ LOGD("[%s]:gnss_support=%d", __func__, (cap)->support_gnss);\
+} while(0)
+
+#define DUMP_EXT_CAP(cap) do {\
+ LOGD("[%s]:gnss_support=%d", __func__, (cap)->support_gnss);\
+} while(0)
+
+static void update_nmea(int64_t timestamp, const char* nmea, int length) {
+ static int nmea_cnt = 100;
+ static int test_cnt = 1024;
+ /*LOGD("timestamp=%ld nmea=[%s] length=%d",
+ timestamp, nmea, length);*/
+ if(test_cnt > 0 && nmea_cnt-- == 0 && mnldinf_basic_fd > 0) {
+ if(test_cnt-- >= 0) {
+ mnldinf_basic_gnss_stop(mnldinf_basic_fd);
+ mnldinf_basic_gnss_cleanup(mnldinf_basic_fd);
+ LOGD("GPS restart cnt(%d)", 1024-test_cnt);
+
+ switch(test_cnt%4) {
+ case 0: //Hot
+ mnldinf_ext_gnss_delete_aiding_data(mnldinf_ext_fd, GPS_DELETE_RTI);
+ break;
+ case 1: //Warm
+ mnldinf_ext_gnss_delete_aiding_data(mnldinf_ext_fd, GPS_DELETE_EPHEMERIS);
+ break;
+ case 2: //Cold
+ mnldinf_ext_gnss_delete_aiding_data(mnldinf_ext_fd, GPS_DELETE_EPHEMERIS |
+ GPS_DELETE_POSITION | GPS_DELETE_TIME | GPS_DELETE_IONO |
+ GPS_DELETE_UTC | GPS_DELETE_HEALTH);
+ break;
+ case 3: //Full
+ mnldinf_ext_gnss_delete_aiding_data(mnldinf_ext_fd, GPS_DELETE_ALL);
+ break;
+ default:
+ mnldinf_ext_gnss_delete_aiding_data(mnldinf_ext_fd, GPS_DELETE_RTI);
+ break;
+ }
+ mnldinf_basic_gnss_init(mnldinf_basic_fd);
+ mnldinf_basic_gnss_start(mnldinf_basic_fd);
+
+ mnldinf_ext_set_ttff_acc(mnldinf_ext_fd, test_cnt%3);
+ nmea_cnt = 100; //Reset nmea_cnt
+ }
+ }
+}
+
+static void update_nmea_done(void) {
+ LOGD("NMEA Done!!!");
+}
+
+static void update_gnss_measurements(gnss_data *data) {
+ LOGD("");
+ //dump_gnss_data(data);
+}
+
+static void basic_capability_update(mnldinf_basic_server_cap *cap) {
+ mnldinf_basic_server_cap basic_server_cap;
+ mnldinf_basic_client_cap basic_client_cap = {
+ .support_gnss = true,
+ };
+
+ memcpy(&basic_server_cap, cap, sizeof(mnldinf_basic_server_cap));
+ mnldinf_basic_capability_config(mnldinf_basic_fd, &basic_client_cap);
+ DUMP_BASIC_CAP(&basic_client_cap);
+}
+
+static void ext_capability_update(mnldinf_ext_server_cap *cap) {
+ mnldinf_ext_server_cap ext_server_cap;
+ mnldinf_ext_client_cap ext_client_cap = {
+ .support_gnss = true,
+ };
+
+ memcpy(&ext_server_cap, cap, sizeof(mnldinf_ext_server_cap));
+ mnldinf_ext_capability_config(mnldinf_ext_fd, &ext_client_cap);
+ DUMP_EXT_CAP(&ext_client_cap);
+}
+
+static void update_gnss_navigation(gnss_nav_msg *msg) {
+ LOGD("");
+ //dump_gnss_nav_msg(msg);
+}
+
+static void request_wakelock() {
+ LOGD("");
+}
+static void release_wakelock() {
+ LOGD("");
+}
+static void request_utc_time() {
+ LOGD("");
+}
+static void request_data_conn(struct sockaddr_storage* addr, agps_type type) {
+ LOGD("");
+}
+static void release_data_conn() {
+ LOGD("");
+}
+static void request_ni_notify(int session_id, agps_ni_type ni_type, agps_notify_type type, const char* requestor_id,
+ const char* client_name, ni_encoding_type requestor_id_encoding,
+ ni_encoding_type client_name_encoding) {
+ /*LOGD(" session_id=%d type=%d requestor_id=[%s] client_name=[%s] requestor_id_encoding=%d client_name_encoding=%d",
+ session_id, type, requestor_id, client_name, requestor_id_encoding, client_name_encoding);*/
+ LOGD("");
+}
+static void request_set_id(request_setid flags) {
+ //LOGD(" flags=0x%x", flags);
+ LOGD("");
+}
+static void request_ref_loc(request_refloc flags) {
+ //LOGD(" flags=0x%x", flags);
+ LOGD("");
+}
+static void output_vzw_debug(const char* str) {
+ LOGD("");
+}
+
+static void update_gnss_name(const char* name, int length) {
+ LOGD("length=%d, name=%s", length, name);
+ LOGD("");
+}
+
+static void request_nlp(bool independent_from_gnss, bool is_user_emergency) {
+ LOGD("request nlp[%d], emergency:%d", independent_from_gnss, is_user_emergency);
+}
+
+void mnldtest_nfw_access_notify(mnldinf_nfw_notification nfw_notify) {
+ LOGD("");
+}
+
+void mnldtest_basic_connection_broken() {
+ LOGD("");
+}
+
+void mnldtest_ext_connection_broken() {
+ LOGD("");
+}
+
+void mnldtest_ext_agps_location_update(mnldinf_agps_location location){
+ LOGD("lat:%f, lng:%f, %lld, type:%d", location.latitude, location.longitude, location.timestamp, location.type);
+}
+
+static mnldinf_ext mnldinf_ext_cbs = {
+ mnldtest_ext_connection_broken,
+ request_wakelock,
+ release_wakelock,
+
+ request_utc_time,
+ request_nlp,
+ request_ni_notify,
+ request_data_conn,
+ release_data_conn,
+
+ request_set_id,
+ request_ref_loc,
+ output_vzw_debug,
+
+ update_gnss_name,
+ update_gnss_navigation,
+ mnldtest_nfw_access_notify,
+ ext_capability_update,
+ mnldtest_ext_agps_location_update,
+};
+
+static mnldinf_basic mnldinf_basic_cbs = {
+ mnldtest_basic_connection_broken,
+ update_location,
+ update_gps_status,
+ update_gps_sv,
+ update_nmea,
+ update_nmea_done,
+ update_gnss_measurements,
+ basic_capability_update,
+};
+
+static void mnld_client_stdin_hdlr(int fd) {
+
+}
+
+int main() {
+ LOGD("mnld interface start, version 1.00");
+
+ mnldinf_basic_fd = mnldinf_basic_register(MNLD_TEST);
+ if(mnldinf_basic_fd == -1) {
+ LOGE("mnldinf_basic_register failed: %s", strerror(errno));
+ exit(1);
+ }
+
+ mnldinf_ext_fd = mnldinf_ext_register(MNLD_TEST);
+ if(mnldinf_ext_fd == -1) {
+ LOGE("mnldinf_ext_register failed: %s", strerror(errno));
+ exit(1);
+ }
+
+ struct epoll_event events[MAX_EPOLL_EVENT];
+ int epfd = epoll_create(MAX_EPOLL_EVENT);
+ if(epfd == -1) {
+ LOGE("epoll_create() failed");
+ exit(1);
+ }
+
+ mnldinf_epoll_add_fd(epfd, mnldinf_basic_fd);
+ mnldinf_epoll_add_fd(epfd, mnldinf_ext_fd);
+
+ mnldinf_epoll_add_fd(epfd, STDIN_FILENO);
+
+ mnldinf_basic_gnss_init(mnldinf_basic_fd);
+
+ mnldinf_basic_gnss_start(mnldinf_basic_fd);
+ mnldinf_basic_gnss_measurement_enable(mnldinf_basic_fd, 1);
+ mnldinf_ext_epo_enable(mnldinf_ext_fd, 0x1);
+ long long sv_bl = 0xFAFA;
+ mnldinf_ext_set_sv_blacklist(mnldinf_ext_fd, &sv_bl, 16);
+
+ while(true) {
+ int i, n;
+ LOGD("wait event");
+ n = epoll_wait(epfd, events, MAX_EPOLL_EVENT, -1);
+ if(n == -1) {
+ if(errno == EINTR) {
+ continue;
+ } else {
+ LOGE("epoll_wait() failed reason=[%s]%d", strerror(errno), errno);
+ crash_with_log();
+ }
+ }
+
+ for(i = 0; i < n; i++) {
+ int fd = events[i].data.fd;
+ if(fd == mnldinf_basic_fd) {
+ if(events[i].events & EPOLLIN) {
+ LOGD("basic hdlr");
+ mnldinf_basic_cmd_hdlr(fd, &mnldinf_basic_cbs);
+ }
+ } else if(fd == mnldinf_ext_fd) {
+ if(events[i].events & EPOLLIN) {
+ LOGD("ext hdlr");
+ mnldinf_ext_cmd_hdlr(fd, &mnldinf_ext_cbs);
+ }
+ } else if(fd == STDIN_FILENO) {
+ if(events[i].events & EPOLLIN) {
+ mnld_client_stdin_hdlr(fd);
+ goto exit;
+ }
+ } else {
+ LOGE("unexpected fd=%d coming", fd);
+ crash_with_log();
+ }
+ }
+
+ }
+exit:
+ close(epfd);
+ close(mnldinf_basic_fd);
+ close(mnldinf_ext_fd);
+ return 0;
+}
diff --git a/src/connectivity/gps/2.0/gps_hal/mnldinf/test/mnldinf_test.h b/src/connectivity/gps/2.0/gps_hal/mnldinf/test/mnldinf_test.h
new file mode 100644
index 0000000..eb0de93
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/mnldinf/test/mnldinf_test.h
@@ -0,0 +1,81 @@
+#ifndef __MNLD_TEST_H__
+#define __MNLD_TEST_H__
+
+#include"hal_mnl_interface_common.h"
+#include"gps_mtk.h"
+
+#define MNLD_TEST_CMD_OPEN "start"
+#define MNLD_TEST_CMD_CLOSE "stop"
+#define MNLD_TEST_CMD_NETWORK "network"
+#define MNLD_TEST_NETWORK_WIFI "wifi"
+#define MNLD_TEST_NETWORK_MOBILE "mobile"
+#define MNLD_TEST_NETWORK_ROAMING "roaming"
+#define MNLD_TEST_NETWORK_DISABLE "disable"
+
+#define MNL_VER_LEN 52
+#define MNL_UTC_TIME_LEN 11
+#define MNLD_TEST_TTFF_SESSION_BEGIN
+
+typedef enum{
+ MNLD_TEST_ACTION_UNKNOWN = -1,
+ MNLD_TEST_ACTION_GNSS_OPEN,
+ MNLD_TEST_ACTION_GNSS_CLOSE,
+ MNLD_TEST_ACTION_SET_NETWORK,
+ MNLD_TEST_ACTION_MAX
+} MNLD_TEST_ACTION;
+
+typedef enum{
+ MNLD_TEST_RESTART_TYPE_UNKNOWN = -1,
+ MNLD_TEST_RESTART_TYPE_HOT,
+ MNLD_TEST_RESTART_TYPE_WARM,
+ MNLD_TEST_RESTART_TYPE_COLD,
+ MNLD_TEST_RESTART_TYPE_FULL,
+ MNLD_TEST_RESTART_TYPE_MAX
+} MNLD_TEST_RESTART_TYPE;
+
+typedef enum{
+ CURR = 0,
+ MIN = 1,
+ MAX = 2,
+ MEAN = 3,
+ TTFF_NUM
+}MNLD_TEST_TTFF;
+
+typedef struct {
+ char chip_ver[12];
+ char mnl_ver[MNL_VER_LEN];
+ char clk_type;
+ char clk_buff;
+ int ttff[TTFF_NUM];//time-to-first_fix in ms
+ int fix_type;
+ GpsLocation_ext location;
+ char utc_time[MNL_UTC_TIME_LEN];
+}mnld_test_result;
+
+typedef struct{
+ char type_int;
+ char type_str[10];
+}clock_type;
+
+#define MNLD_TEST_CMD_CNT_MAX 5
+#define GPS_DELETE_EPHEMERIS 0x0001
+#define GPS_DELETE_ALMANAC 0x0002
+#define GPS_DELETE_POSITION 0x0004
+#define GPS_DELETE_TIME 0x0008
+#define GPS_DELETE_IONO 0x0010
+#define GPS_DELETE_UTC 0x0020
+#define GPS_DELETE_HEALTH 0x0040
+#define GPS_DELETE_SVDIR 0x0080
+#define GPS_DELETE_SVSTEER 0x0100
+#define GPS_DELETE_SADATA 0x0200
+#define GPS_DELETE_RTI 0x0400
+#define GPS_DELETE_CELLDB_INFO 0x8000
+#define GPS_DELETE_ALL 0xFFFF
+
+GpsCallbacks_ext* mnld_test__get_gps_callbacks(void);
+//GpsInterface* gps_device__get_gps_interface(struct gps_device_t* device);
+
+void mnld_test_show_test_result(mnld_test_result* result);
+void mnld_test_get_mnl_ver(void);
+
+#endif //__MNLD_TEST_H__
diff --git a/src/connectivity/gps/2.0/gps_hal/src/agpsinf.c b/src/connectivity/gps/2.0/gps_hal/src/agpsinf.c
new file mode 100644
index 0000000..0a7e019
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/src/agpsinf.c
@@ -0,0 +1,208 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include "gpshal.h"
+#include "hal2mnl_interface.h"
+#include "mtk_lbs_utility.h"
+#include "errno.h"
+#include "inttypes.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "agpsinf"
+
+#ifdef __ANDROID_OS__
+#include <cutils/sockets.h>
+#include <log/log.h> /*logging in logcat*/
+#define LOGD(fmt, arg ...) ALOGD("%s: " fmt, __FUNCTION__ , ##arg)
+#define LOGW(fmt, arg ...) ALOGW("%s: " fmt, __FUNCTION__ , ##arg)
+#define LOGE(fmt, arg ...) ALOGE("%s: " fmt, __FUNCTION__ , ##arg)
+#else
+#include "mnldinf_log.h"
+#endif
+
+//=========================================================
+// Agps Interface
+
+static void agpsinf_init(AGpsCallbacks* callbacks) {
+ g_gpshal_ctx.agps_cbs = callbacks;
+}
+
+static int agpsinf_set_server(AGpsType type, const char* hostname, int port) {
+ if (hal2mnl_set_server(type, hostname, port) == -1) {
+ LOGE("hal2mnl_set_server failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ return 0; // 0:ok, non-zero: error; but GPS JNI will ignore it
+}
+
+static int agpsinf_data_conn_open_with_apn_ip_type(
+ uint64_t networkHandle,
+ const char* apn,
+ ApnIpType apnIpType) {
+ /// todo
+ if (hal2mnl_data_conn_open_with_apn_ip_type(networkHandle, apn, apnIpType) == -1) {
+ LOGE("hal2mnl_data_conn_open_with_apn_ip_type failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ return 0; // 0:ok, non-zero: error; but GPS JNI will ignore it
+}
+
+const AGpsInterface_ext mtk_agps_inf = {
+ sizeof(AGpsInterface_ext),
+ agpsinf_init,
+ hal2mnl_data_conn_open, // GPS JNI will ignore its ret value
+ hal2mnl_data_conn_closed, // GPS JNI will ignore its ret value
+ hal2mnl_data_conn_failed, // GPS JNI will ignore its ret value
+ agpsinf_set_server,
+ agpsinf_data_conn_open_with_apn_ip_type
+};
+
+
+//=========================================================
+// Gps Ni Interface
+
+static void gpsni_init(GpsNiCallbacks *callbacks) {
+ g_gpshal_ctx.gpsni_cbs = callbacks;
+}
+
+static void gpsni_respond(int notif_id, GpsUserResponseType user_response) {
+ if (hal2mnl_ni_respond(notif_id, user_response) == -1) {
+ LOGE("hal2mnl_ni_respond failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+const GpsNiInterface mtk_gps_ni_inf = {
+ sizeof(GpsNiInterface),
+ gpsni_init,
+ gpsni_respond
+};
+
+
+//=========================================================
+// Agps Ril Interface
+
+static void agps_ril_init(AGpsRilCallbacks* callbacks) {
+ g_gpshal_ctx.agpsril_cbs = callbacks;
+}
+
+static void agps_ril_set_ref_location(
+ const AGpsRefLocation *agps_reflocation,
+ __unused size_t sz_struct) {
+ // UNUSED(sz_struct);
+ uint16_t type = agps_reflocation->type;
+ switch (type) {
+ case AGPS_REF_LOCATION_TYPE_GSM_CELLID:
+ case AGPS_REF_LOCATION_TYPE_UMTS_CELLID: {
+ const AGpsRefLocationCellID cell = agps_reflocation->u.cellID;
+ if (hal2mnl_set_ref_location(type, cell.mcc, cell.mnc, cell.lac, cell.cid) == -1) {
+ LOGE("hal2mnl_set_ref_location failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ break;
+ }
+ // case AGPS_REG_LOCATION_TYPE_MAC:
+ // TODO: to support MAC when GPS JNI can support it
+ // break;
+ default:
+ LOGW("%s: unsupported ref loc type: %d", __func__, type);
+ }
+}
+
+static void agps_ril_set_set_id(AGpsSetIDType type, const char* setid) {
+ if (hal2mnl_set_id(type, setid) == -1) {
+ LOGE("hal2mnl_set_id failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void agps_ril_ni_message(uint8_t *msg, size_t len) {
+ if (hal2mnl_ni_message((char*)msg, len) == -1) {
+ LOGE("hal2mnl_ni_message failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void agps_ril_update_network_state(uint64_t networkHandle, bool isConnected,
+ uint16_t capabilities, const char* apn) {
+ /// todo
+ LOGD("agps_ril_update_network_state networkHandle=%"PRId64" isConnected=%d capabilities=%d apn=[%s]",
+ networkHandle, isConnected, capabilities, apn);
+ //hal2mnl_update_network_state(connected, type, roaming, extra_info); //before Android Q
+ if (hal2mnl_update_network_state(networkHandle, isConnected, capabilities, apn) == -1) {
+ LOGE("hal2mnl_update_network_state failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void agps_ril_update_network_availability(int available, const char* apn) {
+ if (hal2mnl_update_network_availability(available, apn) == -1) {
+ LOGE("hal2mnl_update_network_availability failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+const AGpsRilInterface_ext mtk_agps_ril_inf = {
+ sizeof(AGpsRilInterface_ext),
+ agps_ril_init,
+ agps_ril_set_ref_location,
+ agps_ril_set_set_id,
+ agps_ril_ni_message,
+ agps_ril_update_network_state,
+ agps_ril_update_network_availability
+};
+
+//=========================================================
+// Supl Certificate Interface
+
+#if 0 // not ready, even in GPS JNI
+static int suplcert_install_certificates(
+ __unused const DerEncodedCertificate* certificates,
+ __unused size_t length) {
+ UNUSED_VAR(certificates);
+ UNUSED_VAR(length);
+ // TODO: to use the new hal2mnl lib
+ return -1;
+}
+
+static int suplcert_revoke_certificates(
+ __unused const Sha1CertificateFingerprint* fingerprints,
+ __unused size_t length) {
+ UNUSED_VAR(fingerprints);
+ UNUSED_VAR(length);
+ // TODO: to use the new hal2mnl lib
+ return -1;
+}
+
+const SuplCertificateInterface mtk_supl_cert_inf = {
+ sizeof(SuplCertificateInterface),
+ suplcert_install_certificates,
+ suplcert_revoke_certificates,
+};
+#endif
+
diff --git a/src/connectivity/gps/2.0/gps_hal/src/gpshal.c b/src/connectivity/gps/2.0/gps_hal/src/gpshal.c
new file mode 100644
index 0000000..a3ef028
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/src/gpshal.c
@@ -0,0 +1,254 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include "gpshal.h"
+#include <sys/epoll.h> // epoll_create, epoll_event
+#include <errno.h> // errno
+#include <string.h> // strerror
+#include "hal2mnl_interface.h"
+#include "mtk_lbs_utility.h"
+#ifdef __ANDROID_OS__
+#include <cutils/properties.h>
+#endif
+#include <sys/time.h>
+#if 0
+#ifdef LOGD
+#undef LOGD
+#endif
+#ifdef LOGW
+#undef LOGW
+#endif
+#ifdef LOGE
+#undef LOGE
+#endif
+#if 0
+#define LOGD(...) tag_log(1, "[gpshal]", __VA_ARGS__);
+#define LOGW(...) tag_log(1, "[gpshal] WARNING: ", __VA_ARGS__);
+#define LOGE(...) tag_log(1, "[gpshal] ERR: ", __VA_ARGS__);
+#else
+#define LOG_TAG "gpshal"
+#include <cutils/sockets.h>
+#include <log/log.h> /*logging in logcat*/
+#define LOGD(fmt, arg ...) ALOGD("%s: " fmt, __FUNCTION__ , ##arg)
+#define LOGW(fmt, arg ...) ALOGW("%s: " fmt, __FUNCTION__ , ##arg)
+#define LOGE(fmt, arg ...) ALOGE("%s: " fmt, __FUNCTION__ , ##arg)
+#endif
+#endif
+#define GPSHAL_WORKER_THREAD_NAME "gpshal_worker_thread"
+//=========================================================
+
+gpshal_context_t g_gpshal_ctx = {
+ .fd_mnl2hal_basic = -1,
+ .fd_mnl2hal_ext = -1,
+ .fd_worker_epoll = -1,
+ .thd_worker = 0,
+ .mutex_gps_state_intent = PTHREAD_MUTEX_INITIALIZER,
+ .gps_state_intent = GPSHAL_STATE_UNKNOWN,
+ .gps_state = GPSHAL_STATE_UNKNOWN,
+ .gps_cbs = NULL,
+ .agps_cbs = NULL,
+ .gpsni_cbs = NULL,
+ .agpsril_cbs = NULL,
+ .meas_cbs = NULL,
+ .navimsg_cbs = NULL,
+ .geofence_cbs = NULL,
+ .vzw_debug_cbs = NULL,
+ .gps_name = "MTK_MNLD_default,MNL_VER_default",
+ .proxy_apps = {0},
+ .mnl_retry_timer = NULL,
+};
+
+#ifdef FREQUENCE_START
+struct timeval g_last_start_time = {
+ .tv_sec = 0,
+ .tv_usec = 0,
+};
+#endif
+//=========================================================
+
+const char* gpshal_state_to_string(gpshal_state state) {
+ switch (state) {
+ case GPSHAL_STATE_UNKNOWN: return "UNKNOWN";
+ case GPSHAL_STATE_RESOURCE: return "RESOURCE_INIT";
+ case GPSHAL_STATE_CLEANUP: return "CLEANUP";
+ case GPSHAL_STATE_INIT: return "INIT";
+ case GPSHAL_STATE_STOP: return "STOP";
+ case GPSHAL_STATE_START: return "START";
+ default: return "INVALID";
+ }
+}
+
+static void gpshal_set_gps_state(gpshal_state newState) {
+ /*LOGD("gps_state: %s -> %s (intent: %s)",
+ gpshal_state_to_string(g_gpshal_ctx.gps_state),
+ gpshal_state_to_string(newState),
+ gpshal_state_to_string(g_gpshal_ctx.gps_state_intent));*/
+ g_gpshal_ctx.gps_state = newState;
+}
+
+void gpshal_set_gps_state_intent(gpshal_state newState) {
+ /*LOGD("gps_state: %s (intent: %s -> %s)",
+ gpshal_state_to_string(g_gpshal_ctx.gps_state),
+ gpshal_state_to_string(g_gpshal_ctx.gps_state_intent),
+ gpshal_state_to_string(newState));*/
+ g_gpshal_ctx.gps_state_intent = newState;
+}
+
+static void gpshal_check_capability(unsigned int *capabilities, unsigned int *year) {
+ *year = 2020;
+ *capabilities = (GPS_CAP_MEASUREMENTS | GPS_CAP_MSB | GPS_CAP_MSA
+ | GPS_CAP_LOW_POWER_MODE | GPS_CAP_SATELLITE_BLACKLIST | GPS_CAP_CORRECTION);
+}
+//=========================================================
+
+// Design policy
+// Init resources at most once (no retry)
+// Because we can not save an unstable system,
+// we think "less system call is better" for an unstable system
+// Do not deinit resources
+// We want to have a simple design for a built-in service
+// "Deinit" is for an installable / removable service
+static void gpshal_resource_init(GpsCallbacks_ext* src) {
+ unsigned int capabilities = 0;
+ unsigned int year = 0;
+ char *name = g_gpshal_ctx.gps_name;//"Version: MNLD, MNL";
+ g_gpshal_ctx.gps_cbs = (GpsCallbacks_ext*)src;
+
+ gpshal_check_capability(&capabilities, &year);
+ LOGD("year = %d, capabilities = 0x%x, name = %s", year, capabilities, name);
+ g_gpshal_ctx.gps_cbs->set_capabilities_cb(capabilities);
+ g_gpshal_ctx.gps_cbs->set_name_cb(name, strlen(name));
+
+ GnssSystemInfo system_info;
+ system_info.year_of_hw = year;
+ system_info.size = sizeof(GnssSystemInfo);
+ g_gpshal_ctx.gps_cbs->set_system_info_cb(&system_info);
+
+ if (GPSHAL_STATE_UNKNOWN != g_gpshal_ctx.gps_state_intent) return; // at most once
+
+ g_gpshal_ctx.fd_mnl2hal_basic = create_mnl2hal_fd_basic();
+ if (-1 == g_gpshal_ctx.fd_mnl2hal_basic) return; // error
+
+ g_gpshal_ctx.fd_mnl2hal_ext = create_mnl2hal_fd_ext();
+ if (-1 == g_gpshal_ctx.fd_mnl2hal_ext) return; // error
+
+ g_gpshal_ctx.fd_worker_epoll = epoll_create(MAX_EPOLL_EVENT);
+ if (-1 == g_gpshal_ctx.fd_worker_epoll) {
+ LOGE("Fail to create epoll reason=[%s]%d",
+ strerror(errno), errno);
+ return; // error
+ }
+
+ if (mnldinf_epoll_add_fd(
+ g_gpshal_ctx.fd_worker_epoll,
+ g_gpshal_ctx.fd_mnl2hal_basic) == -1) {
+ LOGE("Fail to add fd_mnl2hal basic");
+ return; // error
+ }
+
+ if (mnldinf_epoll_add_fd(
+ g_gpshal_ctx.fd_worker_epoll,
+ g_gpshal_ctx.fd_mnl2hal_ext) == -1) {
+ LOGE("Fail to add fd_mnl2hal ext");
+ return; // error
+ }
+ g_gpshal_ctx.thd_worker = g_gpshal_ctx.gps_cbs->create_thread_cb(
+ GPSHAL_WORKER_THREAD_NAME, gpshal_worker_thread, NULL);
+ if (!g_gpshal_ctx.thd_worker) {
+ LOGE("Fail to create %s", GPSHAL_WORKER_THREAD_NAME);
+ return; // error
+ }
+
+ gpshal_set_gps_state(GPSHAL_STATE_RESOURCE);
+}
+
+int gpshal_gpscbs_save(GpsCallbacks_ext* src) {
+// assert(NULL != src);
+ if (sizeof(GpsCallbacks_ext) == src->size) {
+ LOGD("Use GpsCallbacks");
+ gpshal_resource_init(src);
+ return 0;
+ }
+ LOGE("Bad callback, size: %zd, expected: %zd",
+ src->size, sizeof(GpsCallbacks_ext));
+ return -1; // error
+}
+
+//=========================================================
+
+void gpshal2mnl_gps_init() {
+ if (GPSHAL_STATE_RESOURCE <= g_gpshal_ctx.gps_state) { // Check this for unstable system
+ if (hal2mnl_gps_init() > 0) {
+ gpshal_set_gps_state(GPSHAL_STATE_INIT);
+ }
+ }
+}
+
+void gpshal2mnl_gps_start() {
+ #ifdef FREQUENCE_START
+ struct timeval cur_tv;
+ #endif
+ if (GPSHAL_STATE_RESOURCE <= g_gpshal_ctx.gps_state) {
+ if (hal2mnl_gps_start() > 0) {
+ #ifdef FREQUENCE_START
+ gettimeofday(&cur_tv, NULL);
+ LOGD("cur_time:%ld.%03ld, last_time:%ld.%03ld", cur_tv.tv_sec, cur_tv.tv_usec/1000,
+ g_last_start_time.tv_sec, g_last_start_time.tv_usec/1000);
+ if (((cur_tv.tv_sec-g_last_start_time.tv_sec)*1000 +
+ (cur_tv.tv_usec-g_last_start_time.tv_usec)/1000) > 1000) {
+ LOGD("Sleep 1s");
+ msleep(1000);
+ }
+ gettimeofday(&g_last_start_time, NULL);
+ #endif
+ gpshal_set_gps_state(GPSHAL_STATE_START);
+ }
+ }
+}
+
+void gpshal2mnl_gps_stop() {
+ if (GPSHAL_STATE_RESOURCE <= g_gpshal_ctx.gps_state) {
+ if (hal2mnl_gps_stop() > 0) {
+ gpshal_set_gps_state(GPSHAL_STATE_STOP);
+ }
+ }
+}
+
+void gpshal2mnl_gps_cleanup() {
+ if (GPSHAL_STATE_RESOURCE <= g_gpshal_ctx.gps_state) {
+ if (hal2mnl_gps_cleanup() > 0) {
+ gpshal_set_gps_state(GPSHAL_STATE_CLEANUP);
+ }
+ }
+}
diff --git a/src/connectivity/gps/2.0/gps_hal/src/gpshal_worker.c b/src/connectivity/gps/2.0/gps_hal/src/gpshal_worker.c
new file mode 100644
index 0000000..d0a3031
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/src/gpshal_worker.c
@@ -0,0 +1,668 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include "gpshal.h"
+#include <sys/epoll.h> // epoll_create, epoll_event
+#include <errno.h> // errno
+#include <string.h> // strerror
+#include <inttypes.h>
+// #include <linux/in.h> // INADDR_NONE
+#include "hal2mnl_interface.h"
+#include "mtk_lbs_utility.h"
+#if 0
+#ifdef LOGD
+#undef LOGD
+#endif
+#ifdef LOGW
+#undef LOGW
+#endif
+#ifdef LOGE
+#undef LOGE
+#endif
+#if 0
+#define LOGD(...) tag_log(1, "[gpshal]", __VA_ARGS__);
+#define LOGW(...) tag_log(1, "[gpshal] WARNING: ", __VA_ARGS__);
+#define LOGE(...) tag_log(1, "[gpshal] ERR: ", __VA_ARGS__);
+#else
+#define LOG_TAG "gpshal_worker"
+#include <cutils/sockets.h>
+#include <log/log.h> /*logging in logcat*/
+#define LOGD(fmt, arg ...) ALOGD("%s: " fmt, __FUNCTION__ , ##arg)
+#define LOGW(fmt, arg ...) ALOGW("%s: " fmt, __FUNCTION__ , ##arg)
+#define LOGE(fmt, arg ...) ALOGE("%s: " fmt, __FUNCTION__ , ##arg)
+#endif
+#endif
+//=========================================================
+
+#define GPSHAL_WORKER_THREAD_TIMEOUT (30*1000)
+
+//connection broken retry interval, ms
+#define GPSHAL_MNL_RETRY_INTERVAL (1*1000)
+
+#define fieldp_copy(dst, src, f) (dst)->f = (src)->f
+#define field_copy(dst, src, f) (dst).f = (src).f
+
+//=========================================================
+DebugData mnlDebugData; //for GNSS HIDL v1.1 GPS debug interface
+
+extern float count;
+extern float report_time_interval;
+
+static void update_mnld_reboot() {
+// GPSHAL_DEBUG_FUNC_SCOPE2(g_gpshal_ctx.mutex_gps_state_intent);
+ gpshal_state state = g_gpshal_ctx.gps_state_intent;
+ LOGD("state: (%d)", state);
+
+ if (hal2mnl_set_nfw_access(g_gpshal_ctx.proxy_apps, strlen(g_gpshal_ctx.proxy_apps)) == -1) {
+ LOGE("hal2mnl_set_nfw_access failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ switch (state) {
+ case GPSHAL_STATE_INIT:
+ case GPSHAL_STATE_STOP:
+ gpshal2mnl_gps_init();
+ break;
+ case GPSHAL_STATE_START:
+ gpshal2mnl_gps_init();
+ gpshal2mnl_gps_start();
+ break;
+ case GPSHAL_STATE_CLEANUP:
+ default:
+ LOGW("Current gps_state_intent: %s (%d)",
+ gpshal_state_to_string(state), state);
+ }
+}
+
+static void gpshal_close(int fd) {
+ if(fd != -1) {
+ close(fd);
+ if(fd == g_gpshal_ctx.fd_mnl2hal_basic) {
+ g_gpshal_ctx.fd_mnl2hal_basic = -1;
+ LOGD("mnl2hal_basic fd closed.");
+ } else if(fd == g_gpshal_ctx.fd_mnl2hal_ext) {
+ g_gpshal_ctx.fd_mnl2hal_ext = -1;
+ LOGD("mnl2hal_ext fd closed.");
+ } else {
+ LOGE("unexpected fd=[%d] to be closed", fd);
+ }
+ }
+}
+
+void gpshal_mnl_retry_routine(void) {
+ gpshal_close(g_gpshal_ctx.fd_mnl2hal_basic);
+ gpshal_close(g_gpshal_ctx.fd_mnl2hal_ext);
+
+ g_gpshal_ctx.fd_mnl2hal_basic = create_mnl2hal_fd_basic();
+ if (-1 == g_gpshal_ctx.fd_mnl2hal_basic) { // error
+ LOGW("fd_mnl2hal_basic recreate fail, will retry after %d ms", GPSHAL_MNL_RETRY_INTERVAL);
+ mnldinf_start_timer(g_gpshal_ctx.mnl_retry_timer, GPSHAL_MNL_RETRY_INTERVAL);
+ } else {
+ if (mnldinf_epoll_add_fd(
+ g_gpshal_ctx.fd_worker_epoll,
+ g_gpshal_ctx.fd_mnl2hal_basic) == -1) {
+ LOGE("Fail to add fd_mnl2hal basic");
+ return; // error
+ }
+ }
+
+ g_gpshal_ctx.fd_mnl2hal_ext = create_mnl2hal_fd_ext();
+ if (-1 == g_gpshal_ctx.fd_mnl2hal_ext) { // error
+ LOGW("fd_mnl2hal_ext recreate fail, will retry after %d ms", GPSHAL_MNL_RETRY_INTERVAL);
+ mnldinf_start_timer(g_gpshal_ctx.mnl_retry_timer, GPSHAL_MNL_RETRY_INTERVAL);
+ } else {
+ if (mnldinf_epoll_add_fd(
+ g_gpshal_ctx.fd_worker_epoll,
+ g_gpshal_ctx.fd_mnl2hal_ext) == -1) {
+ LOGE("Fail to add fd_mnl2hal ext");
+ return; // error
+ }
+ }
+
+ if (-1 != g_gpshal_ctx.fd_mnl2hal_basic) {
+ update_mnld_reboot();
+ }
+}
+
+static void update_location(gps_location location) {
+
+ if (report_time_interval > ++count) {
+ LOGD("break location update, count is %f, interval is %f\n", count, report_time_interval);
+ return;
+ }
+
+ count = 0;
+ // Use mutex or not ?
+ // If no, the issue may occur.
+ // If yes, there will be a little performance impact.
+ // GPSHAL_DEBUG_FUNC_SCOPE;
+ GpsLocation_ext loc;
+ //dump_gps_location(location);
+ gpshal_state state = g_gpshal_ctx.gps_state;
+ memset(&loc, 0, sizeof(GpsLocation_ext));
+ //LOGD("state: (%d)", state);
+ if (GPSHAL_STATE_START == state) {
+ loc.legacyLocation.size = sizeof(loc);
+ loc.legacyLocation.flags = location.flags;
+ loc.legacyLocation.latitude = location.lat;
+ loc.legacyLocation.longitude = location.lng;
+ loc.legacyLocation.altitude = location.alt;
+ loc.legacyLocation.speed = location.speed;
+ loc.legacyLocation.bearing = location.bearing;
+ loc.legacyLocation.accuracy = loc.horizontalAccuracyMeters = location.h_accuracy;
+ loc.verticalAccuracyMeters = location.v_accuracy;
+ loc.speedAccuracyMetersPerSecond = location.s_accuracy;
+ loc.bearingAccuracyDegrees = location.b_accuracy;
+ loc.legacyLocation.timestamp = location.timestamp;
+
+ /// not report elapsed real time in mnld, it will be reported in frw.
+ loc.elapsedRealtime.flags = 0; //HAS_TIMESTAMP_NS | HAS_TIME_UNCERTAINTY_NS;
+ loc.elapsedRealtime.timestampNs = 0;
+ loc.elapsedRealtime.timeUncertaintyNs = 0;
+ loc.type = location.type;
+ LOGD("hacc=%f,vacc=%f,sacc=%f,bacc=%f, type:%u", loc.horizontalAccuracyMeters, loc.verticalAccuracyMeters,
+ loc.speedAccuracyMetersPerSecond, loc.bearingAccuracyDegrees, loc.type);
+ g_gpshal_ctx.gps_cbs->location_cb(&loc);
+ //For GNSS HIDL v1.1 Gps debug interface
+ mnlDebugData.position.valid = true;
+ mnlDebugData.position.latitudeDegrees = location.lat;
+ mnlDebugData.position.longitudeDegrees = location.lng;
+ mnlDebugData.position.altitudeMeters = location.alt;
+ mnlDebugData.position.speedMetersPerSec = location.speed;
+ mnlDebugData.position.bearingDegrees = location.bearing;
+ mnlDebugData.position.horizontalAccuracyMeters = location.h_accuracy;
+ mnlDebugData.position.verticalAccuracyMeters = location.v_accuracy;
+ mnlDebugData.position.speedAccuracyMetersPerSecond = location.s_accuracy;
+ mnlDebugData.position.bearingAccuracyDegrees = location.b_accuracy;
+ mnlDebugData.time.timeEstimate = location.timestamp;
+ } else {
+ // Do not report this location to GLP to avoid strange TTFF time issue
+ LOGW("we have a location when gps_state_intent: %s (%d)",
+ gpshal_state_to_string(state), state);
+ }
+}
+static void update_gps_status(gps_status status) {
+ GpsStatus s;
+ memset(&s, 0, sizeof(GpsStatus));
+ LOGD(" status=%d", status);
+ s.size = sizeof(s);
+ s.status = status;
+ g_gpshal_ctx.gps_cbs->status_cb(&s);
+}
+
+static void update_gps_sv(gnss_sv_info sv) {
+
+ // GPSHAL_DEBUG_FUNC_SCOPE;
+ int i;
+ GnssSvStatus_ext gss;
+ //dump_gnss_sv_info(sv);
+ memset(&gss, 0, sizeof(GnssSvStatus_ext));
+ gss.size = sizeof(gss);
+ gss.num_svs = sv.num_svs;
+ if (gss.num_svs > MTK_HAL_GNSS_MAX_MEASUREMENT) {
+ gss.num_svs = MTK_HAL_GNSS_MAX_MEASUREMENT;
+ }
+ for (i = 0; i < gss.num_svs; i++) {
+ GnssSvInfo* dst = &gss.gnss_sv_list[i].legacySvInfo;
+ gnss_sv* src = &sv.sv_list[i];
+ dst->size = sizeof(*dst);
+ fieldp_copy(dst, src, svid);
+ fieldp_copy(dst, src, constellation);
+ fieldp_copy(dst, src, c_n0_dbhz);
+ fieldp_copy(dst, src, elevation);
+ fieldp_copy(dst, src, azimuth);
+ fieldp_copy(dst, src, flags);
+ fieldp_copy(&gss.gnss_sv_list[i], src, carrier_frequency);
+ fieldp_copy(&gss.gnss_sv_list[i], src, basebandCN0DbHz);//hidl v2.1
+ mnlDebugData.satelliteDataArray[i].svid = gss.gnss_sv_list[i].legacySvInfo.svid;
+ mnlDebugData.satelliteDataArray[i].constellation = gss.gnss_sv_list[i].legacySvInfo.constellation;
+ }
+ g_gpshal_ctx.gps_cbs->gnss_sv_status_cb(&gss);
+}
+
+static void update_nmea(int64_t timestamp, const char* nmea, int length) {
+ /*LOGD(" timestamp=%lld nmea=[%s] length=%d",
+ timestamp, nmea, length);
+ LOGD("%"PRId64", nmea_cb:%p",timestamp, g_gpshal_ctx.gps_cbs->nmea_cb);*/
+ g_gpshal_ctx.gps_cbs->nmea_cb(timestamp, nmea, length);
+}
+#if 0
+static void update_gps_capabilities(gps_capabilites capabilities) {
+ LOGD(" capabilities=0x%x", capabilities);
+// g_gpshal_ctx.gps_cbs->set_capabilities_cb(capabilities);
+ g_gpshal_ctx.gps_cap = capabilities;
+}
+#endif
+GnssData_ext gd;
+static void update_gnss_measurements(gnss_data *data) {
+ size_t i;
+ //dump_gnss_data(data);
+ memset(&gd, 0, sizeof(GnssData_ext));
+ gd.size = sizeof(gd);
+ if((*data).measurement_count > MTK_HAL_GNSS_MAX_MEASUREMENT) {
+ (*data).measurement_count = MTK_HAL_GNSS_MAX_MEASUREMENT;
+ }
+ LOGD("meas_cnt:%zu", (*data).measurement_count);
+
+ field_copy(gd, (*data), measurement_count);
+ for (i = 0; i < (*data).measurement_count; i++) {
+ GnssMeasurement* dst = &gd.measurements[i].legacyMeasurement;
+ gnss_measurement* src = &(*data).measurements[i];
+ dst->size = sizeof(*dst);
+ fieldp_copy(dst, src, flags);
+ fieldp_copy(dst, src, svid);
+ fieldp_copy(dst, src, constellation);
+ fieldp_copy(dst, src, time_offset_ns);
+ fieldp_copy(dst, src, state);
+ fieldp_copy(dst, src, received_sv_time_in_ns);
+ fieldp_copy(dst, src, received_sv_time_uncertainty_in_ns);
+ fieldp_copy(dst, src, c_n0_dbhz);
+ fieldp_copy(dst, src, pseudorange_rate_mps);
+ fieldp_copy(dst, src, pseudorange_rate_uncertainty_mps);
+ fieldp_copy(dst, src, accumulated_delta_range_state);
+ fieldp_copy(dst, src, accumulated_delta_range_m);
+ fieldp_copy(dst, src, accumulated_delta_range_uncertainty_m);
+ fieldp_copy(dst, src, carrier_frequency_hz);
+ fieldp_copy(dst, src, carrier_cycles);
+ fieldp_copy(dst, src, carrier_phase);
+ fieldp_copy(dst, src, carrier_phase_uncertainty);
+ fieldp_copy(dst, src, multipath_indicator);
+ fieldp_copy(dst, src, snr_db);
+ fieldp_copy(&gd.measurements[i], src, fullInterSignalBiasNs);// v2.1
+ fieldp_copy(&gd.measurements[i], src, fullInterSignalBiasUncertaintyNs);// v2.1
+ fieldp_copy(&gd.measurements[i], src, satelliteInterSignalBiasNs);// v2.1
+ fieldp_copy(&gd.measurements[i], src, satelliteInterSignalBiasUncertaintyNs);// v2.1
+ fieldp_copy(&gd.measurements[i], src, basebandCN0DbHz);// v2.1
+ fieldp_copy(&gd.measurements[i], src, agc_level_db);// v2.1
+ /// todo
+ MNLD_STRNCPY(gd.measurements[i].codeType, (*data).measurements[i].code_type, sizeof(gd.measurements[i].codeType));
+
+ }
+
+ // To do things like field_copy(gd, data, clock)
+ {
+ GnssClock* dst = &gd.clock.legacyClock;
+ gnss_clock* src = &(*data).clock;
+ dst->size = sizeof(*dst);
+ fieldp_copy(dst, src, flags);
+ fieldp_copy(dst, src, leap_second);
+ fieldp_copy(dst, src, time_ns);
+ fieldp_copy(dst, src, time_uncertainty_ns);
+ fieldp_copy(dst, src, full_bias_ns);
+ fieldp_copy(dst, src, bias_ns);
+ fieldp_copy(dst, src, bias_uncertainty_ns);
+ fieldp_copy(dst, src, drift_nsps);
+ fieldp_copy(dst, src, drift_uncertainty_nsps);
+ fieldp_copy(dst, src, hw_clock_discontinuity_count);
+ fieldp_copy(&gd.clock.referenceSignalTypeForIsb, &src->referenceSignalTypeForIsb, constellation);//hidl v2.1
+ fieldp_copy(&gd.clock.referenceSignalTypeForIsb, &src->referenceSignalTypeForIsb, carrierFrequencyHz);//hidl v2.1
+ MNLD_STRNCPY(gd.clock.referenceSignalTypeForIsb.codeType, src->referenceSignalTypeForIsb.codeType, sizeof(gd.clock.referenceSignalTypeForIsb.codeType));
+ mnlDebugData.time.timeUncertaintyNs = src->time_uncertainty_ns;
+ mnlDebugData.time.frequencyUncertaintyNsPerSec = src->drift_nsps;
+ /// not report elapsed real time in mnld, real time items will be ignored.
+ gd.elapsedRealtime.flags = 0; //HAS_TIMESTAMP_NS | HAS_TIME_UNCERTAINTY_NS;
+ gd.elapsedRealtime.timestampNs = 0;
+ gd.elapsedRealtime.timeUncertaintyNs = 0;
+
+ /// v2.1 TODO
+ //fieldp_copy(gd.clock.referenceSignalTypeForIsb.carrierFrequencyHz, src, carrierFrequencyHz);
+ //fieldp_copy(gd.clock.referenceSignalTypeForIsb.constellation, src, constellation);
+ //MNLD_STRNCPY(gd.clock.referenceSignalTypeForIsb.codeType, src.codeType, sizeof(src.codeType));
+ }
+
+ g_gpshal_ctx.meas_cbs->gnss_measurement_callback(&gd);
+}
+
+static void update_gnss_navigation(gnss_nav_msg *msg) {
+ GnssNavigationMessage gnm;
+ //dump_gnss_nav_msg(msg);
+ memset(&gnm, 0, sizeof(GnssNavigationMessage));
+ gnm.size = sizeof(gnm);
+ field_copy(gnm, (*msg), svid);
+ field_copy(gnm, (*msg), type);
+ field_copy(gnm, (*msg), status);
+ field_copy(gnm, (*msg), message_id);
+ field_copy(gnm, (*msg), submessage_id);
+ field_copy(gnm, (*msg), data_length);
+ gnm.data = (uint8_t*)(*msg).data;
+ g_gpshal_ctx.navimsg_cbs->gnss_navigation_message_callback(&gnm);
+}
+
+static void request_wakelock() {
+ // GPSHAL_DEBUG_FUNC_SCOPE;
+ g_gpshal_ctx.gps_cbs->acquire_wakelock_cb();
+}
+static void release_wakelock() {
+ // GPSHAL_DEBUG_FUNC_SCOPE;
+ g_gpshal_ctx.gps_cbs->release_wakelock_cb();
+}
+static void request_utc_time() {
+ // GPSHAL_DEBUG_FUNC_SCOPE;
+ g_gpshal_ctx.gps_cbs->request_utc_time_cb();
+}
+static void request_data_conn(__unused struct sockaddr_storage* addr, agps_type type) {
+ // GPSHAL_DEBUG_FUNC_SCOPE;
+ UNUSED(addr);
+ AGpsStatus as;
+ as.size = sizeof(AGpsStatus); // our imp supports v3
+ as.type = type;
+ as.status = GPS_REQUEST_AGPS_DATA_CONN;
+ // as.ipaddr = INADDR_NONE; // not used in v3
+ as.addr = *addr;
+ g_gpshal_ctx.agps_cbs->status_cb(&as);
+}
+static void release_data_conn(agps_type type) {
+ // GPSHAL_DEBUG_FUNC_SCOPE;
+ AGpsStatus as;
+ as.size = sizeof(AGpsStatus_v1); // use v1 size to omit optional fields
+ as.type = type;
+ as.status = GPS_RELEASE_AGPS_DATA_CONN;
+ g_gpshal_ctx.agps_cbs->status_cb(&as);
+}
+static void request_ni_notify(int session_id, agps_ni_type ni_type, agps_notify_type type, const char* requestor_id,
+ const char* client_name, ni_encoding_type requestor_id_encoding,
+ ni_encoding_type client_name_encoding) {
+ /*LOGD(" session_id=%d type=%d requestor_id=[%s] client_name=[%s] requestor_id_encoding=%d client_name_encoding=%d",
+ session_id, type, requestor_id, client_name, requestor_id_encoding, client_name_encoding);*/
+ GpsNiNotification gnn;
+ gnn.size = sizeof(gnn);
+ gnn.notification_id = session_id;
+ gnn.ni_type = ni_type;
+ switch (type) {
+ case AGPS_NOTIFY_TYPE_NOTIFY_ONLY:
+ gnn.notify_flags = GPS_NI_NEED_NOTIFY;
+ break;
+ case AGPS_NOTIFY_TYPE_NOTIFY_ALLOW_NO_ANSWER:
+ gnn.notify_flags = GPS_NI_NEED_NOTIFY|GPS_NI_NEED_VERIFY;
+ break;
+ case AGPS_NOTIFY_TYPE_NOTIFY_DENY_NO_ANSWER:
+ gnn.notify_flags = GPS_NI_NEED_NOTIFY|GPS_NI_NEED_VERIFY;
+ break;
+ case AGPS_NOTIFY_TYPE_PRIVACY:
+ gnn.notify_flags = GPS_NI_PRIVACY_OVERRIDE;
+ break;
+ default:
+ gnn.notify_flags = 0;
+ }
+ gnn.timeout = 8;
+ gnn.default_response = GPS_NI_RESPONSE_NORESP;
+ MNLD_STRNCPY(gnn.requestor_id, requestor_id,sizeof(gnn.requestor_id));
+ MNLD_STRNCPY(gnn.text,client_name,sizeof(gnn.text));
+ gnn.requestor_id_encoding = requestor_id_encoding;
+ gnn.text_encoding = client_name_encoding;
+ gnn.extras[0] = 0; // be an empty string ""
+ if (g_gpshal_ctx.gpsni_cbs) {
+ g_gpshal_ctx.gpsni_cbs->notify_cb(&gnn);
+ }
+}
+static void request_set_id(request_setid flags) {
+ //LOGD(" flags=0x%x", flags);
+ if (g_gpshal_ctx.agpsril_cbs) {
+ g_gpshal_ctx.agpsril_cbs->request_setid(flags);
+ }
+}
+static void request_ref_loc(request_refloc flags) {
+ //LOGD(" flags=0x%x", flags);
+ if (g_gpshal_ctx.agpsril_cbs) {
+ g_gpshal_ctx.agpsril_cbs->request_refloc(flags);
+ }
+}
+static void output_vzw_debug(const char* str) {
+ int len;
+ len = strlen(str)+1;
+ if (len > VZW_DEBUG_STRING_MAXLEN) {
+ len = VZW_DEBUG_STRING_MAXLEN;
+ }
+ LOGD("len=%d str=%s", len, str);
+ VzwDebugData vzwdebugdata;
+ vzwdebugdata.size = sizeof(VzwDebugData);
+ memcpy(vzwdebugdata.vzw_msg_data, str, len);
+ vzwdebugdata.vzw_msg_data[VZW_DEBUG_STRING_MAXLEN - 1] = 0;
+
+ if (g_gpshal_ctx.vzw_debug_cbs) {
+ g_gpshal_ctx.vzw_debug_cbs->vzw_debug_cb(&vzwdebugdata);
+ }
+}
+
+static void update_gnss_name(const char* name, int length) {
+ LOGD("length=%d, name=%s", length, name);
+ if(length > GNSS_NAME_LEN) {
+ length = GNSS_NAME_LEN;
+ }
+ MNLD_STRNCPY(g_gpshal_ctx.gps_name, name, GNSS_NAME_LEN);
+}
+
+static void request_nlp(bool independentFromGnss, bool isUserEmergency) {
+ LOGD("request nlp[%d], flag=%d", independentFromGnss, isUserEmergency);
+ if (g_gpshal_ctx.gps_cbs) {
+ //// todo
+ g_gpshal_ctx.gps_cbs->request_location_cb(independentFromGnss, isUserEmergency);
+ }
+}
+
+static void nfw_access_notify(mnldinf_nfw_notification *nfw_notify) {
+ NfwNotification notify;
+ LOGD("APP name: %s, PS: %d, otherPSName: %s, requestor: %d, requestorId: %s, responseType: %d, inEmergencyMode: %d, isCachedLocation: %d"
+ ,(*nfw_notify).proxy_app_package_name
+ ,(*nfw_notify).protocol_stack
+ ,(*nfw_notify).other_protocol_stack_name
+ ,(*nfw_notify).requestor
+ ,(*nfw_notify).requestor_id
+ ,(*nfw_notify).response_type
+ ,(*nfw_notify).in_emergency_mode
+ ,(*nfw_notify).is_cached_location
+ );
+
+ memset(¬ify, 0, sizeof(notify));
+ memcpy(¬ify, nfw_notify, sizeof(notify));
+ if(g_gpshal_ctx.visibility_control_cbs && g_gpshal_ctx.visibility_control_cbs->nfw_notify_cb) {
+ g_gpshal_ctx.visibility_control_cbs->nfw_notify_cb(notify);
+ }
+}
+
+void connection_broken_basic(void) {
+ LOGW("connection broken...");
+ mnldinf_start_timer(g_gpshal_ctx.mnl_retry_timer, GPSHAL_MNL_RETRY_INTERVAL);
+}
+
+void capability_update_basic(mnldinf_basic_server_cap *cap) {
+ LOGD("capability:size:%lu", sizeof(mnldinf_basic_server_cap));
+}
+
+void nmea_done(void) {
+ LOGD("NMEA done");
+}
+
+void connection_broken_ext() {
+ LOGW("extension connection broken...");
+ mnldinf_start_timer(g_gpshal_ctx.mnl_retry_timer, GPSHAL_MNL_RETRY_INTERVAL);
+}
+
+void capability_update_ext(mnldinf_ext_server_cap *cap) {
+ LOGD("externsion capability update:size:%lu", sizeof(mnldinf_ext_server_cap));
+}
+
+
+static void update_agps_location(gps_location location) {
+ GpsLocation_ext loc;
+ gpshal_state state = g_gpshal_ctx.gps_state;
+ memset(&loc, 0, sizeof(GpsLocation_ext));
+ if (GPSHAL_STATE_START == state) {
+ loc.legacyLocation.size = sizeof(loc);
+ loc.legacyLocation.flags = location.flags;
+ loc.legacyLocation.latitude = location.lat;
+ loc.legacyLocation.longitude = location.lng;
+ loc.legacyLocation.altitude = location.alt;
+ loc.legacyLocation.speed = location.speed;
+ loc.legacyLocation.bearing = location.bearing;
+ loc.legacyLocation.accuracy = loc.horizontalAccuracyMeters = location.h_accuracy;
+ loc.verticalAccuracyMeters = location.v_accuracy;
+ loc.speedAccuracyMetersPerSecond = location.s_accuracy;
+ loc.bearingAccuracyDegrees = location.b_accuracy;
+ loc.legacyLocation.timestamp = location.timestamp;
+
+ /// not report elapsed real time in mnld, it will be reported in frw.
+ loc.elapsedRealtime.flags = 0;
+ loc.elapsedRealtime.timestampNs = 0;
+ loc.elapsedRealtime.timeUncertaintyNs = 0;
+ loc.type = location.type;
+ LOGD("AGPS location: hacc=%f,vacc=%f,sacc=%f,bacc=%f, type:%u", loc.horizontalAccuracyMeters, loc.verticalAccuracyMeters,
+ loc.speedAccuracyMetersPerSecond, loc.bearingAccuracyDegrees, loc.type);
+ g_gpshal_ctx.gps_cbs->agps_location_cb(&loc);
+ } else {
+ LOGW("we have a location when gps_state_intent: %s (%d)",
+ gpshal_state_to_string(state), state);
+ }
+}
+
+void agps_location_update(mnldinf_agps_location location) {
+ gps_location loc;
+ LOGD("alt:%f, acc:%f, %lld, type:%d", location.altitude, location.accuracy, location.timestamp, location.type);
+
+ memset(&loc, 0, sizeof(loc));
+ if(location.type_used) {
+ loc.type = location.type;
+ } else {
+ loc.type = MNLDINF_AGPS_LOC_TYPE_UNKNOWN;
+ }
+
+ loc.flags |= MTK_GPS_LOCATION_HAS_LAT_LONG;
+ loc.lat = location.latitude;
+ loc.lng = location.longitude;
+ if (location.altitude_used) {
+ loc.flags |= MTK_GPS_LOCATION_HAS_ALT;
+ loc.alt = location.altitude;
+ }
+ if (location.speed_used) {
+ loc.flags |= MTK_GPS_LOCATION_HAS_SPEED;
+ loc.speed = location.speed;
+ }
+ if (location.bearing_used) {
+ loc.flags |= MTK_GPS_LOCATION_HAS_BEARING;
+ loc.bearing = location.bearing;
+ }
+ if (location.accuracy_used) {
+ loc.flags |= MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY;
+ loc.h_accuracy = location.accuracy;
+ }
+ if (location.timestamp_used) {
+ loc.timestamp = location.timestamp;
+ }
+
+ if(location.type_used &&
+ (location.type == MNLDINF_AGPS_LOC_TYPE_AFLT ||
+ location.type == MNLDINF_AGPS_LOC_TYPE_MOLR_BEGIN_RSP ||
+ location.type == MNLDINF_AGPS_LOC_TYPE_SUPL_END)) {
+ update_location(loc);
+ }
+
+ update_agps_location(loc);
+
+}
+
+static mnldinf_basic gpshal_mnl2hal_interface_basic = {
+ connection_broken_basic,
+ update_location,
+ update_gps_status,
+ update_gps_sv,
+ update_nmea,
+ nmea_done,
+ update_gnss_measurements,
+ capability_update_basic
+};
+
+static mnldinf_ext gpshal_mnl2hal_interface_ext = {
+ connection_broken_ext,
+ request_wakelock,
+ release_wakelock,
+
+ request_utc_time,
+ request_nlp,
+ request_ni_notify,
+
+ request_data_conn,
+ release_data_conn,
+
+ request_set_id,
+ request_ref_loc,
+ output_vzw_debug,
+
+ update_gnss_name,
+
+ update_gnss_navigation,
+ nfw_access_notify,
+
+ capability_update_ext,
+ agps_location_update
+};
+
+//=========================================================
+
+void gpshal_worker_thread(__unused void *arg) {
+ // GPSHAL_DEBUG_FUNC_SCOPE;
+ struct epoll_event events[MAX_EPOLL_EVENT];
+ UNUSED(arg);
+
+ while (true) {
+ int i;
+ int n;
+
+ n = epoll_wait(g_gpshal_ctx.fd_worker_epoll, events, MAX_EPOLL_EVENT , -1);
+ if (n == -1) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ LOGE("%s() epoll_wait failure reason=[%s]%d",
+ __func__, strerror(errno), errno);
+ return;
+ }
+ }
+ mnldinf_wake_lock_take();
+ for (i = 0; i < n; i++) {
+ if (events[i].data.fd == g_gpshal_ctx.fd_mnl2hal_basic) {
+ if (events[i].events & EPOLLIN) {
+ mnldinf_basic_cmd_hdlr(g_gpshal_ctx.fd_mnl2hal_basic,
+ &gpshal_mnl2hal_interface_basic);
+ }
+ } else if (events[i].data.fd == g_gpshal_ctx.fd_mnl2hal_ext) {
+ if (events[i].events & EPOLLIN) {
+ mnldinf_ext_cmd_hdlr(g_gpshal_ctx.fd_mnl2hal_ext,
+ &gpshal_mnl2hal_interface_ext);
+ }
+ } else {
+ LOGE("%s() unknown fd=%d",
+ __func__, events[i].data.fd);
+ }
+ }
+ mnldinf_wake_lock_give();
+ } // of while (true)
+}
diff --git a/src/connectivity/gps/2.0/gps_hal/src/gpsinf.c b/src/connectivity/gps/2.0/gps_hal/src/gpsinf.c
new file mode 100644
index 0000000..82f109d
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/src/gpsinf.c
@@ -0,0 +1,521 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include "gpshal.h"
+#include "gpshal_param_check.h"
+#include "hal2mnl_interface.h"
+#include "mtk_lbs_utility.h"
+#include "errno.h"
+//=========================================================
+
+extern struct hw_module_t HAL_MODULE_INFO_SYM;
+extern DebugData mnlDebugData; //for GNSS HIDL v1.1 GPS debug interface
+
+//=========================================================
+// Gps Measurement Interface
+
+// Thread: BackgroundThread
+// GpsMeasurementsProvider uses GpsLocationProvider's handler
+static int measinf_init(GpsMeasurementCallbacks_ext* callbacks, bool enableFullTracking) {
+ g_gpshal_ctx.meas_cbs = callbacks;
+ int ret = hal2mnl_set_gps_measurement(true, enableFullTracking);
+ return (ret > 0)?
+ GPS_GEOFENCE_OPERATION_SUCCESS :
+ GPS_GEOFENCE_ERROR_GENERIC;
+}
+
+// Thread: BackgroundThread
+// GpsMeasurementsProvider uses GpsLocationProvider's handler
+static void measinf_close(void) {
+ if (hal2mnl_set_gps_measurement(false, false) == -1) {
+ LOGE("hal2mnl_set_gps_measurement failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+const GpsMeasurementInterface_ext mtk_gps_meas_inf = {
+ sizeof(GpsMeasurementInterface_ext),
+ measinf_init,
+ measinf_close
+};
+
+//=========================================================
+// Gnss Antenna Interface
+//TODO
+static int antenna_info_set_callback(GnssAntennaInfoCallbacks* callbacks) {
+ UNUSED(callbacks);
+ return 0;
+}
+
+static void antenna_info_close(void) {
+}
+
+const GnssAntennaInfoInterface mtk_antenna_info_inf = {
+ sizeof(GnssAntennaInfoInterface),
+ antenna_info_set_callback,
+ antenna_info_close
+};
+
+
+//=========================================================
+// Gnss Measurement Correction Interface
+static bool meas_correct_set_callback(MeasurementCorrectionCallbacks_ext* callbacks) {
+ int capabilities = LOS_SATS | EXCESS_PATH_LENGTH | REFLECTING_PLANE;
+ g_gpshal_ctx.meas_correct_cbs = callbacks;
+ g_gpshal_ctx.meas_correct_cbs->set_capabilities_cb(capabilities);
+ return true;
+}
+
+static bool meas_correct_set_correction(MeasurementCorrections* corrections) {
+ LOGD("setCorrections");
+ /*LOGD("corrections = lat: %f, lng: %f, alt: %f, hUnc: %f, vUnc: %f, toa: %llu num_satCorr: %d, ",
+ corrections->latitudeDegrees, corrections->longitudeDegrees, corrections->altitudeMeters,
+ corrections->horizontalPositionUncertaintyMeters,
+ corrections->verticalPositionUncertaintyMeters,
+ corrections->toaGpsNanosecondsOfWeek,
+ corrections->num_satCorrection);
+ int i = 0;*/
+ int ret = 0;
+ if(corrections->num_satCorrection > GNSS_MAX_SVS) {
+ corrections->num_satCorrection = GNSS_MAX_SVS;
+ }
+ /*for (i=0; i < corrections->num_satCorrection; i++) {
+ SingleSatCorrection* ssc = &(corrections->satCorrections[i]);
+ LOGD("i = %d, singleSatCorrection = flags: %d, constellation: %d, svid: %d, cfHz: %f, probLos: %f,"
+ " epl: %f, eplUnc: %f",
+ i,
+ ssc->singleSatCorrectionFlags,
+ ssc->constellation,
+ ssc->svid, ssc->carrierFrequencyHz,
+ ssc->probSatIsLos, ssc->excessPathLengthMeters,
+ ssc->excessPathLengthUncertaintyMeters);
+ LOGD("reflecting plane = lat: %f, lng: %f, alt: %f, azm: %f",
+ ssc->reflectingPlane.latitudeDegrees,
+ ssc->reflectingPlane.longitudeDegrees,
+ ssc->reflectingPlane.altitudeMeters,
+ ssc->reflectingPlane.azimuthDegrees);
+ }*/
+ ret = hal2mnl_set_correction(corrections);
+ return (ret > 0) ? true:false;
+}
+
+const MeasurementCorrectionInterface mtk_gnss_meas_correction_inf = {
+ sizeof(MeasurementCorrectionInterface),
+ meas_correct_set_callback,
+ meas_correct_set_correction
+};
+
+//=========================================================
+// Gnss Visibility Control Interface
+static bool visibility_set_callback(GnssVisibilityControlCallback_ext* callbacks) {
+ g_gpshal_ctx.visibility_control_cbs = callbacks;
+ return true;
+}
+
+static bool enable_nfw_access(const char* proxyApps, int32_t length) {
+ LOGD("enable_nfw_access proxyApps: [%s], len=%d", proxyApps, length);
+ if(length > HAL_NFW_USER_NUM_MAX*HAL_NFW_USER_NAME_LEN) {
+ LOGW("Over length(%d), set to MAX:%d", length, HAL_NFW_USER_NUM_MAX*HAL_NFW_USER_NAME_LEN-1);
+ length = HAL_NFW_USER_NUM_MAX*HAL_NFW_USER_NAME_LEN-1;
+ }
+ memset(g_gpshal_ctx.proxy_apps, 0, sizeof(g_gpshal_ctx.proxy_apps)); //Clear buffer before copy
+ strncpy(g_gpshal_ctx.proxy_apps, proxyApps, length);
+ if (hal2mnl_set_nfw_access(g_gpshal_ctx.proxy_apps, length) == -1) {
+ LOGE("hal2mnl_set_nfw_access failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ return true;
+}
+
+const GnssVisibilityControlInterface mtk_visibility_control_inf = {
+ sizeof(GnssVisibilityControlInterface),
+ visibility_set_callback,
+ enable_nfw_access
+};
+
+//=========================================================
+// Gps Navigation Message Interface
+
+// Thread: BackgroundThread
+// GpsNavigationMessageProvider uses GpsLocationProvider's handler
+static int navimsginf_init(GpsNavigationMessageCallbacks* callbacks) {
+ g_gpshal_ctx.navimsg_cbs = callbacks;
+ int ret = hal2mnl_set_gps_navigation(true);
+ return (ret > 0)?
+ GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS :
+ GPS_NAVIGATION_MESSAGE_ERROR_GENERIC;
+}
+
+// Thread: BackgroundThread
+// GpsNavigationMessageProvider uses GpsLocationProvider's handler
+static void navimsginf_close(void) {
+ if (hal2mnl_set_gps_navigation(false) == -1) {
+ LOGE("hal2mnl_set_gps_navigation failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+const GpsNavigationMessageInterface mtk_navi_msg_inf = {
+ sizeof(GpsNavigationMessageInterface),
+ navimsginf_init,
+ navimsginf_close
+};
+
+static int vzwdebuginf_init(VzwDebugCallbacks* callbacks) {
+ g_gpshal_ctx.vzw_debug_cbs = callbacks;
+ return 0;
+}
+
+static void vzwdebuginf_set(bool enabled) {
+ if (hal2mnl_set_vzw_debug(enabled) == -1) {
+ LOGE("hal2mnl_set_vzw_debug failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+const VzwDebugInterface mtk_vzw_debug_inf = {
+ sizeof(VzwDebugInterface),
+ vzwdebuginf_init,
+ vzwdebuginf_set
+};
+
+static void gnss_configuration_update(const char* config_data, int32_t length) {
+ if (hal2mnl_update_gnss_config(config_data, length) == -1) {
+ LOGE("hal2mnl_update_gnss_config failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void gnss_setBlacklist(long long* blacklist, int32_t size) {
+ if (hal2mnl_setBlacklist(blacklist, size) == -1) {
+ LOGE("hal2mnl_setBlacklist failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void gnss_setEsExtensionSec(uint32_t emergencyExtensionSeconds) {
+ char temp_string[64];
+ LOGD("Set Emergency State Extension Second:%d", emergencyExtensionSeconds);
+ memset(temp_string, 0, sizeof(temp_string));
+ MNLD_SPRINTF(temp_string, "emergencyExtensionSeconds=%d", emergencyExtensionSeconds);
+ if (hal2mnl_update_gnss_config(temp_string, strlen(temp_string)) == -1) {
+ LOGE("hal2mnl_update_gnss_config failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+const GnssConfigurationInterface_ext mtk_gnss_config_inf = {
+ sizeof(GnssConfigurationInterface_ext),
+ gnss_configuration_update,
+ gnss_setBlacklist,
+ gnss_setEsExtensionSec
+};
+
+static bool get_internal_state(DebugData* debugData) {
+ memcpy(debugData, &mnlDebugData, sizeof(DebugData));
+ LOGD("debugData->time:Esttimems:%ld, uncNs: %.3f, ppb: %.3f",
+ debugData->time.timeEstimate,
+ debugData->time.timeUncertaintyNs,
+ debugData->time.frequencyUncertaintyNsPerSec);
+ return true;
+}
+
+const GpsDebugInterface_ext mtk_gps_debug_inf = {
+ sizeof(GpsDebugInterface_ext),
+ get_internal_state
+};
+
+//=========================================================
+// Implementation of
+// Gps Iterface
+
+// Thread: Main thread of system server
+// Call seq:
+// LocationManagerService.systemRunning
+// LocationManagerService.loadProvidersLocked
+// GpsLocationProvider.static
+// android_location_GpsLocationProvider_class_init_native
+// sGpsInterface->get_extension
+static const void* gpsinf_get_extension(const char* name) {
+ if (strcmp(name, AGPS_INTERFACE) == 0) {
+ return &mtk_agps_inf;
+ }
+ if (strcmp(name, GPS_NI_INTERFACE) == 0) {
+ return &mtk_gps_ni_inf;
+ }
+ if (strcmp(name, AGPS_RIL_INTERFACE) == 0) {
+ return &mtk_agps_ril_inf;
+ }
+ if (strcmp(name, GPS_MEASUREMENT_INTERFACE) == 0) {
+ return &mtk_gps_meas_inf;
+ }
+ if (strcmp(name, GNSS_MEASUREMENT_CORRECTION_INTERFACE) == 0) {
+ return &mtk_gnss_meas_correction_inf;
+ }
+ if (strcmp(name, GNSS_VISIBILITY_CONTROL_INTERFACE) == 0) {
+ return &mtk_visibility_control_inf;
+ }
+ if (strcmp(name, GPS_NAVIGATION_MESSAGE_INTERFACE) == 0) {
+ return &mtk_navi_msg_inf;
+ }
+
+ if (strcmp(name, VZW_DEBUG_INTERFACE) == 0) {
+ return &mtk_vzw_debug_inf;
+ }
+
+ if (strcmp(name, GNSS_ANTENNA_INFO_INTERFACE) == 0) {
+ return &mtk_antenna_info_inf;
+ }
+
+ if (!strcmp(name, GNSS_CONFIGURATION_INTERFACE)) {
+ return &mtk_gnss_config_inf;
+ }
+#if 0 // not ready, even in Google's GPS JNI
+ if (strcmp(name, SUPL_CERTIFICATE_INTERFACE) == 0) {
+ return &mtk_supl_cert_inf;
+ }
+#endif
+#if 0 // Similar to our EPO but we will do it in mnld.
+ if (!strcmp(name, GPS_XTRA_INTERFACE))
+ return &mtk_gps_xtra_inf;
+#endif
+ if (!strcmp(name, GPS_DEBUG_INTERFACE)) {
+ return &mtk_gps_debug_inf;
+ }
+ return NULL; // unsupported extension
+}
+
+// Thread: BackgroundThread
+// Its looper is shared by a lot of services including
+// LocationManagerService's handler
+// GpsLocationProvider's handler
+// GpsLocationProvider's broadcast receiver
+// Call seq:
+// GpsLocationProvider.ProviderHandler.handleMessage
+// GpsLocationProvider.handleEnable
+// GpsLocationProvider.native_init
+// android_location_GpsLocationProvider_init
+// sGpsInterface->init
+static int gpsinf_init(GpsCallbacks_ext* callbacks) {
+ // GPSHAL_DEBUG_FUNC_SCOPE2(g_gpshal_ctx.mutex_gps_state_intent);
+
+ mnldinf_wake_lock_init();
+
+ if (gpshal_gpscbs_save(callbacks) != 0) {
+ return -1; // error
+ }
+
+ gpshal_set_gps_state_intent(GPSHAL_STATE_INIT);
+ gpshal2mnl_gps_init();
+ g_gpshal_ctx.mnl_retry_timer = mnldinf_init_timer(gpshal_mnl_retry_routine);
+ return 0; // OK to init
+}
+
+// Thread: BackgroundThread
+static int gpsinf_start(void) {
+ // GPSHAL_DEBUG_FUNC_SCOPE2(g_gpshal_ctx.mutex_gps_state_intent);
+ memset(&mnlDebugData, 0, sizeof(DebugData));//clear debug data every session
+ gpshal_set_gps_state_intent(GPSHAL_STATE_START);
+ gpshal2mnl_gps_start();
+ return 0; // OK to start
+}
+
+// Thread: BackgroundThread
+static int gpsinf_stop(void) {
+ // GPSHAL_DEBUG_FUNC_SCOPE2(g_gpshal_ctx.mutex_gps_state_intent);
+ gpshal_set_gps_state_intent(GPSHAL_STATE_STOP);
+ gpshal2mnl_gps_stop();
+ return 0; // OK to stop
+}
+
+// Thread: BackgroundThread
+static void gpsinf_cleanup(void) {
+ timer_t retry_timer;
+ // GPSHAL_DEBUG_FUNC_SCOPE2(g_gpshal_ctx.mutex_gps_state_intent);
+ gpshal_set_gps_state_intent(GPSHAL_STATE_CLEANUP);
+ gpshal2mnl_gps_cleanup();
+ mnldinf_wake_lock_deinit();
+ retry_timer = g_gpshal_ctx.mnl_retry_timer;
+ g_gpshal_ctx.mnl_retry_timer = INVALID_TIMERID;
+ if(mnldinf_deinit_timer(retry_timer) == -1) {
+ LOGE("mnl_retry_timer deinit fail:%s", strerror(errno));
+ }
+}
+
+// Thread: BackgroundThread
+static int gpsinf_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty) {
+ if (hal2mnl_gps_inject_time(time, timeReference, uncertainty) == -1) {
+ LOGE("hal2mnl_gps_inject_time failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ return 0; // 0:ok, non-zero: error; but GPS JNI will ignore it
+}
+
+// Thread: BackgroundThread
+// NetworkLocationListener uses the looper of GpsLocationProvider's handler
+static int gpsinf_inject_location(
+ double latitude,
+ double longitude,
+ float accuracy) {
+ if (hal2mnl_gps_inject_location(latitude, longitude, accuracy) == -1) {
+ LOGE("hal2mnl_gps_inject_location failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ return 0; // 0:ok, non-zero: error; but GPS JNI will ignore it
+}
+
+// Thread: Binder Thread of LocationManagerService
+//
+// Call seq:
+// LocationManagerService.sendExtraCommand
+// GpsLocationProvider.sendExtraCommand
+// GpsLocationProvider.deleteAidingData
+// GpsLocationProvider.native_delete_aiding_data
+// android_location_GpsLocationProvider_delete_aiding_data
+// sGpsInterface->delete_aiding_data
+static void gpsinf_delete_aiding_data(GpsAidingData flags) {
+ if (hal2mnl_gps_delete_aiding_data(flags) == -1) {
+ LOGE("hal2mnl_gps_delete_aiding_data failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+// Thread: BackgroundThread or ???
+// GpsLocationProvider's handler may call it
+// GpsLocationProvider's mBroadcastReceiver may call it (PowerManager's intent)
+static int gpsinf_set_position_mode(
+ GpsPositionMode mode,
+ GpsPositionRecurrence recurrence,
+ uint32_t min_interval,
+ uint32_t preferred_accuracy,
+ uint32_t preferred_time,
+ bool lowPowerMode) {
+ if (hal2mnl_gps_set_position_mode(
+ mode,
+ recurrence,
+ min_interval,
+ preferred_accuracy,
+ preferred_time,
+ lowPowerMode) == -1) {
+ LOGE("hal2mnl_gps_set_position_mode failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ return 0; // 0:ok, non-zero: error; GLP will show log if error
+}
+
+static int gpsinf_inject_fused_location(
+ double latitude,
+ double longitude,
+ float accuracy) {
+ // TODO: hal2mnl_gps_inject_fused_location(latitude, longitude, accuracy);
+ UNUSED(latitude);
+ UNUSED(longitude);
+ UNUSED(accuracy);
+ return 0; // 0:ok, non-zero: error; but GPS JNI will ignore it
+}
+
+static const GpsInterface_ext mtk_gps_inf = {
+ sizeof(GpsInterface_ext),
+ gpsinf_init,
+ gpsinf_start,
+ gpsinf_stop,
+ gpsinf_cleanup,
+ gpsinf_inject_time,
+ gpsinf_inject_location,
+ gpsinf_delete_aiding_data,
+ gpsinf_set_position_mode,
+ gpsinf_get_extension,
+ gpsinf_inject_fused_location,
+};
+
+#ifdef __ANDROID_OS__
+//=========================================================
+// Between
+// Gps Interface
+// Hardware Module Interface
+
+static const GpsInterface_ext* gps_device__get_gps_interface(
+ __unused struct gps_device_t_ext* device) {
+ GPS_DEVICE__GET_GPS_INTERFACE__CHECK_PARAM;
+ //hal2mnl_hal_reboot();
+ return &mtk_gps_inf;
+}
+
+static const struct gps_device_t_ext gps_device = {
+ .common = { // hw_device_t
+ .tag = HARDWARE_DEVICE_TAG,
+ .version = 0, // GPS JNI will not use it
+ .module = &HAL_MODULE_INFO_SYM,
+ .reserved = {0},
+ .close = NULL // GPS JNI will not call it
+ },
+ .get_gps_interface = gps_device__get_gps_interface
+};
+
+//=========================================================
+// Implementation of
+// Hardware Module Interface
+
+static int gps_hw_module_open(
+ __unused const struct hw_module_t* module,
+ __unused char const* id,
+ struct hw_device_t** device) {
+ GPS_HW_MODULE_OPEN__CHECK_PARAM;
+ *device = (struct hw_device_t*)&gps_device;
+ return 0; // OK: refer to the cpp of GPS JNI
+}
+
+static struct hw_module_methods_t gps_hw_module_methods = {
+ .open = gps_hw_module_open
+};
+
+struct hw_module_t HAL_MODULE_INFO_SYM = {
+ .tag = HARDWARE_MODULE_TAG,
+ .version_major = 1,
+ .version_minor = 0,
+ .id = GPS_HARDWARE_MODULE_ID,
+ .name = "MediaTek GPS Hardware Module",
+ .author = "MediaTek, Inc.",
+ .methods = &gps_hw_module_methods,
+ .dso = NULL,
+ .reserved = {0}
+};
+#else
+//=========================================================
+// Between
+// Gps Interface
+// Hardware Module Interface
+
+const GpsInterface_ext* gps_device__get_gps_interface(struct gps_device_t_ext* device)
+{
+ LOGD("welcome enter libgpshal world\n");
+ //hal2mnl_hal_reboot();
+
+ return &mtk_gps_inf;
+}
+
+const struct gps_device_t_ext linux_gps_device = {
+ .get_gps_interface = gps_device__get_gps_interface
+};
+
+#endif
diff --git a/src/connectivity/gps/2.0/gps_hal/src/gpsinf3337.c b/src/connectivity/gps/2.0/gps_hal/src/gpsinf3337.c
new file mode 100644
index 0000000..5988b6d
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/src/gpsinf3337.c
@@ -0,0 +1,2285 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include <errno.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <sys/epoll.h>
+#include <math.h>
+#include <time.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <semaphore.h>
+
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <cutils/android_filesystem_config.h>
+
+#define LOCATION_NLP_FIX "/data/vendor/gps/LOCATION.DAT"
+#define LOG_TAG "gps_mtk_3337"
+#include <log/log.h>
+#include <cutils/sockets.h>
+#include <cutils/properties.h>
+#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+#endif
+
+#include "hardware/gps_mtk.h"
+#include "gpshal.h"
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#include <termios.h>
+
+/* the name of the controlled socket */
+#define GPS_POWER_NAME "/dev/gps"
+#define GPS_TTY_NAME "/dev/ttyMT1"
+
+#define MNLD_HAL2GPS "/dev/mt3337_gpsonly"
+#define MNL_CONFIG_STATUS "persist.vendor.radio.mnl.prop"
+
+#define PMTK_SOCKET_COM_PORT 49995
+#define PMTK_SERVER_BACKLOG 5
+#define INVALID_SOCKET -1
+#define INVALID_FD -1
+#define GPS_OP "AT%GPS"
+#define GNSS_OP "AT%GNSS"
+#define GPS_AT_ACK_SIZE 60
+
+#define MTKEPO_SV_NUMBER 32
+#define MTKEPO_RECORD_SIZE 72
+#define MTKEPO_SEGMENT_NUM (30 * 4)
+
+#define GPS_DEBUG 1
+#define NEMA_DEBUG 0 /*the flag works if GPS_DEBUG is defined*/
+#if GPS_DEBUG
+#define TRC(f) ALOGD("%s", __func__)
+#define ERR(f, ...) ALOGE("%s: line = %d" f, __func__,__LINE__, ##__VA_ARGS__)
+#define WAN(f, ...) ALOGW("%s: line = %d" f, __func__, __LINE__,##__VA_ARGS__)
+#define DBG(f, ...) ALOGD("%s: line = %d" f, __func__, __LINE__,##__VA_ARGS__)
+#define VER(f, ...) ((void)0) //((void)0)//
+#else
+# define DBG(...) ((void)0)
+# define VER(...) ((void)0)
+#endif
+
+#define GPS_POWER_IOCTL _IOW('G', 0, int)
+static int flag_unlock = 0;
+GpsStatus sta;
+
+extern struct hw_module_t HAL_MODULE_INFO_SYM;
+
+typedef unsigned int UINT4;
+typedef signed int INT4;
+typedef unsigned char UINT8;
+typedef signed char INT8;
+typedef unsigned short int UINT16;
+typedef signed short int INT16;
+typedef unsigned int UINT32;
+typedef signed int INT32;
+typedef signed long long INT64;
+
+#pragma pack(4) // Align by 4 byte
+typedef struct
+{
+ UINT32 size;
+ UINT16 flag;
+ INT16 leapsecond;
+ UINT8 type;
+ INT64 TimeInNs;
+ double TimeUncertaintyInNs;
+ INT64 FullBiasInNs;
+ double BiasInNs;
+ double BiasUncertaintyInNs;
+ double DriftInNsPerSec;
+ double DriftUncertaintyInNsPerSec;
+}MTK_GPS_CLOCK;
+#pragma pack()
+
+typedef struct{
+ GpsUtcTime time;
+ int64_t timeReference;
+ int uncertainty;
+} ntp_context;
+
+typedef struct{
+ double latitude;
+ double longitude;
+ float accuracy;
+ struct timespec ts;
+ unsigned char type;
+ unsigned char started;
+} nlp_context;
+
+/*****************************************************************************/
+/* MTK device control */
+/*****************************************************************************/
+enum {
+ MNL_CMD_UNKNOWN = -1,
+ /*command send from GPS HAL*/
+ MNL_CMD_INIT = 0x00,
+ MNL_CMD_CLEANUP = 0x01,
+ MNL_CMD_STOP = 0x02,
+ MNL_CMD_START = 0x03,
+ MNL_CMD_RESTART = 0x04, /*restart MNL process*/
+ MNL_CMD_RESTART_HOT = 0x05, /*restart MNL by PMTK command: hot start*/
+ MNL_CMD_RESTART_WARM = 0x06, /*restart MNL by PMTK command: warm start*/
+ MNL_CMD_RESTART_COLD = 0x07, /*restart MNL by PMTK command: cold start*/
+ MNL_CMD_RESTART_FULL = 0x08, /*restart MNL by PMTK command: full start*/
+ MNL_CMD_RESTART_AGPS = 0x09, /*restart MNL by PMTK command: AGPS start*/
+ MNL_CMD_GPSMEASUREMENT_INIT = 0x15,
+ MNL_CMD_GPSMEASUREMENT_CLOSE = 0x16,
+
+
+ MNL_CMD_GPSNAVIGATION_INIT = 0x17,
+ MNL_CMD_GPSNAVIGATION_CLOSE = 0x18,
+ MNL_CMD_GPS_LOG_WRITE = 0x40,
+
+ MNL_CMD_ENABLE_AGPS_DEBUG = 0x42,
+ MNL_CMD_DISABLE_AGPS_DEBUG = 0x43,
+};
+
+enum {
+ HAL_CMD_STOP_UNKNOWN = -1,
+ HAL_CMD_MNL_DIE = 0x41,
+ HAL_CMD_GPS_ICON = 0x42,
+
+ MNL_CMD_GPS_INJECT_TIME = 0x46,
+ MNL_CMD_GPS_INJECT_LOCATION = 0x47,
+ MNL_CMD_GPS_INJECT_TIME_REQ = 0x48,
+ MNL_CMD_GPS_INJECT_LOCATION_REQ = 0x49,
+
+ MNL_CMD_GPS_NLP_LOCATION_REQ = 0x4a,
+ HAL_CMD_MEASUREMENT= 0x76,
+ HAL_CMD_NAVIGATION= 0x77,
+ HAL_CMD_SWITCH_AGPS_DEBUG_DONE = 0x44,
+ HAL_CMD_SWITCH_AGPS_DEBUG_FAIL = 0X45,
+};
+
+
+
+#define M_START 0
+#define M_STOP 1
+#define M_CLEANUP 2
+#define M_INIT 3
+#define M_THREAD_EXIT 4
+#define M_MNLDIE 5
+typedef struct sync_lock
+{
+ pthread_mutex_t mutx;
+ pthread_cond_t con;
+ int condtion;
+}SYNC_LOCK_T;
+
+static SYNC_LOCK_T lock_for_sync[] = {{PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER, 0},
+ {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER, 0},
+ {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER, 0},
+ {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER, 0},
+ {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER, 0},
+ {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER, 0}};
+
+const char* gps_native_thread = "GPS NATIVE THREAD";
+const char* gps_pmtk_thread = "GPS PMTK THREAD";
+const char* gps_nmea_read_thread = "GPS NMEA READ THREAD";
+const char* gps_send_epo_thread = "GPS SEND EPO THREAD";
+static GpsCallbacks callback_backup;
+static int start_flag = 0;
+static int g_delete_aiding_data_flag = 0;
+
+//for different SV parse
+typedef enum{
+ UNKNOWN_SV = 0,
+ GPS_SV,
+ GLONASS_SV,
+ BDS_SV,
+ GALILEO_SV,
+}SV_TYPE;
+static float report_time_interval = 0;
+static int started = 0;
+
+//#define NMEA_MAX_SIZE 83
+#define NMEA_MAX_SIZE 255
+/*maximum number of SV information in GPGSV*/
+#define NMEA_MAX_SV_INFO 4
+#define LOC_FIXED(pNmeaReader) ((pNmeaReader->fix_mode == 2) || (pNmeaReader->fix_mode ==3))
+typedef struct {
+ int pos;
+ int overflow;
+ int utc_year;
+ int utc_mon;
+ int utc_day;
+ int utc_diff;
+ GpsLocation fix;
+
+ /*
+ * The fix flag extracted from GPGSA setence: 1: No fix; 2 = 2D; 3 = 3D
+ * if the fix mode is 0, no location will be reported via callback
+ * otherwise, the location will be reported via callback
+ */
+ int fix_mode;
+ /*
+ * Indicate that the status of callback handling.
+ * The flag is used to report GPS_STATUS_SESSION_BEGIN or GPS_STATUS_SESSION_END:
+ * (0) The flag will be set as true when callback setting is changed via nmea_reader_set_callback
+ * (1) GPS_STATUS_SESSION_BEGIN: receive location fix + flag set + callback is set
+ * (2) GPS_STATUS_SESSION_END: receive location fix + flag set + callback is null
+ */
+ int cb_status_changed;
+ int sv_count; /*used to count the number of received SV information*/
+ GnssSvStatus sv_status;
+ GpsCallbacks callbacks;
+ char in[ NMEA_MAX_SIZE + 1 ];
+} NmeaReader;
+
+typedef struct {
+ pthread_t thread;
+ int server_fd;
+}PMTKThread;
+
+/* this is the state of our connection to the daemon */
+typedef struct {
+ int init; // to check whether, have been initialized
+ int pow_fd; //power ctrl
+ int tty_fd; //for read nmea
+ GpsCallbacks callbacks; // up layer callback
+ pthread_t thread;
+ PMTKThread pmtk_thread[1];
+ pthread_t nmea_read_thread;
+ int control[2];
+ int test_time;
+ int epoll_hd;
+ int flag;
+ int start_flag;
+} GpsState;
+
+static GpsState _gps_state[1];
+
+/*****************************************************************/
+/*****************************************************************/
+/***** *****/
+/***** C O N N E C T I O N S T A T E *****/
+/***** *****/
+/*****************************************************************/
+/*****************************************************************/
+
+/* commands sent to the gps thread */
+enum {
+ CMD_QUIT = 0,
+ CMD_START = 1,
+ CMD_STOP = 2,
+ CMD_RESTART = 3,
+ CMD_DOWNLOAD = 4,
+
+ CMD_TEST_START = 10,
+ CMD_TEST_STOP = 11,
+ CMD_TEST_SMS_NO_RESULT = 12,
+ CMD_EPO_DOWNLOAD_DONE = 13,
+};
+
+
+static int gps_nmea_end_tag = 0;
+
+int sv_used_in_fix[256] = {0}; // for multiple sv display
+
+unsigned char calc_nmea_checksum( const char* sentence);
+void send_assistance_data (int iYr, int iMo, int iDay, int iHr, char * timeInfo, int iTimeLen);
+
+static void get_condition(SYNC_LOCK_T *lock)
+{
+ int ret = 0;
+
+ ret = pthread_mutex_lock(&(lock->mutx));
+ DBG("ret get_mutex lock = %d\n",ret);
+
+ while (!lock->condtion)
+ {
+ DBG("ret get_cond wait = %d\n" ,ret);
+ ret = pthread_cond_wait(&(lock->con), &(lock->mutx));
+ }
+
+ lock->condtion = 0;
+ DBG("ret get_mutex unlock = %d\n",ret);
+ ret = pthread_mutex_unlock(&(lock->mutx));
+ DBG("test");
+
+ return;
+}
+
+static void release_condition(SYNC_LOCK_T *lock)
+{
+ int ret = 0;
+
+
+ ret = pthread_mutex_lock(&(lock->mutx));
+ DBG("ret release_mutex lock = %d\n",ret);
+
+ lock->condtion= 1;
+ ret = pthread_cond_signal(&(lock->con));
+ DBG ("ret release_cond_signal = %d\n",ret);
+
+ ret = pthread_mutex_unlock(&(lock->mutx));
+ DBG("ret release_unlock= %d\n",ret);
+
+ return;
+}
+
+int mtk_restart(unsigned char cmd)
+{
+ char buf[] = {cmd};
+ TRC();
+ return 0;
+}
+
+/*****************************************************************/
+/*****************************************************************/
+/***** *****/
+/***** N M E A T O K E N I Z E R *****/
+/***** *****/
+/*****************************************************************/
+/*****************************************************************/
+
+typedef struct {
+ const char* p;
+ const char* end;
+} Token;
+
+#define MAX_NMEA_TOKENS 24
+
+typedef struct {
+ int count;
+ Token tokens[ MAX_NMEA_TOKENS ];
+} NmeaTokenizer;
+
+static int
+nmea_tokenizer_init( NmeaTokenizer* t, const char* p, const char* end ) {
+ int count = 0;
+ char* q;
+
+ // the initial '$' is optional
+ if (p < end && p[0] == '$')
+ p += 1;
+
+ // remove trailing newline
+ if (end > p && end[-1] == '\n') {
+ end -= 1;
+ if (end > p && end[-1] == '\r')
+ end -= 1;
+ }
+
+ // get rid of checksum at the end of the sentecne
+ if (end >= p+3 && end[-3] == '*') {
+ end -= 3;
+ }
+
+ while (p < end) {
+ const char* q = p;
+
+ q = memchr(p, ',', end-p);
+ if (q == NULL)
+ q = end;
+
+ if (q >= p) {
+ if (count < MAX_NMEA_TOKENS) {
+ t->tokens[count].p = p;
+ t->tokens[count].end = q;
+ count += 1;
+ }
+ }
+ if (q < end)
+ q += 1;
+
+ p = q;
+ }
+
+ t->count = count;
+ DBG(" t->count is %d", t->count);
+ return count;
+}
+
+static Token
+nmea_tokenizer_get( NmeaTokenizer* t, int index )
+{
+ Token tok;
+ static const char* dummy = "";
+
+ if (index < 0 || index >= t->count) {
+ tok.p = tok.end = dummy;
+ } else
+ tok = t->tokens[index];
+
+ return tok;
+}
+
+
+static int
+str2int( const char* p, const char* end )
+{
+ int result = 0;
+ int len = end - p;
+ int sign = 1;
+
+ if (*p == '-')
+ {
+ sign = -1;
+ p++;
+ len = end - p;
+ }
+
+ for ( ; len > 0; len--, p++ )
+ {
+ int c;
+
+ if (p >= end)
+ goto Fail;
+
+ c = *p - '0';
+ if ((unsigned)c >= 10)
+ goto Fail;
+
+ result = result*10 + c;
+ }
+ return sign*result;
+
+Fail:
+ return -1;
+}
+
+static double
+str2float( const char* p, const char* end )
+{
+ int result = 0;
+ int len = end - p;
+ char temp[16];
+
+ if (len >= (int)sizeof(temp))
+ return 0.;
+
+ memcpy( temp, p, len );
+ temp[len] = 0;
+ return strtod( temp, NULL );
+}
+
+static void mtk_gps_update_location(nlp_context * location)
+{
+ FILE *fp = NULL;
+
+ fp = fopen(LOCATION_NLP_FIX, "w");
+ if (fp != NULL)
+ {
+ size_t count = 0;
+ count = fwrite(location, sizeof(nlp_context), 1, fp);
+ if (count != 1)
+ {
+ DBG("write count:%d, errno:%s\n", count, strerror(errno));
+ }
+ fclose(fp);
+ }
+}
+
+static bool g_EpoSend = false;
+static void mtk_gps_send_EPO()
+{
+ time_t timep;
+ struct tm* pq;
+ time(&timep);
+ pq = gmtime(&timep);
+ char strBuf[200], outBuf[200];
+ memset(strBuf, 0, sizeof(strBuf));
+ memset(outBuf, 0, sizeof(outBuf));
+ sprintf(strBuf, "PMTK740,%d,%d,%d,%d,%d,%d",pq->tm_year + 1900, pq->tm_mon + 1, pq->tm_mday, pq->tm_hour, pq->tm_min, pq->tm_sec);
+ sprintf(outBuf, "$%s*%02X\r\n", strBuf, calc_nmea_checksum(strBuf));
+ DBG("final PMTK is %s, size is %d, len is %d", outBuf, sizeof(outBuf), strlen(outBuf));
+ send_assistance_data(pq->tm_year + 1900, pq->tm_mon + 1, pq->tm_mday, pq->tm_hour, outBuf, strlen(outBuf));
+}
+
+/*****************************************/
+/*****************************************/
+/***** *****/
+/***** PowerGPS PMTK handle *****/
+/***** *****/
+/****************************************/
+/****************************************/
+
+static bool g_ThreadExitPMTKIn = false;//flag for PowerGPS thread exist
+static int g_hPowerGPS = INVALID_FD;//PowerGPS socket handle
+static NmeaReader g_NmeaReader[1];
+
+/***************Receive From PowerGPS********************/
+void * pmtk_input_func(void * arg)
+{
+ int bytes = 0;
+ int ret = 0;
+ char pmtk_buf[200];
+ char cmd = CMD_RESTART;
+ GpsState* state = (GpsState*) arg;
+
+ while(g_ThreadExitPMTKIn)
+ {
+ memset(pmtk_buf, 0, sizeof(pmtk_buf));
+ bytes = read(g_hPowerGPS, pmtk_buf, 200);
+
+ if (bytes > 0)
+ {
+ DBG("!!!!!!!!!! PowerGPS pass : %s, lenth is %d", pmtk_buf, bytes);
+
+ do {
+ ret=write( state->control[0], &cmd, 1);
+ }
+ while (ret < 0 && errno == EINTR);
+ do {
+ ret=write( state->tty_fd, pmtk_buf, bytes);
+ }while (ret < 0 && errno == EINTR);
+ if (ret < 0)
+ DBG("!!!!!!!!!!!PowerGPS write FAIL, errno is %d (%s)", errno, strerror(errno));
+ else
+ DBG("!!!!!!!!!!!!!!PowerGPS write succeed, ret is %d", ret);
+ if (strstr(pmtk_buf, "PMTK101")
+ || strstr(pmtk_buf, "PMTK102")
+ || strstr(pmtk_buf, "PMTK103")
+ || strstr(pmtk_buf, "PMTK104"))
+ {
+ g_EpoSend = true;
+ DBG("!!!!!!!PowerGPS got A START %s", pmtk_buf);
+ }
+ }
+ else
+ {
+ if (bytes == 0)
+ { //client close
+ DBG("!!!!!!socket client close");
+ break;
+ }
+ else
+ {
+ usleep(200000); // sleep 200 ms
+ DBG("!!!!!!socket error = %d (%s)\r\n", errno, strerror(errno));
+ }
+ }
+ }
+ return NULL;
+}
+
+/***************Output To PowerGPS********************/
+void pmtk_output_func(char * buf, int * length)
+{
+ if (buf[(*length) - 2] != '\r'){
+ buf[(*length) - 1] = '\r';
+ buf[(*length)] = '\n';
+ (*length) += 1;
+ }
+ int len = (*length);
+ int ret = 0;
+ int written = 0;
+ int retry = 0;
+ if (g_hPowerGPS != INVALID_FD)
+ {
+ while( (written != len) && (retry <5))
+ {
+ ret = write(g_hPowerGPS, buf + written, len - written);
+ if (ret < 0)
+ {
+ retry++;
+ }
+ else
+ {
+ written += ret;
+ }
+ }
+ }
+}
+
+void powergps_thread_exit(int sig_no, int server_fd)
+{
+ if(server_fd != INVALID_SOCKET)
+ {
+ close(server_fd);
+ server_fd == INVALID_SOCKET;
+ }
+ pthread_exit((void *)0);
+}
+
+void signal_action_handle(int signum, siginfo_t * info, void *myact)
+{
+ DBG("######got Signal : %d", signum);
+}
+
+/*
+ *Create Socket Server to listen PMTK from PowerGPS
+ */
+void* powergps_pmtk_receive_thread( void* arg )
+{
+ TRC();
+ g_ThreadExitPMTKIn = true;
+ GpsState* state = (GpsState*) arg;
+ int server_fd = state->pmtk_thread->server_fd;
+
+ int conn_fd = INVALID_SOCKET, on;
+ struct sockaddr_in server_addr;
+ struct sockaddr_in client_addr;
+ socklen_t size;
+ int hdlsig = SIGUSR1;
+ struct sigaction sa;
+ char buf[128];
+
+ if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ {
+ DBG("socket error = %d (%s)\r\n", errno, strerror(errno));
+ pthread_exit((void *)0);
+ return NULL;
+ }
+ DBG("########### socket create SUCCESS - pid == %d, fd == %d", getpid(), server_fd);
+
+ /* Enable address reuse */
+ on = 1;
+ if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
+ {
+ close(server_fd);
+ pthread_exit((void *)0);
+ return NULL;
+ }
+ DBG("########### socket set SUCCESS");
+
+ server_addr.sin_family = AF_INET; /*host byte order*/
+ server_addr.sin_port = htons(PMTK_SOCKET_COM_PORT); /*short, network byte order*/
+ server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*automatically fill with my IP*/
+ memset(server_addr.sin_zero, 0x00, sizeof(server_addr.sin_zero));
+
+ if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1)
+ {
+ close(server_fd);
+ pthread_exit((void *)0);
+ return NULL;
+ }
+ DBG("########### socket bind SUCCESS");
+
+ if (listen(server_fd, PMTK_SERVER_BACKLOG) == -1)
+ {
+ close(server_fd);
+ pthread_exit((void *)0);
+ return NULL;
+ }
+ DBG("########### socket listen SUCCESS");
+
+ sa.sa_handler = SIG_IGN;
+ sa.sa_sigaction = signal_action_handle;
+ sa.sa_flags = (0 | SA_SIGINFO);
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(SIGPIPE, &sa, NULL) < 0)
+ {
+ DBG("sigaction error \r\n");
+ }
+
+ while (g_ThreadExitPMTKIn)
+ {
+ size = sizeof(client_addr);
+ DBG("########### waiting the client..........");
+ conn_fd = accept(server_fd, (struct sockaddr*)&client_addr, &size);
+ DBG("########### client comes in..........");
+
+ if (conn_fd <= 0)
+ {
+ DBG("######### no client");
+ close(server_fd);
+ break;
+ }
+ else
+ {
+ g_hPowerGPS = conn_fd;
+ pmtk_input_func(state);
+ }
+ }
+ powergps_thread_exit(0, server_fd);//call pthread_exit() in this function, the code after this sentence will not be executed
+ return NULL;
+}
+
+/*****************************************************************/
+/*****************************************************************/
+/***** *****/
+/***** N M E A P A R S E R *****/
+/***** *****/
+/*****************************************************************/
+/*****************************************************************/
+
+static void
+nmea_reader_update_utc_diff( NmeaReader* const r )
+{
+ time_t now = time(NULL);
+ struct tm tm_local;
+ struct tm tm_utc;
+ unsigned long time_local, time_utc;
+
+ gmtime_r( &now, &tm_utc );
+ localtime_r( &now, &tm_local );
+
+ time_local = mktime(&tm_local);
+ time_utc = mktime(&tm_utc);
+ r->utc_diff = time_utc - time_local;
+}
+
+
+static void
+nmea_reader_init( NmeaReader* const r )
+{
+ memset( r, 0, sizeof(*r) );
+
+ r->pos = 0;
+ r->overflow = 0;
+ r->utc_year = -1;
+ r->utc_mon = -1;
+ r->utc_day = -1;
+ r->utc_diff = 0;
+ r->callbacks.location_cb= NULL;
+ r->callbacks.status_cb= NULL;
+ r->callbacks.gnss_sv_status_cb= NULL;
+ r->sv_count = 0;
+ r->fix_mode = 0; /*no fix*/
+ r->cb_status_changed = 0;
+ memset((void*)&r->sv_status, 0x00, sizeof(r->sv_status));
+ memset((void*)&r->in, 0x00, sizeof(r->in));
+
+ nmea_reader_update_utc_diff( r );
+ r->fix.flags |= GPS_LOCATION_HAS_ACCURACY;
+ r->fix.accuracy = 10;
+}
+
+static void
+nmea_reader_set_callback( NmeaReader* const r, GpsCallbacks* const cbs)
+{
+ if (!r) { /*this should not happen*/
+ return;
+ } else if (!cbs) { /*unregister the callback */
+ return ;
+ } else {/*register the callback*/
+ r->sv_count = r->sv_status.num_svs = 0;
+ r->fix.flags |= GPS_LOCATION_HAS_ACCURACY;
+ r->fix.accuracy = 10;
+ }
+}
+
+
+static int
+nmea_reader_update_time( NmeaReader* const r, Token tok ) {
+ int hour, minute;
+ double seconds;
+ struct tm tm;
+ time_t fix_time;
+
+ if (tok.p + 6 > tok.end)
+ return -1;
+
+ memset((void*)&tm, 0x00, sizeof(tm));
+ if (r->utc_year < 0) {
+ // no date yet, get current one
+ time_t now = time(NULL);
+ gmtime_r( &now, &tm );
+ r->utc_year = tm.tm_year + 1900;
+ r->utc_mon = tm.tm_mon + 1;
+ r->utc_day = tm.tm_mday;
+ }
+
+ hour = str2int(tok.p, tok.p+2);
+ minute = str2int(tok.p+2, tok.p+4);
+ seconds = str2float(tok.p+4, tok.end);
+
+ tm.tm_hour = hour;
+ tm.tm_min = minute;
+ tm.tm_sec = (int) seconds;
+ tm.tm_year = r->utc_year - 1900;
+ tm.tm_mon = r->utc_mon - 1;
+ tm.tm_mday = r->utc_day;
+ tm.tm_isdst = -1;
+
+ if (mktime(&tm) == (time_t)-1)
+ ERR("mktime error: %d %s\n", errno, strerror(errno));
+
+ nmea_reader_update_utc_diff(r);
+
+ fix_time = mktime(&tm) - r->utc_diff;
+ DBG("fix_time: %d\n",fix_time);
+ r->fix.timestamp = (long long)fix_time * 1000;
+ return 0;
+}
+
+static int
+nmea_reader_update_date( NmeaReader* const r, Token date, Token time )
+{
+ Token tok = date;
+ int day, mon, year;
+
+ if (tok.p + 6 != tok.end) {
+ ERR("date not properly formatted: '%.*s'", tok.end-tok.p, tok.p);
+ return -1;
+ }
+ day = str2int(tok.p, tok.p+2);
+ mon = str2int(tok.p+2, tok.p+4);
+ year = str2int(tok.p+4, tok.p+6) + 2000;
+
+ if ((day|mon|year) < 0) {
+ ERR("date not properly formatted: '%.*s'", tok.end-tok.p, tok.p);
+ return -1;
+ }
+
+ r->utc_year = year;
+ r->utc_mon = mon;
+ r->utc_day = day;
+
+ return nmea_reader_update_time( r, time );
+}
+
+
+static double
+convert_from_hhmm( Token tok )
+{
+ double val = str2float(tok.p, tok.end);
+ int degrees = (int)(floor(val) / 100);
+ double minutes = val - degrees*100.;
+ double dcoord = degrees + minutes / 60.0;
+ return dcoord;
+}
+
+
+static int
+nmea_reader_update_latlong( NmeaReader* const r,
+ Token latitude,
+ char latitudeHemi,
+ Token longitude,
+ char longitudeHemi ) {
+ double lat, lon;
+ Token tok;
+
+ tok = latitude;
+ if (tok.p + 6 > tok.end) {
+ return -1;
+ }
+ lat = convert_from_hhmm(tok);
+ if (latitudeHemi == 'S')
+ lat = -lat;
+
+ tok = longitude;
+ if (tok.p + 6 > tok.end) {
+ return -1;
+ }
+ lon = convert_from_hhmm(tok);
+ if (longitudeHemi == 'W')
+ lon = -lon;
+
+ r->fix.flags |= GPS_LOCATION_HAS_LAT_LONG;
+ r->fix.latitude = lat;
+ r->fix.longitude = lon;
+ return 0;
+}
+
+static int
+nmea_reader_update_altitude( NmeaReader* const r,
+ Token altitude,
+ Token units ) {
+ double alt;
+ Token tok = altitude;
+
+ if (tok.p >= tok.end)
+ return -1;
+
+ r->fix.flags |= GPS_LOCATION_HAS_ALTITUDE;
+ r->fix.altitude = str2float(tok.p, tok.end);
+ return 0;
+}
+
+
+static int
+nmea_reader_update_bearing( NmeaReader* const r,
+ Token bearing )
+{
+ double alt;
+ Token tok = bearing;
+
+ if (tok.p >= tok.end)
+ return -1;
+
+ r->fix.flags |= GPS_LOCATION_HAS_BEARING;
+ r->fix.bearing = str2float(tok.p, tok.end);
+ return 0;
+}
+
+
+static int
+nmea_reader_update_speed( NmeaReader* const r,
+ Token speed )
+{
+ double alt;
+ Token tok = speed;
+
+ if (tok.p >= tok.end)
+ return -1;
+
+ r->fix.flags |= GPS_LOCATION_HAS_SPEED;
+
+ //Modify by ZQH to convert the speed unit from knot to m/s
+ //r->fix.speed = str2float(tok.p, tok.end);
+ r->fix.speed = str2float(tok.p, tok.end) / 1.942795467;
+ return 0;
+}
+
+//Add by LCH for accuracy
+static int
+nmea_reader_update_accuracy( NmeaReader* const r,
+ Token accuracy )
+{
+ double alt;
+ Token tok = accuracy;
+
+ if (tok.p >= tok.end)
+ return -1;
+
+ r->fix.flags |= GPS_LOCATION_HAS_ACCURACY;
+ r->fix.accuracy = str2float(tok.p, tok.end);
+ return 0;
+}
+
+static int
+nmea_reader_update_sv_status( NmeaReader* r, int sv_index,
+ int id, Token elevation,
+ Token azimuth, Token snr)
+{
+ //int prn = str2int(id.p, id.end);
+ int prn = id;
+
+ if ((prn <= 0) || (prn < 65 && prn > GPS_MAX_SVS)|| ((prn > 96) && (prn < 200)) || (prn > 232) || (r->sv_count >= GNSS_MAX_SVS)) {
+ VER("sv_status: ignore (%d)", prn);
+ return 0;
+ }
+ sv_index = r->sv_count+r->sv_status.num_svs;
+ if(GNSS_MAX_SVS <= sv_index)
+ {
+ ERR("ERR: sv_index=[%d] is larger than GNSS_MAX_SVS.\n", sv_index);
+ return 0;
+ }
+
+ if ((prn > 0) && (prn < 32)) {
+ r->sv_status.gnss_sv_list[sv_index].svid = prn;
+ r->sv_status.gnss_sv_list[sv_index].constellation = GPS_SV;
+ } else if ((prn >= 65) && (prn <= 96)) {
+ r->sv_status.gnss_sv_list[sv_index].svid = prn-64;
+ r->sv_status.gnss_sv_list[sv_index].constellation = GLONASS_SV;
+ } else if ((prn >= 201) && (prn <= 237)) {
+ r->sv_status.gnss_sv_list[sv_index].svid = prn-200;
+ r->sv_status.gnss_sv_list[sv_index].constellation = BDS_SV;
+ } else if ((prn >= 401) && (prn <= 436)) {
+ r->sv_status.gnss_sv_list[sv_index].svid = prn-400;
+ r->sv_status.gnss_sv_list[sv_index].constellation = GALILEO_SV;
+ } else {
+ DBG("sv_status: ignore (%d)", prn);
+ return 0;
+ }
+
+ r->sv_status.gnss_sv_list[sv_index].c_n0_dbhz = str2float(snr.p, snr.end);
+ r->sv_status.gnss_sv_list[sv_index].elevation = str2int(elevation.p, elevation.end);
+ r->sv_status.gnss_sv_list[sv_index].azimuth = str2int(azimuth.p, azimuth.end);
+ if(1 == sv_used_in_fix[prn]){
+ r->sv_status.gnss_sv_list[sv_index].flags |= 0x04;;
+ }else{
+ r->sv_status.gnss_sv_list[sv_index].flags &= 0xFB;
+ }
+ r->sv_count++;
+ DBG("sv_status(%2d): %2d, %d, %2f, %3f, %2f, %d",
+ sv_index, r->sv_status.gnss_sv_list[sv_index].svid, r->sv_status.gnss_sv_list[sv_index].constellation,
+ r->sv_status.gnss_sv_list[sv_index].elevation, r->sv_status.gnss_sv_list[sv_index].azimuth,
+ r->sv_status.gnss_sv_list[sv_index].c_n0_dbhz, r->sv_status.gnss_sv_list[sv_index].flags);
+ return 0;
+}
+
+static int
+nmea_reader_parse( NmeaReader* const r )
+{
+ /* we received a complete sentence, now parse it to generate
+ * a new GPS fix...
+ */
+ NmeaTokenizer tzer[1];
+ Token tok;
+ Token mtok;
+ SV_TYPE sv_type = 0;
+
+ /*
+ if (r->pos < 9) {
+ ERR("Too short. discarded. '%.*s'", r->pos, r->in);
+ return;
+ }
+ */
+
+ nmea_tokenizer_init(tzer, r->in, r->in + r->pos);
+
+#if NEMA_DEBUG
+ {
+ int n;
+ DBG("Found %d tokens", tzer->count);
+ for (n = 0; n < tzer->count; n++) {
+ Token tok = nmea_tokenizer_get(tzer,n);
+ DBG("%2d: '%.*s'", n, tok.end-tok.p, tok.p);
+ }
+ }
+#endif
+
+ tok = nmea_tokenizer_get(tzer, 0);
+ if (tok.p + 5 > tok.end) {
+ ERR("sentence id '%.*s' too short, ignored.", tok.end-tok.p, tok.p);
+ return -1;
+ }
+
+ // ignore first two characters.
+ mtok.p = tok.p; //Mark the first two char for GPS,GLONASS,BDS SV parse.
+ if(!memcmp(mtok.p, "BD", 2)){
+ sv_type = BDS_SV;
+ DBG("BDS SV type");
+ } else if (!memcmp(mtok.p, "GP", 2)) {
+ sv_type = GPS_SV;
+ } else if (!memcmp(mtok.p, "GL", 2)) {
+ sv_type = GLONASS_SV;
+ } else if (!memcmp(mtok.p, "GA", 2)) {
+ sv_type = GALILEO_SV;
+ }
+ #if NEMA_DEBUG
+ LOGD("SV type: %d", sv_type);
+ #endif
+ tok.p += 2;
+ if ( !memcmp(tok.p, "GGA", 3) )
+ {
+ if (tzer->count < 14)
+ return 0;
+ // GPS fix
+ Token tok_time = nmea_tokenizer_get(tzer,1);
+ Token tok_latitude = nmea_tokenizer_get(tzer,2);
+ Token tok_latitudeHemi = nmea_tokenizer_get(tzer,3);
+ Token tok_longitude = nmea_tokenizer_get(tzer,4);
+ Token tok_longitudeHemi = nmea_tokenizer_get(tzer,5);
+ Token tok_altitude = nmea_tokenizer_get(tzer,9);
+ Token tok_altitudeUnits = nmea_tokenizer_get(tzer,10);
+
+ nmea_reader_update_time(r, tok_time);
+ nmea_reader_update_latlong(r, tok_latitude,
+ tok_latitudeHemi.p[0],
+ tok_longitude,
+ tok_longitudeHemi.p[0]);
+ nmea_reader_update_altitude(r, tok_altitude, tok_altitudeUnits);
+
+ }
+ else if ( !memcmp(mtok.p, "GPGSA", 5)||!memcmp(mtok.p, "BDGSA", 5)||!memcmp(mtok.p, "GLGSA", 5)) {
+ if (tzer->count < 18)
+ return 0;
+ Token tok_fix = nmea_tokenizer_get(tzer, 2);
+ int idx, max = 12; /*the number of satellites in GPGSA*/
+
+ r->fix_mode = str2int(tok_fix.p, tok_fix.end);
+
+ if (LOC_FIXED(r)) { /* 1: No fix; 2: 2D; 3: 3D*/
+ for (idx = 0; idx < max; idx++) {
+ Token tok_satellite = nmea_tokenizer_get(tzer, idx+3);
+ if (tok_satellite.p == tok_satellite.end) {
+ break;
+ }
+ int sate_id = str2int(tok_satellite.p, tok_satellite.end);
+ if (sv_type == BDS_SV){
+ sate_id += 200;
+ }
+ if (sate_id >= 1 && sate_id <= 32) { //GP
+ sv_used_in_fix[sate_id] = 1;
+ }else if(sate_id >= 193 && sate_id <= 197){
+ sv_used_in_fix[sate_id] = 0;
+ continue;
+ }else if(sate_id >= 65 && sate_id <= 96){ //GL
+ sv_used_in_fix[sate_id] = 1;
+ }else if(sate_id >= 201 && sate_id <= 232){ //BD
+ sv_used_in_fix[sate_id] = 1;
+
+ }
+ else{
+ break;
+ }
+ }
+ }
+ }
+ //VER("GPGSA: mask 0x%x", r->sv_status.used_in_fix_mask);
+ else if ( !memcmp(tok.p, "RMC", 3) ) {
+ if (tzer->count < 13)
+ return 0;
+ Token tok_time = nmea_tokenizer_get(tzer,1);
+ Token tok_fixStatus = nmea_tokenizer_get(tzer,2);
+ Token tok_latitude = nmea_tokenizer_get(tzer,3);
+ Token tok_latitudeHemi = nmea_tokenizer_get(tzer,4);
+ Token tok_longitude = nmea_tokenizer_get(tzer,5);
+ Token tok_longitudeHemi = nmea_tokenizer_get(tzer,6);
+ Token tok_speed = nmea_tokenizer_get(tzer,7);
+ Token tok_bearing = nmea_tokenizer_get(tzer,8);
+ Token tok_date = nmea_tokenizer_get(tzer,9);
+
+ if (tok_fixStatus.p[0] == 'A') {
+ nmea_reader_update_date( r, tok_date, tok_time );
+ nmea_reader_update_latlong( r, tok_latitude,
+ tok_latitudeHemi.p[0],
+ tok_longitude,
+ tok_longitudeHemi.p[0] );
+ nmea_reader_update_bearing( r, tok_bearing );
+ nmea_reader_update_speed( r, tok_speed );
+ }
+ }
+ else if ( !memcmp(tok.p, "GSV", 3) ) {
+ if (tzer->count < 4)
+ return 0;
+ Token tok_num = nmea_tokenizer_get(tzer,1); //number of messages
+ Token tok_seq = nmea_tokenizer_get(tzer,2); //sequence number
+ Token tok_cnt = nmea_tokenizer_get(tzer,3); //Satellites in view
+ int num = str2int(tok_num.p, tok_num.end);
+ int seq = str2int(tok_seq.p, tok_seq.end);
+ int cnt = str2int(tok_cnt.p, tok_cnt.end);
+ int sv_base = (seq - 1)*NMEA_MAX_SV_INFO;
+ int sv_num = cnt - sv_base;
+ int idx, base = 4, base_idx;
+ if (sv_num > NMEA_MAX_SV_INFO)
+ sv_num = NMEA_MAX_SV_INFO;
+ if (seq == 1) /*if sequence number is 1, a new set of GSV will be parsed*/
+ r->sv_count = 0;
+ for (idx = 0; idx < sv_num; idx++) {
+ base_idx = base*(idx+1);
+ Token tok_id = nmea_tokenizer_get(tzer, base_idx+0);
+ int sv_id = str2int(tok_id.p, tok_id.end);
+ if (sv_type == BDS_SV)
+ sv_id += 200;
+ else if (sv_type == GALILEO_SV)
+ sv_id += 400;
+ Token tok_ele = nmea_tokenizer_get(tzer, base_idx+1);
+ Token tok_azi = nmea_tokenizer_get(tzer, base_idx+2);
+ Token tok_snr = nmea_tokenizer_get(tzer, base_idx+3);
+ nmea_reader_update_sv_status(r, sv_base+idx, sv_id, tok_ele, tok_azi, tok_snr);
+ }
+ if (seq == num) {
+ if (r->sv_count <= cnt) {
+ r->sv_status.num_svs += r->sv_count;
+ }
+ else {
+ ERR("GPGSV incomplete (%d/%d), ignored!", r->sv_count, cnt);
+ r->sv_count = r->sv_status.num_svs = 0;
+ }
+ }
+ }
+ //Add for Accuracy
+ else if ( !memcmp(tok.p, "ACCURACY", 8)) {
+ if((r->fix_mode == 3)||(r->fix_mode == 2)) {
+ Token tok_accuracy = nmea_tokenizer_get(tzer,1);
+ nmea_reader_update_accuracy(r, tok_accuracy);
+ }
+ }
+ else if ( !(memcmp(mtok.p, "GPBOD", 5)
+ && memcmp(mtok.p, "GPBWC", 5)
+ && memcmp(mtok.p, "GPGLL", 5)
+ && memcmp(mtok.p, "GPHDT", 5)
+ && memcmp(mtok.p, "GPROO", 5)
+ && memcmp(mtok.p, "GPRMA", 5)
+ && memcmp(mtok.p, "GPRMB", 5)
+ && memcmp(mtok.p, "GPRTE", 5)
+ && memcmp(mtok.p, "GPTRF", 5)
+ && memcmp(mtok.p, "GPSTN", 5)
+ && memcmp(mtok.p, "GPVBW", 5)
+ && memcmp(mtok.p, "GPVTG", 5)
+ && memcmp(mtok.p, "GPWPL", 5)
+ && memcmp(mtok.p, "GPXTE", 5)
+ && memcmp(mtok.p, "GPZDA", 5)))
+ {
+ tok.p -= 2;
+ }
+ else if ( !memcmp(mtok.p, "PMTK", 4))
+ {
+ tok.p -=2;
+ DBG("PMTK is %s", r->in);
+ if ( !memcmp(mtok.p, "PMTK010,002", 11) && g_EpoSend)
+ {
+ DBG("we got some START, ready to send EPO data");
+ callback_backup.create_thread_cb(gps_send_epo_thread, mtk_gps_send_EPO, NULL);
+ g_EpoSend = false;
+ }
+ /* disable QZSS start */
+ else if ( !memcmp(mtok.p, "PMTK010,001", 11))
+ {
+ DBG("we got some START, ready to send 352 cmd");
+ int temp_ret = 0;
+ temp_ret = write(_gps_state->tty_fd, "$PMTK352,1*2B\r\n", 15);
+ DBG("hao test : temp_ret is %d", temp_ret);
+ //g_EpoSend = false;
+ }
+ else if ( !memcmp(mtok.p, "PMTK001,352,3", 13))
+ {
+ DBG("received 352,3 response");
+ }
+ /* disable QZSS end */
+ return 0;
+ }
+ else {
+ tok.p -= 2;
+ return 0;
+ }
+ if (!LOC_FIXED(r)) {
+ VER("Location is not fixed, ignored callback\n");
+ }
+ else if (r->fix.flags != 0 && gps_nmea_end_tag) {
+#if NEMA_DEBUG
+ char temp[256];
+ char* p = temp;
+ char* end = p + sizeof(temp);
+ struct tm utc;
+
+ p += snprintf( p, end-p, "sending fix" );
+ if (r->fix.flags & GPS_LOCATION_HAS_LAT_LONG) {
+ p += snprintf(p, end-p, " lat=%g lon=%g", r->fix.latitude, r->fix.longitude);
+ }
+ if (r->fix.flags & GPS_LOCATION_HAS_ALTITUDE) {
+ p += snprintf(p, end-p, " altitude=%g", r->fix.altitude);
+ }
+ if (r->fix.flags & GPS_LOCATION_HAS_SPEED) {
+ p += snprintf(p, end-p, " speed=%g", r->fix.speed);
+ }
+ if (r->fix.flags & GPS_LOCATION_HAS_BEARING) {
+ p += snprintf(p, end-p, " bearing=%g", r->fix.bearing);
+ }
+ if (r->fix.flags & GPS_LOCATION_HAS_ACCURACY) {
+ p += snprintf(p,end-p, " accuracy=%g", r->fix.accuracy);
+ DBG("GPS accuracy=%g\n", r->fix.accuracy);
+ }
+ gmtime_r( (time_t*) &r->fix.timestamp, &utc );
+ p += snprintf(p, end-p, " time=%s", asctime( &utc ) );
+ VER(temp);
+#endif
+ callback_backup.location_cb(&r->fix);
+ {
+ nlp_context fix_location;
+ fix_location.latitude = r->fix.latitude;
+ fix_location.longitude= r->fix.longitude;
+ fix_location.accuracy= r->fix.accuracy;
+ fix_location.type = 1;
+ fix_location.started = started;
+ fix_location.ts.tv_sec = r->fix.timestamp/1000;
+ fix_location.ts.tv_nsec = (r->fix.timestamp%1000) * 1000*1000;
+ mtk_gps_update_location(&fix_location);
+ }
+ r->fix.flags = GPS_LOCATION_HAS_ACCURACY;
+ }
+
+ DBG("r->sv_status.num_svs = %d, gps_nmea_end_tag = %d", r->sv_status.num_svs,gps_nmea_end_tag);
+ if (r->sv_status.num_svs != 0 && gps_nmea_end_tag)
+ {
+ int idx;
+ r->sv_status.size = sizeof(GnssSvStatus);
+ callback_backup.gnss_sv_status_cb(&r->sv_status);
+ r->sv_count = r->sv_status.num_svs = 0;
+ memset( sv_used_in_fix, 0, 256*sizeof(int));
+ }
+ return 1;
+}
+
+
+static void
+nmea_reader_addc( NmeaReader* const r, int c )
+{
+ int ret = 0;
+ if (r->overflow) {
+ r->overflow = (c != '\n');
+ return;
+ }
+
+ if (r->pos >= (int) sizeof(r->in)-1 ) {
+ r->overflow = 1;
+ r->pos = 0;
+ DBG("nmea sentence overflow\n");
+ return;
+ }
+
+ r->in[r->pos] = (char)c;
+ r->pos += 1;
+ //DBG(" r->in[%d] is %c, r->pos is %d", r->pos, r->in[r->pos], r->pos);
+ if (c == '\n')
+ {
+ //r->pos < 9 :too short
+ if (gps_nmea_end_tag == 1 && r->pos >= 9) {
+ ret = nmea_reader_parse( r );
+ if (ret == 1)
+ {
+ DBG("ready to send : %s, strlen is %d, sizeof is %d", r->in, strlen(r->in), sizeof(r->in));
+ callback_backup.nmea_cb( r->fix.timestamp, r->in, r->pos );
+ pmtk_output_func( r->in, &(r->pos));
+ }
+ if (ret == 0)
+ {
+ pmtk_output_func(r->in, &(r->pos));
+ }
+ r->pos = 0;
+ }
+ else {
+ r->pos -=1;
+ }
+ }
+}
+
+static int
+epoll_register( int epoll_fd, int fd )
+{
+ struct epoll_event ev;
+ int ret, flags;
+
+ /* important: make the fd non-blocking */
+ flags = fcntl(fd, F_GETFL);
+ fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+
+ ev.events = EPOLLIN;
+ ev.data.fd = fd;
+ do {
+ ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev );
+ } while (ret < 0 && errno == EINTR);
+ if(ret < 0)
+ ERR("epoll ctl error, error num is %d\n, message is %s\n", errno, strerror(errno));
+ return ret;
+}
+
+
+static int
+epoll_deregister( int epoll_fd, int fd )
+{
+ int ret;
+ do {
+ ret = epoll_ctl( epoll_fd, EPOLL_CTL_DEL, fd, NULL );
+ } while (ret < 0 && errno == EINTR);
+ return ret;
+}
+
+void
+mtk_gps_start_driver()
+{
+ int fp = open("/dev/mt3337_gpsonly", O_RDWR);
+ if (fp == -1) {
+ DBG("open dev/mt3337_gpsonly fail, errorno is %d", errno);
+ }
+ else {
+ ioctl(fp, GPS_POWER_IOCTL, 1);
+ usleep(1000*200);
+ ioctl(fp, GPS_POWER_IOCTL, 0);
+ usleep(1000*200);
+ ioctl(fp, GPS_POWER_IOCTL, 1);
+ }
+ close(fp);
+}
+
+void
+mtk_gps_reset_driver()
+{
+ int fp = open("/dev/mt3337_gpsonly", O_RDWR);
+ if (fp == -1) {
+ DBG("open dev/mt3337_gpsonly fail, errorno is %d", errno);
+ }
+ else {
+ ioctl(fp, GPS_POWER_IOCTL, 0);
+ usleep(1000*1000);
+ ioctl(fp, GPS_POWER_IOCTL, 1);
+ }
+ close(fp);
+}
+
+void
+mtk_gps_stop_driver()
+{
+ int fp = open("/dev/mt3337_gpsonly", O_RDWR);
+ if (fp == -1) {
+ DBG("open dev/mt3337_gpsonly fail, errorno is %d", errno);
+ }
+ else {
+ ioctl(fp, GPS_POWER_IOCTL, 0);
+ }
+ close(fp);
+}
+
+void
+mnl_load_property()
+{
+ char result[512] = {0};
+ int iEpoDisable = 0;
+ int iHotstillEnable = 0;
+ GpsState* s = _gps_state;
+ int ret = 0;
+ if (property_get(MNL_CONFIG_STATUS, result, NULL))
+ {
+ iEpoDisable = result[7] - '0';
+ if (iEpoDisable == 0)
+ {
+ ret = write(s->tty_fd, "$PMTK127*36\r\n", 13);
+ DBG("we r going to clear EPO data, ret is %d", ret);
+ }
+ iHotstillEnable = result[4] - '0';
+ if (iHotstillEnable == 1)
+ {
+ ret = write(s->tty_fd, "$PMTK869,1,1*35\r\n", 17);
+ DBG("we r going to enable easy, ret is %d", ret);
+ }
+ else
+ {
+ ret = write(s->tty_fd, "$PMTK869,1,0*36\r\n", 17);
+ DBG("we r going to disable easy, ret is %d", ret);
+ }
+ }
+ else
+ {
+ DBG("YGPS config not set yet");
+ }
+}
+
+unsigned char
+calc_nmea_checksum( const char* sentence)
+{
+ unsigned char checksum = 0;
+ while (*sentence)
+ {
+ checksum ^= (unsigned char)*sentence++;
+ }
+
+ return checksum;
+}
+
+//translate UTC to GPS_Hour
+int
+utc_to_gps_hour( int iYr, int iMo, int iDay, int iHr)
+{
+ int iYearsElapsed;
+ int iDaysElapsed;
+ int iLeapDays;
+ int i;
+
+ const unsigned short doy[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+ iYearsElapsed = iYr - 1980;
+ i = 0;
+ iLeapDays = 0;
+
+ while (i <= iYearsElapsed)
+ {
+ if ((i % 100) == 20)
+ {
+ if ((i % 400) == 20)
+ {
+ iLeapDays++;
+ }
+ }
+ else if ((i % 4) == 0)
+ {
+ iLeapDays++;
+ }
+ i++;
+ }
+ if ((iYearsElapsed % 100) == 20)
+ {
+ if (((iYearsElapsed % 400) == 20) && (iMo <= 2))
+ {
+ iLeapDays--;
+ }
+ }
+ else if (((iYearsElapsed % 4) == 0) && (iMo <= 2))
+ {
+ iLeapDays--;
+ }
+ iDaysElapsed = iYearsElapsed*365 + (int)doy[iMo - 1] + iDay + iLeapDays - 6;
+
+ return (iDaysElapsed * 24 + iHr);
+}
+
+void
+send_assistance_data (int iYr, int iMo, int iDay, int iHr, char * timeInfo, int iTimeLen)
+{
+ TRC();
+ int fp, ret = 0;
+ int i, segment, epo_gps_hour, current_gps_hour;
+ unsigned epobuf[MTKEPO_RECORD_SIZE/sizeof(unsigned)];
+ char strbuf[200], outbuf[200];
+ GpsState* s = _gps_state;
+ // open EPO file and read the header (assume EPO file has passed integrity check)
+ fp = open(EPO_UPDATE_HAL, O_RDONLY);
+ if (fp < 0)
+ {
+ DBG("!!!!!!no EPO file ERROR: %d, %s", errno, strerror(errno));
+ return;
+ }
+ ret = read(fp, &epo_gps_hour, sizeof(int));
+ epo_gps_hour &= 0x00FFFFFF;
+
+ current_gps_hour = utc_to_gps_hour(iYr, iMo, iDay, iHr);
+ segment = (current_gps_hour - epo_gps_hour) / 6;
+ if ((segment < 0) || (segment >= MTKEPO_SEGMENT_NUM))
+ {
+ DBG("!!!!!segment ERROR : %d", segment);
+ return;
+ }
+ // read binary EPO data and sent it to MT3339
+ lseek(fp, segment*(MTKEPO_RECORD_SIZE)*(MTKEPO_SV_NUMBER), SEEK_SET);
+ DBG("ready to write time info before send EPO data");
+ ret = write(s->tty_fd, timeInfo, iTimeLen);
+ usleep(1000*200);
+ for (i = 0; i < MTKEPO_SV_NUMBER; i++)
+ {
+ read(fp, epobuf, MTKEPO_RECORD_SIZE);
+ // assume host system is little-endian
+ sprintf(strbuf,"PMTK721,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X",
+ i+1,
+ epobuf[0], epobuf[1], epobuf[2], epobuf[3], epobuf[4], epobuf[5],
+ epobuf[6], epobuf[7], epobuf[8], epobuf[9], epobuf[10], epobuf[11],
+ epobuf[12], epobuf[13], epobuf[14], epobuf[15], epobuf[16], epobuf[17]);
+ sprintf(outbuf, "$%s*%02X\r\n", strbuf, calc_nmea_checksum(strbuf));
+ // send them by UART
+ DBG("!!!!this EPO data len is %d,data is : %s", strlen(outbuf), outbuf); // for demo
+ for (int j = 0; j < 3; j++)
+ {
+ ret = write(s->tty_fd, outbuf, strlen(outbuf));
+ if (ret < 0)
+ DBG("Write EPO data fail, errno is %d", errno);
+ else
+ j = 3;
+ }
+ if (i%10 == 0)
+ usleep(1000*200);
+ }
+ close(fp);
+}
+
+/*for reducing the function call to get data from kernel*/
+static char buffGGA[2048];
+/*gps nmea read thread */
+static bool g_NmeaReadStart = false;
+static bool g_ThreadExistNmeaRead = false;
+static bool g_GpsDriverStart = false;
+static pthread_mutex_t g_mutx;
+
+void
+gps_read_nmea_from_uart_thread(void* arg)
+{
+ g_ThreadExistNmeaRead = true;
+ GpsState* state = (GpsState*) arg;
+ int fd = state->tty_fd;
+ while (g_ThreadExistNmeaRead)
+ {
+ if(g_GpsDriverStart && g_NmeaReadStart)
+ {
+ int nn, ret;
+ memset(buffGGA, 0, sizeof(buffGGA));
+ ret = read( fd, buffGGA, sizeof(buffGGA) );
+ gps_nmea_end_tag = 0;
+
+ DBG("before PARSE buffer[%d] is:%s.", ret, buffGGA);
+ memset(g_NmeaReader->in, 0, sizeof(g_NmeaReader->in));
+ for (nn = 0; nn < ret && g_GpsDriverStart; nn++)
+ {
+ if(nn == (ret-1))
+ gps_nmea_end_tag = 1;
+
+ nmea_reader_addc( g_NmeaReader, buffGGA[nn] );
+ }
+ g_NmeaReadStart = false;
+ }
+ usleep(100);
+ }
+ DBG("gps_read_nmea_from_uart_thread exit!");
+}
+/* this is the main thread, it waits for commands from gps_state_start/stop and,
+ * when started, messages from the GPS daemon. these are simple NMEA sentences
+ * that must be parsed to be converted into GPS fixes sent to the framework
+ */
+void
+gps_state_thread( void* arg )
+{
+ static float count = 0;
+ GpsState* state = (GpsState*) arg;
+ state->test_time += 1;
+ int tty_fd = state->tty_fd;
+ int control_fd = state->control[1];
+ int pow_fd = state->pow_fd;
+
+ int epoll_fd = state->epoll_hd;
+ int test_started = 0;
+
+ nmea_reader_init( g_NmeaReader );
+
+ // register control file descriptors for polling
+ if(epoll_register( epoll_fd, control_fd ) < 0)
+ ERR("control_fd register control_fd error, error num is %d\n, message is %s\n", errno, strerror(errno));
+ if(epoll_register( epoll_fd, tty_fd) < 0)
+ ERR("tty_fd register control_fd error, error num is %d\n, message is %s\n", errno, strerror(errno));
+ //if(epoll_register( epoll_fd, pow_fd) < 0)
+ if(mnldinf_epoll_add_fd( epoll_fd, pow_fd) < 0)
+ ERR("pow_fd register control_fd error, error num is %d\n, message is %s\n", errno, strerror(errno));
+
+ release_condition(&lock_for_sync[M_INIT]);
+
+ // now loop
+ for (;;)
+ {
+ struct epoll_event events[5];
+ int ne, nevents;
+ nevents = epoll_wait( epoll_fd, events, 5, -1 );
+ if (nevents < 0)
+ {
+ if (errno != EINTR)
+ ERR("epoll_wait() unexpected error: %s", strerror(errno));
+ continue;
+ }
+
+ for (ne = 0; ne < nevents; ne++)
+ {
+ if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0)
+ {
+ ERR("EPOLLERR or EPOLLHUP after epoll_wait() !?");
+ goto Exit;
+ }
+ if ((events[ne].events & EPOLLIN) != 0)
+ {
+ int fd = events[ne].data.fd;
+
+ if (fd == pow_fd)
+ {
+ ERR("!!!!!!!!!!!EPO donwload done");
+ char cmd = 255;
+ int ret;
+
+ //socket
+ char epo_buff[100] = {0};
+ int offset = 0;
+ int read_len;
+
+ read_len = safe_recvfrom(fd, epo_buff, sizeof(epo_buff));
+ if (read_len <= 0) {
+ DBG("@@@@@@@@@gpsinf3337() safe_recvfrom() failed read_len=%d", read_len);
+ break;
+ }
+ cmd = get_int(epo_buff, &offset, sizeof(epo_buff));
+
+ if (cmd == CMD_EPO_DOWNLOAD_DONE) {
+ DBG("@@@@@@@@@@@@got the EPO download msg");
+ callback_backup.create_thread_cb(gps_send_epo_thread, mtk_gps_send_EPO, NULL);
+ }
+ }
+ else if (fd == control_fd)
+ {
+ char cmd = 255;
+ int ret;
+ do {
+ ret = read( fd, &cmd, 1 );
+ } while (ret < 0 && errno == EINTR);
+
+ if (cmd == CMD_QUIT) {
+ DBG("gps thread quitting on demand");
+ goto Exit;
+ }
+ else if (cmd == CMD_START) {
+ if (!started) {
+ started = 1;
+ nmea_reader_set_callback( g_NmeaReader, &state->callbacks);
+ switch (g_delete_aiding_data_flag) {
+ case 1:
+ DBG("Last time's delete_aiding : hot start");
+ ret = write(tty_fd, "$PMTK101*32\r\n", 13);
+ g_EpoSend = true;
+ break;
+ case 2:
+ DBG("Last time's delete_aiding : warm start");
+ ret = write(tty_fd, "$PMTK102*31\r\n", 13);
+ g_EpoSend = true;
+ break;
+ case 3:
+ DBG("Last time's delete_aiding : cold start");
+ ret = write(tty_fd, "$PMTK103*30\r\n", 13);
+ g_EpoSend = true;
+ break;
+ case 4:
+ DBG("Last time's delete_aiding : full start");
+ ret = write(tty_fd, "$PMTK104*37\r\n", 13);
+ g_EpoSend = true;
+ break;
+ default:
+ break;
+ }
+ g_delete_aiding_data_flag = 0;
+ }
+ }
+ else if (cmd == CMD_STOP) {
+ if (started) {
+ started = 0;
+ nmea_reader_set_callback( g_NmeaReader, NULL );
+ release_condition(&lock_for_sync[M_STOP]);
+ DBG("CMD_STOP has been receiving from HAL thread, release lock so can handle CLEAN_UP\n");
+ }
+ }
+ else if (cmd == CMD_RESTART) {
+ g_NmeaReader->fix_mode = 0;
+ DBG("gps 3337 restart!!!!");
+ }
+ }
+ else if (fd == tty_fd)
+ {
+ if(!flag_unlock)
+ {
+ release_condition(&lock_for_sync[M_START]);
+ flag_unlock = 1;
+ DBG("got first NMEA sentence, release lock to set state ENGINE ON, SESSION BEGIN");
+ }
+ if(report_time_interval > ++count){
+ DBG("[trace]count is %f\n", count);
+ //int ret = read( fd, buff, sizeof(buff) );
+ continue;
+ }
+ count = 0;
+ g_NmeaReadStart = true;
+ }
+ }
+ }
+ }
+Exit:
+ DBG("HAL thread is exiting, release lock to clean resources\n");
+ release_condition(&lock_for_sync[M_CLEANUP]);
+ return;
+}
+static void
+gps_state_done( GpsState* s )
+{
+ TRC();
+ char cmd = CMD_QUIT;
+
+ write( s->control[0], &cmd, 1 );
+ get_condition(&lock_for_sync[M_CLEANUP]);
+
+ g_ThreadExitPMTKIn = false;
+ g_hPowerGPS = INVALID_FD;
+ pthread_join(s->pmtk_thread->thread, NULL);
+ g_ThreadExistNmeaRead = false;
+ pthread_join(s->nmea_read_thread, NULL);
+
+ close( s->control[0] ); s->control[0] = -1;
+ close( s->control[1] ); s->control[1] = -1;
+ close( s->pow_fd ); s->pow_fd = -1;
+ close( s->tty_fd ); s->tty_fd = -1;
+ close(s->epoll_hd); s->epoll_hd = -1;
+ s->init = 0;
+ s->test_time -= 1;
+ DBG("GPS cleanup done");
+
+ return;
+}
+
+
+static void
+gps_state_start( GpsState* s )
+{
+ char cmd = CMD_START;
+ int ret;
+
+ do { ret=write( s->control[0], &cmd, 1 ); }
+ while (ret < 0 && errno == EINTR);
+
+ if (ret != 1)
+ ERR("%s: could not send CMD_START command: ret=%d: %s",
+ __FUNCTION__, ret, strerror(errno));
+}
+
+static void
+gps_state_stop( GpsState* s )
+{
+ char cmd = CMD_STOP;
+ int ret;
+
+ do { ret=write( s->control[0], &cmd, 1 ); }
+ while (ret < 0 && errno == EINTR);
+
+ if (ret != 1)
+ ERR("%s: could not send CMD_STOP command: ret=%d: %s",
+ __FUNCTION__, ret, strerror(errno));
+}
+
+static void
+gps_state_restart( GpsState* s )
+{
+ char cmd = CMD_RESTART;
+ int ret;
+
+ do { ret=write( s->control[0], &cmd, 1 ); }
+ while (ret < 0 && errno == EINTR);
+
+ if (ret != 1)
+ ERR("%s: could not send CMD_RESTART command: ret=%d: %s",
+ __FUNCTION__, ret, strerror(errno));
+}
+
+
+static void
+gps_state_init( GpsState* state )
+{
+ state->control[0] = -1;
+ state->control[1] = -1;
+ state->pow_fd = -1;
+ state->tty_fd = -1;
+
+ TRC();
+
+ //socket
+ state->pow_fd = socket_bind_udp(MNLD_HAL2GPS);
+ socket_set_blocking(state->pow_fd, 0);
+ if (state->pow_fd < 0) {
+ ERR("no gps hardware detected: %s:%d, %s", MNLD_HAL2GPS, state->pow_fd, strerror(errno));
+ return;
+ }
+
+ state->tty_fd = open(GPS_TTY_NAME, O_RDWR | O_NOCTTY | O_NONBLOCK);
+ if (state->tty_fd < 0) {
+ close(state->pow_fd);
+ state->pow_fd = -1;
+ ERR("no gps hardware detected: %s:%d, %s", GPS_TTY_NAME, state->tty_fd, strerror(errno));
+ return;
+ }
+ struct termios options;
+ int i4_baud = B115200;
+ tcgetattr(state->tty_fd, &options);
+ cfsetispeed(&options, i4_baud);
+ cfsetospeed(&options, i4_baud);
+
+ options.c_cflag |= (CLOCAL | CREAD);
+ options.c_cflag &= ~PARENB;
+ options.c_cflag &= ~CSTOPB;
+ options.c_cflag &= ~CSIZE;
+ options.c_cflag &= ~PARODD;
+ options.c_cflag |= CS8;
+ options.c_cflag &= ~CRTSCTS;
+ options.c_lflag &= ~(ISIG | ECHO);
+ options.c_oflag &= ~OPOST;
+ options.c_iflag &= ~(INLCR | INPCK | ISTRIP | IXON | BRKINT );
+ options.c_cc[VMIN] = 1;
+ options.c_cc[VTIME] = 0;
+ tcsetattr(state->tty_fd, TCSANOW, &options);
+
+ int epoll_fd = epoll_create(3);
+ state->epoll_hd = epoll_fd;
+
+ if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) {
+ ERR("could not create thread control socket pair: %s", strerror(errno));
+ goto Fail;
+ }
+ state->thread = callback_backup.create_thread_cb(gps_native_thread, gps_state_thread, state);
+ if (!state->thread){
+ ERR("could not create gps thread: %s", strerror(errno));
+ goto Fail;
+ }
+
+ DBG("gps state initialized, the thread is %d\n", (int)state->thread);
+ if (!g_ThreadExitPMTKIn)
+ {
+ state->pmtk_thread->thread= callback_backup.create_thread_cb(gps_pmtk_thread, powergps_pmtk_receive_thread, state);
+ if (!state->pmtk_thread->thread){
+ ERR("could not create gps pmtk thread: %s", strerror(errno));
+ goto Fail;
+ }
+ }
+
+ if (!g_ThreadExistNmeaRead)
+ {
+ state->nmea_read_thread = callback_backup.create_thread_cb(gps_nmea_read_thread, gps_read_nmea_from_uart_thread, state);
+ if (!state->nmea_read_thread){
+ ERR("could not create nmea read thread: %s", strerror(errno));
+ goto Fail;
+ }
+ }
+
+ DBG("gps PMTK initialized, the thread is %d\n", (int)state->pmtk_thread->thread);
+
+ return;
+
+Fail:
+ gps_state_done( state );
+}
+
+
+/*****************************************************************/
+/*****************************************************************/
+/***** *****/
+/***** I N T E R F A C E *****/
+/***** *****/
+/*****************************************************************/
+/*****************************************************************/
+static int
+mtk_gps_mt3337_init(GpsCallbacks* callbacks)
+{
+ TRC();
+ GpsState* s = _gps_state;
+ int get_time = 20;
+ int res = 0;
+ if(s->init)
+ return 0;
+ s->callbacks = *callbacks;
+ callback_backup = *callbacks;
+
+ gps_state_init(s);
+ get_condition(&lock_for_sync[M_INIT]);
+ usleep(1000*1);
+ s->init = 1;
+ DBG("Set GPS_CAPABILITY_SCHEDULING \n");
+ callback_backup.set_capabilities_cb(GPS_CAPABILITY_SCHEDULING);
+
+ if (gpshal_gpscbs_save(callbacks) != 0) {
+ return -1; // error
+ }
+
+ gpshal_set_gps_state_intent(GPSHAL_STATE_INIT);
+ gpshal2mnl_gps_init();
+ return 0;
+}
+
+static void
+mtk_gps_mt3337_cleanup(void)
+{
+ GpsState* s = _gps_state;
+
+ TRC();
+
+ if(s->start_flag)
+ get_condition(&lock_for_sync[M_STOP]); //make sure gps_stop has set state to GPS_STATUS_ENGINE_OFF by callback function
+ if(lock_for_sync[M_STOP].condtion == 1)
+ {
+ lock_for_sync[M_STOP].condtion = 0; //make sure gps_stop has set state to GPS_STATUS_ENGINE_OFF in next time
+ }
+ if (s->init)
+ gps_state_done(s);
+ gpshal_set_gps_state_intent(GPSHAL_STATE_CLEANUP);
+ gpshal2mnl_gps_cleanup();
+ DBG("mtk_gps_cleanup done");
+}
+
+int
+mtk_gps_mt3337_start()
+{
+ TRC();
+ GpsState* s = _gps_state;
+ int err;
+ int count=0;
+
+
+ if (!s->init) {
+ ERR("%s: called with uninitialized state !!", __FUNCTION__);
+ return -1;
+ }
+
+ while(s->start_flag == 1)
+ {
+ usleep(100000);
+ count++;
+ DBG("mtk_gps_start:start_flag = %d delay=%d \n",s->start_flag,count*100);
+ }
+ mtk_gps_start_driver();
+ g_GpsDriverStart = true;
+ DBG("mtk_gps_mt3337_start done!!!!");
+ mnl_load_property();
+
+ get_condition(&lock_for_sync[M_START]);
+ gps_state_start(s);
+
+ sta.status = GPS_STATUS_ENGINE_ON;
+ callback_backup.status_cb(&sta);
+ sta.status = GPS_STATUS_SESSION_BEGIN;
+ callback_backup.status_cb(&sta);
+
+ callback_backup.acquire_wakelock_cb();//avoid cpu to sleep
+ s->start_flag = 1;
+
+ gpshal_set_gps_state_intent(GPSHAL_STATE_START);
+ gpshal2mnl_gps_start();
+ return 0;
+}
+
+int
+mtk_gps_mt3337_stop()
+{
+ TRC();
+ GpsState* s = _gps_state;
+ int err;
+ int count=0;
+
+ if (!s->init) {
+ ERR("%s: called with uninitialized state !!", __FUNCTION__);
+ return -1;
+ }
+
+ while(s->start_flag == 0)
+ {
+ usleep(100000);
+ count++;
+ DBG("mtk_gps_stop:start_flag = %d delay=%d \n",s->start_flag,count*100);
+ }
+ s->start_flag = 0;
+
+ mtk_gps_stop_driver();
+ g_GpsDriverStart = false;
+ flag_unlock = 0;
+ gps_state_stop(s);
+ gpshal_set_gps_state_intent(GPSHAL_STATE_STOP);
+ gpshal2mnl_gps_stop();
+
+ callback_backup.release_wakelock_cb();
+ DBG("mtk_gps_mt3337_STOP done!!!!");
+ return 0;
+}
+
+static int
+mtk_gps_mt3337_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty)
+{
+ ntp_context inject_ntp;
+ long long time_s = 0;
+ int offset = 0;
+
+ TRC();
+ time_s = time/1000;
+ DBG("inject time= %lld,ctime = %s, timeReference = %lld,uncertainty =%d\n", time,ctime(&time_s), timeReference,uncertainty);
+ memcpy(&(inject_ntp.time),&time,sizeof(GpsUtcTime));
+ inject_ntp.timeReference = timeReference;
+ inject_ntp.uncertainty = uncertainty;
+
+ //do not support detail function
+ return 0;
+}
+
+static int
+mtk_gps_mt3337_inject_location(double latitude, double longitude, float accuracy)
+{
+ nlp_context nlp_location;
+ int offset = 0;
+
+ if(clock_gettime(CLOCK_MONOTONIC , &nlp_location.ts) == -1)
+ {
+ ERR("clock_gettime failed reason=[%s]\n",strerror(errno));
+ return -1;
+ }
+ DBG("ts.tv_sec= %lld,ts.tv_nsec = %lld\n", nlp_location.ts.tv_sec,nlp_location.ts.tv_nsec);
+ DBG("inject location lati= %f, longi = %f,accuracy =%f\n", latitude, longitude,accuracy);
+
+ //do not support detail function
+ return 0;
+}
+
+static void
+mtk_gps_mt3337_delete_aiding_data(GpsAidingData flags)
+{
+ /*workaround to trigger hot/warm/cold/full start*/
+ #define FLAG_HOT_START GPS_DELETE_RTI
+ #define FLAG_WARM_START GPS_DELETE_EPHEMERIS
+ #define FLAG_COLD_START (GPS_DELETE_EPHEMERIS | GPS_DELETE_POSITION | GPS_DELETE_TIME | GPS_DELETE_IONO | GPS_DELETE_UTC | GPS_DELETE_HEALTH)
+ #define FLAG_FULL_START (GPS_DELETE_ALL)
+ #define FLAG_AGPS_START (GPS_DELETE_EPHEMERIS | GPS_DELETE_ALMANAC | GPS_DELETE_POSITION | GPS_DELETE_TIME | GPS_DELETE_IONO | GPS_DELETE_UTC)
+ GpsState* s = _gps_state;
+ int ret;
+
+ DBG("%s:0x%X\n", __FUNCTION__, flags);
+
+ gps_state_restart(s);
+
+ if (flags == FLAG_HOT_START)
+ {
+ mtk_restart(MNL_CMD_RESTART_HOT);
+ if (g_GpsDriverStart)
+ {
+ DBG("GPS driver still start!!! send it HOT_START!!!");
+ ret = write(s->tty_fd, "$PMTK101*32\r\n", 13);
+ if (ret < 0)
+ DBG("HOT_START FAILED!!! error is %d : %s", errno, strerror(errno));
+ g_EpoSend = true;
+ }
+ else
+ {
+ g_delete_aiding_data_flag = 1;
+ }
+ }
+ else if (flags == FLAG_WARM_START)
+ {
+ mtk_restart(MNL_CMD_RESTART_WARM);
+ if (g_GpsDriverStart)
+ {
+ DBG("GPS driver still start!!! send it WARM_START!!!");
+ ret = write(s->tty_fd, "$PMTK102*31\r\n", 13);
+ if (ret < 0)
+ DBG("WARM_START FAILED!!! error is %d : %s", errno, strerror(errno));
+ g_EpoSend = true;
+ }
+ else
+ {
+ g_delete_aiding_data_flag = 2;
+ }
+ }
+ else if (flags == FLAG_COLD_START)
+ {
+ mtk_restart(MNL_CMD_RESTART_HOT);
+ if (g_GpsDriverStart)
+ {
+ DBG("GPS driver still start!!! send it COLD_START!!!");
+ ret = write(s->tty_fd, "$PMTK103*30\r\n", 13);
+ if (ret < 0)
+ DBG("COLD_START FAILED!!! error is %d : %s", errno, strerror(errno));
+ g_EpoSend = true;
+ }
+ else
+ {
+ g_delete_aiding_data_flag = 3;
+ }
+ }
+ else if (flags == FLAG_FULL_START)
+ {
+ mtk_restart(MNL_CMD_RESTART_HOT);
+ if (g_GpsDriverStart)
+ {
+ DBG("GPS driver still start!!! send it COLD_START!!!");
+ ret = write(s->tty_fd, "$PMTK104*37\r\n", 13);
+ if (ret < 0)
+ DBG("FULL_START FAILED!!! error is %d : %s", errno, strerror(errno));
+ g_EpoSend = true;
+ }
+ else
+ {
+ g_delete_aiding_data_flag = 4;
+ }
+ }
+ else if(flags == FLAG_AGPS_START)
+ {
+ DBG("Send MNL_CMD_RESTART_AGPS in HAL\n");
+ mtk_restart(MNL_CMD_RESTART_AGPS);
+ }
+}
+
+static int mtk_gps_mt3337_set_position_mode(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+ uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time)
+{
+ // FIXME - support fix_frequency
+ // only standalone supported for now.
+ DBG("set report location time interval is %d\n", min_interval);
+ if(min_interval <= 1000)
+ report_time_interval = 1;
+ else
+ report_time_interval = (float)min_interval/1000;
+ DBG("set report location time interval is %f s\n", report_time_interval);
+ TRC();
+ return 0;
+}
+
+static const void*
+mtk_gps_mt3337_get_extension(const char* name)
+{
+ TRC();
+ DBG("mtk_gps_get_extension name=[%s]\n", name);
+ if (strcmp(name, AGPS_RIL_INTERFACE) == 0) {
+ return &mtk_agps_ril_inf;
+ }
+/*
+#if EPO_SUPPORT
+ if (!strcmp(name, GPS_XTRA_INTERFACE))
+ return (void*)(&mtkGpsXtraInterface);
+#endif
+*/
+ return NULL;
+}
+
+static const GpsInterface mtkGpsInterface = {
+ sizeof(GpsInterface),
+ mtk_gps_mt3337_init,
+ mtk_gps_mt3337_start,
+ mtk_gps_mt3337_stop,
+ mtk_gps_mt3337_cleanup,
+ mtk_gps_mt3337_inject_time,
+ mtk_gps_mt3337_inject_location,
+ mtk_gps_mt3337_delete_aiding_data,
+ mtk_gps_mt3337_set_position_mode,
+ mtk_gps_mt3337_get_extension,
+};
+
+//=========================================================
+// Between
+// Gps Interface
+// Hardware Module Interface
+
+static const GpsInterface* gps_device__get_gps_interface(
+ __unused struct gps_device_t* device) {
+ /*
+ * hao mt3337 modify
+ * GPS_DEVICE__GET_GPS_INTERFACE__CHECK_PARAM;
+ * hal2mnl_hal_reboot();
+ */
+ return &mtkGpsInterface;
+}
+
+static const struct gps_device_t gps_device = {
+ .common = { // hw_device_t
+ .tag = HARDWARE_DEVICE_TAG,
+ .version = 0, // GPS JNI will not use it
+ .module = &HAL_MODULE_INFO_SYM,
+ .reserved = {0},
+ .close = NULL // GPS JNI will not call it
+ },
+ .get_gps_interface = gps_device__get_gps_interface
+};
+
+
+static int open_gps(const struct hw_module_t* module, char const* name,
+ struct hw_device_t** device)
+{
+ DBG("open_gps HAL 1\n");
+ *device = (struct hw_device_t*)&gps_device;
+ return 0;
+}
+
+
+static struct hw_module_methods_t gps_module_methods = {
+ .open = open_gps
+};
+
+
+struct hw_module_t HAL_MODULE_INFO_SYM = {
+ .tag = HARDWARE_MODULE_TAG,
+ .version_major = 1,
+ .version_minor = 0,
+ .id = GPS_HARDWARE_MODULE_ID,
+ .name = "MediaTek GPS Hardware Module",
+ .author = "MediaTek, Inc.",
+ .methods = &gps_module_methods,
+ .dso = NULL,
+ .reserved = {0}
+};
diff --git a/src/connectivity/gps/2.0/gps_hal/src/hal2mnl_interface.c b/src/connectivity/gps/2.0/gps_hal/src/hal2mnl_interface.c
new file mode 100644
index 0000000..d808d55
--- /dev/null
+++ b/src/connectivity/gps/2.0/gps_hal/src/hal2mnl_interface.c
@@ -0,0 +1,179 @@
+#include "hal2mnl_interface.h"
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#ifdef __ANDROID_OS__
+#include <cutils/sockets.h>
+#include <log/log.h> /*logging in logcat*/
+#endif
+#include "hardware/gps_mtk.h"
+#include "gpshal.h"
+#include "errno.h"
+#include "mnldinf_log.h"
+#include "mnldinf_utility.h"
+#include "mnldinf_data_coder.h"
+
+float count = 0;
+float report_time_interval = 0;
+extern gpshal_context_t g_gpshal_ctx;
+
+int hal2mnl_hal_reboot() {
+ LOGD("hal2mnl_hal_reboot");
+ return 0;
+ #if 0
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ mnldinf_put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+ mnldinf_put_int(buff, &offset, HAL2MNL_HAL_REBOOT);
+
+ return mnldinf_safe_sendto(MTK_HAL2MNL, buff, offset);
+ #endif
+}
+
+int hal2mnl_gps_init() {
+ return mnldinf_basic_gnss_init(g_gpshal_ctx.fd_mnl2hal_basic);
+}
+
+int hal2mnl_gps_start() {
+ return mnldinf_basic_gnss_start(g_gpshal_ctx.fd_mnl2hal_basic);
+}
+int hal2mnl_gps_stop() {
+ return mnldinf_basic_gnss_stop(g_gpshal_ctx.fd_mnl2hal_basic);
+}
+
+int hal2mnl_gps_cleanup() {
+ return mnldinf_basic_gnss_cleanup(g_gpshal_ctx.fd_mnl2hal_basic);
+}
+
+int hal2mnl_gps_inject_time(int64_t time, int64_t time_reference, int uncertainty) {
+ return mnldinf_ext_gnss_inject_time(g_gpshal_ctx.fd_mnl2hal_ext, time, time_reference, uncertainty);
+}
+
+int hal2mnl_gps_inject_location(double lat, double lng, float acc) {
+ return mnldinf_ext_gnss_inject_location(g_gpshal_ctx.fd_mnl2hal_ext, lat, lng, acc);
+}
+
+int hal2mnl_gps_delete_aiding_data(int flags) {
+ return mnldinf_ext_gnss_delete_aiding_data(g_gpshal_ctx.fd_mnl2hal_ext, flags);
+}
+
+int hal2mnl_gps_set_position_mode(gps_pos_mode mode, gps_pos_recurrence recurrence,
+ int min_interval, int preferred_acc, int preferred_time, bool lowPowerMode) {
+
+ if (min_interval <= 1000) {
+ report_time_interval = 1;
+ } else {
+ report_time_interval = (float)min_interval/1000;
+ }
+ LOGD("set report location time interval is %f s\n", report_time_interval);
+
+ return mnldinf_ext_gnss_set_position_mode(g_gpshal_ctx.fd_mnl2hal_ext, mode);
+}
+
+int hal2mnl_data_conn_open(const char* apn) {
+ return mnldinf_ext_data_conn_open(g_gpshal_ctx.fd_mnl2hal_ext, apn);
+}
+
+int hal2mnl_data_conn_open_with_apn_ip_type(uint64_t networkHandle, const char* apn, apn_ip_type ip_type) {
+ return mnldinf_ext_data_conn_open_with_apn_ip_type(g_gpshal_ctx.fd_mnl2hal_ext, networkHandle, apn, ip_type);
+}
+
+int hal2mnl_data_conn_closed() {
+ return mnldinf_ext_data_conn_closed(g_gpshal_ctx.fd_mnl2hal_ext);
+}
+
+int hal2mnl_data_conn_failed() {
+ return mnldinf_ext_data_conn_failed(g_gpshal_ctx.fd_mnl2hal_ext);
+}
+
+int hal2mnl_set_server(agps_type type, const char* hostname, int port) {
+ return mnldinf_ext_set_server(g_gpshal_ctx.fd_mnl2hal_ext, type, hostname, port);
+}
+
+int hal2mnl_set_ref_location(cell_type type, int mcc, int mnc, int lac, int cid) {
+ return mnldinf_ext_set_ref_location(g_gpshal_ctx.fd_mnl2hal_ext, type, mcc, mnc, lac, cid);
+}
+
+int hal2mnl_set_id(agps_id_type type, const char* setid) {
+ return mnldinf_ext_set_id(g_gpshal_ctx.fd_mnl2hal_ext, type, setid);
+}
+
+
+int hal2mnl_ni_message(char* msg, int len) {
+ return mnldinf_ext_ni_message(g_gpshal_ctx.fd_mnl2hal_ext, msg, len);
+}
+
+int hal2mnl_ni_respond(int notif_id, ni_user_response_type user_response) {
+ return mnldinf_ext_ni_respond(g_gpshal_ctx.fd_mnl2hal_ext, notif_id, user_response);
+}
+
+int hal2mnl_update_network_state(uint64_t networkHandle, bool isConnected,
+ uint16_t capabilities, const char* apn) {
+ return mnldinf_ext_update_network_state(g_gpshal_ctx.fd_mnl2hal_ext, networkHandle, isConnected,
+ capabilities, apn);
+}
+
+int hal2mnl_update_network_availability(int available, const char* apn) {
+ return mnldinf_ext_update_network_availability(g_gpshal_ctx.fd_mnl2hal_ext, available, apn);
+}
+
+int hal2mnl_set_gps_measurement(bool enabled, bool enableFullTracking) {
+ int ret1 = 0, ret2 = 0;
+
+ ret1 = mnldinf_basic_gnss_measurement_enable(g_gpshal_ctx.fd_mnl2hal_ext, enabled);
+ ret2 = mnldinf_ext_gnss_full_tracking_enable(g_gpshal_ctx.fd_mnl2hal_ext, enableFullTracking);
+ if(ret1 < 0 || ret2 < 0) {
+ return -1;
+ } else {
+ return ret1+ret2;
+ }
+}
+
+int hal2mnl_set_gps_navigation(bool enabled) {
+ return mnldinf_ext_gnss_navigation_msg_enable(g_gpshal_ctx.fd_mnl2hal_ext, enabled);
+}
+
+int hal2mnl_set_vzw_debug(bool enabled) {
+ return mnldinf_ext_set_vzw_debug(g_gpshal_ctx.fd_mnl2hal_ext, enabled);
+}
+
+int hal2mnl_update_gnss_config(const char* config_data, int length) {
+ return mnldinf_ext_update_gnss_config(g_gpshal_ctx.fd_mnl2hal_ext, config_data, length);
+}
+
+int hal2mnl_setBlacklist(long long* blacklist, int32_t size) {
+ return mnldinf_ext_set_sv_blacklist(g_gpshal_ctx.fd_mnl2hal_ext, blacklist, size);
+}
+
+int hal2mnl_set_correction(MeasurementCorrections* corrections) {
+ return mnldinf_ext_set_correction(g_gpshal_ctx.fd_mnl2hal_ext, (measurement_corrections *)corrections);
+}
+
+int hal2mnl_set_nfw_access(char* proxy_apps, int32_t length) {
+ return mnldinf_ext_set_nfw_access(g_gpshal_ctx.fd_mnl2hal_ext, proxy_apps, length);
+}
+
+int hal2mnl_send_pmtk(char* msg, int len) {
+ return mnldinf_ext_send_pmtk(g_gpshal_ctx.fd_mnl2hal_ext, msg, len);
+}
+
+#define GNSS_HAL "gnss_hal"
+
+// -1 means failure
+int create_mnl2hal_fd_basic() {
+ int fd = mnldinf_basic_register(GNSS_HAL);
+ if(fd < 0) {
+ LOGE("Fail to create basic fd reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ return fd;
+}
+
+// -1 means failure
+int create_mnl2hal_fd_ext() {
+ int fd = mnldinf_ext_register(GNSS_HAL);
+ if(fd < 0) {
+ LOGE("Fail to create extension fd reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ return fd;
+}
diff --git a/src/connectivity/gps/2.0/gpslog/Makefile b/src/connectivity/gps/2.0/gpslog/Makefile
new file mode 100644
index 0000000..8c07d58
--- /dev/null
+++ b/src/connectivity/gps/2.0/gpslog/Makefile
@@ -0,0 +1,52 @@
+CC=gcc
+CXX=g++
+
+FLAGS=\
+ -g \
+ -Wall \
+ -D __COMPILE_OPTION__ \
+ -D __LINUX_OS__ \
+
+# -m32 \
+
+CPPFLAGS=\
+ -std=c++11 \
+
+INCLUDE=\
+ -I./utility/inc/ \
+
+LIBS=\
+ -ldl \
+ -lrt \
+ -lpthread \
+
+CXXSRC=\
+
+CSRC=\
+ gpslog.c \
+ ./utility/src/gpslog_data_coder.c \
+ ./utility/src/gpslog_utility.c \
+ ./utility/src/gpslog_log.c \
+ ./utility/src/gpslog_socket_data_coder.c \
+ ./utility/src/gpslog_socket_utils.c
+
+EXECUTABLE=gpslog
+COBJS=$(CSRC:.c=.o)
+CXXOBJS=$(CXXSRC:.cpp=.o)
+
+all: $(EXECUTABLE)
+
+$(EXECUTABLE): $(COBJS) $(CXXOBJS)
+ $(CC) $(COBJS) $(CXXOBJS) $(LIBS) $(FLAGS) $(CPPFLAGS) -o $@
+
+%.o : %.c
+ $(CC) -c $(FLAGS) $(INCLUDE) -o $@ $<
+
+%.o : %.cpp
+ $(CC) -c $(FLAGS) $(INCLUDE) $(CPPFLAGS) -o $@ $<
+
+.PHONY: clean
+clean:
+ rm -f $(EXECUTABLE) rm -rf *.o
+ rm -rf $(COBJS)
+
diff --git a/src/connectivity/gps/2.0/gpslog/gpslog.c b/src/connectivity/gps/2.0/gpslog/gpslog.c
new file mode 100644
index 0000000..be845ad
--- /dev/null
+++ b/src/connectivity/gps/2.0/gpslog/gpslog.c
@@ -0,0 +1,277 @@
+#include <stdio.h> /* Standard input/output definitions */
+#include <stdbool.h> /* Standard bool true/false definitions */
+#include <string.h> /* String function definitions */
+#include <unistd.h> /* UNIX standard function definitions */
+#include <fcntl.h> /* File control definitions */
+#include <errno.h> /* Error number definitions */
+#include <termios.h> /* POSIX terminal control definitions */
+#include <time.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/epoll.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <strings.h>
+#include <semaphore.h>
+
+#include "gpslog_log.h"
+#include "gpslog_utility.h"
+#include "gpslog_socket_utils.h"
+#include "gpslog_socket_data_coder.h"
+
+#define GPSLOG_UDP_ADDR "mtk_lbs_log_v2s"
+
+#define PRINT_TITLE(...) { printf("\E[0;30;43m"); printf(__VA_ARGS__); printf("\E[0m"); fflush(stdout); }
+#define PRINT_RAW(...) { printf(__VA_ARGS__); fflush(stdout);}
+
+#define GPSLOG_INTERFACE_BUFF_SIZE (80*1024)
+#define GPSLOG_PATH_SIZE (256)
+
+typedef enum {
+ GPSLOG_OPEN_LOG = 0,
+ GPSLOG_CLOSE_LOG = 1,
+ GPSLOG_WRITE_LOG = 2,
+} gpslog_msg_id;
+
+typedef struct {
+ char* sock_addr;
+}log_db;
+
+log_db gpslog_db;
+
+typedef struct {
+ bool (*create_logfile)(const char* path);
+ bool (*write_logdata)(char* data, int len);
+ bool (*close_logfile)();
+} gpslog_inf;
+
+static bool gpslog_handle_open_logfile(const char* file_name) {
+ time_t tm;
+ struct tm *p = NULL;
+ char full_file_name[256] = {0};
+
+ if (time(&tm)==((time_t)-1)) {
+ LOGE("time() fail(%s)!!\r\n", strerror(errno));
+ }
+ p = localtime(&tm);
+
+ if(p == NULL) {
+ LOGE("Get localtime fail:[%s]%d", strerror(errno), errno);
+ return false;
+ }
+
+ snprintf(full_file_name, sizeof(full_file_name), "%s_%04d_%02d%02d_%02d%02d%02d", file_name,
+ 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday,
+ p->tm_hour, p->tm_min, p->tm_sec);
+
+ PRINT_RAW("\r\n==============GPSLog start, %s=============\r\n", full_file_name);
+ return true;
+}
+
+static bool gpslog_handle_write_logdata(char* data, int len) {
+ //PRINT_RAW("%s", data);
+ if(write(STDOUT_FILENO, data, len) != len) {
+ LOGW("STDOUT print fail:[le:%d][%s]", len, data);
+ return false;
+ }
+ return true;
+}
+
+static bool gpslog_handle_close_logfile() {
+ PRINT_RAW("\r\n==============GPSLog end=============\r\n");
+ return true;
+}
+
+static gpslog_inf gpslog_handler_interface = {
+ gpslog_handle_open_logfile,
+ gpslog_handle_write_logdata,
+ gpslog_handle_close_logfile
+};
+
+char gpslog_buff[GPSLOG_INTERFACE_BUFF_SIZE] = {0};
+
+static bool gpslog_hdlr(int fd, log_db* database, gpslog_inf* hdlr) {
+ int offset = 0;
+
+ gpslog_msg_id cmd;
+ int ptype;
+ int log_type;
+ int read_len = 0;
+ bool ret = true;
+
+ if (NULL == database) {
+ LOGE("gpslog_hdlr, database not valid");
+ return false;
+ }
+
+ if (NULL == hdlr) {
+ LOGE("[%s]gpslog_hdlr, hdlr not valid", database->sock_addr);
+ return false;
+ }
+
+ if (fd < 0) {
+ LOGE("[%s]gpslog_hdlr, fd not valid", database->sock_addr);
+ return false;
+ }
+ memset(gpslog_buff, 0, sizeof(gpslog_buff));
+ read_len = gpslog_safe_recv(fd, gpslog_buff, sizeof(gpslog_buff)-1);
+ if (read_len <= 0) {
+ LOGE("[%s]gpslog_hdlr() gpslog_safe_recv() failed read_len=%d", database->sock_addr, read_len);
+ return false;
+ }
+ ptype = gpslog_socket_get_int(gpslog_buff, &offset);
+ UNUSED(ptype);
+ cmd = gpslog_socket_get_int(gpslog_buff, &offset);
+ log_type = gpslog_socket_get_int(gpslog_buff, &offset);
+ UNUSED(log_type);
+
+ switch (cmd) {
+ case GPSLOG_OPEN_LOG: {
+ if (hdlr->create_logfile) {
+ char path[GPSLOG_PATH_SIZE] = {0};
+ //gpslog_socket_get_string(gpslog_buff, &offset, path, sizeof(path));
+ sprintf(path, "GPSHostLog");
+ if (!hdlr->create_logfile(path)) {
+ LOGE("[%s]gpslog_hdlr() create_logfile fail", database->sock_addr);
+ }
+ } else {
+ LOGE("[%s]gpslog_hdlr() create_logfile is NULL", database->sock_addr);
+ ret = false;
+ }
+ break;
+ }
+
+ case GPSLOG_WRITE_LOG: {
+ if (hdlr->write_logdata) {
+ unsigned int len_logdata = gpslog_socket_get_int(gpslog_buff, &offset);
+ if (len_logdata <= GPSLOG_INTERFACE_BUFF_SIZE) {
+ if (!hdlr->write_logdata(gpslog_buff+offset, len_logdata)) {
+ LOGE("[%s]gpslog_hdlr() write_logdata fail", database->sock_addr);
+ }
+ } else {
+ LOGE("[%s]gpslog_hdlr() len_logdata:%u overflow", database->sock_addr, len_logdata);
+ ret = false;
+ }
+ } else {
+ LOGE("[%s]gpslog_hdlr() write_logdata is NULL", database->sock_addr);
+ ret = false;
+ }
+ break;
+ }
+
+ case GPSLOG_CLOSE_LOG: {
+ if (hdlr->close_logfile) {
+ if (!hdlr->close_logfile()) {
+ LOGE("[%s]gpslog_hdlr() close_logfile fail", database->sock_addr);
+ }
+ } else {
+ LOGE("[%s]gpslog_hdlr() close_logfile is NULL", database->sock_addr);
+ ret = false;
+ }
+ break;
+ }
+
+ default: {
+ LOGE("[%s]gpslog_hdlr() unknown cmd=%d", database->sock_addr, cmd);
+ ret = false;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static void* gpslog_write_thread(void *database)
+{
+ #define EPOLL_MAX_NUM 4
+ int fd = -1;
+ int i = 0;
+ int n = 0;
+ int epfd = epoll_create(EPOLL_MAX_NUM);
+ struct epoll_event events[EPOLL_MAX_NUM];
+ log_db* data = (log_db*)database;
+
+ if (NULL == data) {
+ LOGE("gpslog_write_thread exit, database not valid");
+ return 0;
+ }
+
+ LOGD("[%s]gpslog_write_thread created", data->sock_addr);
+
+ if (-1 == epfd) {
+ LOGE("[%s]gpslog_write_thread epoll_create failure, reason=[%s]", data->sock_addr, strerror(errno));
+ return 0;
+ }
+
+ //fd = gpslog_socket_bind_udp(data->sock_addr);
+ fd = gpslog_socket_server_bind_local(data->sock_addr, SOCK_NS_ABSTRACT);
+
+ if (fd < 0) {
+ LOGE("[%s]gpslog_write_thread create fd failed, reason=[%s]", data->sock_addr, strerror(errno));
+ return 0;
+ }
+
+ if (gpslog_epoll_add_fd(epfd, fd) == -1) {
+ LOGE("[%s]gpslog_write_thread failed for fd_hal failed, reason=[%s]", data->sock_addr, strerror(errno));
+ return 0;
+ }
+
+ while (1) {
+ n = epoll_wait(epfd, events, EPOLL_MAX_NUM , -1);
+ if (-1 == n) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ LOGE("[%s]gpslog_write_thread epoll_wait failure reason=[%s]", data->sock_addr, strerror(errno));
+ return 0;
+ }
+ }
+ for (i = 0; i < n; i++) {
+ if (events[i].data.fd == fd) {
+ if (events[i].events & EPOLLIN) {
+ if (!gpslog_hdlr(fd, data, &gpslog_handler_interface)) {
+ LOGE("[%s]gpslog_hdlr failure reason=[%s]", data->sock_addr, strerror(errno));
+ }
+ }
+ } else {
+ LOGE("[%s]mnld_main_thread() unknown fd=%d", data->sock_addr, events[i].data.fd);
+ }
+ }
+ }
+ LOGE("[%s]gpslog_write_thread exit", data->sock_addr);
+ return 0;
+}
+
+static void gpslog_database_init() {
+ memset(&gpslog_db, 0x0, sizeof(gpslog_db));
+
+ //GPS LOG config
+ gpslog_db.sock_addr = GPSLOG_UDP_ADDR;
+}
+
+int gpslog_init() {
+ pthread_t pthread_gps;
+
+ LOGD("gpslog_init");
+ gpslog_database_init();
+
+ pthread_create(&pthread_gps, NULL, gpslog_write_thread, (char*)(&gpslog_db));
+ return 0;
+}
+
+int main(void) {
+ LOGD("LBS debug daemon begin running");
+ if (gpslog_init() != 0) {
+ LOGE("gpslog_init error, exit");
+ return -1;
+ }
+
+ gpslog_block_here();
+ return 0;
+}
diff --git a/src/connectivity/gps/2.0/gpslog/utility/inc/gpslog_log.h b/src/connectivity/gps/2.0/gpslog/utility/inc/gpslog_log.h
new file mode 100644
index 0000000..f9acb29
--- /dev/null
+++ b/src/connectivity/gps/2.0/gpslog/utility/inc/gpslog_log.h
@@ -0,0 +1,194 @@
+/*
+* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2017. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*/
+#ifndef MTK_MNLD_LOG_H
+#define MTK_MNLD_LOG_H
+
+/**
+ * @enum LOG_LEVEL
+ * @brief Define Log Level
+ */
+typedef enum {
+ L_VERBOSE = 0, L_DEBUG, L_INFO, L_WARN, L_ERROR, L_ASSERT, L_SUPPRESS
+} LOG_LEVEL;
+
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+#ifdef LOGD
+#undef LOGD
+#endif
+#ifdef LOGW
+#undef LOGW
+#endif
+#ifdef LOGE
+#undef LOGE
+#endif
+
+#ifndef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "gpslog"
+#endif
+
+#include <string.h>
+
+int set_log_level(int *dst_level, int src_level);
+#define LOG_IS_ENABLED(level) (L_DEBUG <= level)
+
+#define FILE_NAME(x) strrchr(x, '/')?strrchr(x, '/') + 1 : x
+
+#if defined(__ANDROID_OS__)
+
+//#define ANDROID_MNLD_PROP_SUPPORT 1
+
+#include <cutils/sockets.h>
+#include <log/log.h> /*logging in logcat*/
+#include <cutils/android_filesystem_config.h>
+#if defined(__ANDROID_OS__)
+#include <cutils/properties.h>
+#endif
+
+#include "mtk_prop_util.h"
+
+#define PRINT_LOG(loglevel, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ switch (loglevel){\
+ case L_ASSERT:\
+ {\
+ ALOG_ASSERT("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_ERROR:\
+ {\
+ ALOGE("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_WARN:\
+ {\
+ ALOGW("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_INFO:\
+ {\
+ ALOGI("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_DEBUG:\
+ {\
+ ALOGD("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_VERBOSE:\
+ {\
+ ALOGV("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ }\
+ }\
+ } while (0)
+
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, fmt, ##args)
+
+#define TRC(f) ALOGD("%s", __func__)
+
+#elif defined(__LINUX_OS__)
+
+#include <stdio.h>
+//#define ANDROID_MNLD_PROP_SUPPORT 0
+
+
+char time_buff[64];
+int get_time_str(char* buf, int len);
+
+#ifndef gettid
+#include <unistd.h>
+#include <sys/syscall.h>
+#define gettid() syscall(__NR_gettid)
+#define getpid() syscall(__NR_getpid)
+#endif
+
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ get_time_str(time_buff, sizeof(time_buff));\
+ printf("%ld %ld [%s]" LOG_TAG tag "%s %s %d " fmt "\n",\
+ getpid(), gettid(),time_buff, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ fflush(stdout);\
+ }\
+ } while (0)
+
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, "[ASSERT]: ", fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, "[ERROR]: ", fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, "[WARNING]: ", fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, "[INFO]: ", fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, "[DEBUG]: ", fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, "[VERBOSE]: ", fmt, ##args)
+
+#define TRC(f) ((void)0)
+
+#elif defined(__TIZEN_OS__)
+
+#include <dlog/dlog.h>
+
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ dlog_print(DLOG_DEBUG, fmt "\n", ##args);\
+ printf(fmt "\n", ##args);
+ fflush(stdout);\
+ }\
+ } while (0)
+
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, "[ASSERT]: ", fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, "[ERROR]: ", fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, "[WARNING]: ", fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, "[INFO]: ", fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, "[DEBUG]: ", fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, "[VERBOSE]: ", fmt, ##args)
+
+#endif
+#define CONFIG_GPS_ENG_LOAD
+#ifdef CONFIG_GPS_ENG_LOAD
+#define LOGD_ENG(fmt, arg ...) LOGD( fmt, ##arg)
+#else
+#define LOGD_ENG(fmt, arg ...) NULL
+#endif
+
+#endif
diff --git a/src/connectivity/gps/2.0/gpslog/utility/inc/gpslog_socket_data_coder.h b/src/connectivity/gps/2.0/gpslog/utility/inc/gpslog_socket_data_coder.h
new file mode 100644
index 0000000..b42f146
--- /dev/null
+++ b/src/connectivity/gps/2.0/gpslog/utility/inc/gpslog_socket_data_coder.h
@@ -0,0 +1,52 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __DATA_CODER_H__
+#define __DATA_CODER_H__
+
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool mtk_socket_get_bool(char* buff, int* offset);
+char mtk_socket_get_char(char* buff, int* offset);
+short mtk_socket_get_short(char* buff, int* offset);
+int gpslog_socket_get_int(char* buff, int* offset);
+int64_t mtk_socket_get_int64_t(char* buff, int* offset);
+float mtk_socket_get_float(char* buff, int* offset);
+double mtk_socket_get_double(char* buff, int* offset);
+int gpslog_socket_get_string(char* buff, int* offset, char* output, int max_size);
+int mtk_socket_get_bool_array(char* buff, int* offset, bool output[], int max_size);
+int mtk_socket_get_char_array(char* buff, int* offset, char output[], int max_size);
+int mtk_socket_get_short_array(char* buff, int* offset, short output[], int max_size);
+int mtk_socket_get_int_array(char* buff, int* offset, int output[], int max_size);
+int mtk_socket_get_int64_t_array(char* buff, int* offset, int64_t output[], int max_size);
+int mtk_socket_get_float_array(char* buff, int* offset, float output[], int max_size);
+int mtk_socket_get_double_array(char* buff, int* offset, double output[], int max_size);
+int mtk_socket_get_string_array(char* buff, int* offset, void* output, int max_size1, int max_size2);
+
+void mtk_socket_put_bool(char* buff, int* offset, bool input);
+void mtk_socket_put_char(char* buff, int* offset, char input);
+void mtk_socket_put_short(char* buff, int* offset, short input);
+void mtk_socket_put_int(char* buff, int* offset, int input);
+void mtk_socket_put_int64_t(char* buff, int* offset, int64_t input);
+void mtk_socket_put_float(char* buff, int* offset, float input);
+void mtk_socket_put_double(char* buff, int* offset, double input);
+void mtk_socket_put_string(char* buff, int* offset, const char* input);
+void mtk_socket_put_bool_array(char* buff, int* offset, bool input[], int size);
+void mtk_socket_put_char_array(char* buff, int* offset, char input[], int size);
+void mtk_socket_put_short_array(char* buff, int* offset, short input[], int size);
+void mtk_socket_put_int_array(char* buff, int* offset, int input[], int size);
+void mtk_socket_put_int64_t_array(char* buff, int* offset, int64_t input[], int size);
+void mtk_socket_put_float_array(char* buff, int* offset, float input[], int size);
+void mtk_socket_put_double_array(char* buff, int* offset, double input[], int size);
+void mtk_socket_put_string_array(char* buff, int* offset, void* input, int size1, int size2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/gpslog/utility/inc/gpslog_socket_utils.h b/src/connectivity/gps/2.0/gpslog/utility/inc/gpslog_socket_utils.h
new file mode 100644
index 0000000..76d4b8c
--- /dev/null
+++ b/src/connectivity/gps/2.0/gpslog/utility/inc/gpslog_socket_utils.h
@@ -0,0 +1,38 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __MTK_SOCKET_UTILS_H__
+#define __MTK_SOCKET_UTILS_H__
+
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <pthread.h>
+
+#include "gpslog_log.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ SOCK_NS_ABSTRACT = 0,
+ SOCK_NS_FILESYSTEM = 1,
+} mtk_socket_namespace;
+
+
+#define SOCK_LOGD(fmt, arg ...) LOGD(fmt, ##arg)
+#define SOCK_LOGW(fmt, arg ...) LOGW( fmt, ##arg)
+#define SOCK_LOGE(fmt, arg ...) LOGE(fmt, ##arg)
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int gpslog_socket_server_bind_local(const char* path, mtk_socket_namespace sock_namespace);
+int gpslog_safe_recv(int fd, char* buff, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/gpslog/utility/inc/gpslog_utility.h b/src/connectivity/gps/2.0/gpslog/utility/inc/gpslog_utility.h
new file mode 100644
index 0000000..08b740d
--- /dev/null
+++ b/src/connectivity/gps/2.0/gpslog/utility/inc/gpslog_utility.h
@@ -0,0 +1,74 @@
+#ifndef __MTK_LBS_UTILITY_H__
+#define __MTK_LBS_UTILITY_H__
+
+#include <time.h>
+#include <sys/time.h>
+#include <stdint.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdbool.h> /* Standard bool true/false definitions */
+
+#include "gpslog_log.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************
+* Basic Utilities
+**************************************************/
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+#define DUMP_BYTES_PER_LINE 16
+#define DUMP_MAX_PRINT_LINE 10
+
+#define GPSLOG_DUMP_MEM(addr, len) do{\
+ int i = 0, j = 0;\
+ char print_buf[DUMP_BYTES_PER_LINE*5+1] = {0};\
+ unsigned int print_len = len;\
+ if(len > DUMP_MAX_PRINT_LINE*DUMP_BYTES_PER_LINE) {\
+ print_len = DUMP_MAX_PRINT_LINE*DUMP_BYTES_PER_LINE;\
+ }\
+ LOGD(">>>>>DUMP_START(addr:%p, len:%d, print_len:%ud)<<<<<", addr, len,print_len);\
+ for(i = 0; i < print_len; i+=DUMP_BYTES_PER_LINE) {\
+ memset(print_buf, 0, sizeof(print_buf));\
+ for(j=0;j<DUMP_BYTES_PER_LINE;j++) {\
+ sprintf(&print_buf[j*5], "0x%02x ", ((char *)addr)[i*DUMP_BYTES_PER_LINE+j]);\
+ print_buf[DUMP_BYTES_PER_LINE*5] = '\0';\
+ }\
+ LOGD("[%3d]:%s", i/DUMP_BYTES_PER_LINE, print_buf);\
+ }\
+ LOGD("<<<<<DUMP_STOP>>>>>");\
+}while(0)
+
+
+#define MNLD_STRNCPY(dst,src,size) do{\
+ strncpy((char *)(dst), (src), (size - 1));\
+ (dst)[size - 1] = '\0';\
+ }while(0)
+
+// -1 means failure
+int gpslog_block_here();
+
+//exit block_here() and process will exit and restart
+void gpslog_block_exit(void);
+
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int gpslog_epoll_add_fd(int epfd, int fd);
+
+
+/*************************************************
+* string operation
+**************************************************/
+char *safe_strncpy(char *dest, const char *src, size_t n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_data_coder.c b/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_data_coder.c
new file mode 100644
index 0000000..ab67b38
--- /dev/null
+++ b/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_data_coder.c
@@ -0,0 +1,154 @@
+#include <string.h>
+
+#ifndef MAX
+#define MAX(A,B) ((A)>(B)?(A):(B))
+#endif
+#ifndef MIN
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#endif
+
+//===============================================================
+// get
+char get_byte(char* buff, int* offset, int src_len) {
+ char ret = 0;
+ if (*offset >= 0 && *offset < src_len) {
+ ret = buff[*offset];
+ *offset += 1;
+ }
+ return ret;
+}
+
+short get_short(char* buff, int* offset, int src_len) {
+ short ret = 0;
+ ret |= get_byte(buff, offset, src_len) & 0xff;
+ ret |= (get_byte(buff, offset, src_len) << 8);
+ return ret;
+}
+
+int get_int(char* buff, int* offset, int src_len) {
+ int ret = 0;
+ ret |= get_short(buff, offset, src_len) & 0xffff;
+ ret |= (get_short(buff, offset, src_len) << 16);
+ return ret;
+}
+
+long long get_long(char* buff, int* offset, int src_len) {
+ long long ret = 0;
+ ret |= get_int(buff, offset, src_len) & 0xffffffffL;
+ ret |= ((long long)get_int(buff, offset, src_len) << 32);
+ return ret;
+}
+
+float get_float(char* buff, int* offset, int src_len) {
+ float ret;
+ int tmp = get_int(buff, offset, src_len);
+ ret = *((float*)&tmp);
+ return ret;
+}
+
+double get_double(char* buff, int* offset, int src_len) {
+ double ret;
+ long long tmp = get_long(buff, offset, src_len);
+ ret = *((double*)&tmp);
+ return ret;
+}
+
+char* get_string(char* buff, int* offset, int src_len) {
+ char ret = get_byte(buff, offset, src_len);
+ if (ret == 0) {
+ return NULL;
+ } else {
+ char* p = NULL;
+ int len = get_int(buff, offset, src_len);
+ if (*offset < 0 || *offset >= src_len) {
+ *offset = 0;
+ }
+ if ((len > src_len - *offset) || len < 0) {
+ len = src_len - *offset;
+ }
+ if (len <= 0) {
+ return NULL;
+ }
+ p = &buff[*offset];
+ p[len-1] = 0;
+ *offset += len;
+ return p;
+ }
+}
+
+char* get_string2(char* buff, int* offset, int src_len) {
+ char* output = get_string(buff, offset, src_len);
+ if (output == NULL) {
+ return "";
+ } else {
+ return output;
+ }
+}
+
+int get_binary(char* buff, int* offset, char* output, int src_len, int des_len) {
+ int len = 0;
+ if (*offset >= 0 && *offset <= src_len) {
+ len = get_int(buff, offset, src_len);
+ if (len > MIN((src_len-(*offset)), des_len)) {
+ len = MIN((src_len-(*offset)), des_len);
+ }
+ if (len > 0) {
+ memcpy(output, &buff[*offset], len);
+ *offset += len;
+ }
+ }
+ return len;
+}
+
+//===============================================================
+// put
+void put_byte(char* buff, int* offset, const char input) {
+ *((char*)&buff[*offset]) = input;
+ *offset += 1;
+}
+
+void put_short(char* buff, int* offset, const short input) {
+ put_byte(buff, offset, input & 0xff);
+ put_byte(buff, offset, (input >> 8) & 0xff);
+}
+
+void put_int(char* buff, int* offset, const int input) {
+ put_short(buff, offset, input & 0xffff);
+ put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void put_long(char* buff, int* offset, const long long input) {
+ put_int(buff, offset, input & 0xffffffffL);
+ put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void put_float(char* buff, int* offset, const float input) {
+ int* data = (int*)&input;
+ put_int(buff, offset, *data);
+}
+
+void put_double(char* buff, int* offset, const double input) {
+ long long* data = (long long*)&input;
+ put_long(buff, offset, *data);
+}
+
+void put_string(char* buff, int* offset, const char* input) {
+ if (input == NULL) {
+ put_byte(buff, offset, 0);
+ } else {
+ int len = strlen(input) + 1;
+ put_byte(buff, offset, 1);
+ put_int(buff, offset, len);
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+ }
+}
+
+void put_binary(char* buff, int* offset, const char* input, const int len) {
+ put_int(buff, offset, len);
+ if (len > 0) {
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+ }
+}
+
diff --git a/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_log.c b/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_log.c
new file mode 100644
index 0000000..3bb3315
--- /dev/null
+++ b/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_log.c
@@ -0,0 +1,125 @@
+/*
+* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2017. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*/
+#include <sys/time.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+#include <memory.h>
+
+#include "gpslog_log.h"
+
+#if defined(__LINUX_OS__)
+// -1 means failure
+int get_time_str(char* buf, int len) {
+#if 0 //Fix build error
+ struct timeval tv;
+ struct timezone tz;
+ struct tm *tm;
+
+ gettimeofday(&tv, &tz);
+ tm = localtime(&tv.tv_sec);
+
+ memset(buf, 0, len);
+ sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d.%03d",
+ tm->tm_year + 1900, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min,
+ tm->tm_sec, (int)(tv.tv_usec / 1000));
+
+ return 0;
+#else
+ time_t now = time(NULL);
+ struct tm tm_utc;
+ time_t time_utc;
+
+ gmtime_r(&now, &tm_utc);
+ time_utc = mktime(&tm_utc);
+
+ memset(buf, 0, len);
+ sprintf(buf, "%s", ctime(&time_utc));
+
+ buf[strlen(buf)-1] = '\0'; //Remove '\n'
+
+ return 0;
+#endif
+}
+#endif
+
+int set_log_level(int *dst_level, int src_level)
+{
+#if defined(__ANDROID_OS__)
+
+ ALOGI("Current debug level=%d", *dst_level);
+
+ if (src_level < L_VERBOSE || src_level > L_SUPPRESS)
+ {
+ ALOGE("Invalid debug level, level=%d", src_level);
+ ALOGE(" [level] -");
+ ALOGE(" QUIET = 6");
+ ALOGE(" ASSERT = 5");
+ ALOGE(" ERROR = 4");
+ ALOGE(" WARNING = 3");
+ ALOGE(" INFO = 2");
+ ALOGE(" DEBUG = 1");
+ ALOGE(" LOGALL = 0");
+ return -1;
+ }
+
+ *dst_level = src_level;
+
+ ALOGI("New debug level=%d", *dst_level);
+
+#elif defined(__LINUX_OS__)
+
+ printf("Current debug level=%d\n", *dst_level);
+
+ if (src_level < L_VERBOSE || src_level > L_SUPPRESS)
+ {
+ printf("Invalid debug level, level=%d", src_level);
+ printf(" [level] -");
+ printf(" QUIET = 6");
+ printf(" ASSERT = 5");
+ printf(" ERROR = 4");
+ printf(" WARNING = 3");
+ printf(" INFO = 2");
+ printf(" DEBUG = 1");
+ printf(" LOGALL = 0");
+ return -1;
+ }
+
+ *dst_level = src_level;
+
+ printf("New debug level=%d\n", *dst_level);
+
+#endif
+ return 0;
+}
diff --git a/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_socket_data_coder.c b/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_socket_data_coder.c
new file mode 100644
index 0000000..c33e317
--- /dev/null
+++ b/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_socket_data_coder.c
@@ -0,0 +1,256 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include "gpslog_socket_data_coder.h"
+
+bool mtk_socket_get_bool(char* buff, int* offset) {
+ bool ret = (mtk_socket_get_char(buff, offset) == 0)? false : true;
+ return ret;
+}
+
+char mtk_socket_get_char(char* buff, int* offset) {
+ char ret = buff[*offset];
+ *offset += 1;
+ return ret;
+}
+
+short mtk_socket_get_short(char* buff, int* offset) {
+ short ret = 0;
+ ret |= mtk_socket_get_char(buff, offset) & 0xff;
+ ret |= (mtk_socket_get_char(buff, offset) << 8);
+ return ret;
+}
+
+int gpslog_socket_get_int(char* buff, int* offset) {
+ int ret = 0;
+ ret |= mtk_socket_get_short(buff, offset) & 0xffff;
+ ret |= (mtk_socket_get_short(buff, offset) << 16);
+ return ret;
+}
+
+int64_t mtk_socket_get_int64_t(char* buff, int* offset) {
+ int64_t ret = 0;
+ ret |= gpslog_socket_get_int(buff, offset) & 0xffffffffL;
+ ret |= ((int64_t)gpslog_socket_get_int(buff, offset) << 32);
+ return ret;
+}
+
+float mtk_socket_get_float(char* buff, int* offset) {
+ float ret;
+ int tmp = gpslog_socket_get_int(buff, offset);
+ ret = *((float*)&tmp);
+ return ret;
+}
+
+double mtk_socket_get_double(char* buff, int* offset) {
+ double ret;
+ int64_t tmp = mtk_socket_get_int64_t(buff, offset);
+ ret = *((double*)&tmp);
+ return ret;
+}
+
+int gpslog_socket_get_string(char* buff, int* offset, char* output, int max_size) {
+ int size = gpslog_socket_get_int(buff, offset);
+ memset(output, 0, max_size);
+ memcpy(output, &buff[*offset], (size > max_size)? max_size : size);
+ output[max_size - 1] = 0;
+ *offset += size;
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_bool_array(char* buff, int* offset, bool output[], int max_size) {
+ int i = 0;
+ int size = gpslog_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ bool data = mtk_socket_get_bool(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_char_array(char* buff, int* offset, char output[], int max_size) {
+ int size = gpslog_socket_get_int(buff, offset);
+ memcpy(output, &buff[*offset], (size > max_size)? max_size : size);
+ *offset += size;
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_short_array(char* buff, int* offset, short output[], int max_size) {
+ int i = 0;
+ int size = gpslog_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ short data = mtk_socket_get_short(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_int_array(char* buff, int* offset, int output[], int max_size) {
+ int i = 0;
+ int size = gpslog_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ int data = gpslog_socket_get_int(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_int64_t_array(char* buff, int* offset, int64_t output[], int max_size) {
+ int i = 0;
+ int size = gpslog_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ int64_t data = mtk_socket_get_int64_t(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_float_array(char* buff, int* offset, float output[], int max_size) {
+ int i = 0;
+ int size = gpslog_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ float data = mtk_socket_get_float(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_double_array(char* buff, int* offset, double output[], int max_size) {
+ int i = 0;
+ int size = gpslog_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ double data = mtk_socket_get_double(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_string_array(char* buff, int* offset, void* output, int max_size1, int max_size2) {
+ int i = 0;
+ int size1 = gpslog_socket_get_int(buff, offset);
+ for(i = 0; i < size1; i++) {
+ if(i < max_size1) {
+ gpslog_socket_get_string(buff, offset, output, max_size2);
+ output = (char*)output + max_size2;
+ } else {
+ char tmp[max_size2];
+ gpslog_socket_get_string(buff, offset, tmp, max_size2);
+ }
+ }
+ return (size1 > max_size1)? max_size1 : size1;
+}
+
+void mtk_socket_put_bool(char* buff, int* offset, bool input) {
+ mtk_socket_put_char(buff, offset, input);
+}
+
+void mtk_socket_put_char(char* buff, int* offset, char input) {
+ *((char*)&buff[*offset]) = input;
+ *offset += 1;
+}
+
+void mtk_socket_put_short(char* buff, int* offset, short input) {
+ mtk_socket_put_char(buff, offset, input & 0xff);
+ mtk_socket_put_char(buff, offset, (input >> 8) & 0xff);
+}
+
+void mtk_socket_put_int(char* buff, int* offset, int input) {
+ mtk_socket_put_short(buff, offset, input & 0xffff);
+ mtk_socket_put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void mtk_socket_put_int64_t(char* buff, int* offset, int64_t input) {
+ mtk_socket_put_int(buff, offset, input & 0xffffffffL);
+ mtk_socket_put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void mtk_socket_put_float(char* buff, int* offset, float input) {
+ int* data = (int*)&input;
+ mtk_socket_put_int(buff, offset, *data);
+}
+
+void mtk_socket_put_double(char* buff, int* offset, double input) {
+ int64_t* data = (int64_t*)&input;
+ mtk_socket_put_int64_t(buff, offset, *data);
+}
+
+void mtk_socket_put_string(char* buff, int* offset, const char* input) {
+ int len = strlen(input);
+ mtk_socket_put_int(buff, offset, len);
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+}
+
+void mtk_socket_put_bool_array(char* buff, int* offset, bool input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_bool(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_char_array(char* buff, int* offset, char input[], int size) {
+ mtk_socket_put_int(buff, offset, size);
+ memcpy(&buff[*offset], input, size);
+ *offset += size;
+}
+
+void mtk_socket_put_short_array(char* buff, int* offset, short input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_short(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_int_array(char* buff, int* offset, int input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_int(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_int64_t_array(char* buff, int* offset, int64_t input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_int64_t(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_float_array(char* buff, int* offset, float input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_float(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_double_array(char* buff, int* offset, double input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_double(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_string_array(char* buff, int* offset, void* input, int size1, int size2) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size1);
+ for(i = 0; i < size1; i++) {
+ mtk_socket_put_string(buff, offset, (char*)input);
+ input = (char*)input + size2;
+ }
+}
+
diff --git a/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_socket_utils.c b/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_socket_utils.c
new file mode 100644
index 0000000..4200437
--- /dev/null
+++ b/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_socket_utils.c
@@ -0,0 +1,121 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include "gpslog_socket_utils.h"
+#include "gpslog_socket_data_coder.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h> //usleep
+#include <sys/socket.h>
+#include <string.h>
+#include <fcntl.h>
+#include <arpa/inet.h> //inet_addr
+#include <sys/un.h> //struct sockaddr_un
+#include <sys/epoll.h>
+#include <poll.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <inttypes.h>
+
+#if defined(__ANDROID_OS__)
+#include <cutils/log.h> // Android log
+
+#define ANDROID_LOG_TAG "mtk_socket"
+#endif
+
+char *safe_strncpy(char *dest, const char *src, size_t n) {
+ if (dest && n > 0) {
+ // Use strncat for performance because strncpy will always fill n bytes in dest
+ dest[0] = '\0'; // Let dest be an empty string
+ strncat(dest, src, --n); // n-1 because strncat may fill n+1 bytes
+ }
+ return dest;
+}
+
+//-1 means failure
+int gpslog_socket_server_bind_local(const char* path, mtk_socket_namespace sock_namespace) {
+ int size;
+ struct sockaddr_un addr;
+ int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ LOGE("mtk_socket_server_bind_local() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ size = strlen(path) + offsetof(struct sockaddr_un, sun_path) + 1;
+ if(sock_namespace == SOCK_NS_ABSTRACT) {
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, path, strlen(path));
+ } else if(sock_namespace == SOCK_NS_FILESYSTEM) {
+ safe_strncpy(addr.sun_path, path, sizeof(addr.sun_path));
+ unlink(addr.sun_path);
+ } else {
+ LOGE("mtk_socket_server_bind_local() unknown namespace=[%d]", sock_namespace);
+ close(fd);
+ return -1;
+ }
+ if (bind(fd, (struct sockaddr *)&addr, size) == -1) {
+ LOGE("mtk_socket_server_bind_local() bind() failed reason=[%s]%d for path=[%s]",
+ strerror(errno), errno, path);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+
+// -1 means failure
+int gpslog_safe_recvfrom(int fd, char* buff, int len) {
+ int ret = 0;
+ int retry = 10;
+
+ 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);
+ }
+
+ while ((ret = recvfrom(fd, buff, len, 0,
+ NULL, NULL)) == -1) {
+ LOGW("gpslog_safe_recvfrom() ret=%d len=%d", ret, len);
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("gpslog_safe_recvfrom() recvfrom() failed reason=[%s]%d",
+ strerror(errno), errno);
+ break;
+ }
+ return ret;
+}
+
+int gpslog_safe_recv(int fd, char* buff, int len) {
+ int ret = 0;
+ int retry = 10;
+
+ while ((ret = read(fd, buff, len)) == -1) {
+ LOGW("mnldinf_safe_recvfrom() ret=%d len=%d", ret, len);
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("mnldinf_safe_recvfrom() recvfrom() failed reason=[%s]%d",
+ strerror(errno), errno);
+ break;
+ }
+ return ret;
+}
+
diff --git a/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_utility.c b/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_utility.c
new file mode 100644
index 0000000..9a5f1ec
--- /dev/null
+++ b/src/connectivity/gps/2.0/gpslog/utility/src/gpslog_utility.c
@@ -0,0 +1,75 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h> // usleep
+#include <sys/socket.h>
+#include <string.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 <sys/syscall.h>
+
+#if defined(__ANDROID_OS__)
+#include <cutils/log.h> // Android log
+#endif
+#include "gpslog_log.h"
+
+#include "gpslog_utility.h"
+//#include "gpslog_socket_utils.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "gpslog_utility"
+
+sem_t g_mnld_exit_sem;
+
+// -1 means failure
+int gpslog_block_here() {
+ if (sem_init(&g_mnld_exit_sem, 0, 0) == -1) {
+ LOGE("block_here() sem_init failure reason=%s\n", strerror(errno));
+ return -1;
+ }
+ sem_wait(&g_mnld_exit_sem);
+ if (sem_destroy(&g_mnld_exit_sem) == -1) {
+ LOGE("block_here() sem_destroy reason=%s\n", strerror(errno));
+ }
+ return 0;
+}
+
+void gpslog_block_exit(void) {
+ if(sem_post(&g_mnld_exit_sem) == -1) {
+ LOGE("sem_post failed");
+ _exit(0);
+ }
+}
+
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int gpslog_epoll_add_fd(int epfd, int fd) {
+ struct epoll_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.data.fd = fd;
+ ev.events = EPOLLIN;
+ // 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("gpslog_epoll_add_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+ strerror(errno), errno, epfd, fd);
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/connectivity/gps/2.0/mtk_mnld/Android.mk b/src/connectivity/gps/2.0/mtk_mnld/Android.mk
new file mode 100644
index 0000000..89fe4a2
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/Android.mk
@@ -0,0 +1,223 @@
+# Copyright Statement:
+#
+# This software/firmware and related documentation ("MediaTek Software") are
+# protected under relevant copyright laws. The information contained herein
+# is confidential and proprietary to MediaTek Inc. and/or its licensors.
+# Without the prior written permission of MediaTek inc. and/or its licensors,
+# any reproduction, modification, use or disclosure of MediaTek Software,
+# and information contained herein, in whole or in part, shall be strictly prohibited.
+
+# MediaTek Inc. (C) 2016. All rights reserved.
+#
+# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+
+
+# Copyright 2005 The Android Open Source Project
+
+###############################################################################
+# Configuration
+###############################################################################
+#MTK_GPS_CHIP = MTK_GPS_MT6582
+###############################################################################
+# build start
+###############################################################################
+ifeq ($(MTK_GPS_SUPPORT), yes)
+LOCAL_PATH := $(call my-dir)
+
+###############################################################################
+# Define build path ,global defines and feature options by platform
+###############################################################################
+ifneq (,$(filter MT6885,$(MTK_PLATFORM)))
+MY_MNL_PATH := mnl/MNL_6_0
+LOCAL_CFLAGS += -DMNL_6_0
+else
+MY_MNL_PATH := mnl/MNL_6_1
+LOCAL_CFLAGS += -DMNL_6_1
+endif
+$(warning MNL_PATH1=$(MY_MNL_PATH))
+
+include $(CLEAR_VARS)
+LOCAL_MODULE:= libmnl_headers
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/$(MY_MNL_PATH)/inc
+include $(BUILD_HEADER_LIBRARY)
+$(warning libmnl_headers:$(LOCAL_EXPORT_C_INCLUDE_DIRS))
+
+ifneq (,$(filter MT6885,$(MTK_PLATFORM)))
+MY_MPE_PATH := mnl_mpe_interface_6_0
+else
+MY_MPE_PATH := mnl_mpe_interface_6_1
+endif
+$(warning MPE_PATH1=$(MY_MPE_PATH))
+
+include $(CLEAR_VARS)
+LOCAL_MODULE:= mpe_headers
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/$(MY_MPE_PATH)/inc
+include $(BUILD_HEADER_LIBRARY)
+$(warning mpe_headers:$(LOCAL_EXPORT_C_INCLUDE_DIRS))
+
+include $(CLEAR_VARS)
+MY_LOCAL_PATH := $(LOCAL_PATH)
+$(warning feature_option=$(MTK_GPS_CHIP))
+
+###############################################################################
+# Define build path ,global defines and feature options by platform
+###############################################################################
+ifneq (,$(filter MT6885,$(MTK_PLATFORM)))
+
+ifeq ($(TARGET_PRODUCT), full_k6885v1_64_md_gnss_sync)
+LOCAL_CFLAGS += -DMTK_MD_GNSS_SYNC
+endif
+
+ifeq ($(TARGET_PRODUCT), full_k6885v1_64_nsa_sa_mp3)
+LOCAL_CFLAGS += -DMTK_MD_GNSS_SYNC
+endif
+
+else
+LOCAL_CFLAGS += -DMTK_MD_GNSS_SYNC
+endif
+
+ifneq (,$(filter MT6885,$(MTK_PLATFORM)))
+LOCAL_CFLAGS += -DMTK_GPS_DUAL_FREQ_SUPPORT
+endif
+
+ifneq (,$(filter MT6885,$(MTK_PLATFORM)))
+MY_MNL_PATH := mnl/MNL_6_0
+LOCAL_CFLAGS += -DMNL_6_0
+else
+MY_MNL_PATH := mnl/MNL_6_1
+LOCAL_CFLAGS += -DMNL_6_1
+endif
+$(warning MNL_PATH2=$(MY_MNL_PATH))
+
+ifneq (,$(filter MT6885,$(MTK_PLATFORM)))
+MY_MPE_PATH := mnl_mpe_interface_6_0
+else
+MY_MPE_PATH := mnl_mpe_interface_6_1
+endif
+$(warning MPE_PATH2=$(MY_MPE_PATH))
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/utility/inc \
+ $(LOCAL_PATH)/mnl_agps_interface/inc \
+ $(LOCAL_PATH)/mnl_at_cmd_interface/inc \
+ $(LOCAL_PATH)/mnl_flp_interface/inc \
+ $(LOCAL_PATH)/mnl_nlp_interface/inc \
+ $(LOCAL_PATH)/mnl_meta_interface/inc \
+ $(LOCAL_PATH)/mnl_debug_interface/inc \
+ $(LOCAL_PATH)/mnl_log_interface/inc \
+ $(LOCAL_PATH)/mnl_geofence_interface/inc \
+ $(LOCAL_PATH)/mnld_entity/inc \
+ $(LOCAL_PATH)/curl/inc \
+ $(MTK_PATH_SOURCE)/external/nvram/libnvram \
+ external/libxml2/include \
+ $(TOP)/system/core/libcutils/include_vndk \
+ $(MTK_PATH_SOURCE)/external/libudf/libladder \
+
+# MPE HIDL #
+LOCAL_C_INCLUDES += $(TOP)/frameworks/native/include
+LOCAL_C_INCLUDES += $(TOP)/frameworks/hardware/interfaces/sensorservice/libsensorndkbridge
+LOCAL_C_INCLUDES += $(TOP)/hardware/interfaces/sensors/1.0/default/include
+
+LOCAL_CFLAGS += -DGPS_SUSPEND_SUPPORT
+
+LOCAL_SRC_FILES := \
+ mnld_entity/src/mnl2hal_interface.c \
+ utility/src/data_coder.c \
+ utility/src/mtk_lbs_utility.c \
+ utility/src/mtk_socket_data_coder.c \
+ utility/src/mtk_socket_utils.c \
+ mnl_agps_interface/src/mnl_agps_interface.c \
+ mnl_agps_interface/src/mnl2agps_interface.c \
+ mnl_agps_interface/src/agps2mnl_interface.c \
+ mnl_flp_interface/src/mtk_flp_controller.c \
+ mnl_flp_interface/src/mtk_flp_main.c \
+ mnl_flp_interface/src/mtk_flp_mnl_interface.c \
+ mnl_flp_interface/src/mtk_flp_screen_monitor.c \
+ mnl_flp_interface/src/mnl_flp_test_interface.c \
+ mnl_geofence_interface/src/mtk_geofence_controller.c \
+ mnl_geofence_interface/src/mtk_geofence_main.c \
+ mnl_nlp_interface/src/Mnld2NlpUtilsInterface.c \
+ mnl_meta_interface/src/Meta2MnldInterface.c \
+ mnl_meta_interface/src/Meta2Mnld_logctrl_Interface.c \
+ mnl_debug_interface/src/Debug2MnldInterface.c \
+ mnl_debug_interface/src/Mnld2DebugInterface.c \
+ mnl_log_interface/src/LbsLogInterface.c \
+ mnl_at_cmd_interface/src/mnl_at_interface.c \
+ mnld_entity/src/mnld.c \
+ mnld_entity/src/mnld_uti.c \
+ mnld_entity/src/gps_controller.c \
+ mnld_entity/src/nmea_parser.c \
+ mnld_entity/src/epo.c \
+ mnld_entity/src/qepo.c \
+ mnld_entity/src/mtknav.c \
+ mnld_entity/src/mnl_common.c \
+ mnld_entity/src/op01_log.c \
+ mnld_entity/src/gps_dbg_log.c \
+ mnld_entity/src/mpe.c \
+ mnl/src/pseudo_mnl.c \
+ utility/src/mtk_mnld_dump.cpp \
+
+LOCAL_SRC_FILES += $(MY_MPE_PATH)/src/mpe_main.c
+LOCAL_SRC_FILES += $(MY_MPE_PATH)/src/mpe_logger.c
+LOCAL_SRC_FILES += $(MY_MPE_PATH)/src/mpe_sensor.cpp
+
+LOCAL_MODULE := mnld
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MULTILIB := 32
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_EXECUTABLES)
+# LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
+#ifeq ($(MTK_TC1_FEATURE), yes)
+#ifeq ($(GPS_CO_CLOCK_DATA_IN_MD), yes)
+LOCAL_CFLAGS += -DMTK_GPS_CO_CLOCK_DATA_IN_MD
+#endif
+#endif
+ifeq ($(TARGET_BUILD_VARIANT), user)
+LOCAL_CFLAGS += -DCONFIG_GPS_USER_LOAD
+endif
+ifeq ($(TARGET_BUILD_VARIANT), userdebug)
+LOCAL_CFLAGS += -DCONFIG_GPS_USER_DBG_LOAD
+endif
+ifeq ($(TARGET_BUILD_VARIANT), eng)
+LOCAL_CFLAGS += -DCONFIG_GPS_ENG_LOAD
+endif
+ifeq ($(MTK_AGPS_APP), yes)
+LOCAL_CFLAGS += -DMTK_AGPS_SUPPORT
+endif
+LOCAL_STATIC_LIBRARIES += libsupl
+LOCAL_SHARED_LIBRARIES += libmnl libgeofence libcurl libcutils libc libm libnvram libcrypto libssl libz liblog libhardware libladder
+LOCAL_HEADER_LIBRARIES += libcutils_headers libmnl_headers mpe_headers
+
+LOCAL_EXPORT_HEADER_LIBRARY_HEADERS += libhardware_headers
+# MPE HIDL #
+LOCAL_SHARED_LIBRARIES += libDR libutils android.frameworks.sensorservice@1.0 android.hardware.sensors@1.0 libhidlbase libhidltransport libsensorndkbridge
+LOCAL_MODULE_TAGS := optional
+LOCAL_REQUIRED_MODULES := libmnl.so libgeofence.so
+include $(MTK_EXECUTABLE)
+include $(MY_LOCAL_PATH)/mnl/bin/Android.mk
+include $(MY_LOCAL_PATH)/curl/libs/Android.mk
+include $(MY_LOCAL_PATH)/$(MY_MNL_PATH)/libs/Android.mk
+$(warning $(MY_LOCAL_PATH)/$(MY_MNL_PATH)/libs/Android.mk)
+endif
+###############################################################################
diff --git a/src/connectivity/gps/2.0/mtk_mnld/MTK_LICENSE b/src/connectivity/gps/2.0/mtk_mnld/MTK_LICENSE
new file mode 100644
index 0000000..901b162
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/MTK_LICENSE
@@ -0,0 +1,35 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein
+is confidential and proprietary to MediaTek Inc. and/or its licensors.
+Without the prior written permission of MediaTek inc. and/or its licensors,
+any reproduction, modification, use or disclosure of MediaTek Software,
+and information contained herein, in whole or in part, shall be strictly prohibited.
+
+MediaTek Inc. (C) 2018. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+
+The following software/firmware and/or related documentation ("MediaTek Software")
+have been modified by MediaTek Inc. All revisions are subject to any receiver's
+applicable license agreements with MediaTek Inc.
+
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/Makefile b/src/connectivity/gps/2.0/mtk_mnld/Makefile
new file mode 100644
index 0000000..eced03c
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/Makefile
@@ -0,0 +1,138 @@
+#CC=gcc
+#CXX=g++
+
+FLAGS=$(CFLAG)
+
+FO_FLAGS:= \
+ -DADC_CAPTURE_DEFINE \
+ -DGPS_SUSPEND_SUPPORT \
+ -DMTK_GPS_DUAL_FREQ_SUPPORT \
+ -DMTK_GPS_CO_CLOCK_DATA_IN_MD \
+ -DMTK_AGPS_SUPPORT \
+
+FLAGS+=\
+ -g \
+ -std=c99 \
+ -Wall \
+ -fPIC \
+ -D __COMPILE_OPTION__ \
+ -D __LINUX_OS__ \
+ -D_POSIX_C_SOURCE=199309L \
+ -D__USE_BSD \
+ -Wno-unused-function \
+ -Wno-unused-variable \
+ -Wno-implicit-function-declaration \
+ $(FO_FLAGS) \
+
+ifneq ($(findstring __LIBMNL_SIMULATOR__, $(FLAGS)),)
+CC=gcc
+FLAGS+=\
+ -DMTK_GPS_DATA_PATH="\"./etc/gnss/\"" \
+ -DMTK_GPS_DATA_DEFAULT_PATH="\"./etc/\""
+else
+FLAGS+=\
+ -DMTK_GPS_DATA_PATH="\"/etc/gnss/\"" \
+ -DMTK_GPS_DATA_DEFAULT_PATH="\"/etc/\""
+endif
+# -m32 \
+
+CPPFLAGS=\
+ -std=c++11 \
+
+INCLUDE=\
+ -Iutility/inc \
+ -Imnl_agps_interface/inc \
+ -Imnl_at_cmd_interface/inc \
+ -Imnl_nlp_interface/inc \
+ -Imnl_meta_interface/inc \
+ -Imnl_debug_interface/inc \
+ -Imnl_geofence_interface/inc \
+ -Imnld_entity/inc \
+ -Imnld_entity/inc/hardware \
+ -Imnld_entity/src/flashdownload \
+ -Imnl_log_interface/inc \
+ -Icurl/inc \
+ -Imnl/libs/inc
+
+LIBS=\
+ -ldl \
+ -lpthread \
+ -lm \
+ -lz \
+ -lssl \
+ -lcrypto \
+ -lcurl \
+ -lrt \
+
+CXXSRC=\
+
+CSRC=\
+ mnld_entity/src/mnl2hal_interface.c \
+ utility/src/data_coder.c \
+ utility/src/mtk_lbs_utility.c \
+ utility/src/mtk_socket_data_coder.c \
+ utility/src/mtk_socket_utils.c \
+ utility/src/mtk_prop_util.c \
+ utility/src/mtk_mnld_log.c \
+ mnl_agps_interface/src/mnl_agps_interface.c \
+ mnl_agps_interface/src/mnl2agps_interface.c \
+ mnl_agps_interface/src/agps2mnl_interface.c \
+ mnl_geofence_interface/src/mtk_geofence_controller.c \
+ mnl_geofence_interface/src/mtk_geofence_main.c \
+ mnl_nlp_interface/src/Mnld2NlpUtilsInterface.c \
+ mnl_meta_interface/src/Meta2MnldInterface.c \
+ mnl_debug_interface/src/Debug2MnldInterface.c \
+ mnl_debug_interface/src/Mnld2DebugInterface.c \
+ mnl_at_cmd_interface/src/mnl_at_interface.c \
+ mnld_entity/src/mnld.c \
+ mnld_entity/src/mnld_uti.c \
+ mnld_entity/src/gps_controller.c \
+ mnld_entity/src/nmea_parser.c \
+ mnld_entity/src/epo.c \
+ mnld_entity/src/qepo.c \
+ mnld_entity/src/mtknav.c \
+ mnld_entity/src/mnl_common.c \
+ mnld_entity/src/op01_log.c \
+ mnld_entity/src/gps_dbg_log.c \
+ mnl/src/pseudo_mnl.c \
+ mnl_log_interface/src/LbsLogInterface.c \
+ mnl_meta_interface/src/Meta2Mnld_logctrl_Interface.c \
+
+ifneq ($(findstring ADC_CAPTURE_DEFINE, $(FLAGS)),)
+ CSRC+=mnld_entity/src/adc_capture.c
+endif
+
+ifneq ($(findstring __LIBMNL_SIMULATOR__, $(FLAGS)),)
+ CSRC+=mnl/src/mnl_simulator.c
+else
+ LIBS+=\
+ mnl/libs/$(PACKAGE_ARCH)/libmnl_gnss.so \
+ mnl/libs/$(PACKAGE_ARCH)/libhotstill.a
+
+$(warning "mnld LIBS:$(LIBS)")
+endif
+
+EXECUTABLE=mnld
+COBJS=$(CSRC:.c=.o)
+CXXOBJS=$(CXXSRC:.cpp=.o)
+
+all: $(EXECUTABLE)
+
+$(EXECUTABLE): $(COBJS) $(CXXOBJS)
+ $(CC) --sysroot=$(BB_SYSROOT_ADD) $(COBJS) $(CXXOBJS) $(LDFLAGS) $(LIBS) $(FLAGS) $(CPPFLAGS) -o $@
+
+%.o : %.c
+ $(CC) -c $(FLAGS) $(INCLUDE) -o $@ $<
+
+%.o : %.cpp
+ $(CC) -c $(FLAGS) $(INCLUDE) $(CPPFLAGS) -o $@ $<
+
+.PHONY: install clean
+install:
+ install -d $(DESTDIR)/${bindir}
+ install -m 0755 $(EXECUTABLE) $(DESTDIR)/${bindir}
+
+clean:
+ rm -f $(EXECUTABLE) rm -rf *.o
+ find ./ -name *.o | xargs rm -rf
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/NOTICE b/src/connectivity/gps/2.0/mtk_mnld/NOTICE
new file mode 100644
index 0000000..56161a9
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/NOTICE
@@ -0,0 +1,236 @@
+This MediaTek software package contains software with the following notices and under the following licenses:
+
+==============================================================================================================
+
+Copyright (c) 2005-2008, The Android Open Source Project
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+
+
+
+Copyright (c) 2005-2008, The Android Open Source Project
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other materials provided with the distribution.
+ * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+
+
+Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+
+The MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/README b/src/connectivity/gps/2.0/mtk_mnld/README
new file mode 100644
index 0000000..7394158
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/README
@@ -0,0 +1,16 @@
+WHAT IT DOES?
+=============
+mnld is the implementation that mediatek navigating technology to work well as mediatek navigating library process on native.
+
+HOW IT WAS BUILT?
+==================
+As native process, these are built by android build system.
+
+HOW TO USE IT?
+==============
+mnld is run when system boot up,they receive command from GPS HAL/AGPSD,handle with gps start/close/init/cleanup opertions,
+and send responises to GPS HAL/AGPSD.
+
+Source
+==============
+All the source code of these libraries were written by MediaTek co..
diff --git a/src/connectivity/gps/2.0/mtk_mnld/curl/inc/curl.h b/src/connectivity/gps/2.0/mtk_mnld/curl/inc/curl.h
new file mode 100644
index 0000000..b57b3c4
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/curl/inc/curl.h
@@ -0,0 +1,2360 @@
+#ifndef __CURL_CURL_H
+#define __CURL_CURL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * If you have libcurl problems, all docs and details are found here:
+ * http://curl.haxx.se/libcurl/
+ *
+ * curl-library mailing list subscription and unsubscription web interface:
+ * http://cool.haxx.se/mailman/listinfo/curl-library/
+ */
+
+#include "curlver.h" /* libcurl version defines */
+#include "curlbuild.h" /* libcurl build definitions */
+#include "curlrules.h" /* libcurl rules enforcement */
+
+/*
+ * Define WIN32 when build target is Win32 API
+ */
+
+#if (defined(_WIN32) || defined(__WIN32__)) && \
+ !defined(WIN32) && !defined(__SYMBIAN32__)
+#define WIN32
+#endif
+
+#include <stdio.h>
+#include <limits.h>
+
+#if defined(__FreeBSD__) && (__FreeBSD__ >= 2)
+/* Needed for __FreeBSD_version symbol definition */
+#include <osreldate.h>
+#endif
+
+/* The include stuff here below is mainly for time_t! */
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
+#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || defined(__LWIP_OPT_H__))
+/* The check above prevents the winsock2 inclusion if winsock.h already was
+ included, since they can't co-exist without problems */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+#endif
+
+/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
+ libc5-based Linux systems. Only include it on systems that are known to
+ require it! */
+#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
+ defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
+ defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
+ (defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
+#include <sys/select.h>
+#endif
+
+#if !defined(WIN32) && !defined(_WIN32_WCE)
+#include <sys/socket.h>
+#endif
+
+#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__)
+#include <sys/time.h>
+#endif
+
+#ifdef __BEOS__
+#include <support/SupportDefs.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void CURL;
+
+/*
+ * libcurl external API function linkage decorations.
+ */
+
+#ifdef CURL_STATICLIB
+# define CURL_EXTERN
+#elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)
+# if defined(BUILDING_LIBCURL)
+# define CURL_EXTERN __declspec(dllexport)
+# else
+# define CURL_EXTERN __declspec(dllimport)
+# endif
+#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS)
+# define CURL_EXTERN CURL_EXTERN_SYMBOL
+#else
+# define CURL_EXTERN
+#endif
+
+#ifndef curl_socket_typedef
+/* socket typedef */
+#if defined(WIN32) && !defined(__LWIP_OPT_H__)
+typedef SOCKET curl_socket_t;
+#define CURL_SOCKET_BAD INVALID_SOCKET
+#else
+typedef int curl_socket_t;
+#define CURL_SOCKET_BAD -1
+#endif
+#define curl_socket_typedef
+#endif /* curl_socket_typedef */
+
+struct curl_httppost {
+ struct curl_httppost *next; /* next entry in the list */
+ char *name; /* pointer to allocated name */
+ long namelength; /* length of name length */
+ char *contents; /* pointer to allocated data contents */
+ long contentslength; /* length of contents field */
+ char *buffer; /* pointer to allocated buffer contents */
+ long bufferlength; /* length of buffer field */
+ char *contenttype; /* Content-Type */
+ struct curl_slist* contentheader; /* list of extra headers for this form */
+ struct curl_httppost *more; /* if one field name has more than one
+ file, this link should link to following
+ files */
+ long flags; /* as defined below */
+#define HTTPPOST_FILENAME (1<<0) /* specified content is a file name */
+#define HTTPPOST_READFILE (1<<1) /* specified content is a file name */
+#define HTTPPOST_PTRNAME (1<<2) /* name is only stored pointer
+ do not free in formfree */
+#define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer
+ do not free in formfree */
+#define HTTPPOST_BUFFER (1<<4) /* upload file from buffer */
+#define HTTPPOST_PTRBUFFER (1<<5) /* upload file from pointer contents */
+#define HTTPPOST_CALLBACK (1<<6) /* upload file contents by using the
+ regular read callback to get the data
+ and pass the given pointer as custom
+ pointer */
+
+ char *showfilename; /* The file name to show. If not set, the
+ actual file name will be used (if this
+ is a file part) */
+ void *userp; /* custom pointer used for
+ HTTPPOST_CALLBACK posts */
+};
+
+/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered
+ deprecated but was the only choice up until 7.31.0 */
+typedef int (*curl_progress_callback)(void *clientp,
+ double dltotal,
+ double dlnow,
+ double ultotal,
+ double ulnow);
+
+/* This is the CURLOPT_XFERINFOFUNCTION callback proto. It was introduced in
+ 7.32.0, it avoids floating point and provides more detailed information. */
+typedef int (*curl_xferinfo_callback)(void *clientp,
+ curl_off_t dltotal,
+ curl_off_t dlnow,
+ curl_off_t ultotal,
+ curl_off_t ulnow);
+
+#ifndef CURL_MAX_WRITE_SIZE
+ /* Tests have proven that 20K is a very bad buffer size for uploads on
+ Windows, while 16K for some odd reason performed a lot better.
+ We do the ifndef check to allow this value to easier be changed at build
+ time for those who feel adventurous. The practical minimum is about
+ 400 bytes since libcurl uses a buffer of this size as a scratch area
+ (unrelated to network send operations). */
+#define CURL_MAX_WRITE_SIZE 16384
+#endif
+
+#ifndef CURL_MAX_HTTP_HEADER
+/* The only reason to have a max limit for this is to avoid the risk of a bad
+ server feeding libcurl with a never-ending header that will cause reallocs
+ infinitely */
+#define CURL_MAX_HTTP_HEADER (100*1024)
+#endif
+
+/* This is a magic return code for the write callback that, when returned,
+ will signal libcurl to pause receiving on the current transfer. */
+#define CURL_WRITEFUNC_PAUSE 0x10000001
+
+typedef size_t (*curl_write_callback)(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *outstream);
+
+
+
+/* enumeration of file types */
+typedef enum {
+ CURLFILETYPE_FILE = 0,
+ CURLFILETYPE_DIRECTORY,
+ CURLFILETYPE_SYMLINK,
+ CURLFILETYPE_DEVICE_BLOCK,
+ CURLFILETYPE_DEVICE_CHAR,
+ CURLFILETYPE_NAMEDPIPE,
+ CURLFILETYPE_SOCKET,
+ CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */
+
+ CURLFILETYPE_UNKNOWN /* should never occur */
+} curlfiletype;
+
+#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0)
+#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1)
+#define CURLFINFOFLAG_KNOWN_TIME (1<<2)
+#define CURLFINFOFLAG_KNOWN_PERM (1<<3)
+#define CURLFINFOFLAG_KNOWN_UID (1<<4)
+#define CURLFINFOFLAG_KNOWN_GID (1<<5)
+#define CURLFINFOFLAG_KNOWN_SIZE (1<<6)
+#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7)
+
+/* Content of this structure depends on information which is known and is
+ achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man
+ page for callbacks returning this structure -- some fields are mandatory,
+ some others are optional. The FLAG field has special meaning. */
+struct curl_fileinfo {
+ char *filename;
+ curlfiletype filetype;
+ time_t time;
+ unsigned int perm;
+ int uid;
+ int gid;
+ curl_off_t size;
+ long int hardlinks;
+
+ struct {
+ /* If some of these fields is not NULL, it is a pointer to b_data. */
+ char *time;
+ char *perm;
+ char *user;
+ char *group;
+ char *target; /* pointer to the target filename of a symlink */
+ } strings;
+
+ unsigned int flags;
+
+ /* used internally */
+ char * b_data;
+ size_t b_size;
+ size_t b_used;
+};
+
+/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */
+#define CURL_CHUNK_BGN_FUNC_OK 0
+#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */
+#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */
+
+/* if splitting of data transfer is enabled, this callback is called before
+ download of an individual chunk started. Note that parameter "remains" works
+ only for FTP wildcard downloading (for now), otherwise is not used */
+typedef long (*curl_chunk_bgn_callback)(const void *transfer_info,
+ void *ptr,
+ int remains);
+
+/* return codes for CURLOPT_CHUNK_END_FUNCTION */
+#define CURL_CHUNK_END_FUNC_OK 0
+#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */
+
+/* If splitting of data transfer is enabled this callback is called after
+ download of an individual chunk finished.
+ Note! After this callback was set then it have to be called FOR ALL chunks.
+ Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC.
+ This is the reason why we don't need "transfer_info" parameter in this
+ callback and we are not interested in "remains" parameter too. */
+typedef long (*curl_chunk_end_callback)(void *ptr);
+
+/* return codes for FNMATCHFUNCTION */
+#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */
+#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */
+#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */
+
+/* callback type for wildcard downloading pattern matching. If the
+ string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */
+typedef int (*curl_fnmatch_callback)(void *ptr,
+ const char *pattern,
+ const char *string);
+
+/* These are the return codes for the seek callbacks */
+#define CURL_SEEKFUNC_OK 0
+#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */
+#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so
+ libcurl might try other means instead */
+typedef int (*curl_seek_callback)(void *instream,
+ curl_off_t offset,
+ int origin); /* 'whence' */
+
+/* This is a return code for the read callback that, when returned, will
+ signal libcurl to immediately abort the current transfer. */
+#define CURL_READFUNC_ABORT 0x10000000
+/* This is a return code for the read callback that, when returned, will
+ signal libcurl to pause sending data on the current transfer. */
+#define CURL_READFUNC_PAUSE 0x10000001
+
+typedef size_t (*curl_read_callback)(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *instream);
+
+typedef enum {
+ CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
+ CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
+ CURLSOCKTYPE_LAST /* never use */
+} curlsocktype;
+
+/* The return code from the sockopt_callback can signal information back
+ to libcurl: */
+#define CURL_SOCKOPT_OK 0
+#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return
+ CURLE_ABORTED_BY_CALLBACK */
+#define CURL_SOCKOPT_ALREADY_CONNECTED 2
+
+typedef int (*curl_sockopt_callback)(void *clientp,
+ curl_socket_t curlfd,
+ curlsocktype purpose);
+
+struct curl_sockaddr {
+ int family;
+ int socktype;
+ int protocol;
+ unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it
+ turned really ugly and painful on the systems that
+ lack this type */
+ struct sockaddr addr;
+};
+
+typedef curl_socket_t
+(*curl_opensocket_callback)(void *clientp,
+ curlsocktype purpose,
+ struct curl_sockaddr *address);
+
+typedef int
+(*curl_closesocket_callback)(void *clientp, curl_socket_t item);
+
+typedef enum {
+ CURLIOE_OK, /* I/O operation successful */
+ CURLIOE_UNKNOWNCMD, /* command was unknown to callback */
+ CURLIOE_FAILRESTART, /* failed to restart the read */
+ CURLIOE_LAST /* never use */
+} curlioerr;
+
+typedef enum {
+ CURLIOCMD_NOP, /* no operation */
+ CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
+ CURLIOCMD_LAST /* never use */
+} curliocmd;
+
+typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
+ int cmd,
+ void *clientp);
+
+/*
+ * The following typedef's are signatures of malloc, free, realloc, strdup and
+ * calloc respectively. Function pointers of these types can be passed to the
+ * curl_global_init_mem() function to set user defined memory management
+ * callback routines.
+ */
+typedef void *(*curl_malloc_callback)(size_t size);
+typedef void (*curl_free_callback)(void *ptr);
+typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
+typedef char *(*curl_strdup_callback)(const char *str);
+typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
+
+/* the kind of data that is passed to information_callback*/
+typedef enum {
+ CURLINFO_TEXT = 0,
+ CURLINFO_HEADER_IN, /* 1 */
+ CURLINFO_HEADER_OUT, /* 2 */
+ CURLINFO_DATA_IN, /* 3 */
+ CURLINFO_DATA_OUT, /* 4 */
+ CURLINFO_SSL_DATA_IN, /* 5 */
+ CURLINFO_SSL_DATA_OUT, /* 6 */
+ CURLINFO_END
+} curl_infotype;
+
+typedef int (*curl_debug_callback)
+ (CURL *handle, /* the handle/transfer this concerns */
+ curl_infotype type, /* what kind of data */
+ char *data, /* points to the data */
+ size_t size, /* size of the data pointed to */
+ void *userptr); /* whatever the user please */
+
+/* All possible error codes from all sorts of curl functions. Future versions
+ may return other values, stay prepared.
+
+ Always add new return codes last. Never *EVER* remove any. The return
+ codes must remain the same!
+ */
+
+typedef enum {
+ CURLE_OK = 0,
+ CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
+ CURLE_FAILED_INIT, /* 2 */
+ CURLE_URL_MALFORMAT, /* 3 */
+ CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for
+ 7.17.0, reused in April 2011 for 7.21.5] */
+ CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
+ CURLE_COULDNT_RESOLVE_HOST, /* 6 */
+ CURLE_COULDNT_CONNECT, /* 7 */
+ CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */
+ CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server
+ due to lack of access - when login fails
+ this is not returned. */
+ CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for
+ 7.15.4, reused in Dec 2011 for 7.24.0]*/
+ CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */
+ CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server
+ [was obsoleted in August 2007 for 7.17.0,
+ reused in Dec 2011 for 7.24.0]*/
+ CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
+ CURLE_FTP_WEIRD_227_FORMAT, /* 14 */
+ CURLE_FTP_CANT_GET_HOST, /* 15 */
+ CURLE_HTTP2, /* 16 - A problem in the http2 framing layer.
+ [was obsoleted in August 2007 for 7.17.0,
+ reused in July 2014 for 7.38.0] */
+ CURLE_FTP_COULDNT_SET_TYPE, /* 17 */
+ CURLE_PARTIAL_FILE, /* 18 */
+ CURLE_FTP_COULDNT_RETR_FILE, /* 19 */
+ CURLE_OBSOLETE20, /* 20 - NOT USED */
+ CURLE_QUOTE_ERROR, /* 21 - quote command failure */
+ CURLE_HTTP_RETURNED_ERROR, /* 22 */
+ CURLE_WRITE_ERROR, /* 23 */
+ CURLE_OBSOLETE24, /* 24 - NOT USED */
+ CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */
+ CURLE_READ_ERROR, /* 26 - couldn't open/read from file */
+ CURLE_OUT_OF_MEMORY, /* 27 */
+ /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
+ instead of a memory allocation error if CURL_DOES_CONVERSIONS
+ is defined
+ */
+ CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */
+ CURLE_OBSOLETE29, /* 29 - NOT USED */
+ CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */
+ CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */
+ CURLE_OBSOLETE32, /* 32 - NOT USED */
+ CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */
+ CURLE_HTTP_POST_ERROR, /* 34 */
+ CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */
+ CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */
+ CURLE_FILE_COULDNT_READ_FILE, /* 37 */
+ CURLE_LDAP_CANNOT_BIND, /* 38 */
+ CURLE_LDAP_SEARCH_FAILED, /* 39 */
+ CURLE_OBSOLETE40, /* 40 - NOT USED */
+ CURLE_FUNCTION_NOT_FOUND, /* 41 */
+ CURLE_ABORTED_BY_CALLBACK, /* 42 */
+ CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */
+ CURLE_OBSOLETE44, /* 44 - NOT USED */
+ CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */
+ CURLE_OBSOLETE46, /* 46 - NOT USED */
+ CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */
+ CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */
+ CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */
+ CURLE_OBSOLETE50, /* 50 - NOT USED */
+ CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint
+ wasn't verified fine */
+ CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
+ CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */
+ CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as
+ default */
+ CURLE_SEND_ERROR, /* 55 - failed sending network data */
+ CURLE_RECV_ERROR, /* 56 - failure in receiving network data */
+ CURLE_OBSOLETE57, /* 57 - NOT IN USE */
+ CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */
+ CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */
+ CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */
+ CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */
+ CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */
+ CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */
+ CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */
+ CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind
+ that failed */
+ CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */
+ CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not
+ accepted and we failed to login */
+ CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */
+ CURLE_TFTP_PERM, /* 69 - permission problem on server */
+ CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */
+ CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */
+ CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */
+ CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */
+ CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */
+ CURLE_CONV_FAILED, /* 75 - conversion failed */
+ CURLE_CONV_REQD, /* 76 - caller must register conversion
+ callbacks using curl_easy_setopt options
+ CURLOPT_CONV_FROM_NETWORK_FUNCTION,
+ CURLOPT_CONV_TO_NETWORK_FUNCTION, and
+ CURLOPT_CONV_FROM_UTF8_FUNCTION */
+ CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing
+ or wrong format */
+ CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */
+ CURLE_SSH, /* 79 - error from the SSH layer, somewhat
+ generic so the error message will be of
+ interest when this has happened */
+
+ CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL
+ connection */
+ CURLE_AGAIN, /* 81 - socket is not ready for send/recv,
+ wait till it's ready and try again(Added
+ in 7.18.2) */
+ CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or
+ wrong format(Added in 7.19.0) */
+ CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in
+ 7.19.0) */
+ CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */
+ CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */
+ CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */
+ CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */
+ CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */
+ CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the
+ session will be queued */
+ CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not
+ match */
+ CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */
+ CURL_LAST /* never use! */
+} CURLcode;
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all the obsoletetuff removed!*/
+
+/* Previously obsolete error code re-used in 7.38.0 */
+#define CURLE_OBSOLETE16 CURLE_HTTP2
+
+/* Previously obsolete error codes re-used in 7.24.0 */
+#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED
+#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT
+
+/* compatibility with older names */
+#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
+
+/* The following were added in 7.21.5, April 2011 */
+#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
+
+/* The following were added in 7.17.1 */
+/* These are scheduled to disappear by 2009 */
+#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION
+
+/* The following were added in 7.17.0 */
+/* These are scheduled to disappear by 2009 */
+#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */
+#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46
+#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44
+#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10
+#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16
+#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32
+#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29
+#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12
+#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20
+#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40
+#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24
+#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57
+#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN
+
+#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED
+#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE
+#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR
+#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL
+#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS
+#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR
+#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED
+
+/* The following were added earlier */
+
+#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT
+
+#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
+#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED
+#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED
+
+#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
+#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME
+
+/* This was the error code 50 in 7.7.3 and a few earlier versions, this
+ is no longer used by libcurl but is instead #defined here only to not
+ make programs break */
+#define CURLE_ALREADY_COMPLETE 99999
+
+/* Provide defines for really old option names */
+#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */
+#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */
+#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA
+
+/* Since long deprecated options with no code in the lib that does anything
+ with them. */
+#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40
+#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72
+
+#endif /*!CURL_NO_OLDIES*/
+
+/* This prototype applies to all conversion callbacks */
+typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
+
+typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */
+ void *ssl_ctx, /* actually an
+ OpenSSL SSL_CTX */
+ void *userptr);
+
+typedef enum {
+ CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use
+ CONNECT HTTP/1.1 */
+ CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
+ HTTP/1.0 */
+ CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
+ in 7.10 */
+ CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
+ CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */
+ CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the
+ host name rather than the IP address. added
+ in 7.18.0 */
+} curl_proxytype; /* this enum was added in 7.10 */
+
+/*
+ * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options:
+ *
+ * CURLAUTH_NONE - No HTTP authentication
+ * CURLAUTH_BASIC - HTTP Basic authentication (default)
+ * CURLAUTH_DIGEST - HTTP Digest authentication
+ * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication
+ * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated)
+ * CURLAUTH_NTLM - HTTP NTLM authentication
+ * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour
+ * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper
+ * CURLAUTH_ONLY - Use together with a single other type to force no
+ * authentication or just that single type
+ * CURLAUTH_ANY - All fine types set
+ * CURLAUTH_ANYSAFE - All fine types except Basic
+ */
+
+#define CURLAUTH_NONE ((unsigned long)0)
+#define CURLAUTH_BASIC (((unsigned long)1) << 0)
+#define CURLAUTH_DIGEST (((unsigned long)1) << 1)
+#define CURLAUTH_NEGOTIATE (((unsigned long)1) << 2)
+/* Deprecated since the advent of CURLAUTH_NEGOTIATE */
+#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE
+#define CURLAUTH_NTLM (((unsigned long)1) << 3)
+#define CURLAUTH_DIGEST_IE (((unsigned long)1) << 4)
+#define CURLAUTH_NTLM_WB (((unsigned long)1) << 5)
+#define CURLAUTH_ONLY (((unsigned long)1) << 31)
+#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE)
+#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
+
+#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */
+#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */
+#define CURLSSH_AUTH_PUBLICKEY (1 << 0) /* public/private key files */
+#define CURLSSH_AUTH_PASSWORD (1 << 1) /* password */
+#define CURLSSH_AUTH_HOST (1 << 2) /* host key files */
+#define CURLSSH_AUTH_KEYBOARD (1 << 3) /* keyboard interactive */
+#define CURLSSH_AUTH_AGENT (1 << 4) /* agent (ssh-agent, pageant...) */
+#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY
+
+#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */
+#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1 << 0) /* if permitted by policy */
+#define CURLGSSAPI_DELEGATION_FLAG (1 << 1) /* delegate always */
+
+#define CURL_ERROR_SIZE 256
+
+enum curl_khtype {
+ CURLKHTYPE_UNKNOWN,
+ CURLKHTYPE_RSA1,
+ CURLKHTYPE_RSA,
+ CURLKHTYPE_DSS
+};
+
+struct curl_khkey {
+ const char *key; /* points to a zero-terminated string encoded with base64
+ if len is zero, otherwise to the "raw" data */
+ size_t len;
+ enum curl_khtype keytype;
+};
+
+/* this is the set of return values expected from the curl_sshkeycallback
+ callback */
+enum curl_khstat {
+ CURLKHSTAT_FINE_ADD_TO_FILE,
+ CURLKHSTAT_FINE,
+ CURLKHSTAT_REJECT, /* reject the connection, return an error */
+ CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so
+ this causes a CURLE_DEFER error but otherwise the
+ connection will be left intact etc */
+ CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */
+};
+
+/* this is the set of status codes pass in to the callback */
+enum curl_khmatch {
+ CURLKHMATCH_OK, /* match */
+ CURLKHMATCH_MISMATCH, /* host found, key mismatch! */
+ CURLKHMATCH_MISSING, /* no matching host/key found */
+ CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */
+};
+
+typedef int
+ (*curl_sshkeycallback) (CURL *easy, /* easy handle */
+ const struct curl_khkey *knownkey, /* known */
+ const struct curl_khkey *foundkey, /* found */
+ enum curl_khmatch, /* libcurl's view on the keys */
+ void *clientp); /* custom pointer passed from app */
+
+/* parameter for the CURLOPT_USE_SSL option */
+typedef enum {
+ CURLUSESSL_NONE, /* do not attempt to use SSL */
+ CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */
+ CURLUSESSL_CONTROL, /* SSL for the control connection or fail */
+ CURLUSESSL_ALL, /* SSL for all communication or fail */
+ CURLUSESSL_LAST /* not an option, never use */
+} curl_usessl;
+
+/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */
+
+/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the
+ name of improving interoperability with older servers. Some SSL libraries
+ have introduced work-arounds for this flaw but those work-arounds sometimes
+ make the SSL communication fail. To regain functionality with those broken
+ servers, a user can this way allow the vulnerability back. */
+#define CURLSSLOPT_ALLOW_BEAST (1 << 0)
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all the obsolete stuff removed */
+
+
+/* Backwards compatibility with older names */
+/* These are scheduled to disappear by 2009 */
+
+#define CURLFTPSSL_NONE CURLUSESSL_NONE
+#define CURLFTPSSL_TRY CURLUSESSL_TRY
+#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL
+#define CURLFTPSSL_ALL CURLUSESSL_ALL
+#define CURLFTPSSL_LAST CURLUSESSL_LAST
+#define curl_ftpssl curl_usessl
+#endif /*!CURL_NO_OLDIES*/
+
+/* parameter for the CURLOPT_FTP_SSL_CCC option */
+typedef enum {
+ CURLFTPSSL_CCC_NONE, /* do not send CCC */
+ CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */
+ CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */
+ CURLFTPSSL_CCC_LAST /* not an option, never use */
+} curl_ftpccc;
+
+/* parameter for the CURLOPT_FTPSSLAUTH option */
+typedef enum {
+ CURLFTPAUTH_DEFAULT, /* let libcurl decide */
+ CURLFTPAUTH_SSL, /* use "AUTH SSL" */
+ CURLFTPAUTH_TLS, /* use "AUTH TLS" */
+ CURLFTPAUTH_LAST /* not an option, never use */
+} curl_ftpauth;
+
+/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */
+typedef enum {
+ CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */
+ CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD
+ again if MKD succeeded, for SFTP this does
+ similar magic */
+ CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD again even if MKD failed */
+
+ CURLFTP_CREATE_DIR_LAST /* not an option, never use */
+} curl_ftpcreatedir;
+
+/* parameter for the CURLOPT_FTP_FILEMETHOD option */
+typedef enum {
+ CURLFTPMETHOD_DEFAULT, /* let libcurl pick */
+ CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */
+ CURLFTPMETHOD_NOCWD, /* no CWD at all */
+ CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */
+ CURLFTPMETHOD_LAST /* not an option, never use */
+} curl_ftpmethod;
+
+/* bitmask defines for CURLOPT_HEADEROPT */
+#define CURLHEADER_UNIFIED 0
+#define CURLHEADER_SEPARATE (1<<0)
+
+/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
+#define CURLPROTO_HTTP (1<<0)
+#define CURLPROTO_HTTPS (1<<1)
+#define CURLPROTO_FTP (1<<2)
+#define CURLPROTO_FTPS (1<<3)
+#define CURLPROTO_SCP (1<<4)
+#define CURLPROTO_SFTP (1<<5)
+#define CURLPROTO_TELNET (1<<6)
+#define CURLPROTO_LDAP (1<<7)
+#define CURLPROTO_LDAPS (1<<8)
+#define CURLPROTO_DICT (1<<9)
+#define CURLPROTO_FILE (1<<10)
+#define CURLPROTO_TFTP (1<<11)
+#define CURLPROTO_IMAP (1<<12)
+#define CURLPROTO_IMAPS (1<<13)
+#define CURLPROTO_POP3 (1<<14)
+#define CURLPROTO_POP3S (1<<15)
+#define CURLPROTO_SMTP (1<<16)
+#define CURLPROTO_SMTPS (1<<17)
+#define CURLPROTO_RTSP (1<<18)
+#define CURLPROTO_RTMP (1<<19)
+#define CURLPROTO_RTMPT (1<<20)
+#define CURLPROTO_RTMPE (1<<21)
+#define CURLPROTO_RTMPTE (1<<22)
+#define CURLPROTO_RTMPS (1<<23)
+#define CURLPROTO_RTMPTS (1<<24)
+#define CURLPROTO_GOPHER (1<<25)
+#define CURLPROTO_SMB (1<<26)
+#define CURLPROTO_SMBS (1<<27)
+#define CURLPROTO_ALL (~0) /* enable everything */
+
+/* long may be 32 or 64 bits, but we should never depend on anything else
+ but 32 */
+#define CURLOPTTYPE_LONG 0
+#define CURLOPTTYPE_OBJECTPOINT 10000
+#define CURLOPTTYPE_FUNCTIONPOINT 20000
+#define CURLOPTTYPE_OFF_T 30000
+
+/* name is uppercase CURLOPT_<name>,
+ type is one of the defined CURLOPTTYPE_<type>
+ number is unique identifier */
+#ifdef CINIT
+#undef CINIT
+#endif
+
+#ifdef CURL_ISOCPP
+#define CINIT(na, t, nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define LONG CURLOPTTYPE_LONG
+#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
+#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+#define OFF_T CURLOPTTYPE_OFF_T
+#define CINIT(name, type, number) CURLOPT_/**/name = type + number
+#endif
+
+/*
+ * This macro-mania below setups the CURLOPT_[what] enum, to be used with
+ * curl_easy_setopt(). The first argument in the CINIT() macro is the [what]
+ * word.
+ */
+
+typedef enum {
+ /* This is the FILE * or void * the regular output should be written to. */
+ CINIT(WRITEDATA, OBJECTPOINT, 1),
+
+ /* The full URL to get/put */
+ CINIT(URL, OBJECTPOINT, 2),
+
+ /* Port number to connect to, if other than default. */
+ CINIT(PORT, LONG, 3),
+
+ /* Name of proxy to use. */
+ CINIT(PROXY, OBJECTPOINT, 4),
+
+ /* "user:password;options" to use when fetching. */
+ CINIT(USERPWD, OBJECTPOINT, 5),
+
+ /* "user:password" to use with proxy. */
+ CINIT(PROXYUSERPWD, OBJECTPOINT, 6),
+
+ /* Range to get, specified as an ASCII string. */
+ CINIT(RANGE, OBJECTPOINT, 7),
+
+ /* not used */
+
+ /* Specified file stream to upload from (use as input): */
+ CINIT(READDATA, OBJECTPOINT, 9),
+
+ /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
+ * bytes big. If this is not used, error messages go to stderr instead: */
+ CINIT(ERRORBUFFER, OBJECTPOINT, 10),
+
+ /* Function that will be called to store the output (instead of fwrite). The
+ * parameters will use fwrite() syntax, make sure to follow them. */
+ CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
+
+ /* Function that will be called to read the input (instead of fread). The
+ * parameters will use fread() syntax, make sure to follow them. */
+ CINIT(READFUNCTION, FUNCTIONPOINT, 12),
+
+ /* Time-out the read operation after this amount of seconds */
+ CINIT(TIMEOUT, LONG, 13),
+
+ /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about
+ * how large the file being sent really is. That allows better error
+ * checking and better verifies that the upload was successful. -1 means
+ * unknown size.
+ *
+ * For large file support, there is also a _LARGE version of the key
+ * which takes an off_t type, allowing platforms with larger off_t
+ * sizes to handle larger files. See below for INFILESIZE_LARGE.
+ */
+ CINIT(INFILESIZE, LONG, 14),
+
+ /* POST static input fields. */
+ CINIT(POSTFIELDS, OBJECTPOINT, 15),
+
+ /* Set the referrer page (needed by some CGIs) */
+ CINIT(REFERER, OBJECTPOINT, 16),
+
+ /* Set the FTP PORT string (interface name, named or numerical IP address)
+ Use i.e '-' to use default address. */
+ CINIT(FTPPORT, OBJECTPOINT, 17),
+
+ /* Set the User-Agent string (examined by some CGIs) */
+ CINIT(USERAGENT, OBJECTPOINT, 18),
+
+ /* If the download receives less than "low speed limit" bytes/second
+ * during "low speed time" seconds, the operations is aborted.
+ * You could i.e if you have a pretty high speed connection, abort if
+ * it is less than 2000 bytes/sec during 20 seconds.
+ */
+
+ /* Set the "low speed limit" */
+ CINIT(LOW_SPEED_LIMIT, LONG, 19),
+
+ /* Set the "low speed time" */
+ CINIT(LOW_SPEED_TIME, LONG, 20),
+
+ /* Set the continuation offset.
+ *
+ * Note there is also a _LARGE version of this key which uses
+ * off_t types, allowing for large file offsets on platforms which
+ * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE.
+ */
+ CINIT(RESUME_FROM, LONG, 21),
+
+ /* Set cookie in request: */
+ CINIT(COOKIE, OBJECTPOINT, 22),
+
+ /* This points to a linked list of headers, struct curl_slist kind. This
+ list is also used for RTSP (in spite of its name) */
+ CINIT(HTTPHEADER, OBJECTPOINT, 23),
+
+ /* This points to a linked list of post entries, struct curl_httppost */
+ CINIT(HTTPPOST, OBJECTPOINT, 24),
+
+ /* name of the file keeping your private SSL-certificate */
+ CINIT(SSLCERT, OBJECTPOINT, 25),
+
+ /* password for the SSL or SSH private key */
+ CINIT(KEYPASSWD, OBJECTPOINT, 26),
+
+ /* send TYPE parameter? */
+ CINIT(CRLF, LONG, 27),
+
+ /* send linked-list of QUOTE commands */
+ CINIT(QUOTE, OBJECTPOINT, 28),
+
+ /* send FILE * or void * to store headers to, if you use a callback it
+ is simply passed to the callback unmodified */
+ CINIT(HEADERDATA, OBJECTPOINT, 29),
+
+ /* point to a file to read the initial cookies from, also enables
+ "cookie awareness" */
+ CINIT(COOKIEFILE, OBJECTPOINT, 31),
+
+ /* What version to specifically try to use.
+ See CURL_SSLVERSION defines below. */
+ CINIT(SSLVERSION, LONG, 32),
+
+ /* What kind of HTTP time condition to use, see defines */
+ CINIT(TIMECONDITION, LONG, 33),
+
+ /* Time to use with the above condition. Specified in number of seconds
+ since 1 Jan 1970 */
+ CINIT(TIMEVALUE, LONG, 34),
+
+ /* 35 = OBSOLETE */
+
+ /* Custom request, for customizing the get command like
+ HTTP: DELETE, TRACE and others
+ FTP: to use a different list command
+ */
+ CINIT(CUSTOMREQUEST, OBJECTPOINT, 36),
+
+ /* HTTP request, for odd commands like DELETE, TRACE and others */
+ CINIT(STDERR, OBJECTPOINT, 37),
+
+ /* 38 is not used */
+
+ /* send linked-list of post-transfer QUOTE commands */
+ CINIT(POSTQUOTE, OBJECTPOINT, 39),
+
+ CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */
+
+ CINIT(VERBOSE, LONG, 41), /* talk a lot */
+ CINIT(HEADER, LONG, 42), /* throw the header out too */
+ CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */
+ CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */
+ CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 400 */
+ CINIT(UPLOAD, LONG, 46), /* this is an upload */
+ CINIT(POST, LONG, 47), /* HTTP POST method */
+ CINIT(DIRLISTONLY, LONG, 48), /* bare names when listing directories */
+
+ CINIT(APPEND, LONG, 50), /* Append instead of overwrite on upload! */
+
+ /* Specify whether to read the user+password from the .netrc or the URL.
+ * This must be one of the CURL_NETRC_* enums below. */
+ CINIT(NETRC, LONG, 51),
+
+ CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */
+
+ CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
+ CINIT(PUT, LONG, 54), /* HTTP PUT */
+
+ /* 55 = OBSOLETE */
+
+ /* DEPRECATED
+ * Function that will be called instead of the internal progress display
+ * function. This function should be defined as the curl_progress_callback
+ * prototype defines. */
+ CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
+
+ /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
+ callbacks */
+ CINIT(PROGRESSDATA, OBJECTPOINT, 57),
+#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
+
+ /* We want the referrer field set automatically when following locations */
+ CINIT(AUTOREFERER, LONG, 58),
+
+ /* Port of the proxy, can be set in the proxy string as well with:
+ "[host]:[port]" */
+ CINIT(PROXYPORT, LONG, 59),
+
+ /* size of the POST input data, if strlen() is not good to use */
+ CINIT(POSTFIELDSIZE, LONG, 60),
+
+ /* tunnel non-http operations through a HTTP proxy */
+ CINIT(HTTPPROXYTUNNEL, LONG, 61),
+
+ /* Set the interface string to use as outgoing network interface */
+ CINIT(INTERFACE, OBJECTPOINT, 62),
+
+ /* Set the krb4/5 security level, this also enables krb4/5 awareness. This
+ * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string
+ * is set but doesn't match one of these, 'private' will be used. */
+ CINIT(KRBLEVEL, OBJECTPOINT, 63),
+
+ /* Set if we should verify the peer in ssl handshake, set 1 to verify. */
+ CINIT(SSL_VERIFYPEER, LONG, 64),
+
+ /* The CApath or CAfile used to validate the peer certificate
+ this option is used only if SSL_VERIFYPEER is true */
+ CINIT(CAINFO, OBJECTPOINT, 65),
+
+ /* 66 = OBSOLETE */
+ /* 67 = OBSOLETE */
+
+ /* Maximum number of http redirects to follow */
+ CINIT(MAXREDIRS, LONG, 68),
+
+ /* Pass a long set to 1 to get the date of the requested document (if
+ possible)! Pass a zero to shut it off. */
+ CINIT(FILETIME, LONG, 69),
+
+ /* This points to a linked list of telnet options */
+ CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
+
+ /* Max amount of cached alive connections */
+ CINIT(MAXCONNECTS, LONG, 71),
+
+ CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */
+
+ /* 73 = OBSOLETE */
+
+ /* Set to explicitly use a new connection for the upcoming transfer.
+ Do not use this unless you're absolutely sure of this, as it makes the
+ operation slower and is less friendly for the network. */
+ CINIT(FRESH_CONNECT, LONG, 74),
+
+ /* Set to explicitly forbid the upcoming transfer's connection to be re-used
+ when done. Do not use this unless you're absolutely sure of this, as it
+ makes the operation slower and is less friendly for the network. */
+ CINIT(FORBID_REUSE, LONG, 75),
+
+ /* Set to a file name that contains random data for libcurl to use to
+ seed the random engine when doing SSL connects. */
+ CINIT(RANDOM_FILE, OBJECTPOINT, 76),
+
+ /* Set to the Entropy Gathering Daemon socket pathname */
+ CINIT(EGDSOCKET, OBJECTPOINT, 77),
+
+ /* Time-out connect operations after this amount of seconds, if connects are
+ OK within this time, then fine... This only aborts the connect phase. */
+ CINIT(CONNECTTIMEOUT, LONG, 78),
+
+ /* Function that will be called to store headers (instead of fwrite). The
+ * parameters will use fwrite() syntax, make sure to follow them. */
+ CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79),
+
+ /* Set this to force the HTTP request to get back to GET. Only really usable
+ if POST, PUT or a custom request have been used first.
+ */
+ CINIT(HTTPGET, LONG, 80),
+
+ /* Set if we should verify the Common name from the peer certificate in ssl
+ * handshake, set 1 to check existence, 2 to ensure that it matches the
+ * provided hostname. */
+ CINIT(SSL_VERIFYHOST, LONG, 81),
+
+ /* Specify which file name to write all known cookies in after completed
+ operation. Set file name to "-" (dash) to make it go to stdout. */
+ CINIT(COOKIEJAR, OBJECTPOINT, 82),
+
+ /* Specify which SSL ciphers to use */
+ CINIT(SSL_CIPHER_LIST, OBJECTPOINT, 83),
+
+ /* Specify which HTTP version to use! This must be set to one of the
+ CURL_HTTP_VERSION* enums set below. */
+ CINIT(HTTP_VERSION, LONG, 84),
+
+ /* Specifically switch on or off the FTP engine's use of the EPSV command. By
+ default, that one will always be attempted before the more traditional
+ PASV command. */
+ CINIT(FTP_USE_EPSV, LONG, 85),
+
+ /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
+ CINIT(SSLCERTTYPE, OBJECTPOINT, 86),
+
+ /* name of the file keeping your private SSL-key */
+ CINIT(SSLKEY, OBJECTPOINT, 87),
+
+ /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */
+ CINIT(SSLKEYTYPE, OBJECTPOINT, 88),
+
+ /* crypto engine for the SSL-sub system */
+ CINIT(SSLENGINE, OBJECTPOINT, 89),
+
+ /* set the crypto engine for the SSL-sub system as default
+ the param has no meaning...
+ */
+ CINIT(SSLENGINE_DEFAULT, LONG, 90),
+
+ /* Non-zero value means to use the global dns cache */
+ CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */
+
+ /* DNS cache timeout */
+ CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
+
+ /* send linked-list of pre-transfer QUOTE commands */
+ CINIT(PREQUOTE, OBJECTPOINT, 93),
+
+ /* set the debug function */
+ CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94),
+
+ /* set the data for the debug function */
+ CINIT(DEBUGDATA, OBJECTPOINT, 95),
+
+ /* mark this as start of a cookie session */
+ CINIT(COOKIESESSION, LONG, 96),
+
+ /* The CApath directory used to validate the peer certificate
+ this option is used only if SSL_VERIFYPEER is true */
+ CINIT(CAPATH, OBJECTPOINT, 97),
+
+ /* Instruct libcurl to use a smaller receive buffer */
+ CINIT(BUFFERSIZE, LONG, 98),
+
+ /* Instruct libcurl to not use any signal/alarm handlers, even when using
+ timeouts. This option is useful for multi-threaded applications.
+ See libcurl-the-guide for more background information. */
+ CINIT(NOSIGNAL, LONG, 99),
+
+ /* Provide a CURLShare for mutexing non-ts data */
+ CINIT(SHARE, OBJECTPOINT, 100),
+
+ /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
+ CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
+ CINIT(PROXYTYPE, LONG, 101),
+
+ /* Set the Accept-Encoding string. Use this to tell a server you would like
+ the response to be compressed. Before 7.21.6, this was known as
+ CURLOPT_ENCODING */
+ CINIT(ACCEPT_ENCODING, OBJECTPOINT, 102),
+
+ /* Set pointer to private data */
+ CINIT(PRIVATE, OBJECTPOINT, 103),
+
+ /* Set aliases for HTTP 200 in the HTTP Response header */
+ CINIT(HTTP200ALIASES, OBJECTPOINT, 104),
+
+ /* Continue to send authentication (user+password) when following locations,
+ even when hostname changed. This can potentially send off the name
+ and password to whatever host the server decides. */
+ CINIT(UNRESTRICTED_AUTH, LONG, 105),
+
+ /* Specifically switch on or off the FTP engine's use of the EPRT command (
+ it also disables the LPRT attempt). By default, those ones will always be
+ attempted before the good old traditional PORT command. */
+ CINIT(FTP_USE_EPRT, LONG, 106),
+
+ /* Set this to a bitmask value to enable the particular authentications
+ methods you like. Use this in combination with CURLOPT_USERPWD.
+ Note that setting multiple bits may cause extra network round-trips. */
+ CINIT(HTTPAUTH, LONG, 107),
+
+ /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx
+ in second argument. The function must be matching the
+ curl_ssl_ctx_callback proto. */
+ CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108),
+
+ /* Set the userdata for the ssl context callback function's third
+ argument */
+ CINIT(SSL_CTX_DATA, OBJECTPOINT, 109),
+
+ /* FTP Option that causes missing dirs to be created on the remote server.
+ In 7.19.4 we introduced the convenience enums for this option using the
+ CURLFTP_CREATE_DIR prefix.
+ */
+ CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110),
+
+ /* Set this to a bitmask value to enable the particular authentications
+ methods you like. Use this in combination with CURLOPT_PROXYUSERPWD.
+ Note that setting multiple bits may cause extra network round-trips. */
+ CINIT(PROXYAUTH, LONG, 111),
+
+ /* FTP option that changes the timeout, in seconds, associated with
+ getting a response. This is different from transfer timeout time and
+ essentially places a demand on the FTP server to acknowledge commands
+ in a timely manner. */
+ CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112),
+#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
+
+ /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
+ tell libcurl to resolve names to those IP versions only. This only has
+ affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
+ CINIT(IPRESOLVE, LONG, 113),
+
+ /* Set this option to limit the size of a file that will be downloaded from
+ an HTTP or FTP server.
+
+ Note there is also _LARGE version which adds large file support for
+ platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */
+ CINIT(MAXFILESIZE, LONG, 114),
+
+ /* See the comment for INFILESIZE above, but in short, specifies
+ * the size of the file being uploaded. -1 means unknown.
+ */
+ CINIT(INFILESIZE_LARGE, OFF_T, 115),
+
+ /* Sets the continuation offset. There is also a LONG version of this;
+ * look above for RESUME_FROM.
+ */
+ CINIT(RESUME_FROM_LARGE, OFF_T, 116),
+
+ /* Sets the maximum size of data that will be downloaded from
+ * an HTTP or FTP server. See MAXFILESIZE above for the LONG version.
+ */
+ CINIT(MAXFILESIZE_LARGE, OFF_T, 117),
+
+ /* Set this option to the file name of your .netrc file you want libcurl
+ to parse (using the CURLOPT_NETRC option). If not set, libcurl will do
+ a poor attempt to find the user's home directory and check for a .netrc
+ file in there. */
+ CINIT(NETRC_FILE, OBJECTPOINT, 118),
+
+ /* Enable SSL/TLS for FTP, pick one of:
+ CURLUSESSL_TRY - try using SSL, proceed anyway otherwise
+ CURLUSESSL_CONTROL - SSL for the control connection or fail
+ CURLUSESSL_ALL - SSL for all communication or fail
+ */
+ CINIT(USE_SSL, LONG, 119),
+
+ /* The _LARGE version of the standard POSTFIELDSIZE option */
+ CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
+
+ /* Enable/disable the TCP Nagle algorithm */
+ CINIT(TCP_NODELAY, LONG, 121),
+
+ /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 123 OBSOLETE. Gone in 7.16.0 */
+ /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 127 OBSOLETE. Gone in 7.16.0 */
+ /* 128 OBSOLETE. Gone in 7.16.0 */
+
+ /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option
+ can be used to change libcurl's default action which is to first try
+ "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK
+ response has been received.
+
+ Available parameters are:
+ CURLFTPAUTH_DEFAULT - let libcurl decide
+ CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS
+ CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL
+ */
+ CINIT(FTPSSLAUTH, LONG, 129),
+
+ CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130),
+ CINIT(IOCTLDATA, OBJECTPOINT, 131),
+
+ /* 132 OBSOLETE. Gone in 7.16.0 */
+ /* 133 OBSOLETE. Gone in 7.16.0 */
+
+ /* zero terminated string for pass on to the FTP server when asked for
+ "account" info */
+ CINIT(FTP_ACCOUNT, OBJECTPOINT, 134),
+
+ /* feed cookies into cookie engine */
+ CINIT(COOKIELIST, OBJECTPOINT, 135),
+
+ /* ignore Content-Length */
+ CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
+
+ /* Set to non-zero to skip the IP address received in a 227 PASV FTP server
+ response. Typically used for FTP-SSL purposes but is not restricted to
+ that. libcurl will then instead use the same IP address it used for the
+ control connection. */
+ CINIT(FTP_SKIP_PASV_IP, LONG, 137),
+
+ /* Select "file method" to use when doing FTP, see the curl_ftpmethod
+ above. */
+ CINIT(FTP_FILEMETHOD, LONG, 138),
+
+ /* Local port number to bind the socket to */
+ CINIT(LOCALPORT, LONG, 139),
+
+ /* Number of ports to try, including the first one set with LOCALPORT.
+ Thus, setting it to 1 will make no additional attempts but the first.
+ */
+ CINIT(LOCALPORTRANGE, LONG, 140),
+
+ /* no transfer, set up connection and let application use the socket by
+ extracting it with CURLINFO_LASTSOCKET */
+ CINIT(CONNECT_ONLY, LONG, 141),
+
+ /* Function that will be called to convert from the
+ network encoding (instead of using the iconv calls in libcurl) */
+ CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142),
+
+ /* Function that will be called to convert to the
+ network encoding (instead of using the iconv calls in libcurl) */
+ CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143),
+
+ /* Function that will be called to convert from UTF8
+ (instead of using the iconv calls in libcurl)
+ Note that this is used only for SSL certificate processing */
+ CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
+
+ /* if the connection proceeds too quickly then need to slow it down */
+ /* limit-rate: maximum number of bytes per second to send or receive */
+ CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145),
+ CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146),
+
+ /* Pointer to command string to send if USER/PASS fails. */
+ CINIT(FTP_ALTERNATIVE_TO_USER, OBJECTPOINT, 147),
+
+ /* callback function for setting socket options */
+ CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148),
+ CINIT(SOCKOPTDATA, OBJECTPOINT, 149),
+
+ /* set to 0 to disable session ID re-use for this transfer, default is
+ enabled (== 1) */
+ CINIT(SSL_SESSIONID_CACHE, LONG, 150),
+
+ /* allowed SSH authentication methods */
+ CINIT(SSH_AUTH_TYPES, LONG, 151),
+
+ /* Used by scp/sftp to do public/private key authentication */
+ CINIT(SSH_PUBLIC_KEYFILE, OBJECTPOINT, 152),
+ CINIT(SSH_PRIVATE_KEYFILE, OBJECTPOINT, 153),
+
+ /* Send CCC (Clear Command Channel) after authentication */
+ CINIT(FTP_SSL_CCC, LONG, 154),
+
+ /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */
+ CINIT(TIMEOUT_MS, LONG, 155),
+ CINIT(CONNECTTIMEOUT_MS, LONG, 156),
+
+ /* set to zero to disable the libcurl's decoding and thus pass the raw body
+ data to the application even when it is encoded/compressed */
+ CINIT(HTTP_TRANSFER_DECODING, LONG, 157),
+ CINIT(HTTP_CONTENT_DECODING, LONG, 158),
+
+ /* Permission used when creating new files and directories on the remote
+ server for protocols that support it, SFTP/SCP/FILE */
+ CINIT(NEW_FILE_PERMS, LONG, 159),
+ CINIT(NEW_DIRECTORY_PERMS, LONG, 160),
+
+ /* Set the behaviour of POST when redirecting. Values must be set to one
+ of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */
+ CINIT(POSTREDIR, LONG, 161),
+
+ /* used by scp/sftp to verify the host's public key */
+ CINIT(SSH_HOST_PUBLIC_KEY_MD5, OBJECTPOINT, 162),
+
+ /* Callback function for opening socket (instead of socket(2)). Optionally,
+ callback is able change the address or refuse to connect returning
+ CURL_SOCKET_BAD. The callback should have type
+ curl_opensocket_callback */
+ CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163),
+ CINIT(OPENSOCKETDATA, OBJECTPOINT, 164),
+
+ /* POST volatile input fields. */
+ CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165),
+
+ /* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy */
+ CINIT(PROXY_TRANSFER_MODE, LONG, 166),
+
+ /* Callback function for seeking in the input stream */
+ CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167),
+ CINIT(SEEKDATA, OBJECTPOINT, 168),
+
+ /* CRL file */
+ CINIT(CRLFILE, OBJECTPOINT, 169),
+
+ /* Issuer certificate */
+ CINIT(ISSUERCERT, OBJECTPOINT, 170),
+
+ /* (IPv6) Address scope */
+ CINIT(ADDRESS_SCOPE, LONG, 171),
+
+ /* Collect certificate chain info and allow it to get retrievable with
+ CURLINFO_CERTINFO after the transfer is complete. */
+ CINIT(CERTINFO, LONG, 172),
+
+ /* "name" and "pwd" to use when fetching. */
+ CINIT(USERNAME, OBJECTPOINT, 173),
+ CINIT(PASSWORD, OBJECTPOINT, 174),
+
+ /* "name" and "pwd" to use with Proxy when fetching. */
+ CINIT(PROXYUSERNAME, OBJECTPOINT, 175),
+ CINIT(PROXYPASSWORD, OBJECTPOINT, 176),
+
+ /* Comma separated list of hostnames defining no-proxy zones. These should
+ match both hostnames directly, and hostnames within a domain. For
+ example, local.com will match local.com and www.local.com, but NOT
+ notlocal.com or www.notlocal.com. For compatibility with other
+ implementations of this, .local.com will be considered to be the same as
+ local.com. A single * is the only valid wildcard, and effectively
+ disables the use of proxy. */
+ CINIT(NOPROXY, OBJECTPOINT, 177),
+
+ /* block size for TFTP transfers */
+ CINIT(TFTP_BLKSIZE, LONG, 178),
+
+ /* Socks Service */
+ CINIT(SOCKS5_GSSAPI_SERVICE, OBJECTPOINT, 179),
+
+ /* Socks Service */
+ CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),
+
+ /* set the bitmask for the protocols that are allowed to be used for the
+ transfer, which thus helps the app which takes URLs from users or other
+ external inputs and want to restrict what protocol(s) to deal
+ with. Defaults to CURLPROTO_ALL. */
+ CINIT(PROTOCOLS, LONG, 181),
+
+ /* set the bitmask for the protocols that libcurl is allowed to follow to,
+ as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
+ to be set in both bitmasks to be allowed to get redirected to. Defaults
+ to all protocols except FILE and SCP. */
+ CINIT(REDIR_PROTOCOLS, LONG, 182),
+
+ /* set the SSH knownhost file name to use */
+ CINIT(SSH_KNOWNHOSTS, OBJECTPOINT, 183),
+
+ /* set the SSH host key callback, must point to a curl_sshkeycallback
+ function */
+ CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184),
+
+ /* set the SSH host key callback custom pointer */
+ CINIT(SSH_KEYDATA, OBJECTPOINT, 185),
+
+ /* set the SMTP mail originator */
+ CINIT(MAIL_FROM, OBJECTPOINT, 186),
+
+ /* set the SMTP mail receiver(s) */
+ CINIT(MAIL_RCPT, OBJECTPOINT, 187),
+
+ /* FTP: send PRET before PASV */
+ CINIT(FTP_USE_PRET, LONG, 188),
+
+ /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */
+ CINIT(RTSP_REQUEST, LONG, 189),
+
+ /* The RTSP session identifier */
+ CINIT(RTSP_SESSION_ID, OBJECTPOINT, 190),
+
+ /* The RTSP stream URI */
+ CINIT(RTSP_STREAM_URI, OBJECTPOINT, 191),
+
+ /* The Transport: header to use in RTSP requests */
+ CINIT(RTSP_TRANSPORT, OBJECTPOINT, 192),
+
+ /* Manually initialize the client RTSP CSeq for this handle */
+ CINIT(RTSP_CLIENT_CSEQ, LONG, 193),
+
+ /* Manually initialize the server RTSP CSeq for this handle */
+ CINIT(RTSP_SERVER_CSEQ, LONG, 194),
+
+ /* The stream to pass to INTERLEAVEFUNCTION. */
+ CINIT(INTERLEAVEDATA, OBJECTPOINT, 195),
+
+ /* Let the application define a custom write method for RTP data */
+ CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196),
+
+ /* Turn on wildcard matching */
+ CINIT(WILDCARDMATCH, LONG, 197),
+
+ /* Directory matching callback called before downloading of an
+ individual file (chunk) started */
+ CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198),
+
+ /* Directory matching callback called after the file (chunk)
+ was downloaded, or skipped */
+ CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199),
+
+ /* Change match (fnmatch-like) callback for wildcard matching */
+ CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200),
+
+ /* Let the application define custom chunk data pointer */
+ CINIT(CHUNK_DATA, OBJECTPOINT, 201),
+
+ /* FNMATCH_FUNCTION user pointer */
+ CINIT(FNMATCH_DATA, OBJECTPOINT, 202),
+
+ /* send linked-list of name:port:address sets */
+ CINIT(RESOLVE, OBJECTPOINT, 203),
+
+ /* Set a username for authenticated TLS */
+ CINIT(TLSAUTH_USERNAME, OBJECTPOINT, 204),
+
+ /* Set a password for authenticated TLS */
+ CINIT(TLSAUTH_PASSWORD, OBJECTPOINT, 205),
+
+ /* Set authentication type for authenticated TLS */
+ CINIT(TLSAUTH_TYPE, OBJECTPOINT, 206),
+
+ /* Set to 1 to enable the "TE:" header in HTTP requests to ask for
+ compressed transfer-encoded responses. Set to 0 to disable the use of TE:
+ in outgoing requests. The current default is 0, but it might change in a
+ future libcurl release.
+
+ libcurl will ask for the compressed methods it knows of, and if that
+ isn't any, it will not ask for transfer-encoding at all even if this
+ option is set to 1.
+
+ */
+ CINIT(TRANSFER_ENCODING, LONG, 207),
+
+ /* Callback function for closing socket (instead of close(2)). The callback
+ should have type curl_closesocket_callback */
+ CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208),
+ CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209),
+
+ /* allow GSSAPI credential delegation */
+ CINIT(GSSAPI_DELEGATION, LONG, 210),
+
+ /* Set the name servers to use for DNS resolution */
+ CINIT(DNS_SERVERS, OBJECTPOINT, 211),
+
+ /* Time-out accept operations (currently for FTP only) after this amount
+ of miliseconds. */
+ CINIT(ACCEPTTIMEOUT_MS, LONG, 212),
+
+ /* Set TCP keepalive */
+ CINIT(TCP_KEEPALIVE, LONG, 213),
+
+ /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */
+ CINIT(TCP_KEEPIDLE, LONG, 214),
+ CINIT(TCP_KEEPINTVL, LONG, 215),
+
+ /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
+ CINIT(SSL_OPTIONS, LONG, 216),
+
+ /* Set the SMTP auth originator */
+ CINIT(MAIL_AUTH, OBJECTPOINT, 217),
+
+ /* Enable/disable SASL initial response */
+ CINIT(SASL_IR, LONG, 218),
+
+ /* Function that will be called instead of the internal progress display
+ * function. This function should be defined as the curl_xferinfo_callback
+ * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
+ CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
+
+ /* The XOAUTH2 bearer token */
+ CINIT(XOAUTH2_BEARER, OBJECTPOINT, 220),
+
+ /* Set the interface string to use as outgoing network
+ * interface for DNS requests.
+ * Only supported by the c-ares DNS backend */
+ CINIT(DNS_INTERFACE, OBJECTPOINT, 221),
+
+ /* Set the local IPv4 address to use for outgoing DNS requests.
+ * Only supported by the c-ares DNS backend */
+ CINIT(DNS_LOCAL_IP4, OBJECTPOINT, 222),
+
+ /* Set the local IPv4 address to use for outgoing DNS requests.
+ * Only supported by the c-ares DNS backend */
+ CINIT(DNS_LOCAL_IP6, OBJECTPOINT, 223),
+
+ /* Set authentication options directly */
+ CINIT(LOGIN_OPTIONS, OBJECTPOINT, 224),
+
+ /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */
+ CINIT(SSL_ENABLE_NPN, LONG, 225),
+
+ /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */
+ CINIT(SSL_ENABLE_ALPN, LONG, 226),
+
+ /* Time to wait for a response to a HTTP request containing an
+ * Expect: 100-continue header before sending the data anyway. */
+ CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227),
+
+ /* This points to a linked list of headers used for proxy requests only,
+ struct curl_slist kind */
+ CINIT(PROXYHEADER, OBJECTPOINT, 228),
+
+ /* Pass in a bitmask of "header options" */
+ CINIT(HEADEROPT, LONG, 229),
+
+ /* The public key in DER form used to validate the peer public key
+ this option is used only if SSL_VERIFYPEER is true */
+ CINIT(PINNEDPUBLICKEY, OBJECTPOINT, 230),
+
+ /* Path to Unix domain socket */
+ CINIT(UNIX_SOCKET_PATH, OBJECTPOINT, 231),
+
+ /* Set if we should verify the certificate status. */
+ CINIT(SSL_VERIFYSTATUS, LONG, 232),
+
+ /* Set if we should enable TLS false start. */
+ CINIT(SSL_FALSESTART, LONG, 233),
+
+ /* Do not squash dot-dot sequences */
+ CINIT(PATH_AS_IS, LONG, 234),
+
+ CURLOPT_LASTENTRY /* the last unused */
+} CURLoption;
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all the obsolete stuff removed */
+
+
+/* Backwards compatibility with older names */
+/* These are scheduled to disappear by 2011 */
+
+/* This was added in version 7.19.1 */
+#define CURLOPT_POST301 CURLOPT_POSTREDIR
+
+/* These are scheduled to disappear by 2009 */
+
+/* The following were added in 7.17.0 */
+#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD
+#define CURLOPT_FTPAPPEND CURLOPT_APPEND
+#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY
+#define CURLOPT_FTP_SSL CURLOPT_USE_SSL
+
+/* The following were added earlier */
+
+#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD
+#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL
+
+#else
+/* This is set if CURL_NO_OLDIES is defined at compile-time */
+#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
+#endif
+
+
+ /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host
+ name resolves addresses using more than one IP protocol version, this
+ option might be handy to force libcurl to use a specific IP version. */
+#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP
+ versions that your system allows */
+#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */
+#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */
+
+ /* three convenient "aliases" that follow the name scheme better */
+#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
+
+ /* These enums are for use with the CURLOPT_HTTP_VERSION option. */
+enum {
+ CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd
+ like the library to choose the best possible for us */
+
+ CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */
+ CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */
+ CURL_HTTP_VERSION_2_0, /* please use HTTP 2.0 in the request */
+
+ CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
+};
+
+/*
+ * Public API enums for RTSP requests
+ */
+enum {
+ CURL_RTSPREQ_NONE, /* first in list */
+ CURL_RTSPREQ_OPTIONS,
+ CURL_RTSPREQ_DESCRIBE,
+ CURL_RTSPREQ_ANNOUNCE,
+ CURL_RTSPREQ_SETUP,
+ CURL_RTSPREQ_PLAY,
+ CURL_RTSPREQ_PAUSE,
+ CURL_RTSPREQ_TEARDOWN,
+ CURL_RTSPREQ_GET_PARAMETER,
+ CURL_RTSPREQ_SET_PARAMETER,
+ CURL_RTSPREQ_RECORD,
+ CURL_RTSPREQ_RECEIVE,
+ CURL_RTSPREQ_LAST /* last in list */
+};
+
+ /* These enums are for use with the CURLOPT_NETRC option. */
+enum CURL_NETRC_OPTION {
+ CURL_NETRC_IGNORED, /* The .netrc will never be read.
+ * This is the default. */
+ CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred
+ * to one in the .netrc. */
+ CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored.
+ * Unless one is set programmatically, the .netrc
+ * will be queried. */
+ CURL_NETRC_LAST
+};
+
+enum {
+ CURL_SSLVERSION_DEFAULT,
+ CURL_SSLVERSION_TLSv1, /* TLS 1.x */
+ CURL_SSLVERSION_SSLv2,
+ CURL_SSLVERSION_SSLv3,
+ CURL_SSLVERSION_TLSv1_0,
+ CURL_SSLVERSION_TLSv1_1,
+ CURL_SSLVERSION_TLSv1_2,
+
+ CURL_SSLVERSION_LAST /* never use, keep last */
+};
+
+enum CURL_TLSAUTH {
+ CURL_TLSAUTH_NONE,
+ CURL_TLSAUTH_SRP,
+ CURL_TLSAUTH_LAST /* never use, keep last */
+};
+
+/* symbols to use with CURLOPT_POSTREDIR.
+ CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303
+ can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302
+ | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */
+
+#define CURL_REDIR_GET_ALL 0
+#define CURL_REDIR_POST_301 1
+#define CURL_REDIR_POST_302 2
+#define CURL_REDIR_POST_303 4
+#define CURL_REDIR_POST_ALL \
+ (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303)
+
+typedef enum {
+ CURL_TIMECOND_NONE,
+
+ CURL_TIMECOND_IFMODSINCE,
+ CURL_TIMECOND_IFUNMODSINCE,
+ CURL_TIMECOND_LASTMOD,
+
+ CURL_TIMECOND_LAST
+} curl_TimeCond;
+
+
+/* curl_strequal() and curl_strnequal() are subject for removal in a future
+ libcurl, see lib/README.curlx for details */
+CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
+CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
+
+/* name is uppercase CURLFORM_<name> */
+#ifdef CFINIT
+#undef CFINIT
+#endif
+
+#ifdef CURL_ISOCPP
+#define CFINIT(name) CURLFORM_ ## name
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define CFINIT(name) CURLFORM_/**/name
+#endif
+
+typedef enum {
+ CFINIT(NOTHING), /********* the first one is unused ************/
+
+ /* */
+ CFINIT(COPYNAME),
+ CFINIT(PTRNAME),
+ CFINIT(NAMELENGTH),
+ CFINIT(COPYCONTENTS),
+ CFINIT(PTRCONTENTS),
+ CFINIT(CONTENTSLENGTH),
+ CFINIT(FILECONTENT),
+ CFINIT(ARRAY),
+ CFINIT(OBSOLETE),
+ CFINIT(FILE),
+
+ CFINIT(BUFFER),
+ CFINIT(BUFFERPTR),
+ CFINIT(BUFFERLENGTH),
+
+ CFINIT(CONTENTTYPE),
+ CFINIT(CONTENTHEADER),
+ CFINIT(FILENAME),
+ CFINIT(END),
+ CFINIT(OBSOLETE2),
+
+ CFINIT(STREAM),
+
+ CURLFORM_LASTENTRY /* the last unused */
+} CURLformoption;
+
+#undef CFINIT /* done */
+
+/* structure to be used as parameter for CURLFORM_ARRAY */
+struct curl_forms {
+ CURLformoption option;
+ const char *value;
+};
+
+/* use this for multipart formpost building */
+/* Returns code for curl_formadd()
+ *
+ * Returns:
+ * CURL_FORMADD_OK on success
+ * CURL_FORMADD_MEMORY if the FormInfo allocation fails
+ * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
+ * CURL_FORMADD_NULL if a null pointer was given for a char
+ * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
+ * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
+ * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
+ * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated
+ * CURL_FORMADD_MEMORY if some allocation for string copying failed.
+ * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
+ *
+ ***************************************************************************/
+typedef enum {
+ CURL_FORMADD_OK, /* first, no error */
+
+ CURL_FORMADD_MEMORY,
+ CURL_FORMADD_OPTION_TWICE,
+ CURL_FORMADD_NULL,
+ CURL_FORMADD_UNKNOWN_OPTION,
+ CURL_FORMADD_INCOMPLETE,
+ CURL_FORMADD_ILLEGAL_ARRAY,
+ CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */
+
+ CURL_FORMADD_LAST /* last */
+} CURLFORMcode;
+
+/*
+ * NAME curl_formadd()
+ *
+ * DESCRIPTION
+ *
+ * Pretty advanced function for building multi-part formposts. Each invoke
+ * adds one part that together construct a full post. Then use
+ * CURLOPT_HTTPPOST to send it off to libcurl.
+ */
+CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost,
+ struct curl_httppost **last_post,
+ ...);
+
+/*
+ * callback function for curl_formget()
+ * The void *arg pointer will be the one passed as second argument to
+ * curl_formget().
+ * The character buffer passed to it must not be freed.
+ * Should return the buffer length passed to it as the argument "len" on
+ * success.
+ */
+typedef size_t (*curl_formget_callback)(void *arg, const char *buf,
+ size_t len);
+
+/*
+ * NAME curl_formget()
+ *
+ * DESCRIPTION
+ *
+ * Serialize a curl_httppost struct built with curl_formadd().
+ * Accepts a void pointer as second argument which will be passed to
+ * the curl_formget_callback function.
+ * Returns 0 on success.
+ */
+CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
+ curl_formget_callback append);
+/*
+ * NAME curl_formfree()
+ *
+ * DESCRIPTION
+ *
+ * Free a multipart formpost previously built with curl_formadd().
+ */
+CURL_EXTERN void curl_formfree(struct curl_httppost *form);
+
+/*
+ * NAME curl_getenv()
+ *
+ * DESCRIPTION
+ *
+ * Returns a malloc()'ed string that MUST be curl_free()ed after usage is
+ * complete. DEPRECATED - see lib/README.curlx
+ */
+CURL_EXTERN char *curl_getenv(const char *variable);
+
+/*
+ * NAME curl_version()
+ *
+ * DESCRIPTION
+ *
+ * Returns a static ascii string of the libcurl version.
+ */
+CURL_EXTERN char *curl_version(void);
+
+/*
+ * NAME curl_easy_escape()
+ *
+ * DESCRIPTION
+ *
+ * Escapes URL strings (converts all letters consider illegal in URLs to their
+ * %XX versions). This function returns a new allocated string or NULL if an
+ * error occurred.
+ */
+CURL_EXTERN char *curl_easy_escape(CURL *handle,
+ const char *string,
+ int length);
+
+/* the previous version: */
+CURL_EXTERN char *curl_escape(const char *string,
+ int length);
+
+
+/*
+ * NAME curl_easy_unescape()
+ *
+ * DESCRIPTION
+ *
+ * Unescapes URL encoding in strings (converts all %XX codes to their 8bit
+ * versions). This function returns a new allocated string or NULL if an error
+ * occurred.
+ * Conversion Note: On non-ASCII platforms the ASCII %XX codes are
+ * converted into the host encoding.
+ */
+CURL_EXTERN char *curl_easy_unescape(CURL *handle,
+ const char *string,
+ int length,
+ int *outlength);
+
+/* the previous version */
+CURL_EXTERN char *curl_unescape(const char *string,
+ int length);
+
+/*
+ * NAME curl_free()
+ *
+ * DESCRIPTION
+ *
+ * Provided for de-allocation in the same translation unit that did the
+ * allocation. Added in libcurl 7.10
+ */
+CURL_EXTERN void curl_free(void *p);
+
+/*
+ * NAME curl_global_init()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_init() should be invoked exactly once for each application that
+ * uses libcurl and before any call of other libcurl functions.
+ *
+ * This function is not thread-safe!
+ */
+CURL_EXTERN CURLcode curl_global_init(long flags);
+
+/*
+ * NAME curl_global_init_mem()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_init() or curl_global_init_mem() should be invoked exactly once
+ * for each application that uses libcurl. This function can be used to
+ * initialize libcurl and set user defined memory management callback
+ * functions. Users can implement memory management routines to check for
+ * memory leaks, check for mis-use of the curl library etc. User registered
+ * callback routines with be invoked by this library instead of the system
+ * memory management routines like malloc, free etc.
+ */
+CURL_EXTERN CURLcode curl_global_init_mem(long flags,
+ curl_malloc_callback m,
+ curl_free_callback f,
+ curl_realloc_callback r,
+ curl_strdup_callback s,
+ curl_calloc_callback c);
+
+/*
+ * NAME curl_global_cleanup()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_cleanup() should be invoked exactly once for each application
+ * that uses libcurl
+ */
+CURL_EXTERN void curl_global_cleanup(void);
+
+/* linked-list structure for the CURLOPT_QUOTE option (and other) */
+struct curl_slist {
+ char *data;
+ struct curl_slist *next;
+};
+
+/*
+ * NAME curl_slist_append()
+ *
+ * DESCRIPTION
+ *
+ * Appends a string to a linked list. If no list exists, it will be created
+ * first. Returns the new list, after appending.
+ */
+CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
+ const char *);
+
+/*
+ * NAME curl_slist_free_all()
+ *
+ * DESCRIPTION
+ *
+ * free a previously built curl_slist.
+ */
+CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
+
+/*
+ * NAME curl_getdate()
+ *
+ * DESCRIPTION
+ *
+ * Returns the time, in seconds since 1 Jan 1970 of the time string given in
+ * the first argument. The time argument in the second parameter is unused
+ * and should be set to NULL.
+ */
+CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
+
+/* info about the certificate chain, only for OpenSSL builds. Asked
+ for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */
+struct curl_certinfo {
+ int num_of_certs; /* number of certificates with information */
+ struct curl_slist **certinfo; /* for each index in this array, there's a
+ linked list with textual information in the
+ format "name: value" */
+};
+
+/* enum for the different supported SSL backends */
+typedef enum {
+ CURLSSLBACKEND_NONE = 0,
+ CURLSSLBACKEND_OPENSSL = 1,
+ CURLSSLBACKEND_GNUTLS = 2,
+ CURLSSLBACKEND_NSS = 3,
+ CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */
+ CURLSSLBACKEND_GSKIT = 5,
+ CURLSSLBACKEND_POLARSSL = 6,
+ CURLSSLBACKEND_CYASSL = 7,
+ CURLSSLBACKEND_SCHANNEL = 8,
+ CURLSSLBACKEND_DARWINSSL = 9,
+ CURLSSLBACKEND_AXTLS = 10
+} curl_sslbackend;
+
+/* Information about the SSL library used and the respective internal SSL
+ handle, which can be used to obtain further information regarding the
+ connection. Asked for with CURLINFO_TLS_SESSION. */
+struct curl_tlssessioninfo {
+ curl_sslbackend backend;
+ void *internals;
+};
+
+#define CURLINFO_STRING 0x100000
+#define CURLINFO_LONG 0x200000
+#define CURLINFO_DOUBLE 0x300000
+#define CURLINFO_SLIST 0x400000
+#define CURLINFO_MASK 0x0fffff
+#define CURLINFO_TYPEMASK 0xf00000
+
+typedef enum {
+ CURLINFO_NONE, /* first, never use this */
+ CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1,
+ CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2,
+ CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3,
+ CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4,
+ CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5,
+ CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6,
+ CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7,
+ CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8,
+ CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9,
+ CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10,
+ CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11,
+ CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12,
+ CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13,
+ CURLINFO_FILETIME = CURLINFO_LONG + 14,
+ CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
+ CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16,
+ CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
+ CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18,
+ CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19,
+ CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20,
+ CURLINFO_PRIVATE = CURLINFO_STRING + 21,
+ CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22,
+ CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23,
+ CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24,
+ CURLINFO_OS_ERRNO = CURLINFO_LONG + 25,
+ CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26,
+ CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27,
+ CURLINFO_COOKIELIST = CURLINFO_SLIST + 28,
+ CURLINFO_LASTSOCKET = CURLINFO_LONG + 29,
+ CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30,
+ CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31,
+ CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32,
+ CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33,
+ CURLINFO_CERTINFO = CURLINFO_SLIST + 34,
+ CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35,
+ CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36,
+ CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37,
+ CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38,
+ CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39,
+ CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
+ CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
+ CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
+ CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43,
+ /* Fill in new entries below here! */
+
+ CURLINFO_LASTONE = 43
+} CURLINFO;
+
+/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
+ CURLINFO_HTTP_CODE */
+#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE
+
+typedef enum {
+ CURLCLOSEPOLICY_NONE, /* first, never use this */
+
+ CURLCLOSEPOLICY_OLDEST,
+ CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
+ CURLCLOSEPOLICY_LEAST_TRAFFIC,
+ CURLCLOSEPOLICY_SLOWEST,
+ CURLCLOSEPOLICY_CALLBACK,
+
+ CURLCLOSEPOLICY_LAST /* last, never use this */
+} curl_closepolicy;
+
+#define CURL_GLOBAL_SSL (1<<0)
+#define CURL_GLOBAL_WIN32 (1<<1)
+#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
+#define CURL_GLOBAL_NOTHING 0
+#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL
+#define CURL_GLOBAL_ACK_EINTR (1<<2)
+
+
+/*****************************************************************************
+ * Setup defines, protos etc for the sharing stuff.
+ */
+
+/* Different data locks for a single share */
+typedef enum {
+ CURL_LOCK_DATA_NONE = 0,
+ /* CURL_LOCK_DATA_SHARE is used internally to say that
+ * the locking is just made to change the internal state of the share
+ * itself.
+ */
+ CURL_LOCK_DATA_SHARE,
+ CURL_LOCK_DATA_COOKIE,
+ CURL_LOCK_DATA_DNS,
+ CURL_LOCK_DATA_SSL_SESSION,
+ CURL_LOCK_DATA_CONNECT,
+ CURL_LOCK_DATA_LAST
+} curl_lock_data;
+
+/* Different lock access types */
+typedef enum {
+ CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */
+ CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */
+ CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */
+ CURL_LOCK_ACCESS_LAST /* never use */
+} curl_lock_access;
+
+typedef void (*curl_lock_function)(CURL *handle,
+ curl_lock_data data,
+ curl_lock_access locktype,
+ void *userptr);
+typedef void (*curl_unlock_function)(CURL *handle,
+ curl_lock_data data,
+ void *userptr);
+
+typedef void CURLSH;
+
+typedef enum {
+ CURLSHE_OK, /* all is fine */
+ CURLSHE_BAD_OPTION, /* 1 */
+ CURLSHE_IN_USE, /* 2 */
+ CURLSHE_INVALID, /* 3 */
+ CURLSHE_NOMEM, /* 4 out of memory */
+ CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */
+ CURLSHE_LAST /* never use */
+} CURLSHcode;
+
+typedef enum {
+ CURLSHOPT_NONE, /* don't use */
+ CURLSHOPT_SHARE, /* specify a data type to share */
+ CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */
+ CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */
+ CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */
+ CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock
+ callback functions */
+ CURLSHOPT_LAST /* never use */
+} CURLSHoption;
+
+CURL_EXTERN CURLSH *curl_share_init(void);
+CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
+CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *);
+
+/****************************************************************************
+ * Structures for querying information about the curl library at runtime.
+ */
+
+typedef enum {
+ CURLVERSION_FIRST,
+ CURLVERSION_SECOND,
+ CURLVERSION_THIRD,
+ CURLVERSION_FOURTH,
+ CURLVERSION_LAST /* never actually use this */
+} CURLversion;
+
+/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by
+ basically all programs ever that want to get version information. It is
+ meant to be a built-in version number for what kind of struct the caller
+ expects. If the struct ever changes, we redefine the NOW to another enum
+ from above. */
+#define CURLVERSION_NOW CURLVERSION_FOURTH
+
+typedef struct {
+ CURLversion age; /* age of the returned struct */
+ const char *version; /* LIBCURL_VERSION */
+ unsigned int version_num; /* LIBCURL_VERSION_NUM */
+ const char *host; /* OS/host/cpu/machine when configured */
+ int features; /* bitmask, see defines below */
+ const char *ssl_version; /* human readable string */
+ long ssl_version_num; /* not used anymore, always 0 */
+ const char *libz_version; /* human readable string */
+ /* protocols is terminated by an entry with a NULL protoname */
+ const char * const *protocols;
+
+ /* The fields below this were added in CURLVERSION_SECOND */
+ const char *ares;
+ int ares_num;
+
+ /* This field was added in CURLVERSION_THIRD */
+ const char *libidn;
+
+ /* These field were added in CURLVERSION_FOURTH */
+
+ /* Same as '_libiconv_version' if built with HAVE_ICONV */
+ int iconv_ver_num;
+
+ const char *libssh_version; /* human readable string */
+} curl_version_info_data;
+
+#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */
+#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported
+ (deprecated) */
+#define CURL_VERSION_SSL (1<<2) /* SSL options are present */
+#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */
+#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */
+#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported
+ (deprecated) */
+#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */
+#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */
+#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */
+#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */
+#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are
+ supported */
+#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */
+#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */
+#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */
+#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */
+#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper
+ is suported */
+#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */
+#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */
+#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */
+#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */
+
+ /*
+ * NAME curl_version_info()
+ *
+ * DESCRIPTION
+ *
+ * This function returns a pointer to a static copy of the version info
+ * struct. See above.
+ */
+CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion);
+
+/*
+ * NAME curl_easy_strerror()
+ *
+ * DESCRIPTION
+ *
+ * The curl_easy_strerror function may be used to turn a CURLcode value
+ * into the equivalent human readable error string. This is useful
+ * for printing meaningful error messages.
+ */
+CURL_EXTERN const char *curl_easy_strerror(CURLcode);
+
+/*
+ * NAME curl_share_strerror()
+ *
+ * DESCRIPTION
+ *
+ * The curl_share_strerror function may be used to turn a CURLSHcode value
+ * into the equivalent human readable error string. This is useful
+ * for printing meaningful error messages.
+ */
+CURL_EXTERN const char *curl_share_strerror(CURLSHcode);
+
+/*
+ * NAME curl_easy_pause()
+ *
+ * DESCRIPTION
+ *
+ * The curl_easy_pause function pauses or unpauses transfers. Select the new
+ * state by setting the bitmask, use the convenience defines below.
+ *
+ */
+CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
+
+#define CURLPAUSE_RECV (1<<0)
+#define CURLPAUSE_RECV_CONT (0)
+
+#define CURLPAUSE_SEND (1<<2)
+#define CURLPAUSE_SEND_CONT (0)
+
+#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND)
+#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT)
+
+#ifdef __cplusplus
+}
+#endif
+
+/* unfortunately, the easy.h and multi.h include files need options and info
+ stuff before they can be included! */
+#include "easy.h" /* nothing in curl is fun without the easy stuff */
+#include "multi.h"
+
+/* the typechecker doesn't work in C++ (yet) */
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
+ ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \
+ !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK)
+#include "typecheck-gcc.h"
+#else
+#if defined(__STDC__) && (__STDC__ >= 1)
+/* This preprocessor magic that replaces a call with the exact same call is
+ only done to make sure application authors pass exactly three arguments
+ to these functions. */
+#define curl_easy_setopt(handle, opt, param) curl_easy_setopt(handle, opt, param)
+#define curl_easy_getinfo(handle, info, arg) curl_easy_getinfo(handle, info, arg)
+#define curl_share_setopt(share, opt, param) curl_share_setopt(share, opt, param)
+#define curl_multi_setopt(handle, opt, param) curl_multi_setopt(handle, opt, param)
+#endif /* __STDC__ >= 1 */
+#endif /* gcc >= 4.3 && !__cplusplus */
+
+#endif /* __CURL_CURL_H */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/curl/inc/curlbuild.h b/src/connectivity/gps/2.0/mtk_mnld/curl/inc/curlbuild.h
new file mode 100644
index 0000000..f09419a
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/curl/inc/curlbuild.h
@@ -0,0 +1,585 @@
+#ifndef __CURL_CURLBUILD_H
+#define __CURL_CURLBUILD_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */
+/* ================================================================ */
+
+/*
+ * NOTE 1:
+ * -------
+ *
+ * See file include/curl/curlbuild.h.in, run configure, and forget
+ * that this file exists it is only used for non-configure systems.
+ * But you can keep reading if you want ;-)
+ *
+ */
+
+/* ================================================================ */
+/* NOTES FOR NON-CONFIGURE SYSTEMS */
+/* ================================================================ */
+
+/*
+ * NOTE 1:
+ * -------
+ *
+ * Nothing in this file is intended to be modified or adjusted by the
+ * curl library user nor by the curl library builder.
+ *
+ * If you think that something actually needs to be changed, adjusted
+ * or fixed in this file, then, report it on the libcurl development
+ * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/
+ *
+ * Try to keep one section per platform, compiler and architecture,
+ * otherwise, if an existing section is reused for a different one and
+ * later on the original is adjusted, probably the piggybacking one can
+ * be adversely changed.
+ *
+ * In order to differentiate between platforms/compilers/architectures
+ * use only compiler built in predefined preprocessor symbols.
+ *
+ * This header file shall only export symbols which are 'curl' or 'CURL'
+ * prefixed, otherwise public name space would be polluted.
+ *
+ * NOTE 2:
+ * -------
+ *
+ * For any given platform/compiler curl_off_t must be typedef'ed to a
+ * 64-bit wide signed integral data type. The width of this data type
+ * must remain constant and independent of any possible large file
+ * support settings.
+ *
+ * As an exception to the above, curl_off_t shall be typedef'ed to a
+ * 32-bit wide signed integral data type if there is no 64-bit type.
+ *
+ * As a general rule, curl_off_t shall not be mapped to off_t. This
+ * rule shall only be violated if off_t is the only 64-bit data type
+ * available and the size of off_t is independent of large file support
+ * settings. Keep your build on the safe side avoiding an off_t gating.
+ * If you have a 64-bit off_t then take for sure that another 64-bit
+ * data type exists, dig deeper and you will find it.
+ *
+ * NOTE 3:
+ * -------
+ *
+ * Right now you might be staring at file include/curl/curlbuild.h.dist or
+ * at file include/curl/curlbuild.h, this is due to the following reason:
+ * file include/curl/curlbuild.h.dist is renamed to include/curl/curlbuild.h
+ * when the libcurl source code distribution archive file is created.
+ *
+ * File include/curl/curlbuild.h.dist is not included in the distribution
+ * archive. File include/curl/curlbuild.h is not present in the git tree.
+ *
+ * The distributed include/curl/curlbuild.h file is only intended to be used
+ * on systems which can not run the also distributed configure script.
+ *
+ * On systems capable of running the configure script, the configure process
+ * will overwrite the distributed include/curl/curlbuild.h file with one that
+ * is suitable and specific to the library being configured and built, which
+ * is generated from the include/curl/curlbuild.h.in template file.
+ *
+ * If you check out from git on a non-configure platform, you must run the
+ * appropriate buildconf* script to set up curlbuild.h and other local files.
+ *
+ */
+
+/* ================================================================ */
+/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */
+/* ================================================================ */
+
+#ifdef CURL_SIZEOF_LONG
+# error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
+#endif
+
+#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
+# error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
+#endif
+
+#ifdef CURL_SIZEOF_CURL_SOCKLEN_T
+# error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
+#endif
+
+#ifdef CURL_TYPEOF_CURL_OFF_T
+# error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_FORMAT_CURL_OFF_T
+# error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_FORMAT_CURL_OFF_TU
+# error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
+#endif
+
+#ifdef CURL_FORMAT_OFF_T
+# error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SIZEOF_CURL_OFF_T
+# error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SUFFIX_CURL_OFF_T
+# error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SUFFIX_CURL_OFF_TU
+# error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
+#endif
+
+/* ================================================================ */
+/* EXTERNAL INTERFACE SETTINGS FOR NON-CONFIGURE SYSTEMS ONLY */
+/* ================================================================ */
+
+#if defined(__DJGPP__) || defined(__GO32__)
+# if defined(__DJGPP__) && (__DJGPP__ > 1)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# else
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__SALFORDC__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__BORLANDC__)
+# if (__BORLANDC__ < 0x520)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# else
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_FORMAT_OFF_T "%I64d"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__TURBOC__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__WATCOMC__)
+# if defined(__386__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_FORMAT_OFF_T "%I64d"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# else
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__POCC__)
+# if (__POCC__ < 280)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# elif defined(_MSC_VER)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_FORMAT_OFF_T "%I64d"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# else
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__LCC__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__SYMBIAN32__)
+# if defined(__EABI__) /* Treat all ARM compilers equally */
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(__CW32__)
+# pragma longlong on
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(__VC32__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__MWERKS__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(_WIN32_WCE)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_FORMAT_OFF_T "%I64d"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__MINGW32__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_FORMAT_OFF_T "%I64d"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__VMS)
+# if defined(__VAX)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# else
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__OS400__)
+# if defined(__ILEC400__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+# endif
+
+#elif defined(__MVS__)
+# if defined(__IBMC__) || defined(__IBMCPP__)
+# if defined(_ILP32)
+# define CURL_SIZEOF_LONG 4
+# elif defined(_LP64)
+# define CURL_SIZEOF_LONG 8
+# endif
+# if defined(_LONG_LONG)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(_LP64)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+# endif
+
+#elif defined(__370__)
+# if defined(__IBMC__) || defined(__IBMCPP__)
+# if defined(_ILP32)
+# define CURL_SIZEOF_LONG 4
+# elif defined(_LP64)
+# define CURL_SIZEOF_LONG 8
+# endif
+# if defined(_LONG_LONG)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(_LP64)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+# endif
+
+#elif defined(TPF)
+# define CURL_SIZEOF_LONG 8
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+/* ===================================== */
+/* KEEP MSVC THE PENULTIMATE ENTRY */
+/* ===================================== */
+
+#elif defined(_MSC_VER)
+# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_FORMAT_OFF_T "%I64d"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# else
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+/* ===================================== */
+/* KEEP GENERIC GCC THE LAST ENTRY */
+/* ===================================== */
+
+#elif defined(__GNUC__)
+# if defined(__ILP32__) || \
+ defined(__i386__) || defined(__ppc__) || defined(__arm__) || defined(__sparc__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(__LP64__) || \
+ defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__)
+# define CURL_SIZEOF_LONG 8
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+
+#else
+# error "Unknown non-configure build target!"
+ Error Compilation_aborted_Unknown_non_configure_build_target
+#endif
+
+/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */
+/* sys/types.h is required here to properly make type definitions below. */
+#ifdef CURL_PULL_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */
+/* sys/socket.h is required here to properly make type definitions below. */
+#ifdef CURL_PULL_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+/* Data type definition of curl_socklen_t. */
+
+#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
+ typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
+#endif
+
+/* Data type definition of curl_off_t. */
+
+#ifdef CURL_TYPEOF_CURL_OFF_T
+ typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
+#endif
+
+#endif /* __CURL_CURLBUILD_H */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/curl/inc/curlrules.h b/src/connectivity/gps/2.0/mtk_mnld/curl/inc/curlrules.h
new file mode 100644
index 0000000..301ce6e
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/curl/inc/curlrules.h
@@ -0,0 +1,262 @@
+#ifndef __CURL_CURLRULES_H
+#define __CURL_CURLRULES_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* COMPILE TIME SANITY CHECKS */
+/* ================================================================ */
+
+/*
+ * NOTE 1:
+ * -------
+ *
+ * All checks done in this file are intentionally placed in a public
+ * header file which is pulled by curl/curl.h when an application is
+ * being built using an already built libcurl library. Additionally
+ * this file is also included and used when building the library.
+ *
+ * If compilation fails on this file it is certainly sure that the
+ * problem is elsewhere. It could be a problem in the curlbuild.h
+ * header file, or simply that you are using different compilation
+ * settings than those used to build the library.
+ *
+ * Nothing in this file is intended to be modified or adjusted by the
+ * curl library user nor by the curl library builder.
+ *
+ * Do not deactivate any check, these are done to make sure that the
+ * library is properly built and used.
+ *
+ * You can find further help on the libcurl development mailing list:
+ * http://cool.haxx.se/mailman/listinfo/curl-library/
+ *
+ * NOTE 2
+ * ------
+ *
+ * Some of the following compile time checks are based on the fact
+ * that the dimension of a constant array can not be a negative one.
+ * In this way if the compile time verification fails, the compilation
+ * will fail issuing an error. The error description wording is compiler
+ * dependent but it will be quite similar to one of the following:
+ *
+ * "negative subscript or subscript is too large"
+ * "array must have at least one element"
+ * "-1 is an illegal array size"
+ * "size of array is negative"
+ *
+ * If you are building an application which tries to use an already
+ * built libcurl library and you are getting this kind of errors on
+ * this file, it is a clear indication that there is a mismatch between
+ * how the library was built and how you are trying to use it for your
+ * application. Your already compiled or binary library provider is the
+ * only one who can give you the details you need to properly use it.
+ */
+
+/*
+ * Verify that some macros are actually defined.
+ */
+
+#ifndef CURL_SIZEOF_LONG
+# error "CURL_SIZEOF_LONG definition is missing!"
+ Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing
+#endif
+
+#ifndef CURL_TYPEOF_CURL_SOCKLEN_T
+# error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing
+#endif
+
+#ifndef CURL_SIZEOF_CURL_SOCKLEN_T
+# error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing
+#endif
+
+#ifndef CURL_TYPEOF_CURL_OFF_T
+# error "CURL_TYPEOF_CURL_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_FORMAT_CURL_OFF_T
+# error "CURL_FORMAT_CURL_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_FORMAT_CURL_OFF_TU
+# error "CURL_FORMAT_CURL_OFF_TU definition is missing!"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing
+#endif
+
+#ifndef CURL_FORMAT_OFF_T
+# error "CURL_FORMAT_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing
+#endif
+
+#ifndef CURL_SIZEOF_CURL_OFF_T
+# error "CURL_SIZEOF_CURL_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_SUFFIX_CURL_OFF_T
+# error "CURL_SUFFIX_CURL_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_SUFFIX_CURL_OFF_TU
+# error "CURL_SUFFIX_CURL_OFF_TU definition is missing!"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing
+#endif
+
+/*
+ * Macros private to this header file.
+ */
+
+#define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1
+
+#define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1
+
+/*
+ * Verify that the size previously defined and expected for long
+ * is the same as the one reported by sizeof() at compile time.
+ */
+
+typedef char
+ __curl_rule_01__
+ [CurlchkszEQ(long, CURL_SIZEOF_LONG)];
+
+/*
+ * Verify that the size previously defined and expected for
+ * curl_off_t is actually the the same as the one reported
+ * by sizeof() at compile time.
+ */
+
+typedef char
+ __curl_rule_02__
+ [CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)];
+
+/*
+ * Verify at compile time that the size of curl_off_t as reported
+ * by sizeof() is greater or equal than the one reported for long
+ * for the current compilation.
+ */
+
+typedef char
+ __curl_rule_03__
+ [CurlchkszGE(curl_off_t, long)];
+
+/*
+ * Verify that the size previously defined and expected for
+ * curl_socklen_t is actually the the same as the one reported
+ * by sizeof() at compile time.
+ */
+
+typedef char
+ __curl_rule_04__
+ [CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)];
+
+/*
+ * Verify at compile time that the size of curl_socklen_t as reported
+ * by sizeof() is greater or equal than the one reported for int for
+ * the current compilation.
+ */
+
+typedef char
+ __curl_rule_05__
+ [CurlchkszGE(curl_socklen_t, int)];
+
+/* ================================================================ */
+/* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */
+/* ================================================================ */
+
+/*
+ * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
+ * these to be visible and exported by the external libcurl interface API,
+ * while also making them visible to the library internals, simply including
+ * curl_setup.h, without actually needing to include curl.h internally.
+ * If some day this section would grow big enough, all this should be moved
+ * to its own header file.
+ */
+
+/*
+ * Figure out if we can use the ## preprocessor operator, which is supported
+ * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
+ * or __cplusplus so we need to carefully check for them too.
+ */
+
+#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
+ defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
+ defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
+ defined(__ILEC400__)
+ /* This compiler is believed to have an ISO compatible preprocessor */
+#define CURL_ISOCPP
+#else
+ /* This compiler is believed NOT to have an ISO compatible preprocessor */
+#undef CURL_ISOCPP
+#endif
+
+/*
+ * Macros for minimum-width signed and unsigned curl_off_t integer constants.
+ */
+
+#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
+# define __CURL_OFF_T_C_HLPR2(x) x
+# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x)
+# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
+ __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
+# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
+ __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
+#else
+# ifdef CURL_ISOCPP
+# define __CURL_OFF_T_C_HLPR2(Val, Suffix) Val ## Suffix
+# else
+# define __CURL_OFF_T_C_HLPR2(Val, Suffix) Val/**/Suffix
+# endif
+# define __CURL_OFF_T_C_HLPR1(Val, Suffix) __CURL_OFF_T_C_HLPR2(Val, Suffix)
+# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val, CURL_SUFFIX_CURL_OFF_T)
+# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val, CURL_SUFFIX_CURL_OFF_TU)
+#endif
+
+/*
+ * Get rid of macros private to this header file.
+ */
+
+#undef CurlchkszEQ
+#undef CurlchkszGE
+
+/*
+ * Get rid of macros not intended to exist beyond this point.
+ */
+
+#undef CURL_PULL_WS2TCPIP_H
+#undef CURL_PULL_SYS_TYPES_H
+#undef CURL_PULL_SYS_SOCKET_H
+#undef CURL_PULL_SYS_POLL_H
+#undef CURL_PULL_STDINT_H
+#undef CURL_PULL_INTTYPES_H
+
+#undef CURL_TYPEOF_CURL_SOCKLEN_T
+#undef CURL_TYPEOF_CURL_OFF_T
+
+#ifdef CURL_NO_OLDIES
+#undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */
+#endif
+
+#endif /* __CURL_CURLRULES_H */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/curl/inc/curlver.h b/src/connectivity/gps/2.0/mtk_mnld/curl/inc/curlver.h
new file mode 100644
index 0000000..7976c1f
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/curl/inc/curlver.h
@@ -0,0 +1,69 @@
+#ifndef __CURL_CURLVER_H
+#define __CURL_CURLVER_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* This header file contains nothing but libcurl version info, generated by
+ a script at release-time. This was made its own header file in 7.11.2 */
+
+/* This is the global package copyright */
+#define LIBCURL_COPYRIGHT "1996 - 2015 Daniel Stenberg, <daniel@haxx.se>."
+
+/* This is the version number of the libcurl package from which this header
+ file origins: */
+#define LIBCURL_VERSION "7.42.1"
+
+/* The numeric version number is also available "in parts" by using these
+ defines: */
+#define LIBCURL_VERSION_MAJOR 7
+#define LIBCURL_VERSION_MINOR 42
+#define LIBCURL_VERSION_PATCH 1
+
+/* This is the numeric version of the libcurl version number, meant for easier
+ parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
+ always follow this syntax:
+
+ 0xXXYYZZ
+
+ Where XX, YY and ZZ are the main version, release and patch numbers in
+ hexadecimal (using 8 bits each). All three numbers are always represented
+ using two digits. 1.2 would appear as "0x010200" while version 9.11.7
+ appears as "0x090b07".
+
+ This 6-digit (24 bits) hexadecimal number does not show pre-release number,
+ and it is always a greater number in a more recent release. It makes
+ comparisons with greater than and less than work.
+*/
+#define LIBCURL_VERSION_NUM 0x072a01
+
+/*
+ * This is the date and time when the full source package was created. The
+ * timestamp is not stored in git, as the timestamp is properly set in the
+ * tarballs by the maketgz script.
+ *
+ * The format of the date should follow this template:
+ *
+ * "Mon Feb 12 11:35:33 UTC 2007"
+ */
+#define LIBCURL_TIMESTAMP "Wed Apr 29 06:07:13 UTC 2015"
+
+#endif /* __CURL_CURLVER_H */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/curl/inc/easy.h b/src/connectivity/gps/2.0/mtk_mnld/curl/inc/easy.h
new file mode 100644
index 0000000..c1e3e76
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/curl/inc/easy.h
@@ -0,0 +1,102 @@
+#ifndef __CURL_EASY_H
+#define __CURL_EASY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CURL_EXTERN CURL *curl_easy_init(void);
+CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
+CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
+CURL_EXTERN void curl_easy_cleanup(CURL *curl);
+
+/*
+ * NAME curl_easy_getinfo()
+ *
+ * DESCRIPTION
+ *
+ * Request internal information from the curl session with this function. The
+ * third argument MUST be a pointer to a long, a pointer to a char * or a
+ * pointer to a double (as the documentation describes elsewhere). The data
+ * pointed to will be filled in accordingly and can be relied upon only if the
+ * function returns CURLE_OK. This function is intended to get used *AFTER* a
+ * performed transfer, all results from this function are undefined until the
+ * transfer is completed.
+ */
+CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
+
+
+/*
+ * NAME curl_easy_duphandle()
+ *
+ * DESCRIPTION
+ *
+ * Creates a new curl session handle with the same options set for the handle
+ * passed in. Duplicating a handle could only be a matter of cloning data and
+ * options, internal state info and things like persistent connections cannot
+ * be transferred. It is useful in multithreaded applications when you can run
+ * curl_easy_duphandle() for each new thread to avoid a series of identical
+ * curl_easy_setopt() invokes in every thread.
+ */
+CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl);
+
+/*
+ * NAME curl_easy_reset()
+ *
+ * DESCRIPTION
+ *
+ * Re-initializes a CURL handle to the default values. This puts back the
+ * handle to the same state as it was in when it was just created.
+ *
+ * It does keep: live connections, the Session ID cache, the DNS cache and the
+ * cookies.
+ */
+CURL_EXTERN void curl_easy_reset(CURL *curl);
+
+/*
+ * NAME curl_easy_recv()
+ *
+ * DESCRIPTION
+ *
+ * Receives data from the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
+ size_t *n);
+
+/*
+ * NAME curl_easy_send()
+ *
+ * DESCRIPTION
+ *
+ * Sends data over the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
+ size_t buflen, size_t *n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/curl/inc/multi.h b/src/connectivity/gps/2.0/mtk_mnld/curl/inc/multi.h
new file mode 100644
index 0000000..42306a9
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/curl/inc/multi.h
@@ -0,0 +1,399 @@
+#ifndef __CURL_MULTI_H
+#define __CURL_MULTI_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/*
+ This is an "external" header file. Don't give away any internals here!
+
+ GOALS
+
+ o Enable a "pull" interface. The application that uses libcurl decides where
+ and when to ask libcurl to get/send data.
+
+ o Enable multiple simultaneous transfers in the same thread without making it
+ complicated for the application.
+
+ o Enable the application to select() on its own file descriptors and curl's
+ file descriptors simultaneous easily.
+
+*/
+
+/*
+ * This header file should not really need to include "curl.h" since curl.h
+ * itself includes this file and we expect user applications to do #include
+ * <curl/curl.h> without the need for especially including multi.h.
+ *
+ * For some reason we added this include here at one point, and rather than to
+ * break existing (wrongly written) libcurl applications, we leave it as-is
+ * but with this warning attached.
+ */
+#include "curl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void CURLM;
+
+typedef enum {
+ CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
+ curl_multi_socket*() soon */
+ CURLM_OK,
+ CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
+ CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
+ CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
+ CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
+ CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
+ CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
+ CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
+ attempted to get added - again */
+ CURLM_LAST
+} CURLMcode;
+
+/* just to make code nicer when using curl_multi_socket() you can now check
+ for CURLM_CALL_MULTI_SOCKET too in the same style it works for
+ curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
+#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
+
+typedef enum {
+ CURLMSG_NONE, /* first, not used */
+ CURLMSG_DONE, /* This easy handle has completed. 'result' contains
+ the CURLcode of the transfer */
+ CURLMSG_LAST /* last, not used */
+} CURLMSG;
+
+struct CURLMsg {
+ CURLMSG msg; /* what this message means */
+ CURL *easy_handle; /* the handle it concerns */
+ union {
+ void *whatever; /* message-specific data */
+ CURLcode result; /* return code for transfer */
+ } data;
+};
+typedef struct CURLMsg CURLMsg;
+
+/* Based on poll(2) structure and values.
+ * We don't use pollfd and POLL* constants explicitly
+ * to cover platforms without poll(). */
+#define CURL_WAIT_POLLIN 0x0001
+#define CURL_WAIT_POLLPRI 0x0002
+#define CURL_WAIT_POLLOUT 0x0004
+
+struct curl_waitfd {
+ curl_socket_t fd;
+ short events;
+ short revents; /* not supported yet */
+};
+
+/*
+ * Name: curl_multi_init()
+ *
+ * Desc: inititalize multi-style curl usage
+ *
+ * Returns: a new CURLM handle to use in all 'curl_multi' functions.
+ */
+CURL_EXTERN CURLM *curl_multi_init(void);
+
+/*
+ * Name: curl_multi_add_handle()
+ *
+ * Desc: add a standard curl handle to the multi stack
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
+ CURL *curl_handle);
+
+ /*
+ * Name: curl_multi_remove_handle()
+ *
+ * Desc: removes a curl handle from the multi stack again
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
+ CURL *curl_handle);
+
+ /*
+ * Name: curl_multi_fdset()
+ *
+ * Desc: Ask curl for its fd_set sets. The app can use these to select() or
+ * poll() on. We want curl_multi_perform() called as soon as one of
+ * them are ready.
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
+ fd_set *read_fd_set,
+ fd_set *write_fd_set,
+ fd_set *exc_fd_set,
+ int *max_fd);
+
+/*
+ * Name: curl_multi_wait()
+ *
+ * Desc: Poll on all fds within a CURLM set as well as any
+ * additional fds passed to the function.
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
+ struct curl_waitfd extra_fds[],
+ unsigned int extra_nfds,
+ int timeout_ms,
+ int *ret);
+
+ /*
+ * Name: curl_multi_perform()
+ *
+ * Desc: When the app thinks there's data available for curl it calls this
+ * function to read/write whatever there is right now. This returns
+ * as soon as the reads and writes are done. This function does not
+ * require that there actually is data available for reading or that
+ * data can be written, it can be called just in case. It returns
+ * the number of handles that still transfer data in the second
+ * argument's integer-pointer.
+ *
+ * Returns: CURLMcode type, general multi error code. *NOTE* that this only
+ * returns errors etc regarding the whole multi stack. There might
+ * still have occurred problems on invidual transfers even when this
+ * returns OK.
+ */
+CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
+ int *running_handles);
+
+ /*
+ * Name: curl_multi_cleanup()
+ *
+ * Desc: Cleans up and removes a whole multi stack. It does not free or
+ * touch any individual easy handles in any way. We need to define
+ * in what state those handles will be if this function is called
+ * in the middle of a transfer.
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
+
+/*
+ * Name: curl_multi_info_read()
+ *
+ * Desc: Ask the multi handle if there's any messages/informationals from
+ * the individual transfers. Messages include informationals such as
+ * error code from the transfer or just the fact that a transfer is
+ * completed. More details on these should be written down as well.
+ *
+ * Repeated calls to this function will return a new struct each
+ * time, until a special "end of msgs" struct is returned as a signal
+ * that there is no more to get at this point.
+ *
+ * The data the returned pointer points to will not survive calling
+ * curl_multi_cleanup().
+ *
+ * The 'CURLMsg' struct is meant to be very simple and only contain
+ * very basic informations. If more involved information is wanted,
+ * we will provide the particular "transfer handle" in that struct
+ * and that should/could/would be used in subsequent
+ * curl_easy_getinfo() calls (or similar). The point being that we
+ * must never expose complex structs to applications, as then we'll
+ * undoubtably get backwards compatibility problems in the future.
+ *
+ * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
+ * of structs. It also writes the number of messages left in the
+ * queue (after this read) in the integer the second argument points
+ * to.
+ */
+CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
+ int *msgs_in_queue);
+
+/*
+ * Name: curl_multi_strerror()
+ *
+ * Desc: The curl_multi_strerror function may be used to turn a CURLMcode
+ * value into the equivalent human readable error string. This is
+ * useful for printing meaningful error messages.
+ *
+ * Returns: A pointer to a zero-terminated error message.
+ */
+CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
+
+/*
+ * Name: curl_multi_socket() and
+ * curl_multi_socket_all()
+ *
+ * Desc: An alternative version of curl_multi_perform() that allows the
+ * application to pass in one of the file descriptors that have been
+ * detected to have "action" on them and let libcurl perform.
+ * See man page for details.
+ */
+#define CURL_POLL_NONE 0
+#define CURL_POLL_IN 1
+#define CURL_POLL_OUT 2
+#define CURL_POLL_INOUT 3
+#define CURL_POLL_REMOVE 4
+
+#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
+
+#define CURL_CSELECT_IN 0x01
+#define CURL_CSELECT_OUT 0x02
+#define CURL_CSELECT_ERR 0x04
+
+typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
+ curl_socket_t s, /* socket */
+ int what, /* see above */
+ void *userp, /* private callback
+ pointer */
+ void *socketp); /* private socket
+ pointer */
+/*
+ * Name: curl_multi_timer_callback
+ *
+ * Desc: Called by libcurl whenever the library detects a change in the
+ * maximum number of milliseconds the app is allowed to wait before
+ * curl_multi_socket() or curl_multi_perform() must be called
+ * (to allow libcurl's timed events to take place).
+ *
+ * Returns: The callback should return zero.
+ */
+typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
+ long timeout_ms, /* see above */
+ void *userp); /* private callback
+ pointer */
+
+CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
+ int *running_handles);
+
+CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
+ curl_socket_t s,
+ int ev_bitmask,
+ int *running_handles);
+
+CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
+ int *running_handles);
+
+#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
+/* This macro below was added in 7.16.3 to push users who recompile to use
+ the new curl_multi_socket_action() instead of the old curl_multi_socket()
+*/
+#define curl_multi_socket(x, y, z) curl_multi_socket_action(x, y, 0, z)
+#endif
+
+/*
+ * Name: curl_multi_timeout()
+ *
+ * Desc: Returns the maximum number of milliseconds the app is allowed to
+ * wait before curl_multi_socket() or curl_multi_perform() must be
+ * called (to allow libcurl's timed events to take place).
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
+ long *milliseconds);
+
+#undef CINIT /* re-using the same name as in curl.h */
+
+#ifdef CURL_ISOCPP
+#define CINIT(name, type, num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define LONG CURLOPTTYPE_LONG
+#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
+#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+#define OFF_T CURLOPTTYPE_OFF_T
+#define CINIT(name, type, number) CURLMOPT_/**/name = type + number
+#endif
+
+typedef enum {
+ /* This is the socket callback function pointer */
+ CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
+
+ /* This is the argument passed to the socket callback */
+ CINIT(SOCKETDATA, OBJECTPOINT, 2),
+
+ /* set to 1 to enable pipelining for this multi handle */
+ CINIT(PIPELINING, LONG, 3),
+
+ /* This is the timer callback function pointer */
+ CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
+
+ /* This is the argument passed to the timer callback */
+ CINIT(TIMERDATA, OBJECTPOINT, 5),
+
+ /* maximum number of entries in the connection cache */
+ CINIT(MAXCONNECTS, LONG, 6),
+
+ /* maximum number of (pipelining) connections to one host */
+ CINIT(MAX_HOST_CONNECTIONS, LONG, 7),
+
+ /* maximum number of requests in a pipeline */
+ CINIT(MAX_PIPELINE_LENGTH, LONG, 8),
+
+ /* a connection with a content-length longer than this
+ will not be considered for pipelining */
+ CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9),
+
+ /* a connection with a chunk length longer than this
+ will not be considered for pipelining */
+ CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10),
+
+ /* a list of site names(+port) that are blacklisted from
+ pipelining */
+ CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11),
+
+ /* a list of server types that are blacklisted from
+ pipelining */
+ CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12),
+
+ /* maximum number of open connections in total */
+ CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13),
+
+ CURLMOPT_LASTENTRY /* the last unused */
+} CURLMoption;
+
+
+/*
+ * Name: curl_multi_setopt()
+ *
+ * Desc: Sets options for the multi handle.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
+ CURLMoption option, ...);
+
+
+/*
+ * Name: curl_multi_assign()
+ *
+ * Desc: This function sets an association in the multi handle between the
+ * given socket and a private pointer of the application. This is
+ * (only) useful for curl_multi_socket uses.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
+ curl_socket_t sockfd, void *sockp);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/curl/inc/typecheck-gcc.h b/src/connectivity/gps/2.0/mtk_mnld/curl/inc/typecheck-gcc.h
new file mode 100644
index 0000000..0e3d6c9
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/curl/inc/typecheck-gcc.h
@@ -0,0 +1,610 @@
+#ifndef __CURL_TYPECHECK_GCC_H
+#define __CURL_TYPECHECK_GCC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* wraps curl_easy_setopt() with typechecking */
+
+/* To add a new kind of warning, add an
+ * if (_curl_is_sometype_option(_curl_opt))
+ * if (!_curl_is_sometype(value))
+ * _curl_easy_setopt_err_sometype();
+ * block and define _curl_is_sometype_option, _curl_is_sometype and
+ * _curl_easy_setopt_err_sometype below
+ *
+ * NOTE: We use two nested 'if' statements here instead of the && operator, in
+ * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x
+ * when compiling with -Wlogical-op.
+ *
+ * To add an option that uses the same type as an existing option, you'll just
+ * need to extend the appropriate _curl_*_option macro
+ */
+#define curl_easy_setopt(handle, option, value) \
+__extension__({ \
+ __typeof__(option) _curl_opt = option; \
+ if (__builtin_constant_p(_curl_opt)) { \
+ if (_curl_is_long_option(_curl_opt)) \
+ if (!_curl_is_long(value)) \
+ _curl_easy_setopt_err_long(); \
+ if (_curl_is_off_t_option(_curl_opt)) \
+ if (!_curl_is_off_t(value)) \
+ _curl_easy_setopt_err_curl_off_t(); \
+ if (_curl_is_string_option(_curl_opt)) \
+ if (!_curl_is_string(value)) \
+ _curl_easy_setopt_err_string(); \
+ if (_curl_is_write_cb_option(_curl_opt)) \
+ if (!_curl_is_write_cb(value)) \
+ _curl_easy_setopt_err_write_callback(); \
+ if ((_curl_opt) == CURLOPT_READFUNCTION) \
+ if (!_curl_is_read_cb(value)) \
+ _curl_easy_setopt_err_read_cb(); \
+ if ((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
+ if (!_curl_is_ioctl_cb(value)) \
+ _curl_easy_setopt_err_ioctl_cb(); \
+ if ((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
+ if (!_curl_is_sockopt_cb(value)) \
+ _curl_easy_setopt_err_sockopt_cb(); \
+ if ((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
+ if (!_curl_is_opensocket_cb(value)) \
+ _curl_easy_setopt_err_opensocket_cb(); \
+ if ((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
+ if (!_curl_is_progress_cb(value)) \
+ _curl_easy_setopt_err_progress_cb(); \
+ if ((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
+ if (!_curl_is_debug_cb(value)) \
+ _curl_easy_setopt_err_debug_cb(); \
+ if ((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
+ if (!_curl_is_ssl_ctx_cb(value)) \
+ _curl_easy_setopt_err_ssl_ctx_cb(); \
+ if (_curl_is_conv_cb_option(_curl_opt)) \
+ if (!_curl_is_conv_cb(value)) \
+ _curl_easy_setopt_err_conv_cb(); \
+ if ((_curl_opt) == CURLOPT_SEEKFUNCTION) \
+ if (!_curl_is_seek_cb(value)) \
+ _curl_easy_setopt_err_seek_cb(); \
+ if (_curl_is_cb_data_option(_curl_opt)) \
+ if (!_curl_is_cb_data(value)) \
+ _curl_easy_setopt_err_cb_data(); \
+ if ((_curl_opt) == CURLOPT_ERRORBUFFER) \
+ if (!_curl_is_error_buffer(value)) \
+ _curl_easy_setopt_err_error_buffer(); \
+ if ((_curl_opt) == CURLOPT_STDERR) \
+ if (!_curl_is_FILE(value)) \
+ _curl_easy_setopt_err_FILE(); \
+ if (_curl_is_postfields_option(_curl_opt)) \
+ if (!_curl_is_postfields(value)) \
+ _curl_easy_setopt_err_postfields(); \
+ if ((_curl_opt) == CURLOPT_HTTPPOST) \
+ if (!_curl_is_arr((value), struct curl_httppost)) \
+ _curl_easy_setopt_err_curl_httpost(); \
+ if (_curl_is_slist_option(_curl_opt)) \
+ if (!_curl_is_arr((value), struct curl_slist)) \
+ _curl_easy_setopt_err_curl_slist(); \
+ if ((_curl_opt) == CURLOPT_SHARE) \
+ if (!_curl_is_ptr((value), CURLSH)) \
+ _curl_easy_setopt_err_CURLSH(); \
+ } \
+ curl_easy_setopt(handle, _curl_opt, value); \
+})
+
+/* wraps curl_easy_getinfo() with typechecking */
+/* FIXME: don't allow const pointers */
+#define curl_easy_getinfo(handle, info, arg) \
+__extension__({ \
+ __typeof__(info) _curl_info = info; \
+ if (__builtin_constant_p(_curl_info)) { \
+ if (_curl_is_string_info(_curl_info)) \
+ if (!_curl_is_arr((arg), char *)) \
+ _curl_easy_getinfo_err_string(); \
+ if (_curl_is_long_info(_curl_info)) \
+ if (!_curl_is_arr((arg), long)) \
+ _curl_easy_getinfo_err_long(); \
+ if (_curl_is_double_info(_curl_info)) \
+ if (!_curl_is_arr((arg), double)) \
+ _curl_easy_getinfo_err_double(); \
+ if (_curl_is_slist_info(_curl_info)) \
+ if (!_curl_is_arr((arg), struct curl_slist *)) \
+ _curl_easy_getinfo_err_curl_slist(); \
+ } \
+ curl_easy_getinfo(handle, _curl_info, arg); \
+})
+
+/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
+ * for now just make sure that the functions are called with three
+ * arguments
+ */
+#define curl_share_setopt(share, opt, param) curl_share_setopt(share, opt, param)
+#define curl_multi_setopt(handle, opt, param) curl_multi_setopt(handle, opt, param)
+
+
+/* the actual warnings, triggered by calling the _curl_easy_setopt_err*
+ * functions */
+
+/* To define a new warning, use _CURL_WARNING(identifier, "message") */
+#define _CURL_WARNING(id, message) \
+ static void __attribute__((__warning__(message))) \
+ __attribute__((__unused__)) __attribute__((__noinline__)) \
+ id(void) { __asm__(""); }
+
+_CURL_WARNING(_curl_easy_setopt_err_long,
+ "curl_easy_setopt expects a long argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
+ "curl_easy_setopt expects a curl_off_t argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_string,
+ "curl_easy_setopt expects a "
+ "string (char* or char[]) argument for this option"
+ )
+_CURL_WARNING(_curl_easy_setopt_err_write_callback,
+ "curl_easy_setopt expects a curl_write_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_read_cb,
+ "curl_easy_setopt expects a curl_read_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
+ "curl_easy_setopt expects a curl_ioctl_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb,
+ "curl_easy_setopt expects a curl_sockopt_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb,
+ "curl_easy_setopt expects a "
+ "curl_opensocket_callback argument for this option"
+ )
+_CURL_WARNING(_curl_easy_setopt_err_progress_cb,
+ "curl_easy_setopt expects a curl_progress_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_debug_cb,
+ "curl_easy_setopt expects a curl_debug_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb,
+ "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_conv_cb,
+ "curl_easy_setopt expects a curl_conv_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_seek_cb,
+ "curl_easy_setopt expects a curl_seek_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_cb_data,
+ "curl_easy_setopt expects a "
+ "private data pointer as argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_error_buffer,
+ "curl_easy_setopt expects a "
+ "char buffer of CURL_ERROR_SIZE as argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_FILE,
+ "curl_easy_setopt expects a FILE* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_postfields,
+ "curl_easy_setopt expects a void* or char* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
+ "curl_easy_setopt expects a struct curl_httppost* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
+ "curl_easy_setopt expects a struct curl_slist* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
+ "curl_easy_setopt expects a CURLSH* argument for this option")
+
+_CURL_WARNING(_curl_easy_getinfo_err_string,
+ "curl_easy_getinfo expects a pointer to char * for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_long,
+ "curl_easy_getinfo expects a pointer to long for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_double,
+ "curl_easy_getinfo expects a pointer to double for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
+ "curl_easy_getinfo expects a pointer to struct curl_slist * for this info")
+
+/* groups of curl_easy_setops options that take the same type of argument */
+
+/* To add a new option to one of the groups, just add
+ * (option) == CURLOPT_SOMETHING
+ * to the or-expression. If the option takes a long or curl_off_t, you don't
+ * have to do anything
+ */
+
+/* evaluates to true if option takes a long argument */
+#define _curl_is_long_option(option) \
+ (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
+
+#define _curl_is_off_t_option(option) \
+ ((option) > CURLOPTTYPE_OFF_T)
+
+/* evaluates to true if option takes a char* argument */
+#define _curl_is_string_option(option) \
+ ((option) == CURLOPT_URL || \
+ (option) == CURLOPT_PROXY || \
+ (option) == CURLOPT_INTERFACE || \
+ (option) == CURLOPT_NETRC_FILE || \
+ (option) == CURLOPT_USERPWD || \
+ (option) == CURLOPT_USERNAME || \
+ (option) == CURLOPT_PASSWORD || \
+ (option) == CURLOPT_PROXYUSERPWD || \
+ (option) == CURLOPT_PROXYUSERNAME || \
+ (option) == CURLOPT_PROXYPASSWORD || \
+ (option) == CURLOPT_NOPROXY || \
+ (option) == CURLOPT_ACCEPT_ENCODING || \
+ (option) == CURLOPT_REFERER || \
+ (option) == CURLOPT_USERAGENT || \
+ (option) == CURLOPT_COOKIE || \
+ (option) == CURLOPT_COOKIEFILE || \
+ (option) == CURLOPT_COOKIEJAR || \
+ (option) == CURLOPT_COOKIELIST || \
+ (option) == CURLOPT_FTPPORT || \
+ (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
+ (option) == CURLOPT_FTP_ACCOUNT || \
+ (option) == CURLOPT_RANGE || \
+ (option) == CURLOPT_CUSTOMREQUEST || \
+ (option) == CURLOPT_SSLCERT || \
+ (option) == CURLOPT_SSLCERTTYPE || \
+ (option) == CURLOPT_SSLKEY || \
+ (option) == CURLOPT_SSLKEYTYPE || \
+ (option) == CURLOPT_KEYPASSWD || \
+ (option) == CURLOPT_SSLENGINE || \
+ (option) == CURLOPT_CAINFO || \
+ (option) == CURLOPT_CAPATH || \
+ (option) == CURLOPT_RANDOM_FILE || \
+ (option) == CURLOPT_EGDSOCKET || \
+ (option) == CURLOPT_SSL_CIPHER_LIST || \
+ (option) == CURLOPT_KRBLEVEL || \
+ (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
+ (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \
+ (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \
+ (option) == CURLOPT_CRLFILE || \
+ (option) == CURLOPT_ISSUERCERT || \
+ (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
+ (option) == CURLOPT_SSH_KNOWNHOSTS || \
+ (option) == CURLOPT_MAIL_FROM || \
+ (option) == CURLOPT_RTSP_SESSION_ID || \
+ (option) == CURLOPT_RTSP_STREAM_URI || \
+ (option) == CURLOPT_RTSP_TRANSPORT || \
+ (option) == CURLOPT_XOAUTH2_BEARER || \
+ (option) == CURLOPT_DNS_SERVERS || \
+ (option) == CURLOPT_DNS_INTERFACE || \
+ (option) == CURLOPT_DNS_LOCAL_IP4 || \
+ (option) == CURLOPT_DNS_LOCAL_IP6 || \
+ (option) == CURLOPT_LOGIN_OPTIONS || \
+ 0)
+
+/* evaluates to true if option takes a curl_write_callback argument */
+#define _curl_is_write_cb_option(option) \
+ ((option) == CURLOPT_HEADERFUNCTION || \
+ (option) == CURLOPT_WRITEFUNCTION)
+
+/* evaluates to true if option takes a curl_conv_callback argument */
+#define _curl_is_conv_cb_option(option) \
+ ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
+ (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
+ (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
+
+/* evaluates to true if option takes a data argument to pass to a callback */
+#define _curl_is_cb_data_option(option) \
+ ((option) == CURLOPT_WRITEDATA || \
+ (option) == CURLOPT_READDATA || \
+ (option) == CURLOPT_IOCTLDATA || \
+ (option) == CURLOPT_SOCKOPTDATA || \
+ (option) == CURLOPT_OPENSOCKETDATA || \
+ (option) == CURLOPT_PROGRESSDATA || \
+ (option) == CURLOPT_HEADERDATA || \
+ (option) == CURLOPT_DEBUGDATA || \
+ (option) == CURLOPT_SSL_CTX_DATA || \
+ (option) == CURLOPT_SEEKDATA || \
+ (option) == CURLOPT_PRIVATE || \
+ (option) == CURLOPT_SSH_KEYDATA || \
+ (option) == CURLOPT_INTERLEAVEDATA || \
+ (option) == CURLOPT_CHUNK_DATA || \
+ (option) == CURLOPT_FNMATCH_DATA || \
+ 0)
+
+/* evaluates to true if option takes a POST data argument (void* or char*) */
+#define _curl_is_postfields_option(option) \
+ ((option) == CURLOPT_POSTFIELDS || \
+ (option) == CURLOPT_COPYPOSTFIELDS || \
+ 0)
+
+/* evaluates to true if option takes a struct curl_slist * argument */
+#define _curl_is_slist_option(option) \
+ ((option) == CURLOPT_HTTPHEADER || \
+ (option) == CURLOPT_HTTP200ALIASES || \
+ (option) == CURLOPT_QUOTE || \
+ (option) == CURLOPT_POSTQUOTE || \
+ (option) == CURLOPT_PREQUOTE || \
+ (option) == CURLOPT_TELNETOPTIONS || \
+ (option) == CURLOPT_MAIL_RCPT || \
+ 0)
+
+/* groups of curl_easy_getinfo infos that take the same type of argument */
+
+/* evaluates to true if info expects a pointer to char * argument */
+#define _curl_is_string_info(info) \
+ (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
+
+/* evaluates to true if info expects a pointer to long argument */
+#define _curl_is_long_info(info) \
+ (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
+
+/* evaluates to true if info expects a pointer to double argument */
+#define _curl_is_double_info(info) \
+ (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
+
+/* true if info expects a pointer to struct curl_slist * argument */
+#define _curl_is_slist_info(info) \
+ (CURLINFO_SLIST < (info))
+
+
+/* typecheck helpers -- check whether given expression has requested type*/
+
+/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
+ * otherwise define a new macro. Search for __builtin_types_compatible_p
+ * in the GCC manual.
+ * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
+ * the actual expression passed to the curl_easy_setopt macro. This
+ * means that you can only apply the sizeof and __typeof__ operators, no
+ * == or whatsoever.
+ */
+
+/* XXX: should evaluate to true iff expr is a pointer */
+#define _curl_is_any_ptr(expr) \
+ (sizeof(expr) == sizeof(void*))
+
+/* evaluates to true if expr is NULL */
+/* XXX: must not evaluate expr, so this check is not accurate */
+#define _curl_is_NULL(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
+
+/* evaluates to true if expr is type*, const type* or NULL */
+#define _curl_is_ptr(expr, type) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), type *) || \
+ __builtin_types_compatible_p(__typeof__(expr), const type *))
+
+/* evaluates to true if expr is one of type[], type*, NULL or const type* */
+#define _curl_is_arr(expr, type) \
+ (_curl_is_ptr((expr), type) || \
+ __builtin_types_compatible_p(__typeof__(expr), type[]))
+
+/* evaluates to true if expr is a string */
+#define _curl_is_string(expr) \
+ (_curl_is_arr((expr), char) || \
+ _curl_is_arr((expr), signed char) || \
+ _curl_is_arr((expr), unsigned char))
+
+/* evaluates to true if expr is a long (no matter the signedness)
+ * XXX: for now, int is also accepted (and therefore short and char, which
+ * are promoted to int when passed to a variadic function) */
+#define _curl_is_long(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), long) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed long) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \
+ __builtin_types_compatible_p(__typeof__(expr), int) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed int) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \
+ __builtin_types_compatible_p(__typeof__(expr), short) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed short) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \
+ __builtin_types_compatible_p(__typeof__(expr), char) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed char) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned char))
+
+/* evaluates to true if expr is of type curl_off_t */
+#define _curl_is_off_t(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
+
+/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
+/* XXX: also check size of an char[] array? */
+#define _curl_is_error_buffer(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), char *) || \
+ __builtin_types_compatible_p(__typeof__(expr), char[]))
+
+/* evaluates to true if expr is of type (const) void* or (const) FILE* */
+#if 0
+#define _curl_is_cb_data(expr) \
+ (_curl_is_ptr((expr), void) || \
+ _curl_is_ptr((expr), FILE))
+#else /* be less strict */
+#define _curl_is_cb_data(expr) \
+ _curl_is_any_ptr(expr)
+#endif
+
+/* evaluates to true if expr is of type FILE* */
+#define _curl_is_FILE(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), FILE *))
+
+/* evaluates to true if expr can be passed as POST data (void* or char*) */
+#define _curl_is_postfields(expr) \
+ (_curl_is_ptr((expr), void) || \
+ _curl_is_arr((expr), char))
+
+/* FIXME: the whole callback checking is messy...
+ * The idea is to tolerate char vs. void and const vs. not const
+ * pointers in arguments at least
+ */
+/* helper: __builtin_types_compatible_p distinguishes between functions and
+ * function pointers, hide it */
+#define _curl_callback_compatible(func, type) \
+ (__builtin_types_compatible_p(__typeof__(func), type) || \
+ __builtin_types_compatible_p(__typeof__(func), type*))
+
+/* evaluates to true if expr is of type curl_read_callback or "similar" */
+#define _curl_is_read_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) || \
+ _curl_callback_compatible((expr), _curl_read_callback1) || \
+ _curl_callback_compatible((expr), _curl_read_callback2) || \
+ _curl_callback_compatible((expr), _curl_read_callback3) || \
+ _curl_callback_compatible((expr), _curl_read_callback4) || \
+ _curl_callback_compatible((expr), _curl_read_callback5) || \
+ _curl_callback_compatible((expr), _curl_read_callback6))
+typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*);
+typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*);
+typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*);
+typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*);
+typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*);
+typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*);
+
+/* evaluates to true if expr is of type curl_write_callback or "similar" */
+#define _curl_is_write_cb(expr) \
+ (_curl_is_read_cb(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) || \
+ _curl_callback_compatible((expr), _curl_write_callback1) || \
+ _curl_callback_compatible((expr), _curl_write_callback2) || \
+ _curl_callback_compatible((expr), _curl_write_callback3) || \
+ _curl_callback_compatible((expr), _curl_write_callback4) || \
+ _curl_callback_compatible((expr), _curl_write_callback5) || \
+ _curl_callback_compatible((expr), _curl_write_callback6))
+typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*);
+typedef size_t (_curl_write_callback2)(const char *, size_t, size_t,
+ const void*);
+typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*);
+typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*);
+typedef size_t (_curl_write_callback5)(const void *, size_t, size_t,
+ const void*);
+typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*);
+
+/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
+#define _curl_is_ioctl_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback1) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback2) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback3) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback4))
+typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*);
+typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*);
+typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*);
+typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*);
+
+/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
+#define _curl_is_sockopt_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) || \
+ _curl_callback_compatible((expr), _curl_sockopt_callback1) || \
+ _curl_callback_compatible((expr), _curl_sockopt_callback2))
+typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
+typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t,
+ curlsocktype);
+
+/* evaluates to true if expr is of type curl_opensocket_callback or
+ "similar" */
+#define _curl_is_opensocket_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\
+ _curl_callback_compatible((expr), _curl_opensocket_callback1) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback2) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback3) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback4))
+typedef curl_socket_t (_curl_opensocket_callback1)
+ (void *, curlsocktype, struct curl_sockaddr *);
+typedef curl_socket_t (_curl_opensocket_callback2)
+ (void *, curlsocktype, const struct curl_sockaddr *);
+typedef curl_socket_t (_curl_opensocket_callback3)
+ (const void *, curlsocktype, struct curl_sockaddr *);
+typedef curl_socket_t (_curl_opensocket_callback4)
+ (const void *, curlsocktype, const struct curl_sockaddr *);
+
+/* evaluates to true if expr is of type curl_progress_callback or "similar" */
+#define _curl_is_progress_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) || \
+ _curl_callback_compatible((expr), _curl_progress_callback1) || \
+ _curl_callback_compatible((expr), _curl_progress_callback2))
+typedef int (_curl_progress_callback1)(void *,
+ double, double, double, double);
+typedef int (_curl_progress_callback2)(const void *,
+ double, double, double, double);
+
+/* evaluates to true if expr is of type curl_debug_callback or "similar" */
+#define _curl_is_debug_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) || \
+ _curl_callback_compatible((expr), _curl_debug_callback1) || \
+ _curl_callback_compatible((expr), _curl_debug_callback2) || \
+ _curl_callback_compatible((expr), _curl_debug_callback3) || \
+ _curl_callback_compatible((expr), _curl_debug_callback4) || \
+ _curl_callback_compatible((expr), _curl_debug_callback5) || \
+ _curl_callback_compatible((expr), _curl_debug_callback6) || \
+ _curl_callback_compatible((expr), _curl_debug_callback7) || \
+ _curl_callback_compatible((expr), _curl_debug_callback8))
+typedef int (_curl_debug_callback1) (CURL *,
+ curl_infotype, char *, size_t, void *);
+typedef int (_curl_debug_callback2) (CURL *,
+ curl_infotype, char *, size_t, const void *);
+typedef int (_curl_debug_callback3) (CURL *,
+ curl_infotype, const char *, size_t, void *);
+typedef int (_curl_debug_callback4) (CURL *,
+ curl_infotype, const char *, size_t, const void *);
+typedef int (_curl_debug_callback5) (CURL *,
+ curl_infotype, unsigned char *, size_t, void *);
+typedef int (_curl_debug_callback6) (CURL *,
+ curl_infotype, unsigned char *, size_t, const void *);
+typedef int (_curl_debug_callback7) (CURL *,
+ curl_infotype, const unsigned char *, size_t, void *);
+typedef int (_curl_debug_callback8) (CURL *,
+ curl_infotype, const unsigned char *, size_t, const void *);
+
+/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
+/* this is getting even messier... */
+#define _curl_is_ssl_ctx_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
+typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *);
+typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
+typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
+typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *);
+#ifdef HEADER_SSL_H
+/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
+ * this will of course break if we're included before OpenSSL headers...
+ */
+typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
+typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
+typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
+typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
+ const void *);
+#else
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
+#endif
+
+/* evaluates to true if expr is of type curl_conv_callback or "similar" */
+#define _curl_is_conv_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) || \
+ _curl_callback_compatible((expr), _curl_conv_callback1) || \
+ _curl_callback_compatible((expr), _curl_conv_callback2) || \
+ _curl_callback_compatible((expr), _curl_conv_callback3) || \
+ _curl_callback_compatible((expr), _curl_conv_callback4))
+typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
+typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
+typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
+typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
+
+/* evaluates to true if expr is of type curl_seek_callback or "similar" */
+#define _curl_is_seek_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) || \
+ _curl_callback_compatible((expr), _curl_seek_callback1) || \
+ _curl_callback_compatible((expr), _curl_seek_callback2))
+typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
+typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
+
+
+#endif /* __CURL_TYPECHECK_GCC_H */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/curl/libs/Android.mk b/src/connectivity/gps/2.0/mtk_mnld/curl/libs/Android.mk
new file mode 100644
index 0000000..f796975
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/curl/libs/Android.mk
@@ -0,0 +1,16 @@
+ifneq ($(TRUSTONIC_TEE_SUPPORT),yes)
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+#LOCAL_MODULE := libcurl
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+#LOCAL_MODULE_TAGS := optional
+#LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+#LOCAL_SRC_FILES_arm := libcurl_32.so
+#LOCAL_SRC_FILES_arm64 := libcurl_64.so
+#LOCAL_MODULE_SUFFIX := .so
+#LOCAL_MULTILIB := both
+#include $(BUILD_PREBUILT)
+endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/curl/libs/NOTICE b/src/connectivity/gps/2.0/mtk_mnld/curl/libs/NOTICE
new file mode 100644
index 0000000..163b299
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/curl/libs/NOTICE
@@ -0,0 +1,21 @@
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 1996 - 2010, Daniel Stenberg, <daniel@haxx.se>.
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software for any purpose
+with or without fee is hereby granted, provided that the above copyright
+notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
+NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization of the copyright holder.
diff --git a/src/connectivity/gps/2.0/mtk_mnld/curl/libs/README b/src/connectivity/gps/2.0/mtk_mnld/curl/libs/README
new file mode 100644
index 0000000..c713169
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/curl/libs/README
@@ -0,0 +1,15 @@
+WHAT IT DOES?
+=============
+libcurl.so is the implementation that access URL for downloading epo data as one shared library.
+
+HOW IT WAS BUILT?
+==================
+As library files, these are built by android build system.
+
+HOW TO USE IT?
+==============
+Their API will be called to download epo data when GPS open if epo file is expired.
+
+Source
+==============
+All the source code of this library were downloaded from http://curl.haxx.se/
\ No newline at end of file
diff --git a/src/connectivity/gps/2.0/mtk_mnld/curl/libs/libcurl_32.so b/src/connectivity/gps/2.0/mtk_mnld/curl/libs/libcurl_32.so
new file mode 100644
index 0000000..8a3449e
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/curl/libs/libcurl_32.so
Binary files differ
diff --git a/src/connectivity/gps/2.0/mtk_mnld/curl/libs/libcurl_64.so b/src/connectivity/gps/2.0/mtk_mnld/curl/libs/libcurl_64.so
new file mode 100644
index 0000000..5669ca5
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/curl/libs/libcurl_64.so
Binary files differ
diff --git a/src/connectivity/gps/2.0/mtk_mnld/files/MNL_Config.xml b/src/connectivity/gps/2.0/mtk_mnld/files/MNL_Config.xml
new file mode 100644
index 0000000..f0fadc8
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/files/MNL_Config.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<mnl_config version="19100901.6.00.99" type="gps">
+
+ <feature>GLP
+ <version>2.0</version>
+ <config>1</config>
+ <format>Enable</format>
+ <setting>1</setting>
+ </feature>
+
+ <feature>CAIC
+ <version>1.0</version>
+ <config>0</config>
+ <format>L1 CAIC FrequencyHz</format>
+ <setting>1560000000</setting>
+ <format>L5 CAIC FrequencyHz</format>
+ <setting>1170000000</setting>
+ </feature>
+
+ <feature>GnssMode
+ <version>1.0</version>
+ <config>0</config>
+ <format>GP+GL:0, GP+BD:1, GP+GL+BD:2, GP:3, BD:4, GL:5, GP+GL+GA+BD:6, GP+GA:7, GP+GL+GA:8, GA:9</format>
+ <setting>6</setting>
+ </feature>
+
+ <feature>DCB
+ <version>1.0</version>
+ <config>1</config>
+ <format>L5_DCB_GPS,L5_DCB_QZSS,L5_DCB_CNSS,L5_DCB_GALILEO</format>
+ <setting>-5.15,-5.16,-5.83,-5.22</setting>
+ </feature>
+
+ <feature>L1Only
+ <version>1.0</version>
+ <config>0</config>
+ <format>L1 only: 1</format>
+ <setting>0</setting>
+ </feature>
+
+ <feature>L5Test
+ <version>1.0</version>
+ <config>0</config>
+ <format>Search and used GPS L5 satellites according to the healthy status: 0, Search and used GPS L5 satellites regardless of its healthy status: 1</format>
+ <setting>1</setting>
+ </feature>
+
+ <feature>MDTime
+ <version>1.0</version>
+ <config>0</config>
+ <format>featureOption,requestInterval,sizeOfWindow,syncBackNum(optional)</format>
+ <setting>0,5000,1500,0</setting>
+ </feature>
+
+ <feature>ClockExt
+ <version>1.0</version>
+ <config>1</config>
+ <format>Enable</format>
+ <setting>0</setting>
+ </feature>
+
+</mnl_config>
diff --git a/src/connectivity/gps/2.0/mtk_mnld/files/k6880v1_mdot2_datacard/MNL_Config.xml b/src/connectivity/gps/2.0/mtk_mnld/files/k6880v1_mdot2_datacard/MNL_Config.xml
new file mode 100644
index 0000000..1f1c454
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/files/k6880v1_mdot2_datacard/MNL_Config.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<mnl_config version="19100901.6.00.99" type="gps">
+
+ <feature>GLP
+ <version>2.0</version>
+ <config>1</config>
+ <format>Enable</format>
+ <setting>1</setting>
+ </feature>
+
+ <feature>CAIC
+ <version>1.0</version>
+ <config>0</config>
+ <format>L1 CAIC FrequencyHz</format>
+ <setting>1560000000</setting>
+ <format>L5 CAIC FrequencyHz</format>
+ <setting>1170000000</setting>
+ </feature>
+
+ <feature>GnssMode
+ <version>1.0</version>
+ <config>0</config>
+ <format>GP+GL:0, GP+BD:1, GP+GL+BD:2, GP:3, BD:4, GL:5, GP+GL+GA+BD:6, GP+GA:7, GP+GL+GA:8, GA:9</format>
+ <setting>6</setting>
+ </feature>
+
+ <feature>DCB
+ <version>1.0</version>
+ <config>1</config>
+ <format>L5_DCB_GPS,L5_DCB_QZSS,L5_DCB_CNSS,L5_DCB_GALILEO</format>
+ <setting>-5.15,-5.16,-5.83,-5.22</setting>
+ </feature>
+
+ <feature>L1Only
+ <version>1.0</version>
+ <config>1</config>
+ <format>L1 only: 1</format>
+ <setting>1</setting>
+ </feature>
+
+ <feature>L5Test
+ <version>1.0</version>
+ <config>0</config>
+ <format>Search and used GPS L5 satellites according to the healthy status: 0, Search and used GPS L5 satellites regardless of its healthy status: 1</format>
+ <setting>1</setting>
+ </feature>
+
+ <feature>MDTime
+ <version>1.0</version>
+ <config>0</config>
+ <format>featureOption,requestInterval,sizeOfWindow,syncBackNum(optional)</format>
+ <setting>0,5000,1500,0</setting>
+ </feature>
+
+ <feature>ClockExt
+ <version>1.0</version>
+ <config>1</config>
+ <format>Enable</format>
+ <setting>0</setting>
+ </feature>
+
+</mnl_config>
diff --git a/src/connectivity/gps/2.0/mtk_mnld/files/mnld.init b/src/connectivity/gps/2.0/mtk_mnld/files/mnld.init
new file mode 100644
index 0000000..07535c3
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/files/mnld.init
@@ -0,0 +1,26 @@
+#!/bin/sh /etc/rc.common
+
+USE_PROCD=1
+
+START=53
+STOP=46
+
+NAME=mnld
+PROG=/usr/bin/mnld
+
+start_service() {
+ echo "start mnld"
+ procd_open_instance
+ procd_set_param command /usr/bin/mnld
+ procd_set_param respawn
+ # forward stdout and stderr of the command to logd
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_close_instance
+}
+
+reload_service() {
+ echo "reload mnld"
+ stop
+ start
+}
diff --git a/src/connectivity/gps/2.0/mtk_mnld/make_mnld.sh b/src/connectivity/gps/2.0/mtk_mnld/make_mnld.sh
new file mode 100755
index 0000000..ada1bd0
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/make_mnld.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+config_file_prepare()
+{
+ mkdir ./etc/
+ mkdir ./etc/gnss
+ cp files/MNL_Config.xml ./etc/
+}
+
+#if [ !$1 ]; then
+# mnld_folder=~/Git/mtk_gps_dual_freq/gps/mtk_mnld/
+#else
+# mnld_folder=$1
+#fi
+
+config_file_prepare
+make clean && make CFLAG=-D__LIBMNL_SIMULATOR__ 2>&1 |tee build.log
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/aarch64/libhotstill.a b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/aarch64/libhotstill.a
new file mode 100644
index 0000000..7da9502
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/aarch64/libhotstill.a
Binary files differ
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/aarch64/libmnl_gnss.so b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/aarch64/libmnl_gnss.so
new file mode 100644
index 0000000..cf56661
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/aarch64/libmnl_gnss.so
Binary files differ
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/MTK_BEE.h b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/MTK_BEE.h
new file mode 100644
index 0000000..a2763aa
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/MTK_BEE.h
@@ -0,0 +1,359 @@
+/***********************************************************************
+* This software/firmware and related documentation ("MediaTek Software")
+* are protected under relevant copyright laws. The information contained
+* herein is confidential and proprietary to MediaTek Inc. and/or its licensors.
+*
+* Without the prior written permission of MediaTek Inc. and/or its licensors,
+* any reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly prohibited.
+*
+* MediaTek Inc. (C) [2008]. All rights reserved.
+*
+*************************************************************************/
+//*****************************************************************************
+// [File] MTK_BEE.h : Defines the entry point for BEE library
+// [Version] v1.0
+// [Revision Date] 2008-03-31
+// [Author] YC Chien, yc.chien@mediatek.com, 21558
+// WG Yau, wg.yau@mediatek.com, 26967
+// [Description]
+//*****************************************************************************
+
+
+#ifndef MTK_BEE_H
+#define MTK_BEE_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "MTK_Type.h"
+#include "mtk_gps_type.h"
+
+
+//*****************************************************************************
+// MTK_BEE_Init : Initialize BEE kernel data
+//
+// PARAMETER : void
+//
+// RETURN : 1 for success, 0 for error
+// If return value is 0, you should NOT proceed with any BEE function
+
+MTK_BEE_INT MTK_BEE_Init (void);
+
+
+//*****************************************************************************
+// MTK_BEE_Init : Uninitialize BEE kernel data
+//
+// PARAMETER : void
+//
+// RETURN : void
+
+MTK_BEE_VOID MTK_BEE_Uninit (void);
+
+
+//*****************************************************************************
+// MTK_BEE_Set_File_Path : Set File Path for BEE kernel file
+//
+// PARAMETER : szFilePath [IN] - (1) Input file path for ARC.BIN, BEE.BIN and
+// BEET000A.
+// (2) Maximal path length is 256 bytes.
+// (3) MUST BE null-terminated string.
+// (4) MUST BE called before MTK_BEE_Init().
+// (5) MUST BE ended with a directory separator
+// character. (ex: '\\')
+// (6) If this function has not been called,
+// then no file path is set.
+// EXAMPLE :
+// MTK_BEE_Set_File_path("C:\\BEE\\");
+// MTK_BEE_Init();
+// ===> Input File path before MTK_BEE_Init() is called.
+//
+// RETURN : 1 for success, 0 for error
+// If return value is 0, you should NOT proceed with any BEE function
+
+MTK_BEE_INT MTK_BEE_Set_File_Path (char szFilePath[256]);
+
+
+//*****************************************************************************
+// MTK_BEE_Get_Table_Health : Get the health status of BEE data file (BEET000A)
+//
+// PARAMETER : void
+//
+// RETURN : 0 -> BEE data file is healthy
+// 1 -> BEE data file is valid for BEE functionality, but an update for this file is suggested
+// 2 -> BEE data file is expired so that BEE functionality has been stopped
+// 3 -> User has updated BEE data file to an older version,
+// BEE functionality has been stopped, need to update data file
+
+MTK_BEE_INT MTK_BEE_Get_Table_Health (void);
+
+
+//*****************************************************************************
+// MTK_BEE_Proc_Eph : Save broadcast ephemeris into BEE kernel database
+//
+// PARAMETER : u1SvId [IN] - satellite ID
+// au4Word [IN] - 24-word ephemeris raw data (word 3-8 of subframe 1,2,3)
+//
+// RETURN : void
+
+MTK_BEE_VOID MTK_BEE_Proc_Eph (unsigned char u1SvId, unsigned int au4Word[24]);
+
+
+//*****************************************************************************
+// MTK_BEE_Have_Enough_Eph : Check how many satellites have enough ephemeris for BEE generation
+//
+// PARAMETER : i2WeekNo [IN] - week number (count from Jan. 6, 1980)
+// i4Tow [IN] - time of week
+//
+// RETURN : Number of satellites with enough ephemeris for BEE generation
+// Ex : 5 -> 5 satellites have enough ephemeris
+//
+// NOTE : i2WeekNo and i4Tow SHOULD BE set to the correct current time ( > 0),
+// If i2WeekNo = 0 and i4Tow = 0 this function will not do optimization !!!
+//
+// EXAMPLE :
+// short i2WeekNo;
+// int i4Tow;
+// int i4NumSvToGen = MTK_BEE_Have_Enough_Eph(i2WeekNo, i4Tow);
+// if ( i4NumSvToGen >= 3 ) ===> Do BEE generation when at least 3 satellites have enough ephemeris
+// {
+// MTK_BEE_Gen_Auto(i2WeekNo, i4Tow);
+// }
+
+MTK_BEE_INT MTK_BEE_Have_Enough_Eph (short i2WeekNo, int i4Tow);
+
+
+//*****************************************************************************
+// MTK_BEE_Gen_All : Generate BEE ephemeris of all satellites
+//
+// PARAMETER : void
+//
+// RETURN : void
+
+MTK_BEE_VOID MTK_BEE_Gen_All (void);
+
+
+//*****************************************************************************
+// MTK_BEE_Gen_Auto : Auto Generate BEE ephemeris of all satellites
+//
+// PARAMETER : i2WeekNo [IN] - week number (count from Jan. 6, 1980)
+// i4Tow [IN] - time of week
+//
+// RETURN : 1 -> BEE data is already FULL generated
+// 0 -> BEE data is not FULL generated
+//
+// NOTE : i2WeekNo and i4Tow MUST BE set to the correct current time ( > 0),
+// otherwise this function may have wrong generated data !!!
+// If i2WeekNo = 0 and i4Tow = 0 this function will not do optimization !!!
+
+MTK_BEE_INT MTK_BEE_Gen_Auto (short i2WeekNo, int i4Tow);
+
+
+//*****************************************************************************
+// MTK_BEE_Gen_Data : Generate BEE ephemeris of the specified satellite
+//
+// PARAMETER : u1SvId [IN] - satellite ID
+// i2WeekNo [IN] - week number (count from Jan. 6, 1980)
+// i4Tow [IN] - time of week
+// u1GenLength [IN] - generate length ( MUST > 0 )
+// =1 -> Generate 1 Day Data
+// =2 -> Generate 2 Days Data
+// =3 -> Generate 3 Days Data
+// >3 -> Generate 3 Days Data
+//
+// RETURN : 0 -> No data has been generated / No BEE data
+// 1 -> 1 day data is already generated
+// 2 -> 2 days data is already generated
+// 3 -> 3 days data is already generated
+//
+// NOTE : If i2WeekNo and i4Tow is set to the current time ( > 0), then this function will delete expired BEE data
+// (ex. 3 days ago data) based on this current time. Therefore, return value will be 0.
+// Set i2WeekNo = 0 and i4Tow = 0 to bypass this time checking.
+//
+// EXAMPLE :
+// unsigned char u1GenState;
+// unsigned char u1SvId = 1;
+// (1)
+// u1GenState = MTK_BEE_Gen_Data(u1SvId, 0, 0, 3);
+// ===> Generate 3 days BEE data of SV 1, bypass time checking.
+// If u1GenState = 3, means already has 3 days BEE data, not necessary to generate data within this period,
+// unless receive new ephemeris.
+// (2)
+// u1GenState = MTK_BEE_Gen_Data(u1SvId, 0, 0, 1);
+// ===> Generate 1 day BEE data of SV 1, bypass time checking.
+// (3)
+// u1GenState = MTK_BEE_Gen_Data(u1SvId, 1467, 313200, 1);
+// ===> Generate 1 day BEE data of SV 1, using time checking.
+//
+// (4) Methods for 3 days BEE data generation
+// ------------------------------------------
+// (a) u1GenState = MTK_BEE_Gen_Data(u1SvId, 1467, 313200, 1); ==> u1GenState = 1 (has 1 day BEE data)
+// u1GenState = MTK_BEE_Gen_Data(u1SvId, 1467, 313300, 1); ==> u1GenState = 2 (has 2 days BEE data)
+// u1GenState = MTK_BEE_Gen_Data(u1SvId, 1467, 313400, 1); ==> u1GenState = 3 (has 3 days BEE data)
+//
+// (b) u1GenState = MTK_BEE_Gen_Data(u1SvId, 1467, 313200, 2); ==> u1GenState = 2 (has 2 day BEE data)
+// u1GenState = MTK_BEE_Gen_Data(u1SvId, 1467, 313300, 1); ==> u1GenState = 3 (has 3 days BEE data)
+//
+// (c) u1GenState = MTK_BEE_Gen_Data(u1SvId, 1467, 313200, 3); ==> u1GenState = 3 (has 3 day BEE data)
+
+MTK_BEE_INT MTK_BEE_Gen_Data (unsigned char u1SvId, short i2WeekNo, int i4Tow, unsigned char u1GenLength);
+
+
+//*****************************************************************************
+// MTK_BEE_Get_Progress : Get the progress of BEE generation
+//
+// PARAMETER : void
+//
+// RETURN : Progress of current BEE generation, represented in percentage (%)
+// 100 : No action (no generation under going / generation finished)
+// 0 - 99 : Progress
+
+MTK_BEE_INT MTK_BEE_Get_Progress (void);
+
+
+//*****************************************************************************
+// MTK_BEE_Get_Data : Get BEE ephemeris of the specified satellite at the specified time
+//
+// PARAMETER : u1SvId [IN] - satellite ID
+// i2WeekNo [IN] - week number (count from Jan. 6, 1980)
+// i4Tow [IN] - time of week
+// BeeData [OUT] - BEE ephemeris
+//
+// RETURN : 1 for success, 0 for no BEE data
+
+MTK_BEE_INT MTK_BEE_Get_Data (unsigned char u1SvId, short i2WeekNo, int i4Tow, unsigned char BeeData[48]);
+
+
+//*****************************************************************************
+// MTK_BEE_Get_Available_Info : Get information about BEE ephemeris of which satellite
+//
+// PARAMETER : i2WeekNo [IN] - week number (count from Jan. 6, 1980)
+// i4Tow [IN] - time of week
+// BeeAvail [OUT] - Array of 32 unsigned char for 32 satellites
+// 0 -- no BEE available for this satellite
+// 1-xx -- BEE is available for this satellite ( Valid Hours )
+//
+// RETURN : 1 for success
+
+MTK_BEE_INT MTK_BEE_Get_Available_Info (short i2WeekNo, int i4Tow, unsigned char BeeAvail[32]);
+
+//*****************************************************************************
+// MTK_BEE_Get_GNSS_Available_Info : Get information about BEE ephemeris of which satellite
+//
+// PARAMETER : i2WeekNo [IN] - week number (count from Jan. 6, 1980)
+// i4Tow [IN] - time of week
+// BeeAvail [OUT] - Array of 256 unsigned char for 256 satellites
+// 0 -- no BEE available for this satellite
+// 1-xx -- BEE is available for this satellite ( Valid Hours )
+//
+// RETURN : 1 for success
+
+MTK_BEE_INT MTK_BEE_Get_GNSS_Available_Info (short i2WeekNo, int i4Tow, unsigned char BeeAvail[256]);
+
+//*****************************************************************************
+// MTK_BEE_Enable_Eph_Update : Enable updating BEE with broadcast ephemeris
+// for ALL satellites and save the configuration to file
+//
+// PARAMETER : void
+//
+// RETURN : 1 for success, 0 if fail to save configuration to file
+
+MTK_BEE_INT MTK_BEE_Enable_Eph_Update (void);
+
+
+//*****************************************************************************
+// MTK_BEE_Disable_Eph_Update : Disable updating BEE with broadcast ephemeris
+// for ALL satellites and save the configuration to file
+//
+// PARAMETER : void
+//
+// RETURN : 1 for success, 0 if fail to save configuration to file
+
+MTK_BEE_INT MTK_BEE_Disable_Eph_Update (void);
+
+
+//*****************************************************************************
+// MTK_BEE_Set_Eph_Update : Set whether to update BEE with broadcast ephemeris
+// for individual satellite and save the configuration to file
+//
+// PARAMETER : UpdateEph [IN] - Array of 32 unsigned char for 32 satellites
+// 0 -- disable updating broadcast ephemeris for this satellite
+// 1 -- enable updating broadcast ephemeris for this satellite
+//
+// RETURN : 1 for success, 0 if fail to save configuration to file
+
+MTK_BEE_INT MTK_BEE_Set_Eph_Update (unsigned char UpdateEph[32]);
+
+
+//*****************************************************************************
+// MTK_BEE_Hot_Still_Test : Perform hot still test
+//
+// PARAMETER : u4Test_Mode [IN] -
+// bit0 : use old force model parameters
+//
+// RETURN : void
+
+MTK_BEE_VOID MTK_BEE_Hot_Still_Test(unsigned long u4Test_Mode);
+
+
+//*****************************************************************************
+// MTK_BEE_Test : Perform BEE self-test, output data is stored in BEE_TEST.BIN
+//
+// PARAMETER : u1SvId [IN] - PRN of the satellite to be tested
+//
+// RETURN : void
+
+MTK_BEE_VOID MTK_BEE_Test (unsigned char u1SvId);
+
+//*****************************************************************************
+// MTK_BEE_Shutdown : force HotStill run into shutdown mode. (shutdown all jobs after curretn prediction done)
+//
+// PARAMETER : fgEnableShutdown [IN] -
+// 0 : disable shutdown to resume original state
+// 1 : enable shutdown
+// RETURN : void
+MTK_BEE_VOID MTK_BEE_Shutdown(unsigned char fgEnableShutdown);
+
+//*****************************************************************************
+// MTK_BEE_Get_Version_Info : Get BEE and HotStill related information
+//
+// PARAMETER : Version [OUT] - Library version
+// Lib_Date [OUT] - Library release dat information
+//
+// RETURN : void
+
+MTK_BEE_VOID MTK_BEE_Get_Version_Info (double *Version, char *Lib_Date);
+
+//*****************************************************************************
+// MTK_BEE_Get_Calibration_Status : Get HotStill calibration status
+//
+// PARAMETER : void
+//
+// RETURN : 1 for calibration and gen in progess, 0 for calibration not in progress
+
+MTK_BEE_INT MTK_BEE_Get_Calibration_Status(void);
+
+//*****************************************************************************
+// MTK_BEE_Set_Debug_Config : Set HotStill debug configuration
+//
+// PARAMETER : DbgType [IN] - debug type
+// DbgLevel [IN] - debug level
+// RETURN : 1 success, 0 fail
+
+MTK_BEE_INT MTK_BEE_Set_Debug_Config(MTK_DEBUG_TYPE DbgType, MTK_DEBUG_LEVEL DbgLevel);
+
+//*****************************************************************************
+// MTK_BEE_Get_Debug_Config : Get HotStill debug configuration
+//
+// PARAMETER : DbgType [IN] - debug type
+// *DbgLevel [OUT] - debug level
+//
+// RETURN : 1 success, 0 fail
+MTK_BEE_INT MTK_BEE_Get_Debug_Config(MTK_DEBUG_TYPE DbgType, MTK_DEBUG_LEVEL *DbgLevel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MTK_BEE_H */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/MTK_SDK_Bee.h b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/MTK_SDK_Bee.h
new file mode 100644
index 0000000..51277e4
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/MTK_SDK_Bee.h
@@ -0,0 +1,530 @@
+/***********************************************************************
+* This software/firmware and related documentation ("MediaTek Software")
+* are protected under relevant copyright laws. The information contained
+* herein is confidential and proprietary to MediaTek Inc. and/or its licensors.
+*
+* Without the prior written permission of MediaTek Inc. and/or its licensors,
+* any reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly prohibited.
+*
+* MediaTek Inc. (C) [2008]. All rights reserved.
+*
+*************************************************************************/
+#ifndef MTK_SDK_BEE_H
+#define MTK_SDK_BEE_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//*****************************************************************************************************
+// MTK_Bee_Feed_Eph : Feed the ephemeris to Bee Host
+//
+// Description : MTK_Bee_Feed_Eph ( unsigned char Svid , unsigned int au4Word[24] )
+// Svid : GPS satellite PRN (1~32)
+// au4Word -- 24 words ephemeris data
+//
+// Returns: zero(fail), nonzero(pass)
+//
+// Example :
+// unsigned char SvId = 0;
+// unsigned int Ephdata[24];
+// iRes = MTK_Bee_Feed_Eph ( SvId, Ephdata);
+//
+// =====> Ephdata is ephemeris data and need to transfer to BEE HOST
+// If iRes > 0 --> Data is valid and can be transfered to BEE HOST
+
+int MTK_Bee_Feed_Eph ( unsigned char Svid , unsigned int au4Word[24] );
+
+//*****************************************************************************************************
+// MTK_Bee_Receive_Bee_Data : Receive the Bee data from HOST
+//
+// Description : MTK_Bee_Receive_Bee_Data ( char *BeeData )
+// BeeData -- BEE data from HOST for aiding.
+// BEE data buf mest be greater than 96 bytes.
+//
+// Returns: zero(fail), nonzero(pass)
+//
+// Example :
+// char Beedatabuf[96]; // must be >= 96 bytes
+// iRes = MTK_Bee_Receive_Bee_Data ( Beedatabuf );
+//
+// =====> Beedatabuf is BEE data and need to feed to GPS receiver
+// If iRes > 0 --> Bee data aiding is valid.
+
+int MTK_Bee_Receive_Bee_Data ( char *BeeData );
+
+//*****************************************************************************************************
+// MTK_Bee_Request_All : Send request BEE data command to HOST.
+//
+// Description : MTK_Bee_Request_All ( void )
+// Send a Nmea command to HOST for request the BEE data.
+//
+// Example :
+// MTK_Bee_Request_All();
+//
+// =====> $PMTKRQTBEE*17
+
+void MTK_Bee_Request_All ( void );
+
+//********************************************************************************************************
+// MTK_Bee_Get_Eph_Info : Get the information whether satellites has Ephemeris (BRDC / BEE) or not
+//
+// Note : Eph is arrays with 32 unsigned char.
+// 0 ---> This SV has no Ephemeris.
+// 1 ---> This SV has BRDC Ephemeris.
+// 2 ---> This SV has 1st day BEE Ephemeris.
+// 3 ---> This SV has 2nd day BEE Ephemeris.
+// 4 ---> This SV has 3rd day BEE Ephemeris.
+//
+// Example:
+// unsigned char Eph[32];
+// MTK_Bee_Get_Eph_Info(Eph);
+// MTK_UART_OutputData("SDK: Eph = %d", Eph[16]);
+//
+// =====> SDK: Eph = 1 ---> SV17 has BRDC Ephemeris.
+// =====> SDK: Eph = 2 ---> SV17 has 1st day BEE Ephemeris.
+
+void MTK_Bee_Get_Eph_Info (unsigned char Eph[32]);
+
+//********************************************************************************************************
+// MTK_Bee_Get_New_Eph_Info : Get the information whether satellites has new Ephemeris or not
+//
+// Note : NewEph is 1 unsigned int with 32 bit.
+// bit x = 0 ---> No New Ephemeris, x+1 = GPS satellite PRN.
+// bit x = 1 ---> Has New Ephemeris, x+1 = GPS satellite PRN.
+// Example:
+// int i;
+// unsigned int NewEph,EPhMask;
+// MTK_Bee_Get_Eph_Info(&NewEph);
+// MTK_UART_OutputData("SDK: NewEph = %d", NewEph);
+// if ( NewEph != 0 )
+// {
+// EPhMask = 1;
+// for (i = 0; i < 32; i++)
+// {
+// if ( (NewEph & EPhMask) != 0 )
+// {
+// MTK_UART_OutputData("SV%d: NewEph = %d", i+1, NewEph);
+// }
+// EPhMask = EPhMask << 1;
+// }
+// }
+// =====> SDK: NewEph = 1 ---> Has New Ephemeris.
+// =====> SV3: NewEph = 1 ---> SV3 has New Ephemeris.
+// =====> SV17: NewEph = 1 ---> SV17 has New Ephemeris.
+
+void MTK_Bee_Get_New_Eph_Info (unsigned int *NewEph);
+
+//********************************************************************************************************
+// MTK_Bee_Req_Info : Get the information whether need to request BEE data or not
+//
+// Note : BeeReq is arrays with 32 unsigned char.
+// 0 ---> This SV no need to request BEE Ephemeris.
+// 1 ---> This SV need to request BEE Ephemeris.
+// Example:
+// unsigned char BeeReq[32];
+// MTK_Bee_Req_Info(BeeReq);
+// MTK_UART_OutputData("SDK: BeeReq = %d", BeeReq[16]);
+//
+// =====> SDK: BeeReq = 1 ---> SV17 need to request BEE Ephemeris.
+// =====> SDK: BeeReq = 0 ---> SV17 no need to request BEE Ephemeris.
+
+void MTK_Bee_Req_Info (unsigned char BeeReq[32]);
+
+//********************************************************************************************************
+// MTK_Bee_Age : Get the age information of BEE data
+//
+// Note : BeeAge is arrays with 32 short.
+// -1 ---> BEE Ephemeris is not valid .
+// nonzero ---> BEE Ephemeris age.
+// Example:
+// short BeeAge [32];
+// MTK_Bee_Age(BeeAge);
+// MTK_UART_OutputData("SDK: BeeAge = %d", BeeAge[16]);
+//
+// =====> SDK: BeeReq = 300 ---> SV17 BEE Ephemeris has been used 300 sec.
+// =====> SDK: BeeReq = -1 ---> SV17 BEE Ephemeris is not valid.
+
+void MTK_Bee_Age ( short BeeAge[32]);
+
+//********************************************************************************************************
+// MTK_Bee_Send_New_Eph : Send new ephemeris to Host
+//
+// Description : MTK_Bee_Send_New_Eph (unsigned int *NewEphSv);
+// NewEphSv -- 32-bit mask to indicate if satellites have new ephemeirs or not
+// bit x = 0 ---> No New Ephemeris, x+1 = GPS satellite PRN
+// bit x = 1 ---> Has New Ephemeris, x+1 = GPS satellite PRN
+//
+// Return : 0 ---> No new BRDC
+// 1 ---> Have new BRDC, Receiver should start handshaking with Host
+// 2 ---> Have new BRDC and handshaking is OK, Receiver should send BRDC data to Host
+//
+// Example :
+// void SDK_Main (void)
+// {
+// int NewEphStep;
+// unsigned char SvId;
+// unsigned int EphData[24];
+// NewEphStep = MTK_Bee_Send_New_Eph();
+// if (NewEphStep == 1)
+// {
+// ... Send handshaking message to Host ...
+// }
+// else if (NewEphStep == 2)
+// {
+// if ( MTK_Bee_Get_New_Eph_Data(&SvId, EphData) )
+// {
+// ... Send ephemeris data to Host ...
+// }
+// }
+// }
+
+int MTK_Bee_Send_New_Eph (unsigned int *NewEphSv);
+
+//********************************************************************************************************
+// MTK_Bee_Get_New_Eph_Data : Get ephemeris data to send
+//
+// Description : MTK_Bee_Get_New_Eph_Data ( unsigned char *SvId, unsigned int EphData[24] )
+// SvId -- pointer to Satellite ID
+// EphData -- 24-word ephemeris data
+//
+// Note : This function automatically determines which ephemeris should be sent at current time
+//
+// Return : 0 ---> No ephemeris data needed to be sent
+// 1 ---> Have ephemeris data to be sent
+//
+// Example :
+// unsigned char SvId;
+// unsigned int EphData[24];
+// iRes = MTK_Bee_Get_New_Eph_Data(&SvId, EphData);
+// if ( iRes )
+// {
+// for ( i = 0; i < 24; i++ )
+// {
+// sprintf(( buf + i*7 ), ",%06X", EphData[i]);
+// }
+// MTK_NMEA_OutputData("PMTKDTEPH,%02X%s", SvId, buf);
+// }
+
+int MTK_Bee_Get_New_Eph_Data (unsigned char *SvId, unsigned int EphData[24]);
+
+//********************************************************************************************************
+// MTK_Bee_Receive_New_Eph_Host_Ready : Receive message of Host ready to receive new ephemeris
+//
+// Description : MTK_Bee_Receive_New_Eph_Ack ( unsigned char SvId )
+// SvId -- Satellite ID for ACK
+//
+// Example :
+// MTK_Bee_Receive_New_Eph_Host_Ready();
+// MTK_UART_OutputData("READY TO SEND BRDC DATA");
+
+void MTK_Bee_Receive_New_Eph_Host_Ready (void);
+
+//********************************************************************************************************
+// MTK_Bee_Receive_New_Eph_Ack : Receive ack for new ephemeris data from Host
+//
+// Description : MTK_Bee_Receive_New_Eph_Ack ( unsigned char SvId )
+// SvId -- Satellite ID for ACK
+//
+// Return : 0 ---> Invalid ACK, satellite ID does not match the ephemeris sent
+// 1 ---> ACK is valid
+//
+// Example :
+// unsigned char SvId;
+// iRes = MTK_Bee_Receive_New_Eph_Ack(SvId);
+// if ( iRes )
+// {
+// MTK_UART_OutputData("BRDC ACK SV %d OK", SvId);
+// }
+// else
+// {
+// MTK_UART_OutputData("BRDC ACK SV %d FAIL", SvId);
+// }
+
+int MTK_Bee_Receive_New_Eph_Ack (unsigned char SvId);
+
+//********************************************************************************************************
+// MTK_Bee_Request_Data : Get a list of satellites which need BEE data
+//
+// Description : MTK_Bee_Request_Data ( unsigned char BeeReq[32] )
+// BeeReq -- Array with 32 unsigned char
+// 0 ---> Seed BEE request for this satellite
+// 1 ---> Do not send BEE request for this satellite
+//
+// Note : If MTK_Bee_Disable_BEE() is called to diable BEE,
+// this function will not request any BEE data.
+// Only after MTK_Bee_Enable_BEE() is called,
+// this function will restart to request BEE data.
+//
+// Example :
+// int NumSv, NumSvOnce, i;
+// unsigned char BeeReq[32];
+// char buf[256], tmp[16];
+// MTK_Bee_Request_Data(BeeReq);
+// for ( i = 0; i < 32; i++ )
+// {
+// if ( BeeReq[i] )
+// {
+// NumSv++;
+// sprintf(tmp, ",%d", i + 1);
+// strcat(buf, tmp);
+// }
+// }
+// NumSvOnce = 6;
+// if ( NumSv > 0 )
+// {
+// MTK_NMEA_OutputData("PMTKRQTBEE,%d,%d%s", NumSvOnce, NumSv, buf);
+// }
+
+void MTK_Bee_Request_Data (unsigned char BeeReq[32]);
+
+//********************************************************************************************************
+// MTK_Bee_Receive_Host_Info : Receive a list of satellites which Host has their BEE data
+//
+// Description : MTK_Bee_Receive_Host_Info ( int NumSv, unsigned char HostBeeInfo[32] )
+// NumSv -- Number of satellites in
+// HostBeeInfo -- Array with 32 unsigned char
+// 0 ---> Host does not have BEE data for this satellite
+// 1 ---> Host has BEE data for this satellite
+//
+// Return : 0 ---> Fail, input information is not valid
+// 1 ---> OK, input information is valid
+//
+// Example :
+// int NumSv, Res;
+// unsigned char HostBeeInfo[32];
+// Res = MTK_Bee_Receive_Host_Info(NumSv, HostBeeInfo);
+// if ( Res )
+// {
+// MTK_UART_OutputData("HOST BEE INFO OK");
+// }
+// else
+// {
+// MTK_UART_OutputData("HOST BEE INFO FAIL");
+// }
+
+int MTK_Bee_Receive_Host_Info (int NumSv, unsigned char HostBeeInfo[32]);
+
+//********************************************************************************************************
+// MTK_Bee_Receive_End_Data : Receive end of BEE data transmission message from Host
+//
+// Description : The receiver stops checking which satellite needs BEE data after
+// MTK_Bee_Receive_Host_Info() is called.
+// The receiver will restart to check which satellite needs BEE data after
+// MTK_Bee_Receive_End_Data() is called.
+//
+// Example :
+// MTK_Bee_Receive_End_Data();
+// MTK_UART_OutputData("BEE TRANSMISSION FINISH");
+
+void MTK_Bee_Receive_End_Data (void);
+
+//*****************************************************************************************************
+// MTK_Bee_Disable_BEE : Disable ALL BEE data
+//
+// Description : If no need using BEE data for generate fix, then
+// using MTK_Bee_Disable_BEE() to disable BEE data.
+//
+// Returns : NONE
+//
+// Example :
+// Receive some special command( DISABLE_BEE ), then Disable BEE data
+// UART_RECEIVE()
+// {
+// ......
+// case DISABLE_BEE:
+// MTK_Bee_Disable_BEE();
+// break;
+// ......
+// }
+
+void MTK_Bee_Disable_BEE ( void );
+
+//*****************************************************************************************************
+// MTK_Bee_Enable_BEE : Enable ALL BEE data
+//
+// Description : If needed using BEE data for generate fix, then
+// using MTK_Bee_Enable_BEE() to enable BEE data.
+//
+// Returns : NONE
+//
+// Example :
+// Receive some special command( ENABLE_BEE ), then Enable BEE data
+// UART_RECEIVE()
+// {
+// ......
+// case ENABLE_BEE:
+// MTK_Bee_Enable_BEE();
+// break;
+// ......
+// }
+
+void MTK_Bee_Enable_BEE ( void );
+
+//*****************************************************************************************************
+// MTK_Bee_Set_BEE : Set enable / disable BEE data for individual satellite
+//
+// Description : MTK_Bee_Set_BEE ( unsigned char EnableBEE[32] )
+// EnableBEE -- Array with 32 unsigned char
+// 0 ---> Disable use of BEE data in the fix for this satellite
+// 1 ---> Enable use of BEE data in the fix for this satellite
+//
+// Returns : NONE
+//
+// Example :
+// Receive some special command( SET_BEE ), then Set enable / disable BEE data
+// UART_RECEIVE()
+// {
+// ......
+// case SET_BEE:
+// unsigned char EnableBEE[32];
+// EnableBEE[5] = 1;
+// EnableBEE[12] = 0;
+// EnableBEE[16] = 1;
+// MTK_Bee_Set_BEE(EnableBEE);
+// break;
+// ......
+// }
+//
+// =====> Enable use BEE data of PRN 5, 16 in the fix
+// Disable use BEE data of PRN 12 in the fix
+
+void MTK_Bee_Set_BEE ( unsigned char EnableBEE[32] );
+
+//*****************************************************************************************************
+// MTK_Bee_Disable_BRDC : Disable ALL BRDC data
+//
+// Description : If no need using BRDC data for generate fix, then
+// using MTK_Bee_Disable_BRDC() to disable BRDC data.
+//
+// Returns : NONE
+//
+// Example :
+// Receive some special command( DISABLE_BRDC ), then Disable BRDC data
+// UART_RECEIVE()
+// {
+// ......
+// case DISABLE_BRDC:
+// MTK_Bee_Disable_BRDC();
+// break;
+// ......
+// }
+
+void MTK_Bee_Disable_BRDC ( void );
+
+//*****************************************************************************************************
+// MTK_Bee_Enable_BRDC : Enable ALL BRDC data
+//
+// Description : If needed using BRDC data for generate fix, then
+// using MTK_Bee_Enable_BRDC() to enable BRDC data.
+//
+// Returns : NONE
+//
+// Example :
+// Receive some special command( ENABLE_BRDC ), then Enable BRDC data
+// UART_RECEIVE()
+// {
+// ......
+// case ENABLE_BRDC:
+// MTK_Bee_Enable_BRDC();
+// break;
+// ......
+// }
+
+void MTK_Bee_Enable_BRDC ( void );
+
+//*****************************************************************************************************
+// MTK_Bee_Set_BRDC : Set enable / disable BRDC data for individual satellite
+//
+// Description : MTK_Bee_Set_BRDC ( unsigned char EnableBRDC[32] )
+// EnableBRDC -- Array with 32 unsigned char
+// 0 ---> Disable use of BRDC data in the fix for this satellite
+// 1 ---> Enable use of BRDC data in the fix for this satellite
+//
+// Returns : NONE
+//
+// Example :
+// Receive some special command( SET_BRDC ), then Set enable / disable BRDC data
+// UART_RECEIVE()
+// {
+// ......
+// case SET_BRDC:
+// unsigned char EnableBRDC[32];
+// EnableBRDC[5] = 1;
+// EnableBRDC[12] = 0;
+// EnableBRDC[16] = 1;
+// MTK_Bee_Set_BRDC(EnableBRDC);
+// break;
+// ......
+// }
+//
+// =====> Enable use BRDC ephemeris of PRN 5, 16 in the fix
+// Disable use BRDC ephemeris of PRN 12 in the fix
+
+void MTK_Bee_Set_BRDC ( unsigned char EnableBRDC[32] );
+
+
+//*****************************************************************************************************
+// MTK_Bee_Query_BRDC_Status : Query BRDC ephemeris status
+//
+// Description : MTK_Bee_Query_BRDC_Status ( unsigned char QueryBRDC[32] )
+// QueryBRDC -- Array with 32 unsigned char
+// 0 ---> BRDC ephemeris is disable use in the fix for this satellite
+// 1 ---> BRDC ephemeris is enable use in the fix for this satellite
+//
+// Returns : NONE
+//
+// Example :
+// Receive some special command( QUERY_BRDC ), then Query BRDC ephemeris
+// UART_RECEIVE()
+// {
+// ......
+// case QUERY_BRDC:
+// unsigned char QueryBRDC[32];
+// MTK_Bee_Query_BRDC_Status(QueryBRDC);
+// break;
+// ......
+// }
+//
+// =====> if QueryBRDC[5] = 1; QueryBRDC[19] = 0; QueryBRDC[25] = 1;
+// BRDC ephemeris of PRN 5, 25 is enable use in the fix
+// BRDC ephemeris of PRN 19 is disable use in the fix
+
+void MTK_Bee_Query_BRDC_Status ( unsigned char QueryBRDC[32] );
+
+
+//*****************************************************************************************************
+// MTK_Bee_Query_BEE_Status : Query BEE data status
+//
+// Description : MTK_Bee_Query_BRDC_Status ( unsigned char QueryBEE[32] )
+// QueryBRDC -- Array with 32 unsigned char
+// 0 ---> BEE data is disable use in the fix for this satellite
+// 1 ---> BEE data is enable use in the fix for this satellite
+//
+// Returns : NONE
+//
+// Example :
+// Receive some special command( QUERY_BEE ), then Query BEE data
+// UART_RECEIVE()
+// {
+// ......
+// case QUERY_BEE:
+// unsigned char QueryBEE[32];
+// MTK_Bee_Query_BEE_Status(QueryBEE);
+// break;
+// ......
+// }
+//
+// =====> if QueryBEE[5] = 1; QueryBEE[19] = 0; QueryBEE[25] = 1;
+// BEE data of PRN 5, 25 is enable use in the fix
+// BEE data of PRN 19 is disable use in the fix
+
+void MTK_Bee_Query_BEE_Status ( unsigned char QueryBEE[32] );
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* MTK_SDK_BEE_H */
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/MTK_Sys.h b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/MTK_Sys.h
new file mode 100644
index 0000000..9d4bca0
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/MTK_Sys.h
@@ -0,0 +1,263 @@
+/***********************************************************************
+* This software/firmware and related documentation ("MediaTek Software")
+* are protected under relevant copyright laws. The information contained
+* herein is confidential and proprietary to MediaTek Inc. and/or its licensors.
+*
+* Without the prior written permission of MediaTek Inc. and/or its licensors,
+* any reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly prohibited.
+*
+* MediaTek Inc. (C) [2008]. All rights reserved.
+*
+*************************************************************************/
+//*****************************************************************************
+// [File] MTK_Sys.h
+// [Version] v1.0
+// [Revision Date] 2008-03-31
+// [Author] YC Chien, yc.chien@mediatek.com, 21558
+// [Description] Define the prototypes of operating system dependent functions
+//*****************************************************************************
+
+#ifndef MTK_SYS_H
+#define MTK_SYS_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "MTK_Type.h"
+
+//#define BEE_HEAP_DEBUG
+
+//*****************************************************************************
+// Semaphore Functions
+//*****************************************************************************
+
+//*****************************************************************************
+// MTK_Sys_Init_Smphr : Initial semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to be initizlized
+//
+// RETURN : void
+
+void MTK_Sys_Init_Smphr (MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// MTK_Sys_Delete_Smphr : Delete semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to be deleted
+//
+// RETURN : void
+
+void MTK_Sys_Delete_Smphr (MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// MTK_Sys_Reserve_Smphr : Reserve semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to reserve
+//
+// RETURN : void
+
+void MTK_Sys_Reserve_Smphr (MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// MTK_Sys_Release_Smphr : Release semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to release
+//
+// RETURN : void
+
+void MTK_Sys_Release_Smphr (MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// MTK_Sys_Init_Smphr_For_EPO : Initial semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to be initizlized
+//
+// RETURN : void
+
+void MTK_Sys_Init_Smphr_For_EPO (MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// MTK_Sys_Delete_Smphr_For_EPO : Delete semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to be deleted
+//
+// RETURN : void
+
+void MTK_Sys_Delete_Smphr_For_EPO(MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// MTK_Sys_Reserve_Smphr_For_EPO : Reserve semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to reserve
+//
+// RETURN : void
+
+void MTK_Sys_Reserve_Smphr_For_EPO (MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// MTK_Sys_Release_Smphr_For_EPO : Release semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to release
+//
+// RETURN : void
+
+void MTK_Sys_Release_Smphr_For_EPO (MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// Memory Functions
+//*****************************************************************************
+
+//*****************************************************************************
+// MTK_Sys_Memory_Alloc : Allocate a block of memory
+//
+// PARAMETER : u4Size [IN] - size of memory (bytes) to be allocated
+//
+// RETURN : On success, return the pointer to the allocated memory
+// If fail, return NULL
+
+void* MTK_Sys_Memory_Alloc (MTK_UINT32 u4Size);
+
+
+//*****************************************************************************
+// MTK_Sys_Memory_Free : Deallocate memory previosly allocated by MTK_Sys_Memory_Alloc()
+//
+// PARAMETER : pMemory [IN] - pointer to memory to be freed
+//
+// RETURN : void
+
+void MTK_Sys_Memory_Free (void *pMemory);
+
+
+//*****************************************************************************
+// File Functions
+//*****************************************************************************
+
+//*****************************************************************************
+// MTK_Sys_File_Open : Open a file
+//
+// PARAMETER : szFileName [IN] - name of the file to be opened
+// i4Mode [IN] - file access mode (read / write / read + write)
+// 0 -- open file for reading (r)
+// 1 -- create file for writing,
+// discard previous contents if any (w)
+// 2 -- open or create file for writing at end of file (a)
+// 3 -- open file for reading and writing (r+)
+// 4 -- create file for reading and writing,
+// discard previous contents if any (w+)
+// 5 -- open or create file for reading and writing at end of file (a+)
+//
+// NOTE : For system which treats binary mode and text mode differently,
+// such as Windows / DOS, please make sure to open file in BINARY mode
+//
+// RETURN : On success, return the file handle
+// If fail, return 0
+
+MTK_FILE MTK_Sys_File_Open (const char *szFileName, MTK_INT32 i4Mode);
+
+
+//*****************************************************************************
+// MTK_Sys_File_Close : Close a file
+//
+// PARAMETER : hFile [IN] - handle of file to be closed
+//
+// RETURN : void
+
+void MTK_Sys_File_Close (MTK_FILE hFile);
+
+
+//*****************************************************************************
+// MTK_Sys_File_Read : Read a block of data from file
+//
+// PARAMETER : hFile [IN] - handle of file
+// DstBuf [OUT] - pointer to data buffer to be read
+// u4Length [IN] - number of bytes to read
+//
+// RETURN : Number of bytes read
+
+MTK_UINT32 MTK_Sys_File_Read (MTK_FILE hFile, void *DstBuf, MTK_UINT32 u4Length);
+
+
+//*****************************************************************************
+// MTK_Sys_File_Write : Write a block of data from file
+//
+// PARAMETER : hFile [IN] - handle of file
+// SrcBuf [IN] - pointer to data buffer to be written
+// u4Length [IN] - number of bytes to write
+//
+// RETURN : Number of bytes written
+
+MTK_UINT32 MTK_Sys_File_Write (MTK_FILE hFile, void *SrcBuf, MTK_UINT32 u4Length);
+
+
+//*****************************************************************************
+// MTK_Sys_File_Seek : Set the position indicator associated with file handle
+// to a new position defined by adding offset to a reference
+// position specified by origin
+//
+// PARAMETER : hFile [IN] - handle of file
+// u4OffSet [IN] - number of bytes to offset from origin
+// u4Origin [IN] - position from where offset is added
+// 0 -- seek from beginning of file
+// 1 -- seek from current position
+// 2 -- seek from end of file
+//
+// RETURN : On success, return a zero value
+// Otherwise, return a non-zero value
+
+MTK_INT32 MTK_Sys_File_Seek (MTK_FILE hFile, MTK_UINT32 u4OffSet, MTK_UINT32 u4Origin);
+
+//*****************************************************************************
+// MTK_Sys_Debug_Output : Output debug messages of HotStill library
+// Porting layer can help to log on file
+// or sent by other interfaces
+//
+// PARAMETER : buffer [IN] - data pointer
+// length [IN] - size of data
+//
+// RETURN : On success, return a zero value
+// Otherwise, return a non-zero value
+
+MTK_BEE_INT MTK_Sys_Debug_Output (char* buffer, unsigned int length);
+
+
+//*****************************************************************************
+// Time Functions
+//*****************************************************************************
+
+//*****************************************************************************
+// MTK_Sys_Time : Get the current system time
+//
+// PARAMETER : pUTCTime [OUT] - UTC time
+//
+// RETURN : Success (MTK_TRUE) or Fail (MTK_FAIL)
+
+MTK_BOOL MTK_Sys_Time (MTK_TIME *pUTCTime);
+
+/*****************************************************************************
+ * FUNCTION
+ * MTK_Sys_Get_EPO_File_Size
+ * DESCRIPTION
+ * Get the file size
+ * PARAMETERS
+ * None
+ * RETURNS
+ * File size
+ *****************************************************************************/
+MTK_UINT32 MTK_Sys_Get_EPO_File_Size(MTK_FILE hFile);
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* MTK_SYS_H */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/MTK_Type.h b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/MTK_Type.h
new file mode 100644
index 0000000..b704863
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/MTK_Type.h
@@ -0,0 +1,101 @@
+/***********************************************************************
+* This software/firmware and related documentation ("MediaTek Software")
+* are protected under relevant copyright laws. The information contained
+* herein is confidential and proprietary to MediaTek Inc. and/or its licensors.
+*
+* Without the prior written permission of MediaTek Inc. and/or its licensors,
+* any reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly prohibited.
+*
+* MediaTek Inc. (C) [2008]. All rights reserved.
+*
+*************************************************************************/
+//*****************************************************************************
+// [File] MTK_Type.h
+// [Version] v1.0
+// [Revision Date] 2008-03-31
+// [Author] YC Chien, yc.chien@mediatek.com, 21558
+// [Description]
+//*****************************************************************************
+
+#ifndef MTK_TYPE_H
+#define MTK_TYPE_H
+
+
+typedef unsigned char MTK_UINT8;
+typedef signed char MTK_INT8;
+
+typedef unsigned short int MTK_UINT16;
+typedef signed short int MTK_INT16;
+
+typedef unsigned int MTK_UINT32;
+typedef signed int MTK_INT32;
+
+typedef unsigned long MTK_UINT64;
+typedef signed long MTK_INT64;
+
+
+typedef enum
+{
+ MTK_FALSE = 0,
+ MTK_TRUE = 1
+} MTK_BOOL;
+
+typedef unsigned long MTK_FILE;
+
+typedef enum
+{
+ MTK_FS_READ = 0, // open file for reading (r)
+ MTK_FS_WRITE, // create file for writing, discard previous contents if any (w)
+ MTK_FS_APPEND, // open or create file for writing at end of file (a)
+ MTK_FS_RW, // open file for reading and writing (r+)
+ MTK_FS_RW_DISCARD, // create file for reading and writing, discard previous contents if any (w+)
+ MTK_FS_RW_APPEND // open or create file for reading and writing at end of file (a+)
+} MTK_FMODE;
+
+typedef enum
+{
+ MTK_FS_SEEK_SET = 0, // seek from beginning of file
+ MTK_FS_SEEK_CUR, // seek from current position
+ MTK_FS_SEEK_END // seek from end of file
+} MTK_FSEEK;
+
+typedef struct _MTK_TIME
+{
+ MTK_UINT16 Year;
+ MTK_UINT16 Month;
+ MTK_UINT16 Day;
+ MTK_UINT16 Hour;
+ MTK_UINT16 Min;
+ MTK_UINT16 Sec;
+ MTK_UINT16 Msec;
+} MTK_TIME;
+
+typedef enum
+{
+ HSDBGT_INIT = 0,
+ HSDBGT_LIB,
+ HSDBGT_KER,
+ HSDBGT_CAL,
+ HSDBGT_SYS,
+ HSDBGT_COMM,
+ HSDBGT_MSG,
+ HSDBGT_STR,
+ HSDBGT_MEM,
+ HSDBGT_ALL,
+ HSDBGT_END
+} MTK_DEBUG_TYPE;
+
+typedef enum
+{
+ HSDBGL_NONE = 0,
+ HSDBGL_ERR,
+ HSDBGL_WRN,
+ HSDBGL_INFO1,
+ HSDBGL_END
+} MTK_DEBUG_LEVEL;
+
+#define MTK_BEE_VOID void
+#define MTK_BEE_INT int
+
+#endif /* MTK_TYPE_H */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/SUPL_encryption.h b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/SUPL_encryption.h
new file mode 100644
index 0000000..dc79a90
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/SUPL_encryption.h
@@ -0,0 +1,32 @@
+/***********************************************************************
+* This software/firmware and related documentation ("MediaTek Software")
+* are protected under relevant copyright laws. The information contained
+* herein is confidential and proprietary to MediaTek Inc. and/or its licensors.
+*
+* Without the prior written permission of MediaTek Inc. and/or its licensors,
+* any reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly prohibited.
+*
+* MediaTek Inc. (C) [2008]. All rights reserved.
+*
+*************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * SUPL_encryption.h
+ *
+ * Description:
+ * ------------
+ * Prototype of encryption/decryption function for SUPL PMTK command
+ *
+ ****************************************************************************/
+
+#ifndef SUPL_ENCRYPTION_H
+#define SUPL_ENCRYPTION_H
+
+int SUPL_encrypt(unsigned char *plain, unsigned char *cipher, unsigned int length);
+int SUPL_decrypt(unsigned char *plain, unsigned char *cipher, unsigned int length);
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/agps_agent.h b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/agps_agent.h
new file mode 100644
index 0000000..c3f4edd
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/agps_agent.h
@@ -0,0 +1,331 @@
+/***********************************************************************
+* This software/firmware and related documentation ("MediaTek Software")
+* are protected under relevant copyright laws. The information contained
+* herein is confidential and proprietary to MediaTek Inc. and/or its licensors.
+*
+* Without the prior written permission of MediaTek Inc. and/or its licensors,
+* any reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly prohibited.
+*
+* MediaTek Inc. (C) [2008]. All rights reserved.
+*
+*************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * agps_agent.h
+ *
+ * Description:
+ * ------------
+ * Prototype of MTK AGPS Agent related functions
+ *
+ ****************************************************************************/
+
+#ifndef MTK_AGPS_AGENT_H
+#define MTK_AGPS_AGENT_H
+
+
+#if defined(WIN32) || defined(WINCE)
+#include "windows.h"
+#else
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#endif
+#include "mtk_gps_type.h"
+#include "MTK_Type.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Copy required parameters from MNL internal header files.
+ Remember to sync with MNL when any of these are changed. */
+
+#define PMTK_MAX_PKT_LENGTH 256
+#define MGlONID (24)
+
+// message between mnl and agps agent
+#define MTK_GPS_EVENT_BASE (0)
+#define MTK_GPS_MSG_BASE (MTK_GPS_EVENT_BASE+500)
+#define MTK_GPS_MNL_MSG (MTK_GPS_MSG_BASE+1) //msg to mnl
+#define MTK_GPS_MNL_EPO_MSG (MTK_GPS_MSG_BASE+2) //msg to agent epo module
+#define MTK_GPS_MNL_BEE_MSG (MTK_GPS_MSG_BASE+3) //msg to agent bee module
+#define MTK_GPS_MNL_SUPL_MSG (MTK_GPS_MSG_BASE+4) //msg to agent supl module
+//#define MTK_GPS_MNL_EPO_MSG (MTK_GPS_MSG_BASE+5) //msg to agent epo module
+#define MTK_GPS_MNL_BEE_IND_MSG (MTK_GPS_MSG_BASE+6) //msg to agent bee module
+//#define MTK_GPS_MNL_SUPL_MSG (MTK_GPS_MSG_BASE+7) //msg to agent supl module
+
+#define AGPS_AGENT_DEBUG
+
+//agps state machine
+#define AGENT_ST_IDLE (0)
+#define AGENT_ST_WORKING (1)
+
+#define AGENT_WORK_MODE_IDLE (0)
+#define AGENT_WORK_MODE_EPO (1)
+#define AGENT_WORK_MODE_BEE (2)
+#define AGENT_WORK_MODE_SUPL_SI (3)
+#define AGENT_WORK_MODE_SUPL_NI (4)
+#define AGENT_WORK_MODE_WIFI_AIDING (5)
+#define AGENT_WORK_MODE_CELLID_AIDING (6)
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_agent_init
+ * DESCRIPTION
+ * Initialize AGPS Agent module
+ * PARAMETERS
+ * void
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_init(UINT32 u4Param);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_proc
+ * DESCRIPTION
+ * process the message recv. from agps agent thread
+ * PARAMETERS
+ * prmsg [IN] the message recv. from agps agent thread
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_proc (MTK_GPS_AGPS_AGENT_MSG *prmsg);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_epo_init
+ * DESCRIPTION
+ * Initialize EPO module
+ * PARAMETERS
+ * path [IN] single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_epo_init(UINT8 *epo_file_name, UINT8 *epo_update_file_name);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_epo_uninit
+ * DESCRIPTION
+ * Un-initialize EPO module
+ * PARAMETERS
+ * void
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_epo_uninit();
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_qepo_init
+ * DESCRIPTION
+ * Initialize QEPO module
+ * PARAMETERS
+ * path [IN] single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_init(UINT8 *qepo_file_name, UINT8 *qepo_update_file_name);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_qepo_uninit
+ * DESCRIPTION
+ * Un-initialize QEPO module
+ * PARAMETERS
+ * path [IN] single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_uninit();
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_qepo_bd_init
+ * DESCRIPTION
+ * Initialize QEPO module
+ * PARAMETERS
+ * path [IN] single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_bd_init(UINT8 *qepo_file_name, UINT8 *qepo_update_file_name);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_qepo_bd_uninit
+ * DESCRIPTION
+ * Un-initialize QEPO module
+ * PARAMETERS
+ * path [IN] single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_bd_uninit();
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_qepo_ga_init
+ * DESCRIPTION
+ * Initialize QEPO module
+ * PARAMETERS
+ * path [IN] single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_ga_init(UINT8 *qepo_file_name, UINT8 *qepo_update_file_name);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_qepo_ga_uninit
+ * DESCRIPTION
+ * Un-initialize QEPO module
+ * PARAMETERS
+ * path [IN] single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_ga_uninit();
+
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_epo_read_gps_time
+ * DESCRIPTION
+ * Get start time/expire time of the EPO file [gps time]
+ * PARAMETERS
+ * pFile: EPO file fd
+ * [out]u4GpsSecs: GPS seconds
+ * RETURNS
+ * success: MTK_GPS_SUCCESS fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_epo_read_gps_time(UINT32 *u4GpsSecs_start, UINT32 *u4GpsSecs_expire);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_epo_read_utc_time
+ * DESCRIPTION
+ * Get start time/expire time of the EPO file [utc time]
+ * PARAMETERS
+ * pFile: EPO file fd
+ * [out]u4GpsSecs: GPS seconds
+ * RETURNS
+ * success: MTK_GPS_SUCCESS fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_epo_read_utc_time(time_t *uSecond_start, time_t *uSecond_expire);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_epo_extract_data
+ * DESCRIPTION
+ * Extract ading data from EPO file
+ * PARAMETERS
+ * [IN]u4GpsSec: segment time
+ * [out]epo_data: ading data
+ * RETURNS
+ * success: MTK_GPS_SUCCESS fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_epo_extract_data(UINT32 u4GpsSecs, MTK_GPS_PARAM_EPO_DATA_CFG *epo_data);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_epo_file_update
+ * DESCRIPTION
+ * Update the EPO file after the new Epo file download
+ * PARAMETERS
+ * None
+ * RETURNS
+ * success: MTK_GPS_SUCCESS fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_epo_file_update();
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_qepo_file_update
+ * DESCRIPTION
+ * Update the qEPO file after the new qEpo file download
+ * PARAMETERS
+ * None
+ * RETURNS
+ * success: MTK_GPS_SUCCESS fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_file_update();
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_qepo_bd_file_update
+ * DESCRIPTION
+ * Update the qEPO file after the new qEpo file download
+ * PARAMETERS
+ * None
+ * RETURNS
+ * success: MTK_GPS_SUCCESS fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_bd_file_update();
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_qepo_ga_file_update
+ * DESCRIPTION
+ * Update the qEPO file after the new qEpo file download
+ * PARAMETERS
+ * None
+ * RETURNS
+ * success: MTK_GPS_SUCCESS fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_ga_file_update();
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_qepo_get_rqst_time
+ * DESCRIPTION
+ * Get the GPS time and system time of the latest QEPO request
+ * PARAMETERS
+ * wn [OUT]:The week number of GPS time
+ * tow [OUT]:The Time Of Week of GPS time
+ * sys_time [OUT]:The system time of the latest QEPO request, the unit is second
+ * RETURNS
+ * success: MTK_GPS_SUCCESS fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_get_rqst_time(UINT16 *wn, UINT32 *tow, UINT32 *sys_time);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_qepo_file_verify
+
+ *****************************************************************************/
+
+INT32
+mtk_agps_agent_qepo_file_verify(MTK_FILE hFile, UINT8 *qepo_type, INT64 *file_size);
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* MTK_GPS_H */
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mnld2rtk_interface.h b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mnld2rtk_interface.h
new file mode 100644
index 0000000..5630e1f
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mnld2rtk_interface.h
@@ -0,0 +1,1635 @@
+/*
+ * Copyright (c) 2018 Qianxun SI Inc. All rights reserved.
+ *
+ * Revision: 1.6
+ */
+
+#ifndef _RTKSDK_SDK_H_
+#define _RTKSDK_SDK_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+#include "mtk_gps_type.h"
+
+/**
+ * Definition for SDK status.
+ */
+typedef enum {
+ RTKSDK_SDK_STATUS_UNKNOWN = 0,
+ RTKSDK_SDK_STATUS_SYSTEM_FAILURE = 1001,
+ RTKSDK_SDK_STATUS_NETWORK_UNAVAILABLE = 1002,
+ RTKSDK_SDK_STATUS_NETWORK_NO_PERMISSION = 1003,
+ RTKSDK_SDK_STATUS_CONFIG_ERROR = 1004,
+ RTKSDK_SDK_STATUS_INVALID_PARAM = 1005,
+ RTKSDK_SDK_STATUS_UNKNOWN_APPKEY = 1006,
+ RTKSDK_SDK_STATUS_NO_ACCESS = 1007,
+ RTKSDK_SDK_STATUS_SERVER_ABORT = 1008,
+
+ RTKSDK_SDK_STATUS_INIT_SUCCESS = 2000,
+ RTKSDK_SDK_STATUS_INIT_FAILED = 2001,
+ RTKSDK_SDK_STATUS_START_SUCCESS = 2002,
+ RTKSDK_SDK_STATUS_START_FAILED = 2003,
+ RTKSDK_SDK_STATUS_STOP_SUCCESS = 2004,
+ RTKSDK_SDK_STATUS_STOP_FAILED = 2005,
+ RTKSDK_SDK_STATUS_CLEANUP_SUCCESS = 2006,
+ RTKSDK_SDK_STATUS_CLEANUP_FAILED = 2007,
+
+ RTKSDK_SDK_STATUS_GNSS_RUNTIME_ERROR = 3000,
+ RTKSDK_SDK_STATUS_GNSS_LOST_POSITION = 3001,
+ RTKSDK_SDK_STATUS_GNSS_HAVE_POSITION = 3002,
+
+ RTKSDK_SDK_STATUS_FLP_IMU_FAULT_DETECT = 3500,
+ RTKSDK_SDK_STATUS_FLP_IMU_NOMOUNTED = 3501,
+ RTKSDK_SDK_STATUS_FLP_ODOMETER_INVALID = 3502,
+ RTKSDK_SDK_STATUS_FLP_PPS_INVLIAD = 3503,
+ RTKSDK_SDK_STATUS_FLP_GNSS_MEAS_DELAY = 3504,
+ RTKSDK_SDK_STATUS_FLP_IMU_BREAK = 3505,
+ RTKSDK_SDK_STATUS_FLP_GNSS_BREAK = 3506,
+
+ RTKSDK_SDK_STATUS_AUTH_PARAM_ERROR = 4000,
+ RTKSDK_SDK_STATUS_AUTH_ACCOUNT_NOT_EXIST = 4001,
+ RTKSDK_SDK_STATUS_AUTH_UNACTIVATED_ACCOUNT = 4002,
+ RTKSDK_SDK_STATUS_AUTH_NO_AVAILABLE_ACCOUNT = 4003,
+ RTKSDK_SDK_STATUS_AUTH_ACCOUNT_EXPIRED = 4004,
+ RTKSDK_SDK_STATUS_AUTH_ACCOUNT_TOEXPIRE = 4005,
+ RTKSDK_SDK_STATUS_AUTH_ACCOUNT_NEED_BIND = 4006,
+ RTKSDK_SDK_STATUS_AUTH_NO_VDR_PERMISSION = 4007,
+ RTKSDK_SDK_STATUS_AUTH_NO_PDR_PERMISSION = 4008,
+ RTKSDK_SDK_STATUS_AUTH_NO_AGNSS_PERMISSION = 4009,
+ RTKSDK_SDK_STATUS_AUTH_NO_RTK_PERMISSION = 4010,
+
+ RTKSDK_SDK_STATUS_AUTH_SUCCESS = 4011,
+ RTKSDK_SDK_STATUS_AUTH_NEED_MANUAL_ACTIVATION = 4012,
+ RTKSDK_SDK_STATUS_AUTH_NEED_TERMINAL_ACTIVATION = 4013,
+ RTKSDK_SDK_STATUS_AUTH_ACCOUNT_BEING_PROCESSED = 4014,
+ RTKSDK_SDK_STATUS_AUTH_ACCOUNT_FORBIDDEN = 4015,
+ RTKSDK_SDK_STATUS_AUTH_PARTIAL_CAPS_UNAVAILABLE = 4016,
+ RTKSDK_SDK_STATUS_AUTH_NO_CAPS_AVAILABLE = 4017,
+
+ RTKSDK_SDK_STATUS_OSS_CONNECT_SUCCESS = 5000,
+ RTKSDK_SDK_STATUS_OSS_CONNECT_FAIL = 5001,
+ RTKSDK_SDK_STATUS_OSS_CONNECT_TIMEOUT = 5002,
+ RTKSDK_SDK_STATUS_OSS_RECONNECTING = 5003,
+ RTKSDK_SDK_STATUS_OSS_DISCONNECT_SUCCESS = 5004,
+ RTKSDK_SDK_STATUS_OSS_DISCONNECT_FAIL = 5005,
+ RTKSDK_SDK_STATUS_OSS_CONNECTION_KICKOFF = 5006,
+
+ RTKSDK_SDK_STATUS_NOSR_REQUEST_RTK_SUCCESS = 6000,
+ RTKSDK_SDK_STATUS_NOSR_REQUEST_RTK_FAIL = 6001,
+ RTKSDK_SDK_STATUS_NOSR_CLOSE_RTK_SUCCESS = 6002,
+ RTKSDK_SDK_STATUS_NOSR_CLOSE_RTK_FAIL = 6003,
+ RTKSDK_SDK_STATUS_NOSR_RTK_UNAVAILABLE = 6004,
+ RTKSDK_SDK_STATUS_NOSR_GGA_OUT_OF_SERVICE_AREA = 6005,
+ RTKSDK_SDK_STATUS_NOSR_INVALID_GGA = 6006,
+ RTKSDK_SDK_STATUS_NOSR_KICKOFF = 6007,
+ RTKWX_SDK_STATUS_IAP_SUCCESS = 7000,
+ RTKWX_SDK_STATUS_IAP_FAIL = 7001,
+ RTKWX_SDK_STATUS_IAP_UPDATING = 7002,
+ RTKWX_SDK_STATUS_IAP_TIMEOUT = 7003
+} RTKSDKSdkStatus;
+
+/**
+ * Definition for network status.
+ */
+typedef enum {
+ /**
+ * unknown network, the initial value.
+ */
+ RTKSDK_NET_TYPE_UNKNOWN,
+ /**
+ * none network.
+ */
+ RTKSDK_NET_TYPE_NONETWORK,
+ /**
+ * wifi network.
+ */
+ RTKSDK_NET_TYPE_WIFI,
+ /**
+ * gsm network.
+ */
+ RTKSDK_NET_TYPE_GSM
+} RTKSDKNetworkStatus;
+
+/**
+ * Definition for position mode.
+ */
+typedef enum {
+ /**
+ * Positioning with RTK service.
+ */
+ RTKSDK_POS_MODE_RTK = 1,
+ /**
+ * Positioning with RTK + DR services.
+ */
+ RTKSDK_POS_MODE_RTK_DR = 2,
+ RTKSDK_POS_MODE_CHIP = 3
+} RTKSDKPosMode;
+
+/**
+ * Aiding data type(s) to delete
+ */
+typedef unsigned short RTKGNSSAidingData;
+#define RTKSDK_GNSS_DEL_EPHEMERIS 0x0001
+#define RTKSDK_GNSS_DEL_ALMANAC 0x0002
+#define RTKSDK_GNSS_DEL_POSITION 0x0004
+#define RTKSDK_GNSS_DEL_TIME 0x0008
+#define RTKSDK_GNSS_DEL_IONO 0x0010
+#define RTKSDK_GNSS_DEL_UTC 0x0020
+#define RTKSDK_GNSS_DEL_HEALTH 0x0040
+#define RTKSDK_GNSS_DEL_SVDIR 0x0080
+#define RTKSDK_GNSS_DEL_SVSTEER 0x0100
+#define RTKSDK_GNSS_DEL_SADATA 0x0200
+#define RTKSDK_GNSS_DEL_RTI 0x0400
+#define RTKSDK_GNSS_DEL_CELLDB_INFO 0x8000
+#define RTKSDK_GNSS_DEL_ALL 0xFFFF
+
+
+/* Application scenarios */
+typedef unsigned char RTKGnssApplyScene;
+#define RTKSDK_GNSS_APPLY_SCENE_ANYWHERE 0 /* for anywhere */
+#define RTKSDK_GNSS_APPLY_SCENE_AUTOROOF 1 /* on the roof of auto */
+#define RTKSDK_GNSS_APPLY_SCENE_AUTOINSIDE 2 /* inside the auto */
+#define RTKSDK_GNSS_APPLY_SCENE_BIKE 3 /* share bike */
+#define RTKSDK_GNSS_APPLY_SCENE_CAMERA 4 /* monitor camera */
+#define RTKSDK_GNSS_APPLY_SCENE_WATCH 5 /* Watch */
+
+
+/*Flags to indicate logmask.*/
+typedef unsigned int RTKSDKLogMask;
+/*LOG enable flag. */
+/*Disable all kinds of logs*/
+#define RTKSDK_LOG_MASK_OFF 0
+/*NOTE: This is Special, it means enable all kinds of logs*/
+#define RTKSDK_LOG_MASK_ON 1
+/*Enable basic debug log*/
+#define RTKSDK_LOG_MASK_DEBUG 0x04
+/*Enable Pedatain for rtk playback, it needs more space*/
+#define RTKSDK_LOG_MASK_ALGO 0x08
+/*Enable NMEA Files for statistical accuracy*/
+#define RTKSDK_LOG_MASK_NMEA 0x10
+/*Enable Raw Measurement Data*/
+#define RTKSDK_LOG_MASK_RAWX 0x20
+/*Enable algo_nmea for DR playback, it needs more space*/
+#define RTKSDK_LOG_MASK_ALGO_DR 0x40
+
+/* Authentication mode */
+typedef unsigned char RTKSDKAuthMode;
+#define RTKSDK_AUTH_MODE_APPKEY 0 /* authenticate by application key */
+#define RTKSDK_AUTH_MODE_DSK 1 /* authenticate by device service key */
+
+/**
+ * Configuration of SDK server info.
+ */
+typedef struct {
+ size_t size;
+ char auth_server[64];
+ unsigned short auth_port;
+} RTKSDKServerConfig;
+
+/**
+ * Represent the SDK configuration.
+ */
+typedef struct {
+ size_t size;
+ /**
+ * Authentication mode.
+ */
+ RTKSDKAuthMode auth_mode;
+ /**
+ * Refer to authencation mode.
+ * Application unique identity for RTK_AUTH_MODE_APPKEY.
+ * Device service key for RTK_AUTH_MODE_DSK.
+ */
+ char app_key[32];
+ /**
+ * Refer to authencation mode.
+ * Secret for corresponding key.
+ */
+ char app_secret[128];
+ /**
+ * Device id, UUID.
+ */
+ char device_id[64];
+ /**
+ * Device type.
+ */
+ char device_type[64];
+ /**
+ * SDK working directoy.
+ */
+ char root_dir[256];
+
+ /**
+ * LOG enable flag, please refer to RTKSDKLogMask
+ */
+ RTKSDKLogMask log_enable;
+
+ /**
+ * Separate log directoy if needed, otherwise logs also stored in the root_dir.
+ */
+ char log_dir[256];
+
+ /**
+ * The dir to create AF_UNIX socket used by RTK, the dir must have all permissions(RWX).
+ */
+ char socket_dir[256];
+
+ /**
+ * The path & filename of RTK's configurate file as RTK supply for,
+ * since many of customers wanna to change the path.
+ * Notice, the path MUST contain the filename,etc: "/etc/testCfg.ini".
+ */
+ char cfg_filename[256];
+
+ /**
+ * see 'Application scenarios'.
+ */
+ RTKGnssApplyScene apply_scenario;
+
+ /**
+ * Configuration of SDK server info.
+ */
+ RTKSDKServerConfig server_config;
+} RTKSDKSdkConfig;
+
+
+/* Fusion position flag */
+typedef unsigned char RTKGnssPosFlag;
+#define POS_FUSION_FLAG_UNAVAILABLE 0
+#define POS_FUSION_FLAG_GNSSONLY 1
+#define POS_FUSION_FLAG_DGNSS 2
+#define POS_FUSION_FLAG_RTK_FIX 4
+#define POS_FUSION_FLAG_RTK_FLOAT 5
+#define POS_FUSION_FLAG_FUSION 6
+#define POS_FUSION_FLAG_DR 7
+#define POS_FUSION_FLAG_CHIP 8
+#define POS_FUSION_FLAG_CHIP_FUSION 9
+#define POS_FUSION_FLAG_PPP 10
+#define POS_FUSION_FLAG_BT 11
+#define POS_FUSION_FLAG_WIFI 12
+#define POS_FUSION_FLAG_GNSSONLY_FUSION 13
+#define POS_FUSION_FLAG_RTK_FUSION 14
+
+typedef unsigned long long RTKGnssUtcTime;
+
+/* Pos confidence flag*/
+typedef unsigned int RTKGnssConfidenceFlag;
+#define POS_CONFIDENCE_FLAG_INVALID 0
+#define POS_CONFIDENCE_FLAG_GNSSONLY 1
+#define POS_CONFIDENCE_FLAG_DGNSS 2
+#define POS_CONFIDENCE_FLAG_RTK_FIX 4
+#define POS_CONFIDENCE_FLAG_RTK_FLOAT 5
+#define POS_CONFIDENCE_FLAG_DR 60
+#define POS_CONFIDENCE_FLAG_GNSS_FUSION 61
+#define POS_CONFIDENCE_FLAG_RTK_FIX_FUSION 64
+#define POS_CONFIDENCE_FLAG_RTK_FLOAT_FUSION 65
+
+typedef struct {
+ RTKGnssConfidenceFlag conf_type;
+ float conf_param_68[3]; /* 68% N/E/U confidence */
+ float conf_param_95[3]; /* 95% N/E/U confidence */
+ float conf_param_99[3]; /* 99.9% N/E/U confidence */
+} RTKSDKGnssConfidenceParams;
+
+
+typedef unsigned int RTKSDKReportFreq;
+#define RTKSDK_REPORT_FREQ_0_1_HZ 1
+#define RTKSDK_REPORT_FREQ_0_2_HZ 2
+#define RTKSDK_REPORT_FREQ_1_HZ 3
+#define RTKSDK_REPORT_FREQ_5_HZ 4
+#define RTKSDK_REPORT_FREQ_10_HZ 5
+#define RTKSDK_IOCTL_CMD_IMU_RATE 1
+typedef int RTKSDKIMURate;
+#define RTKSDK_IMU_RATE_0_HZ 0
+#define RTKSDK_IMU_RATE_1_HZ 1
+#define RTKSDK_IMU_RATE_2_HZ 2
+#define RTKSDK_IMU_RATE_5_HZ 5
+#define RTKSDK_IMU_RATE_10_HZ 10
+#define RTKSDK_IMU_RATE_25_HZ 25
+#define RTKSDK_IMU_RATE_50_HZ 50
+
+/**
+ *Set the extra device type
+ */
+#define RTKSDK_IOCTL_CMD_SET_EXT_DEVTYPE 2
+
+/**
+ * IOCTL TABLE
+ *
+ * CMD DATA_TYPE COMMENTS
+ * RTKSDK_IOCTL_CMD_IMU_RATE RTKSDKIMURate configure the output rate(0/1/2/5/10/25/50 HZ) of WZIMU info.
+ * RTKSDKIMURate rate = RTKSDK_IMU_RATE_1_HZ;
+ * int len = sizeof(RTKSDKIMURate);
+ * ioctl(RTKSDK_IOCTL_CMD_IMU_RATE, (void *)&rate, (int *)&len));
+ *
+ */
+
+
+/**
+ * Represent the GNSS location.
+ */
+typedef struct {
+ /**
+ * Set to sizeof(RTKSDKGnssLocation)
+ */
+ size_t size;
+ /**
+ * Position fusion flag
+ */
+ RTKGnssPosFlag posflag;
+ /**
+ * Represents latitude in degrees.
+ */
+ double latitude;
+ /**
+ * Represents longitude in degrees.
+ */
+ double longitude;
+ /**
+ * Represents altitude in meters above the WGS 84 reference ellipsoid.
+ */
+ double altitude;
+ /**
+ * Represents speed in meters per second.
+ */
+ float speed;
+ /**
+ * Represents heading in degrees.
+ */
+ float bearing;
+ /**
+ * Represents expected accuracy in meters.
+ */
+ float accuracy;
+ /**
+ * Timestamp for the location fix.
+ */
+ RTKGnssUtcTime timestamp;
+ /**
+ * Average CN0
+ */
+ float avg_cno;
+ /**
+ * HDOP
+ */
+ float hdop;
+ /**
+ * Number of satellites used for positioning.
+ */
+ unsigned char sat_used;
+ /**
+ * Confidence coefficient.
+ */
+ RTKSDKGnssConfidenceParams confidence_param;
+} RTKSDKGnssLocation;
+
+#define RTK_SENSOR_TYPE_LEN 64
+/**
+ * Represent DR configuration.
+ */
+typedef struct {
+ /**
+ * Set to sizeof(RTKSDKSensorConfig).
+ */
+ size_t size;
+ /**
+ * Gyro type
+ */
+ char gyro_type[RTK_SENSOR_TYPE_LEN];
+ /**
+ * Accelerometer type
+ */
+ char acce_type[RTK_SENSOR_TYPE_LEN];
+ /**
+ * Magnetometer type
+ */
+ char magn_type[RTK_SENSOR_TYPE_LEN];
+ /**
+ * Barometer model
+ */
+ char press_type[RTK_SENSOR_TYPE_LEN];
+ /**
+ * Odometer type
+ */
+ char odom_type[RTK_SENSOR_TYPE_LEN];
+ /**
+ * Thermometer type
+ */
+ char temp_type[RTK_SENSOR_TYPE_LEN];
+ /**
+ * Four wheel speed type
+ */
+ char ospd_type[RTK_SENSOR_TYPE_LEN];
+} RTKSDKSensorConfig;
+
+typedef struct {
+ unsigned long long TimeStamp;
+ unsigned short int CheckSum;
+ unsigned short int MatchConfidence;
+ unsigned short int RoadID;
+ unsigned short int GridID;
+ unsigned char RoadType; // 0:normal 1:channel 2:tunnel, 3:bridge 4:near IC
+ unsigned char RoadClass;
+ signed short int NorthDis; //m
+ signed short int EastDis; //m
+ unsigned short int LinkLength1; //m
+ unsigned short int LinkLength2; //m
+ unsigned short int LinkDirection; // degree
+ double MatchLat; // degree
+ double MatchLon; // degree;
+ unsigned char MatchType;
+ signed char State;
+ unsigned long long Reserved; // 0:unknown, 1:from server 2:from local 3:local ramp entry 4: local ramp exit
+ float MatchDistance; //m
+ signed short int Fence; // 0:unsure, 2: ele road
+ unsigned int ADCode; //000000
+ float RoadSpeedLimit; //meters/s
+ float RoadHeading; // road heading, from -180~180
+ unsigned short int MapMatchedRamp;
+ int NearMap; // 0-NO, !0-YES
+} RTKSDKMapMatchingPara;
+
+typedef enum {
+ RTK_SENSOR_TYPE_ACCEL = 0X0002,
+ RTK_SENSOR_TYPE_MAGN = 0X0004,
+ RTK_SENSOR_TYPE_PRESS = 0X0008,
+ RTK_SENSOR_TYPE_GYRO = 0X0010,
+ RTK_SENSOR_TYPE_TEMP = 0X0020,
+ RTK_SENSOR_TYPE_ODOM = 0X0040,
+ RTK_SENSOR_TYPE_4SPD = 0X0080
+} RTK_SENSOR_TYPE;
+
+typedef struct {
+ unsigned int m_Mask; /* valid sensor mask */
+ unsigned long long m_Time; /* time */
+ float m_ARate[3]; /* angular rate in radius per second */
+ float m_SForce[3]; /* specific force in m/s2 */
+ float m_Mag[3]; /* mag field in gauss */
+ float m_Baro; /* baro in Pa */
+ float m_Temp; /* temperature in celsius */
+ float m_Speed; /* auto speed in m/s */
+ float m_4Spd[5]; /* steering and 4 speed of front-left, front-right, rear-left, rear-right respectively */
+} RTKSDKSensorData;
+
+typedef struct {
+ int Valid; // 0 means invalid; Non-zero means valid
+ unsigned long long TimeStamp;
+} RTKSDKGNSSPPS;
+
+typedef struct {
+ int Valid; // 0 means invalid; Non-zero means valid
+ unsigned long long TimeStamp;
+ float Orientation;
+ float BaseLen;
+} RTKSDKGNSSOrt;
+
+/**
+ * Represent Lever-arm configuration.
+ */
+typedef struct {
+ /**
+ * Set to sizeof(RTKSDKLeverArmParams).
+ */
+ size_t size;
+ /**
+ * Lever-arm of GNSS antenna and IMU
+ */
+ float gnss2imu[3];
+ /**
+ * Lever-arm of IMU and the middle of vehicle's rear wheels
+ */
+ float imu2rearmiddle[3];
+ /**
+ * misalignment angle of IMU and vehicle
+ */
+ float imu2vehicle[3];
+ /**
+ * REAR Wheel Track
+ */
+ float wheeltrack;
+} RTKSDKLeverArmParams;
+
+/** Maximum number of Measurements in gnss_measurement_callback(). */
+#define RTKSDK_GNSS_MAX_MEASUREMENT 128
+/** Maximum number of frequency in each GNSS system that is used in position calculation. */
+#define RTKSDK_MAX_FREQ_NUM 1
+
+/**
+ * Flags to indicate what fields in RTKSDKGnssMeasurement are valid.
+ */
+typedef uint32_t RTKSDKGnssMeasurementFlags;
+/** A valid 'snr' is stored in the data structure. */
+#define RTKSDK_GNSS_MEASUREMENT_HAS_SNR (1<<0)
+/** A valid 'elevation' is stored in the data structure. */
+#define RTKSDK_GNSS_MEASUREMENT_HAS_ELEVATION (1<<1)
+/** A valid 'elevation uncertainty' is stored in the data structure. */
+#define RTKSDK_GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY (1<<2)
+/** A valid 'azimuth' is stored in the data structure. */
+#define RTKSDK_GNSS_MEASUREMENT_HAS_AZIMUTH (1<<3)
+/** A valid 'azimuth uncertainty' is stored in the data structure. */
+#define RTKSDK_GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY (1<<4)
+/** A valid 'pseudorange' is stored in the data structure. */
+#define RTKSDK_GNSS_MEASUREMENT_HAS_PSEUDORANGE (1<<5)
+/** A valid 'pseudorange uncertainty' is stored in the data structure. */
+#define RTKSDK_GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY (1<<6)
+/** A valid 'carrier frequency' is stored in the data structure. */
+#define RTKSDK_GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9)
+/** A valid 'carrier cycles' is stored in the data structure. */
+#define RTKSDK_GNSS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10)
+/** A valid 'carrier phase' is stored in the data structure. */
+#define RTKSDK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11)
+/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define RTKSDK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12)
+/** A valid 'doppler shift' is stored in the data structure. */
+#define RTKSDK_GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT (1<<15)
+/** A valid 'doppler shift uncertainty' is stored in the data structure. */
+#define RTKSDK_GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY (1<<16)
+/** A valid 'used in fix' flag is stored in the data structure. */
+#define RTKSDK_GNSS_MEASUREMENT_HAS_USED_IN_FIX (1<<17)
+
+
+/**
+ * Constellation type of GnssSvInfo
+ */
+typedef uint8_t RTKSDKGnssConstellationType;
+#define RTKSDK_GNSS_CONSTELLATION_UNKNOWN (0)
+#define RTKSDK_GNSS_CONSTELLATION_GPS (1)
+#define RTKSDK_GNSS_CONSTELLATION_SBAS (2)
+#define RTKSDK_GNSS_CONSTELLATION_GLONASS (3)
+#define RTKSDK_GNSS_CONSTELLATION_QZSS (4)
+#define RTKSDK_GNSS_CONSTELLATION_BEIDOU (5)
+#define RTKSDK_GNSS_CONSTELLATION_GALILEO (6)
+
+typedef uint16_t RTKSDKGnssNavigationMessageType;
+#define RTKSDK_GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN 0
+/** GPS L1 C/A message contained in the structure. */
+#define RTKSDK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA 0x0101
+/** GPS L2-CNAV message contained in the structure. */
+#define RTKSDK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV 0x0102
+/** GPS L5-CNAV message contained in the structure. */
+#define RTKSDK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV 0x0103
+/** GPS CNAV-2 message contained in the structure. */
+#define RTKSDK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2 0x0104
+/** Glonass L1 CA message contained in the structure. */
+#define RTKSDK_GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA 0x0301
+/** Beidou D1 message contained in the structure. */
+#define RTKSDK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1 0x0501
+/** Beidou D2 message contained in the structure. */
+#define RTKSDK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2 0x0502
+/** Galileo I/NAV message contained in the structure. */
+#define RTKSDK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I 0x0601
+/** Galileo F/NAV message contained in the structure. */
+#define RTKSDK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F 0x0602
+
+/**
+ * Flags indicating the GNSS measurement state.
+ *
+ * The expected behavior here is for GPS HAL to set all the flags that applies.
+ * For example, if the state for a satellite is only C/A code locked and bit
+ * synchronized, and there is still millisecond ambiguity, the state should be
+ * set as:
+ *
+ * RTKSDK_GNSS_MEASUREMENT_STATE_CODE_LOCK | RTKSDK_GNSS_MEASUREMENT_STATE_BIT_SYNC |
+ * RTKSDK_GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS
+ *
+ * If GNSS is still searching for a satellite, the corresponding state should be
+ * set to RTKSDK_GNSS_MEASUREMENT_STATE_UNKNOWN(0).
+ */
+typedef uint32_t RTKSDKGnssMeasurementState;
+#define RTKSDK_GNSS_MEASUREMENT_STATE_UNKNOWN (0)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_SYMBOL_SYNC (1<<5)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC (1<<6)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED (1<<7)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC (1<<8)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC (1<<9)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK (1<<10)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK (1<<11)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC (1<<12)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_SBAS_SYNC (1<<13)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_TOW_KNOWN (1<<14)
+#define RTKSDK_GNSS_MEASUREMENT_STATE_GLO_TOD_KNOWN (1<<15)
+
+
+/**
+ * Flags indicating the Accumulated Delta Range's states.
+ */
+typedef uint16_t RTKSDKGnssAccumulatedDeltaRangeState;
+#define RTKSDK_GNSS_ADR_STATE_UNKNOWN (0)
+#define RTKSDK_GNSS_ADR_STATE_VALID (1<<0)
+#define RTKSDK_GNSS_ADR_STATE_RESET (1<<1)
+#define RTKSDK_GNSS_ADR_STATE_CYCLE_SLIP (1<<2)
+#define RTKSDK_GNSS_ADR_STATE_HALF_CYCLE_RESOLVED (1<<3)
+#define RTKSDK_GNSS_ADR_STATE_HALF_CYCLE_REPORTED (1<<4)
+
+
+/**
+ * Enumeration of available values for the GNSS Measurement's multipath
+ * indicator.
+ */
+typedef uint8_t RTKSDKGnssMultipathIndicator;
+/** The indicator is not available or unknown. */
+#define RTKSDK_GNSS_MULTIPATH_INDICATOR_UNKNOWN (0)
+/** The measurement is indicated to be affected by multipath. */
+#define RTKSDK_GNSS_MULTIPATH_INDICATOR_PRESENT (1)
+/** The measurement is indicated to be not affected by multipath. */
+#define RTKSDK_GNSS_MULTIPATH_INDICATOR_NOT_PRESENT (2)
+
+/**
+ * Flags to indicate what fields in RTKSDKGnssClock are valid.
+ */
+typedef uint16_t RTKSDKGnssClockFlags;
+/** A valid 'leap second' is stored in the data structure. */
+#define RTKSDK_GNSS_CLOCK_HAS_LEAP_SECOND (1<<0)
+/** A valid 'time uncertainty' is stored in the data structure. */
+#define RTKSDK_GNSS_CLOCK_HAS_TIME_UNCERTAINTY (1<<1)
+/** A valid 'full bias' is stored in the data structure. */
+#define RTKSDK_GNSS_CLOCK_HAS_FULL_BIAS (1<<2)
+/** A valid 'bias' is stored in the data structure. */
+#define RTKSDK_GNSS_CLOCK_HAS_BIAS (1<<3)
+/** A valid 'bias uncertainty' is stored in the data structure. */
+#define RTKSDK_GNSS_CLOCK_HAS_BIAS_UNCERTAINTY (1<<4)
+/** A valid 'drift' is stored in the data structure. */
+#define RTKSDK_GNSS_CLOCK_HAS_DRIFT (1<<5)
+/** A valid 'drift uncertainty' is stored in the data structure. */
+#define RTKSDK_GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY (1<<6)
+
+
+/**
+ * Status of Navigation Message
+ * When a message is received properly without any parity error in its navigation words, the
+ * status should be set to NAV_MESSAGE_STATUS_PARITY_PASSED. But if a message is received
+ * with words that failed parity check, but GPS is able to correct those words, the status
+ * should be set to NAV_MESSAGE_STATUS_PARITY_REBUILT.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+typedef uint16_t RTKSDKNavigationMessageStatus;
+#define RTKSDK_NAV_MESSAGE_STATUS_UNKONW (0)
+#define RTKSDK_NAV_MESSAGE_STATUS_PARITY_PASSED (1<<0)
+#define RTKSDK_NAV_MESSAGE_STATUS_PARITY_REBUILT (1<<1)
+
+/**
+ * Represents an estimate of the GNSS clock time.
+ */
+typedef struct {
+ /** set to sizeof(RTKSDKGnssClock) */
+ size_t size;
+
+ /**
+ * A set of flags indicating the validity of the fields in this data
+ * structure.
+ */
+ RTKSDKGnssClockFlags flags;
+
+ /**
+ * Leap second data.
+ * The sign of the value is defined by the following equation:
+ * utc_time_ns = time_ns - (full_bias_ns + bias_ns) - leap_second *
+ * 1,000,000,000
+ *
+ * If the data is available 'flags' must contain RTKSDK_GNSS_CLOCK_HAS_LEAP_SECOND.
+ */
+ int16_t leap_second;
+
+ /**
+ * The GNSS receiver internal clock value. This is the local hardware clock
+ * value.
+ *
+ * For local hardware clock, this value is expected to be monotonically
+ * increasing while the hardware clock remains power on. (For the case of a
+ * HW clock that is not continuously on, see the
+ * hw_clock_discontinuity_count field). The receiver's estimate of GPS time
+ * can be derived by substracting the sum of full_bias_ns and bias_ns (when
+ * available) from this value.
+ *
+ * This GPS time is expected to be the best estimate of current GPS time
+ * that GNSS receiver can achieve.
+ *
+ * Sub-nanosecond accuracy can be provided by means of the 'bias_ns' field.
+ * The value contains the 'time uncertainty' in it.
+ *
+ * This field is mandatory.
+ */
+ int64_t time_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain
+ * RTKSDK_GNSS_CLOCK_HAS_TIME_UNCERTAINTY. This value is effectively zero (it is
+ * the reference local clock, by which all other times and time
+ * uncertainties are measured.) (And thus this field can be not provided,
+ * per RTKSDK_GNSS_CLOCK_HAS_TIME_UNCERTAINTY flag, or provided & set to 0.)
+ */
+ double time_uncertainty_ns;
+
+ /**
+ * The difference between hardware clock ('time' field) inside GPS receiver
+ * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
+ *
+ * The sign of the value is defined by the following equation:
+ * local estimate of GPS time = time_ns - (full_bias_ns + bias_ns)
+ *
+ * This value is mandatory if the receiver has estimated GPS time. If the
+ * computed time is for a non-GPS constellation, the time offset of that
+ * constellation to GPS has to be applied to fill this value. The error
+ * estimate for the sum of this and the bias_ns is the bias_uncertainty_ns,
+ * and the caller is responsible for using this uncertainty (it can be very
+ * large before the GPS time has been solved for.) If the data is available
+ * 'flags' must contain RTKSDK_GNSS_CLOCK_HAS_FULL_BIAS.
+ */
+ int64_t full_bias_ns;
+
+ /**
+ * Sub-nanosecond bias.
+ * The error estimate for the sum of this and the full_bias_ns is the
+ * bias_uncertainty_ns
+ *
+ * If the data is available 'flags' must contain RTKSDK_GNSS_CLOCK_HAS_BIAS. If GPS
+ * has computed a position fix. This value is mandatory if the receiver has
+ * estimated GPS time.
+ */
+ double bias_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the local estimate of GPS time (clock
+ * bias) in nanoseconds. The uncertainty is represented as an absolute
+ * (single sided) value.
+ *
+ * If the data is available 'flags' must contain
+ * RTKSDK_GNSS_CLOCK_HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+ * has estimated GPS time.
+ */
+ double bias_uncertainty_ns;
+
+ /**
+ * The clock's drift in nanoseconds (per second).
+ *
+ * A positive value means that the frequency is higher than the nominal
+ * frequency, and that the (full_bias_ns + bias_ns) is growing more positive
+ * over time.
+ *
+ * The value contains the 'drift uncertainty' in it.
+ * If the data is available 'flags' must contain RTKSDK_GNSS_CLOCK_HAS_DRIFT.
+ *
+ * This value is mandatory if the receiver has estimated GNSS time
+ */
+ double drift_nsps;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available 'flags' must contain
+ * RTKSDK_GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY. If GPS has computed a position fix this
+ * field is mandatory and must be populated.
+ */
+ double drift_uncertainty_nsps;
+
+ /**
+ * When there are any discontinuities in the HW clock, this field is
+ * mandatory.
+ *
+ * A "discontinuity" is meant to cover the case of a switch from one source
+ * of clock to another. A single free-running crystal oscillator (XO)
+ * should generally not have any discontinuities, and this can be set and
+ * left at 0.
+ *
+ * If, however, the time_ns value (HW clock) is derived from a composite of
+ * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+ * restarted, then this value shall be incremented each time a discontinuity
+ * occurs. (E.g. this value may start at zero at device boot-up and
+ * increment each time there is a change in clock continuity. In the
+ * unlikely event that this value reaches full scale, rollover (not
+ * clamping) is required, such that this value continues to change, during
+ * subsequent discontinuity events.)
+ *
+ * While this number stays the same, between RTKGnssClock reports, it can be
+ * safely assumed that the time_ns value has been running continuously, e.g.
+ * derived from a single, high quality clock (XO like, or better, that's
+ * typically used during continuous GNSS signal sampling.)
+ *
+ * It is expected, esp. during periods where there are few GNSS signals
+ * available, that the HW clock be discontinuity-free as long as possible,
+ * as this avoids the need to use (waste) a GNSS measurement to fully
+ * re-solve for the GPS clock bias and drift, when using the accompanying
+ * measurements, from consecutive RTKSDKGnssData reports.
+ */
+ uint32_t hw_clock_discontinuity_count;
+
+ /**
+ * system time tag, millisecond since 1970/1/1 locally.
+ */
+ int64_t time_stamp;
+
+} RTKSDKGnssClock;
+
+typedef struct {
+ /**
+ * Time offset at which the measurement was taken in nanoseconds.
+ * The reference receiver's time is specified by RTKSDKGnssData::clock::time_ns and should be
+ * interpreted in the same way as indicated by GpsClock::type.
+ *
+ * The sign of time_offset_ns is given by the following equation:
+ * measurement time = RTKSDKGnssClock::time_ns + time_offset_ns
+ *
+ * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+ * This is a mandatory value.
+ */
+ double time_offset_ns;
+
+ /**
+ * Per satellite sync state. It represents the current sync state for the associated satellite.
+ * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+ *
+ * This is a mandatory value.
+ */
+ RTKSDKGnssMeasurementState state;
+
+ /**
+ * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+ * Ensure that this field is independent (see comment at top of
+ * RTKGnssMeasurement struct.)
+ *
+ * For GPS & QZSS, this is:
+ * Received GPS Time-of-Week at the measurement time, in nanoseconds.
+ * The value is relative to the beginning of the current GPS week.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range
+ * for this field can be:
+ * Searching : [ 0 ] : RTKSDK_GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : RTKSDK_GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync : [ 0 20ms ] : RTKSDK_GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe sync : [ 0 6s ] : RTKSDK_GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * TOW decoded : [ 0 1week ] : RTKSDK_GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * Note well: if there is any ambiguity in integer millisecond,
+ * RTKSDK_GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+ *
+ * This value must be populated if 'state' != RTKSDK_GNSS_MEASUREMENT_STATE_UNKNOWN.
+ *
+ * For Glonass, this is:
+ * Received Glonass time of day, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : RTKSDK_GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : RTKSDK_GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 10ms ] : RTKSDK_GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+ * Bit sync : [ 0 20ms ] : RTKSDK_GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * String sync : [ 0 2s ] : RTKSDK_GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC is set
+ * Time of day : [ 0 1day ] : RTKSDK_GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED is set
+ *
+ * For Beidou, this is:
+ * Received Beidou time of week, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : RTKSDK_GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock: [ 0 1ms ] : RTKSDK_GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync (D2): [ 0 2ms ] : RTKSDK_GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC is set
+ * Bit sync (D1): [ 0 20ms ] : RTKSDK_GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe (D2): [ 0 0.6s ] : RTKSDK_GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC is set
+ * Subframe (D1): [ 0 6s ] : RTKSDK_GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * Time of week : [ 0 1week ] : RTKSDK_GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * For Galileo, this is:
+ * Received Galileo time of week, at the measurement time in nanoseconds.
+ *
+ * E1BC code lock : [ 0 4ms ] : RTKSDK_GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK is set
+ * E1C 2nd code lock: [ 0 100ms ] :
+ * RTKSDK_GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is set
+ *
+ * E1B page : [ 0 2s ] : RTKSDK_GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC is set
+ * Time of week: [ 0 1week ] : RTKSDK_GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * For SBAS, this is:
+ * Received SBAS time, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite,
+ * valid range for this field can be:
+ * Searching : [ 0 ] : RTKSDK_GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock: [ 0 1ms ] : RTKSDK_GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 2ms ] : RTKSDK_GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+ * Message : [ 0 1s ] : RTKSDK_GNSS_MEASUREMENT_STATE_SBAS_SYNC is set
+ */
+ int64_t received_sv_time_in_ns;
+
+ /**
+ * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+ *
+ * This value must be populated if 'state' != RTKSDK_GNSS_MEASUREMENT_STATE_UNKNOWN.
+ */
+ int64_t received_sv_time_uncertainty_in_ns;
+
+ /**
+ * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+ * It contains the measured C/N0 value for the signal at the antenna port.
+ *
+ * This is a mandatory value.
+ */
+ double c_n0_dbhz;
+
+ /**
+ * Pseudorange rate at the timestamp in m/s. The correction of a given
+ * Pseudorange Rate value includes corrections for receiver and satellite
+ * clock frequency errors. Ensure that this field is independent (see
+ * comment at top of RTKGnssMeasurement struct.)
+ *
+ * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
+ * 'drift' field as well (When providing the uncorrected pseudorange rate, do not apply the
+ * corrections described above.)
+ *
+ * The value includes the 'pseudorange rate uncertainty' in it.
+ * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler
+ * shift' is given by the equation:
+ * pseudorange rate = -k * doppler shift (where k is a constant)
+ *
+ * This should be the most accurate pseudorange rate available, based on
+ * fresh signal measurements from this channel.
+ *
+ * It is mandatory that this value be provided at typical carrier phase PRR
+ * quality (few cm/sec per second of uncertainty, or better) - when signals
+ * are sufficiently strong & stable, e.g. signals from a GPS simulator at >=
+ * 35 dB-Hz.
+ */
+ double pseudorange_rate_mps;
+
+ /**
+ * 1-Sigma uncertainty of the pseudorange_rate_mps.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * This is a mandatory value.
+ */
+ double pseudorange_rate_uncertainty_mps;
+
+ /**
+ * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+ * (indicating loss of lock).
+ *
+ * This is a mandatory value.
+ */
+ RTKSDKGnssAccumulatedDeltaRangeState accumulated_delta_range_state;
+
+ /**
+ * Accumulated delta range since the last channel reset in meters.
+ * A positive value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+ * is given by the equation:
+ * accumulated delta range = -k * carrier phase (where k is a constant)
+ *
+ * This value must be populated if 'accumulated delta range state' != RTKSDK_GNSS_ADR_STATE_UNKNOWN.
+ * However, it is expected that the data is only accurate when:
+ * 'accumulated delta range state' == GPS_ADR_STATE_VALID.
+ */
+ double accumulated_delta_range_m;
+
+ /**
+ * 1-Sigma uncertainty of the accumulated delta range in meters.
+ * This value must be populated if 'accumulated delta range state' != RTKSDK_GNSS_ADR_STATE_UNKNOWN.
+ */
+ double accumulated_delta_range_uncertainty_m;
+
+ /**
+ * Best derived Pseudorange by the chip-set, in meters.
+ * The value contains the 'pseudorange uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain RTKSDK_GNSS_MEASUREMENT_HAS_PSEUDORANGE.
+ */
+ double pseudorange_m;
+
+ /**
+ * 1-Sigma uncertainty of the pseudorange in meters.
+ * The value contains the 'pseudorange' and 'clock' uncertainty in it.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain RTKSDK_GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY.
+ */
+ double pseudorange_uncertainty_m;
+
+ /**
+ * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+ * If the field is not set, the carrier frequency is assumed to be L1.
+ *
+ * If the data is available, 'flags' must contain
+ * RTKSDK_GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+ */
+ float carrier_frequency_hz;
+
+ /**
+ * The number of full carrier cycles between the satellite and the receiver.
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * Indications of possible cycle slips and resets in the accumulation of
+ * this value can be inferred from the accumulated_delta_range_state flags.
+ *
+ * If the data is available, 'flags' must contain
+ * RTKSDK_GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
+ */
+ int64_t carrier_cycles;
+
+ /**
+ * The RF phase detected by the receiver, in the range [0.0, 1.0].
+ * This is usually the fractional part of the complete carrier phase measurement.
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'carrier-phase uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain
+ * RTKSDK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE.
+ */
+ double carrier_phase;
+
+ /**
+ * 1-Sigma uncertainty of the carrier-phase.
+ * If the data is available, 'flags' must contain
+ * RTKSDK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+ */
+ double carrier_phase_uncertainty;
+
+ /**
+ * Doppler shift in Hz.
+ * A positive value indicates that the SV is moving toward the receiver.
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'doppler shift uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain RTKSDK_GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT.
+ */
+ double doppler_shift_hz;
+
+ /**
+ * 1-Sigma uncertainty of the doppler shift in Hz.
+ * If the data is available, 'flags' must contain RTKSDK_GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY.
+ */
+ double doppler_shift_uncertainty_hz;
+
+ /**
+ * An enumeration that indicates the 'multipath' state of the event.
+ *
+ * The multipath Indicator is intended to report the presence of overlapping
+ * signals that manifest as distorted correlation peaks.
+ *
+ * - if there is a distorted correlation peak shape, report that multipath
+ * is RTKSDK_GNSS_MULTIPATH_INDICATOR_PRESENT.
+ * - if there is not a distorted correlation peak shape, report
+ * RTKSDK_GNSS_MULTIPATH_INDICATOR_NOT_PRESENT
+ * - if signals are too weak to discern this information, report
+ * RTKSDK_GNSS_MULTIPATH_INDICATOR_UNKNOWN
+ *
+ * Example: when doing the standardized overlapping Multipath Performance
+ * test (3GPP TS 34.171) the Multipath indicator should report
+ * RTKSDK_GNSS_MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+ * contain multipath, and RTKSDK_GNSS_MULTIPATH_INDICATOR_NOT_PRESENT for those
+ * signals that are tracked and do not contain multipath.
+ */
+ RTKSDKGnssMultipathIndicator multipath_indicator;
+
+ /**
+ * Signal-to-noise ratio at correlator output in dB.
+ * If the data is available, 'flags' must contain RTKSDK_GNSS_MEASUREMENT_HAS_SNR.
+ * This is the power ratio of the "correlation peak height above the
+ * observed noise floor" to "the noise RMS".
+ */
+ double snr_db;
+
+ /**
+ * Loss of lock indicator.
+ */
+ int32_t LLI;
+
+} QZWZGnssChannelMeas;
+
+/**
+ * Represents a GNSS Measurement, it contains raw and computed information.
+ *
+ * Independence - All signal measurement information (e.g. sv_time,
+ * pseudorange_rate, multipath_indicator) reported in this struct should be
+ * based on GNSS signal measurements only. You may not synthesize measurements
+ * by calculating or reporting expected measurements based on known or estimated
+ * position, velocity, or time.
+ */
+typedef struct {
+ /** set to sizeof(RTKSDKGnssMeasurement) */
+ size_t size;
+
+ /** A set of flags indicating the validity of the fields in this data structure. */
+ RTKSDKGnssMeasurementFlags flags;
+
+ /**
+ * Pseudo-random number for the SV, or FCN/OSN number for Glonass. The
+ * distinction is made by looking at constellation field. Values should be
+ * in the range of:
+ *
+ * - GPS: 1-32
+ * - SBAS: 120-151, 183-192
+ * - GLONASS: 1-24, the orbital slot number (OSN), if known. Or, if not:
+ * 93-106, the frequency channel number (FCN) (-7 to +6) offset by + 100
+ * i.e. report an FCN of -7 as 93, FCN of 0 as 100, and FCN of +6 as 106.
+ * - QZSS: 193-200
+ * - Galileo: 1-36
+ * - Beidou: 1-37
+ */
+ int16_t svid;
+
+ /**
+ * Defines the constellation of the given SV. Value should be one of those
+ * GNSS_CONSTELLATION_* constants
+ */
+ RTKSDKGnssConstellationType constellation;
+
+ /**
+ * A set of bit-mask indicating the validity of parameter group of each
+ * frequency point. From low bit to high, corresponding to different GNSS system,
+ * each bit relates to L1, L2, L5 from GPS, or L1, L2, L3 from GLONASS, and so on.
+ */
+ uint8_t gnss_frequency_mask;
+
+
+ /**
+ * Elevation in degrees, the valid range is [-90, 90].
+ * The value contains the 'elevation uncertainty' in it.
+ * If the data is available, 'flags' must contain RTKSDK_GNSS_MEASUREMENT_HAS_ELEVATION.
+ */
+ double elevation_deg;
+
+ /**
+ * 1-Sigma uncertainty of the elevation in degrees, the valid range is [0, 90].
+ * The uncertainty is represented as the absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain RTKSDK_GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY.
+ */
+ double elevation_uncertainty_deg;
+
+ /**
+ * Azimuth in degrees, in the range [0, 360).
+ * The value contains the 'azimuth uncertainty' in it.
+ * If the data is available, 'flags' must contain RTKSDK_GNSS_MEASUREMENT_HAS_AZIMUTH.
+ * */
+ double azimuth_deg;
+
+ /**
+ * 1-Sigma uncertainty of the azimuth in degrees, the valid range is [0, 180].
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain RTKSDK_GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY.
+ */
+ double azimuth_uncertainty_deg;
+
+ /**
+ * Whether the GNSS represented by the measurement was used for computing the most recent fix.
+ * If the data is available, 'flags' must contain RTKSDK_GNSS_MEASUREMENT_HAS_USED_IN_FIX.
+ */
+ unsigned char used_in_fix;
+
+
+ /**
+ * 3-element array containing groups of paramters, each of which is specific to a GNSS
+ * frequency point. The validity of each group is masked by bit field in
+ * gnss_frequency_mask.
+ */
+ QZWZGnssChannelMeas channel_meas[RTKSDK_MAX_FREQ_NUM];
+
+ int32_t reserved1[4];
+
+ double reserved2[4];
+} RTKSDKGnssMeasurement;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+ /** set to sizeof(RTKSDKGnssData) */
+ size_t size;
+
+ /** Number of measurements. */
+ size_t measurement_count;
+
+ /** The array of measurements. */
+ RTKSDKGnssMeasurement measurements[RTKSDK_GNSS_MAX_MEASUREMENT];
+
+ /** The GPS clock time reading. */
+ RTKSDKGnssClock clock;
+} RTKSDKGnssData;
+
+/** Represents a GPS navigation message (or a fragment of it). */
+typedef struct {
+ /** set to sizeof(RTKGnssNavigationMessage) */
+ size_t size;
+
+ /**
+ * Pseudo-random number for the SV, or FCN/OSN number for Glonass. The
+ * distinction is made by looking at constellation field. Values should be
+ * in the range of:
+ *
+ * - GPS: 1-32
+ * - SBAS: 120-151, 183-192
+ * - GLONASS: 1-24, the orbital slot number (OSN), if known. Or, if not:
+ * 93-106, the frequency channel number (FCN) (-7 to +6) offset by + 100
+ * i.e. report an FCN of -7 as 93, FCN of 0 as 100, and FCN of +6 as 106.
+ * - QZSS: 193-200
+ * - Galileo: 1-36
+ * - Beidou: 1-37
+ */
+ int16_t svid;
+
+ /**
+ * The type of message contained in the structure.
+ * This is a Mandatory value.
+ */
+ RTKSDKGnssNavigationMessageType type;
+
+ /**
+ * The status of the received navigation message.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+ RTKSDKNavigationMessageStatus status;
+
+ /**
+ * Message identifier.
+ * It provides an index so the complete Navigation Message can be assembled. i.e. fo L1 C/A
+ * subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message.
+ * Subframe 1, 2, 3 does not contain a 'frame id' and this value can be set to -1.
+ */
+ int16_t message_id;
+
+ /**
+ * Sub-message identifier.
+ * If required by the message 'type', this value contains a sub-index within the current
+ * message (or frame) that is being transmitted.
+ * i.e. for L1 C/A the submessage id corresponds to the sub-frame id of the navigation message.
+ */
+ int16_t submessage_id;
+
+ /**
+ * The length of the data (in bytes) contained in the current message.
+ * If this value is different from zero, 'data' must point to an array of the same size.
+ * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+ *
+ * This is a Mandatory value.
+ */
+ size_t data_length;
+
+ /**
+ * The data of the reported GPS message.
+ * The bytes (or words) specified using big endian format (MSB first).
+ *
+ * For L1 C/A, each subframe contains 10 30-bit GPS words. Each GPS word (30 bits) should be
+ * fitted into the last 30 bits in a 4-byte word (skip B31 and B32), with MSB first.
+ */
+ uint8_t data[64];
+
+} RTKSDKGnssNavigationMessage;
+
+/**
+ * Represents GPS Navigation model info
+ * Refer to ICD-200 for the description of each element.
+ */
+typedef struct {
+ uint8_t codeL2; /* Code on L2 flag */
+ uint8_t URA; /* SF1 raw accuracy factor */
+ uint8_t SV_health; /* SV health byte */
+ uint8_t L2Pdata; /* L2-P data flag */
+ uint8_t fit_interval; /* As in ICD-200 */
+ uint8_t IODE; /* As in ICD-200 */
+ uint16_t weeknum; /* GPS week number */
+ uint16_t IODC; /* IODC -- 10 LSBs */
+ float SVacc; /* SV accuracy; meters */
+ float T_GD; /* Group delay time factor; seconds */
+ float t_oc; /* Time of this block's applicability; */
+ float a_f2; /* SV clock coef2; sec/sec^2 */
+ float a_f1; /* SV clock coef1; sec/sec */
+ float a_f0; /* SV clock coef0; sec */
+ float C_uc; /* Radians */
+ float C_us; /* Radians */
+ float t_oe; /* Seconds */
+ float C_ic; /* Radians */
+ float C_is; /* Radians */
+ float C_rc; /* Meters */
+ float C_rs; /* Meters */
+ double delta_n; /* Radians/sec */
+ double M_0; /* Radians */
+ double e; /* Dimensionless */
+ double sqrt_A; /* Meters**-1/2 */
+ double OMEGA_0; /* Radians */
+ double i_0; /* Radians */
+ double omega; /* Radians */
+ double OMEGADOT; /* Radians */
+ double IDOT; /* Radians */
+} RTKSDKGpsNaviModel;
+
+
+/**
+ * Represents Glonass Navigation model info
+ *
+ */
+typedef struct {
+ uint8_t FT; /*User Range Accuracy index. P32 ICD Glonass for value of Ft.*/
+ uint8_t M; /*Glonass vehicle type. M=1 means type M*/
+ uint8_t Bn; /*Bn SV health see p30 ICD Glonass. */
+ uint8_t utc_offset; /*Current GPS-UTC leap seconds [sec]; 0 if unknown. */
+ uint8_t En; /*Age of current information in days */
+ uint8_t P1; /*Time interval between adjacent values of tb in minutes */
+ uint8_t P2; /*1 if tb is odd and 0 if tb is even */
+ double deltaTau; /*time difference between transmission in G2 and G1*/
+ double gamma; /*SV clock frequency error ratio */
+ double freqno; /*Freq slot: -7 to +13 incl. */
+ double lsx; /* x luni solar accel */
+ double lsy; /* y luni solar accel */
+ double lsz; /*z luni solar accel */
+ double tauN; /*SV clock bias scale factor 2^-30 [seconds]. */
+ double gloSec; /*gloSec=[(N4-1)*1461 + (NT-1)]*86400 + tb*900 */
+ double x; /*x position at toe */
+ double y; /*y position at toe */
+ double z; /*z position at toe */
+ double vx; /* x velocity at toe */
+ double vy; /* y velocity at toe */
+ double vz; /*z velocity at toe */
+ double tauGPS;
+} RTKSDKGlonassNaviModel;
+
+
+/**
+ * Represents Beidou Navigation model info
+ *
+ */
+typedef struct {
+ uint8_t AODE; /*Age of Data, Ephemeris*/
+ uint8_t AODC; /*Age of Data, Clock (AODC)*/
+ uint8_t URAI; /*URA Index, URA is used to describe the signal-in-space accuracy in meters*/
+ uint32_t weeknum; /* BDS week number */
+ float t_oc; /* Time of this block's applicability; */
+ float t_oe; /* Ephemeris reference time */
+ float C_uc; /* Radians */
+ float C_us; /* Radians */
+ float C_ic; /* Radians */
+ float C_is; /* Radians */
+ float C_rc; /* Meters */
+ float C_rs; /* Meters */
+ double sqrt_A; /* Meters**-1/2 */
+ double e; /* Dimensionless */
+ double omega; /* Radians */
+ double delta_n; /* Radians/sec */
+ double M_0; /* Radians */
+ double OMEGA_0; /* Radians */
+ double OMEGADOT; /* Radians */
+ double i_0; /* Radians */
+ double IDOT; /* Radians */
+ double a_0; /*Clock correction polynomial coefficient(seconds) */
+ double a_1; /*Clock correction polynomial coefficient (sec/sec) */
+ double a_2; /*Clock correction polynomial coefficient (sec/sec2) */
+ double T_GD_1; /*Equipment group delay differential TGD1 */
+ double T_GD_2; /*Equipment group delay differential TGD2 */
+ uint8_t SV_health; /*health status of this Ephemeris*/
+} RTKSDKBdsNaviModel;
+
+/** Represents a GNSS navigation model message. */
+typedef struct {
+ /** set to sizeof(GnssNavigationModelMessage) */
+ size_t size;
+
+ /**
+ * Pseudo-random number for the SV, or FCN/OSN number for Glonass. The
+ * distinction is made by looking at constellation field. Values should be
+ * in the range of:
+ *
+ * - GPS: 1-32
+ * - GLONASS: 1-24, the orbital slot number (OSN), if known. Or, if not:
+ * 93-106, the frequency channel number (FCN) (-7 to +6) offset by + 100
+ * i.e. report an FCN of -7 as 93, FCN of 0 as 100, and FCN of +6 as 106.
+ * - Beidou: 1-37
+ */
+ int16_t svid;
+
+ /**
+ * Defines the constellation of the given SV. Value should be one of those
+ * GNSS_CONSTELLATION_* constants
+ */
+ RTKSDKGnssConstellationType constellation;
+ union {
+ RTKSDKGpsNaviModel gps_eph;
+ RTKSDKGlonassNaviModel gln_eph;
+ RTKSDKBdsNaviModel bds_eph;
+ } choice;
+
+} RTKSDKGnssNavigationModelMessage;
+
+
+typedef struct {
+ /** set to sizeof(GnssNavigationModelData) */
+ size_t size;
+
+ /** Number of satellite navigation models. */
+ size_t navigation_model_count;
+
+ /** The array of navigation models. */
+ RTKSDKGnssNavigationModelMessage navigation_models[RTKSDK_GNSS_MAX_MEASUREMENT];
+} RTKSDKGnssNavigationModelData;
+
+
+typedef struct {
+ RTKSDKGnssConstellationType constellation;
+ float alfa0;
+ float alfa1;
+ float alfa2;
+ float alfa3;
+ float beta0;
+ float beta1;
+ float beta2;
+ float beta3;
+} RTKSDKGnssIonosphericModelMessage;
+
+/**
+ * Represent SDK callbacks.
+ */
+typedef struct {
+ /**
+ * Set to sizeof(RTKSDKSdkCallbacks).
+ */
+ size_t size;
+
+ /**
+ * Callback utility for acquiring the system wakelock. It needs to be
+ * passed in if the application layer does not manage the wakelock.
+ * 1 for acquiring the system wakelock; 0 for releasing the system wakelock.
+ */
+ void (*acquire_wakeLock)(int flag);
+ /*
+ * Notify sdk integrator to push the raw data cached in buf back to
+ * QianXun rubik module for controlling.
+ */
+ void (*fill_raw_data)(unsigned char *buf, int len);
+ /*
+ * Callback to report positioning results.
+ */
+ void (*fill_position)(RTKSDKGnssLocation *pos);
+ /*
+ * Callback to report NMEA.
+ */
+ void (*fill_nmea_info)(RTKGnssUtcTime time, const char* nmea, int len);
+ /*
+ * Callback to report sdk status code.
+ */
+ void (*status_response)(RTKSDKSdkStatus status);
+} RTKSDKSdkCallbacks;
+
+/**
+ * Represent the SDK interface.
+ */
+typedef struct {
+ /**
+ * Set to sizeof(RTKSDKSdkInterface).
+ */
+ size_t size;
+ /**
+ * Initialize the SDK, to provide sdk callbacks and configuration.
+ */
+ int (*init)(RTKSDKSdkCallbacks *callbacks, RTKSDKSdkConfig *config);
+ /**
+ * Start the sdk.
+ */
+ int (*start)(void);
+ /**
+ * Stop the sdk.
+ */
+ int (*stop)(void);
+ /**
+ * Cleanup the sdk.
+ */
+ int (*cleanup)(void);
+ /**
+ * Get sdk version.
+ */
+ char* (*get_ver_info)(void);
+ /**
+ * Algo control.
+ */
+ int (*ioctl)(int command, void* params, int* paramsLen);
+ /**
+ * Notify sdk when network status changes.
+ */
+ void (*update_conn_status)(RTKSDKNetworkStatus networkType);
+ /**
+ * Configure positioning mode. RTKSDKPosMode defines the positioning mode, including rtk
+ * and rtk + dr mode. frequency presents the time gap between position fix reports.
+ * It will take effect immediately.
+ */
+ void (*set_position_mode)(RTKSDKPosMode mode, RTKSDKReportFreq frequency);
+ /**
+ * Delete specific types of aiding data.
+ */
+ void (*delete_aiding_data)(RTKGNSSAidingData flags);
+
+ /**
+ * Inject ephemeris of GPS/GLONASS/Beidou, etc.
+ */
+ int (*inject_eph)(RTKSDKGnssNavigationModelData *data);
+ /**
+ * Inject measurements
+ */
+ int (*inject_meas)(RTKSDKGnssData *data);
+ /**
+ * Inject raw navigation message
+ */
+ int (*inject_navMsg)(RTKSDKGnssNavigationMessage *message);
+ /**
+ * Inject inospheric model data
+ */
+ int (*inject_iono)(RTKSDKGnssIonosphericModelMessage *message);
+
+ /**
+ * Injects current location from another location provider
+ */
+ int (*inject_position)(RTKSDKGnssLocation *pos);
+
+ /**
+ * Inject gnss data which must include RXM-RAWX(Multi-GNSS Raw Measurement Data).
+ */
+ int (*inject_gnss_data)(unsigned char *buffer, size_t len);
+ /**
+ * Inject pulse per second which is acquired at the time of GNSS positioned.
+ */
+ int (*inject_gnss_pps)(RTKSDKGNSSPPS *pps);
+ /**
+ * Inject dual antenna GNSS orientation.
+ */
+ int (*inject_gnss_ort)(RTKSDKGNSSOrt *ort);
+ /**
+ * Inject sensor configuration.
+ */
+ int (*inject_sensor_config)(RTKSDKSensorConfig *config);
+ /**
+ * Inject senor data.
+ */
+ int (*inject_sensor_data)(RTKSDKSensorData *sensorData);
+ /**
+ * Use third-party offline map matching. Insert external map match
+ * to SDK instead of using the offline map inside the SDK.
+ */
+ int (*inject_map_matching_para)(RTKSDKMapMatchingPara *mapParams);
+ /**
+ * Set lever arm configurations.
+ */
+ int (*set_lever_arm_para)(RTKSDKLeverArmParams *lam);
+} RTKSDKSdkInterface;
+typedef struct {
+ RTKSDKSdkCallbacks *callbacks;
+ RTKSDKSdkConfig *config;
+}RTKSdkInit;
+typedef struct {
+ int command;
+ void* params;
+ int* paramsLen;
+}RTKSdkIoctl;
+typedef struct {
+ RTKSDKPosMode mode;
+ RTKSDKReportFreq frequency;
+}RTKSdkSetPositionMode;
+typedef struct {
+ unsigned char *buffer;
+ size_t len;
+}RTKSdkInjectGnssData;
+typedef struct {
+ RTKGnssUtcTime time;
+ const char* nmea;
+ int len;
+}RTKSdkCbFillNmeaInfo;
+
+UINT8 mnld_rtk_interface(MNLDRtkInterfaceType rtk_message_type, void* rtk_message);
+unsigned char MNLD_RTK_loading(void);
+unsigned char MNLD_RTK_unloading();
+int mnld_rtk_init();
+int mnld_rtk_cleanup();
+int mnld_rtk_start();
+int mnld_rtk_stop();
+
+/**
+ * Get the SDK interfaces.
+
+ * @param void
+ * @return a pointer of RTKSDKSdkInterface type that contains the SDK's interfaces
+ */
+typedef const RTKSDKSdkInterface* (*GetRTKSDKSdkInterface)(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _RTKSDK_SDK_H_ */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps.h b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps.h
new file mode 100644
index 0000000..f86a7d6
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps.h
@@ -0,0 +1,2396 @@
+/***********************************************************************
+* This software/firmware and related documentation("MediaTek Software")
+* are protected under relevant copyright laws. The information contained
+* herein is confidential and proprietary to MediaTek Inc. and/or its licensors.
+*
+* Without the prior written permission of MediaTek Inc. and/or its licensors,
+* any reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly prohibited.
+*
+* MediaTek Inc.(C) [2008]. All rights reserved.
+*
+*************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * mtk_gps.h
+ *
+ * Description:
+ * ------------
+ * Prototype of MTK navigation library
+ *
+ ****************************************************************************/
+
+#ifndef MTK_GPS_H
+#define MTK_GPS_H
+
+#include "mtk_gps_type.h"
+#include "mtk_gps_agps.h"
+
+#include "mtk_gps_driver_wrapper.h"
+#ifdef USING_NAMING_MARC
+#include "mtk_gps_macro.h"
+#endif
+
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+/* ================= Application layer functions ================= */
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_run
+ * DESCRIPTION
+ * The main routine for the MTK Nav Library task
+ * PARAMETERS
+ * application_cb [IN]
+ * default_cfg(mtk_init_cfg) [IN]
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_run(MTK_GPS_CALLBACK application_cb, const MTK_GPS_INIT_CFG* default_cfg);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_hotstill_run
+ * DESCRIPTION
+ * The main routine for the HotStill task
+ * PARAMETERS
+ * driver_cfg [IN] factory default configuration
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_hotstill_run(MTK_GPS_DRIVER_CFG* driver_cfg);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_agent_run
+ * DESCRIPTION
+ * The main routine for the Agent task
+ * PARAMETERS
+ * driver_cfg [IN] factory default configuration
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_agent_run(MTK_GPS_DRIVER_CFG* driver_cfg);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_update_gps_data
+ * DESCRIPTION
+ * Force to write NV-RAM data to storage file
+ * PARAMETERS
+ *
+ * RETURNS
+ * None
+ *****************************************************************************/
+INT32
+mtk_gps_update_gps_data(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_data_input
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ * buffer [IN] the content of the gps measuremnt
+ * length [IN] the length of the gps measurement
+ * p_accepted_length [OUT] indicate how many data was actually accepted into library
+ * if this value is not equal to length, then it means library internal
+ * fifo is full, please let library task can get cpu usage to digest input data
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_data_input(const char* buffer, UINT32 length, UINT32* p_accepted_length);
+
+INT32
+mtk_gps_data_input2(const char* buffer, UINT32 length, UINT32* accepted_length);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_rtcm_input
+ * DESCRIPTION
+ * accept RTCM differential correction data
+ * PARAMETERS
+ * buffer [IN] the content of RTCM data
+ * length [IN] the length of RTCM data(no more than 1KB)
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_rtcm_input(const char* buffer, UINT32 length);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_nmea_input
+ * DESCRIPTION
+ * accept NMEA(PMTK) sentence raw data
+ * PARAMETERS
+ * buffer [IN] the content of NMEA(PMTK) data
+ * length [IN] the length of NMEA(PMTK) data
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_nmea_input(const char* buffer, UINT32 length);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_agps_input
+ * DESCRIPTION
+ * accept NMEA(PMTK) sentence raw data(only for agent using)
+ * PARAMETERS
+ * buffer [IN] the content of NMEA(PMTK) data
+ * length [IN] the length of NMEA(PMTK) data
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_agps_input(const char* buffer, UINT32 length);
+
+
+/* ====================== Utility functions ====================== */
+/* These functions must be used in application_cb() callback
+ function specified in mtk_gps_run() */
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_position
+ * DESCRIPTION
+ * obtain detailed fix information
+ * PARAMETERS
+ * pvt_data [OUT] pointer to detailed fix information
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_position(MTK_GPS_POSITION* pvt_data);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_sv_info
+ * DESCRIPTION
+ * obtain detailed information of all satellites for GPS/QZSS
+ * PARAMETERS
+ * sv_data [OUT] pointer to satellites information
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_sv_info(MTK_GPS_SV_INFO* sv_data);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_gleo_sv_info
+ * DESCRIPTION
+ * obtain detailed information of all satellites for GALIILEO
+ * PARAMETERS
+ * sv_data [OUT] pointer to satellites information
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_gleo_sv_info(MTK_GLEO_SV_INFO* sv_gleo_data);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_glon_sv_info
+ * DESCRIPTION
+ * obtain detailed information of all satellites for GALIILEO
+ * PARAMETERS
+ * sv_data [OUT] pointer to satellites information
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_glon_sv_info(MTK_GLON_SV_INFO* sv_glon_data);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_bedo_sv_info
+ * DESCRIPTION
+ * obtain detailed information of all satellites for GALIILEO
+ * PARAMETERS
+ * sv_data [OUT] pointer to satellites information
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_bedo_sv_info(MTK_BEDO_SV_INFO* sv_bedo_data);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_param
+ * DESCRIPTION
+ * Get the current setting of the GPS receiver
+ * PARAMETERS
+ * key [IN] the configuration you want to know
+ * value [OUT] the current setting
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ * EXAMPLE
+ * // get the current DGPS mode
+ * mtk_param_dgps_config param_dgps_config;
+ * mtk_gps_get_param(MTK_PARAM_DGPS_CONFIG, ¶m_dgps_config);
+ * printf("DGPS mode=%d",(int)param_dgps_config.dgps_mode);
+ *****************************************************************************/
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_sv_list
+ * DESCRIPTION
+ * Return SV list(Elev >= 5)
+ * PARAMETERS
+ * *UINT32 SV list bit map
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_sv_list(UINT32 *svListBitMap);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_param
+ * DESCRIPTION
+ * Get the current setting of the GPS receiver
+ * PARAMETERS
+ * key [IN] the configuration you want to know
+ * value [OUT] the current setting
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ * EXAMPLE
+ * // get the current DGPS mode
+ * mtk_param_dgps_config param_dgps_config;
+ * mtk_gps_get_param(MTK_PARAM_DGPS_CONFIG, ¶m_dgps_config);
+ * printf("DGPS mode=%d",(int)param_dgps_config.dgps_mode);
+ *****************************************************************************/
+INT32
+mtk_gps_get_param(MTK_GPS_PARAM key, void* value);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_param
+ * DESCRIPTION
+ * Change the behavior of the GPS receiver
+ * PARAMETERS
+ * key [IN] the configuration needs to be changed
+ * value [IN] the new setting
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_param(MTK_GPS_PARAM key, const void* value);
+INT32
+mtk_gps_get_mnl_info(MTK_GPS_MNL_INFO* lib_info);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_mnl_create_dbg_port
+ * DESCRIPTION
+ * Create debug socket in running time
+ * If debug socket is disabled at start time, will create it
+ * If debug socket is enabled at start time, will not create it repeatedly
+ * PARAMETERS
+ * port_num [IN] the port number needs to be created
+ * RETURNS
+ * void
+ *****************************************************************************/
+void mtk_gps_mnl_create_dbg_port(UINT32 port_num);
+
+//****************************************************************************
+// mtk_gps_set_nmea_format : Set NMEA format
+//
+// Parameters:
+// Mode = 0 : NMEA show as normal
+// Mode = 1 : NMEA show
+// $GPGGA,,,,,,0,,,,,,,,*66
+// $GPVTG,,T,,M,,N,,K,N*2C
+// $GPRMC,,V,,,,,,,,,,N*53
+// Mode > 1 : Reserved
+//
+//
+// Description :
+// show different GGA/VTF/RMC format when GNSS in no-fix status
+//
+UINT8 mtk_gps_set_nmea_format(UINT8 *NMEA_format);
+
+// *****************************************************************************
+// mtk_gps_set_navigation_speed_threshold :
+// The function will keep fix the postion output to the same point if the current
+// estimated 3D speed is less than SpeedThd or the distance of true position and the fix points
+// are large than 20 meter.
+// Parameters :
+// SpeedThd must be >= 0
+// The unit of SpeedThd is [meter/second]
+// if SpeedThd = 0, The navigation speed threshold function will be disabled.
+// For exapmle,
+// The fix points will keep to the same points until estimated speed is large than 0.4m/s
+//
+// float SpeedThd = 0.4;
+// MTK_Set_Navigation_Speed_Threshold(SpeedThd);
+//
+
+INT32
+mtk_gps_set_navigation_speed_threshold(float SpeedThd);
+
+// *****************************************************************************
+// mtk_gps_get_navigation_speed_threshold :
+// Query the current Static Navigation Speed Threshold
+// Parameters : The unit of SpeedThd is [meter/second]
+// if SpeedThd = 0, The navigation speed threshold is not functional.
+
+INT32
+mtk_gps_get_navigation_speed_threshold(float *SpeedThd);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_pmtk_data
+ * DESCRIPTION
+ * send PMTK command to GPS receiver
+ * PARAMETERS
+ * prPdt [IN] pointer to the data structure of the PMTK command
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_pmtk_data(const MTK_GPS_PMTK_DATA_T *prPdt);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_pmtk_response
+ * DESCRIPTION
+ * obtain detailed information of PMTK response
+ * PARAMETERS
+ * rs_data [OUT] pointer to PMTK response data
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_pmtk_response(MTK_GPS_PMTK_RESPONSE_T *prRsp);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_position
+ * DESCRIPTION
+ * Set the receiver's initial position
+ * Notes: To make the initial position take effect, please invoke restart
+ * (hot start/warm start) after this function
+ * PARAMETERS
+ * LLH [IN] LLH[0]: receiver latitude in degrees(positive for North)
+ * LLH[1]: receiver longitude in degrees(positive for East)
+ * LLH[2]: receiver WGS84 height in meters
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_position(const double LLH[3]);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_time
+ * DESCRIPTION
+ * Set the current GPS time
+ * Note: The time will not be set if the receiver has better knowledge
+ * of the time than the new value.
+ * PARAMETERS
+ * weekno [IN] GPS week number(>1024)
+ * TOW [IN] time of week(in second; 0.0~684800.0)
+ * timeRMS [IN] estimated RMS error of the TOW value(sec^2)
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_time(UINT16 weekno, double tow, float timeRMS);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_ephemeris
+ * DESCRIPTION
+ * Upload ephemeris
+ * PARAMETERS
+ * svid [IN] GPS satellite PRN(1~32)
+ * data [IN] binary ephemeris words from words 3-10 of subframe 1-3
+ * all parity bits(bit 5-0) have been removed
+ * data[0]: bit 13-6 of word 3, subframe 1
+ * data[1]: bit 21-14 of word 3, subframe 1
+ * data[2]: bit 29-22 of word 3, subframe 1
+ * data[3]: bit 13-6 of word 4, subframe 1
+ * ......
+ * data[71]: bit 29-22 of word 10, subframe 3
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_ephemeris(UINT8 svid, const char data[72]);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_tcxo_mode
+ * DESCRIPTION
+ * Set MNL TCXO mode
+ * PARAMETERS
+ *
+
+ * MTK_TCXO_NORMAL, // normal mode
+ * MTK_TCXO_PHONE // phone mode
+
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+
+INT32
+mtk_gps_set_tcxo_mode(MTK_GPS_TCXO_MODE tcxo_mode);
+
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_AIC_mode
+ * DESCRIPTION
+ * Set AIC mode
+ * PARAMETERS
+ *
+ * disalbe = 0
+ * enable = 1
+
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+
+INT32
+mtk_gps_set_AIC_mode(MTK_GPS_AIC_MODE AIC_Enable);
+
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_almanac
+ * DESCRIPTION
+ * Upload almanac
+ * PARAMETERS
+ * svid [IN] GPS satellite PRN(1~32)
+ * weekno [IN] the week number of the almanac data record
+ * data [IN] binary almanac words from words 3-10 of either subframe 4
+ * pages 2-10 or subframe 5 pages 1-24
+ * all parity bits(bit 5-0) have been removed
+ * data[0]: bit 13-6 of word 3
+ * data[1]: bit 21-14 of word 3
+ * data[2]: bit 29-22 of word 3
+ * data[3]: bit 13-6 of word 4
+ * ......
+ * data[23]: bit 29-22 of word 10
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_almanac(UINT8 svid, UINT16 weekno, const char data[24]);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_ephemeris
+ * DESCRIPTION
+ * Download ephemeris
+ * PARAMETERS
+ * svid [IN] GPS satellite PRN(1~32)
+ * data [OUT] binary ephemeris words from words 3-10 of subframe 1-3
+ * all parity bits(bit 5-0) have been removed
+ * data[0]: bit 13-6 of word 3, subframe 1
+ * data[1]: bit 21-14 of word 3, subframe 1
+ * data[2]: bit 29-22 of word 3, subframe 1
+ * data[3]: bit 13-6 of word 4, subframe 1
+ * ......
+ * data[71]: bit 29-22 of word 10, subframe 3
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_ephemeris(UINT8 svid, char data[72]);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_almanac
+ * DESCRIPTION
+ * Download almanac
+ * PARAMETERS
+ * svid [IN] GPS satellite PRN(1~32)
+ * p_weekno [OUT] pointer to the week number of the almanac data record
+ * data [OUT] binary almanac words from words 3-10 of either subframe 4
+ * pages 2-10 or subframe 5 pages 1-24
+ * all parity bits(bit 5-0) have been removed
+ * data[0]: bit 13-6 of word 3
+ * data[1]: bit 21-14 of word 3
+ * data[2]: bit 29-22 of word 3
+ * data[3]: bit 13-6 of word 4
+ * ......
+ * data[23]: bit 29-22 of word 10
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_almanac(UINT8 svid, UINT16* p_weekno, char data[24]);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_assist_bitmap
+ * DESCRIPTION
+ * Set assist(EPH/ALM) bitmap
+ * PARAMETERS
+ * UINT8 AssistBitMap
+ * If you want EPH assist data, please set AssistBitMap to 0x08
+ * If you want ALM assist data, please set AssistBitMap to 0x01
+ * If you want EPH and ALM assist data, please set AssistBitMap to 0x09
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_assist_bitmap(UINT16 AssistBitMap);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_assist_bitmap
+ * DESCRIPTION
+ * Get Re-aiding assist(EPH/ALM) bitmap
+ * PARAMETERS
+ * uint8* pAssistBitMap
+ * Get current Re-aiding assist bitmap
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_assist_bitmap(UINT16 *pAssistBitMap);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_clear_ephemeris
+ * DESCRIPTION
+ * clear the ephemeris of the specified PRN
+ * PARAMETERS
+ * svid [IN] GPS satellite PRN(1~32)
+ *****************************************************************************/
+void
+mtk_gps_clear_ephemeris(UINT8 svid);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_clear_almanac
+ * DESCRIPTION
+ * clear the almanac of the specified PRN
+ * PARAMETERS
+ * svid [IN] GPS satellite PRN(1~32)
+ *****************************************************************************/
+void
+mtk_gps_clear_almanac(UINT8 svid);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_sbas_msg_amount
+ * DESCRIPTION
+ * Get the number of SBAS message blocks received in this epoch.
+ * Later on, please use mtk_gps_get_sbas_msg() to get the message
+ * content one by one.
+ * PARAMETERS
+ * p_msg_amount [OUT] The number of SBAS message blocks received in this epoch
+ * RETURNS
+ *
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_sbas_msg_amount(UINT32* p_msg_amount);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_sbas_msg
+ * DESCRIPTION
+ * After calling mtk_gps_get_sbas_msg_amount(), we know the
+ * number of SBAS messages received in this epoch.
+ * mtk_gps_get_sbas_msg() gives a way to access each message
+ * data
+ * PARAMETERS
+ * index [IN] which message you want to read
+ * pSVID [OUT] the PRN of the SBAS satellite
+ * pMsgType [OUT] the SBAS message type
+ * pParityError [OUT] nonzero(parity error); zero(parity check pass)
+ * data [OUT] The 212-bit message data excluding the preamble,
+ * message type field, and the parity check.
+ * Regarding to endian, the data[0] is the beginning the
+ * message, such as IODP field. The data[26] is the end of
+ * message, and the bit 3..0 are padding zero.
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ * EXAMPLE
+ * // dump the SBAS message to UART output
+ * int i, count;
+ * unsigned char PRN, MsgType, ParityError;
+ * char data[27];
+ *
+ * mtk_gps_get_sbas_msg_amount(&count);
+ * for(i = 0; i < count; i++)
+ * {
+ * mtk_gps_get_sbas_msg(i, &PRN, &MsgType, &ParityError, data);
+ * }
+ *****************************************************************************/
+INT32
+mtk_gps_get_sbas_msg(INT32 index, unsigned char* pSVID,
+ unsigned char* pMsgType, unsigned char* pParityError, char data[27]);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_cn0_test
+ * DESCRIPTION
+ * Get Channel CNR and in CN0 test mode
+ * PARAMETERS
+ * ChnSNR [OUT] Channel SNR
+ * PRN[0]: GPS PRN 1
+ * PRN[1]: GPS PRN 2
+ * PRN[2]: GLO PRN 8
+ * PRN[3]: BDS PRN 6
+ * PRN[4]: BDS PRN 7
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ * if you do not enter test mode first or Channel tracking not ready,
+ * return MTK_GPS_ERROR
+ *****************************************************************************/
+
+INT32
+mtk_gps_get_cn0_test(INT32 SVID[5],INT32 SV_type[5],float ChnSNR[5]);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_chn_status
+ * DESCRIPTION
+ * Get Channel SNR and Clock Drift Status in Channel Test Mode
+ * PARAMETERS
+ * ChnSNR [OUT] Channel SNR
+ * ClkDrift [OUT] Clock Drift
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ * if you do not enter test mode first or Channel tracking not ready,
+ * return MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_gps_get_chn_test(float ChnSNR[16], float *ClkDrift);
+
+
+
+/****************************************************************************
+* FUNCTION
+*mtk_gps_D2_Set_Enable
+*DESCRIPTION
+* Bediou D2 data Enable/Disable functions
+*PARAMETERS
+* UsedD2Corr =1, Enable D2 correction data.
+* UsedD2Corr =0, Disable D2 correction data.
+*RETURNS
+* None
+ *****************************************************************************/
+
+void mtk_gps_D2_Set_Enable(unsigned char bUsedD2Corr);
+
+
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_glonass_chn_status
+ * DESCRIPTION
+ * Get Channel SNR and Clock Drift Status in Channel Test Mode
+ * PARAMETERS
+ * ChnSNR [OUT] Channel SNR
+ * ClkDrift [OUT] Clock Drift
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ * if you do not enter test mode first or Channel tracking not ready,
+ * return MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_gps_get_glonass_chn_test(float ChnSNR[3]);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_jammer_test
+ * DESCRIPTION
+ * Obtain the CW jammer estimation result
+ * PARAMETERS
+ * Freq [OUT] jammer frequency offset in KHz
+ * JNR [OUT] JNR of the associated jammer
+ * jammer_peaks [OUT] The number(0~195) of jammer peaks if ready
+ * 0 means no jammer detected
+ * Negative if not ready
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_jammer_test(INT32 *jammer_peaks, short Freq[231], UINT16 JNR[231]);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_jammer_test
+ * DESCRIPTION
+ * Enter or leave Jammer Test Mode
+ * PARAMETERS
+ * action [IN] 1 = enter Jammer test(old); 2 = enter Jammer test(new); 0 = leave Jammer test
+ * SVid [IN] please assign any value between 1~32
+ * range [IN] no use in new jammer scan, any value is ok.
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+*****************************************************************************/
+INT32
+mtk_gps_set_jammer_test(INT32 action, UINT16 mode, UINT16 arg);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_gnss_jammer_test
+ * DESCRIPTION
+ * Enter or leave Jammer Test Mode
+ * PARAMETERS
+ * action [IN] 1 = enter Jammer test; 0 = leave Jammer test, not ready
+ * mode [IN] 0 = GPS; 1 = GLONASS ;2 = Beidou
+ * arg [IN] unused
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_gnss_jammer_test(INT32 action, UINT16 mode, UINT16 arg);
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_phase_test
+ * DESCRIPTION
+ * Obtain the last phase error calibration result
+ * PARAMETERS
+ * result [OUT] 0~64(success)
+ * Negative(failure or not ready)
+ * The return value is 64*{|I|/sqrt(I*I + Q*Q)}
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_phase_test(INT32 *result);
+
+
+// *************************************************************************************
+// mtk_gps_get_sat_accurate_snr : Get the accurate SNR of all satellites
+//
+// Note : SNR is an array with 32 float.
+// Example:
+// float SNR[32];
+// mtk_gps_get_sat_accurate_snr(SNR);
+// // Get SNR of SV 17
+// MTK_UART_OutputData("SV17: SNR = %lf", SNR[16]);
+//
+// =====> SV17: SNR = 38.1
+
+void mtk_gps_get_sat_accurate_snr(float SNR[32]);
+
+
+// *************************************************************************************
+// mtk_gps_get_glon_sat_accurate_snr : Get the accurate SNR of all GLONASS satellites
+//
+// Note : SNR is an array with [24] float.
+// Example:
+// float SNR[24];
+// mtk_gps_get_glon_sat_accurate_snr(SNR);
+// // Get SNR of SV 1
+// MTK_UART_OutputData("GLON,SV1: SNR = %lf", SNR[0]);
+//
+// =====>GLON,SV1: SNR = 38.1
+
+void mtk_gps_get_glon_sat_accurate_snr(float ASNR[24]);
+
+
+// *************************************************************************************
+// mtk_gps_get_bd_sat_accurate_snr : Get the accurate SNR of all Beidou satellites
+//
+// Note : SNR is an array with 63 float.
+// Example:
+// float SNR[63];
+// mtk_gps_get_bd_sat_accurate_snr(SNR);
+// // Get SNR of SV 17
+// MTK_UART_OutputData("BD,SV17: SNR = %lf", SNR[16]);
+//
+// =====>BD,SV17: SNR = 38.1
+
+void mtk_gps_get_bd_sat_accurate_snr(float SNR[63]);
+
+// *************************************************************************************
+// mtk_gps_get_gleo_sat_accurate_snr : Get the accurate SNR of all GALILEO satellites
+//
+// Note : SNR is an array with [36] float.
+// Example:
+// float SNR[36];
+// mtk_gps_get_gleo_sat_accurate_snr(SNR);
+// // Get SNR of SV 1
+// MTK_UART_OutputData("GAL,SV1: SNR = %lf", SNR[0]);
+//
+// =====>GAL,SV1: SNR = 38.1
+
+void mtk_gps_get_gleo_sat_accurate_snr(float SNR[36]);
+
+void mtk_gps_get_nic_sat_accurate_snr(float SNR[14]);
+
+
+void mtk_gps_get_sat_accurate_snr_L5(float SNR[32]);
+void mtk_gps_get_bd_sat_accurate_snr_L5(float SNR[63]);
+void mtk_gps_get_gleo_sat_accurate_snr_L5(float SNR[36]);
+
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_per_test
+ * DESCRIPTION
+ * Enable PER test
+ * PARAMETERS
+ * Threshold [IN] power of 2(1,2,4,8,...)
+ * SVid [IN] SVid for PER test that can be tracked in sky
+ * TargetCount [IN] Test time in 20ms unit
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_per_test(INT16 Threshold, UINT16 SVid, UINT16 TargetCount);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_chip_capability
+ * DESCRIPTION
+ * send chip capability to mnld (ex: 6797: GPS + Beidou + Glonass)
+ * PARAMETERS
+ * pradt [out]
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+void
+mtk_gps_get_chip_capability (UINT8* SV_TYPE);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gnss_get_gps_time_infor
+ * DESCRIPTION
+ * send GPS TOW,WK and leap second when send PMTK761/763
+ * PARAMETERS
+ * pradt [IN] pointer to the data structure of the A-GPS command or data
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gnss_get_gps_time_infor (unsigned int *p_dfTOW, short *p_i2WeekNo, double *p_UTC_Cor);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_agps_data
+ * DESCRIPTION
+ * send A-GPS assistance data or command to GPS receiver
+ * PARAMETERS
+ * pradt [IN] pointer to the data structure of the A-GPS command or data
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_agps_data(const MTK_GPS_AGPS_CMD_DATA_T *prAdt);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_agps_response
+ * DESCRIPTION
+ * obtain detailed information of A-GPS reponse
+ * PARAMETERS
+ * prRsp [OUT] pointer to A-GPS response data
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_agps_response(MTK_GPS_AGPS_RESPONSE_T *prRsp);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_agps_lppe_3Dstatus_response
+ * DESCRIPTION
+ * obtain detailed information of A-GPS reponse
+ * PARAMETERS
+ * prRsp [OUT] pointer to A-GPS response data
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_agps_lppe_3Dstatus_response(gnss_ha_3Dposition_struct *hight_3Dposition,gnss_ha_3Dvelocity_struct *hight_3Dvelocity);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_agps_lppe_meas_response
+ * DESCRIPTION
+ * obtain detailed information of A-GPS reponse
+ * PARAMETERS
+ * prRsp [OUT] pointer to A-GPS response data
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_agps_lppe_meas_response(gnss_ha_Measure_struct *ha_Measure);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_agps_req_mod
+ * DESCRIPTION
+ * obtain req module of A-GPS response
+ * PARAMETERS
+ * ReqMod [OUT] pointer to request module
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_agps_req_mod(MTK_GPS_MODULE *pReqMod);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_time_change_notify
+ * DESCRIPTION
+ * Notify MNL to handle RTC time change
+ * PARAMETERS
+ * INT32RtcDiff [IN] System RTC time changed: old rtc time - new rtc time
+ * RETURNS
+ *
+ *****************************************************************************/
+void
+mtk_gps_time_change_notify(INT32 INT32RtcDiff);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_rtc_offset
+ * DESCRIPTION
+ * Notify MNL to handle RTC time change
+ * PARAMETERS
+ * r8RtcOffset [OUT] System RTC time changed
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_rtc_offset(double *r8RtcOffset);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_time_update_notify
+ * DESCRIPTION
+ * Notify MNL to handle RTC time change
+ * PARAMETERS
+ * fgSyncGpsTime [IN] System time sync to GPS time
+ * i4RtcDiff [IN] Difference of system RTC time changed
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_time_update_notify(UINT8 fgSyncGpsTime, INT32 i4RtcDiff);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_debug_config
+ * DESCRIPTION
+ * config the debug log type and level
+ * PARAMETERS
+ * DbgType [IN] Debug message category
+ * DbgLevel [IN] Debug message output level
+ *
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+
+INT32
+mtk_gps_sys_debug_config(MTK_GPS_DBG_TYPE DbgType, MTK_GPS_DBG_LEVEL DbgLevel);
+
+
+/* =================== Porting layer functions =================== */
+/* The function body needs to be implemented */
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_gps_mnl_callback
+ * DESCRIPTION
+ * MNL CallBack function
+ * PARAMETERS
+ * mtk_gps_notification_type
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+
+INT32
+mtk_gps_sys_gps_mnl_callback(MTK_GPS_NOTIFICATION_TYPE msg);
+
+/*****************************************************************************
+ * FUNCTION
+* mtk_gps_sys_time_tick_get
+* DESCRIPTION
+* get the current system tick of target platform(msec)
+* PARAMETERS
+* none
+* RETURNS
+* system time tick
+*****************************************************************************/
+UINT32
+mtk_gps_sys_time_tick_get(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_time_tick_get_max
+ * DESCRIPTION
+ * get the maximum system tick of target platform(msec)
+ * PARAMETERS
+ * none
+ * RETURNS
+ * system time tick
+ *****************************************************************************/
+UINT32
+mtk_gps_sys_time_tick_get_max(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_time_read
+ * DESCRIPTION
+ * Read system time
+ * PARAMETERS
+ * utctime [IN/OUT] get the host system time
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ * failed(MTK_GPS_ERROR)
+ * system time changed since last call(MTK_GPS_ERROR_TIME_CHANGED)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_time_read(MTK_GPS_TIME* utctime);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_task_sleep
+ * DESCRIPTION
+ * Task sleep function
+ * PARAMETERS
+ * milliseconds [IN]
+ * RETURNS
+ * void
+ *****************************************************************************/
+void
+mtk_gps_sys_task_sleep(UINT32 milliseconds);
+
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_storage_open
+ * DESCRIPTION
+ * Open a non-volatile file
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_storage_open(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_storage_close
+ * DESCRIPTION
+ * Close a non-volatile file
+ * RETURNS
+ * void
+ *****************************************************************************/
+void
+mtk_gps_sys_storage_close(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_storage_delete
+ * DESCRIPTION
+ * Delete a non-volatile file
+ * RETURNS
+ * void
+ *****************************************************************************/
+void
+mtk_gps_sys_storage_delete(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_storage_read
+ * DESCRIPTION
+ * Read a non-volatite file
+ * - blocking read until reaching 'length' or EOF
+ * PARAMETERS
+ * buffer [OUT]
+ * offset [IN]
+ * length [IN]
+ * p_nRead [OUT]
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_storage_read(void* buffer, UINT32 offset, UINT32 length,
+ UINT32* p_nRead);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_storage_write
+ * DESCRIPTION
+ * Write a non-volatite file
+ * PARAMETERS
+ * buffer [IN]
+ * offset [IN]
+ * length [IN]
+ * p_nWritten [OUT]
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_storage_write(const void* buffer, UINT32 offset, UINT32 length,
+ UINT32* p_nWritten);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_mem_alloc
+ * DESCRIPTION
+ * Allocate a block of memory
+ * PARAMETERS
+ * size [IN] the length of the whole memory to be allocated
+ * RETURNS
+ * On success, return the pointer to the allocated memory
+ * NULL(0) if failed
+ *****************************************************************************/
+void*
+mtk_gps_sys_mem_alloc(UINT32 size);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_mem_free
+ * DESCRIPTION
+ * Release unused memory
+ * PARAMETERS
+ * pmem [IN]
+ * RETURNS
+ * void
+ *****************************************************************************/
+void
+mtk_gps_sys_mem_free(void* pmem);
+
+/*****************************************************************************
+* FUNCTION
+* mtk_gps_sys_event_delete
+* DESCRIPTION
+* event delete for Android
+* PARAMETERS
+* event_idx [IN] MTK_GPS_EVENT_ENUM
+* RETURNS
+* success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mtk_gps_sys_event_delete(MTK_GPS_EVENT_ENUM event_idx);
+
+/*****************************************************************************
+* FUNCTION
+* mtk_gps_sys_event_create
+* DESCRIPTION
+* event create for Android
+* PARAMETERS
+* event_idx [IN] MTK_GPS_EVENT_ENUM
+* RETURNS
+* success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mtk_gps_sys_event_create(MTK_GPS_EVENT_ENUM event_idx);
+
+/*****************************************************************************
+* FUNCTION
+* mtk_gps_sys_event_set
+* DESCRIPTION
+* event set for Android
+* PARAMETERS
+* event_idx [IN] MTK_GPS_EVENT_ENUM
+* RETURNS
+* success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mtk_gps_sys_event_set(MTK_GPS_EVENT_ENUM event_idx);
+
+/*****************************************************************************
+* FUNCTION
+* mtk_gps_sys_event_wait
+* DESCRIPTION
+* event wait for android
+*
+* PARAMETERS
+* event_idx [IN] MTK_GPS_EVENT_ENUM
+* RETURNS
+* success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mtk_gps_sys_event_wait(MTK_GPS_EVENT_ENUM event_idx);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_uart_init
+ * DESCRIPTION
+ * Initiialize UART
+ * PARAMETERS
+ * portname [IN]
+ * baudrate [IN]
+ * txbufsize [IN]
+ * rxbufsize [IN]
+ * RETURNS
+ * Result of Handler
+ *****************************************************************************/
+INT32
+mtk_gps_sys_uart_init(char* portname, UINT32 baudrate, UINT32 txbufsize,
+ UINT32 rxbufsize);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_uart_read
+ * DESCRIPTION
+ * Initiialize UART
+ * PARAMETERS
+ * UARTHandle [IN]
+ * buffer [IN]
+ * bufsize [IN]
+ * length [IN]
+ * RETURNS
+ * Result of Handler
+ *****************************************************************************/
+INT32
+mtk_gps_sys_uart_read(INT32 UARTHandle, char* buffer, UINT32 bufsize,
+ INT32* length);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_uart_write
+ * DESCRIPTION
+ * Initiialize UART
+ * PARAMETERS
+ * UARTHandle [IN]
+ * buffer [IN]
+ * bufsize [IN]
+ * length [IN]
+ * RETURNS
+ * Result of Handler
+ *****************************************************************************/
+INT32 mtk_gps_sys_uart_write(INT32 UARTHandle, const char* buffer, UINT32 bufsize,
+ INT32* wrotenlength);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_uart_uninit
+ * DESCRIPTION
+ * Initiialize UART
+ * PARAMETERS
+ * UARTHandle [IN]
+ * RETURNS
+ * void
+ *****************************************************************************/
+void
+mtk_gps_sys_uart_uninit(INT32 UARTHandle);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_if_set_spd
+ * DESCRIPTION
+ * Set baud rate at host side from GPS lib
+ * (The function body needs to be implemented)
+ * PARAMETERS
+ * baudrate [IN] UART baudrate
+ * hw_fc [IN] UART hardware flow control
+ * 0: without hardware flow contorl(defualt)
+ * 1: with hardware flow contorl
+ * RETURNS
+ * success(0)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_if_set_spd(UINT32 baudrate, UINT8 hw_fc);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_data_output
+ * DESCRIPTION
+ * Transmit data to the GPS chip
+ * (The function body needs to be implemented)
+ * PARAMETERS
+ * msg [IN]
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_data_output(char* buffer, UINT32 length);
+
+/*****************************************************************************
+* FUNCTION
+* mtk_gps_sys_nmea_output
+* DESCRIPTION
+* Transmit NMEA data out to task
+* (The function body needs to be implemented)
+* PARAMETERS
+* buffer [IN] data pointer
+* length [IN] size of data
+* RETURNS
+* success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mtk_gps_sys_nmea_output(char* buffer, UINT32 length);
+
+
+/*****************************************************************************
+* FUNCTION
+* mtk_sys_nmea_output_to_app
+* DESCRIPTION
+* Transmit NMEA data out to APP layer
+* (The function body needs to be implemented)
+* PARAMETERS
+* buffer [IN] data pointer
+* length [IN] size of data
+* RETURNS
+* success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mtk_gps_sys_nmea_output_to_app(const char * buffer, UINT32 length);
+
+INT32
+mtk_gps_sys_nmea_output_to_app_print(const char *fmt, ...);
+
+#if 1
+/*****************************************************************************
+* FUNCTION
+* mtk_sys_nmea_output_to_mnld
+* DESCRIPTION
+* Transmit NMEA data out to MNLD
+* (The function body needs to be implemented)
+* PARAMETERS
+* buffer [IN] data pointer
+* length [IN] size of data
+* RETURNS
+* success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mtk_gps_sys_nmea_output_to_mnld(const char * buffer, UINT32 length);
+#endif
+
+/*****************************************************************************
+* FUNCTION
+* mnl_sys_alps_gps_dbg2file_mnld
+* DESCRIPTION
+* Transfer GPS debug log to MNLD to write to file
+* (The function body needs to be implemented)
+* PARAMETERS
+* buffer [IN] data pointer
+* length [IN] size of data
+* RETURNS
+* success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mnl_sys_alps_gps_dbg2file_mnld(const char * buffer, UINT32 length);
+
+// Otehr platform
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_start_result_handler
+ * DESCRIPTION
+ * Handler routine for the result of restart command
+ * (The function body needs to be implemented)
+ * PARAMETERS
+ * result [IN] the result of restart
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_start_result_handler(MTK_GPS_START_RESULT result);
+
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_spi_poll
+ * DESCRIPTION
+ * Polling data input routine for SPI during dsp boot up stage.
+ * If use UART interface, this function can do nothing at all.
+ * (The function body needs to be implemented)
+ * PARAMETERS
+ * void
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_spi_poll(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_set_spi_mode
+ * DESCRIPTION
+ * Set SPI interrupt/polling and support burst or not.
+ * If use UART interface, this function can do nothing at all.
+ * (The function body needs to be implemented)
+ * PARAMETERS
+ * enable_int [IN] 1 for enter interrupt mode , 0 for entering polling mode
+ * enable_burst [IN] 1 for enable burst transfer, 0 for disable burst transfer
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_set_spi_mode(UINT8 enable_int, UINT8 enable_burst);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_dsp_boot_begin_handler
+ * DESCRIPTION
+ * Handler routine for porting layer implementation right before GPS DSP boot up
+ * (The function body needs to be implemented)
+ * PARAMETERS
+ * none
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_dsp_boot_begin_handler(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_dsp_boot_end_handler
+ * DESCRIPTION
+ * Handler routine for porting layer implementation right after GPS DSP boot up
+ * (The function body needs to be implemented)
+ * PARAMETERS
+ * none
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_dsp_boot_end_handler(void);
+
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_frame_sync_meas
+ * DESCRIPTION
+ * PARAMETERS
+ * pFrameTime [OUT] frame time of the issued frame pulse(seconds)
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+
+INT32 mtk_gps_sys_frame_sync_meas(double *pdfFrameTime);
+
+INT32 mtk_gps_sys_frame_sync_enable_sleep_mode(unsigned char mode);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_frame_sync_meas_resp
+ * DESCRIPTION
+ * accept a frame sync measurement response
+ * PARAMETERS
+ * eResult [IN] success to issue a frame sync meas request
+ * dfFrameTime [IN] frame time of the issued frame pulse(seconds)
+ * RETURNS
+ * void
+ *****************************************************************************/
+void
+mtk_gps_frame_sync_meas_resp(MTK_GPS_FS_RESULT eResult, double dfFrameTime);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_frame_sync_meas_req_by_network
+ * DESCRIPTION
+ * issue a frame sync measurement request
+ * PARAMETERS
+ * none
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ * fail(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_frame_sync_meas_req_by_network(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_frame_sync_meas_req
+ * DESCRIPTION
+ * issue a frame sync measurement request
+ * PARAMETERS
+ * mode [out] frame sync request indication for aiding or maintain
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ * fail(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_frame_sync_meas_req(MTK_GPS_FS_WORK_MODE mode);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_initialize_mutex
+ * DESCRIPTION
+ * Inialize mutex array
+ * PARAMETERS
+ * void
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_initialize_mutex(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_create_mutex
+ * DESCRIPTION
+ * Create a mutex object
+ * PARAMETERS
+ * mutex_num [IN] mutex index used by MTK Nav Library
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_create_mutex(MTK_GPS_MUTEX_ENUM mutex_idx);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_take_mutex
+ * DESCRIPTION
+ * Request ownership of a mutex and if it's not available now, then block the thread execution
+ * PARAMETERS
+ * mutex_num [IN] mutex index used by MTK Nav Library
+ * RETURNS
+ * void
+ *****************************************************************************/
+
+void
+mtk_gps_sys_take_mutex(MTK_GPS_MUTEX_ENUM mutex_idx);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_give_mutex
+ * DESCRIPTION
+ * Release a mutex ownership
+ * PARAMETERS
+ * mutex_num [IN] mutex index used by MTK Nav Library
+ * RETURNS
+ * void
+ *****************************************************************************/
+
+void
+mtk_gps_sys_give_mutex(MTK_GPS_MUTEX_ENUM mutex_idx);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_destroy_mutex
+ * DESCRIPTION
+ * Destroy a mutex object
+ * PARAMETERS
+ * mutex_num [IN] mutex index used by MTK Nav Library
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_destroy_mutex(MTK_GPS_MUTEX_ENUM mutex_idx);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_pmtk_cmd_cb
+ * DESCRIPTION
+ * Notify porting layer that MNL has received one PMTK command.
+ * PARAMETERS
+ * UINT16CmdNum [IN] The received PMTK command number.
+ * RETURNS
+ * void
+ *****************************************************************************/
+void
+mtk_gps_sys_pmtk_cmd_cb(UINT16 UINT16CmdNum);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_sys_spi_poll
+ * DESCRIPTION
+ * Polling data input routine for SPI during dsp boot up stage.
+ * If use UART interface, this function can do nothing at all.
+ * (The function body needs to be implemented)
+ * PARAMETERS
+ * void
+ * RETURNS
+ * success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32 mtk_gps_sys_spi_poll(void);
+
+ /*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_uart_poll
+ * DESCRIPTION
+ * GPS RX polling function
+ * PARAMETERS
+ * void
+ * RETURNS
+ * success(0)
+ *****************************************************************************/
+INT32 mtk_gps_sys_uart_poll(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_rtc_info
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ * dfrtcD [OUT] RTC clock drift(unit : ppm).
+ * dfage [OUT] RTC drift age : current gps time - gps time of latest rtc drift calculated.(unit : sec)
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_rtc_info(double *dfrtcD, double *dfage);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_delete_nv_data
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ * u4Bitmap [INPUT]
+ *
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32 mtk_gps_delete_nv_data(UINT32 assist_data_bit_map);
+
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_tsx_xvt
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ * u4Bitmap [INPUT]
+ *
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+
+INT32
+mtk_gps_tsx_xvt(UINT8 enable);
+
+/*****************************************************************************
+ * mtk_gps_set_wifi_location_aiding :
+ * set Wifi location information to MNL
+ * Parameters :
+ * latitude :Wifi latitude unit: [degree]
+ * longitude:Wifi longitude unit: [degree]
+ * posvar :position accuracy unit: [m]
+ * Return Value: 0: fail; 1: pass
+ *****************************************************************************/
+INT32 mtk_gps_set_wifi_location_aiding(MTK_GPS_REF_LOCATION *RefLocation,
+ double latitude, double longitude, double accuracy);
+
+/*****************************************************************************
+ * mtk_gps_inject_ntp_time :
+ * inject ntp time into MNL
+ * Parameters :
+ * time : ntp time unit: [degree]
+ * timeRef: the system time tick when sync NTP time to network unit: mini-second
+ * Uncertainty: ntp time uncertainty error: [mini]
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32 mtk_gps_inject_ntp_time(MTK_GPS_NTP_T* ntp);
+
+/*****************************************************************************
+ * mtk_gps_inject_nlp_location :
+ * inject nlp location into MNL
+ * Parameters :
+ * latitude : nlp latitude
+ * longitude: nlp longitude
+ * accuracy: nlp location uncertainty : [m]
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32 mtk_gps_inject_nlp_location(MTK_GPS_NLP_T* nlp);
+
+
+/*****************************************************************************
+ * mtk_gps_measurement :
+ * get gps measurement
+ * Parameters :
+ * flag: A set of flags indicating the validity of the fields in this data structure
+ * PRN: Pseudo-random number in the range of [1, 32]
+ * TimeOffsetInNs: Time offset at which the measurement was taken in nanoseconds.
+ The reference receiver's time is specified by GpsData::clock::time_ns and should be
+ interpreted in the same way as indicated by GpsClock::type.
+ The sign of time_offset_ns is given by the following equation:
+ measurement time = GpsClock::time_ns + time_offset_ns
+ It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+ * state: Per satellite sync state. It represents the current sync state for the associated satellite.
+ Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+ * ReGpsTowInNs: Received GPS Time-of-Week at the measurement time, in nanoseconds.
+ The value is relative to the beginning of the current GPS week.
+ Given the sync state of GPS receiver, per each satellite, valid range for this field can be:
+ Searching : [ 0 ] : GPS_MEASUREMENT_STATE_UNKNOWN
+ Ranging code lock : [ 0 1ms ] : GPS_MEASUREMENT_STATE_CODE_LOCK is set
+ Bit sync : [ 0 20ms ] : GPS_MEASUREMENT_STATE_BIT_SYNC is set
+ Subframe sync : [ 0 6ms ] : GPS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ TOW decoded : [ 0 1week ] : GPS_MEASUREMENT_STATE_TOW_DECODED is set
+ * ReGpsTowUnInNs: 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds
+ * Cn0InDbHz: Carrier-to-noise density in dB-Hz, in the range [0, 63].
+ It contains the measured C/N0 value for the signal at the antenna input.
+ * PRRateInMeterPreSec: Pseudorange rate at the timestamp in m/s.
+ The value also includes the effects of the receiver clock frequency and satellite clock
+ frequency errors.
+ The value includes the 'pseudorange rate uncertainty' in it.
+ A positive value indicates that the pseudorange is getting larger.
+ * PRRateUnInMeterPreSec: 1-Sigma uncertainty of the pseudurange rate in m/s.
+ The uncertainty is represented as an absolute(single sided) value.
+ * AcDRState10: Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+ (indicating loss of lock).
+ * AcDRInMeters: Accumulated delta range since the last channel reset in meters.
+ * AcDRUnInMeters: 1-Sigma uncertainty of the accumulated delta range in meters.
+ * PRInMeters: Best derived Pseudorange by the chip-set, in meters.
+ The value contains the 'pseudorange uncertainty' in it.
+ * PRUnInMeters: 1-Sigma uncertainty of the pseudorange in meters.
+ The value contains the 'pseudorange' and 'clock' uncertainty in it.
+ The uncertainty is represented as an absolute(single sided) value.
+ * CPInChips: A fraction of the current C/A code cycle, in the range [0.0, 1023.0]
+ This value contains the time(in Chip units) since the last C/A code cycle(GPS Msec epoch).
+ The reference frequency is given by the field 'carrier_frequency_hz'.
+ The value contains the 'code-phase uncertainty' in it.
+ * CPUnInChips: 1-Sigma uncertainty of the code-phase, in a fraction of chips.
+ The uncertainty is represented as an absolute(single sided) value.
+ * CFInhZ: Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+ If the field is not set, the carrier frequency is assumed to be L1.
+ * CarrierCycle: The number of full carrier cycles between the satellite and the receiver.
+ The reference frequency is given by the field 'carrier_frequency_hz'.
+ * CarrierPhase: The RF phase detected by the receiver, in the range [0.0, 1.0].
+ This is usually the fractional part of the complete carrier phase measurement.
+ The reference frequency is given by the field 'carrier_frequency_hz'.
+ The value contains the 'carrier-phase uncertainty' in it.
+ * CarrierPhaseUn: 1-Sigma uncertainty of the carrier-phase.
+ * LossOfLock: An enumeration that indicates the 'loss of lock' state of the event.
+ * BitNumber: The number of GPS bits transmitted since Sat-Sun midnight(GPS week).
+ * TimeFromLastBitInMs: The elapsed time since the last received bit in milliseconds, in the range [0, 20]
+ * DopperShiftInHz: Doppler shift in Hz.
+ A positive value indicates that the SV is moving toward the receiver.
+ The reference frequency is given by the field 'carrier_frequency_hz'.
+ The value contains the 'doppler shift uncertainty' in it.
+ * DopperShiftUnInHz: 1-Sigma uncertainty of the doppler shift in Hz.
+ * MultipathIndicater: An enumeration that indicates the 'multipath' state of the event.
+ * SnrInDb: Signal-to-noise ratio in dB.
+ * ElInDeg: Elevation in degrees, the valid range is [-90, 90].
+ The value contains the 'elevation uncertainty' in it.
+ * ElUnInDeg: 1-Sigma uncertainty of the elevation in degrees, the valid range is [0, 90].
+ The uncertainty is represented as the absolute(single sided) value.
+ * AzInDeg: Azimuth in degrees, in the range [0, 360).
+ The value contains the 'azimuth uncertainty' in it.
+ * AzUnInDeg: 1-Sigma uncertainty of the azimuth in degrees, the valid range is [0, 180].
+ The uncertainty is represented as an absolute(single sided) value.
+ * UsedInFix: Whether the GPS represented by the measurement was used for computing the most recent fix.
+ *****************************************************************************/
+void
+mtk_gps_get_measurement(MTK_GPS_MEASUREMENT GpsMeasurement[32], INT8 Ch_Proc_Ord_PRN[32]);
+
+/*****************************************************************************
+ * mtk_gps_clock :
+ * get clock parameter
+ * Parameters :
+ * flag: A set of flags indicating the validity of the fields in this data structure.
+ * leapsecond: Leap second data.
+ The sign of the value is defined by the following equation:
+ utc_time_ns = time_ns +(full_bias_ns + bias_ns) - leap_second * 1,000,000,000
+ * type: Indicates the type of time reported by the 'time_ns' field.
+ * TimeInNs: The GPS receiver internal clock value. This can be either the local hardware clock value
+ (GPS_CLOCK_TYPE_LOCAL_HW_TIME), or the current GPS time derived inside GPS receiver
+ (GPS_CLOCK_TYPE_GPS_TIME). The field 'type' defines the time reported.
+
+ For local hardware clock, this value is expected to be monotonically increasing during
+ the reporting session. The real GPS time can be derived by compensating the 'full bias'
+ (when it is available) from this value.
+
+ For GPS time, this value is expected to be the best estimation of current GPS time that GPS
+ receiver can achieve. Set the 'time uncertainty' appropriately when GPS time is specified.
+
+ Sub-nanosecond accuracy can be provided by means of the 'bias' field.
+ The value contains the 'time uncertainty' in it.
+ * TimeUncertaintyInNs: 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+ The uncertainty is represented as an absolute(single sided) value.
+ This value should be set if GPS_CLOCK_TYPE_GPS_TIME is set.
+ * FullBiasInNs: The difference between hardware clock('time' field) inside GPS receiver and the true GPS
+ time since 0000Z, January 6, 1980, in nanoseconds.
+ This value is used if and only if GPS_CLOCK_TYPE_LOCAL_HW_TIME is set, and GPS receiver
+ has solved the clock for GPS time.
+ The caller is responsible for using the 'bias uncertainty' field for quality check.
+
+ The sign of the value is defined by the following equation:
+ true time(GPS time) = time_ns +(full_bias_ns + bias_ns)
+
+ This value contains the 'bias uncertainty' in it.
+ * BiasInNs: Sub-nanosecond bias.
+ The value contains the 'bias uncertainty' in it.
+ * BiasUncertaintyInNs: 1-Sigma uncertainty associated with the clock's bias in nanoseconds.
+ The uncertainty is represented as an absolute(single sided) value.
+ * DriftInNsPerSec: The clock's drift in nanoseconds(per second).
+ A positive value means that the frequency is higher than the nominal frequency.
+
+ The value contains the 'drift uncertainty' in it.
+ * DriftUncertaintyInNsPerSec: 1-Sigma uncertainty associated with the clock's drift in nanoseconds(per second).
+ The uncertainty is represented as an absolute(single sided) value.
+ *
+ * Return Value: 0: fail; 1: pass
+ *****************************************************************************/
+INT32
+mtk_gps_get_clock(MTK_GPS_CLOCK *GpsClock);
+
+/*****************************************************************************
+ * mtk_gps_navigation_event :
+ * get navigation event
+ * Parameters :
+ * type: The type of message contained in the structure.
+ * prn: Pseudo-random number in the range of [1, 32]
+ * meaasgeID: Message identifier.
+ It provides an index so the complete Navigation Message can be assembled. i.e. fo L1 C/A
+ subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message.
+ Subframe 1, 2, 3 does not contain a 'frame id' and this value can be set to -1.
+ * submeaasgeID: Sub-message identifier.
+ If required by the message 'type', this value contains a sub-index within the current
+ message(or frame) that is being transmitted.
+ i.e. for L1 C/A the submessage id corresponds to the sub-frame id of the navigation message.
+ * data[]: The data of the reported GPS message.
+ The bytes(or words) specified using big endian format(MSB first).
+
+ For L1 C/A, each subframe contains 10 30-bit GPS words. Each GPS word(30 bits) should be
+ fitted into the last 30 bits in a 4-byte word(skip B31 and B32), with MSB first.
+ *
+ * Return Value: 0: fail; 1: pass
+ *****************************************************************************/
+INT32
+mtk_gps_get_navigation_event(MTK_GPS_NAVIGATION_EVENT *NavEvent, UINT8 SVID);
+
+void
+mtk_gnss_get_measurement(
+Gnssmeasurement GpQzMeasurement[MTK_GPS_SV_MAX_PRN+MTK_QZS_SV_MAX_PRN],
+Gnssmeasurement GloMeasurement[MTK_GLON_SV_MAX_NUM],
+Gnssmeasurement BDMeasurement[MTK_BEDO_SV_MAX_NUM],
+Gnssmeasurement GalMeasurement[MTK_GLEO_SV_MAX_NUM],
+Gnssmeasurement SBASMeasurement[MTK_SBAS_SV_MAX_NUM],
+Gnssmeasurement IRNSSMeasurement[MTK_NAVIC_SV_MAX_NUM],
+INT8 GpQz_Ch_Proc_Ord_PRN[MTK_GPS_SV_MAX_PRN+MTK_QZS_SV_MAX_PRN],
+INT8 Glo_Ch_Proc_Ord_PRN[MTK_GLON_SV_MAX_NUM],
+INT8 BD_Ch_Proc_Ord_PRN[MTK_BEDO_SV_MAX_NUM],
+INT8 Gal_Ch_Proc_Ord_PRN[MTK_GLEO_SV_MAX_NUM],
+INT8 SBAS_Ch_Proc_Ord_PRN[MTK_SBAS_SV_MAX_NUM],
+INT8 IRNSS_Ch_Proc_Ord_PRN[MTK_NAVIC_SV_MAX_NUM]);
+
+INT32
+mtk_gnss_get_clock(Gnssclock *GnssClock);
+
+
+INT32
+mtk_gnss_get_navigation_event (GnssNavigationmessage *NavEvent, UINT8 SVID, UINT8 SV_type);
+
+
+// *****************************************************************************
+// mtk_gps_set_mpe_event :(MNL to MPE)
+// set mpe event
+// Parameters :
+// *****************************************************************************
+UINT16
+mtk_gps_set_mpe_info(UINT8 *msg);
+
+// *****************************************************************************
+// mtk_gps_mnl_mpe_callback_reg :(MNLD to MNL)
+// MNLD register callback function in libmnl
+// Parameters :
+// name [IN] callback function address in MNLD
+// Return
+// success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+// *****************************************************************************
+int
+mtk_gps_mnl_mpe_callback_reg(MPECallBack *name);
+
+// *****************************************************************************
+// mtk_gps_mnl_mpe_run_callback :(MNL to MNLD)
+// Run MNLD function registered in libmnl
+// Parameters :
+// Return
+// success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+// *****************************************************************************
+int
+mtk_gps_mnl_mpe_run_callback(void);
+
+/*****************************************************************************
+ * mtk_gps_get_sensor_info :
+ * get sensor LLH,head,head acc,vout information(MPE to MNL)
+ * Parameters :
+ *****************************************************************************/
+void
+mtk_gps_get_sensor_info(INT8 *msg, int len);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_debug_type
+ * DESCRIPTION
+ * Set the GPS debug type in running time
+ * PARAMETERS
+ * debug_type [IN] the debug type needs to be changed
+ *
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_debug_type(const UINT8 debug_type);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_debug_type
+ * DESCRIPTION
+ * Get the GPS debug type in running time
+ * PARAMETERS
+ * debug_type [out] current debug type
+ *
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_debug_type(UINT8* debug_type);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_debug_file
+ * DESCRIPTION
+ * Set the GPS debug file name(include the path name) in running time
+ * PARAMETERS
+ * file_name [IN] the debug file name needs to be changed
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_debug_file(char* file_name);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_rtc_info
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ * PRN [OUT] PRN Number (1~32 are valid).
+ * ParityError [OUT] Parity Error flag (ex :3FF = 10 words are wrong)
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_word_parity(UINT32 *TTick,UINT8 PRN[26], UINT16 ParityError[26]);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_get_jamming_indicator
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ * JammingIndicator [OUT] Jamming Indicator
+ * 1 : No jammer, healthy status
+ * 2 : Warning status
+ * 3 : Critical status
+ *****************************************************************************/
+void mtk_get_jamming_indicator(unsigned char *JammingIndicator);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_set_gnss_low_power_mode
+ * DESCRIPTION
+ * Set GNSS Low Power mode
+ * PARAMETERS
+ * GNSSLowPowerMode [IN] Enable GNSS Low Power or not
+ * 0 : Disable GNSS Low Power
+ * 1 : Enable GNSS Low Power
+ *****************************************************************************/
+void mtk_set_gnss_low_power_mode(unsigned char GNSSLowPowerMode);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_get_gnss_low_power_mode
+ * DESCRIPTION
+ * Get GNSS Low Power mode
+ * PARAMETERS
+ * GNSSLowPowerMode [OUT] GNSS Low Power enabled or not
+ * 0 : GNSS Low Power disabled
+ * 1 : GNSS Low Power enabled
+ *****************************************************************************/
+void mtk_get_gnss_low_power_mode(unsigned char *GNSSLowPowerMode);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_set_ext_lna_control_test
+ * DESCRIPTION
+ * Test the external LNA. The external LNA would be turn off when calling this function.
+ *****************************************************************************/
+void mtk_set_ext_lna_control_test(unsigned char dsp_name);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_set_pps_config
+ * DESCRIPTION
+ * Set PPS Config
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+
+INT32 mtk_gps_set_pps_config (MTK_GPS_PPS_CFG *pps_cfg);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_pps_config
+ * DESCRIPTION
+ * Get PPS Config
+ *****************************************************************************/
+
+INT32 mtk_gps_get_pps_config (MTK_GPS_PPS_CFG *pps_cfg);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_get_position_accuracy
+ * DESCRIPTION
+ * get position
+ * PARAMETERS
+ * double *Lat,double *Lon,int *accuracy)
+ * Get return result
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_position_accuracy(double *Lat, double *Lon, int *accuracy);
+
+void
+mtk_gps_mnl_get_sensor_info(UINT8 *msg, int len);
+
+void
+mtk_gps_mnl_set_sensor_info(UINT8 *msg, int len);
+
+int
+mtk_gps_mnl_trigger_mpe(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_qepo_file_update
+ * DESCRIPTION
+ * Update the qEPO file after the new qEpo file download
+ * PARAMETERS
+ * None
+ * RETURNS
+ * success: MTK_GPS_SUCCESS fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32 mtk_agps_agent_qepo_file_update();
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_agent_mtknav_file_update
+ * DESCRIPTION
+ * Update the MTKNAV file after the new MTKNAV file download
+ * PARAMETERS
+ * None
+ * RETURNS
+ * success: MTK_GPS_SUCCESS fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32 mtk_agps_agent_mtknav_file_update();
+
+#if 1 // mnl offload interface start
+/*****************************************************************************
+ * \bref for mnl offload
+ * enable offload:
+ * 1. mtk_gps_ofl_set_cfg(MNL_OFL_CFG_ENALBE_OFFLOAD)
+ * 2. mnl_sys_alps_gps_run
+ * disable offload, only one step:
+ * 1. mnl_sys_alps_gps_run
+ */
+// ============================================================================
+// Offload: MNLD => libmnl.so
+// ============================================================================
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_ofl_set_option
+ * DESCRIPTION
+ * Configure mnl offload parameters.
+ * Now whether to enable mnl offload is controlled by this function
+ * PARAMETERS
+ * user_bitmask [IN] bitmask like MNL_OFL_CFG_XXX
+ * RETURNS
+ * MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+#define MNL_OFL_OPTION_ENALBE_OFFLOAD 0x1
+
+INT32 mtk_gps_ofl_set_option(UINT32 cfg_bitmask);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_ofl_set_user
+ * DESCRIPTION
+ * Set the owners who use MNL, then how to init CONNSYS-MNL can be initilised.
+ * PARAMETERS
+ * user_bitmask [IN] bitmask which stands for different users like GPS_USR_XXX.
+ * The bitmask must contaion all the users of GPS so mnld msut
+ * must keep a copy of this bitmask.
+ * RETURNS
+ * MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+#define GPS_USER_UNKNOWN 0x0
+#define GPS_USER_APP 0x1
+#define GPS_USER_AGPS 0x2
+#define GPS_USER_META 0x4 // meta or factory mode
+#define GPS_USER_RESTART 0x8
+#define GPS_USER_FLP 0x10
+#define GPS_USER_OFL_TEST 0x20 // for offload test
+#define GPS_USER_AT_CMD 0x40 // for offload test
+#define GPS_USER_APM 0x80
+#define GPS_USER_GEOFENCE 0x100
+#define GPS_USER_RAW_MEAS 0x200 //RAW measurement
+
+INT32 mtk_gps_ofl_set_user(UINT32 user_bitmask);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_ofl_rst_stpgps_begin_ntf
+ * DESCRIPTION
+ * Notify libmnl.so that MNLD is to reopen /dev/stpgps.
+ * PARAMETERS
+ * void
+ * RETURNS
+ * MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32 mtk_gps_ofl_rst_stpgps_begin_ntf();
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_ofl_rst_stpgps_begin_ntf
+ * DESCRIPTION
+ * Notify libmnl.so that MNLD has reopened /dev/stpgps and tell libmnl.so the new fd.
+ * PARAMETERS
+ * dsp_fd [IN] the new fd of /dev/stpgps after reopened.
+ * RETURNS
+ * MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32 mtk_gps_ofl_rst_stpgps_end_ntf(int dsp_fd);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_ofl_send_flp_data
+ * DESCRIPTION
+ * Reroute data from HOST FLP to CONNSYS FLP.
+ * PARAMETERS
+ * buf [IN] buffer to send
+ * len [IN] length of the data
+ * RETURNS
+ * MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32 mtk_gps_ofl_send_flp_data(UINT8 *buf, UINT32 len);
+
+#if 0
+/* These 2 API can be replaced by:
+mtk_gps_ofl_set_user(gps_user | GPS_USER_FLP);
+mtk_gps_ofl_set_user(gps_user & ~GPS_USER_FLP);
+*/
+INT32 mtk_gps_ofl_flp_init();
+INT32 mtk_gps_ofl_flp_deinit();
+#endif
+
+// ============================================================================
+// Offload: libmnl.so => MNLD
+// ============================================================================
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_ofl_sys_rst_stpgps_req
+ * DESCRIPTION
+ * Request MNLD to reopen /dev/stpgps.
+ * PARAMETERS
+ * void
+ * RETURNS
+ * MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+
+INT32 sys_gps_mnl_data2mnld_callback(const char *data, unsigned int length);
+/*****************************************************************************
+ * FUNCTION
+ * sys_gps_mnl_data2mnld_callback
+ * DESCRIPTION
+ * Submit data from mnl to mnld.
+ * PARAMETERS
+ * buf [IN] buffer to send
+ * len [IN] length of the data
+ * RETURNS
+ * MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+
+INT32 mtk_gps_ofl_sys_rst_stpgps_req(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_ofl_sys_submit_flp_data
+ * DESCRIPTION
+ * Submit data from CONNSYS FLP to HOST FLP.
+ * PARAMETERS
+ * buf [IN] buffer to send
+ * len [IN] length of the data
+ * RETURNS
+ * MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32 mtk_gps_ofl_sys_submit_flp_data(UINT8 *buf, UINT32 len);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_ofl_sys_mnl_offload_callback
+ * DESCRIPTION
+ * Callback for libmnl.so to notify MNLD for something.
+ * RETURNS
+ * MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32 mtk_gps_ofl_sys_mnl_offload_callback(
+ MTK_GPS_OFL_CB_TYPE type, UINT16 length, UINT8 *data);
+#endif // mnl offload interface end
+
+
+#if 1 // for FLP AP mode function only
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_flp_get_location
+ *
+ * DESCRIPTION
+ * Porting layer or MNL daemon can call this API to fill location data to
+ * "buf", then it can be reported to FLP daemon.
+ *
+ * The "buf" will be filled with "MtkGpsLocation". Due to MNLD use
+ * "buf" rather then "MtkGpsLocation" as parameter, any change on
+ * "MtkGpsLocation" structure only need to be synchronized between
+ * FLP daemon and libmnl, then maintian effort can be eased.
+ *
+ * Please note that:
+ * 1. It's better if "buf" is 4-byte alligned. On some platform, non-alligned
+ * address for structure filling may cause issue.
+ * 2. The "buf_len" should be greater than or equal to
+ * sizeof("MtkGpsLocation"), otherwise function will return
+ * "MTK_GPS_ERROR" and no data will be filled into "buf".
+ * 3. If function return MTK_GPS_SUCCESS, "buf" will be filled and the filled
+ * length can be get from "*p_get_len".
+ * 4. If function return MTK_GPS_ERROR, "*p_get_len" indicates the wanted "buf_len"
+ *
+ * PARAMETERS
+ * buf [OUT] buffer to be filled
+ * buf_len [IN] length of the buffer
+ * p_get_len [OUT] the actual length of data be filled to buffer.
+ * it should be
+ * RETURNS
+ * MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32 mtk_gps_flp_get_location(void *buf, UINT32 buf_len, UINT32 *p_get_len);
+#endif // for FLP AP mode function only
+
+
+//*************************************************************************************
+// mtk_gps_get_gnss_operation_mode : Set GNSS operation mode
+//
+// Note : fgGLONStatus = [0] Disable GLONASS [1] Enable GLONASS
+// fgGALIStatus = [0] Disable GALIELO [1] Enable GALIELO
+// fgBEDOStatus = [0] Disable BEIDOU [1] Enable BEIDOU
+// Example:
+// unsigned char fgGLONStatus = 0;
+// unsigned char fgGALIStatus = 0;
+// unsigned char fgBEDOStatus = 0;
+// mtk_gps_get_gnss_operation_mode(&fgGLONStatus,&fgGALIStatus,&fgBEDOStatus);
+
+void mtk_gps_get_gnss_operation_mode(unsigned char *fgGLONStatus, unsigned char *fgGALIStatus, unsigned char *fgBEDOStatus, unsigned char *fgGPSStatus);
+
+//*************************************************************************************
+// mtk_gps_set_gnss_operation_mode : Set GNSS operation mode
+//
+// Note : fgGLONStatus = [0] Disable GLONASS [1] Enable GLONASS
+// fgGALIStatus = [0] Disable GALIELO [1] Enable GALIELO
+// fgBEDOStatus = [0] Disable BEIDOU [1] Enable BEIDOU
+// Notice :
+// GLONASS + GALILEO and Beidou are mutal exclusion.
+// If you enable GLONASS, GALILEO and Beidou at the same time, Beidou will be disabled automatically.
+//
+// Notice : The GALILEO mode switch is not support in this release.
+//
+// Example:
+// mtk_gps_set_gnss_operation_mode(1,0,0) : Enable GLONASS
+// mtk_gps_set_gnss_operation_mode(0,0,0) : Disable GLOANSS, GALIELO , BEIDOU
+// mtk_gps_set_gnss_operation_mode(0,0,1) : Enable BEIDOU
+// mtk_gps_set_gnss_operation_mode(1,1,1) : Enable GLONASS. Beidou will be disabled automatically.
+
+void mtk_gps_set_gnss_operation_mode(unsigned char fgGLONStatus, unsigned char fgGALIStatus, unsigned char fgBEDOStatus);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_log_line_enc_inplace
+ *
+ * DESCRIPTION
+ * Byte to byte encrypt the log buffer. Stop and return after
+ * non-printable char (ASCII0~31,128~255) is found or the length is reached.
+ *
+ * PARAMETERS
+ * buffer [IN/OUT] log buffer whith can be read or write
+ * length [IN] length of the data in buffer
+ * RETURNS
+ * The length actual replaced with encrypted char
+ *****************************************************************************/
+UINT32 mtk_gps_log_line_enc_inplace(char *buffer, UINT32 length);
+
+ /*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_do_hw_suspend_resume
+ * DESCRIPTION
+ * callback to do GPS HW suspend and resume to reset GPS HW
+ * PARAMETERS
+ * bitmask [IN] bitmask to identify why libmnl call this api
+ * see: MNL_HW_SUSPEND_MASK_*
+ * RETURNS
+ * MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+#define MNL_HW_SUSPEND_MASK_ENABLED_FLAG 0x0001
+#define MNL_HW_SUSPEND_MASK_RESUME_FLAG 0x0002
+#define MNL_HW_SUSPEND_MASK_RESTART_FLAG 0x0004
+#define MNL_HW_SUSPEND_MASK_L5_FLAG 0x0010
+INT32 mtk_gps_sys_do_hw_suspend_resume(UINT32 bitmask);
+
+/*****************************************************************************
+* FUNCTION
+* mtk_gps_sys_suspend_extention_set
+* DESCRIPTION
+* callback to set suspend extention enable/disable and externtion time in second
+* PARAMETERS
+* enable [IN] 0: disable; 1: enable
+* ext_sec [IN] externtion time to suspend(second)
+* RETURNS
+* void
+*****************************************************************************/
+void mtk_gps_sys_suspend_extention_set(INT32 enable, INT32 ext_sec);
+
+/*****************************************************************************
+* FUNCTION
+* mtk_gps_get_MNL_Config_XML_param
+* DESCRIPTION
+* Get the feature config parameters in MNL_Config.xml
+* PARAMETERS
+* MNL_Config_File_Path [IN] path to read MNL_Config.xml, ex. data/vendor/gps
+* mnl_config_xml [IN/OUT] parameter in mnl_config_xml.xml_feature_name
+* RETURNS
+* MTK_GPS_ERROR / MTK_GPS_SUCCESS
+*****************************************************************************/
+
+unsigned char mtk_gps_get_MNL_Config_XML_param (char MNL_Config_File_Path[], MTK_GPS_MNL_CONFIG_XML_PARAM *mnl_config_xml);
+
+/*****************************************************************************
+* FUNCTION
+* mtk_gps_set_MNL_Config_XML_param
+* DESCRIPTION
+* Set the feature config parameters to MNL_Config.xml
+* PARAMETERS
+* MNL_Config_File_Path [IN] path to write MNL_Config.xml, ex. data/vendor/gps
+* mnl_config_xml [IN] parameters settings
+*****************************************************************************/
+
+void mtk_gps_set_MNL_Config_XML_param (char MNL_Config_File_Path[], MTK_GPS_MNL_CONFIG_XML_PARAM *mnl_config_xml);
+
+/*****************************************************************************
+* FUNCTION
+* mtk_gps_geofence_get_position
+* DESCRIPTION
+* obtain detailed fix information for geofence
+* PARAMETERS
+* pos_data [OUT] pointer to detailed fix information for geofence
+* RETURNS
+* success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32 mtk_gps_geofence_get_position (mtk_geofence_position_info* pos_data);
+
+
+void mtk_gps_nmea_process (char *NmeaData, INT32 NmeaLength);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* MTK_GPS_H */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_agps.h b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_agps.h
new file mode 100644
index 0000000..59fda96
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_agps.h
@@ -0,0 +1,1224 @@
+/***********************************************************************
+* This software/firmware and related documentation ("MediaTek Software")
+* are protected under relevant copyright laws. The information contained
+* herein is confidential and proprietary to MediaTek Inc. and/or its licensors.
+*
+* Without the prior written permission of MediaTek Inc. and/or its licensors,
+* any reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly prohibited.
+*
+* MediaTek Inc. (C) [2008]. All rights reserved.
+*
+*************************************************************************/
+#ifndef MTK_GPS_AGPS_H
+#define MTK_GPS_AGPS_H
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "mtk_gps_type.h"
+
+#define MGPSID (32)
+#if ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 200000 ) )
+// for ADS1.x
+#elif ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400000 ) )
+// for RVCT2.x or RVCT3.x
+#else
+#pragma pack(4)
+#endif
+
+
+
+#define GPS_EPH_WORD_MAX 24
+#define GPS_L5_EPH_WORD_MAX 22
+#if 1//def AGPS_SUPPORT_GNSS
+#define GLO_EPH_WORD_MAX 12
+#define BDS_EPH_WORD_MAX 15
+#define GAL_EPH_WORD_MAX 18
+#endif
+
+#define GPS_ALM_WORD_MAX 8
+#define GPS_L5_ALM_WORD_MAX 5
+#if 1//def AGPS_SUPPORT_GNSS
+#define GLO_ALM_WORD_MAX 6
+#define BDS_ALM_WORD_MAX 8
+#define GAL_ALM_WORD_MAX 19
+#endif
+#define SUPPORT_AGA
+#define AGPS_RRLP_MAX_PRM 14
+
+typedef enum {
+ MTK_AGPS_OPEN_TYPE_UNKNOWN = 0, // 0 (i.e., old agpsd)
+ MTK_AGPS_OPEN_TYPE_C2K = 0x10, // 0x10
+ MTK_AGPS_OPEN_TYPE_SUPL = 0x20, // 0x20
+ MTK_AGPS_OPEN_TYPE_CP_NILR = 0x30, // 0x30
+ MTK_AGPS_OPEN_TYPE_CP_MTLR, // 0x31
+ MTK_AGPS_OPEN_TYPE_CP_MOLR, // 0x32
+ MTK_AGPS_OPEN_TYPE_CP_QUERY, // 0x33
+ MTK_AGPS_OPEN_TYPE_CP_MLR // 0x34
+} mtk_agps_open_type;
+
+typedef struct
+{
+ UINT8 u1Arg1;
+ UINT8 u1Arg2;
+ UINT8 u1Arg3; //VERSION
+ UINT8 u1Arg4; //C2K Flag
+} MTK_GPS_AGPS_CMD_MODE_T;
+
+typedef struct
+{
+#ifdef AGPS_SUPPORT_QOPMS
+ float u1Delay; // Response time in unit of sec.
+ // change from interge sec to mini-sec. so the Required response time will be more accurate
+ // for example
+ //old : $PMTK293,16,0,0,51*<Check Sum>
+ //new: $PMTK293,15.296,0,0,51*<Check Sum>
+#else
+ UINT8 u1Delay; // Response time in unit of sec.
+#endif
+ UINT32 u4HAcc; // Horizontal accuracy in unit of meter.
+ UINT16 u2VAcc; // Vertical accuracy in unit of meter.
+ UINT16 u2PRAcc; // Pseudorange accuracy in unit of meter.
+ float f4DelayEarlyFix; //[TS 36.355 R12] new item->responseTimeEarlyFix-r12
+ UINT32 u4PeriodicMode;// For Moving Scenario, default 0:normal mod, 1:moving scenario, >1, reserved.
+ UINT8 u1HAccConf;//(MSB only)Horizontal confidence [0~100]. 0 consider as "no information" and consider it as 90%.
+ UINT8 u1VAccConf;//(MSB only)Confidence associated with the altitude[0~100].0 consider as "no information" and consider it as 90%.
+ UINT8 u1PRAccConf;//(MSA only)MA accuracy confidence associated with the pseudorange error [0~100].0 consider as "no information" and consider it as 90%.
+} MTK_GPS_AGPS_CMD_QOP_T;
+
+typedef struct
+{
+ UINT8 u1SvId;
+ UINT32 au4Word[GPS_EPH_WORD_MAX];
+} MTK_GPS_ASSIST_EPH_T;
+
+typedef struct
+{
+ UINT32 u1SvId;
+ UINT32 au1Byte[55];
+ UINT32 u1Lf;
+} MTK_ASSIST_GLON_EPH_T;
+
+
+typedef struct
+{
+ UINT8 u1SvId;
+ UINT16 u2WeekNo;
+ UINT32 au4Word[GPS_ALM_WORD_MAX];
+} MTK_GPS_ASSIST_ALM_T;
+
+typedef struct
+{
+ UINT16 u2WeekNo;
+ double dfTow; // sec
+ double dfTowRms; // ms
+ double dfFS_Tow; // sec, not used
+ double dfFS_TowRms; // ms, not used
+ MTK_GPS_BOOL fgTimeComp; /* TRUE: indicate ref time compensation from modem , FALSE: no ref time composate */
+ double dfTimeDelay; /* the value of ref time compensation */
+ UINT8 gpsWeekCycleNumber; //INTEGER(0..7) -- GPS Acquisition Assistance Rel-10 Extension
+} MTK_GPS_ASSIST_TIM_T;
+
+typedef struct
+{
+ UINT16 u2WeekNo;
+ double dfTow; // sec
+ double dfTowRms; // ms
+ double dfFTime; // sec, Frame Time correspond to GPS TOW
+ double dfFTimeRms; // ms, Frame Time RMS accuracy
+} MTK_GPS_ASSIST_FTA_T, MTK_GPS_AGPS_DT_FTIME_T; // Fine Time Assistance
+
+typedef struct
+{
+ double dfLat; // Receiver Latitude in degrees
+ double dfLon; // Receiver Longitude in degrees
+ double dfAlt; // Receiver Altitude in meters
+ float fAcc_Maj; // semi-major RMS accuracy [m]
+ float fAcc_Min; // semi-minor RMS accuracy [m]
+ UINT8 u1Maj_Bear; // Bearing of semi-major axis in degrees
+ float fAcc_Vert; // Vertical RMS accuracy [m]
+ UINT8 u1Confidence; // Position Confidence: range from 0 ~ 100 [%]
+} MTK_GPS_ASSIST_LOC_T;
+
+typedef struct
+{
+ double dUtc_hms; // UTC: hhmmss.sss
+ double dUtc_ymd; // UTC: yyyymmdd
+ UINT8 u1FixType; // the type of measurements performed by the MS [0: 2D or 1: 3D]
+ double dfLat; // latitude (degree)
+ double dfLon; // longitude (degree)
+ INT16 i2Alt; // altitude (m)
+ float fUnc_SMaj; // semi-major axis of error ellipse (m)
+ float fUnc_SMin; // semi-minor axis of error ellipse (m)
+ UINT16 u2Maj_brg; // bearing of the semi-major axis (degrees) [0 - 179]
+ float fUnc_Vert; // Altitude uncertainty
+ UINT8 u1Conf; // The confidence by which the position is known to be within the shape description, expressed as a percentage. [0 ~ 100] (%)
+ UINT16 u2HSpeed; // Horizontal speed (km/hr)
+ UINT16 u2Bearing; // Direction (degree) of the horizontal speed [0 ~ 359]
+} MTK_GPS_AGPS_CMD_MA_LOC_T;
+typedef struct
+{
+ double dfClkDrift; // GPS Clock Frequency Error [nsec/sec]
+ INT32 i4ClkRMSAcc; // Frequency Measurement RSM Accuracy [nsec/sec]
+ INT32 i4ClkAge; // Age (sec) of the clock drift value since last estimated
+} MTK_GPS_ASSIST_CLK_T;
+
+typedef struct
+{
+ INT8 i1a0; // Klobuchar - alpha 0 (seconds) / (2^-30)
+ INT8 i1a1; // Klobuchar - alpha 1 (sec/semi-circle) / (2^-27/PI)
+ INT8 i1a2; // Klobuchar - alpha 2 (sec/semi-circle^2) / (2^-24/PI^2)
+ INT8 i1a3; // Klobuchar - alpha 3 (sec/semi-circle^3) / (2^-24/PI^3)
+ INT8 i1b0; // Klobuchar - beta 0 (seconds) / (2^11)
+ INT8 i1b1; // Klobuchar - beta 1 (sec/semi-circle) / (2^14/PI)
+ INT8 i1b2; // Klobuchar - beta 2 (sec/semi-circle^2) / (2^16/PI^2)
+ INT8 i1b3; // Klobuchar - beta 3 (sec/semi-circle^3) / (2^16/PI^3)
+} MTK_GPS_ASSIST_KLB_T;
+
+typedef struct
+{
+ INT32 i4A1; // UTC parameter A1 (seconds/second)/(2^-50)
+ INT32 i4A0; // UTC parameter A0 (seconds)/(2^-30)
+ UINT8 u1Tot; // UTC reference time of week (seconds)/(2^12)
+ UINT8 u1WNt; // UTC reference week number (weeks)
+ INT8 i1dtLS; // UTC time difference due to leap seconds before event (seconds)
+ UINT8 u1WNLSF; // UTC week number when next leap second event occurs (weeks)
+ UINT8 u1DN; // UTC day of week when next leap second event occurs (days)
+ INT8 i1dtLSF; // UTC time difference due to leap seconds after event (seconds)
+} MTK_GPS_ASSIST_UCP_T;
+
+typedef struct
+{
+ INT8 i1NumBad; // Number of Bad Satellites listed
+ UINT8 au1SvId[MTK_GPS_SV_MAX_PRN]; // A list of bad SV id
+} MTK_GPS_ASSIST_BSV_T;
+
+
+typedef struct
+{
+ UINT8 u1SV; // SV PRN number (1 ~ 32) (0 means no data available)
+ INT32 i4GPSTOW; // TOW of last Acquisition Assistance data, Units 0.08 sec
+ INT16 i2Dopp; // Doppler value. Units 2.5 Hz
+ INT8 i1DoppRate; // Doppler rate of change. Units (1/42) Hz/s
+ UINT8 u1DoppSR; // Doppler search range. index. [0 ~ 4]
+ UINT16 u2Code_Ph; // C/A Code Phase chips [range 0..1022]
+ // relative to the previous msec edge
+ INT8 i1Code_Ph_Int; // Integer C/A Code msec into the GPS Data Bit
+ // [range 0..19 msec] (-1 if not known)
+ INT8 i1GPS_Bit_Num; // GPS Data Bit Number, modulo 80 msec [range 0..3]
+ // (-1 if not known)
+ UINT8 u1CodeSR; // Code search range. index. [0 ~ 15]
+ UINT8 u1Azim; // Azimuth. Units 11.25 degrees
+ UINT8 u1Elev; // Elevation. Units 11.25 degrees
+} MTK_GPS_ASSIST_ACQ_T;
+
+
+#define RTCM_MAX_N_SAT 11
+typedef struct
+{
+ UINT8 u1SatID; // [1 - 32]
+ UINT8 u1IODE; // [0 - 255]
+ UINT8 u1UDRE; // [0 - 3]
+ INT16 i2PRC; // [-655.04 - 655.04], Units 0.32m
+ INT8 i1RRC; // [-4.064 - 4.064], Units 0.032m
+} MTK_GPS_RTCM_SV_CORR_T;
+
+typedef struct
+{
+ UINT32 u4Tow; // the baseline time for the corrections are valid [0 - 604799]
+ UINT8 u1Status; // the status of the differential corrections [0 - 7]
+ UINT8 u1NumSv; // the number of satellites for which differential corrections are available [1 - 11]
+ MTK_GPS_RTCM_SV_CORR_T arSVC[RTCM_MAX_N_SAT];
+} MTK_GPS_ASSIST_DGP_T;
+
+#define TOW_MAX_N_SAT 11
+typedef struct
+{
+ UINT8 u1SatID; // [1 - 32]
+ UINT16 u2TLM; // [0 - 16383]
+ UINT8 u1Anti_s; // [0 - 1]
+ UINT8 u1Alert; // [0 - 1]
+ UINT8 u1Reserved; // [0 - 3]
+} MTK_GPS_TOW_SV_T;
+
+typedef struct
+{
+ UINT16 u2WN; // GPS week number (weeks)
+ UINT32 u4Tow; // GPS time of week of the TLM message applied [0 - 604799]
+ UINT8 u1NumSv; // the number of satellites for which TOW assist are available [1 - 11]
+ MTK_GPS_TOW_SV_T atSV[TOW_MAX_N_SAT];
+} MTK_GPS_ASSIST_TOW_T;
+
+typedef struct
+{
+ MTK_GPS_BOOL fgAcceptAlm; // Satellite Almanac
+ MTK_GPS_BOOL fgAcceptUcp; // UTC Model
+ MTK_GPS_BOOL fgAcceptKlb; // Ionospheric Model
+ MTK_GPS_BOOL fgAcceptEph; // Navigation Model
+ MTK_GPS_BOOL fgAcceptDgps; // DGPS Corrections
+ MTK_GPS_BOOL fgAcceptLoc; // Reference Location
+ MTK_GPS_BOOL fgAcceptTim; // Reference Time
+ MTK_GPS_BOOL fgAcceptAcq; // Acquisition Assistance
+ MTK_GPS_BOOL fgAcceptBsv; // Real-Time Integrity
+} MTK_GPS_AGPS_CMD_ACCEPT_MAP_T;
+
+typedef struct
+{
+ UINT32 u4Frame; // BTS Reference Frame number during which the location estimate was measured [0 - 65535]
+ UINT16 u2WeekNo; // the GPS week number for which the location estimate is valid
+ UINT32 u4TowMS; // the GPS TOW (ms) for which the location estimate is valid [0 - 604799999]
+ UINT8 u1FixType; // the type of measurements performed by the MS [0: 2D or 1: 3D]
+ double dfLat; // latitude (degree)
+ double dfLon; // longitude (degree)
+ INT16 i2Alt; // altitude (m)
+ float fUnc_SMaj; // semi-major axis of error ellipse (m)
+ float fUnc_SMin; // semi-minor axis of error ellipse (m)
+ UINT16 u2Maj_brg; // bearing of the semi-major axis (degrees) [0 - 179]
+ float fUnc_Vert; // Altitude uncertainty
+ UINT8 u1Conf; // The confidence by which the position is known to be within the shape description, expressed as a percentage. [0 ~ 100] (%)
+ UINT16 u2HSpeed; // Horizontal speed (km/hr)
+ UINT16 u2Bearing; // Direction (degree) of the horizontal speed [0 ~ 359]
+} MTK_GPS_AGPS_DT_LOC_EST_T;
+
+
+typedef struct // Satellite Pseudorange Measurement Data
+{
+ UINT8 u1PRN_num; // Satellite PRN number [1 - 32]
+ UINT8 u1SNR; // Satellite Signal to Noise Ratio [dBHz} (range 0-63)
+ INT16 i2Dopp; // Measured Doppler frequency [0.2 Hz] (range +/-6553.6)
+ UINT16 u2Code_whole; // Satellite Code phase measurement - whole chips
+ // [C/A chips] (range 0..1022)
+ UINT16 u2Code_fract; // Satellite Code phase measurement - fractional chips
+ // [2^-10 C/A chips] (range 0..1023)
+ UINT8 u1Mul_Path_Ind; // Multipath indicator (range 0..3)
+ // (see TIA/EIA/IS-801 Table 3.2.4.2-7)
+ UINT8 u1Range_RMS_Exp;// Pseudorange RMS error: Exponent (range 0..7)
+ // (see TIA/EIA/IS-801 Table 3.2.4.2-8)
+ UINT8 u1Range_RMS_Man;// Pseudorange RMS error: Mantissa (range 0..7)
+ // (see TIA/EIA/IS-801 Table 3.2.4.2-8)
+
+} MTK_GPS_AGPS_PRM_SV_DATA_T; // Satellite Pseudorange Measurement Data
+
+typedef struct
+{
+ UINT32 u4Frame; // [0 - 65535]
+ UINT8 u1NumValidMeas; // Number of valid measurements available (0..NUM_CH)
+ UINT32 u4GpsTow; // Time of validity [ms] modulus 14400000
+ MTK_GPS_AGPS_PRM_SV_DATA_T SV_Data[AGPS_RRLP_MAX_PRM]; // Satellite Pseudorange Measurement Data
+} MTK_GPS_AGPS_DT_GPS_MEAS_T; // RRLP Pseudorange Data
+
+typedef struct
+{
+ UINT8 u1Type;
+} MTK_GPS_AGPS_DT_FTIME_ERR_T;
+
+typedef struct
+{
+ UINT16 u2AckCmd;
+ UINT8 u1Flag;
+} MTK_GPS_AGPS_DT_ACK_T;
+
+typedef struct
+{
+ UINT8 u1Type;
+} MTK_GPS_AGPS_DT_LOC_ERR_T;
+
+typedef struct
+{
+ UINT16 u2BitMap;
+ // bit0 0x0001 // almanac
+ // bit1 0x0002 // UTC model
+ // bit2 0x0004 // ionospheric model
+ // bit3 0x0008 // navigation data
+ // bit4 0x0010 // DGPS corrections
+ // bit5 0x0020 // reference location
+ // bit6 0x0040 // reference time
+ // bit7 0x0080 // acquisition assistance
+ // bit8 0x0100 // Real-Time integrity
+} MTK_GPS_AGPS_DT_REQ_ASSIST_T;
+typedef struct
+{
+
+ UINT8 u1FixType;
+ UINT8 u1FixQuality;
+ UINT8 u1SelectType;
+ double dfWRTSeaLevel;
+ float dfPDOP;
+ float dfHDOP;
+ float dfVDOP;
+
+ UINT8 u1SatNumInUse;
+ UINT8 SVInUsePRNs[MTK_GPS_SV_MAX_NUM];
+
+ UINT8 u1SatNumInView;
+ UINT8 u1SVInViewPRNs[MTK_GPS_SV_MAX_NUM];
+ INT8 u1SVInViewEle[MTK_GPS_SV_MAX_NUM];
+ UINT16 u1SVInViewAzi[MTK_GPS_SV_MAX_NUM];
+ float u1SVInViewSNR[MTK_GPS_SV_MAX_NUM];
+
+} MTK_GPS_AGPS_DT_LOC_EXTRA_T;
+#if defined(AGPS_SUPPORT_GNSS)
+//start for AGPS_SUPPORT_GNSS
+/* for AGPS with GNSS supported GNSS assist bitmap */
+
+/* The BITMAP is define for PMTK760 coding operation of MODEM/AGPSD/MNL , but NOT the same as GNSS ID(3GPP protocol). */
+#define BITMAP_GPS 0
+#define BITMAP_GLONASS 1
+#define BITMAP_GALILEO 2
+#define BITMAP_BEIDOU 3
+
+
+#define BITINDEX_TMOD 0
+#define BITINDEX_DGNSS 1
+#define BITINDEX_EPH 2
+#define BITINDEX_RTI 3
+#define BITINDEX_DBA 4
+#define BITINDEX_AA 5
+#define BITINDEX_ALM 6
+#define BITINDEX_UTC 7
+#define BITINDEX_AUX 8
+
+#define BITMAP_TMOD 0x0001
+#define BITMAP_DGNSS 0x0002
+#define BITMAP_EPH 0x0004
+#define BITMAP_RTI 0x0008
+#define BITMAP_DBA 0x0010
+#define BITMAP_AA 0x0020
+#define BITMAP_ALM 0x0040
+#define BITMAP_UTC 0x0080
+#define BITMAP_AUX 0x0100
+
+typedef struct
+{
+ //UINT16 u2BitMap;
+ MTK_GPS_BOOL fgReqTime; //commonAssistDataReq: GNSS reference time request flag
+ MTK_GPS_BOOL fgReqLoc; //commonAssistDataReq: GNSS reference location request flag
+ MTK_GPS_BOOL fgReqIon; //commonAssistDataReq: GNSS reference Inospheris request flag
+ MTK_GPS_BOOL fgReqEop; //commonAssistDataReq: GNSS reference EarthOrentationParameters request flag
+ UINT16 u2BitMap[GNSS_ID_MAX_NUM]; //GenerateAssistDataReq: u2BitMap
+ // bit0 0x0001 // Time mode Request
+ // bit1 0x0002 // Differential Corrections Request
+ // bit2 0x0004 // Navigation Model(Ephemeris) Request
+ // bit3 0x0008 // Real-Time Integrity Request
+ // bit4 0x0010 // Data Bit Assistance Request
+ // bit5 0x0020 // Acquisition Assist Request
+ // bit6 0x0040 // Almanac Request
+ // bit7 0x0080 // UTC Model Request
+ // bit8 0x0100 // Auxiliary Information Request
+} MTK_AGNSS_DT_REQ_ASSIST_T;
+
+typedef struct
+{
+
+ UINT8 u1GnssTimeID; /* gnss system time ID:eque to GNSS-ID(,0-GPS,1-SBAS, 2-QZSS,3-Galileo,4-GLONASS, 5~16 reserved) */
+ INT16 i2DayNo; /* [0-32767] gnssDayNumber do not report DayNo to server */
+ UINT32 u4Todms; /* [0-3599999] in seconds */
+ UINT16 u2GnssIDsInUse; //in-use GNSSID bitmap :
+ //bit 0:gps
+ //bit 1:sbas
+ //bit 2:qzss
+ //bit 3:galileo
+ //bit 4:glonass
+ //bit 5~15:reserved
+
+ UINT8 u1FixType; // the type of measurements performed by the MS [0: 2D or 1: 3D]
+ double dfLat; // latitude (degree)
+ double dfLon; // longitude (degree)
+ INT16 i2Alt; // altitude (m)
+ float fUnc_SMaj; // semi-major axis of error ellipse (m)
+ float fUnc_SMin; // semi-minor axis of error ellipse (m)
+ UINT16 u2Maj_brg; // bearing of the semi-major axis (degrees) [0 - 179]
+ float fUnc_Vert; // Altitude uncertainty
+ UINT8 u1Conf; // The confidence by which the position is known to be within the shape description, expressed as a percentage. [0 ~ 100] (%)
+ UINT16 u2HSpeed; // Horizontal speed (km/hr)
+ UINT16 u2Bearing; // Direction (degree) of the horizontal speed [0 ~ 359]
+
+ UINT16 u4Frame;
+ UINT16 u2GnssIDsUsed;
+ float fUnc_SMaj_Raw; // Raw semi-major axis of error ellipse (m)
+ float fUnc_SMin_Raw; // Raw semi-minor axis of error ellipse (m)
+ float fUnc_Vert_Raw; // Raw altitude uncertainty
+
+} MTK_AGNSS_DT_LOC_EST_T;
+
+typedef struct
+{
+
+ UINT16 u1PRN_num; //
+ MTK_GNSS_ID_ENUM eGnssID; //in-use GNSSID :
+ //bit 0:gps
+ //bit 1:sbas
+ //bit 2:qzss
+ //bit 3:galileo
+ //bit 4:glonass
+ //bit 5~15:reserved
+ UINT8 u2SignalID; //in-use signal ID :
+ //now for GPS only support GNSS_SGN_ID_VALUE_GPS_L1C_A
+ //now for GLONASS only support GNSS_SGN_ID_VALUE_GLONASS_G1
+ //now for QZSS only support GNSS_SGN_ID_VALUE_QZSS_L1C_A
+
+ UINT8 u1SNR; //[0..63] SNR
+ INT16 i2Dopp; // [-32768..32767]
+ UINT32 u4CodePh; //[0..2097151] ms 21-bits with 2^-21 resolution
+ UINT8 u1CodePhInt; //[0~127] ms
+ UINT8 u1Mul_Path_Ind; //[0~3] refer to RRLP table A.9
+
+ UINT8 u1CarryQualInd; //[0~3]
+ UINT32 u1Adr; //[0..33554431] 25-bits with 2^-10 resolution
+ UINT8 u1Range_RMS_Man ; //Pseudorange RMS Error mantissa
+ UINT8 u1Range_RMS_Exp; //Pseudorange RMS Error Exponent
+
+ UINT8 u1SigBitmap;
+}MTK_GPS_AGNSS_PRM_SV_DATA_T;
+#define AGNSS_RRLP_MAX_PRM 78
+typedef struct
+{
+ UINT8 u1NumValidGPSSig;
+ UINT8 u1GPSSigIDs;
+ UINT8 u1NumValidGLOSig;
+ UINT8 u1GLOSigIDs;
+}MTK_AGNSS_SIGNALIDS_T;
+
+typedef struct
+{
+
+ UINT8 u1GnssTimeID; /* gnss system time ID:eque to GNSS-ID(,0-GPS,1-SBAS, 2-QZSS,3-Galileo,4-GLONASS, 5~16 reserved) */
+ INT16 i2DayNo;
+ UINT32 u4Todms; /* [0-3599999] in ms */
+ UINT16 u2TodFrag; /* [0-3999] with resolution of 250ns optional */
+ UINT32 u4TodUnc ; /* [0-127] with resolution of 250ns optional */
+ UINT8 u1NumValidMeas;
+ UINT8 u1NumValidGnss;
+ UINT16 u2GnssIDsInUse; //in-use GNSSID bitmap
+ MTK_AGNSS_SIGNALIDS_T u1SignalIDsInUse; //in-use GNSSID bitmap :
+ UINT8 u1CodePhAmb; // [0~127 ]the codephase ambiguity in interge ms default set to 0¡£ optional
+ MTK_GPS_AGNSS_PRM_SV_DATA_T SV_Data[AGNSS_RRLP_MAX_PRM]; // Satellite Pseudorange Measurement Data
+
+} MTK_AGNSS_DT_MEAS_T; // RRLP Pseudorange Data MTK_AGNSS_DT_REQ_ASSIST_T
+//MTK_GPS_AGPS_DT_GPS_MEAS_T
+
+
+/*=== GNSS Common Assistance Data ===*/
+typedef struct
+{
+ UINT8 u1GnssTimeID; /* gnss system time ID:eque to GNSS-ID(,0-GPS,1-SBAS, 2-QZSS,3-Galileo,4-GLONASS, 5~16 reserved) */
+ /**
+ * This field specifies the sequential number of days from the origin of the GNSS System Time as follows:
+ * GPS, QZSS, SBAS Days from January 6th 1980 00:00:00 UTC(USNO)
+ * Galileo ¡V TBD;
+ * GLONASS ¡V Days from January 1st 1996
+ */
+ UINT16 u2DN; /* [0-32767] gnssDayNumber */
+ double dfTod; /* [0-86399.999] in seconds */
+ double dfTodRms; /* K = [0..127], uncertainty r (microseconds) = C*(((1+x)^K)-1), C=0.5, x=0.14 */
+ MTK_GPS_BOOL u1NotifyLeap; /* [0~1] flag to notify leap second only present when gnss=GLONASS */
+ MTK_GPS_BOOL fgTimeComp; /* TRUE: indicate ref time compensation from modem , FALSE: no ref time composate */
+ double dfTimeDelay; /* the ref time compensation */
+ UINT8 ganssDayCycleNumber;//INTEGER(0..7) -- GPS Acquisition Assistance Rel-10 Extension
+} MTK_GNSS_ASSIST_TIM_T;
+
+typedef MTK_GPS_ASSIST_LOC_T MTK_GNSS_ASSIST_LOC_T;
+
+/* start for gnss ionospheric model */
+
+//gnss Klobuchar model
+typedef struct
+{
+ UINT8 u1DataID; /*bit[0..1] : "11"generated by QZSS. aplicable within the area of QZSS */
+ /* "00"generated by GPS,GLONASS. aplicable worldwild */
+ MTK_GPS_ASSIST_KLB_T rdata; /*these field is simillar to GPS Klobuchar struct */
+
+}MTK_GNSS_ASSIST_KLB_T;
+
+//gnss NeQuick model
+typedef struct
+{
+ UINT16 u2Ai0; /* [0..4095] */
+ UINT16 u2Ai1; /* [0..4095] */
+ UINT16 u2Ai2; /* [0..4095] */
+ /* optional field */
+ /**
+ * iono storm flag represent five region: [value 0: no disturbance, value 1: disturbance]
+ * region 1: for the northern region (60¢X<MODIP<90¢X)
+ * region 2: for the northern middle region (30¢X<MODIP<60¢X)
+ * region 3: for the equatorial region (-30¢X<MODIP<30¢X)
+ * region 4: for the southern middle region (-60¢X<MODIP<-30¢X)
+ * region 5: for the southern region (-90¢X<MODIP<-60¢X)
+ */
+ UINT8 u2StValidBit; /*Stormflag valid bitmap to indicate if fgStormFlag is aviliable or not */
+ /*bit0 -> indicate fgStormFlag[0] aviliable or not*/
+ /*bit1 -> indicate fgStormFlag[1] aviliable or not*/
+ /*bit2 -> indicate fgStormFlag[2] aviliable or not*/
+ /*bit3 -> indicate fgStormFlag[3] aviliable or not*/
+ /*bit4 -> indicate fgStormFlag[4] aviliable or not*/
+ MTK_GPS_BOOL fgStormFlag[5];
+
+}MTK_GNSS_ASSIST_NQK_T;
+
+typedef struct
+{
+ UINT8 u1InoModel; /*[0~7] 0: INO Klobuchar Model -used for GPS,GLONASS,QZSS */
+ /* 1: NeQuick Model - used for Galileo */
+ union
+ {
+ MTK_GNSS_ASSIST_KLB_T rAKlb; /*Klobuchar Model */
+ MTK_GNSS_ASSIST_NQK_T rANqk; /*NeQuick Model */
+ }data;
+
+}MTK_GNSS_ASSIST_ION_T;
+
+/* end for gnss ionospheric model */
+
+
+/* start for gnss earth orientation parameters */
+typedef struct
+{
+ UINT16 u2Teop; /* [0..65535], EOP data reference time in seconds, scale factor 2^4 seconds */
+ INT32 i4PmX; /* [-1048576..1048575], X-axis polar motion value at reference time in arc-seconds, scale factor 2^(-20) arc-seconds */
+ INT16 i2PmXdot; /* [-16384..16383], X-axis polar motion drift at reference time in arc-seconds/day, scale factor 2^(-21) arc-seconds/day */
+ INT32 i4PmY; /* [-1048576..1048575], Y-axis polar motion value at reference time in arc-seconds, scale factor 2^(-20) arc-seconds */
+ INT16 i2PmYdot; /* [-16384..16383] Y-axis polar motion drift at reference time in arc-seconds/day, scale factor 2^(-21) arc-seconds/day */
+ INT32 i4DeltaUT1; /* [-1073741824..1073741823], UT1-UTC diff at reference time in seconds, scale factor 2^(-24) seconds */
+ INT32 i4DeltaUT1dot; /* [-262144..262143], the rate of UT1-UTC diff at reference time in seconds/day, scale factor 2^(-25) seconds/day */
+} MTK_GNSS_ASSIST_EOP_T;
+/* end for gnss earth orientation parameters */
+
+
+
+
+/*=== GNSS Generic Assistance Data ===*/
+
+/* start for gnss time model */
+/**
+ * in LPP, location server could provide up to 15 GNSS-GNSS system time offset
+ * in RRC/RRLP, location server could provide up to 7 GNSS-GNSS system time offset
+ * i.e. generic assist data is for GPS, time model could provide GPS-GLONASS time offset
+ */
+typedef struct
+{
+ /* note that RRC/RRLP tA0, tA1 range is larger than LPP, although scale factor is the same */
+ MTK_GNSS_ID_ENUM eGnssID;
+ UINT16 u2TmodTOW; /* [0..65535], the reference time of week TOW , scale factor 2^4 seconds */
+ INT32 i4Ta0; /* [-67108864..67108863] for LPP, [-2147483648 .. 2147483647] for RRC/RRLP, the bias coefficient, scale factor 2^(-35) seconds */
+ INT16 i2Ta1; /* [-4096..4095] for LPP, [-8388608 .. 8388607] for RRC/RRLP, the drift coefficient, scale factor 2^(-51) seconds/second */
+ INT8 i1Ta2; /* [-64..63], the drift rate correction coefficient, scale factor 2^(-68) seconds/second^2 */
+ MTK_GNSS_TO_ID_ENUM eGnssToId; /* GPS, Galileo, QZSS, GLOANSS */
+ /* optional field */
+ UINT16 u2WeekNo; /* [0..8191], the reference week */
+ INT8 i1DeltaT; /* [-128..127], the integer number of seconds of GNSS-GNSS time offset */
+} MTK_GNSS_ASSIST_TMOD_T;
+
+
+typedef MTK_GPS_ASSIST_EPH_T MTK_ASSIST_GPS_EPH_T;
+//aGLONASS EPH
+typedef struct
+{
+ UINT8 u1SvId; // GLONASS SV PRN number 1~24
+ UINT32 au4Word[GLO_EPH_WORD_MAX];
+} MTK_GLO_ASSIST_EPH_T;
+
+typedef struct
+{
+ UINT8 u1SvId; // BD SV PRN number 1~30
+ UINT32 au4Word[BDS_EPH_WORD_MAX];
+} MTK_BDS_ASSIST_EPH_T;
+
+#ifdef SUPPORT_AGA
+typedef struct
+{
+ UINT8 u1SvId; // Gallileo SV PRN number 1~30
+ UINT32 au4Word[GAL_EPH_WORD_MAX];
+} MTK_GAL_ASSIST_EPH_T;
+#endif
+
+typedef struct
+{
+ UINT8 u1SvId;
+ UINT32 au4Word[GPS_L5_EPH_WORD_MAX];
+} MTK_GPS_L5_ASSIST_EPH_T;
+typedef struct
+{
+ MTK_GNSS_ID_ENUM eGnssID;
+
+ union
+ {
+ MTK_GPS_ASSIST_EPH_T rAGpsEph; /* for GPS eph */
+ MTK_GLO_ASSIST_EPH_T rAGloEph; /* for GLO eph */
+ MTK_BDS_ASSIST_EPH_T rABDEph; /* for BD eph */
+ // MTK_QZS_ASSIST_EPH_T rAQzsEph; /* for GLONASS */
+ MTK_GAL_ASSIST_EPH_T rAGAEph; /* for Gallileo */
+ MTK_GPS_L5_ASSIST_EPH_T rAGpsL5Eph; /* for GPS L5*/
+ } data;
+} MTK_GNSS_ASSIST_EPH_T;
+
+//aGLONASS ALM
+typedef struct
+{
+ UINT8 u1SvId;//GLONASS SV PRN:1~24
+ UINT16 u2DayNum;
+ UINT32 au4Word[GLO_ALM_WORD_MAX];
+} MTK_GLO_ASSIST_ALM_T;
+
+//ABD ALM
+typedef struct
+{
+ UINT8 u1SvId;
+ UINT16 u2DayNum;
+ UINT32 au4Word[BDS_ALM_WORD_MAX];
+} MTK_BDS_ASSIST_ALM_T;
+
+#ifdef SUPPORT_AGA
+typedef struct
+{
+ UINT8 u1SvId;
+ UINT16 u2WeekNo;
+ UINT8 au1Word[GAL_ALM_WORD_MAX];
+} MTK_GAL_ASSIST_ALM_T;
+#endif
+
+typedef struct
+{
+ UINT8 u1SvId;
+ UINT16 u2WeekNo;
+ UINT32 au4Word[GPS_L5_ALM_WORD_MAX];
+} MTK_GPS_L5_ASSIST_ALM_T;
+typedef struct
+{
+ MTK_GNSS_ID_ENUM eGnssID;
+
+ union
+ {
+ MTK_GPS_ASSIST_ALM_T rAGpsAlm; /* for GPS alm */
+ MTK_GLO_ASSIST_ALM_T rAGloAlm; /* for GLONASS alm */
+ MTK_BDS_ASSIST_ALM_T rABDAlm; /* for BDS alm */
+ MTK_GAL_ASSIST_ALM_T rAGAAlm; /* for Gallileo */
+ MTK_GPS_L5_ASSIST_ALM_T rAGpsL5Alm; /* for GPS L5*/
+ } data;
+} MTK_GNSS_ASSIST_ALM_T;
+
+/* start for gnss real time integrity */
+
+typedef struct
+{
+ UINT16 u1SVID;
+ UINT8 u1BSignalIDs; /* identidy the bad signal or signals of a satellite, bit string representation, map to GNSS_SGN_ID_BITMAP_* */
+} MTK_GNSS_ASSIST_BSIG_T;
+
+typedef struct
+{
+ MTK_GNSS_ID_ENUM eGnssID;
+ UINT8 u1BsvNum;
+ MTK_GNSS_ASSIST_BSIG_T rBsv[MGPSID];
+} MTK_GNSS_ASSIST_BSV_T;
+/* end for gnss real time integrity */
+
+
+/* start for gnss acquisition assistance */
+typedef struct
+{
+ MTK_GNSS_ID_ENUM eGnssID;
+ UINT16 u2SvId; //,GPS:1~32 GLO:65~96
+ UINT8 u1SigID; /* GNSS type, map to GNSS_SGN_ID_VALUE_* */
+ UINT8 u1Conf; /* [0..100] only for LPP */
+ double dfTod; /* [0-86399.999] in seconds */
+ INT16 i2Dopp0; /* [-2048..2047], Doppler (0th order term) value for velocity, scale factor 0.5 m/s in th range from -1024 m/s to +1023.5 m/s */
+ UINT8 u1Dopp1; /* [0..63], i1DoppRate, Doppler (1th order term) value for acceleration, scale factor 1/210 m/s^2 in the range from -0.2 m/s^2 to +0.1 m/s^2 */
+ UINT8 u1DoppSR; /* [0..4], defined values: 2.5 m/s, 5 m/s, 10 m/s, 20 m/s, 40 m/s encoded as integer range 0-4 by 2^(-n)*40 m/s, n=0-4 */
+ UINT16 u2CodePh; /* [0..1022], scale factor 2^(-10) ms in the range from 0 to (1-2^(-10)) ms */
+ UINT8 u1CodePhInt; /* [0..127], integer codephase, scale factor 1ms */
+ UINT8 u1CodePhSR; /* [0..31], map to value-to-searchwindow table (ms) */
+ UINT16 u2Azim; /* [0..511], azimuth angle a, x-degrees of satellite x<=a<x+0.703125, scale factor 0.703125 degrees */
+ UINT8 u1Elev; /* [0..127], elevation angle e, y-degrees of satellite y>=e<y+0.703125, scale factr 0.703125 degrees */
+ /* optional field */
+ MTK_GPS_BOOL fgCodePh1023; /* only use if codePhase is 1022, codePhase value is 1023*2^(-10) = (1-2^(-10)) ms */
+ /* if support dopplerUncertaintyExtR10, should ignore dopplerUncertainty field */
+ MTK_GNSS_ACQ_DOPP_UNCERT_EXT_ENUM u1DopExtEnum; /* enumerated value map to 60 m/s, 80 m/s, 100 m/s, 120 ms, and No Information */
+ UINT8 u1CodeSR;
+
+} MTK_GNSS_ASSIST_ACQ_T;
+/* end for gnss acquisition assistance */
+
+/* start for gnss acquisition assistance */
+typedef struct
+{
+ double GPSTOW;
+ double dfGNSSTOD;
+ MTK_GPS_BOOL AzElIncl;
+ MTK_GPS_BOOL UseEph;
+ unsigned char NumSV;
+ UINT16 SV[24]; //,GPS:1~32 GLO:65~96
+ UINT8 u1SigID[24]; /* GNSS type, map to GNSS_SGN_ID_VALUE_* */
+ UINT8 u1Conf[24]; /* [0..100] only for LPP */
+ double dfTod[24]; /* [0-86399.999] in seconds */
+ INT16 Dopp[24]; /* [-2048..2047], Doppler (0th order term) value for velocity, scale factor 0.5 m/s in th range from -1024 m/s to +1023.5 m/s */
+ UINT8 DoppRate[24]; /* [0..63], i1DoppRate, Doppler (1th order term) value for acceleration, scale factor 1/210 m/s^2 in the range from -0.2 m/s^2 to +0.1 m/s^2 */
+ UINT8 DoppSR[24]; /* [0..4], defined values: 2.5 m/s, 5 m/s, 10 m/s, 20 m/s, 40 m/s encoded as integer range 0-4 by 2^(-n)*40 m/s, n=0-4 */
+ UINT16 Code_Ph[24]; /* [0..1022], scale factor 2^(-10) ms in the range from 0 to (1-2^(-10)) ms */
+ UINT8 Code_Ph_Int[24]; /* [0..127], integer codephase, scale factor 1ms */
+ UINT8 CodePhSR[24]; /* [0..31], map to value-to-searchwindow table (ms) */
+ UINT8 CodeSR[24];
+ UINT16 Azim[24]; /* [0..511], azimuth angle a, x-degrees of satellite x<=a<x+0.703125, scale factor 0.703125 degrees */
+ UINT8 Elev[24]; /* [0..127], elevation angle e, y-degrees of satellite y>=e<y+0.703125, scale factr 0.703125 degrees */
+ /* optional field */
+ MTK_GPS_BOOL fgCodePh1023[24]; /* only use if codePhase is 1022, codePhase value is 1023*2^(-10) = (1-2^(-10)) ms */
+ /* if support dopplerUncertaintyExtR10, should ignore dopplerUncertainty field */
+ MTK_GNSS_ACQ_DOPP_UNCERT_EXT_ENUM u1DopExtEnum[24]; /* enumerated value map to 60 m/s, 80 m/s, 100 m/s, 120 ms, and No Information */
+
+} s_NA_GLO_AcqAss;
+
+/* start for gnss acquisition assistance */
+typedef struct
+{
+ double dfGNSSTOD;
+ MTK_GPS_BOOL AzElIncl;
+ MTK_GPS_BOOL UseEph;
+ unsigned char NumSV;
+ UINT16 SV[24]; //,GPS:1~32 GLO:65~96
+ UINT8 u1SigID[24]; /* GNSS type, map to GNSS_SGN_ID_VALUE_* */
+ UINT8 u1Conf[24]; /* [0..100] only for LPP */
+ double dfTod[24]; /* [0-86399.999] in seconds */
+ INT16 Dopp[24]; /* [-2048..2047], Doppler (0th order term) value for velocity, scale factor 0.5 m/s in th range from -1024 m/s to +1023.5 m/s */
+ UINT8 DoppRate[24]; /* [0..63], i1DoppRate, Doppler (1th order term) value for acceleration, scale factor 1/210 m/s^2 in the range from -0.2 m/s^2 to +0.1 m/s^2 */
+ UINT8 DoppSR[24]; /* [0..4], defined values: 2.5 m/s, 5 m/s, 10 m/s, 20 m/s, 40 m/s encoded as integer range 0-4 by 2^(-n)*40 m/s, n=0-4 */
+ UINT16 Code_Ph[24]; /* [0..1022], scale factor 2^(-10) ms in the range from 0 to (1-2^(-10)) ms */
+ UINT8 Code_Ph_Int[24]; /* [0..127], integer codephase, scale factor 1ms */
+ UINT8 CodePhSR[24]; /* [0..31], map to value-to-searchwindow table (ms) */
+ UINT8 CodeSR[24];
+ UINT16 Azim[24]; /* [0..511], azimuth angle a, x-degrees of satellite x<=a<x+0.703125, scale factor 0.703125 degrees */
+ UINT8 Elev[24]; /* [0..127], elevation angle e, y-degrees of satellite y>=e<y+0.703125, scale factr 0.703125 degrees */
+ /* optional field */
+ MTK_GPS_BOOL fgCodePh1023[24]; /* only use if codePhase is 1022, codePhase value is 1023*2^(-10) = (1-2^(-10)) ms */
+ /* if support dopplerUncertaintyExtR10, should ignore dopplerUncertainty field */
+ MTK_GNSS_ACQ_DOPP_UNCERT_EXT_ENUM u1DopExtEnum[24]; /* enumerated value map to 60 m/s, 80 m/s, 100 m/s, 120 ms, and No Information */
+} MTK_GNSS_ASSIST_ACQ_RAW_DATA_T;
+/* end for gnss acquisition assistance */
+
+/* start for gnss acquisition assistance */
+typedef struct
+{
+ UINT16 Code_Ph[24]; /* [0..1022], scale factor 2^(-10) ms in the range from 0 to (1-2^(-10)) ms */
+ UINT8 Code_Ph_Int[24]; /* [0..127], integer codephase, scale factor 1ms */
+ UINT8 Acq_GPS_Secs;
+ MTK_GPS_BOOL AzElIncl;
+ MTK_GPS_BOOL UseEph;
+ double dfGNSSTOD;
+ UINT8 CodeSR[24];
+ unsigned char NumSV;
+ UINT16 SV[24]; //,GPS:1~32 GLO:65~96
+ UINT8 u1SigID; /* GNSS type, map to GNSS_SGN_ID_VALUE_* */
+ UINT8 u1Conf; /* [0..100] only for LPP */
+ double dfTod; /* [0-86399.999] in seconds */
+ INT16 Dopp[24]; /* [-2048..2047], Doppler (0th order term) value for velocity, scale factor 0.5 m/s in th range from -1024 m/s to +1023.5 m/s */
+ UINT8 DoppRate[24]; /* [0..63], i1DoppRate, Doppler (1th order term) value for acceleration, scale factor 1/210 m/s^2 in the range from -0.2 m/s^2 to +0.1 m/s^2 */
+ UINT8 DoppSR[24]; /* [0..4], defined values: 2.5 m/s, 5 m/s, 10 m/s, 20 m/s, 40 m/s encoded as integer range 0-4 by 2^(-n)*40 m/s, n=0-4 */
+ UINT16 CodePh[24]; /* [0..1022], scale factor 2^(-10) ms in the range from 0 to (1-2^(-10)) ms */
+ UINT8 CodePhInt[24]; /* [0..127], integer codephase, scale factor 1ms */
+ UINT8 CodePhSR[24]; /* [0..31], map to value-to-searchwindow table (ms) */
+ UINT16 Azim[24]; /* [0..511], azimuth angle a, x-degrees of satellite x<=a<x+0.703125, scale factor 0.703125 degrees */
+ UINT8 Elev[24]; /* [0..127], elevation angle e, y-degrees of satellite y>=e<y+0.703125, scale factr 0.703125 degrees */
+ /* optional field */
+ MTK_GPS_BOOL fgCodePh1023; /* only use if codePhase is 1022, codePhase value is 1023*2^(-10) = (1-2^(-10)) ms */
+ /* if support dopplerUncertaintyExtR10, should ignore dopplerUncertainty field */
+ MTK_GNSS_ACQ_DOPP_UNCERT_EXT_ENUM u1DopExtEnum; /* enumerated value map to 60 m/s, 80 m/s, 100 m/s, 120 ms, and No Information */
+} MTK_GNSS_ASSIST_ACQ_DATA_T;
+/* end for gnss acquisition assistance */
+
+typedef struct
+{
+ UINT32 Code_whole;
+ UINT32 Code_fract;
+
+ UINT16 PRN_num; //
+ INT8 i1ChannelID;
+ MTK_GNSS_ID_ENUM eGnssID; //in-use GNSSID :
+ //bit 0:gps
+ //bit 1:sbas
+ //bit 2:qzss
+ //bit 3:galileo
+ //bit 4:glonass
+ //bit 5~15:reserved
+ UINT8 u2SignalID; //in-use signal ID :
+ //now for GPS only support GNSS_SGN_ID_VALUE_GPS_L1C_A
+ //now for GLONASS only support GNSS_SGN_ID_VALUE_GLONASS_G1
+ //now for QZSS only support GNSS_SGN_ID_VALUE_QZSS_L1C_A
+
+ UINT8 SNR; //[0..63] SNR
+ INT16 Dopp; // [-32768..32767]
+ UINT32 u4CodePh; //[0..2097151] ms 21-bits with 2^-21 resolution
+ UINT8 u1CodePhInt; //[0~127] ms
+ UINT8 Mul_Path_Ind; //[0~3] refer to RRLP table A.9
+
+ UINT8 u1CarryQualInd; //[0~3]
+ UINT32 u1Adr; //[0..33554431] 25-bits with 2^-10 resolution
+ UINT8 Range_RMS_Man ; //Pseudorange RMS Error mantissa
+ UINT8 Range_RMS_Exp; //Pseudorange RMS Error Exponent
+}MTK_IS801_SV_DATA_T;
+
+typedef struct
+{
+ UINT8 Time_Ref; //I4
+ UINT8 TimeRefSrc; //I4
+ UINT8 NumValidMeas; //U4
+ UINT32 Time_Tow;
+ UINT8 u1GnssTimeID; /* gnss system time ID:eque to GNSS-ID(,0-GPS,1-SBAS, 2-QZSS,3-Galileo,4-GLONASS, 5~16 reserved) */
+ INT16 i2DayNo; /* [0-] in day */
+ UINT32 u4Todms; /* [0-3599999] in ms */
+ UINT16 u2TodFrag; /* [0-3999] with resolution of 250ns optional */
+ UINT32 u4TodUnc ; /* [0-127] with resolution of 250ns optional */
+ UINT8 u1NumValidMeas;
+ UINT8 u1NumValidGnss;
+ UINT16 u2GnssIDsInUse; //in-use GNSSID bitmap
+ MTK_AGNSS_SIGNALIDS_T u1SignalIDsInUse; //in-use GNSSID bitmap :
+ UINT8 u1CodePhAmb; // [0~127 ]the codephase ambiguity in interge ms default set to 0¡£ optional
+ MTK_IS801_SV_DATA_T SV_Data[AGNSS_RRLP_MAX_PRM]; // Satellite Pseudorange Measurement Data
+
+}s_API_IS801_GNSS_PRMeas;
+
+/* start for gnss utc model */
+/* for GPS UTC model */
+/*
+typedef struct
+{
+ INT32 i4UtcA1; //[-8388608..8388607], scale factor 2^(-50) seconds/second
+ INT32 i4UtcA0; // [-2147483648..2147483647], scale factor 2^(-30) seconds
+ UINT8 u1UtcTot; // [0..255], scale factor 2^12 seconds
+ UINT8 u1UtcWNt; // [0..255], scale factor 1 week
+ INT8 i1UtcDeltaTls; //[-128..127], scale factor 1 second
+ UINT8 u1UtcWNlsf; // [0..255], scale factor 1 week
+ INT8 i1UtcDN; // [-128..127], scale factor 1 day
+ INT8 i1UtcDeltaTlsf; // [-128..127], scale factor 1 second
+} MTK_GPS_ASSIST_UCP_T;
+*/
+
+/* for QZSS UTC model */
+typedef struct
+{
+ INT16 i2UtcA0; /* [-32768..32767], bias coefficient of GNSS time scale relative to UTC time scale, scale factor 2^(-35) seconds */
+ INT16 i2UtcA1; /* [-4096..4095], drift coefficient of GNSS time scale relative to UTC time scale, scale factor 2^(-51) seconds/second */
+ INT8 i1UtcA2; /* [-64..63], drift rate correction coefficient of GNSS time sacel relative to UTC time scale, scale factor 2^(-68) seconds/second^2 */
+ INT8 i1UtcDeltaTls; /* [-128..127], current or past leap second count, scale factor 1 second */
+ UINT16 u2UtcTot; /* [0..65535], time data reference time of week, scale factor 2^4 seconds */
+ UINT16 u2UtcWNot; /* [0..8191], time data reference week number, scale factor 1 week */
+ UINT8 u1UtcWNlsf; /* [0..255], leap second reference week number, scale factor 1 week */
+ UINT8 u1UtcDN; /* 4 bits field, leap second reference day number, scale factor 1 day */
+ INT8 i1UtcDeltaTlsf; /* [-128..127], current or future leap second count, scale factor 1 second */
+} MTK_QZSS_ASSIST_UCP_T;
+
+/* for GLONASS UTC model */
+typedef struct
+{
+ UINT16 u2nA; /* [1..1461], callendar day number within four-year period beginning since the leap year, scale factor 1 day */
+ INT32 i4tauC; /* [-2147483648..2147483647], GLONASS time scale correction to UTC(SU), scale factor 2^(-31) seconds */
+ //optional field /* mandatory present if GLONASS-M satellites are presnet in the current GLONASS constellation */
+ INT16 i2b1; /* [-1024..1023],default 0. coefficient to determine delta UT1, scale factor 2^(-10) seconds */
+ INT16 i2b2; /* [-512..511],default 0. coefficient to determind delta UT1, scale factor 2^(-16) seconds/msd */
+ UINT8 u1kp; /* 2 bits field, default 0. notification of expected leap second correction */
+} MTK_GLO_ASSIST_UCP_T;
+
+/* for SBAS UTC model */
+typedef struct
+{
+ INT32 i4UtcA1wnt; /* [-8388608..8388607], scale factor 2^(-50) seconds/second */
+ INT32 i4UtcA0wnt; /* [-2147483648..2147483647], scale factor 2^(-30) seconds */
+ UINT8 u1UtcTot; /* [0..255], scale factor 2^12 seconds */
+ UINT8 u1UtcWNt; /* [0..255], scale factor 1 week */
+ INT8 i1UtcDeltaTls; /* [-128..127], scale factor 1 second */
+ UINT8 u1UtcWNlsf; /* [0..255], scale factor 1 week */
+ INT8 i1UtcDN; /* [-128..127], scale factor 1 day */
+ INT8 i1UtcDeltaTlsf; /* [-128..127], scale factor 1 second */
+ INT8 i1UtcStandardID; /* [0..7], if GNSS-ID indicates SBAS, this field indicated the UTC stadard used for the SBAS network time indicated by SBAS-ID to UTC relation */
+} MTK_SBAS_ASSIST_UCP_T;
+
+/* for BDS UTC model */
+typedef struct
+{
+ INT32 i4UtcA0; /* [-2147483648..2147483647], scale factor 2^(-30) seconds */
+ INT32 i4UtcA1; /*[-8388608..8388607], scale factor 2^(-50) seconds/second */
+ INT8 i1UtcDeltaTls; /* [-128..127], scale factor 1 second */
+ UINT8 u1UtcWNlsf; /* [0..255], scale factor 1 week */
+ UINT8 u1UtcDN; /* [-128..127], scale factor 1 day */
+ INT8 i1UtcDeltaTlsf; /* [-128..127], scale factor 1 second */
+} MTK_BDS_ASSIST_UCP_T;
+
+#ifdef SUPPORT_AGA
+typedef struct
+{
+ INT32 i4A1; // UTC parameter A1 (seconds/second)/(2^-50)
+ INT32 i4A0; // UTC parameter A0 (seconds)/(2^-30)
+ UINT32 u4Tot; // UTC reference time of week (seconds)/(2^12)
+ UINT8 u1WNt; // UTC reference week number (weeks)
+ INT8 i1dtLS; // UTC time difference due to leap seconds before event (seconds)
+ UINT8 u1WNLSF; // UTC week number when next leap second event occurs (weeks)
+ UINT8 u1DN; // UTC day of week when next leap second event occurs (days)
+ INT8 i1dtLSF; // UTC time difference due to leap seconds after event (seconds)
+} MTK_GAL_ASSIST_UCP_T;
+#endif
+
+typedef struct
+{
+ MTK_GNSS_UTC_TYPE_ENUM u1UtcMd;
+
+ union
+ {
+ MTK_GPS_ASSIST_UCP_T utcModel1; /* for GPS */
+ MTK_QZSS_ASSIST_UCP_T utcModel2; /* for QZSS */
+ MTK_GLO_ASSIST_UCP_T utcModel3; /* for GLONASS */
+ MTK_SBAS_ASSIST_UCP_T utcModel4; /* for SBAS */
+ MTK_BDS_ASSIST_UCP_T utcModel5; /* for BDS */
+ MTK_GAL_ASSIST_UCP_T utcModel6; /* for GALILEO */
+ } data;
+} MTK_GNSS_ASSIST_UCP_T;
+/* end for gnss utc model */
+
+/* start for gnss data bit assistance */
+typedef struct
+{
+ MTK_GNSS_ID_ENUM eGnssID;
+ UINT16 u2GnssTOD; /* [0..3599999] milli-second, reference time of the first bit of the data modulo 1 hour, scale factor 1 second */
+ // UINT16 u2GnssTODms; /* [0..999], fractional part of gnssTD, scale factor 1 milli-second */
+ UINT16 u2SvId;
+ UINT8 u1SigType;
+ UINT16 u2DataBitsNum; /* data bit original max is 1024 bits */
+ UINT16 u2Num; /* x th PMTK for this SV-signal */
+ UINT16 u2NumIndex; /* Index; */
+ UINT32 au4Word[16];/* 16Word*4-byte*8-bits = 2^9 =512 bit */
+} MTK_GNSS_ASSIST_DBA_T;
+/* end for gnss data bit assistance */
+
+/* start for gnss aux info */
+typedef struct
+{
+ UINT8 u1SvId; // PRN GPS:1~32 GLO:1~24
+ UINT8 u1SigAvai; /* 8 bits field, indicate the ranging signals supported by the satellite indicated by svID */
+ /* optional field */
+ INT8 i1ChannelId; /* indicate the GLONASS carrier frequency number of the satellite identified by svID */
+ /* for GLONASS[-7..13]. if there are no this parameter, this para is set "256": 0xff
+ for GPS there is no part for this para in PMTK765.So need to handle this para besides GLONASS */
+} MTK_GNSS_ASSIST_AUX_ELE_T;
+
+typedef struct
+{
+ //MTK_GNSS_AUX_TYPE_ENUM eType;
+ MTK_GNSS_ID_ENUM eGnssID;
+ UINT8 u1GnssEleNum;
+ MTK_GNSS_ASSIST_AUX_ELE_T rGnssEle[GNSS_MAX_AUX_SAT_ELEMENT];
+
+} MTK_GNSS_ASSIST_AUX_T;
+/* end for gnss aux info */
+/* for GNSS capbility */
+
+typedef struct
+{
+ MTK_GNSS_ID_ENUM eGnssID;
+ UINT8 u1SigBitmap;
+} MTK_GNSS_SIGNAL_T;
+
+typedef struct
+{
+ MTK_GPS_BOOL fgADR;
+ MTK_GPS_BOOL fgFta;
+ MTK_GPS_BOOL fgDgnss;
+ UINT8 u1GnssNum;
+ MTK_GNSS_SIGNAL_T GnssSigIDs[GNSS_ID_MAX_NUM];
+
+ MTK_GPS_AGNSS_PRM_SV_DATA_T SV_Data[AGNSS_RRLP_MAX_PRM];
+} MTK_AGNSS_DT_CAPBILITY_T;
+typedef struct
+{
+
+ UINT8 u1GnssTimeID; /* gnss system time ID:eque to GNSS-ID(,0-GPS,1-SBAS, 2-QZSS,3-Galileo,4-GLONASS, 5~16 reserved) */
+ /**
+ * This field specifies the sequential number of days from the origin of the GNSS System Time as follows:
+ * GPS, QZSS, SBAS Days from January 6th 1980 00:00:00 UTC(USNO)
+ * Galileo ¡V TBD;
+ * GLONASS ¡V Days from January 1st 1996
+ */
+ UINT16 u2DN; /* [0-32767] gnssDayNumber */
+ double dfTod; /* [0-86399.999] in seconds */
+ double dfTodRms; /* K = [0..127], uncertainty r (microseconds) = C*(((1+x)^K)-1), C=0.5, x=0.14 */
+ double dfFTime; // sec, Frame Time correspond to GNSS TOD
+ double dfFTimeRms; // ms, Frame Time RMS accuracy
+} MTK_GNSS_ASSIST_FTA_T, MTK_GNSS_AGPS_DT_FTIME_T; // Fine Time Assistance
+#endif
+//end for AGPS_SUPPORT_GNSS
+typedef struct
+{
+ UINT8 u1Type; /* 1: co-clock clock drift ;2:.... */
+ UINT32 u4ClkErrRange; /* ppb need to convert to ppm */
+ //INT32 u4ClkErrRange; /* ppb need to convert to ppm */
+}MTK_GPS_ASSIST_FREQ_T;
+typedef struct
+{
+
+ UINT8 u1FtaType; /* Frame sync aiding type */
+ UINT16 u2WeekNum; /* [0-32767] gnssWeekNumber */
+ double dfTow; /* [0-604799.999] in seconds */
+ double dfTowOffset; /* [0-999.999] in us */
+ UINT8 u1ClkDriftFlag; // flag of clock drift. 1:
+ double dfClkDrift; // clock drift +/-20000 ppb (+/-20ppm)
+ UINT8 errType;
+} MTK_GNSS_ASSIST_FSYNC_T, MTK_GNSS_AGPS_DT_FSYNC_T; // Fine Time Assistance
+
+typedef struct
+{
+ UINT16 u2Cmd; // PMTK command ID:
+ // please get the data arguements in the following corresponding data structure.
+ union
+ {
+ MTK_GPS_AGPS_DT_ACK_T rAck; // PMTK001
+ MTK_GPS_AGPS_CMD_MODE_T rAgpsMode; // PMTK290
+ MTK_GPS_AGPS_DT_REQ_ASSIST_T rReqAssist; // PMTK730
+ MTK_GPS_AGPS_DT_LOC_EST_T rLoc; // PMTK731
+ MTK_GPS_AGPS_DT_GPS_MEAS_T rPRM; // PMTK732
+ MTK_GPS_AGPS_DT_LOC_ERR_T rLocErr; // PMTK733
+ MTK_GPS_AGPS_DT_FTIME_T rFTime; // PMTK734
+ MTK_GPS_AGPS_DT_FTIME_ERR_T rFTimeErr; // PMTK735
+ MTK_GPS_AGPS_DT_LOC_EXTRA_T rLocExtra; // PMTK742/743/744
+#if defined(AGPS_SUPPORT_GNSS)
+ MTK_AGNSS_DT_REQ_ASSIST_T rGnssReqAssist; // PMTK760
+ MTK_AGNSS_DT_LOC_EST_T rGnssLoc; // PMTK761
+ MTK_AGNSS_DT_MEAS_T rGnssPRM; // PMTK763
+ MTK_AGNSS_DT_CAPBILITY_T rGnssCap; // PMTK764
+#endif
+ } uData;
+} MTK_GPS_AGPS_RESPONSE_T;
+
+
+
+#if defined(AGPS_SUPPORT_GNSS)
+typedef struct
+{
+ UINT8 u1Arg1; // version of Query location parameters: 1:GNSS format 0:GPS format
+ UINT8 u1Arg2; // if is for early report? 1:early report 0:normal report
+ UINT8 u1Arg3;
+ UINT8 u1Arg4;
+ UINT16 u1Arg5;
+} MTK_GNSS_CMD_LOC_T;
+
+typedef struct
+{
+ UINT8 u1Arg1; // version of Query measurement parameters: 1:GNSS format 0:GPS format
+ UINT8 u1Arg2; // if is for early report? 1:early report 0:normal report
+ UINT8 u1Arg3; // multi freq measurment req?
+ UINT16 u1Arg4; // gnss bitmap
+} MTK_GNSS_CMD_MEAS_T;
+
+typedef struct
+{
+ UINT8 u1Arg1; // 1: Query parameters using GNSS format 0:GPS format
+} MTK_GNSS_CMD_BITMAP_T;
+
+typedef struct
+{
+ UINT8 u1Arg1; // 1: Query parameters using GNSS format 0:GPS format
+} MTK_GNSS_CMD_CAPB_T;
+#endif
+typedef struct
+{
+ UINT16 u2Cmd; // PMTK command ID: if the PMTK command has data arguments,
+ // please assign the data in the following corresponding data structure.
+ union
+ {
+ MTK_GPS_AGPS_CMD_MODE_T rMode; // PMTK290
+ MTK_GPS_AGPS_CMD_ACCEPT_MAP_T rAcceptMap; // PMTK292
+ MTK_GPS_AGPS_CMD_QOP_T rQop; // PMTK293
+ MTK_GPS_ASSIST_EPH_T rAEph; // PMTK710
+ MTK_GPS_ASSIST_ALM_T rAAlm; // PMTK711
+ MTK_GPS_ASSIST_TIM_T rATim; // PMTK712
+ MTK_GPS_ASSIST_LOC_T rALoc; // PMTK713
+ MTK_GPS_ASSIST_CLK_T rAClk; // PMTK714
+ MTK_GPS_ASSIST_KLB_T rAKlb; // PMTK715
+ MTK_GPS_ASSIST_UCP_T rAUcp; // PMTK716
+ MTK_GPS_ASSIST_BSV_T rABsv; // PMTK717
+ MTK_GPS_ASSIST_ACQ_T rAAcq; // PMTK718
+ MTK_GPS_ASSIST_FTA_T rAFta; // PMTK719
+ MTK_GPS_ASSIST_DGP_T rARtcm; // PMTK720
+ MTK_GPS_ASSIST_TOW_T rATow; // PMTK725
+ MTK_GPS_AGPS_CMD_MA_LOC_T rAMA_Loc; // PMTK739
+#if defined(AGPS_SUPPORT_GNSS)
+ MTK_GNSS_CMD_LOC_T rLoc; // PMTK485,1* PMTK485,0*
+ MTK_GNSS_CMD_MEAS_T rMeas; // PMTK486,1* PMTK486,0*
+ MTK_GNSS_CMD_BITMAP_T rBitMap; // PMTK487,1* PMTK487,0*
+ MTK_GNSS_CMD_CAPB_T rCapb; // PMTK493,1* PMTK493,0*
+
+ MTK_GNSS_ASSIST_TIM_T rAGnssTim; // PMTK752
+ MTK_GNSS_ASSIST_TMOD_T rAGnssTmod; // PMTK753
+ MTK_GNSS_ASSIST_ION_T rAGnssIon; // PMTK754
+ MTK_GNSS_ASSIST_UCP_T rAGnssUcp; // PMTK755
+ MTK_GNSS_ASSIST_DBA_T rAGnssDba; // PMTK756
+ MTK_GNSS_ASSIST_BSV_T rAGnssBsv; // PMTK757
+ MTK_GNSS_ASSIST_ACQ_T rAGnssAcq; // PMTK758
+ MTK_GNSS_ASSIST_EOP_T rAGnssEop; // PMTK759
+ MTK_GNSS_ASSIST_AUX_T rAGnssAux; // PMTK765
+ MTK_GNSS_ASSIST_EPH_T rAGnssEph; // PMTK710
+ MTK_GNSS_ASSIST_ALM_T rAGnssAlm; // PMTK713
+ MTK_GNSS_ASSIST_LOC_T rAGnssLoc; // PMTK712
+ MTK_GNSS_ASSIST_FTA_T rAGnssFta; // PMTK766
+#endif
+ MTK_GNSS_ASSIST_FSYNC_T rAGnssFsync; // PMTK768
+ MTK_GPS_ASSIST_FREQ_T rAGPSFreq; // PMTK680
+ } uData;
+} MTK_GPS_AGPS_CMD_DATA_T;
+
+
+#if ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 200000 ) )
+// for ADS1.x
+#elif ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400000 ) )
+// for RVCT2.x or RVCT3.x
+#else
+#pragma pack()
+#endif
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_get_param
+ * DESCRIPTION
+ * Get the current setting of the AGPS Agent
+ * PARAMETERS
+ * key [IN] the configuration you want to know
+ * value [OUT] the current setting
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_get_param (MTK_GPS_PARAM key, void* value, UINT16 srcMod, UINT16 dstMod);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_agps_set_param
+ * DESCRIPTION
+ * Change the behavior of the AGPS Agent
+ * PARAMETERS
+ * key [IN] the configuration needs to be changed
+ * value [IN] the new setting
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_set_param (MTK_GPS_PARAM key, const void* value, UINT16 srcMod, UINT16 dstMod);
+INT32
+mtk_agps_set_param_with_payload_len (MTK_GPS_PARAM key, const void* value, UINT16 srcMod, UINT16 dstMod, int len);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_agps_disaptcher_callback
+ * DESCRIPTION
+ * called by MNL when need send data
+ * PARAMETERS
+ * type: msg type, length: payload length, data: payload pointer
+ * RETURNS
+ * none
+ *****************************************************************************/
+INT32
+mtk_gps_sys_agps_disaptcher_callback (UINT16 type, UINT16 length, char *data);
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif
+
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_bee.h b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_bee.h
new file mode 100644
index 0000000..06f8933
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_bee.h
@@ -0,0 +1,69 @@
+/***********************************************************************
+* This software/firmware and related documentation ("MediaTek Software")
+* are protected under relevant copyright laws. The information contained
+* herein is confidential and proprietary to MediaTek Inc. and/or its licensors.
+*
+* Without the prior written permission of MediaTek Inc. and/or its licensors,
+* any reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly prohibited.
+*
+* MediaTek Inc. (C) [2009]. All rights reserved.
+*
+*************************************************************************/
+#ifndef MTK_GPS_BEE_H
+#define MTK_GPS_BEE_H
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "mtk_gps_type.h"
+
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_bee_init
+ * DESCRIPTION
+ * Initialize BEE module
+ * PARAMETERS
+ * path [IN] single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_bee_init(UINT8 *path);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_bee_uninit
+ * DESCRIPTION
+ * Un-initialize BEE module
+ * PARAMETERS
+ * void
+ * RETURNS
+ * void
+ *****************************************************************************/
+void
+mtk_gps_bee_uninit(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_bee_gen
+ * DESCRIPTION
+ * Generate BEE data
+ * PARAMETERS
+ * void
+ * RETURNS
+ * void
+ *****************************************************************************/
+void
+mtk_gps_bee_gen(void);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_driver_wrapper.h b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_driver_wrapper.h
new file mode 100644
index 0000000..2ab4442
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_driver_wrapper.h
@@ -0,0 +1,97 @@
+/***********************************************************************
+* This software/firmware and related documentation ("MediaTek Software")
+* are protected under relevant copyright laws. The information contained
+* herein is confidential and proprietary to MediaTek Inc. and/or its licensors.
+*
+* Without the prior written permission of MediaTek Inc. and/or its licensors,
+* any reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly prohibited.
+*
+* MediaTek Inc. (C) [2008]. All rights reserved.
+*
+*************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * mtk_gps_driver_wrapper.h
+ *
+ * Description:
+ * ------------
+ * Prototype of driver layer API
+ *
+ ****************************************************************************/
+
+#ifndef MTK_GPS_DRIVER_WRAPPER_H
+#define MTK_GPS_DRIVER_WRAPPER_H
+
+#include "mtk_gps_type.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_threads_create
+ * DESCRIPTION
+ * Create MNL thread in the porting layer
+ * PARAMETERS
+ * void
+ * RETURNS
+ * MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32
+mtk_gps_threads_create(MTK_GPS_THREAD_ID_ENUM thread_id);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_threads_release
+ * DESCRIPTION
+ * Release MNL thread (array) in the porting layer
+ * PARAMETERS
+ * void
+ * RETURNS
+ * MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32
+mtk_gps_threads_release(void);
+
+//----------------------------------------------------------------------------------
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_mnl_run
+ * DESCRIPTION
+ * RUN MTK Nav Library
+ * PARAMETERS
+ * default_cfg [IN] factory default configuration
+ * driver_dfg [IN] UART/COM PORT setting
+ * RETURNS
+ * MTK_GPS_BOOT_STATUS
+ *****************************************************************************/
+MTK_GPS_BOOT_STATUS
+mtk_gps_mnl_run(const MTK_GPS_INIT_CFG* default_cfg, const MTK_GPS_DRIVER_CFG* driver_dfg);
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_mnl_stop
+ * DESCRIPTION
+ * STOP MTK Nav Library
+ * PARAMETERS
+ * void
+ * RETURNS
+ * void
+ *****************************************************************************/
+void
+mtk_gps_mnl_stop(void);
+
+
+INT32
+mtk_gps_sys_event_wait_timeout(MTK_GPS_EVENT_ENUM event_idx,int time_sec);
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* MTK_GPS_DRIVER_WRAPPER_H */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_sys_fp.h b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_sys_fp.h
new file mode 100644
index 0000000..1a0982b
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_sys_fp.h
@@ -0,0 +1,100 @@
+/***********************************************************************
+* This software/firmware and related documentation ("MediaTek Software")
+* are protected under relevant copyright laws. The information contained
+* herein is confidential and proprietary to MediaTek Inc. and/or its licensors.
+*
+* Without the prior written permission of MediaTek Inc. and/or its licensors,
+* any reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly prohibited.
+*
+* MediaTek Inc. (C) [2008]. All rights reserved.
+*
+*************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * mtk_gps_sys_fp.h
+ *
+ * Description:
+ * ------------
+ * Marco porting layer APT to Function pointer using by MTK navigation library
+ *
+ ****************************************************************************/
+
+#ifndef MTK_GPS_SYS_FP_H
+#define MTK_GPS_SYS_FP_H
+
+#include "mtk_gps_type.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+extern INT32 (*gfpmtk_gps_sys_gps_mnl_callback )(MTK_GPS_NOTIFICATION_TYPE);
+extern INT32 (*gfpmtk_gps_sys_nmea_output_to_app)(const char *,UINT32);
+extern INT32 (*gfpmtk_gps_sys_nmea_output_to_mnld)(const char *,UINT32);
+extern INT32 (*gfpmtk_gps_sys_frame_sync_enable_sleep_mode)(unsigned char);
+extern INT32 (*gfpmtk_gps_sys_frame_sync_meas_req_by_network)(void);
+extern INT32 (*gfpmtk_gps_sys_frame_sync_meas_req) (MTK_GPS_FS_WORK_MODE);
+extern INT32 (*gfpmtk_gps_sys_agps_disaptcher_callback) (UINT16, UINT16, char *);
+extern void (*gfpmtk_gps_sys_pmtk_cmd_cb)(UINT16);
+extern int (*gfpSUPL_encrypt)(unsigned char *, unsigned char *, unsigned int );
+extern int (*gfpSUPL_decrypt)(unsigned char *, unsigned char *, unsigned int );
+extern INT32 (*gfmtk_gps_sys_alps_gps_dbg2file_mnld)(const char * buffer, UINT32 length);
+
+extern INT32 (*gfmtk_gps_ofl_sys_rst_stpgps_req)(void);
+extern INT32 (*gfmtk_gps_ofl_sys_submit_flp_data)(UINT8 *buf, UINT32 len);
+extern INT32 (*gfmtk_gps_ofl_sys_mnl_offload_cb)(MTK_GPS_OFL_CB_TYPE, UINT16, UINT8 *);
+extern INT32 (*gfmtk_gps_sys_do_hw_suspend_resume)(UINT32 bitmask);
+extern void (*gfmtk_gps_sys_clk_extention_set)(INT32 enable, INT32 ext_sec);
+extern INT32 (*gfmtk_gps_sys_extpvt_callback)(INT32 msg, void *data, INT32 size);
+extern INT32 (*gfmtk_gps_sys_set_errno_to_extpvt)(INT32 errorId);
+extern UINT8(*gfmtk_gps_sys_rtk_interface)(MNLDRtkInterfaceType rtk_message_type, void* rtk_message);
+typedef struct
+{
+ INT32 (*sys_gps_mnl_callback)(MTK_GPS_NOTIFICATION_TYPE );
+ INT32 (*sys_nmea_output_to_app)(const char *,UINT32);
+ INT32 (*sys_nmea_output_to_mnld)(const char *,UINT32);
+ INT32 (*sys_frame_sync_enable_sleep_mode)(unsigned char );
+ INT32 (*sys_frame_sync_meas_req_by_network)(void );
+ INT32 (*sys_frame_sync_meas_req)(MTK_GPS_FS_WORK_MODE );
+ INT32 (*sys_agps_disaptcher_callback)(UINT16, UINT16, char * );
+ void (*sys_pmtk_cmd_cb)(UINT16 );
+ int (*encrypt)(unsigned char *, unsigned char *, unsigned int );
+ int (*decrypt)(unsigned char *, unsigned char *, unsigned int );
+
+ INT32 (*ofl_sys_rst_stpgps_req)(void);
+ INT32 (*ofl_sys_submit_flp_data)(UINT8 *buf, UINT32 len);
+
+ INT32 (*sys_alps_gps_dbg2file_mnld)(const char * buffer, UINT32 length);
+
+ // 2016.10.30 add for MNL offload
+ INT32 (*ofl_sys_mnl_offload_callback)(MTK_GPS_OFL_CB_TYPE, UINT16 , UINT8 *);
+ INT32 (*sys_gps_mnl_data2mnld_callback)(const char *, UINT32);
+
+ INT32 (*sys_do_hw_suspend_resume)(UINT32 bitmask);
+ void (*sys_clk_extention_set)(INT32 enable, INT32 ext_sec);
+ INT32 (*sys_extpvt_callback)(INT32 msg, void *data, INT32 size);
+ INT32 (*sys_set_errno_to_extpvt)(INT32 errorId);
+ UINT8 (*rtk_interface)(MNLDRtkInterfaceType rtk_message_type, void* rtk_message);
+} MTK_GPS_SYS_FUNCTION_PTR_T;
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_function_registery
+ * DESCRIPTION
+ * register the body of function pointer
+ * PARAMETERS
+ * fp_t [IN] function pointer API
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_function_register (MTK_GPS_SYS_FUNCTION_PTR_T *fp_t);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* MTK_GPS_SYS_FP_H */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_sys_fp_macro.h b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_sys_fp_macro.h
new file mode 100644
index 0000000..8fb830b
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_sys_fp_macro.h
@@ -0,0 +1,60 @@
+/***********************************************************************
+* This software/firmware and related documentation ("MediaTek Software")
+* are protected under relevant copyright laws. The information contained
+* herein is confidential and proprietary to MediaTek Inc. and/or its licensors.
+*
+* Without the prior written permission of MediaTek Inc. and/or its licensors,
+* any reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly prohibited.
+*
+* MediaTek Inc. (C) [2008]. All rights reserved.
+*
+*************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * mtk_gps_sys_fp.h
+ *
+ * Description:
+ * ------------
+ * Marco porting layer APT to Function pointer using by MTK navigation library
+ *
+ ****************************************************************************/
+
+#ifndef MTK_GPS_SYS_FP_MACRO_H
+#define MTK_GPS_SYS_FP_MACRO_H
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#define mtk_gps_sys_gps_mnl_callback gfpmtk_gps_sys_gps_mnl_callback
+#define mtk_gps_sys_nmea_output_to_app gfpmtk_gps_sys_nmea_output_to_app
+#define mtk_gps_sys_nmea_output_to_mnld gfpmtk_gps_sys_nmea_output_to_mnld
+#define mtk_gps_sys_frame_sync_enable_sleep_mode gfpmtk_gps_sys_frame_sync_enable_sleep_mode
+#define mtk_gps_sys_frame_sync_meas_req_by_network gfpmtk_gps_sys_frame_sync_meas_req_by_network
+#define mtk_gps_sys_frame_sync_meas_req gfpmtk_gps_sys_frame_sync_meas_req
+#define mtk_gps_sys_agps_disaptcher_callback gfpmtk_gps_sys_agps_disaptcher_callback
+#define mtk_gps_sys_pmtk_cmd_cb gfpmtk_gps_sys_pmtk_cmd_cb
+#define SUPL_encrypt gfpSUPL_encrypt
+#define SUPL_decrypt gfpSUPL_decrypt
+#define mtk_gps_sys_alps_gps_dbg2file_mnld gfmtk_gps_sys_alps_gps_dbg2file_mnld
+
+#define mtk_gps_ofl_sys_rst_stpgps_req gfmtk_gps_ofl_sys_rst_stpgps_req
+#define mtk_gps_ofl_sys_submit_flp_data gfmtk_gps_ofl_sys_submit_flp_data
+#define mtk_gps_ofl_sys_mnl_offload_cb gfmtk_gps_ofl_sys_mnl_offload_cb
+#define mtk_gps_sys_msg_output_to_app gfpmtk_gps_sys_msg_output_to_app
+#define _mtk_gps_sys_do_hw_suspend_resume gfmtk_gps_sys_do_hw_suspend_resume
+#define mtk_gps_sys_clk_extention_set gfmtk_gps_sys_clk_extention_set
+#define mtk_gps_sys_extpvt_callback gfmtk_gps_sys_extpvt_callback
+#define mtk_gps_sys_set_errno_to_extpvt gfmtk_gps_sys_set_errno_to_extpvt
+#define mtk_gps_sys_rtk_interface gfmtk_gps_sys_rtk_interface
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* MTK_GPS_SYS_FP_MACRO_H */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_type.h b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_type.h
new file mode 100644
index 0000000..c443d62
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/libs/inc/mtk_gps_type.h
@@ -0,0 +1,4105 @@
+/***********************************************************************
+* This software/firmware and related documentation ("MediaTek Software")
+* are protected under relevant copyright laws. The information contained
+* herein is confidential and proprietary to MediaTek Inc. and/or its licensors.
+*
+* Without the prior written permission of MediaTek Inc. and/or its licensors,
+* any reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly prohibited.
+*
+* MediaTek Inc. (C) [2008]. All rights reserved.
+*
+*************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * mtk_gps_type.h
+ *
+ * Description:
+ * ------------
+ * Data types used by MTK navigation library
+ *
+ ****************************************************************************/
+
+#ifndef MTK_GPS_TYPE_H
+#define MTK_GPS_TYPE_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define MTK_GPS_SV_MAX_NUM 128
+#define MTK_GPS_SV_MAX_PRN 32
+#define MTK_QZS_SV_MAX_PRN 7 // QZSS PRN : 193~199
+#define MTK_GLEO_SV_MAX_NUM 36 // Galileo SV number, should be >= MGLEOID
+#define MTK_GLON_SV_MAX_NUM 24 // Glonass SV number, should be >= MGLONID
+#define MTK_BEDO_SV_MAX_NUM 63 // Beidou SV number, should be >= MBEDOID
+#define MTK_SBAS_SV_MAX_NUM 19
+#define MTK_NAVIC_SV_MAX_NUM 14
+
+#define MTK_GPS_ENABLE_DEBUG_MSG (0x01)
+#define MTK_GPS_NMEA_SOCKET_DISABLE (0xFFFFF)
+#define MTK_GPS_LIB_VER_LEN_MAX 64
+#define MTK_GPS_EPO_FILE_NAME_LEN 48
+
+/**The file & data lenght and type number definition for MTKNAV**/
+#define AGT_MTKNAV_TYPE_MAX_LEN (1024) //The max length of one type is 1kB
+
+// MTK_GNSS_CONFIGURATION for AGNSS part
+#define MTK_CONFIG_AGPS_MODE_BIT_MASK (1 << 8)
+#define MTK_CONFIG_AGLONASS_MODE_BIT_MASK (1 << 9)
+#define MTK_CONFIG_ABEIDOU_MODE_BIT_MASK (1 << 10)
+
+#define AGPS_SET_GPS_ENABLE ((0x01<<0) & (0xFF))
+#define AGPS_SET_GLONASS_ENABLE ((0x01<<1) & (0xFF))
+#define AGPS_SET_BEIDOU_ENABLE ((0x01<<2) & (0xFF))
+#define AGPS_SET_GALILEO_ENABLE ((0x01<<3) & (0xFF))
+#define AGPS_SET_AGLONASS_ENABLE ((0x01<<4) & (0xFF))
+#define AGPS_SET_AGPS_ENABLE ((0x01<<5) & (0xFF))
+#define AGPS_SET_ABEIDOU_ENABLE ((0x01<<6) & (0xFF))
+#define AGPS_SET_AGALILEO_ENABLE ((0x01<<7) & (0xFF))
+
+
+/*******************************************************************************
+ * Type Definitions
+ *******************************************************************************/
+typedef unsigned int UINT4;
+typedef signed int INT4;
+
+typedef unsigned char UINT8;
+typedef signed char INT8;
+
+typedef unsigned short int UINT16;
+typedef signed short int INT16;
+
+typedef unsigned int UINT32;
+typedef signed int INT32;
+
+typedef unsigned long long UINT64;
+typedef signed long long INT64;
+
+#if ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 200000 ))
+// for ADS1.x
+#elif ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400000 ) )
+// for RVCT2.x or RVCT3.x
+#else
+#pragma pack(4)
+#endif
+
+// GPS Measurement
+
+#define MTK_GPS_MEASUREMENT_HAS_SNR (1<<0) // A valid 'snr' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_ELEVATION (1<<1) // A valid 'elevation' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY (1<<2) // A valid 'elevation uncertainty' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_AZIMUTH (1<<3) // A valid 'azimuth' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY (1<<4) // A valid 'azimuth uncertainty' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_PSEUDORANGE (1<<5) // A valid 'pseudorange' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY (1<<6) // A valid 'pseudorange uncertainty' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_CODE_PHASE (1<<7) // A valid 'code phase' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY (1<<8) // A valid 'code phase uncertainty' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9) // A valid 'carrier frequency' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10) // A valid 'carrier cycles' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11) // A valid 'carrier phase' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12) // A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_BIT_NUMBER (1<<13) // A valid 'bit number' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT (1<<14) // A valid 'time from last bit' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_DOPPLER_SHIFT (1<<15) // A valid 'doppler shift' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY (1<<16) // A valid 'doppler shift uncertainty' is stored in the data structure.
+#define MTK_GPS_MEASUREMENT_HAS_USED_IN_FIX (1<<17) // A valid 'used in fix' flag is stored in the data structure.
+
+#define MTK_GPS_LOSS_OF_LOCK_UNKNOWN 0 // The indicator is not available or it is unknown.
+#define MTK_GPS_LOSS_OF_LOCK_OK 1 // The measurement does not present any indication of loss of lock.
+#define MTK_GPS_LOSS_OF_LOCK_CYCLE_SLIP 2 // Loss of lock between previous and current observation: cycle slip possible.
+
+#define MTK_GPS_MULTIPATH_INDICATOR_UNKNOWN 0 // The indicator is not available or unknown.
+#define MTK_GPS_MULTIPATH_INDICATOR_DETECTED 1 // The measurement has been indicated to use multipath.
+#define MTK_GPS_MULTIPATH_INDICATOR_NOT_USED 2 // The measurement has been indicated Not to use multipath.
+
+#define MTK_GPS_MEASUREMENT_STATE_UNKNOWN 0
+#define MTK_GPS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define MTK_GPS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define MTK_GPS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define MTK_GPS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+
+#define MTK_GPS_ADR_STATE_UNKNOWN 0
+#define MTK_GPS_ADR_STATE_VALID (1<<0)
+#define MTK_GPS_ADR_STATE_RESET (1<<1)
+#define MTK_GPS_ADR_STATE_CYCLE_SLIP (1<<2)
+
+// Gps Clock
+#define MTK_GPS_CLOCK_HAS_LEAP_SECOND (1<<0) // A valid 'leap second' is stored in the data structure.
+#define MTK_GPS_CLOCK_HAS_TIME_UNCERTAINTY (1<<1) // A valid 'time uncertainty' is stored in the data structure.
+#define MTK_GPS_CLOCK_HAS_FULL_BIAS (1<<2) // A valid 'full bias' is stored in the data structure.
+#define MTK_GPS_CLOCK_HAS_BIAS (1<<3) // A valid 'bias' is stored in the data structure.
+#define MTK_GPS_CLOCK_HAS_BIAS_UNCERTAINTY (1<<4) // A valid 'bias uncertainty' is stored in the data structure.
+#define MTK_GPS_CLOCK_HAS_DRIFT (1<<5 ) // A valid 'drift' is stored in the data structure.
+#define MTK_GPS_CLOCK_HAS_DRIFT_UNCERTAINTY (1<<6) // A valid 'drift uncertainty' is stored in the data structure.
+
+#define MTK_GPS_CLOCK_TYPE_UNKNOWN 0
+#define MTK_GPS_CLOCK_TYPE_LOCAL_HW_TIME 1
+#define MTK_GPS_CLOCK_TYPE_GPS_TIME 2
+
+// Gps NavigationMessage
+#define MTK_GPS_NAVIGATION_MESSAGE_TYPE_UNKNOWN 0
+#define MTK_GPS_NAVIGATION_MESSAGE_TYPE_L1CA 1 // L1 C/A message contained in the structure.
+#define MTK_GPS_NAVIGATION_MESSAGE_TYPE_L2CNAV 2 // L2-CNAV message contained in the structure.
+#define MTK_GPS_NAVIGATION_MESSAGE_TYPE_L5CNAV 3 // L5-CNAV message contained in the structure.
+#define MTK_GPS_NAVIGATION_MESSAGE_TYPE_CNAV2 4 // CNAV-2 message contained in the structure.
+
+#define GPS_DEBUG_LOG_FILE_NAME_MAX_LEN 128 //The max lenght of debug log file name, include the path name
+
+#define ASSIST_REQ_BIT_NTP 0x01 // NTP request bitmap
+#define ASSIST_REQ_BIT_NLP 0x02 // NLP request bitmap
+
+// GNSS Measurement
+#define MTK_GNSS_MAX_SVS (32+7+24+63+36+19+14) //195, GPS+QZSS+Glonass+Beidou+Galileo+SBAS+IRNSS_SV
+#define MTK_GNSS_MAX_MEASUREMENT 64
+
+typedef UINT32 MTK_GnssMeasurementflags;
+#define MTK_GNSS_MEASUREMENT_HAS_SNR (1<<0) /** A valid 'snr' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_ELEVATION (1<<1) /** A valid 'elevation' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY (1<<2) /** A valid 'elevation uncertainty' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_AZIMUTH (1<<3) /** A valid 'azimuth' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY (1<<4) /** A valid 'azimuth uncertainty' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_PSEUDORANGE (1<<5) /** A valid 'pseudorange' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY (1<<6) /** A valid 'pseudorange uncertainty' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CODE_PHASE (1<<7) /** A valid 'code phase' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY (1<<8) /** A valid 'code phase uncertainty' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9) /** A valid 'carrier frequency' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10) /** A valid 'carrier cycles' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11) /** A valid 'carrier phase' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12) /** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_AUTOMATIC_GAIN_CONTROL (1<<13) /** A valid automatic gain control is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT (1<<14) /** A valid 'time from last bit' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT (1<<15) /** A valid 'doppler shift' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_HAS_FULL_ISB (1<<16) /** A valid full inter-signal bias is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_HAS_FULL_ISB_UNCERTAINTY (1<<17) /** A valid full inter-signal bias uncertainty is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_HAS_SATELLITE_ISB (1<<18) /** A valid satellite inter-signal bias is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_HAS_SATELLITE_ISB_UNCERTAINTY (1<<19) /** A valid satellite inter-signal bias uncertainty is stored in the data structure. */
+
+typedef UINT16 MTK_GnssAccumulatedDeltaRangestate;
+#define MTK_GNSS_ADR_STATE_UNKNOWN 0
+#define MTK_GNSS_ADR_STATE_VALID (1<<0)
+#define MTK_GNSS_ADR_STATE_RESET (1<<1)
+#define MTK_GNSS_ADR_STATE_SLIP (1<<2)
+#define MTK_GNSS_ADR_STATE_HALF_RESOLVED (1<<3)
+#define MTK_GNSS_ADR_STATE_HALF_REPORTED (1<<4)
+
+
+
+typedef INT16 MTK_GnssNavigationmessageType;
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN 0
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA 0x0101/** GPS L1 C/A message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV 0x0102/** GPS L2-CNAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV 0x0103/** GPS L5-CNAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2 0x0104/** GPS CNAV-2 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA 0x0301/** Glonass L1 CA message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1 0x0501/** Beidou D1 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2 0x0502/** Beidou D2 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I 0x0601/** Galileo I/NAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F 0x0602/** Galileo F/NAV message contained in the structure. */
+
+typedef UINT16 MTK_NavigationMessageStatus;
+#define MTK_NAV_MESSAGE_STATUS_UNKNOWN 0
+#define MTK_NAV_MESSAGE_STATUS_PARITY_PASSED (1<<0)
+#define MTK_NAV_MESSAGE_STATUS_PARITY_REBUILT (1<<1)
+
+typedef UINT8 MTK_GnssSvFlags;
+#define MTK_GNSS_SV_FLAGS_NONE 0
+#define MTK_GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA (1 << 0)
+#define MTK_GNSS_SV_FLAGS_HAS_ALMANAC_DATA (1 << 1)
+#define MTK_GNSS_SV_FLAGS_USED_IN_FIX (1 << 2)
+
+typedef UINT32 MTK_GnssMeasurementstate;
+#define MTK_GNSS_MEASUREMENT_STATE_UNKNOWN 0
+#define MTK_GNSS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define MTK_GNSS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define MTK_GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define MTK_GNSS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+#define MTK_GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4)
+#define MTK_GNSS_MEASUREMENT_STATE_SYMBOL_SYNC (1<<5)
+#define MTK_GNSS_MEASUREMENT_STATE_STRING_SYNC (1<<6)
+#define MTK_GNSS_MEASUREMENT_STATE_TOD_DECODED (1<<7)
+#define MTK_GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC (1<<9)
+#define MTK_GNSS_MEASUREMENT_STATE_STATE_TOW_KNOWN (1<<14)
+#define MTK_GNSS_MEASUREMENT_STATE_STATE_TOD_KNOWN (1<<15)
+
+
+
+typedef UINT8 MTK_GnssConstellationtype;
+#define MTK_GNSS_CONSTELLATION_UNKNOWN 0
+#define MTK_GNSS_CONSTELLATION_GPS 1
+#define MTK_GNSS_CONSTELLATION_SBAS 2
+#define MTK_GNSS_CONSTELLATION_GLONASS 3
+#define MTK_GNSS_CONSTELLATION_QZSS 4
+#define MTK_GNSS_CONSTELLATION_BEIDOU 5
+#define MTK_GNSS_CONSTELLATION_GALILEO 6
+#define MTK_GNSS_CONSTELLATION_IRNSS 7
+#define MTK_GNSS_CONSTELLATION_SIZE 8
+
+// Gnsss Clock
+typedef UINT16 MTK_GnssClockflags;
+#define MTK_GNSS_CLOCK_HAS_LEAP_SECOND (1<<0)/** A valid 'leap second' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_TIME_UNCERTAINTY (1<<1)/** A valid 'time uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_FULL_BIAS (1<<2)/** A valid 'full bias' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_BIAS (1<<3)/** A valid 'bias' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_BIAS_UNCERTAINTY (1<<4)/** A valid 'bias uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_DRIFT (1<<5)/** A valid 'drift' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY (1<<6)/** A valid 'drift uncertainty' is stored in the data structure. */
+
+// Gnsss NavigationMessage
+typedef UINT8 MTK_GnssMultipathindicator;
+#define MTK_GNSS_MULTIPATH_INDICATOR_UNKNOWN 0/** The indicator is not available or unknown. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_PRESENT 1/** The measurement is indicated to be affected by multipath. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_NOT_PRESENT 2/** The measurement is indicated to be not affected by multipath. */
+
+/**QEPO GNSS Bitmap**/
+#define AGT_QEPO_GP_BIT (0x01<<0)
+#define AGT_QEPO_GL_BIT (0x01<<1)
+#define AGT_QEPO_BD_BIT (0x01<<2)
+#define AGT_QEPO_GA_BIT (0x01<<3)
+/****The bit number of QEPO download response result****/
+/****The Lowest 4 bit is the value of QEPO download response(Pass or Fail)****/
+/****The next high 4 bit is the QEPO GNSS Bitmap****/
+#define MTK_QEPO_RSP_BIT_NUM 4
+
+
+//*****************************************************************************
+// User System Configurations
+//*****************************************************************************
+typedef enum
+{
+ HOST_USER_CONFIG_SYS_1 = 1, // user configuration in system operation
+ HOST_USER_CONFIG_SYS_2 = 2, // user configuration in GPS operation
+ HOST_USER_CONFIG_SYS_3 = 3, // user configuration in Anti-Jamming Debug
+ HOST_USER_CONFIG_SYS_4 = 4, // user configuration for aiding data to NVRAM
+ HOST_USER_CONFIG_SYS_5 = 5, // user configuration for aiding almanac data to NVRAM
+ HOST_USER_CONFIG_SYS_6 = 6, // user configuration for aiding eph data to NVRAM
+ HOST_USER_CONFIG_SYS_7 = 7, // user configuration for aiding position data to NVRAM
+ HOST_USER_CONFIG_SYS_8 = 8, // user configuration for aiding time data to NVRAM
+ HOST_USER_CONFIG_SYS_9 = 9, // user configuration for clean ehp data from NVRAM
+ HOST_USER_CONFIG_SYS_10 = 10, // user configuration for clean alman data from NVRAM
+ HOST_USER_CONFIG_SYS_11 = 11, // user configuration for chn test
+ HOST_USER_CONFIG_SYS_12 = 12, // user configuration for jammer test
+ HOST_USER_CONFIG_SYS_13 = 13, // user configuration for phase test
+ HOST_USER_CONFIG_SYS_14 = 14, // user configuration for phase test
+ HOST_USER_CONFIG_SYS_15 = 15, // user configuration for time_change_notify
+ HOST_USER_CONFIG_SYS_16 = 16, // user configuration for time_update_notify
+ HOST_USER_CONFIG_SYS_17 = 17, // user configuration for debug_config
+ HOST_USER_CONFIG_SYS_18 = 18, // user configuration for update NVfile immedate
+ HOST_USER_CONFIG_SYS_19 = 19, // user configuration for setting tcxo mode
+ HOST_USER_CONFIG_SYS_20 = 20, // user configuration for TSX XVT
+ HOST_USER_CONFIG_SYS_21 = 21, // user configuration for GNSS jammer test
+ HOST_USER_CONFIG_SYS_END // user configuration for aiding almanac data to NVRAM
+}MTK_GPS_USER_SYSTEM_CONFIG;
+
+#define USER_SYS_1_ENABLE_DEBUG ( 1 << 0)
+#define USER_SYS_2_TRIGGER_PPS ( 1 << 0)
+
+//*****************************************************************************
+// User System Stauts
+//*****************************************************************************
+typedef enum
+{
+ USER_SYS_ANT_STATUS = 1
+}MTK_GPS_SYSTEM_STATUS;
+#define MTK_SYS_ANT_STATUS_AOK ( 1 << 0)
+#define MTK_SYS_ANT_STATUS_ASHORT ( 1 << 1)
+
+
+
+typedef enum
+{
+ MTK_GPS_FALSE = 0,
+ MTK_GPS_TRUE = 1
+} MTK_GPS_BOOL;
+
+typedef enum
+{
+ MTK_GPS_START_DEFAULT = 0,
+ MTK_GPS_START_HOT,
+ MTK_GPS_START_WARM,
+ MTK_GPS_START_COLD,
+ MTK_GPS_START_FULL,
+ MTK_GPS_START_BATTERY,
+ MTK_GPS_START_AGPS,
+ MTK_GPS_START_D_EPH_ALM, // delete ephemeris and almanac only
+ MTK_GPS_START_D_TIME, // delete time only
+ MTK_GPS_START_D_TIME_POS_EPH_ALM, // delete time, pos, eph and alm
+ MTK_GPS_START_D_BITMASK // delete by bitmask
+} MTK_GPS_START_TYPE;
+
+typedef enum
+{
+ MTK_GPS_START_RESULT_ERROR = 0,
+ MTK_GPS_START_RESULT_OK
+} MTK_GPS_START_RESULT;
+
+typedef enum
+{
+ MTK_GPS_MSG_FIX_READY,
+ MTK_GPS_MSG_DEBUG_READY,
+ MTK_GPS_MSG_CONFIG_READY,
+ MTK_GPS_MSG_TEST_STATUS_READY,
+ MTK_GPS_MSG_BUFFER_ENOUGH,
+ MTK_GPS_MSG_AGPS_RESPONSE,
+ MTK_GPS_MSG_PMTK_RESPONSE,
+ MTK_GPS_MSG_FIX_PROHIBITED,
+ MTK_GPS_MSG_ASSIST_READY,
+ MTK_GPS_MSG_MNL_START,
+ MTK_GPS_MSG_MNL_RESTART_NTF,
+ MTK_GPS_MSG_MNL_INIT_FAIL,
+ MTK_GPS_MSG_REQUEST_NW_LOCATION,
+ MTK_GPS_MSG_NEED_RESTART
+} MTK_GPS_NOTIFICATION_TYPE;
+
+typedef enum
+{
+ MTK_GPS_FIX_Q_INVALID = 0,
+ MTK_GPS_FIX_Q_GPS = 1,
+ MTK_GPS_FIX_Q_DGPS = 2,
+ MTK_GPS_FIX_Q_EST = 6
+} MTK_GPS_FIX_QUALITY;
+
+typedef enum
+{
+ MTK_GPS_FIX_TYPE_INVALID = 1,
+ MTK_GPS_FIX_TYPE_2D = 2,
+ MTK_GPS_FIX_TYPE_3D = 3
+} MTK_GPS_FIX_TYPE;
+
+typedef enum
+{
+ MTK_DGPS_MODE_NONE = 0,
+ MTK_DGPS_MODE_RTCM = 1,
+ MTK_DGPS_MODE_SBAS = 2,
+ MTK_DGPS_MODE_AUTO = 3
+} MTK_GPS_DGPS_MODE;
+
+typedef enum
+{
+ MTK_AGPS_MODE_NONE = 1,
+ MTK_AGPS_MODE_SUPL = 2,
+ MTK_AGPS_MODE_EPO = 4,
+ MTK_AGPS_MODE_BEE = 8,
+ MTK_AGPS_MODE_AUTO = 16
+} MTK_GPS_AGPS_MODE;
+
+// Thread definition
+typedef enum
+{
+ MTK_MOD_NIL = 0,
+ MTK_MOD_MNL,
+ MTK_MOD_DSPIN,
+ MTK_MOD_PMTKIN,
+ MTK_MOD_AGENT,
+ MTK_MOD_BEE_GEN,
+ MTK_MOD_DISPATCHER,
+ MTK_MOD_RTCM,
+ MTK_MOD_EPO_FILE_UPDATER,
+ MTK_MOD_END_LIST
+} MTK_GPS_MODULE;
+
+// API from Dispatcher to Agent
+typedef enum
+{
+ MTK_AGPS_MSG_EPO = 0,
+ MTK_AGPS_MSG_BEE,
+ MTK_AGPS_MSG_SUPL,
+ MTK_AGPS_MSG_SUPL_PMTK,
+ MTK_AGPS_MSG_PROFILE,
+ MTK_AGPS_MSG_SUPL_TERMINATE, //dispatcher send terminate to indicate SUPL stop
+ MTK_AGPS_MSG_REQ_NI, //request AGPS aiding from dispatcher
+ MTK_AGPS_MSG_REQ, //request AGPS aiding from mnl
+ MTK_AGPS_MSG_AGT_BEE_REQ, //AGENT request next mode(BEE)
+ MTK_AGPS_MSG_AGT_SUPL_REQ, //AGENT request next mode(SUPL)
+ MTK_AGPS_MSG_REQ_QEPO, //MNL request quarter EPO
+ MTK_AGPS_MSG_TERMINATE,
+ MTK_AGPS_MSG_EPO_FILE_UPDATE_DONE, // Notify agent to inject EPO after MNLD update it done
+ MTK_AGPS_MSG_QEPO_RESPONSE, //Notify agent the QEPO download/update result
+ MTK_AGPS_MSG_LPPE_STATE_SYNC,//Notify agent LPPE status
+ MTK_AGPS_MSG_REQ_MTKNAV, //MNL request MTKNAV
+ MTK_AGPS_MSG_MTKNAV_RESPONSE, //Notify agent the MTKNAV download/update result
+ MTK_AGPS_MSG_END_LIST
+} MTK_GPS_AGPS_AGENT_MSG_TYPE;
+
+// Callback from Agent to Dispatcher
+typedef enum
+{
+ MTK_AGPS_CB_SUPL_PMTK = 0,
+ MTK_AGPS_CB_ASSIST_REQ,
+ MTK_AGPS_CB_SUPL_NI_REQ,
+ MTK_AGPS_CB_START_REQ,
+ MTK_AGPS_CB_AGPS_RAWDATA_CONT,
+ MTK_AGPS_CB_BITMAP_UPDATE, //this message is used for NTP NTP request to MNLD->HAL GPS->locationservice
+ MTK_AGPS_CB_QEPO_DOWNLOAD_REQ,
+ MTK_AGPS_CB_LPPE_ASSIST_REQ,
+ MTK_AGPS_CB_MTKNAV_DOWNLOAD_REQ,
+
+ MTK_AGPS_CB_MD_TIME_SYNC_REQ, // Case 1: MNL-Initiated
+ MTK_AGPS_CB_MD_TIME_INFO_RSP, // OK to have a location with time sync
+ MTK_AGPS_CB_NOTIFY_LOC_MEA_REPORT,
+ MTK_AGPS_CB_END_LIST
+} MTK_GPS_AGPS_CB_MSG_TYPE;
+
+typedef struct
+{
+ UINT64 ntp; //ntp: mini-second, indicate the time tick(mini-second) from Jan.1.1970
+ UINT64 timeReference; //indicate the timestamp of ntp sync with network
+ INT32 uncertainty;
+} MTK_GPS_NTP_T;
+
+typedef struct
+{
+ double lattidude;
+ double longitude;
+ float accuracy;
+ UINT32 timeReference[2]; //indicate the timestamp of location generated
+ UINT8 type; // indicate location type: 0: NLP, 1: fixed location
+ UINT8 started ; // 0 MNL not run / 1 MNL run
+}MTK_GPS_NLP_T;
+
+typedef struct
+{
+ UINT8 mode;
+ long long sv_list[8];
+} MTK_GPS_SV_BLACKLIST;
+
+// AGPS feature on/off
+typedef enum
+{
+ MTK_AGPS_FEATURE_OFF = 0,
+ MTK_AGPS_FEATURE_ON = 1
+} MTK_GPS_AGPS_FUNC_ONOFF;
+
+typedef struct
+{
+ UINT8 EPO_enabled;
+ UINT8 BEE_enabled;
+ UINT8 SUPL_enabled;
+ UINT8 SUPLSI_enabled;
+ UINT8 EPO_priority;
+ UINT8 BEE_priority;
+ UINT8 SUPL_priority;
+ UINT8 fgGpsAosp_Ver;
+ UINT8 LPPE_enabled;
+} MTK_AGPS_USER_PROFILE;
+
+typedef struct
+{
+ UINT16 type; /* message ID */
+ UINT16 length; /* length of 'data' */
+ char data[1]; /* message content */
+} MTK_GPS_MSG;
+
+typedef struct
+{
+ UINT16 srcMod;
+ UINT16 dstMod;
+ UINT16 type; /* message ID */
+ UINT16 length; /* length of 'data' */
+ char data[1]; /* message content */
+} MTK_GPS_AGPS_AGENT_MSG;
+//MTK_GPS_AGPS_AGENT_MSG definition need to sync to SUPL msg 's definition
+typedef enum
+{
+ MTK_BEE_DISABLE = 0,
+ MTK_BEE_ENABLE = 1
+} MTK_GPS_BEE_EN;
+
+typedef enum
+{
+ MTK_BRDC_DISABLE = 0,
+ MTK_BRDC_ENABLE = 1
+} MTK_GPS_BRDC_EN;
+
+typedef enum
+{
+ MTK_DBG_DISABLE = 0,
+ MTK_DBG_ERR,
+ MTK_DBG_WRN,
+ MTK_DBG_INFO,
+ MTK_DBG_END
+} MTK_GPS_DBG_LEVEL;
+
+
+typedef enum
+{
+ MDBG_BOOT = 0,
+ MDBG_TIME,
+ MDBG_COMM,
+ MDBG_MEM,
+ MDBG_MSG,
+ MDBG_STORE,
+ MDBG_AL,
+ MDBG_GPS,
+ MDBG_AGPS,
+ MDBG_FS,
+ MDBG_ALL,
+ MDBG_TYPE_END
+} MTK_GPS_DBG_TYPE;
+
+typedef enum
+{
+ MTK_QZSS_DISABLE = 0,
+ MTK_QZSS_ENABLE = 1
+} MTK_QZSS_SEARCH_MODE;
+
+typedef enum
+{
+ MTK_NO_SPEED_FILTERING = 0,
+ MTK_SPEED_FILTERING_0_POINT_2 = 1,
+ MTK_SPEED_FILTERING_0_POINT_4 = 2,
+ MTK_SPEED_FILTERING_0_POINT_6 = 3,
+ MTK_SPEED_FILTERING_0_POINT_8 = 4,
+ MTK_SPEED_FILTERING_1_POINT_0 = 5,
+ MTK_SPEED_FILTERING_1_POINT_5 = 6,
+ MTK_SPEED_FILTERING_2_POINT_0 = 7
+} MTK_LOW_SPEED_FILTERING_MODE;
+
+
+
+typedef struct
+{
+ UINT16 year; /* years since 1900 */
+ UINT8 month; /* 0-11 */
+ UINT8 mday; /* 1-31 */
+ UINT8 hour; /* 0-23 */
+ UINT8 min; /* 0-59 */
+ UINT8 sec; /* 0-59 */
+ UINT8 pad1;
+ UINT16 msec; /* 0-999 */
+ UINT16 pad2;
+} MTK_GPS_TIME;
+
+typedef enum
+{
+ MTK_TCXO_NORMAL, //normal mode
+ MTK_TCXO_PHONE //bad mode
+} MTK_GPS_TCXO_MODE;
+
+typedef enum
+{
+ MTK_AIC_OFF, //AIC off
+ MTK_AIC_ON //AIC on
+} MTK_GPS_AIC_MODE;
+
+typedef enum
+{
+ MTK_SIB8_16_OFF, //SIB8/SIB16 off
+ MTK_SIB8_16_ON //ASIB8/SIB16 on
+} MTK_GPS_SIB8_16_EN;
+typedef enum
+{
+ MTK_DEBUG2APP_OFF, //Debug to APP off
+ MTK_DEBUG2APP_ON //Debug to APP on
+} MTK_GPS_DEBUG2APP_EN;
+
+typedef enum
+{
+ MTK_LPPE_OFF, //LPPE off
+ MTK_LPPE_ON //LPPE on
+} MTK_GPS_LPPE_EN;
+
+typedef struct
+{
+ UINT16 version;
+ UINT16 size;
+ MTK_GPS_TIME utc_time;
+ INT16 leap_second; /* GPS-UTC time difference */
+ UINT16 WeekNo; /* GPS week number */
+ UINT32 TOW; /* GPS time of week (integer part) */
+ UINT8 fix_quality; /* MTK_GPS_FIX_QUALITY for GPGGA */
+ UINT8 fix_type; /* MTK_GPS_FIX_TYPE for GPGSA */
+ double clock_drift; /* clock drift (s/s) */
+ double clock_bias; /* clock bias (s) */
+ double LLH[4]; /* LLH[0]: Latitude (degree) */
+ /* LLH[1]: Longitude (degree) */
+ /* LLH[2]: Height WGS84 (m) */
+ /* LLH[3]: Height Mean Sea Level (m) */
+ float gspeed; /* 2D ground speed (m/s) */
+ float vspeed; /* vertical speed (m/s) */
+ float heading; /* track angle (deg) */
+ float PDOP, HDOP, VDOP, TDOP; /* dilution of precision */
+ float EPE[3]; /* estimated position error (m) */
+ /* EPE[0]: North accuracy */
+ /* EPE[1]: East accuracy */
+ /* EPE[2]: vertical accuracy */
+ float EVE[3]; /* estimated velocity error (m/s) */
+ /* EVE[0]: North accuracy */
+ /* EVE[1]: East accuracy */
+ /* EVE[2]: vertical accuracy */
+ float Pos_2D_Accuracy; // Position Accuracy in Horizontal Direction [m]
+ float Pos_3D_Accuracy; // Position Accuracy in 3-D space [m]
+ float Vel_3D_Accuracy; // Velocity Accuracy in 3-D space [m]
+ float DGPS_age; /* time since last DGPS update (s) */
+ UINT16 DGPS_station_ID;
+ UINT8 DGPS_fix_mode; /* MTK_GPS_DGPS_MODE: 0(N/A); 1(RTCM); 2(SBAS) */
+ UINT8 sv_used_num; /* for GPGSA */
+ UINT8 sv_in_view_num; /* for GPGSV */
+ UINT8 sv_used_prn_list[MTK_GPS_SV_MAX_NUM];
+ UINT8 sv_used_type_list[MTK_GPS_SV_MAX_NUM];
+ UINT8 sv_in_view_prn_list[MTK_GPS_SV_MAX_NUM];
+ UINT8 sv_in_view_type_list[MTK_GPS_SV_MAX_NUM];
+ INT8 sv_in_view_elev[MTK_GPS_SV_MAX_NUM];
+ UINT16 sv_in_view_azim[MTK_GPS_SV_MAX_NUM];
+ float sv_in_view_snr[MTK_GPS_SV_MAX_NUM];
+ UINT8 sv_eph_valid[MTK_GPS_SV_MAX_PRN]; /* sv ephemeris status 0: no ephemeris, 1: broadcast eph, 2: BEE ephmeris, */
+ UINT8 sv_eph_day[MTK_GPS_SV_MAX_PRN]; /* day of BEE */
+ UINT8 fgMulti_GNSS;
+ float sv_in_view_snr_L5[MTK_GPS_SV_MAX_NUM];
+} MTK_GPS_POSITION;
+
+typedef struct
+{ /* GPSS/QZSS index 0~31 represents PRN 1~32, respectively */
+ UINT8 health[MTK_GPS_SV_MAX_PRN]; /* nonzero: healthy */
+ UINT8 eph[MTK_GPS_SV_MAX_PRN]; /* nonzero: ephemeris available */
+ UINT8 alm[MTK_GPS_SV_MAX_PRN]; /* nonzero: almanac available */
+ UINT8 dgps[MTK_GPS_SV_MAX_PRN]; /* nonzero: DGPS correction ready */
+ UINT8 codelock[MTK_GPS_SV_MAX_PRN]; /* nonzero: code lock */
+ UINT8 freqlock[MTK_GPS_SV_MAX_PRN]; /* nonzero: frequency lock */
+ UINT8 carrlock[MTK_GPS_SV_MAX_PRN]; /* nonzero: carrier lock */
+
+ /* index 0~4 represents PRN 193~197, respectively */
+ UINT8 qzshealth[MTK_QZS_SV_MAX_PRN]; /* nonzero: healthy */
+ UINT8 qzseph[MTK_QZS_SV_MAX_PRN]; /* nonzero: ephemeris available */
+ UINT8 qzsalm[MTK_QZS_SV_MAX_PRN]; /* nonzero: almanac available */
+ UINT8 qzsdgps[MTK_QZS_SV_MAX_PRN]; /* nonzero: DGPS correction ready */
+ UINT8 qzscodelock[MTK_QZS_SV_MAX_PRN]; /* nonzero: code lock */
+ UINT8 qzsfreqlock[MTK_QZS_SV_MAX_PRN]; /* nonzero: frequency lock */
+ UINT8 qzscarrlock[MTK_QZS_SV_MAX_PRN]; /* nonzero: carrier lock */
+} MTK_GPS_SV_INFO;
+
+typedef struct
+{ /* GALILEO */
+ UINT8 health[MTK_GLEO_SV_MAX_NUM]; /* nonzero: healthy */
+ UINT8 eph[MTK_GLEO_SV_MAX_NUM]; /* nonzero: ephemeris available */
+ UINT8 alm[MTK_GLEO_SV_MAX_NUM]; /* nonzero: almanac available */
+ UINT8 dgps[MTK_GLEO_SV_MAX_NUM]; /* nonzero: DGPS correction ready */
+ UINT8 codelock[MTK_GLEO_SV_MAX_NUM]; /* nonzero: code lock */
+ UINT8 freqlock[MTK_GLEO_SV_MAX_NUM]; /* nonzero: frequency lock */
+ UINT8 carrlock[MTK_GLEO_SV_MAX_NUM]; /* nonzero: carrier lock */
+} MTK_GLEO_SV_INFO;
+
+typedef struct
+{ /* BLONASS PRN 1~24 represents */
+ UINT8 health[MTK_GLON_SV_MAX_NUM]; /* nonzero: healthy */
+ UINT8 eph[MTK_GLON_SV_MAX_NUM]; /* nonzero: ephemeris available */
+ UINT8 alm[MTK_GLON_SV_MAX_NUM]; /* nonzero: almanac available */
+ UINT8 dgps[MTK_GLON_SV_MAX_NUM]; /* nonzero: DGPS correction ready */
+ UINT8 codelock[MTK_GLON_SV_MAX_NUM]; /* nonzero: code lock */
+ UINT8 freqlock[MTK_GLON_SV_MAX_NUM]; /* nonzero: frequency lock */
+ UINT8 carrlock[MTK_GLON_SV_MAX_NUM]; /* nonzero: carrier lock */
+} MTK_GLON_SV_INFO;
+
+typedef struct
+{ // Beidou
+ UINT8 health[MTK_BEDO_SV_MAX_NUM]; /* nonzero: healthy */
+ UINT8 eph[MTK_BEDO_SV_MAX_NUM]; /* nonzero: ephemeris available */
+ UINT8 alm[MTK_BEDO_SV_MAX_NUM]; /* nonzero: almanac available */
+ UINT8 dgps[MTK_BEDO_SV_MAX_NUM]; /* nonzero: DGPS correction ready */
+ UINT8 codelock[MTK_BEDO_SV_MAX_NUM]; /* nonzero: code lock */
+ UINT8 freqlock[MTK_BEDO_SV_MAX_NUM]; /* nonzero: frequency lock */
+ UINT8 carrlock[MTK_BEDO_SV_MAX_NUM]; /* nonzero: carrier lock */
+} MTK_BEDO_SV_INFO;
+
+typedef INT32 (*MTK_GPS_CALLBACK)(MTK_GPS_NOTIFICATION_TYPE msg);
+
+
+typedef enum
+{
+ MTK_DATUM_WGS84,
+ MTK_DATUM_TOKYO_M,
+ MTK_DATUM_TOKYO_A,
+ MTK_DATUM_USER_SETTING,
+ MTK_DATUM_ADINDAN_BURKINA_FASO,
+ MTK_DATUM_ADINDAN_CAMEROON,
+ MTK_DATUM_ADINDAN_ETHIOPIA,
+ MTK_DATUM_ADINDAN_MALI,
+ MTK_DATUM_ADINDAN_MEAN_FOR_ETHIOPIA_SUDAN,
+ MTK_DATUM_ADINDAN_SENEGAL,
+ MTK_DATUM_ADINDAN_SUDAN,
+ MTK_DATUM_AFGOOYE_SOMALIA,
+ MTK_DATUM_AIN_EL_ABD1970_BAHRAIN,
+ MTK_DATUM_AIN_EL_ABD1970_SAUDI_ARABIA,
+ MTK_DATUM_AMERICAN_SAMOA1962_AMERICAN_SAMOA,
+ MTK_DATUM_ANNA_1_ASTRO1965_COCOS_ISLAND,
+ MTK_DATUM_ANTIGU_ISLAND_ASTRO1943_ANTIGUA,
+ MTK_DATUM_ARC1950_BOTSWANA,
+ MTK_DATUM_ARC1950_BURUNDI,
+ MTK_DATUM_ARC1950_LESOTHO,
+ MTK_DATUM_ARC1950_MALAWI,
+ MTK_DATUM_ARC1950_MEAN_FOR_BOTSWANA,
+ MTK_DATUM_ARC1950_SWAZILAND,
+ MTK_DATUM_ARC1950_ZAIRE,
+ MTK_DATUM_ARC1950_ZAMBIA,
+ MTK_DATUM_ARC1950_ZIMBABWE,
+ MTK_DATUM_ARC1960_MEAN_FOR_KENYA_TANZANIA,
+ MTK_DATUM_ARC1960_KENYA,
+ MTK_DATUM_ARC1960_TAMZAMIA,
+ MTK_DATUM_ASCENSION_ISLAND1958_ASCENSION,
+ MTK_DATUM_ASTRO_BEACONE1945_IWO_JIMA,
+ MTK_DATUM_ASTRO_DOS714_ST_HELENA_ISLAND,
+ MTK_DATUM_ASTRO_TERN_ISLAND_FRIG1961_TERN_ISLAND,
+ MTK_DATUM_ASTRONOMICAL_STATION1952_MARCUS_ISLAND,
+ MTK_DATUM_AUSTRALIAN_GEODETIC1966_AUSTRALIA_TASMANIA,
+ MTK_DATUM_AUSTRALIAN_GEODETIC1984_AUSTRALIA_TASMANIA,
+ MTK_DATUM_AYABELLE_LIGHTHOUSE_DJIBOUTI,
+ MTK_DATUM_BELLEVUE_IGN_EFATE_ERROMANGO_ISLAND,
+ MTK_DATUM_BERMUDA1957_BERMUDA,
+ MTK_DATUM_BISSAU_GUUINEA_BISSAU,
+ MTK_DATUM_BOGOTA_OBSERVAORY_COLOMBIA,
+ MTK_DATUM_BUKIT_RIMPAH_INDONESIA,
+ MTK_DATUM_CAMP_AREA_ASTRO_ANTARCTICA,
+ MTK_DATUM_CAMPO_INCHAUSPE_ARGENTINA,
+ MTK_DATUM_CANTON_ASTRO1966_PHOENIX_ISLAND,
+ MTK_DATUM_CAPE_SOUTH_AFRICA,
+ MTK_DATUM_CAPE_CANAVERAL_BAHAMAS_FLORIDA,
+ MTK_DATUM_CARTHAGE_TUNISIA,
+ MTK_DATUM_CHATHAM_ISLAND_ASTRO1971_NEW_ZEALAND,
+ MTK_DATUM_CHUA_ASTRO_PARAGUAY,
+ MTK_DATUM_CORREGO_ALEGRE_BRAZIL,
+ MTK_DATUM_DABOLA_GUINEA,
+ MTK_DATUM_DECEPTION_ISLAND_DECEPTION_ISLAND_ANTARCTIA,
+ MTK_DATUM_DJAKARTA_BATAVIA_INDONESIA_SUMATRA,
+ MTK_DATUM_DOS1968_NEW_GEORGIA_ISLAND_GIZO_ISLAND,
+ MTK_DATUM_EASTER_ISLAND1967_EASTER_ISLAND,
+ MTK_DATUM_ESTONIA_COORDINATE_SYSTEM1937_ESTONIA,
+ MTK_DATUM_EUROPEAN1950_CYPRUS,
+ MTK_DATUM_EUROPEAN1950_EGYPT,
+ MTK_DATUM_EUROPEAN1950_ENGLAND_CHANNEL_ISLANDS_SCOTLAND_SHETLAND_ISLANDS,
+ MTK_DATUM_EUROPEAN1950_ENGLAND_IRELAND_SCOTLAND_SHETLAND_ISLANDS,
+ MTK_DATUM_EUROPEAN1950_FINLAND_NORWAY,
+ MTK_DATUM_EUROPEAN1950_GREECE,
+ MTK_DATUM_EUROPEAN1950_IRAN,
+ MTK_DATUM_EUROPEAN1950_ITALY_SARDINIA,
+ MTK_DATUM_EUROPEAN1950_ITALT_SLCILY,
+ MTK_DATUM_EUROPEAN1950_MALTA,
+ MTK_DATUM_EUROPEAN1950_MEAN_FOR_AUSTRIA_BELGIUM,//_DENMARK_FINLAND_FRANCE_WGERMANY_GIBRALTAR_GREECE_ITALY_LUXEMBOURG_NETHERLANDS_NORWAY_PORTUGAL_SPAIN_SWEDEN_SWITZERLAND,
+ MTK_DATUM_EUROPEAN1950_MEAN_FOR_AUSTRIA_DEBNMARK,//_FRANCE_WGERMANY_NETHERLAND_SWITZERLAND,
+ MTK_DATUM_EUROPEAN1950_MEAN_FOR_IRAG_ISRAEL_JORDAN,//_LEBANON_KUWAIT_SAUDI_ARABIA_SYRIA,
+ MTK_DATUM_EUROPEAN1950_PORTUGAL_SPAIN,
+ MTK_DATUM_EUROPEAN1950_TUNISIA,
+ MTK_DATUM_EUROPEAN1979_MEAN_FOR_AUSTRIA_FINLAND_,//NETHERLANDS_NORWAY_SPAIN_SWEDEN_SWITZERLAND,
+ MTK_DATUM_FORT_THOMAS1955_NEVIS_ST_KITTS_LEEWARD_ISLANDS,
+ MTK_DATUM_GAN1970_REPUBLIC_OF_MALDIVES,
+ MTK_DATUM_GEODETIC_DATAUM1970_NEW_ZEALAND,
+ MTK_DATUM_GRACIOSA_BASE_SW1948_AZORES_FAIAL_GRACIOSA_PICO_SAO,
+ MTK_DATUM_GUAM1963_GUAM,
+ MTK_DATUM_GUNUNG_SEGARA_INDONESIA_KALIMANTAN,
+ MTK_DATUM_GUX_1_ASTRO_GUADALCANAL_ISLAND,
+ MTK_DATUM_HERAT_NORTH_AFGHANISTAN,
+ MTK_DATUM_HERMANNSKOGEL_DATUM_CROATIA_SERBIA_BOSNIA_HERZEGOIVNA,
+ MTK_DATUM_HJORSEY1955_ICELAND,
+ MTK_DATUM_HONGKONG1963_HONGKONG,
+ MTK_DATUM_HU_TZU_SHAN_TAIWAN,
+ MTK_DATUM_INDIAN_BANGLADESH,
+ MTK_DATUM_INDIAN_INDIA_NEPAL,
+ MTK_DATUM_INDIAN_PAKISTAN,
+ MTK_DATUM_INDIAN1954_THAILAND,
+ MTK_DATUM_INDIAN1960_VIETNAM_CON_SON_ISLAND,
+ MTK_DATUM_INDIAN1960_VIETNAM_NEAR16N,
+ MTK_DATUM_INDIAN1975_THAILAND,
+ MTK_DATUM_INDONESIAN1974_INDONESIA,
+ MTK_DATUM_IRELAND1965_IRELAND,
+ MTK_DATUM_ISTS061_ASTRO1968_SOUTH_GEORGIA_ISLANDS,
+ MTK_DATUM_ISTS073_ASTRO1969_DIEGO_GARCIA,
+ MTK_DATUM_JOHNSTON_ISLAND1961_JOHNSTON_ISLAND,
+ MTK_DATUM_KANDAWALA_SRI_LANKA,
+ MTK_DATUM_KERGUELEN_ISLAND1949_KERGUELEN_ISLAND,
+ MTK_DATUM_KERTAU1948_WEST_MALAYSIA_SINGAPORE,
+ MTK_DATUM_KUSAIE_ASTRO1951_CAROLINE_ISLANDS,
+ MTK_DATUM_KOREAN_GEODETIC_SYSTEM_SOUTH_KOREA,
+ MTK_DATUM_LC5_ASTRO1961_CAYMAN_BRAC_ISLAND,
+ MTK_DATUM_LEIGON_GHANA,
+ MTK_DATUM_LIBERIA1964_LIBERIA,
+ MTK_DATUM_LUZON_PHILIPPINES_EXCLUDING_MINDANAO,
+ MTK_DATUM_LUZON_PHILLIPPINES_MINDANAO,
+ MTK_DATUM_MPORALOKO_GABON,
+ MTK_DATUM_MAHE1971_MAHE_ISLAND,
+ MTK_DATUM_MASSAWA_ETHIOPIA_ERITREA,
+ MTK_DATUM_MERCHICH_MOROCCO,
+ MTK_DATUM_MIDWAY_ASTRO1961_MIDWAY_ISLANDS,
+ MTK_DATUM_MINNA_CAMEROON,
+ MTK_DATUM_MINNA_NIGERIA,
+ MTK_DATUM_MONTSERRAT_ISLAND_ASTRO1958_MONTSERRAT_LEEWARD_ISLAND,
+ MTK_DATUM_NAHRWAN_OMAN_MASIRAH_ISLAND,
+ MTK_DATUM_NAHRWAN_SAUDI_ARABIA,
+ MTK_DATUM_NAHRWAN_UNITED_ARAB_EMIRATES,
+ MTK_DATUM_NAPARIMA_BWI_TRINIDAD_TOBAGO,
+ MTK_DATUM_NORTH_AMERICAN1927_ALASKA_EXCLUDING_ALEUTIAN_IDS,
+ MTK_DATUM_NORTH_AMERICAN1927_ALASKA_ALEUTIAN_IDS_EAST_OF_180W,
+ MTK_DATUM_NORTH_AMERICAN1927_ALASKA_ALEUTIAN_IDS_WEST_OF_180W,
+ MTK_DATUM_NORTH_AMERICAN1927_BAHAMAS_EXCEPT_SAN_SALVADOR_ISLANDS,
+ MTK_DATUM_NORTH_AMERICAN1927_BAHAMAS_SAN_SALVADOR_ISLANDS,
+ MTK_DATUM_NORTH_AMERICAN1927_CANADA_ALBERTA_BRITISH_COLUMBIA,
+ MTK_DATUM_NORTH_AMERICAN1927_CANADA_MANITOBA_ONTARIO,
+ MTK_DATUM_NORTH_AMERICAN1927_CANADA_NEW_BRUNSWICK_NEWFOUNDLAND_NOVA_SCOTIA_QUBEC,
+ MTK_DATUM_NORTH_AMERICAN1927_CANADA_NORTHWEST_TERRITORIES_SASKATCHEWAN,
+ MTK_DATUM_NORTH_AMERICAN1927_CANADA_YUKON,
+ MTK_DATUM_NORTH_AMERICAN1927_CANAL_ZONE,
+ MTK_DATUM_NORTH_AMERICAN1927_CUBA,
+ MTK_DATUM_NORTH_AMERICAN1927_GREENLAND_HAYES_PENINSULA,
+ MTK_DATUM_NORTH_AMERICAN1927_MEAN_FOR_ANTIGUA_BARBADOS_BARBUDA_CAICOS, // _ISLANDS_CUBA_DOMINICAN_GRAND_CAYMAN_JAMAICA_TURKS_ISLANDS,
+ MTK_DATUM_NORTH_AMERICAN1927_MEAN_FOR_BELIZE_COSTA_RICA_SALVADOR_GUATEMALA,//_HONDURAS_NICARAGUA,
+ MTK_DATUM_NORTH_AMERICAN1927_MEAN_FOR_CANADA,
+ MTK_DATUM_NORTH_AMERICAN1927_MEAN_FOR_CONUS,
+ MTK_DATUM_NORTH_AMERICAN1927_MEAN_FOR_CONUS_EAST_OF_MISSISSIPPI_RIVER, //_INCLUDING_LOUISIANA_MISSOURI_MINNESOTA,
+ MTK_DATUM_NORTH_AMERICAN1927_MEAN_FOR_CONUS_WEST_OF_MISSISSIPPI_RIVER,//_EXCLUDING_LOUISIANA_MINNESOTA_MISSOURI,
+ MTK_DATUM_NORTH_AMERICAN1927_MEXICO,
+ MTK_DATUM_NORTH_AMERICAN1983_ALASKA_EXCLUDING_ALEUTIAN_IDS,
+ MTK_DATUM_NORTH_AMERICAN1983_ALEUTIAN_IDS,
+ MTK_DATUM_NORTH_AMERICAN1983_CANADA,
+ MTK_DATUM_NORTH_AMERICAN1983_CONUS,
+ MTK_DATUM_NORTH_AMERICAN1983_HAHWII,
+ MTK_DATUM_NORTH_AMERICAN1983_MEXICO_CENTRAL_AMERICA,
+ MTK_DATUM_NORTH_SAHARA1959_ALGERIA,
+ MTK_DATUM_OBSERVATORIO_METEOROLOGICO1939_AZORES_CORVO_FLORES_ISLANDS,
+ MTK_DATUM_OLD_EGYPTIAN1907_EGYPT,
+ MTK_DATUM_OLD_HAWAIIAN_HAWAII,
+ MTK_DATUM_OLD_HAWAIIAN_KAUAI,
+ MTK_DATUM_OLD_HAWAIIAN_MAUI,
+ MTK_DATUM_OLD_HAWAIIAN_MEAN_FOR_HAWAII_KAUAI_MAUI_OAHU,
+ MTK_DATUM_OLD_HAWAIIAN_OAHU,
+ MTK_DATUM_OMAN_OMAN,
+ MTK_DATUM_ORDNANCE_SURVEY_GREAT_BRITIAN1936_ENGLAND,
+ MTK_DATUM_ORDNANCE_SURVEY_GREAT_BRITIAN1936_ENGLAND_ISLE_OF_MAN_WALES,
+ MTK_DATUM_ORDNANCE_SURVEY_GREAT_BRITIAN1936_MEAN_FOR_ENGLAND_ISLE_OF_MAN,//_SCOTLAND_SHETLAND_ISLAND_WALES,
+ MTK_DATUM_ORDNANCE_SURVEY_GREAT_BRITIAN1936_SCOTLAND_SHETLAND_ISLANDS,
+ MTK_DATUM_ORDNANCE_SURVEY_GREAT_BRITIAN1936_WALES,
+ MTK_DATUM_PICO_DE_LAS_NIEVES_CANARY_ISLANDS,
+ MTK_DATUM_PITCAIRN_ASTRO1967_PITCAIRN_ISLAND,
+ MTK_DATUM_POINT58_MEAN_FOR_BURKINA_FASO_NIGER,
+ MTK_DATUM_POINTE_NOIRE1948_CONGO,
+ MTK_DATUM_PORTO_SANTO1936_PORTO_SANTO_MADERIA_ISLANDS,
+ MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_BOLOVIA,
+ MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_CHILE_NORTHERN_NEAR_19DS,
+ MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_CHILE_SOUTHERN_NEAN_43DS,
+ MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_COLOMBIA,
+ MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_ECUADOR,
+ MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_GUYANA,
+ MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_MEAN_FOR_BOLIVIA_CHILE,//_COLOMBIA_ECUADOR_GUYANA_PERU_VENEZUELA,
+ MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_PERU,
+ MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_VENEZUELA,
+ MTK_DATUM_PROVISIONAL_SOUTH_CHILEAN1963_CHILE_NEAR_53DS_HITO_XV3,
+ MTK_DATUM_PUERTO_RICO_PUERTO_RICO_VIRGIN_ISLANDS,
+ MTK_DATUM_PULKOVO1942_RUSSIA,
+ MTK_DATUM_QATAR_NATIONAL_QATAR,
+ MTK_DATUM_QORNOQ_GREENLAND_SOUTH,
+ MTK_DATUM_REUNION_MASCARENE_ISLAND,
+ MTK_DATUM_ROME1940_ITALY_SARDINIA,
+ MTK_DATUM_S42_PULKOVO1942_HUNGARY,
+ MTK_DATUM_S42_PULKOVO1942_POLAND,
+ MTK_DATUM_S42_PULKOVO1942_CZECHOSLAVAKIA,
+ MTK_DATUM_S42_PULKOVO1942_LATIVA,
+ MTK_DATUM_S42_PULKOVO1942_KAZAKHSTAN,
+ MTK_DATUM_S42_PULKOVO1942_ALBANIA,
+ MTK_DATUM_S42_PULKOVO1942_ROMANIA,
+ MTK_DATUM_SJTSK_CZECHOSLAVAKIA_PRIOR1_JAN1993,
+ MTK_DATUM_SANTO_DOS1965_ESPIRITO_SANTO_ISLAND,
+ MTK_DATUM_SAO_BRAZ_AZORES_SAO_MIGUEL_SANTA_MARIA_IDS,
+ MTK_DATUM_SAPPER_HILL1943_EAST_FALKLAND_ISLAND,
+ MTK_DATUM_SCHWARZECK_NAMIBIA,
+ MTK_DATUM_SELVAGEM_GRANDE1938_SALVAGE_ISLANDS,
+ MTK_DATUM_SIERRA_LEONE1960_SIERRA_LEONE,
+ MTK_DATUM_SOUTH_AMERICAN1969_ARGENTINA,
+ MTK_DATUM_SOUTH_AMERICAN1969_BOLIVIA,
+ MTK_DATUM_SOUTH_AMERICAN1969_BRAZIAL,
+ MTK_DATUM_SOUTH_AMERICAN1969_CHILE,
+ MTK_DATUM_SOUTH_AMERICAN1969_COLOMBIA,
+ MTK_DATUM_SOUTH_AMERICAN1969_ECUADOR,
+ MTK_DATUM_SOUTH_AMERICAN1969_ECUADOR_BALTRA_GALAPAGOS,
+ MTK_DATUM_SOUTH_AMERICAN1969_GUYANA,
+ MTK_DATUM_SOUTH_AMERICAN1969_MEAN_FOR_ARGENTINA_BOLIVIA_BRAZIL,//_CHILE_COLOMBIA_ECUADOR_GUYANA_PARAGUAY_PERU_TRINIDAD_TOBAGO_VENEZUELA,
+ MTK_DATUM_SOUTH_AMERICAN1969_PARAGUAY,
+ MTK_DATUM_SOUTH_AMERICAN1969_PERU,
+ MTK_DATUM_SOUTH_AMERICAN1969_TRINIDAD_TOBAGO,
+ MTK_DATUM_SOUTH_AMERICAN1969_VENEZUELA,
+ MTK_DATUM_SOUTH_ASIA_SINGAPORE,
+ MTK_DATUM_TANANARIVE_OBSERVATORY1925_MADAGASCAR,
+ MTK_DATUM_TIMBALAI1948_BRUNEI_E_MALAYSIA_SABAH_SARAWAK,
+ MTK_DATUM_TOKYO_JAPAN,
+ MTK_DATUM_TOKYO_MEAN_FOR_JAPAN_SOUTH_KOREA_OKINAWA,
+ MTK_DATUM_TOKYO_OKINAWA,
+ MTK_DATUM_TOKYO_SOUTH_KOREA,
+ MTK_DATUM_TRISTAN_ASTRO1968_TRISTAM_DA_CUNHA,
+ MTK_DATUM_VITI_LEVU1916_FIJI_VITI_LEVU_ISLAND,
+ MTK_DATUM_VOIROL1960_ALGERIA,
+ MTK_DATUM_WAKE_ISLAND_ASTRO1952_WAKE_ATOLL,
+ MTK_DATUM_WAKE_ENIWETOK1960_MARSHALL_ISLANDS,
+ MTK_DATUM_WGS1972_GLOBAL_DEFINITION,
+ MTK_DATUM_WGS1984_GLOBAL_DEFINITION,
+ MTK_DATUM_YACARE_URUGUAY,
+ MTK_DATUM_ZANDERIJ_SURINAME
+} MTK_GPS_DATUM;
+
+/************************************************
+ * defines for set_param and get_param
+ ************************************************/
+/*-------- keys --------*/
+typedef enum
+{
+ MTK_PARAM_CMD_TERMINATE,
+ MTK_PARAM_CMD_RESET_DSP,
+ MTK_PARAM_CMD_RESET_KERNEL,
+ MTK_PARAM_CMD_CONFIG,
+ MTK_PARAM_CMD_TESTMODE,
+ MTK_PARAM_CMD_RESTART,
+ MTK_PARAM_DGPS_CONFIG,
+ MTK_PARAM_NAV_CONFIG,
+ MTK_PARAM_BUF_CONFIG,
+ MTK_PARAM_LIB_VERSION,
+ MTK_PARAM_LIB_RELEASE_INFO,
+ MTK_PARAM_TCXO_SINGLE_CONFIG,
+ MTK_PARAM_TCXO_MULTIPLE_CONFIG,
+ MTK_PARAM_EPH_PROGRESS_CONFIG,
+ MTK_PARAM_EPO_STAGE_CONFIG,
+ MTK_PARAM_CMD_STOP,
+ MTK_PARAM_CMD_SLEEP,
+ MTK_PARAM_CMD_WAKEUP,
+ MTK_PARAM_CMD_BLOCK,
+ MTK_PARAM_BEE_CONFIG,
+ MTK_PARAM_BRDC_CONFIG,
+ MTK_PARAM_FRAME_SYNC_RESP,
+ MTK_PARAM_CMD_CONFIG_EPO_DATA,
+ MTK_PARAM_CMD_CONFIG_EPO_TIME,
+ MTK_PARAM_CMD_CONFIG_EPO_POS,
+ MTK_PARAM_CMD_CLR_CLK_DFT,
+ MTK_MSG_EPO_REQ,
+ MTK_MSG_EPO_RESP,
+ MTK_MSG_BEE_REQ,
+ MTK_MSG_BEE_RESP,
+ MTK_MSG_REQ_ASSIST,
+ MTK_MSG_AGENT_BEE_REQ,
+ MTK_MSG_AGENT_SUPL_REQ,
+ MTK_MSG_BEE_IND,
+ MTK_MSG_AGPS_MSG_REQ_NI,
+ MTK_MSG_AGPS_MSG_SUPL_PMTK,
+ MTK_MSG_AGPS_MSG_SUPL_TERMINATE,
+ MTK_MSG_AGPS_MSG_PROFILE,
+ MTK_MSG_AGPS_MSG_RESET_SM,
+ MTK_MSG_VTIMER_IND,
+ MTK_MSG_AL_CFG,
+ MTK_MSG_AL_DEE_CFG,
+ MTK_PARAM_SYSTEM_CONFIG,
+ MTK_PARAM_SYSTEM_STATUS,
+ MTK_PARAM_CMD_SEARCH_QZSS,
+ MTK_PARAM_CMD_LOW_SPEED_FILTERING,
+ MTK_PARAM_NMEA_OUTPUT,
+ MTK_PARAM_CMD_RTC_CFG,
+ MTK_PARAM_CMD_MNL_INIT,
+ MTK_MSG_AGPS_MSG_AGENT_TERMINATE,
+ MTK_PARAM_QUERY_AGC,
+ MTK_MSG_RAW_MEAS,
+ MTK_MSG_REPLACE_LLH,
+ MTK_MSG_QUARTER_EPO_REQ,
+ MTK_MSG_EPO_FILE_UPDATE_DONE,
+ MTK_PARAM_CMD_AUTO_DESENSE,
+ MTK_PARAM_QEPO_DOWNLOAD_RESPONSE,
+ MTK_PARAM_NLP_LLA,
+ MTK_PARAM_CMD_SWITCH_CONSTELLATION,
+ MTK_PARAM_CMD_SIB8_16_ENABLE,
+ MTK_PARAM_CMD_LPPE_ENABLE,
+ MTK_AGPS_MSG_SUPL_LPPE_DATA,
+ MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_IONO, // refer to gnss_ha_common_ionospheric_model_struct
+ MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_TROP, // refer to gnss_ha_common_troposphere_model_struct
+ MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_ALT, // refer to gnss_ha_common_altitude_assist_struct
+ MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_SOLAR,// refer to gnss_ha_common_solar_radiation_struct
+ MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_CCP, // refer to gnss_ha_common_ccp_assist_struct
+ MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_GENERIC_CCP, // refer to gnss_ha_generic_ccp_assist_struct
+ MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_GENERIC_DM, // refer to gnss_ha_generic_degradation_model_struct
+ MTK_PARAM_MTKNAV_DOWNLOAD_RESPONSE,
+ MTK_MSG_MTKNAV_REQ,
+ MTK_PARAM_CMD_CONFIG_MTKNAV_CLEAR,
+ MTK_PARAM_CMD_CONFIG_MTKNAV_DATA,
+ MTK_PARAM_CMD_DEBUG2APP_CONFIG,
+ MTK_PARAM_CMD_ENABLE_FULL_TRACKING,
+ MTK_PARAM_CMD_CONFIG_BLUE_SAT_CORR,
+ MTK_PARAM_CMD_CONFIG_BLUE_MEAS_CORR,
+ MTK_PARAM_CMD_SET_SV_BLACKLIST,
+ MTK_PARAM_CMD_ENABLE_DCB_CALIBRATION,
+ MTK_PARAM_CMD_MD_TIME_SYNC_IND,// Case 2: MD-Initiated (similar to PMTK768)
+ MTK_PARAM_CMD_MD_HW_PULSE,
+ MTK_PARAM_CMD_EXTPVT_OUT_FINAL_REPORT,
+ MTK_PARAM_CMD_EXTPVT_PGNSS_REF_TIME,
+ MTK_PARAM_CMD_EXTPVT_REF_LOC,
+ MTK_PARAM_CMD_EXTPVT_GPS_EPH,
+ MTK_PARAM_CMD_EXTPVT_GANSS_EPH,
+ MTK_PARAM_CMD_EXTPVT_GPS_ALM,
+ MTK_PARAM_CMD_EXTPVT_GANSS_ALM,
+ MTK_PARAM_CMD_EXTPVT_GPS_ION,
+ MTK_PARAM_CMD_EXTPVT_GPS_UTC,
+ MTK_PARAM_CMD_EXTPVT_GPS_RTI,
+ MTK_PARAM_CMD_EXTPVT_GANSS_AUX,
+ MTK_PARAM_CMD_EXTPVT_SET_CN0_MASK,
+ MTK_PARAM_CMD_EXTPVT_SET_ELE_MASK,
+ MTK_PARAM_CMD_EXTPVT_SET_STATIC_VEL_MASK,
+ MTK_PARAM_CMD_EXTPVT_SET_CP_CN0_MASK,
+ MTK_PARAM_CMD_EXTPVT_SET_MEAS_RATE,
+ MTK_PARAM_CMD_SET_AGPS_OPEN_TYPE,
+ MTK_PARAM_CMD_EXTPVT_SET_GEOFANCE,
+ MTK_PARAM_CMD_RTK_FILL_NMEA_INFO,
+ MTK_PARAM_CMD_RTK_FILL_POSITION,
+ MTK_PARAM_CMD_RTK_STATUS_REPONSE,
+} MTK_GPS_PARAM;
+
+typedef enum{
+ MNLD_RTK_INIT = 0,
+ MNLD_RTK_START,
+ MNLD_RTK_STOP,
+ MNLD_RTK_CLEANUP,
+ MNLD_RTK_GET_VER,
+ MNLD_RTK_IOCTL,
+ MNLD_RTK_UPDATE_CONN_STATUS,
+ MNLD_RTK_SET_POSITION_MODE,
+ MNLD_RTK_DELETE_AIDING_DATA,
+ MNLD_RTK_INJECT_EPH,
+ MNLD_RTK_INITINJECT_MEAS,
+ MNLD_RTK_INJECT_NAVMSG,
+ MNLD_RTK_INJECT_IONO,
+ MNLD_RTK_INJECT_POSITION,
+ MNLD_RTK_INJECT_GNSS_DATA,
+ MNLD_RTK_INJECT_GNSS_PPS,
+ MNLD_RTK_INJECT_GNSS_ORT,
+ MNLD_RTK_INJECT_SENSOR_CONFIG,
+ MNLD_RTK_INJECT_SENSOR_DATA,
+ MNLD_RTK_INJECT_MAP_MATCHING_PARA,
+ MNLD_RTK_SET_LEVER_ARM_PARA,
+} MNLDRtkInterfaceType;
+
+/*------- values -------*/
+/* MTK_PARAM_CMD_TERMINATE : terminate GPS main thread: no payload */
+
+/* MTK_PARAM_CMD_CONFIG : schedule an event for get/set aiding data or config:
+ no payload */
+
+/* MTK_PARAM_CMD_TESTMODE : enter/leave a test mode */
+typedef enum
+{
+ MTK_TESTMODE_OFF = 0,
+ MTK_TESTMODE_CHANNEL,
+ MTK_TESTMODE_JAMMER,
+ MTK_TESTMODE_PHASE,
+ MTK_TESTMODE_PER,
+ MTK_TESTMODE_TTICK_OVERFLOW,
+ MTK_TESTMODE_TTICK_OVERFLOW_L5,
+ MTK_TESTMODE_ENTER_MP,
+ MTK_TESTMODE_LEAVE_MP,
+ MTK_TESTMODE_CW_MODE,
+ MTK_TESTMODE_GNSS_JAMMER,
+ MTK_TESTMODE_CN0
+} MTK_GPS_TESTMODE;
+
+typedef struct
+{
+ MTK_GPS_TESTMODE test_mode;
+ UINT8 svid;
+ UINT8 SVid_GLO1; // SVid_GLO1 : 201 ~214 to represent GLONASS Frequency ID
+ UINT8 SVid_GLO2; // SVid_GLO2 : for example, GLONASS FreqID = -7 ==> SVid_GLO1 = -7 +208 = 201;
+ UINT8 SVid_GLO3; // SVid_GLO3 : for example, GLONASS FreqID = 6 ==> SVid_GLO1 = 6 +208 = 214;
+ UINT8 SVid_BD;
+ UINT32 time;
+ UINT8 threshold;
+ UINT16 targetCount;
+ UINT8 CN0;
+} MTK_GPS_PARAM_TESTMODE;
+
+#if 1
+//Auto Desense
+
+#define AUTODSN_TEST_CNT_MAX 50
+
+
+typedef enum
+{
+ MTK_GNSS_AUTODSN_STOP = 0,
+ MTK_GNSS_AUTODSN_CW_MODE = 1,
+ MTK_GNSS_AUTODSN_SIGNAL_MODE,
+ MTK_GNSS_AUTODSN_NORMAL_MODE,
+ MTK_GNSS_AUTODSN_MODE_MAX
+}MTK_GNSS_AUTODSN_MODE;
+
+#if 0
+typedef enum
+{
+ MTK_GNSS_AUTODSN_TI_SUSPEND = 1,
+ MTK_GNSS_AUTODSN_TI_LCM_ONOFF,
+ MTK_GNSS_AUTODSN_TI_LCM_UPDATE,
+ MTK_GNSS_AUTODSN_TI_BACKLIGHT,
+ MTK_GNSS_AUTODSN_TI_WIFI_TX,
+ MTK_GNSS_AUTODSN_TI_WIFI_RX,
+ MTK_GNSS_AUTODSN_TI_MAX = 120
+}MTK_GNSS_AUTODSN_TEST_ITEM;
+#endif
+
+typedef struct
+{
+ MTK_GNSS_AUTODSN_MODE test_mode;
+ UINT8 test_item;
+ UINT8 item_state;
+ UINT8 test_count;
+ UINT8 sv_count;
+ UINT8 SVid_GPS;
+ UINT8 SVid_GLO1; // SVid_GLO1 : 201 ~214 to represent GLONASS Frequency ID
+ UINT8 SVid_GLO2; // SVid_GLO2 : for example, GLONASS FreqID = -7 ==> SVid_GLO1 = -7 +208 = 201;
+ UINT8 SVid_GLO3; // SVid_GLO3 : for example, GLONASS FreqID = 6 ==> SVid_GLO1 = 6 +208 = 214;
+ UINT8 SVid_BD;
+ UINT8 SVid_GPS_L5;
+} MTK_GNSS_PARAM_AUTODSN_MODE;
+
+typedef struct{
+UINT16 sv_id;
+float snr;
+INT8 ele;
+UINT16 azm;
+float snr_l5;
+}MTK_GNSS_BASIC_INFO;
+#endif
+
+/* MTK_PARAM_CMD_RESTART : trigger restart of GPS main thread and dsp code */
+typedef struct
+{
+ MTK_GPS_START_TYPE restart_type; /* MTK_GPS_START_HOT, MTK_GPS_START_WARM, MTK_GPS_START_COLD, MTK_GPS_START_FULL */
+} MTK_GPS_PARAM_RESTART;
+
+/* MTK_PARAM_BEE_CONFIG : configuration of bee */
+typedef struct
+{
+ MTK_GPS_BEE_EN bee_en; /* MTK_BEE_DISABLE MTK_BEE_ENABLE */
+} MTK_GPS_PARAM_BEE_CONFIG;
+
+/* MTK_PARAM_BRDC_CONFIG : configuration of broadcast satellite data */
+typedef struct
+{
+ MTK_GPS_BRDC_EN brdc_en; /* MTK_BRDC_DISABLE MTK_BRDC_ENABLE */
+} MTK_GPS_PARAM_BRDC_CONFIG;
+
+
+typedef struct
+{
+ UINT8 ucSVid;
+ UINT16 u2Weekno;
+ char data[24];
+}MTK_AIDING_PARAM_ALMANAC;
+
+typedef struct
+{
+ UINT8 ucSVid;
+ char data[72];
+}MTK_AIDING_PARAM_EPHEMERIS;
+
+typedef struct
+{
+ UINT16 u2Weekno;
+ double Tow;
+ float timeRMS;
+}MTK_AIDING_PARAM_TIME;
+
+typedef struct
+{
+ double LLH[3];
+}MTK_AIDING_PARAM_POSITION;
+
+typedef struct
+{
+ UINT8 SVid;
+ UINT8 SVid_GLO1;
+ UINT8 SVid_GLO2;
+ UINT8 SVid_GLO3;
+ UINT8 SVid_BD;
+ INT32 action;
+}MTK_PARAM_CHN_TEST;
+
+typedef struct
+{
+ UINT16 mode;
+ UINT16 arg;
+ INT32 action;
+}MTK_PARAM_JAMMER_TEST;
+
+typedef struct
+{
+ INT32 action;
+ UINT32 time;
+ UINT8 SVid;
+}MTK_PARAM_PHASE_TEST;
+
+typedef struct
+{
+ INT16 Threshold;
+ UINT16 SVid;
+ UINT16 TargetCount;
+}MTK_PARAM_PER_TEST;
+
+typedef struct
+{
+ UINT8 fgSyncGpsTime;
+ INT32 i4RtcDiff;
+}MTK_PARAM_TIME_UPDATE_NOTIFY;
+
+typedef struct
+{
+ MTK_GPS_DBG_TYPE DbgType;
+ MTK_GPS_DBG_LEVEL DbgLevel;
+}MTK_PARAM_DEBUG_CONFIG;
+
+typedef struct
+{
+ MTK_GPS_NLP_T NLP; // indicate location type: 0: NLP, 1: fixed location
+ MTK_GPS_TIME utc;
+ UINT8 read_flag; // 0 = non-readed / 1 = readed
+}MTK_GPS_NLP_UTC_T;
+
+//mtk_gps_debug_config(mtk_gps_dbg_type DbgType, mtk_gps_dbg_level DbgLevel)
+
+
+/* MTK_PARAM_SYSTEM_CONFIG : configuration of system parameters */
+typedef struct
+{
+ MTK_GPS_USER_SYSTEM_CONFIG system_config_type; /* system config type */
+ UINT32 system_config_value; /* set/get system config value*/
+ MTK_AIDING_PARAM_EPHEMERIS param_eph;
+ MTK_AIDING_PARAM_ALMANAC param_almanac;
+ MTK_AIDING_PARAM_POSITION param_position;
+ MTK_AIDING_PARAM_TIME param_time;
+ MTK_PARAM_TIME_UPDATE_NOTIFY param_time_update_notify;
+ MTK_PARAM_DEBUG_CONFIG param_debug_config;
+ //
+ MTK_PARAM_CHN_TEST param_chn_test;
+ MTK_PARAM_JAMMER_TEST param_jam_test;
+ MTK_PARAM_PHASE_TEST param_pha_test;
+ MTK_PARAM_PER_TEST param_per_test;
+ MTK_GPS_TCXO_MODE param_tcxo_mode;
+ //
+ INT32 i4RtcDiff;
+ UINT8 TSX_XVT;
+
+} MTK_GPS_PARAM_SYSTEM_CONFIG;
+
+/* MTK_PARAM_SYSTEM_STATUS : status of system parameters */
+typedef struct
+{
+ MTK_GPS_SYSTEM_STATUS system_status_type; /* system status type */
+ UINT32 system_status_value; /* set/get system status value*/
+} MTK_GPS_PARAM_SYSTEM_STATUS;
+
+/* MTK_PARAM_DGPS_CONFIG */
+typedef struct
+{
+ MTK_GPS_DGPS_MODE dgps_mode; /* Off/RTCM/SBAS */
+ UINT8 dgps_timeout; /* DGPS timeout in seconds */
+ MTK_GPS_BOOL sbas_test_mode; /* TRUE=test; FALSE=integrity */
+ UINT8 sbas_prn; /* 0=automatic; 120-139=specific PRN */
+ MTK_GPS_BOOL full_correction; /* SBAS data correction mode */
+ /* TRUE=full [Fast/Long-Term and IONO] */
+ /* FALSE=partial [Fast/Long-Term or IONO] */
+ MTK_GPS_BOOL select_corr_only; /* satellite selection mode */
+ /* TRUE=only SVs with corrections */
+ /* FALSE=any SVs available */
+} MTK_GPS_PARAM_DGPS_CFG;
+
+/* MTK_PARAM_NAV_CONFIG */
+typedef struct
+{
+ UINT32 fix_interval; /* fix interval in milliseconds */
+ /* 1000=>1Hz, 200=>5Hz, 2000=>0.5Hz */
+ MTK_GPS_DATUM datum; /* datum */
+ INT8 elev_mask; /* elevation angle mask in degree */
+} MTK_GPS_PARAM_NAV_CFG;
+
+/* MTK_PARAM_BUF_CONFIG */
+typedef struct
+{
+ UINT16 buf_empty_threshold; /* If the buffer free space reach this value
+ then it will report to callback once */
+ UINT16 buf_empty_size; /* Buffer free space in bytes, read only */
+} MTK_GPS_PARAM_BUF_CFG;
+
+/* MTK_PARAM_AL_CONFIG : config always locate */
+typedef enum
+{
+ MTK_AL_TYPE_NORMAL = 0, // Navigation
+ MTK_AL_TYPE_USER_PERIODIC = 1, // User periodic mode
+ MTK_AL_TYPE_AUTO_PERIODIC = 9 // Auto periodic mode
+} MTK_GPS_AL_TYPE;
+
+typedef struct
+{
+ MTK_GPS_AL_TYPE type; /* application type */
+ UINT32 u4FirstRunTime; /* run time for peridic mode, (milli-second) */
+ UINT32 u4FirstSlpTime; /* sleep time for peridic mode, (milli-second)*/
+ UINT32 u4SecondRunTime; /* run time for peridic mode, (milli-second) */
+ UINT32 u4SecondSlpTime; /* sleep time for peridic mode, (milli-second)*/
+} MTK_PARAM_AL_CFG;
+
+typedef struct
+{
+ UINT8 u1SV ; /* SV number for DEE extension start criterion */
+ UINT8 u1SNR; /* SNR threshold for DEE extension start criterion */
+ UINT32 u4ExtensionThreshold; /* Extension time limitation for DEE, (milli-second) */
+ UINT32 u4ExtensionGap; /* Extension gap limitation between neighbor DEE , (milli-second)*/
+} MTK_PARAM_AL_DEE_CFG;
+typedef struct
+{
+ char support_lppe ;
+ char vertion[MTK_GPS_LIB_VER_LEN_MAX];
+} MTK_GPS_MNL_INFO;
+
+typedef struct
+{
+ UINT32 u4EPOWORD[18]; /* 18 words [LSB first] of one EPO segment data (total 72 bytes) */
+ UINT8 u1SatID; /* 1~32 */
+} MTK_GPS_PARAM_EPO_DATA_CFG;
+
+typedef struct
+{
+ UINT32 u4Type;
+ UINT32 u4Len;
+ UINT32 u4Data[(AGT_MTKNAV_TYPE_MAX_LEN)/sizeof(UINT32)]; /* [LSB first] one type of MTKNAV data */
+ UINT32 u4Csm;
+} MTK_GPS_PARAM_MTKNAV_DATA_CFG;
+
+typedef struct
+{
+ UINT16 u2YEAR ; /* > 2000 */
+ UINT8 u1MONTH; /* 1~12 */
+ UINT8 u1DAY; /* 1~31*/
+ UINT8 u1HOUR; /* 0~23*/
+ UINT8 u1MIN; /* 0~59*/
+ UINT8 u1SEC; /* 0~59*/
+} MTK_GPS_PARAM_EPO_TIME_CFG;
+
+typedef struct
+{
+ double dfLAT; /* > -90 and <90 (degree)*/
+ double dfLON; /* > -180 and <180 (degree)*/
+ double dfALT; /* (m) */
+ UINT16 u2YEAR; /* > 2000 */
+ UINT8 u1MONTH; /* 1~12 */
+ UINT8 u1DAY; /* 1~31*/
+ UINT8 u1HOUR; /* 0~23*/
+ UINT8 u1MIN; /* 0~59*/
+ UINT8 u1SEC; /* 0~59*/
+} MTK_GPS_PARAM_EPO_POS_CFG;
+
+typedef struct
+{
+ float r4TcxoOffest; /* TCXO offest frequency (Hz)*/
+ UINT8 u1SatID; /* 1~32 */
+} MTK_GPS_PARAM_TCXO_CFG;
+
+typedef struct
+{
+ float r4EphProgress[MTK_GPS_SV_MAX_PRN]; /* The current Eph Progress (0~1)*/
+} MTK_GPS_PARAM_EPH_PROGRESS_CFG;
+
+typedef struct
+{
+ UINT32 u4EpoStage; /* The invalid/valid Epo Stage in bit map format(0/1)*/
+} MTK_GPS_PARAM_EPO_STAGE_CFG;
+
+typedef enum
+{
+ MTK_GPS_FS_RESULT_INIT = 0, /* FS request initial value */
+ MTK_GPS_FS_RESULT_ERR, /* FS request error and clear naram's data */
+ MTK_GPS_FS_RESULT_ERR_NOT_CLR, /* FS request error but don't clear nvram's data */
+ MTK_GPS_FS_RESULT_OK /* FS request success */
+} MTK_GPS_FS_RESULT;
+
+typedef enum
+{
+ MTK_GPS_FS_WORK_MODE_AIDING = 0, /* FS request for aiding phase */
+ MTK_GPS_FS_WORK_MODE_MAINTAIN /* FS request for maintain phase */
+} MTK_GPS_FS_WORK_MODE;
+
+/* MTK_PARAM_FRAME_SYNC_RESP : receive a result of a frame sync meas request */
+typedef struct
+{
+ MTK_GPS_FS_RESULT eResult; /* frame sync measurement request result */
+ double dfFrameTime; /* frame time of the issued frame pulse */
+} MTK_GPS_PARAM_FRAME_SYNC_RESP;
+
+/* MTK_PARAM_QZSS_SEARCH_CONFIG : configuration of broadcast satellite data */
+typedef struct
+{
+ MTK_QZSS_SEARCH_MODE qzss_en; /* MTK_QZSS_DISABLE MTK_QZSS_ENABLE */
+} MTK_PARAM_QZSS_SEARCH_MODE;
+
+
+/* MTK_PARAM_LOW_SPEED_FILTERING_CONFIGURATION : configuration of low speed filtering setting */
+typedef struct
+{
+ MTK_LOW_SPEED_FILTERING_MODE low_speed_filtering_en; /* MTK_LOW_SPEED_FILTERING_SETTING */
+} MTK_PARAM_LOW_SPEED_FILTERING;
+
+
+
+/* MTK_PARAM_QUERY_AGC : query AGC value */
+typedef struct
+{
+ UINT16 u2AGC; /* AGC value */
+} MTK_GPS_PARAM_QUERY_AGC_VALUE;
+
+
+/* MTK_PARAM_PMTK_CMD : receive a PMTK message for BEE safety design */
+#define MTK_PMTK_CMD_MAX_SIZE 256
+typedef struct
+{
+ char pmtk[MTK_PMTK_CMD_MAX_SIZE]; /* Buffer free space in bytes, read only */
+} MTK_GPS_PARAM_PMTK_CMD;
+
+typedef struct
+{
+ UINT16 u2Bitmap;
+ INT16 i2WeekNo;
+ INT32 i4Tow;
+ MTK_GPS_BOOL fgFirstReq;
+} MTK_GPS_PARAM_AGPS_REQ;
+
+typedef struct
+{
+ UINT16 u2AckCmd;
+ UINT8 u1Flag;
+} MTK_GPS_PMTKD_001T;
+
+typedef struct{
+ double dfRtcDltTime;
+} MTK_GPS_PMTKD_243_T;
+
+typedef struct{
+ MTK_GPS_BOOL fgSet; // reference location: 0 - clear, 1 - set
+ double dfRefLat;
+ double dfRefLon;
+ float fRefAlt;
+} MTK_GPS_PMTKD_244_T;
+
+typedef struct
+{
+ UINT16 u2Cmd; // PMTK command ID:
+ // please get the data arguements in the following corresponding data structure.
+ union
+ {
+ MTK_GPS_PMTKD_001T rAck; // PMTK001
+ } uData;
+} MTK_GPS_PMTK_RESPONSE_T;
+
+typedef struct
+{
+ UINT16 u2Cmd; // PMTK command ID: if the PMTK command has data arguments,
+ // please assign the data in the following corresponding data structure.
+ union
+ {
+ MTK_GPS_PMTKD_243_T r243;
+ MTK_GPS_PMTKD_244_T r244;
+ } uData;
+} MTK_GPS_PMTK_DATA_T;
+
+
+typedef struct
+{
+ UINT16 type;
+ UINT16 mcc;
+ UINT16 mnc;
+ UINT16 lac;
+ UINT16 cid;
+} MTK_GPS_REF_LOCATION_CELLID;
+
+typedef struct
+{
+ UINT8 mac[6];
+} MTK_GPS_REF_LOCATION_MAC;
+
+/** Represents ref locations */
+typedef struct
+{
+ UINT16 type; // 0 : Cell ID; 1: MAC
+ union
+ {
+ MTK_GPS_REF_LOCATION_CELLID cellID;
+ MTK_GPS_REF_LOCATION_MAC mac;
+ }u;
+} MTK_GPS_REF_LOCATION;
+
+
+typedef enum
+{
+ MTK_IF_SW_EMULATION = 0,
+ MTK_IF_UART_NO_HW_FLOW_CTRL,
+ MTK_IF_UART_HW_FLOW_CTRL,
+ MTK_IF_SPI,
+ MTK_IF_APB
+} MTK_GPS_IF_TYPE;
+
+typedef enum
+{
+ MTK_PPS_DISABLE = 0,
+ MTK_PPS_ATFER_TTFF,
+ MTK_PPS_3D_FIX,
+ MTK_PPS_2D_FIX,
+ MTK_PPS_ALWAYS
+} MTK_GPS_PPS_MODE;
+
+// ****************** Important Notice *************************//
+// In oder to make sure the GNSS configuration works correctly,
+// Please delete "mtk_gps.dat" after change the MTK_GNSS_CONFIGURATION setting.
+typedef enum
+{
+ MTK_CONFIG_GPS_GLONASS = 0,
+ MTK_CONFIG_GPS_BEIDOU,
+ MTK_CONFIG_GPS_GLONASS_BEIDOU,
+ MTK_CONFIG_GPS_ONLY,
+ MTK_CONFIG_BEIDOU_ONLY,
+ MTK_CONFIG_GLONASS_ONLY,
+ MTK_CONFIG_GPS_GLONASS_BEIDOU_GALILEO,
+ MTK_CONFIG_GPS_GALILEO,
+ MTK_CONFIG_GPS_GLONASS_GALILEO,
+ MTK_CONFIG_GALILEO_ONLY,
+ MTK_CONFIG_GPS_GLONASS_BEIDOU_GALILEO_NAVIC,
+ MTK_CONFIG_GNSS_END
+} MTK_GNSS_CONFIGURATION;
+
+typedef struct
+{
+ UINT32 pps_version;
+ UINT16 pps_delay;
+ UINT8 pps_polarity;
+ UINT16 pps_duty;
+} MTK_GPS_PPS_CFG;
+
+
+// for AOSP AGPS:
+// 1. PMTK data don't encript
+// 2. don't output PMTK010 to AGPSD
+typedef enum
+{
+ MTK_GPS_NORMAL_MODE = 0, // used for legacy AGPS
+ MTK_GPS_AOSP_MODE = 1, // used in AOSP AGPS
+}MTK_GPS_VERSION_MODE;
+
+/* factory default configuration for mtk_gps_init() */
+typedef struct
+{
+ MTK_GPS_IF_TYPE if_type; /* interface type UART/SPI */
+ MTK_GPS_PPS_MODE pps_mode; /* 1PPS mode, Default: MTK_PPS_3D_FIX */
+ MTK_GPS_DATUM datum; /* datum */
+ MTK_GPS_DGPS_MODE dgps_mode; /* Off/RTCM/SBAS */
+ MTK_GPS_TCXO_MODE tcxo_mode;
+ UINT16 pps_duty; /* PPS pulse high duration (ms), Range: 0~999, Default: 100 */
+ UINT8 pps_port; /* pps output port select */
+ UINT8 u1ClockType; // FLASH_SIG_USE_16368_TCXO 0 // 16.368M integer, the most stable
+ // FLASH_SIG_USE_16369M_TCXO 1 // 16.369M integer, generated freq has bias
+ // FLASH_SIG_USE_26M_FRAC_TCXO 2 // not used
+ // FLASH_SIG_USE_26M_INT_TCXO 3 // 26M integer, generated freq has bias,
+ // FLASH_SIG_USE_WIDERANGE_XTAL 0xFE // wide range crystal.
+ // FLASH_SIG_USE_WIDERANGE 0xFF // wide range, more power consumption, no freq bias
+ UINT16 hw_Clock_Drift; /* TCXO clock drift in ppb (500=0.5ppm; 2500=2.5ppm) */
+ UINT32 hw_Clock_Freq; /* TCXO frequency in Hz */
+ UINT32 if_link_spd; /* interface link speed (bps of UART) */
+ UINT32 fix_interval; /* fix interval in milliseconds */
+ /* 1000=>1Hz, 200=>5Hz, 2000=>0.5Hz */
+ UINT8 Int_LNA_Config; /* for 3326, 1: internal LNA, for 3336,1: high gain, for 3332, 1: high gain */
+
+ UINT32 reservedx;
+ UINT32 reservedx_2;
+ void* reservedy;
+ void* reservedy_2;
+ MTK_GNSS_CONFIGURATION GNSSOPMode; // In oder to make sure the GNSS configuration works correctly,
+ // Please delete "mtk_gps.dat" after change the MTK_GNSS_CONFIGURATION setting.
+ UINT32 C0;
+ UINT32 C1;
+ UINT32 initU;
+ UINT32 lastU;
+ MTK_GPS_VERSION_MODE mtk_gps_version_mode; //AOSP or not
+ UINT8 Int_IMAX_Config; // O: no IMAX test, 1 IMAX
+ UINT8 Jamming_Detection_Msg; // 0: Disable PMTKSPF message output, 1: Enable PMTKSPF message output
+ UINT32 eLNA_pin_num; //gps eLNA pin number
+ UINT8 sv_type_agps_set;
+ UINT8 GLP_Enabled; //0: Disable GLP, 1: Enable GLP
+ UINT8 fast_HTTFF_enabled; //0: Disable, 1: Enable
+ UINT8 factory_test_state; //0: normal, 1: specific customer's factory test
+ UINT8 factory_mode; //0: normal mode, 1: non-normal mode
+ UINT8 pps_polarity; /* Range: 0~1 , Default: 0 */
+ UINT16 pps_delay; /* Range: 0~2000, Default: 0 */
+ INT8 elev_mask; /* Range: 0~90 */
+} MTK_GPS_INIT_CFG;
+
+#define MTK_GPS_DRIVER_CFG_EXT_SUPPORT
+typedef struct
+{
+ UINT32 nmea_link_spd; //NMEA Baydrate
+ UINT8 DebugType;
+ // 1: Enable Agent debug
+ // 0: Disable Agent debug
+ char nv_file_name[30]; // NV ram file name
+ char ofl_nv_file_name[30]; // NV ram file name for offload mode
+ char dbg_file_name[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN]; // NMEA dbg file name
+ char dsp_port_name[30]; //DSP port name
+ char dsp2_port_name[30]; //DSP port name
+ char nmea_port_name[30]; //NMEA out port name
+ char nmeain_port_name[30];//NMEA in port name
+ UINT8 bee_path_name[30]; // HS patch name
+ UINT8 epo_file_name[MTK_GPS_EPO_FILE_NAME_LEN]; // epo working file
+ UINT8 epo_update_file_name[MTK_GPS_EPO_FILE_NAME_LEN]; // epo updated file
+ UINT8 qepo_file_name[MTK_GPS_EPO_FILE_NAME_LEN]; // qepo working file
+ UINT8 qepo_update_file_name[MTK_GPS_EPO_FILE_NAME_LEN]; // qepo updated file
+ UINT8 qepo_bd_file_name[MTK_GPS_EPO_FILE_NAME_LEN]; // qepo working file
+ UINT8 qepo_bd_update_file_name[MTK_GPS_EPO_FILE_NAME_LEN]; // qepo updated file
+ INT32 gps_test_mode; // GPS TEST MODE, 1: Enable TSET MODE, 0 : Normal MODE
+ UINT8 u1AgpsMachine; // 0: for field test or Spirent ULTS (Default value in MNL), 1: R&S CRTU
+ int dsp_fd;
+ int dsp2_fd;
+ UINT8 reserved;
+ UINT32 log_file_max_size; //The max size limitation of one debug log file, 1MB(1024*1024)~48MB(48*1024*1024), default is 20MB
+ UINT32 log_folder_max_size; //The max size limitation of the debug log folder, log_file_max_size*12~512MB(512*1024*1024), default is 240MB
+ UINT32 socket_port;//The socket port number. 0xFFFFF: close socket
+ char hal_ver[30];
+ char mnld_ver[30];
+ UINT8 mtknav_file_name[MTK_GPS_EPO_FILE_NAME_LEN]; // mtknav working file
+ UINT8 mtknav_update_file_name[MTK_GPS_EPO_FILE_NAME_LEN]; // mtknav updated file
+ UINT8 qepo_ga_file_name[MTK_GPS_EPO_FILE_NAME_LEN]; // Galileo qepo working file
+ UINT8 qepo_ga_update_file_name[MTK_GPS_EPO_FILE_NAME_LEN]; //Galileo qepo updated file
+
+#ifdef MTK_GPS_DRIVER_CFG_EXT_SUPPORT
+ /* add some members to make GPS driver cfg more extensible */
+ UINT16 ext_offset;
+ UINT16 ext_size;
+ UINT16 ext_magic;
+ UINT16 ext_ver;
+#endif
+ /* new member should be added bellow here */
+
+ UINT32 EMI_Start_Address;
+ UINT32 EMI_End_Address;
+ UINT8 raw_meas_enable;
+
+ //if it's true,
+ //libmnl restart will call mtk_gps_sys_do_hw_suspend_resume to replace MVCD
+ UINT8 hw_suspend_enabled;
+
+ //if both it and hw_suspend_enabled are true,
+ //libmnl init will call mtk_gps_sys_do_hw_suspend_resume to replace MVCD
+ UINT8 hw_resume_required;
+ MTK_GPS_SV_BLACKLIST blacklist;
+
+ UINT8 mnl_cfg_xml_default_path_name[30]; // MNL_Config.xml path name in default load
+ UINT8 mnl_read_write_path_name[30]; // Path name where MNL can read and write
+ float RfPathLossDb_Ap; // RF path loss
+ float RfPathLossDb_Cp;
+ float RfPathLossDb_Up;
+} MTK_GPS_DRIVER_CFG;
+
+#define FEATURE_NAMING_SIZE 20
+#define MAX_MNL_SETTING_LINE_PER_FEATURE 20
+#define MAX_MNL_SETTING_ARGU_PER_FEATURE 25
+
+typedef struct
+{
+ char xml_feature_name[FEATURE_NAMING_SIZE];
+ double xml_feature_version;
+ char xml_feature_config;
+ unsigned int xml_feature_setting_number;
+ double xml_feature_setting[MAX_MNL_SETTING_LINE_PER_FEATURE][MAX_MNL_SETTING_ARGU_PER_FEATURE];
+
+} MTK_GPS_MNL_CONFIG_XML_PARAM;
+
+
+#ifdef MTK_GPS_DRIVER_CFG_EXT_SUPPORT
+#define MTK_GPS_DRIVER_CFG_EXT_OFFSET \
+ ((UINT16)(long)&(((MTK_GPS_DRIVER_CFG *)0)->ext_size))
+
+#define MTK_GPS_DRIVER_CFG_EXT_SIZE \
+ ((UINT16)(UINT32)sizeof(MTK_GPS_DRIVER_CFG) - MTK_GPS_DRIVER_CFG_EXT_OFFSET)
+
+#define MTK_GPS_DRIVER_CFG_EXT_MAGIC 0xAA55
+
+#define MTK_GPS_DRIVER_CFG_EXT_VER 0x0102 //v0.1.0.2
+#endif /* MTK_GPS_DRIVER_CFG_EXT_SUPPORT */
+
+
+/** GPS measurement support **/
+typedef struct
+{
+ UINT32 size;
+ UINT32 flag;
+ INT8 PRN;
+ double TimeOffsetInNs;
+ UINT16 state;
+ INT64 ReGpsTowInNs; //Re: Received
+ INT64 ReGpsTowUnInNs; //Re: Received, Un:Uncertainty
+ double Cn0InDbHz;
+ double PRRateInMeterPreSec; // PR: Pseuderange
+ double PRRateUnInMeterPreSec; // PR: Pseuderange Un:Uncertainty
+ UINT16 AcDRState10; // Ac:Accumulated, DR:Delta Range
+ double AcDRInMeters; // Ac:Accumulated, DR:Delta Range
+ double AcDRUnInMeters; // Ac:Accumulated, DR:Delta Range, Un:Uncertainty
+ double PRInMeters; // PR: Pseuderange
+ double PRUnInMeters;
+ double CPInChips; // CP: Code Phase
+ double CPUnInChips; // CP: Code Phase
+ float CFInhZ; // CP: Carrier Frequency
+ INT64 CarrierCycle;
+ double CarrierPhase;
+ double CarrierPhaseUn; // Un:Uncertainty
+ UINT8 LossOfLock;
+ INT32 BitNumber;
+ INT16 TimeFromLastBitInMs;
+ double DopperShiftInHz;
+ double DopperShiftUnInHz; // Un:Uncertainty
+ UINT8 MultipathIndicater;
+ double SnrInDb;
+ double ElInDeg; // El: elevation
+ double ElUnInDeg; // El: elevation, Un:Uncertainty
+ double AzInDeg; // Az: Azimuth
+ double AzUnInDeg; // Az: Azimuth
+ char UsedInFix;
+}MTK_GPS_MEASUREMENT;
+
+typedef struct
+{
+ UINT32 size;
+ UINT16 flag;
+ INT16 leapsecond;
+ UINT8 type;
+ INT64 TimeInNs;
+ double TimeUncertaintyInNs;
+ INT64 FullBiasInNs;
+ double BiasInNs;
+ double BiasUncertaintyInNs;
+ double DriftInNsPerSec;
+ double DriftUncertaintyInNsPerSec;
+}MTK_GPS_CLOCK;
+
+typedef struct
+{
+ UINT32 size;
+ INT8 type;
+ UINT8 prn;
+ INT16 messageID;
+ INT16 submessageID;
+ UINT32 length;
+ UINT8 data[40]; // 10 word
+} MTK_GPS_NAVIGATION_EVENT;
+
+typedef struct {
+ UINT32 size;
+ MTK_GnssMeasurementflags flags;
+ INT16 svid;
+ MTK_GnssConstellationtype constellation;
+ double time_offset_ns;
+ UINT32 state;
+ INT64 received_sv_time_in_ns;
+ INT64 received_sv_time_uncertainty_in_ns;
+ double c_n0_dbhz;
+ double pseudorange_rate_mps;
+ double pseudorange_rate_uncertainty_mps;
+ MTK_GnssAccumulatedDeltaRangestate accumulated_delta_range_state;
+ double accumulated_delta_range_m;
+ double accumulated_delta_range_uncertainty_m;
+ float carrier_frequency_hz;
+ INT64 carrier_cycles;
+ double carrier_phase;
+ double carrier_phase_uncertainty;
+ MTK_GnssMultipathindicator multipath_indicator;
+ double snr_db;
+ double fullInterSignalBiasNs;
+ double fullInterSignalBiasUncertaintyNs;
+ double satelliteInterSignalBiasNs;
+ double satelliteInterSignalBiasUncertaintyNs;
+ double basebandCN0DbHz;
+} Gnssmeasurement;
+
+typedef struct {
+ MTK_GnssConstellationtype constellation;
+ double carrierFrequencyHz;
+ UINT8 codeType[8];
+}MTK_GnssSignalType;
+
+
+typedef struct {
+ UINT32 size;
+ MTK_GnssClockflags flags;
+ INT16 leap_second;
+ INT64 time_ns;
+ double time_uncertainty_ns;
+ INT64 full_bias_ns;
+ double bias_ns;
+ double bias_uncertainty_ns;
+ double drift_nsps;
+ double drift_uncertainty_nsps;
+ UINT32 hw_clock_discontinuity_count;
+ MTK_GnssSignalType referenceSignalTypeForIsb;
+} Gnssclock;
+
+typedef struct {
+ UINT32 size;
+ INT16 svid;
+ MTK_GnssNavigationmessageType type;
+ UINT16 status;
+ INT16 message_id;
+ INT16 submessage_id;
+ UINT32 data_length;
+ union
+ {
+ UINT8 GP_data[40];
+ UINT8 GL_data[12];
+ UINT8 BD_data[40];
+ UINT8 GA_data[40];
+ } uData;
+} GnssNavigationmessage;
+
+
+// blue sky
+enum {
+ LOS_SATS = 1 << 0,
+ EXCESS_PATH_LENGTH = 1 << 1,
+ REFLECTING_PLANE = 1 << 2
+};
+typedef UINT32 MeasurementCorrectionCapabilities;
+
+enum {
+ HAS_SAT_IS_LOS_PROBABILITY = 0x0001,
+ HAS_EXCESS_PATH_LENGTH = 0x0002,
+ HAS_EXCESS_PATH_LENGTH_UNC = 0x0004,
+ HAS_REFLECTING_PLANE = 0x0008
+};
+typedef UINT16 GnssSingleSatCorrectionFlags;
+
+typedef struct {
+ double latitudeDegrees;
+ double longitudeDegrees;
+ double altitudeMeters;
+ double azimuthDegrees;
+} ReflectingPlane ;
+
+typedef struct {
+ UINT16 singleSatCorrectionFlags;
+ MTK_GnssConstellationtype constellation;
+ UINT16 svid;
+ float carrierFrequencyHz;
+ float probSatIsLos;
+ float excessPathLengthMeters;
+ float excessPathLengthUncertaintyMeters;
+ ReflectingPlane reflectingPlane;
+}MTK_GPS_PARAM_SAT_CORR; //SingleSatCorrection
+
+typedef struct {
+ double latitudeDegrees;
+ double longitudeDegrees;
+ double altitudeMeters;
+ double horizontalPositionUncertaintyMeters;
+ double verticalPositionUncertaintyMeters;
+ UINT64 toaGpsNanosecondsOfWeek;
+ UINT64 num_satCorrection;
+ MTK_GPS_PARAM_SAT_CORR satCorrections[MTK_GNSS_MAX_SVS];
+ char hasEnvironmentBearing;
+ float environmentBearingDegrees;
+ float environmentBearingUntertaintyDegrees;
+} MTK_GPS_PARAM_MEAS_CORR; //MeasurementCorrections
+
+
+typedef struct
+{
+ double latitude[2]; /* latitude in radius */
+ double longitude[2]; /* longitude in radius */
+ double altitude[2]; /* altitude in meters above the WGS 84 reference ellipsoid */
+ float KF_velocity[3]; /* Kalman Filter velocity in meters per second under (N,E,D) frame */
+ float LS_velocity[3]; /* Least Square velocity in meters per second under (N,E,D) frame */
+ float HACC; /* position horizontal accuracy in meters */
+ float VACC; /* vertical accuracy in meters */
+ float KF_velocitySigma[3]; /* Kalman Filter velocity one sigma error in meter per second under (N,E,D) frame */
+ float velocityInfo[3]; /* Least Square velocity one sigma error in meter per second under (N,E,D) frame */
+ float HDOP; /* horizontal dilution of precision value in unitless */
+ float confidenceIndex[3]; /* GPS confidence index */
+ float GNSS_extra_info[5]; /* GNSS_extra_info */
+ unsigned int leap_sec; /* correct GPS time with phone kernel time */
+ double gps_sec; /* Timestamp of GPS location */
+ INT64 gps_kernel_time;
+ int PR_ResxDOP_index; /*[-1]: ResxDOP is not usable. [ 0~4 ]: index of PR_ResxDOP. The smaller index, the better position accuracy*/
+ float PR_ResxDOP[5]; /*PR_Res stage = |10.0|; HDOP = 1.6 ==> ResxDOP = 16; the smaller the better [0]: default value*/
+ int SVNumofPRStage[5]; /*SV number that meet PR_Res criteria [0]: default value*/
+ float HDOPofDOStage[3]; /*HDOP that meet DO_Res criteria [0]: default value*/
+ int SVNumofDOStage[3]; /*SV number that meet DO_Res criteria. [0]: default value*/
+ int L5_used; /*[0] : L5 not used. [1]: L5 used for positioning*/
+ int DR_mode[3]; /*[0] : MPE normal running [1]: MPE enter DR mode (don't use GNSS reported position)*/
+ int Special_Mode[3]; /**/
+} MNL_location_output_t;
+
+typedef struct
+{
+ double latitude; // latitude in radian
+ double longitude; // longitude in radian
+ double altitude; // altitude in meters above the WGS 84 reference ellipsoid
+ float velocity[3]; // SENSOR velocity in meters per second under (N,E,D) frame
+ float velocityMean[3]; // SENSOR velocity mean in meters per second under (N,E,D) frame
+ float acceleration[3]; // SENSOR acceleration in meters per second^2 under (N,E,D) frame
+ float accelerationMean[3]; // SENSOR acceleration mean in meters per second^2 under (N,E,D) frame
+ float HACC; // position horizontal accuracy in meters
+ float VACC; // vertical accuracy in meters
+ float velocitySigma[3]; // SENSOR velocity one sigma error in meter per second under (N,E,D) frame
+ float accelerationSigma[3]; // SENSOR acceleration one sigma error in meter per second^2 under (N,E,D) frame
+ float roll; // SENSOR roll in radians UNDER (N,E,D) frame
+ float pitch; // SENSOR pitch in radians UNDER (N,E,D) frame
+ float bearing; // SENSOR heading in degrees UNDER (N,E,D) frame
+ float bearingSigma; // SENSOR heading one sigma error in degrees UNDER (N,E,D) frame
+ float confidenceIndex[4]; // SENSOR confidence index
+ float barometerHeight; // barometer height in meter
+ float stepSpeed; // step speed from Pedometer in m/s
+ float stepSpeedSigma; // step speed from Pedometer one sigma error in m/s
+ int valid_flag[4]; // SENSOR AGMB hardware valid flag
+ int mpe_extra_info_int[6]; // mpe_extra_info in integer
+ float mpe_extra_info_float[3]; // mpe_extra_info in float
+ char mpe_udr_version[30]; // UDR version
+ char mpe_pdr_version[30]; // PDR version
+ int staticIndex; // AR status [static, move, uncertain],[0,1,99]
+ unsigned long long timestamp; // Timestamp of SENSOR location
+} MNL_location_input_t;
+
+typedef enum
+{
+ // To MPE
+ CMD_START_MPE_REQ = 0x00, // no payload , request start of MPE
+ CMD_STOP_MPE_REQ, // no payload, request stop of MPE
+ CMD_SET_MPE_MODE, // set MPE operational mode
+ CMD_DEINIT_MPE_REQ, //Request shutdown of MPE
+ CMD_GET_SENSOR_RAW_REQ, // request for raw sensor data
+ CMD_GET_SENSOR_CALIBRATION_REQ, // request for calibrated sensor data
+ CMD_GET_SENSOR_FUSION_REQ, // request for sensor fusion data (Euler angle)
+ CMD_SET_GPS_AIDING_REQ, //Request MPE send fused location (per request, by FLP)
+ CMD_GET_ADR_STATUS_REQ, // Request MPE send AR & heading status (per request, by MNL)
+ CMD_SEND_GPS_TIME_RES, //Send GPS timeto MPE
+
+ // From MPE
+ CMD_START_MPE_RES = 0x20, //no payload, response MPE start status
+ CMD_STOP_MPE_RES, //no payload, response MPE stop status
+ CMD_SEND_SENSOR_RAW_RES, // response MPE sensor raw data
+ CMD_SEND_SENSOR_CALIBRATION_RES, // response MPE calibrated sensor data
+ CMD_SEND_SENSOR_FUSION_RES, // response MPE fused sensor data
+ CMD_SEND_GPS_AIDING_RES, //PDR response fused loc status upon request to FLP
+ CMD_SEND_ADR_STATUS_RES, //ADR response AR & heading status upon request to MNL
+ CMD_SEND_GPS_TIME_REQ, //Request for GPS time for recording & replay purpose
+ CMD_MPE_END = 0x30
+}MPE_CMD;
+
+//location source
+typedef enum
+{
+ MPE_LOC_SOURCE_FLP = 1,
+ MPE_LOC_SOURCE_GNSS = 2,
+ MPE_LOC_SOURCE_OTHER = 4,
+ MPE_LOC_SOURCE_END
+} MPE_LOC_SOURCE;
+
+typedef struct
+{
+ UINT32 type; /* message ID */
+ UINT32 length; /* length of 'data' */
+} MPE_MSG;
+
+typedef int (*MPECallBack)(); /* Callback function register in mnld, for 1sec delay issue*/
+
+// MTK_GPS_INIT_CFG.opmode defines
+#define MTK_INITCFG_OPMODE_2D_FIRSTFIX (1 << 2)
+
+// Task synchronization related type
+typedef enum
+{
+ MTK_MUTEX_BIN_Q = 0,
+ MTK_MUTEX_BIN_Q_L5,
+ MTK_MUTEX_MSG_CNT,
+ MTK_MUTEX_NV_HANDLE,
+ MTK_MUTEX_DEBUG,
+ MTK_MUTEX_MSG_Q,
+ MTK_MUTEX_AGPS_MSG_CNT,
+ MTK_MUTEX_AGPS_MSG_Q,
+ //#ifdef SUPPORT_MULTI_INTERFACE
+ //#endif
+ //MTK_MUTEX_STAGE1,
+ MTK_MUTEX_AARDVARK_I2C_DATA,
+ MTK_MUTEX_AARDVARK_I2C,
+ MTK_MUTEX_AARDVARK_SPI,
+ MTK_MUTEX_FILE,
+ MTK_MUTEX_END
+} MTK_GPS_MUTEX_ENUM;
+
+typedef enum
+{
+ MTK_EVENT_GPS = 0,
+ MTK_EVENT_HS,
+ MTK_EVENT_AGENT,
+ MTK_EVENT_FILE,
+ MTK_EVENT_DSP1_INIT,
+ MTK_EVENT_DSP2_INIT,
+ MTK_EVENT_END
+} MTK_GPS_EVENT_ENUM;
+
+typedef enum
+{
+ GPS_MNL_THREAD_UNKNOWN = -1,
+ GPS_MNL_THREAD_DSP_INPUT = 0,
+ GPS_MNL_THREAD_PMTK_INPUT = 1,
+ GPS_MNL_THREAD_BEE = 2,
+ GPS_MNL_THREAD_MNL = 3,
+ GPS_MNL_THREAD_AGENT = 4,
+ GPS_MNL_THREAD_FILE_CONTROL = 5,
+
+ // flush data in slots to connsys(/dev/stpgps)
+ GPS_MNL_THREAD_MNL_OFL_OUTPUT = 6,
+
+ // fwrite(dbg log) may block too long (>5s) to block offload pkt parser,
+ // then the time of no NMEA will exceed 5s, and libmnl.so will be reset.
+ // create a dedicated thread for offload fwrite to avoid it blocks offload
+ // main thread (GPS_MNL_THREAD_MNL).
+ GPS_MNL_THREAD_MNL_OFL_DEBUG = 7,
+ GPS_MNL_THREAD_DSP_INPUT2 = 8,
+ GPS_MNL_THREAD_DSP_CTRL1 = 9,
+ GPS_MNL_THREAD_DSP_CTRL2 = 10,
+ GPS_MNL_THREAD_NUM = 11
+} MTK_GPS_THREAD_ID_ENUM;
+
+typedef enum
+{
+ MNL_STATUS_DEF = 0,
+ MNL_DSP_UART_INIT_ERR,
+ MNL_NMEA_UART_INIT_ERR,
+ MNL_NMEAIN_UART_INIT_ERR,
+ MNL_GPS_HW_CHECK_ERR,
+ MNL_GPS_MUTEX_INIT_ERR,
+ MNL_GPS_MUTEX_CREATE_ERR,
+ MNL_MNL_THREAD_CREATE_ERR,
+ MNL_MNL_THREAD_ADJUST_ERR,
+ MNL_DSP_THREAD_CREATE_ERR,
+ MNL_DSP_THREAD_ADJUST_ERR,
+ MNL_PMTK_THREAD_CREATE_ERR,
+ MNL_PMTK_THREAD_ADJUST_ERR,
+ MNL_PMTK_APP_THREAD_CREATE_ERR,
+ MNL_BEE_THREAD_CREATE_ERR,
+ MNL_AGT_THREAD_CREATE_ERR,
+ MNL_FILE_CONTROL_THREAD_CREATE_ERR,
+ MNL_DSP_BOOT_ERR,
+ MNL_INIT_SUCCESS = 18,
+ MNL_OFFLOAD_INIT_ERR = 19,
+ MNL_DSP2_UART_INIT_ERR,
+ MNL_DSP2_THREAD_CREATE_ERR,
+ MNL_DSP2_THREAD_ADJUST_ERR,
+ MNL_DSP2_BOOT_ERR = 23
+} MTK_GPS_BOOT_STATUS;
+
+typedef enum
+{
+ HS_DEFAULT_STATUS,
+ HS_INIT_ERR,
+ HS_RUN_SUCCESS
+}mtk_gps_hotstill_status;
+
+typedef enum
+{
+ /*MT6620*/
+ MT6620_E1 = 0,
+ MT6620_E2,
+ MT6620_E3,
+ MT6620_E4,
+ MT6620_EN, // MUST smaller than 0x10
+ /*MT6628*/
+ MT6628_E1 = 0 + (0x10),
+ MT6628_E2,
+ MT6628_EN, // MUST smaller then 0x20
+ /*MT3332*/
+ MT3332_E1 = 0 + (0x20),
+ MT3332_E2,
+ MT3332_EN, // MUST smaller then 0x30
+ /*MT3336*/
+ MT3336_E1 = 0 + (0x30),
+ MT3336_E2,
+ MT3336_EN,
+ MT6572_E1 = 0 + (0x40),
+ MT6572_EN,
+ MT6582_E1 = 0 + (0x50),
+ MT6582_EN ,
+ MT6592_E1 = 0 + (0x60),
+ MT6592_EN ,
+ MT6571_E1 = 0 + (0x70),
+ MT6571_EN,
+ MT6630_E1 = 0 + (0x80),
+ MT6630_E2,
+ MT6630_EN,
+ MT6752_E1 = 0 + (0x90),
+ MT6752_EN,
+ MT6735_E1 = 0 + (0xA0),
+ MT6735_EN,
+ MT6735M_E1 = 0 + (0xB0),
+ MT6735M_EN,
+ MT6753_E1 = 0 + (0xC0),
+ MT6753_EN,
+ MT6580_E1 = 0 + (0xD0),
+ MT6580_EN,
+ MT6755_E1 = 0 + (0xE0),
+ MT6755_EN,
+ MT6797_E1 = 0 + (0xF0),
+ MT6797_EN,
+ MT6632_E1 = 0 + (0x100),
+ MT6632_E3,
+ MT6632_EN,
+ MT6757_E1 = 0 + (0x110),
+ MT6757_EN,
+ MT6570_E1 = 0 + (0x120),
+ MT6570_EN,
+ MT6759_E1 = 0 + (0x130),
+ MT6759_EN,
+ MT6763_E1 = 0 + (0x140),
+ MT6763_EN,
+ MT6758_E1 = 0 + (0x150),
+ MT6758_EN,
+ MT6739_E1 = 0 + (0x160),
+ MT6739_EN,
+ MT6771_E1 = 0 + (0x170),
+ MT6771_EN,
+ MT6775_E1 = 0 + (0x180),
+ MT6775_EN,
+ MT6765_E1 = 0 + (0x190),
+ MT6765_EN,
+ MT3967_E1 = 0 + (0x1A0),
+ MT3967_EN,
+ MT6761_E1 = 0 + (0x1B0),
+ MT6761_EN,
+ MT6779_E1 = 0 + (0x1C0),
+ MT6779_EN,
+ MT6768_E1 = 0 + (0x1D0),
+ MT6768_EN,
+ MT8168_E1 = 0 + (0x1E0),
+ MT8168_EN,
+ MT6785_E1 = 0 + (0x1F0),
+ MT6785_EN,
+ MT6885_E1 = 0 + (0x200),
+ MT6885_EN,
+ MT6873_E1 = 0 + (0x210),
+ MT6873_EN,
+ MT6853_E1 = 0 + (0x220),
+ MT6853_EN,
+ MT6880_E1 = 0 + (0x230),
+ MT6880_EN,
+ MT6890_E1 = 0 + (0x240),
+ MT6890_EN,
+ MT6893_E1 = 0 + (0x250),
+ MT6893_EN,
+ MT6833_E1 = 0 + (0x260),
+ MT6833_EN
+}eMTK_GPS_CHIP_TYPE;
+
+//#define MTK_GPS_THIP_KEY (0xFFFF6620) //
+#define MTK_GPS_CHIP_KEY_MT6620 (0xFFFF6620)
+#define MTK_GPS_CHIP_KEY_MT6628 (0xFFFF6628)
+#define MTK_GPS_CHIP_KEY_MT3332 (0xFFFF3332)
+#define MTK_GPS_CHIP_KEY_MT3336 (0xFFFF3336)
+#define MTK_GPS_CHIP_KEY_MT6572 (0xFFFF6572)
+#define MTK_GPS_CHIP_KEY_MT6582 (0xFFFF6582)
+#define MTK_GPS_CHIP_KEY_MT6592 (0xFFFF6592)
+#define MTK_GPS_CHIP_KEY_MT6571 (0xFFFF6571)
+#define MTK_GPS_CHIP_KEY_MT6630 (0xFFFF6630)
+#define MTK_GPS_CHIP_KEY_MT6752 (0xFFFF6752)
+#define MTK_GPS_CHIP_KEY_MT6735 (0xFFFF6735)
+#define MTK_GPS_CHIP_KEY_MT6735M (0xFFFE6735)
+#define MTK_GPS_CHIP_KEY_MT6739 (0xFFFF6739)
+#define MTK_GPS_CHIP_KEY_MT6753 (0xFFFF6753)
+#define MTK_GPS_CHIP_KEY_MT6763 (0xFFFF6763)
+#define MTK_GPS_CHIP_KEY_MT6580 (0xFFFF6580)
+#define MTK_GPS_CHIP_KEY_MT6570 (0xFFFF6570)
+#define MTK_GPS_CHIP_KEY_MT6755 (0xFFFF6755)
+#define MTK_GPS_CHIP_KEY_MT6797 (0xFFFF6797)
+#define MTK_GPS_CHIP_KEY_MT6759 (0xFFFF6759)
+#define MTK_GPS_CHIP_KEY_MT6632 (0xFFFF6632)
+#define MTK_GPS_CHIP_KEY_MT6757 (0xFFFF6757)
+#define MTK_GPS_CHIP_KEY_MT6758 (0xFFFF6758)
+#define MTK_GPS_CHIP_KEY_MT6771 (0xFFFF6771)
+#define MTK_GPS_CHIP_KEY_MT6775 (0xFFFF6775)
+#define MTK_GPS_CHIP_KEY_MT6765 (0xFFFF6765)
+#define MTK_GPS_CHIP_KEY_MT3967 (0xFFFF3967)
+#define MTK_GPS_CHIP_KEY_MT6761 (0xFFFF6761)
+#define MTK_GPS_CHIP_KEY_MT6779 (0xFFFF6779)
+#define MTK_GPS_CHIP_KEY_MT6768 (0xFFFF6768)
+#define MTK_GPS_CHIP_KEY_MT8168 (0xFFFF8168)
+#define MTK_GPS_CHIP_KEY_MT6785 (0xFFFF6785)
+#define MTK_GPS_CHIP_KEY_MT6833 (0xFFFF6833)
+#define MTK_GPS_CHIP_KEY_MT6853 (0xFFFF6853)
+#define MTK_GPS_CHIP_KEY_MT6873 (0xFFFF6873)
+#define MTK_GPS_CHIP_KEY_MT6885 (0xFFFF6885)
+#define MTK_GPS_CHIP_KEY_MT6880 (0xFFFF6880)
+#define MTK_GPS_CHIP_KEY_MT6890 (0xFFFF6890)
+#define MTK_GPS_CHIP_KEY_MT6893 (0xFFFF6893)
+
+/* Return value for most APIs */
+#define MTK_GPS_SUCCESS (0)
+#define MTK_GPS_ERROR (-1)
+#define MTK_GPS_ERROR_NMEA_INCOMPLETE (-2)
+#define MTK_GPS_ERROR_TIME_CHANGED (1)
+#define MTK_GPS_NO_MSG_RECEIVED (1)
+
+
+#define MTK_GPS_DELETE_EPHEMERIS 0x0001
+#define MTK_GPS_DELETE_ALMANAC 0x0002
+#define MTK_GPS_DELETE_POSITION 0x0004
+#define MTK_GPS_DELETE_TIME 0x0008
+#define MTK_GPS_DELETE_IONO 0x0010
+#define MTK_GPS_DELETE_UTC 0x0020
+#define MTK_GPS_DELETE_HEALTH 0x0040
+#define MTK_GPS_DELETE_SVDIR 0x0080
+#define MTK_GPS_DELETE_SVSTEER 0x0100
+#define MTK_GPS_DELETE_SADATA 0x0200
+#define MTK_GPS_DELETE_RTI 0x0400
+#define MTK_GPS_DELETE_CLK 0x0800
+#define MTK_GPS_DELETE_CELLDB_INFO 0x8000
+#define MTK_GPS_DELETE_ALL 0xFFFF
+
+
+//start for AGPS_SUPPORT_GNSS
+#define GNSS_MAX_REF_TIME_SAT_ELEMENT 16 /* 64 for LPP, 16 for RRC, 12 for RRLP. Use 16 to reduce structure size */
+#define GNSS_MAX_REF_CELL_FTA_ELEMENT 16 /* 16 for LPP, 1 for RRC/RRLP */
+
+#define GNSS_MAX_GNSS_GENERIC_ASSIST_DATA_ELEMENT 16 /* 16 for LPP, 8 for RRC/RRLP in provide assistance data;
+ 16 for LPP/RRLP, 8 for RRC in capability */
+
+/* GNSS Time Model */
+#define GNSS_MAX_TIME_MODEL_ELEMENT 4 /* 15 for LPP, 7 for RRC/RRLP, Use 4 since gnss-TO-ID only 4 (GPS, Galileo, QZSS, GLONASS) */
+
+/* GNSS DGNSS */
+#define GNSS_MAX_DGNSS_SGN_TYPE_ELEMENT 3 /* 3 for LPP/RRLP, 8 for RRC */
+#define GNSS_MAX_DGNSS_CORRECTION_INFO_ELEMENT 16 /* 64 for LPP/RRC, 16 for RRLP. Use 16 to reduce structure size */
+
+/* GNSS Navigation Model */
+#define GNSS_MAX_NAV_SAT_ELEMENT 16 /* 64 for LPP/RRC, 32 for RRLP. Use 16 to reduce structure size */
+#define GNSS_MAX_NAV_SAT_ELEMENT_BIT_POS 64 /* 64 for LPP/RRC, 32 for RRLP, dedicated for assist data req */
+#define GNSS_MAX_NAV_STD_CLK_MODEL_ELEMENT 4 /* 2 for LPP/RRLP, 4 for RRC */
+#define GNSS_MAX_NAV_CLOCK_MODEL_ELEMENT 5 /* currently there is 5 clock models */
+#define GNSS_MAX_NAV_ORBIT_MODEL_ELEMENT 5 /* currently there is 5 orbit models */
+
+/* GNSS Real Time Integrity */
+#define GNSS_MAX_RTI_BAD_SAT_ELEMENT 16 /* 64 for LPP/RRC, 16 for RRLP. Use 16 to reduce structure size */
+
+/* GNSS Data Bit Assistance */
+#define GNSS_MAX_DBA_SGN_TYPE_ELEMENT 8 /* 8 for LPP/RRC/RRLP */
+#define GNSS_MAX_DBA_SAT_ELEMENT 16 /* 64 for LPP/RRC, 32 for RRLP. Use 16 to reduce structure size */
+#define GNSS_MAX_DBA_BIT_LENGTH 64 /* 1024 bit for LPP/RRC/RRLP, but RRLP use integer intead of bit. Process only max 64 bits to reduce structure size */
+
+/* GNSS Acquisition Assitance */
+#define GNSS_MAX_ACQ_ASSIST_SAT_ELEMENT 16 /* 64 for LPP/RRC, 16 for RRLP. Use 16 to reduce structure size */
+
+/* GNSS Almanac */
+#define GNSS_MAX_ALMANAC_SAT_ELEMENT 32 /* 64 for LPP/RRC, 36 for RRLP. Use 32 to reduce structure size */
+
+/* GNSS Auxiliary Information */
+#define GNSS_MAX_AUX_SAT_ELEMENT 16 /* 64 for LPP/RRC/RRLP. Use 16 to reduce structure size */
+
+/* GNSS Measurement Info */
+#define GNSS_MAX_MEASURED_GNSS_ELEMENT GNSS_MAX_SUPPORT_NUM /* 16 for LPP, 8 for RRC/RRLP, Use GNSS_MAX_SUPPORT_NUM (4) to reduce structure size */
+#define GNSS_MAX_MEASURED_SGN_PER_GNSS_ELEMENT 4 /* 8 for LPP/RRC/RRLP, Use 4 to reduce structure size */
+#define GNSS_MAX_MEASURED_SAT_PER_SGN_ELEMENT 16 /* 64 for LPP/RRC, 16 for RRLP. Use 16 to reduce structure size */
+
+/* GNSS Request Additional Generic Assist Data */
+#define GNSS_MAX_REQ_ADD_GENERIC_ASSIST_DATA_ELEMENT GNSS_MAX_SUPPORT_NUM /* 16 for LPP, 8 for RRC, unspecified for RRLP (up to 40 bytes), Use 9 since number of generic assistance data type is only 9 */
+
+
+/* GNSS ID Bitmap, use one-byte representation */
+#define GNSS_ID_BITMAP_NONE 0x00
+#define GNSS_ID_BITMAP_GPS 0x8000 /* gps (0) */
+#define GNSS_ID_BITMAP_SBAS 0x4000 /* sbas (1) */
+#define GNSS_ID_BITMAP_QZSS 0x2000 /* qzss (2) */
+#define GNSS_ID_BITMAP_GALILEO 0x1000 /* galileo (3) */
+#define GNSS_ID_BITMAP_GLONASS 0x0800 /* glonass (4) */
+#define GNSS_ID_BITMAP_BEIDOU 0x0400 /* beidou (5) */
+
+
+#define GNSS_ID_BITMAP_GPS_GLONASS (GNSS_ID_BITMAP_GPS | GNSS_ID_BITMAP_GLONASS)
+#define GNSS_ID_BITMAP_GPS_BEIDOU (GNSS_ID_BITMAP_GPS | GNSS_ID_BITMAP_BEIDOU )
+
+/* TBD: check with WCN, MT6630 support GPS+QZSS+GLONASS+Galileo+Beidou */
+#define GNSS_MAX_SUPPORT_NUM 0x02 /* A-GPS + A-GLONASS */
+
+/* SBAS ID Bitmap, use one-byte representation */
+#define SBAS_ID_BITMAP_NONE 0x00
+#define SBAS_ID_BITMAP_WASS 0x80 /* waas (0) */
+#define SBAS_ID_BITMAP_EGNOS 0x40 /* egnos (1) */
+#define SBAS_ID_BITMAP_MSAS 0x20 /* msas (2) */
+#define SBAS_ID_BITMAP_GAGAN 0x10 /* gagan (3) */
+
+/* GNSS Signal IDs Bitmap, use one-byte representation
+ * GNSS | Bit 1 | Bit 2 | Bit 3 | Bit 4 | Bit 5 | Bit 6 | Bit 7 | Bit 8 |
+ * --------+--------+-------+-------+-------+-------+-------+-------+-------+
+ * GPS | L1 C/A | L1C | L2C | L5 | -- reserved --|-------|-------|
+ * SBAS | L1 | -- reserved --|-------|-------|-------|-------|-------|
+ * QZSS | QZS-L1 |QZS-L1C|QZS-L2C| QZS-L5| -- reserved --|-------|-------|
+ * GLONASS | G1 | G2 | G3 | -- reserved --|-------|-------|-------|
+ * Galileo | E1 | E5a | E5b | E6 |E5a+E5b| -- reserved --|-------|
+*/
+/* TBD: need confirmation GNSS signal spectrum from WCN */
+#define GNSS_SGN_ID_BITMAP_GPS_L1C_A 0x80 /* bit 1 */
+#define GNSS_SGN_ID_BITMAP_GPS_L1C 0x40 /* bit 2 */
+#define GNSS_SGN_ID_BITMAP_GPS_L2C 0x20 /* bit 3 */
+#define GNSS_SGN_ID_BITMAP_GPS_L5 0x10 /* bit 4 */
+
+#define GNSS_SGN_ID_BITMAP_SBAS_L1 0x80 /* bit 1 */
+
+#define GNSS_SGN_ID_BITMAP_QZSS_L1C_A 0x80 /* bit 1 */
+#define GNSS_SGN_ID_BITMAP_QZSS_L1C 0x40 /* bit 2 */
+#define GNSS_SGN_ID_BITMAP_QZSS_L2C 0x20 /* bit 3 */
+#define GNSS_SGN_ID_BITMAP_QZSS_L5 0x10 /* bit 4 */
+
+#define GNSS_SGN_ID_BITMAP_GLONASS_G1 0x80 /* bit 1 */
+#define GNSS_SGN_ID_BITMAP_GLONASS_G2 0x40 /* bit 2 */
+#define GNSS_SGN_ID_BITMAP_GLONASS_G3 0x20 /* bit 3 */
+
+#define GNSS_SGN_ID_BITMAP_GALILEO_E1 0x80 /* bit 1 */
+#define GNSS_SGN_ID_BITMAP_GALILEO_E5A 0x40 /* bit 2 */
+#define GNSS_SGN_ID_BITMAP_GALILEO_E5B 0x20 /* bit 3 */
+#define GNSS_SGN_ID_BITMAP_GALILEO_E6 0x10 /* bit 4 */
+#define GNSS_SGN_ID_BITMAP_GALILEO_E5_A_B 0x08 /* bit 5 */
+
+#define GNSS_SGN_ID_BITMAP_BDS_B1I 0x80 /* bit 1 */
+
+/* GNSS Signal ID value */
+#define GNSS_SGN_ID_VALUE_GPS_L1C_A 0
+#define GNSS_SGN_ID_VALUE_GPS_L1C 1
+#define GNSS_SGN_ID_VALUE_GPS_L2C 2
+#define GNSS_SGN_ID_VALUE_GPS_L5 3
+
+#define GNSS_SGN_ID_VALUE_SBAS_L1 0
+
+#define GNSS_SGN_ID_VALUE_QZSS_L1C_A 0
+#define GNSS_SGN_ID_VALUE_QZSS_L1C 1
+#define GNSS_SGN_ID_VALUE_QZSS_L2C 2
+#define GNSS_SGN_ID_VALUE_QZSS_L5 3
+
+#define GNSS_SGN_ID_VALUE_GLONASS_G1 0
+#define GNSS_SGN_ID_VALUE_GLONASS_G2 1
+#define GNSS_SGN_ID_VALUE_GLONASS_G3 2
+
+#define GNSS_SGN_ID_VALUE_GALILEO_E1 0
+#define GNSS_SGN_ID_VALUE_GALILEO_E5A 1
+#define GNSS_SGN_ID_VALUE_GALILEO_E5B 2
+#define GNSS_SGN_ID_VALUE_GALILEO_E6 3
+#define GNSS_SGN_ID_VALUE_GALILEO_E5_A_B 4
+
+#define GNSS_SGN_ID_VALUE_BEIDOU_B1I 0
+#define GNSS_SGN_ID_VALUE_BEIDOU_B2I 1
+
+#define GNSS_SGN_ID_VALUE_MAX 7
+
+/* GNSS Clock and Orbit Model Value (for Navigation Model) */
+#define GNSS_NAV_CLOCK_MODEL_1_VALUE_STANDARD 1 /* model-1 */
+#define GNSS_NAV_CLOCK_MODEL_2_VALUE_NAV 2 /* model-2 */
+#define GNSS_NAV_CLOCK_MODEL_3_VALUE_CNAV 3 /* model-3 */
+#define GNSS_NAV_CLOCK_MODEL_4_VALUE_GLONASS 4 /* model-4 */
+#define GNSS_NAV_CLOCK_MODEL_5_VALUE_SBAS 5 /* model-5 */
+
+#define GNSS_NAV_ORBIT_MODEL_1_VALUE_KEPLERIAN_SET 1 /* model-1 */
+#define GNSS_NAV_ORBIT_MODEL_2_VALUE_NAV_KEPLERIAN_SET 2 /* model-2 */
+#define GNSS_NAV_ORBIT_MODEL_3_VALUE_CNAV_KEPLERIAN_SET 3 /* model-3 */
+#define GNSS_NAV_ORBIT_MODEL_4_VALUE_GLONASS_ECEF 4 /* model-4 */
+#define GNSS_NAV_ORBIT_MODEL_5_VALUE_SBAS_ECEF 5 /* model-5 */
+
+/* Almanac Model Value */
+#define GNSS_ALMANAC_MODEL_1_VALUE_KEPLERIAN_SET 1 /* model-1 */
+#define GNSS_ALMANAC_MODEL_2_VALUE_NAV_KEPLERIAN_SET 2 /* model-2 */
+#define GNSS_ALMANAC_MODEL_3_VALUE_REDUCED_KEPLERIAN_SET 3 /* model-3 */
+#define GNSS_ALMANAC_MODEL_4_VALUE_MIDI_KEPLERIAN_SET 4 /* model-4 */
+#define GNSS_ALMANAC_MODEL_5_VALUE_GLONASS_SET 5 /* model-5 */
+#define GNSS_ALMANAC_MODEL_6_VALUE_ECEF_SBAS_SET 6 /* model-6 */
+
+/* UTC Model Value */
+#define GNSS_UTC_MODEL_1_VALUE 1 /* model-1 (0) */
+#define GNSS_UTC_MODEL_2_VALUE 2 /* model-2 (1) */
+#define GNSS_UTC_MODEL_3_VALUE 3 /* model-3 (2) */
+#define GNSS_UTC_MODEL_4_VALUE 4 /* model-4 (3) */
+/* Ionoshoeruc Model */
+#define GNSS_ION_MODEL_KLOBUCHAR 0x80 /* klobuchar (0) */
+#define GNSS_ION_MODEL_NEQUICK 0x40 /* neQuick (1) */
+
+
+/* Navigation Model */
+#define GNSS_NAV_CLOCK_MODEL_1_STANDARD 0x80 /* model-1 (0) */
+#define GNSS_NAV_CLOCK_MODEL_2_NAV 0x40 /* model-2 (1) */
+#define GNSS_NAV_CLOCK_MODEL_3_CNAV 0x20 /* model-3 (2) */
+#define GNSS_NAV_CLOCK_MODEL_4_GLONASS 0x10 /* model-4 (3) */
+#define GNSS_NAV_CLOCK_MODEL_5_SBAS 0x08 /* model-5 (4) */
+
+#define GNSS_NAV_ORBIT_MODEL_1_KEPLERIAN_SET 0x80 /* model-1 (0) */
+#define GNSS_NAV_ORBIT_MODEL_2_NAV_KEPLERIAN_SET 0x40 /* model-2 (1) */
+#define GNSS_NAV_ORBIT_MODEL_3_CNAV_KEPLERIAN_SET 0x20 /* model-3 (2) */
+#define GNSS_NAV_ORBIT_MODEL_4_GLONASS_ECEF 0x10 /* model-4 (3) */
+#define GNSS_NAV_ORBIT_MODEL_5_SBAS_ECEF 0x08 /* model-5 (4) */
+
+
+/* Almanac */
+#define GNSS_ALMANAC_MODEL_1_KEPLERIAN_SET 0x80 /* model-1 (0) */
+#define GNSS_ALMANAC_MODEL_2_NAV_KEPLERIAN_SET 0x40 /* model-2 (1) */
+#define GNSS_ALMANAC_MODEL_3_REDUCED_KEPLERIAN_SET 0x20 /* model-3 (2) */
+#define GNSS_ALMANAC_MODEL_4_MIDI_KEPLERIAN_SET 0x10 /* model-4 (3) */
+#define GNSS_ALMANAC_MODEL_5_GLONASS_SET 0x08 /* model-5 (4) */
+#define GNSS_ALMANAC_MODEL_6_ECEF_SBAS_SET 0x04 /* model-6 (5) */
+
+
+/* UTC Model*/
+#define GNSS_UTC_MODEL_1 0x80 /* model-1 (0) */
+#define GNSS_UTC_MODEL_2 0x40 /* model-2 (1) */
+#define GNSS_UTC_MODEL_3 0x20 /* model-3 (2) */
+#define GNSS_UTC_MODEL_4 0x10 /* model-4 (3) */
+
+/*GNSS Signal Bitmap for PMTK710/711*/
+#define GNSS_SIGNAL_GPS_L1CA (0)
+#define GNSS_SIGNAL_GPS_L1C (1<<0)
+#define GNSS_SIGNAL_GPS_L2C (1<<1)
+#define GNSS_SIGNAL_GPS_L5 (1<<2)
+
+/* NNUM ********************************************************************/
+typedef enum
+{
+ PMTK_CMD_VER_0 = 0, //conversional GPS
+ PMTK_CMD_VER_1 = 1, //GNSS
+ PMTK_CMD_VER_2 = 2, //dual Fre for L5
+ PMTK_CMD_VER_END
+} MTK_GNSS_CMD_VER_ENUM;
+typedef enum
+{
+ C2K_AGPS_DISABLE = 0, // Disable C2K AGPS
+ C2K_AGPS_ENABLE = 1, // Enable C2K AGPS
+ C2K_AGPS_End
+} MTK_C2K_AGPS_ENUM;
+typedef enum
+{
+ MTK_GPS_KLB_WILD_USE = 0, //KLB model only for QZSS
+ MTK_GPS_KLB_QZSS_ONLY = 3, //KLB model only for QZSS
+ MTK_GPS_KLB_TYPE_END
+} MTK_GPS_KLB_DATAID_ENUM;
+
+typedef enum
+{
+ GNSS_NETWORK_CELL_NULL = 0,
+ GNSS_NETWORK_CELL_EUTRA = 1,
+ GNSS_NETWORK_CELL_UTRA = 2,
+ GNSS_NETWORK_CELL_GSM = 3,
+ GNSS_NETWORK_CELL_END
+} MTK_GNSS_NETWORK_CELL_ENUM;
+
+
+typedef enum
+{
+ GNSS_ID_GPS = 0,
+ GNSS_ID_SBAS = 1,
+ GNSS_ID_QZSS = 2,
+ GNSS_ID_GALILEO = 3,
+ GNSS_ID_GLONASS = 4,
+ GNSS_ID_BEIDOU = 5,
+ GNSS_ID_GPS_L5 = 6,
+ GNSS_ID_MAX_NUM
+} MTK_GNSS_ID_ENUM;
+
+
+typedef enum
+{
+ GNSS_TO_ID_GPS = 1,
+ GNSS_TO_ID_GALILEO ,
+ GNSS_TO_ID_QZSS ,
+ GNSS_TO_ID_GLONASS ,
+ GNSS_TO_ID_BEIDOU ,
+ GNSS_TO_ID_END
+} MTK_GNSS_TO_ID_ENUM;
+
+
+typedef enum
+{
+ SBAS_ID_WAAS = 0,
+ SBAS_ID_EGNOS = 1,
+ SBAS_ID_MSAS = 2,
+ SBAS_ID_GAGAN = 3,
+ SBAS_ID_BEIDOU = 4,
+ SBAS_ID_END
+} MTK_SBAS_ID_ENUM;
+
+
+typedef enum
+{
+ GNSS_COMMON_ASSIST_TIM = 0,
+ GNSS_COMMON_ASSIST_LOC = 1,
+ GNSS_COMMON_ASSIST_ION = 2,
+ GNSS_COMMON_ASSIST_EOP = 3,
+
+} MTK_GNSS_COMMON_ASSIST_ENUM;
+
+
+typedef enum
+{
+ GNSS_GENERIC_ASSIST_TMD = 0,
+ GNSS_GENERIC_ASSIST_DGNSS = 1,
+ GNSS_GENERIC_ASSIST_EPH = 2,
+ GNSS_GENERIC_ASSIST_RTI = 3,
+ GNSS_GENERIC_ASSIST_DBA = 4,
+ GNSS_GENERIC_ASSIST_ACQ = 5,
+ GNSS_GENERIC_ASSIST_ALM = 6,
+ GNSS_GENERIC_ASSIST_UTC = 7,
+ GNSS_GENERIC_ASSIST_AUX = 8,
+ GNSS_GENERIC_ASSIST_END = 9,
+} MTK_GNSS_GENERIC_ASSIST_ENUM;
+
+
+typedef enum
+{
+ GNSS_CLOCK_MODEL_TYPE_STANDARD,
+ GNSS_CLOCK_MODEL_TYPE_NAV,
+ GNSS_CLOCK_MODEL_TYPE_CNAV,
+ GNSS_CLOCK_MODEL_TYPE_GLONASS,
+ GNSS_CLOCK_MODEL_TYPE_SBAS
+} gnss_clock_model_type_enum;
+
+
+typedef enum
+{
+ GNSS_ORBIT_MODEL_TYPE_KEPLERIAN_SET,
+ GNSS_ORBIT_MODEL_TYPE_NAV_KEPLERIAN_SET,
+ GNSS_ORBIT_MODEL_TYPE_CNAV_KEPLERIAN_SET,
+ GNSS_ORBIT_MODEL_TYPE_GLONASS_ECEF,
+ GNSS_ORBIT_MODEL_TYPE_SBAS_ECEF
+} gnss_orbit_model_type_enum;
+
+
+typedef enum
+{
+ GNSS_ACQ_ASSIST_DOPPLER_UNCERTAINTY_EXT_ENUM_D60,
+ GNSS_ACQ_ASSIST_DOPPLER_UNCERTAINTY_EXT_ENUM_D80,
+ GNSS_ACQ_ASSIST_DOPPLER_UNCERTAINTY_EXT_ENUM_D100,
+ GNSS_ACQ_ASSIST_DOPPLER_UNCERTAINTY_EXT_ENUM_D120,
+ GNSS_ACQ_ASSIST_DOPPLER_UNCERTAINTY_EXT_ENUM_NO_INFO
+} MTK_GNSS_ACQ_DOPP_UNCERT_EXT_ENUM;
+
+
+typedef enum
+{
+ GNSS_ALMANAC_TYPE_KEPLERIAN_SET,
+ GNSS_ALMANAC_TYPE_NAV_KEPLERIAN_SET,
+ GNSS_ALMANAC_TYPE_REDUCED_KEPLERIAN_SET,
+ GNSS_ALMANAC_TYPE_MIDI_KEPLERIAN_SET,
+ GNSS_ALMANAC_TYPE_GLONASS_SET,
+ GNSS_ALMANAC_TYPE_ECEF_SBAS_SET,
+} gnss_almanac_type_enum;
+
+
+typedef enum
+{
+ UTC_MODEL_GPS,
+ UTC_MODEL_QZSS,
+ UTC_MODEL_GLO,
+ UTC_MODEL_SBAS,
+ UTC_MODEL_BEIDOU,
+ UTC_MODEL_GALILEO,
+ UTC_MODEL_UNKNOWN,
+} MTK_GNSS_UTC_TYPE_ENUM;
+
+typedef enum
+{
+ GNSS_AUX_TYPE_GPS,
+ GNSS_AUX_TYPE_GLONASS
+} MTK_GNSS_AUX_TYPE_ENUM;
+
+typedef enum
+{
+ MTK_QEPO_RSP_UPDATE_SUCCESS = 0,
+ MTK_QEPO_RSP_UPDATE_FAIL,
+ MTK_QEPO_RSP_DOWNLOAD_FAIL,
+ MTK_QEPO_RSP_NETWORK_CONNECT_FAIL,
+ MTK_QEPO_RSP_SIZE_FAIL,
+ MTK_QEPO_RSP_TIMEOUT
+}MTK_QEPO_RSP;
+
+typedef enum
+{
+ MTK_MTKNAV_RSP_UPDATE_SUCCESS = 0,
+ MTK_MTKNAV_RSP_UPDATE_FAIL,
+ MTK_MTKNAV_RSP_DOWNLOAD_FAIL,
+ MTK_MTKNAV_RSP_NETWORK_CONNECT_FAIL,
+ MTK_MTKNAV_RSP_SIZE_FAIL,
+ MTK_MTKNAV_RSP_NO_UPDATE,
+ MTK_MTKNAV_RSP_TIMEOUT
+}MTK_MTKNAV_RSP;
+
+typedef enum {
+ //PAYLOAD = 12byte:
+ //uint32, whether 1st run
+ //uint32, heart_beat cnt, start at 0
+ //uint32, max micro-secends to next heartbeat
+ MTK_GPS_OFL_CB_HEART_BEAT = 0,
+
+ MTK_GPS_OFL_CB_CNT
+} MTK_GPS_OFL_CB_TYPE;
+
+//end for AGPS_SUPPORT_GNSS
+#if ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 200000 ))
+// for ADS1.x
+#elif ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400000 ) )
+// for RVCT2.x or RVCT3.x
+#else
+#pragma pack()
+#endif
+/*gnss2lcsp_enum*/
+
+/* MACROS *******************************************************************/
+
+/**
+ * among LPP/RRC/RRLP, the max number of elements for GNSS data is different in some data fields.
+ * we take the largest value as element definition for common interface
+ */
+#define LPPE_IONOSPHERIC_STATIC_MODEL_VALID (0x1<<0)
+#define LPPE_IONOSPHERIC_PERIODIC_MODEL_VALID (0x1<<1)
+#define LPPE_TROPOSPHERE_MODEL_VALID (0x1<<2)
+#define LPPE_ALTITUDE_ASSIST_VALID (0x1<<3)
+#define LPPE_SOLAR_RADIATION_VALID (0x1<<4)
+#define LPPE_ASSIST_COMMON_CCP_COM_PARA_VALID (0x1<<5)
+#define LPPE_ASSIST_COMMON_CCP_CTR_PARA_VALID (0x1<<6)
+#define LPPE_ASSIST_GENERIC_CCP_VALID (0x1<<7)
+#define LPPE_ASSIST_GENERIC_DM_VALID (0x1<<8)
+
+/* GNSS measurement fields validity bitmask */
+#define GNSS_MEAS_INFO_CARRIER_QUALITY_VALIDITY 0x01
+#define GNSS_MEAS_INFO_INT_CODE_PHASE_VALIDITY 0x02
+#define GNSS_MEAS_INFO_DOPPLER_VALIDITY 0x04
+#define GNSS_MEAS_INFO_ADR_VALIDITY 0x08
+#define GNSS_MEAS_INFO_ALL_VALIDITY 0x0F
+
+#define CHECK_GNSS_MEAS_INFO_CARRIER_QUALITY_VALIDITY(validity) ((validity & GNSS_MEAS_INFO_ALL_VALIDITY) & GNSS_MEAS_INFO_CARRIER_QUALITY_VALIDITY) ? KAL_TRUE : KAL_FALSE
+#define SET_GNSS_MEAS_INFO_CARRIER_QUALITY_VALIDITY(validity) (validity |= GNSS_MEAS_INFO_CARRIER_QUALITY_VALIDITY)
+
+#define CHECK_GNSS_MEAS_INFO_INT_CODE_PHASE_VALIDITY(validity) ((validity & GNSS_MEAS_INFO_ALL_VALIDITY) & GNSS_MEAS_INFO_INT_CODE_PHASE_VALIDITY) ? KAL_TRUE : KAL_FALSE
+#define SET_GNSS_MEAS_INFO_INT_CODE_PHASE_VALIDITY(validity) (validity |= GNSS_MEAS_INFO_INT_CODE_PHASE_VALIDITY)
+
+#define CHECK_GNSS_MEAS_INFO_DOPPLER_VALIDITY(validity) ((validity & GNSS_MEAS_INFO_ALL_VALIDITY) & GNSS_MEAS_INFO_DOPPLER_VALIDITY) ? KAL_TRUE : KAL_FALSE
+#define SET_GNSS_MEAS_INFO_DOPPLER_VALIDITY(validity) (validity |= GNSS_MEAS_INFO_DOPPLER_VALIDITY)
+
+#define CHECK_GNSS_MEAS_INFO_ADR_VALIDITY(validity) ((validity & GNSS_MEAS_INFO_ALL_VALIDITY) & GNSS_MEAS_INFO_ADR_VALIDITY) ? KAL_TRUE : KAL_FALSE
+#define SET_GNSS_MEAS_INFO_ADR_VALIDITY(validity) (validity |= GNSS_MEAS_INFO_ADR_VALIDITY)
+
+
+/* GNSS assist data type bitmask */
+#define GNSS_ASSIST_MASK_NONE 0x0
+
+#define GNSS_COM_ASSIST_MASK_REF_TIME (1 << 0) /* 0x0001 */
+#define GNSS_COM_ASSIST_MASK_REF_LOCATION (1 << 1) /* 0x0002 */
+#define GNSS_COM_ASSIST_MASK_IONOSPHERE (1 << 2) /* 0x0004 */
+#define GNSS_COM_ASSIST_MASK_EARTH_ORIENT_PARAMS (1 << 3) /* 0x0008 */
+
+#define GNSS_GEN_ASSIST_MASK_TIME_MODEL (1 << 4) /* 0x0010 */
+#define GNSS_GEN_ASSIST_MASK_DGNSS_CORRECTION (1 << 5) /* 0x0020 */
+#define GNSS_GEN_ASSIST_MASK_NAV_MODEL (1 << 6) /* 0x0040 */
+#define GNSS_GEN_ASSIST_MASK_RTI (1 << 7) /* 0x0080 */
+#define GNSS_GEN_ASSIST_MASK_DATA_BIT_ASSIST (1 << 8) /* 0x0100 */
+#define GNSS_GEN_ASSIST_MASK_ACQUISITION (1 << 9) /* 0x0200 */
+#define GNSS_GEN_ASSIST_MASK_ALMANAC (1 <<10) /* 0x0400 */
+#define GNSS_GEN_ASSIST_MASK_UTC_MODEL (1 <<11) /* 0x0800 */
+#define GNSS_GEN_ASSIST_MASK_AUX_INFO (1 <<12) /* 0x1000 */
+
+
+#define GNSS_ASSIST_MB_MANDATORY_MASK (GNSS_COM_ASSIST_MASK_REF_TIME | \
+ GNSS_COM_ASSIST_MASK_REF_LOCATION | \
+ GNSS_COM_ASSIST_MASK_IONOSPHERE | \
+ GNSS_COM_ASSIST_MASK_EARTH_ORIENT_PARAMS | \
+ GNSS_GEN_ASSIST_MASK_TIME_MODEL | \
+ GNSS_GEN_ASSIST_MASK_DGNSS_CORRECTION | \
+ GNSS_GEN_ASSIST_MASK_NAV_MODEL | \
+ GNSS_GEN_ASSIST_MASK_RTI | \
+ GNSS_GEN_ASSIST_MASK_DATA_BIT_ASSIST | \
+ GNSS_GEN_ASSIST_MASK_ALMANAC | \
+ GNSS_GEN_ASSIST_MASK_UTC_MODEL | \
+ GNSS_GEN_ASSIST_MASK_AUX_INFO) /* 0x1DFF */
+
+
+#define GNSS_ASSIST_MA_MANDATORY_MASK (GNSS_COM_ASSIST_MASK_REF_TIME | \
+ GNSS_GEN_ASSIST_MASK_ACQUISITION | \
+ GNSS_GEN_ASSIST_MASK_AUX_INFO) /* 0x1201 */
+
+
+#define GNSS_ASSIST_TIME_INDEPENDENT_MASK (GNSS_COM_ASSIST_MASK_REF_LOCATION) /* 0x0002 */
+
+
+#define GNSS_LAST_SEC_TIME 1000
+#define GNSS_MDT_GPS_RESPONSE_TIME 1000
+#define GNSS_MDT_LBS_ERRC_PERIOD_TIME 1280
+#define GNSS_INIT_TIMER_INTERVAL 10000
+
+
+/* ---LPPe HA GNSS Interface--- maximum element definition */
+#define GNSS_HA_MAX_LOCAL_KLOBUCHAR_MODEL_ELEMENT 16
+#define GNSS_HA_MAX_LOCAL_KLOBUCHAR_MODEL 8
+//#define GNSS_HA_MAX_LOCAL_KLOBUCHAR_MODEL 1
+
+#define GNSS_HA_MAX_STORM_ELEMENT 16
+#define GNSS_HA_MAX_LOCAL_TROPO_DELAY_AREA_ELEMENT 8
+#define GNSS_HA_MAX_LOCAL_TROPO_DELAY_TIME_ELEMENT 8
+//#define GNSS_HA_MAX_LOCAL_TROPO_DELAY_TIME_ELEMENT 1
+
+#define GNSS_HA_MAX_LOCAL_SURFACE_PARAMS_ELEMENT 8
+#define GNSS_HA_MAX_LOCAL_SURFACE_PARAMS_TIME_ELEMENT 8
+//#define GNSS_HA_MAX_LOCAL_SURFACE_PARAMS_TIME_ELEMENT 1
+
+#define GNSS_HA_MAX_ALTITUDE_ASSIST_AREA_ELEMENT 8
+#define GNSS_HA_MAX_PRESSURE_ASSIST_ELEMENT 16
+//#define GNSS_HA_MAX_PRESSURE_ASSIST_ELEMENT 1
+
+#define GNSS_HA_MAX_CCP_SIGNAL_SUPP_ELEMENT 8
+#define GNSS_HA_MAX_CCP_PREF_STATION_LIST_ELEMENT 8 /* OMA-TS-LPPe: maxReferenceStations */
+#define GNSS_HA_MAX_WA_IONO_SURF_PER_SV_ELEMENT 16 /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+#define GNSS_HA_MAX_MECHANICS_SV_ELEMENT 16 /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+#define GNSS_HA_MAX_DCB_LIST_ELEMENT 16 /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+#define GNSS_HA_MAX_DCB_ELEMENT 16
+#define GNSS_HA_MAX_DEGRAD_MODEL_ELEMENT 16 /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+#define GNSS_HA_MAX_CCP_GENERIC_ELEMENT 8
+//#define GNSS_HA_MAX_CCP_GENERIC_ELEMENT 4
+
+#define GNSS_HA_MAX_CCP_PER_SIG_ELEMENT 8
+#define GNSS_HA_MAX_CCP_PER_SV_ELEMENT 16 /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+//#define GNSS_HA_MAX_CCP_PER_SV_ELEMENT 8 /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+
+#define GNSS_HA_MAX_REQ_NAV_MODEL_ID_ELEMENT 8
+#define GNSS_HA_MAX_MEAS_PER_GNSS_ELEMENT 16
+#define GNSS_HA_MAX_MEAS_PER_SIGNAL_ELEMENT 8
+#define GNSS_HA_MAX_MEAS_PER_SV_ELEMENT 16 /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+#define GNSS_HA_MAX_TEC_PER_SV_ELEMENT 16 /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+
+#define GNSS_HA_MAX_GNSS_GENERIC_ASSIST_DATA_ELEMENT 16
+#define GNSS_HA_MAX_GENERIC_AD_NAV_MODEL_ID_ELEMENT 8
+#define GNSS_HA_MAX_HA_GNSS_CAPA_ELEMENT 8
+
+
+/* ---LPPe HA GNSS Interface--- optional field validity bit definition */
+#define GNSS_HA_MAPPING_FUNC_PARAMS_BIT_BH_VALID 0x80
+#define GNSS_HA_MAPPING_FUNC_PARAMS_BIT_CH_VALID 0x40
+#define GNSS_HA_MAPPING_FUNC_PARAMS_BIT_AW_VALID 0x20
+#define GNSS_HA_MAPPING_FUNC_PARAMS_BIT_BW_VALID 0x10
+#define GNSS_HA_MAPPING_FUNC_PARAMS_BIT_CW_VALID 0x08
+
+#define GNSS_HA_LOCAL_TROPO_DELAY_TIME_ELEMENT_BIT_EH_VALID 0x80
+#define GNSS_HA_LOCAL_TROPO_DELAY_TIME_ELEMENT_BIT_ZW0_VALID 0x40
+#define GNSS_HA_LOCAL_TROPO_DELAY_TIME_ELEMENT_BIT_EW_VALID 0x20
+#define GNSS_HA_LOCAL_TROPO_DELAY_TIME_ELEMENT_BIT_GN_VALID 0x10
+#define GNSS_HA_LOCAL_TROPO_DELAY_TIME_ELEMENT_BIT_GE_VALID 0x08
+
+#define GNSS_HA_LOCAL_SURF_PARAMS_TIME_ELEMENT_BIT_GN_PRESSURE 0x80
+#define GNSS_HA_LOCAL_SURF_PARAMS_TIME_ELEMENT_BIT_GE_PRESSURE 0x40
+#define GNSS_HA_LOCAL_SURF_PARAMS_TIME_ELEMENT_BIT_TEMPERATURE 0x20
+#define GNSS_HA_LOCAL_SURF_PARAMS_TIME_ELEMENT_BIT_TEMPERATURE_RATE 0x10
+#define GNSS_HA_LOCAL_SURF_PARAMS_TIME_ELEMENT_BIT_GN_TEMPERATURE 0x08
+#define GNSS_HA_LOCAL_SURF_PARAMS_TIME_ELEMENT_BIT_GE_TEMPERATURE 0x04
+
+
+/* ---LPPe HA GNSS Interface--- bitmask field bit defintion */
+#define GNSS_HA_COMM_AD_REQ_IONO_BIT_KLOBUCHAR_MODEL 0x01
+#define GNSS_HA_COMM_AD_REQ_IONO_BIT_IONO_STORM_WARNING 0x02
+
+#define GNSS_HA_COMM_AD_REQ_TROPO_BIT_DELAY_LIST 0x01
+#define GNSS_HA_COMM_AD_REQ_TROPO_BIT_SURFACE_PARAMS 0x02
+
+#define GNSS_HA_IONO_MEAS_REQ_BIT_TEC_PER_SV 0x01
+#define GNSS_HA_IONO_MEAS_REQ_BIT_ZENITH_TEC 0x02
+
+#define GNSS_HA_COMM_IONO_AD_SUPP_BIT_LOCAL_KLOBUCHAR 0x01
+#define GNSS_HA_COMM_IONO_AD_SUPP_BIT_IONO_STORM_WARNING 0x02
+#define GNSS_HA_COMM_IONO_AD_SUPP_BIT_WIDE_AREA_IONO_SURFACE 0x04
+
+#define GNSS_HA_COMM_TROPO_AD_SUPP_BIT_LOCAL_TROPOSPHERE_DELAY 0x01
+#define GNSS_HA_COMM_TROPO_AD_SUPP_BIT_SURFACE_PARAMETERS 0x02
+#define GNSS_HA_COMM_TROPO_AD_SUPP_BIT_MULTI_GRID_POINTS 0x04
+
+#define GNSS_HA_COMM_CCP_AD_SUPP_BIT_SUPPORT_AREA_ASSIST 0x01
+#define GNSS_HA_COMM_CCP_AD_SUPP_BIT_MULTI_REF_STATION 0x02
+
+#define GNSS_HA_GENE_AD_SUPP_BIT_BIT_TEC_PER_SV 0x01
+#define GNSS_HA_GENE_AD_SUPP_BIT_BIT_ZENITH_TEC 0x02
+
+#define GNSS_HA_MODE_SUPPORT_BIT_UE_BASED 0x01
+#define GNSS_HA_MODE_SUPPORT_BIT_UE_ASSISTED 0x02
+
+#define GNSS_HA_ANT_SUPPORT_BIT_ANT_DESCRIPTION 0x01
+#define GNSS_HA_ANT_SUPPORT_BIT_ANT_ORIENTATION 0x02
+
+
+
+/* NNUM ********************************************************************/
+
+typedef enum
+{
+ GNSS_NETWORK_CELL_TYPE_NULL,
+ GNSS_NETWORK_CELL_TYPE_EUTRA,
+ GNSS_NETWORK_CELL_TYPE_UTRA,
+ GNSS_NETWORK_CELL_TYPE_GSM
+} gnss_network_cell_type_enum;
+
+typedef enum
+{
+ GNSS_COMMON_ASSIST_DATA_TYPE_REF_TIME,
+ GNSS_COMMON_ASSIST_DATA_TYPE_REF_LOCACTION,
+ GNSS_COMMON_ASSIST_DATA_TYPE_ION_MODEL,
+ GNSS_COMMON_ASSIST_DATA_TYPE_EARTH_ORIENT_PARAMS
+} gnss_common_assist_data_type_enum;
+
+
+typedef enum
+{
+ GNSS_GENERIC_ASSIST_DATA_TYPE_TIME_MODEL,
+ GNSS_GENERIC_ASSIST_DATA_TYPE_DGNSS_CORRECTION,
+ GNSS_GENERIC_ASSIST_DATA_TYPE_NAVIGATION_MODEL,
+ GNSS_GENERIC_ASSIST_DATA_TYPE_RTI,
+ GNSS_GENERIC_ASSIST_DATA_TYPE_DATA_BIT_ASSIST,
+ GNSS_GENERIC_ASSIST_DATA_TYPE_ACQUISITION,
+ GNSS_GENERIC_ASSIST_DATA_TYPE_ALMANAC,
+ GNSS_GENERIC_ASSIST_DATA_TYPE_UTC_MODEL,
+ GNSS_GENERIC_ASSIST_DATA_TYPE_AUX_INFO
+} gnss_generic_assist_data_type_enum;
+
+typedef enum
+{
+ GNSS_NAV_MODEL_REQ_TYPE_STORED_NAV_LIST,
+ GNSS_NAV_MODEL_REQ_TYPE_REQ_NAV_LIST
+} gnss_nav_model_req_type_enum;
+
+typedef enum
+{
+ GNSS_UTC_MODEL_TYPE_MODEL1,
+ GNSS_UTC_MODEL_TYPE_MODEL2,
+ GNSS_UTC_MODEL_TYPE_MODEL3,
+ GNSS_UTC_MODEL_TYPE_MODEL4
+} gnss_utc_model_type_enum;
+
+
+typedef enum
+{
+ GNSS_AUX_INFO_GNSS_TYPE_GPS,
+ GNSS_AUX_INFO_GNSS_TYPE_GLONASS
+} gnss_aux_info_gnss_type_enum;
+
+
+typedef enum
+{
+ GNSS_POS_RESULT_TYPE_POS_CNF,
+ GNSS_POS_RESULT_TYPE_ASSIST_DATA_REQ
+} gnss_pos_result_type_enum;
+
+
+typedef enum
+{
+ GNSS_MEAS_RESULT_TYPE_MEAS_CNF,
+ GNSS_MEAS_RESULT_TYPE_ASSIST_DATA_REQ
+} gnss_meas_result_type_enum;
+
+
+typedef enum
+{
+ GNSS_LOC_RESULT_NULL,
+ GNSS_LOC_RESULT_NO_ERROR,
+ GNSS_LOC_RESULT_UNDEFINED,
+ GNSS_LOC_RESULT_REQ_TIMEOUT,
+ GNSS_LOC_RESULT_NOT_ENOUGH_SATELLITES,
+ GNSS_LOC_RESULT_ASSIST_DATA_MISSING, /* not used in POS(MEAS)_REQ/CNF primitive */
+
+ /* dedicated for RRLP */
+ GNSS_LOC_RESULT_METHOD_NOT_SUPPORTED,
+ GNSS_LOC_RESULT_REFERENCE_BTS_NOT_SERVING_BTS,
+
+ /* dedicated for RRC */
+ GNSS_LOC_RESULT_NOT_ACCOMPLISHED_TIMING_OF_CELL_FRAMES, /* similar to FINE_TIME_ASSISTANCE_MEASUREMENTS_NOT_POSSIBLE */
+ GNSS_LOC_RESULT_REFERENCE_CELL_NOT_SERVING_CELL, /* reference cell's SFN cannot be decoded */
+
+ /* dedicated for LPP */
+ GNSS_LOC_RESULT_FINE_TIME_ASSISTANCE_MEASUREMENTS_NOT_POSSIBLE, /* fineTimeAssistanceMeasurementsNotPossible IE present */
+ GNSS_LOC_RESULT_ADR_MEASUREMENTS_NOT_POSSIBLE, /* adrMeasurementsNotPossible IE present */
+ GNSS_LOC_RESULT_MULTI_FREQUENCY_MEASUREMENTS_NOT_POSSIBLE /* multiFrequencyMeasurementsNotPossible IE present */
+
+} gnss_loc_result_enum;
+
+typedef enum {
+ TIME_SIB_RESULT_OK =0, /* ERRC/EL1 reported useful info, check fields in lbs_errc_read_time_sib_ind_struct */
+ TIME_SIB_RESULT_NOT_TRY =1, /* No valid SIB info, and LBS doesnt need to try again */
+ TIME_SIB_RESULT_RE_TRY =2, /* No valid SIB info, and LBS may try again */
+ TIME_SIB_RESULT_TIMEOUT =3 /* While trying to read SIB for time sync, guard timer timeouts(2s), Can retry, ask ERRC for further check*/
+} time_sib_result_enum;
+
+typedef enum {
+ TIME_SIB_CDMA_SYS_TIME_SYNC =0,
+ TIME_SIB_CDMA_SYS_TIME_ASYNC =1
+} time_sib_cdma_sys_time_type_enum;
+
+typedef enum {
+ GNSS_TIME,
+ GPS_TIME,
+ UTC_TIME
+} frame_sync_pulse_time_type_enum;
+
+
+/* ---LPPe HA GNSS Interface--- */
+typedef enum
+{
+ GNSS_HA_IONO_MODEL_TYPE_STATIC_MODEL,
+ GNSS_HA_IONO_MODEL_TYPE_PERIODIC_MODEL
+} gnss_ha_iono_model_type_enum;
+
+
+typedef enum
+{
+ GNSS_HA_COMMON_ASSIST_DATA_TYPE_IONO_MODEL,
+ GNSS_HA_COMMON_ASSIST_DATA_TYPE_TROPO_MODEL,
+ GNSS_HA_COMMON_ASSIST_DATA_TYPE_ALTITUDE,
+ GNSS_HA_COMMON_ASSIST_DATA_TYPE_SOLAR_RAD,
+ GNSS_HA_COMMON_ASSIST_DATA_TYPE_CCP_ASSIST,
+} gnss_ha_common_assist_data_type_enum;
+
+
+typedef enum
+{
+ GNSS_HA_GENERIC_ASSIST_DATA_TYPE_WA_ION_SURF,
+ GNSS_HA_GENERIC_ASSIST_DATA_TYPE_SV_MECHANICS,
+ GNSS_HA_GENERIC_ASSIST_DATA_TYPE_SV_DCB,
+ GNSS_HA_GENERIC_ASSIST_DATA_TYPE_DEGRAD_MODEL,
+ GNSS_HA_GENERIC_ASSIST_DATA_TYPE_CCP_ASSIST,
+ GNSS_HA_GENERIC_ASSIST_DATA_TYPE_NAV_MODEL,
+} gnss_ha_generic_assist_data_type_enum;
+
+
+typedef enum
+{
+ GNSS_HA_CCP_ASSIST_COMMON_TYPE_COMMOM,
+ GNSS_HA_CCP_ASSIST_COMMON_TYPE_CONTROL
+} gnss_ha_ccp_assist_common_type_enum;
+
+
+typedef enum
+{
+ GNSS_HA_SV_TYPE_GPS_IIR,
+ GNSS_HA_SV_TYPE_GPS_IIRM,
+ GNSS_HA_SV_TYPE_GPS_IIF,
+ GNSS_HA_SV_TYPE_GPS_III,
+ GNSS_HA_SV_TYPE_GLONASS_M,
+ GNSS_HA_SV_TYPE_GLONASS_K1,
+ GNSS_HA_SV_TYPE_GLONASS_K2,
+ GNSS_HA_SV_TYPE_GLONASS_KM,
+ GNSS_HA_SV_TYPE_UNKNOWN
+} gnss_ha_sv_type_enum;
+
+
+typedef enum
+{
+ GNSS_HA_DCB_REF_PD_PILOT,
+ GNSS_HA_DCB_REF_PD_DATA,
+ GNSS_HA_DCB_REF_PD_NOT_APPLICABLE
+} gnss_ha_dcb_ref_pd_enum;
+
+
+typedef enum
+{
+ GNSS_HA_CODE_PHASE_ERR_TYPE_RMS,
+ GNSS_HA_CODE_PHASE_ERR_TYPE_CNR
+} gnss_ha_code_phase_err_type_enum;
+
+
+typedef enum
+{
+ GNSS_HA_AGNSS_QOR_TYPE_10_M,
+ GNSS_HA_AGNSS_QOR_TYPE_1_KM,
+ GNSS_HA_AGNSS_QOR_TYPE_10_KM,
+ GNSS_HA_AGNSS_QOR_TYPE_100_KM
+} gnss_ha_agnss_qor_type_enum;
+
+
+typedef enum
+{
+ GNSS_HA_HORI_UNC_TYPE_CEP,
+ GNSS_HA_HORI_UNC_TYPE_ELLIPSE
+} gnss_ha_hori_unc_type_enum;
+
+
+typedef enum
+{
+ GNSS_HA_MULTIPATH_DETECTION_TYPE_LOW,
+ GNSS_HA_MULTIPATH_DETECTION_TYPE_MODERATE,
+ GNSS_HA_MULTIPATH_DETECTION_TYPE_HIGH,
+ GNSS_HA_MULTIPATH_DETECTION_TYPE_NOT_MEASURED
+} gnss_ha_multipath_detect_type_enum;
+
+
+typedef enum
+{
+ GNSS_HA_TGT_ERR_CAUSE_UNDEFINED,
+ GNSS_HA_TGT_ERR_CAUSE_HA_METHOD_NOT_SUPPORTED
+} gnss_ha_tgt_err_cause_enum;
+
+
+typedef enum
+{
+ GNSS_HA_TGT_IONO_MEAS_ERR_CAUSE_UNDEFINED,
+ GNSS_HA_TGT_IONO_MEAS_ERR_CAUSE_IONO_MEAS_NOT_SUPPORTED,
+ GNSS_HA_TGT_IONO_MEAS_ERR_CAUSE_IONO_MEAS_NOT_AVAILABLE
+} gnss_ha_tgt_iono_meas_err_cause_enum;
+
+typedef enum
+{
+ GNSS_HA_TGT_ENV_OBSERVE_ERR_CAUSE_UNDEFINED,
+ GNSS_HA_TGT_ENV_OBSERVE_ERR_CAUSE_SURF_MEAS_NOT_SUPPORTED,
+ GNSS_HA_TGT_ENV_OBSERVE_ERR_CAUSE_SURF_MEAS_NOT_AVAILABLE
+} gnss_ha_tgt_env_observe_err_cause_enum;
+
+
+typedef enum
+{
+ GNSS_HA_TGT_GNSS_ERR_CAUSE_UNDEFINED,
+ GNSS_HA_TGT_GNSS_ERR_CAUSE_GNSS_NOT_SUPPORTED_BY_TARGET,
+ GNSS_HA_TGT_GNSS_ERR_CAUSE_GNSS_UNAVAILABLE_FOR_ALL_REQUESTED_SIGNALS,
+ GNSS_HA_TGT_GNSS_ERR_CAUSE_GNSS_ANTENNA_INFO_NOT_SUPPORTED,
+ GNSS_HA_TGT_GNSS_ERR_CAUSE_GNSS_ANTENNA_INFO_NOT_AVAILABLE,
+ GNSS_HA_TGT_GNSS_ERR_CAUSE_GNSS_PRESSURE_INFO_NOT_SUPPORTED,
+ GNSS_HA_TGT_GNSS_ERR_CAUSE_GNSS_PRESSURE_INFO_NOT_AVAILABLE,
+ GNSS_HA_TGT_GNSS_ERR_CAUSE_GNSS_UNABLE_TO_MODIFY_CTRL_PARAMS
+} gnss_ha_tgt_gnss_err_cause_enum;
+
+
+typedef enum
+{
+ GNSS_HA_REQ_CCP_REF_STATION_TYPE_POS_BASED,
+ GNSS_HA_REQ_CCP_REF_STATION_TYPE_ID_BASED,
+ GNSS_HA_REQ_CCP_REF_STATION_TYPE_KILL_LIST
+} gnss_ha_req_ccp_ref_station_type_enum;
+
+/*gnss2lcsp_struct*/
+
+typedef char kal_bool;
+typedef unsigned char kal_uint8;
+typedef char kal_int8;
+typedef unsigned short kal_uint16;
+typedef short kal_int16;
+typedef unsigned int kal_uint32;
+typedef int kal_int32;
+typedef unsigned long long kal_uint64;
+typedef long long kal_int64;
+
+/*=== GNSS Common Assistance Data ===*/
+
+/* start for gnss reference time */
+typedef struct
+{
+ kal_uint8 svID; /* satellite PRN [1..64] */
+ kal_uint16 tlmWord; /* telemetry message [0..16383] */
+ kal_uint8 antiSpoof; /* anti spoof flag [0..1] */
+ kal_uint8 alert; /* alert flag [0..1] */
+ kal_uint8 tlmRsvdBits; /* 2 bit reserved bits [0..3] */
+} gnss_gps_tow_assist_struct;
+
+
+typedef struct
+{
+ MTK_GNSS_ID_ENUM gnssTimeID;
+ /**
+ * This field specifies the sequential number of days from the origin of the GNSS System Time as follows:
+ * GPS, QZSS, SBAS V Days from January 6th 1980 00:00:00 UTC(USNO)
+ * Galileo V TBD;
+ * GLONASS V Days from January 1st 1996
+ */
+ kal_uint16 gnssDayNumber; /* [0..32767] */
+ kal_uint32 gnssTimeOfDay; /* [0..86399] in seconds */
+ kal_bool gnssTimeOfDayFracMsecValid;
+ kal_uint16 gnssTimeOfDayFracMsec; /* [0..999] in milli-seconds */
+ kal_bool notificationLeapSecondValid;
+ kal_uint8 notificationLeapSecond; /* only present when gnss=GLONASS */
+ kal_uint8 numGpsTowAssist; /* only present when gnss=GPS */
+ gnss_gps_tow_assist_struct gpsTowAssist[GNSS_MAX_REF_TIME_SAT_ELEMENT];
+} gnss_system_time_struct;
+
+/* start for gnss reference location */
+typedef struct
+{
+ kal_bool signOfLatitude; /* TRUE: SOUTH, FALSE: NORTH */
+ kal_uint32 degreesLatitude; /* [0..8388607] */
+ kal_int32 degreesLongitude; /* [-8388608..8388607] */
+ kal_bool signOfAltitude; /* TRUE: DEPTH, FALSE: HEIGHT */
+ kal_uint16 altitude; /* [0..32767] */
+ kal_uint8 uncertaintySemiMajor; /* K: [0..127], uncertainty r (meter) = C*((1+x)^K-1), C=10, x=0.1 */
+ kal_uint8 uncertaintySemiMinor; /* K: [0..127], uncertaintyr (meter) = C*((1+x)^K-1), C=10, x=0.1 */
+ kal_uint8 orientationMajorAxis; /* bearing angle degree: [0-179] */
+ kal_uint8 uncertaintyAltitude; /* K: [0..127], uncertainty h (meter) = C*((1+x)^K-1), C=45, x=0.025 */
+ kal_uint8 confidence; /* [0..100] */
+} gnss_reference_location_struct;
+/* end for gnss reference location */
+
+/* ---LPPe HA GNSS Interface---begin--- */
+typedef struct
+{
+ gnss_system_time_struct beginTime; /* specify the start time of the validity period */
+ kal_bool beginTimeAltValid;
+ kal_uint16 beginTimeAlt; /* [0..2881], specify the alternative start time, and the start time is relative the time the message was received, scale factor 15 min (range from 0 minutes to 43215 min = 30 days) */
+ kal_uint16 duration; /* [0..2881], specify the duration of the validity period after the beginTime, scale factor 15 min (range from 0 minutes to 43215 min = 30 days) */
+} gnss_ha_validity_period_struct;
+
+
+typedef struct
+{
+ kal_uint8 regionSizeInv; /* [1..255], specify the inverse of the size of each side of the region in degrees, for value N the size is 10/N degrees */
+ kal_bool areaWidthValid;
+ kal_uint16 areaWidth; /* [2..9180], specify the number of regions in the area in East-West direction, if the field is not present, the value is 1 */
+ kal_uint16 codedLatOfNWCorner; /* [0..4589], specify the latitude of the North-West corner of the area, encoded as explained in OMA-TS-LPPe Appendix C.1 */
+ kal_uint16 codedLonOfNWCorner; /* [0..9179], specify the longitude of the North-West corner of the area, encoded as explained in OMA-TS-LPPe Appendix C.1 */
+
+ kal_bool rleListValid;
+ //LPP_EXT_OMA_LPPe_RleList rleList; /* TBD: redefine internal structure? */ /* This field lists the regions in which the data is valid. If the field is not present, the data is valid in all the regions in the area */
+} gnss_ha_validity_area_struct;
+
+
+typedef struct
+{
+ kal_uint8 regionSizeInv; /* specify the inverse of the size of each side of the region in degrees, for value N the size is 10/N degrees */
+ kal_bool areaWidthValid;
+ kal_uint16 areaWidth; /* specify the number of regions in the area in East-West direction, if the field is not present, the value is 1 */
+ kal_uint16 codedLatOfNWCorner; /* specify the latitude of the North-West corner of the area, encoded as explained in OMA-TS-LPPe Appendix C.1 */
+ kal_uint16 codedLonOfNWCorner; /* specify the longitude of the North-West corner of the area, encoded as explained in OMA-TS-LPPe Appendix C.1 */
+} gnss_ha_storm_validity_area_struct; /* only used in gnss_ha_iono_storm_ind_struct */
+
+
+typedef struct
+{
+ kal_uint8 duration; /* [1..63], scale factor 15 min, range [15, 945 min], i.e. upto 16 hours */
+ kal_bool durationLSBValid;
+ kal_uint8 durationLSB; /* [1..89], finer granularity duration, scale factor is 10 seconds, range [10, 890] seconds */
+} gnss_ha_duration;
+
+
+typedef struct
+{
+ kal_uint8 validityBitmap; /* bhValid, chValid, awValid, bwValid, cwValid, use GNSS_HA_MAPPING_FUNC_PARAMS_BIT_*_VALID */
+ kal_uint16 ah; /* [0..16383], the a-coefficient of the hydrostatic mapping function, scale factor 2^-14 */
+ /* optional */
+ kal_uint16 bh; /* [0..16383], the b-coefficient of the hydrostatic mapping function, scale factor 2^-14 */
+ /* optional */
+ kal_uint16 ch; /* [0..16383], the c-coefficient of the hydrostatic mapping function, scale factor 2^-14 */
+ /* optional */
+ kal_uint16 aw; /* [0..16383], the a-coefficient of the wet mapping function, scale factor 2^-14 */
+ /* optional */
+ kal_uint16 bw; /* [0..16383], the b-coefficient of the wet mapping function, scale factor 2^-14 */
+ /* optional */
+ kal_uint16 cw; /* [0..16383], the c-coefficient of the wet mapping function, scale factor 2^-14 */
+} gnss_ha_mapping_func_params_struct;
+
+
+typedef struct
+{
+ kal_int32 latitude; /* [-2147483648..2147483647], latitude based on WGS84 [GPS-ICD-200D] datum, the relation between the latitude X in range [-90', 90'],
+ and the coded number N is N = floor((X/90')*2^31), where value N=2^31 is coded as N=2^31-1, resolution 4.7 mm */
+ kal_int32 longitude; /* [-2147483648..2147483647], longitude based on WGS84 [GPS-ICD-200D] datum, the relation between the longitude X in range [-180', 180'),
+ and the coded number N is floor((X/180')*2^31), worst-case resolution (at the Equator) 9.3 mm */
+ kal_bool cepValid;
+ kal_uint8 cep; /* [0..255], horizontal uncertainty expressed as Circular Error Probable expressed as the coded number N,
+ the relation between the CEP and the coded number is given by CEP = 0.3*((1+0.02)^N - 1) meters, range [0, 45.6) meters */
+ kal_bool uncSemiMajorValid;
+ kal_uint8 uncSemiMajor; /* [0..255], the semi-major axis of the horizontal uncertainty ellipse expressed as the coded number N,
+ the relation between the semi-major axis and the coded number is given by semi-major axis = 0.3*( (1+0.02)^N -1) meters, range [0, 45.6) meters */
+ kal_bool uncSemiMinorValid;
+ kal_uint8 uncSemiMinor; /* [0..255], the semi-minor axis of the horizontal uncertainty ellipse expressed as the coded number N,
+ the relation between the semi-minor axis and the coded number is given by semi-minor axis = 0.3*((1+0.02)^N -1) meters, range [0, 45.6) meters */
+ kal_bool offsetAngleValid;
+ kal_uint8 offsetAngle; /* [0..179], the angle of semi-major axis measured clockwise with respect to True North in steps of 1 degree */
+
+ kal_bool confHorizontalValid;
+ kal_uint8 confHorizontal; /* [0..99], specify the horizontal confidence percentage associated with the CEP or Uncertainty Ellipse depending upon which is included */
+ kal_int32 altitude; /* [-64000..1280000], altitude with respect to WGS84 [GPS-ICD-200D] ellipsoid, scale factor 2^(-7) meters, range [-500, 10000] meters */
+ kal_uint8 uncAltitude; /* [0..255], the altitude uncertainty expressed as the coded number N, the relation between the altitude uncertainty and
+ the coded number is given by uncertainty= 0.3*((1+0.02)^N -1) meters, range [0, 45.6) meters */
+ kal_bool confVerticalValid;
+ kal_uint8 confVertical; /* [0..99], specify the confidence percentage associated with the altitude uncertainty */
+} gnss_ha_high_accu_3d_position_struct;
+
+/* begin of gnss_ha_ionospheric_model */
+typedef struct
+{
+ gnss_ha_validity_period_struct validityPeriod; /* specify the start time and duration of the model validity period */
+ kal_int8 alfa0; /* [-128..127], specify the alpha0 parameter of the Klobuchar model, scale factor 2^(-30) seconds */
+ kal_int8 alfa1; /* [-128..127], specify the alpha1 parameter of the Klobuchar model, scale factor 2^(-27) seconds/semi-circle */
+ kal_int8 alfa2; /* [-128..127], specify the alpha2 parameter of the Klobuchar model, scale factor 2^(-24) seconds/semi-circle^2 */
+ kal_int8 alfa3; /* [-128..127], specify the alpha3 parameter of the Klobuchar model, scale factor 2^(-24) seconds/semi-circle^3 */
+ kal_int8 beta0; /* [-128..127], specify the beta0 parameter of the Klobuchar model, scale factor 2^11 seconds */
+ kal_int8 beta1; /* [-128..127], specify the beta1 parameter of the Klobuchar model, scale factor 2^14 seconds/semi-circle */
+ kal_int8 beta2; /* [-128..127], specify the beta2 parameter of the Klobuchar model, scale factor 2^16 seconds/semi-circle^2 */
+ kal_int8 beta3; /* [-128..127], specify the beta3 parameter of the Klobuchar model, scale factor 2^16 seconds/semi-circle^3 */
+} gnss_ha_local_klobuchar_model_struct;
+
+
+typedef struct
+{
+ gnss_ha_validity_area_struct validityArea;
+ kal_uint8 numKlobucharModel;
+ gnss_ha_local_klobuchar_model_struct klobucharModel[GNSS_HA_MAX_LOCAL_KLOBUCHAR_MODEL]; /* local klobuchar model per validity period */
+} gnss_ha_local_klobuchar_model_element_struct;
+
+
+typedef struct
+{
+ kal_uint8 numKlobucharElement;
+ gnss_ha_local_klobuchar_model_element_struct klobucharElement[GNSS_HA_MAX_LOCAL_KLOBUCHAR_MODEL_ELEMENT]; /* local klobuchar model per validity area */
+} gnss_ha_local_klobuchar_model_list_struct;
+
+
+typedef struct
+{
+ gnss_ha_validity_period_struct validityPeriod; /* specify the time interval over which the storm data is valid */
+ //LPP_EXT_OMA_LPPe_AGNSS_RleListIono rleListIono; /* TBD: structure is too big, redefine internal structure? */
+} gnss_ha_storm_element_struct;
+
+
+typedef struct
+{
+ kal_uint8 numStormElement;
+ gnss_ha_storm_element_struct stormElement[GNSS_HA_MAX_STORM_ELEMENT]; /* storm indication element per validity period */
+} gnss_ha_storm_list_struct;
+
+
+typedef struct
+{
+ gnss_ha_storm_validity_area_struct area; /* rlelist is not not included or ignored in IonoStormIndication */
+ gnss_ha_storm_list_struct stormList; /* provide information on the ionospheric activity in the area defined by area */
+} gnss_ha_iono_storm_ind_struct;
+
+
+typedef struct
+{
+ kal_bool localKlobucharListValid;
+ gnss_ha_local_klobuchar_model_list_struct localKlobucharList; /* localized Klobuchar model */
+
+ kal_bool ionoStormIndValid;
+ gnss_ha_iono_storm_ind_struct ionoStormInd; /* information on the ionosphere conditions in the area */
+} gnss_ha_ionospheric_static_model_struct;
+
+
+typedef struct
+{
+ kal_bool durationValid;
+ gnss_ha_duration duration; /* specify the length of the continuous periodic assistance session */
+
+ kal_bool rateValid;
+ kal_uint8 rate; /* [1..64], specify the length of the continuous periodic assistance session */
+
+ kal_bool refPositionValid;
+ //LPP_EXT_Ellipsoid_Point referencePosition; /* TBD: redefine internal structure? */
+
+ kal_bool validityAreaValid;
+ gnss_ha_validity_area_struct validityArea;
+} gnss_ha_wa_iono_control_param_struct;
+
+
+typedef struct
+{
+ gnss_ha_validity_period_struct validityPeriod; /* define the validity period of the widea area ionosphere correction */
+} gnss_ha_wa_iono_common_param_struct;
+
+
+typedef struct
+{
+ kal_bool controlParamsValid;
+ gnss_ha_wa_iono_control_param_struct controlParams; /* carry the control parameters of the periodic Wide Area ionosphere surface corrections */
+ kal_bool commonParamsValid;
+ gnss_ha_wa_iono_common_param_struct commonParams; /* carry the common parameters of the periodic Wide Area ionosphere surface corrections */
+} gnss_ha_ionospheric_periodic_model_struct;
+
+
+typedef struct
+{
+ kal_uint16 transactionID;
+ gnss_ha_iono_model_type_enum type;
+ union
+ {
+ gnss_ha_ionospheric_static_model_struct staticModel;
+ gnss_ha_ionospheric_periodic_model_struct periodicWAIono; /* based on the real-time GNSS observations and thus updated frequently to the target */
+ } data;
+} gnss_ha_common_ionospheric_model_struct;
+/* end of gnss_ha_ionospheric_model */
+
+
+/* begin of gnss_ha_troposphere_model */
+typedef struct
+{
+ gnss_ha_validity_period_struct validityPeriod; /* specify the start time and duration of the local troposphere parameters validity period */
+ kal_uint16 zh0; /* [0..4095], the hydrostatic zenith delay (meters), measured at the reference altitude level, scale factor 2^(-10) m */
+
+ kal_uint8 validityBitmap; /* ehValid, zw0Valid, ewValid, gNValid, gEValid, use GNSS_HA_LOCAL_TROPO_DELAY_TIME_ELEMENT_BIT_*_VALID */
+ /* optional */
+ kal_uint16 eh; /* [0..4095], the exponential fit parameter (1/m) for scaling zh0 to the target altitude, scale factor 2^(-20) (1/m) */
+ /* optional */
+ kal_uint16 zw0; /* [0..4095], the wet zenith delay (meters), measured at the reference altitude level, scale factor 2^(-10) m */
+ /* optional */
+ kal_uint16 ew; /* [0..4095], the exponential fit parameter (1/m) for scaling zw0 to the target altitude, scale factor 2^(-20) (1/m) */
+ /* optional */
+ kal_int16 gN; /* [-8192..8191], the gradient parameter (m) in North direction of the azimuthally asymmetric part of the tropospheric slant delay, scale factor 2^(-7) m */
+ /* optioanl */
+ kal_int16 gE; /* [-8192..8191], the gradient parameter (m) in East direction of the azimuthally asymmetric part of the tropospheric slant delay, scale factor 2^(-7) m */
+
+ gnss_ha_mapping_func_params_struct mappingFuncParams; /* coefficients of the mapping functions */
+} gnss_ha_local_tropo_delay_time_element_struct;
+
+
+typedef struct
+{
+ kal_uint8 numDelayTimeElement;
+ gnss_ha_local_tropo_delay_time_element_struct delayTimeElement[GNSS_HA_MAX_LOCAL_TROPO_DELAY_TIME_ELEMENT];
+} gnss_ha_local_tropo_delay_time_list_struct;
+
+
+typedef struct
+{
+ gnss_ha_validity_area_struct validityArea; /* specify the geographical validity area of the local troposphere model parameters */
+
+ kal_bool refAltitudeValid;
+ kal_int16 refAltitude; /* [-1000..8192], specify the reference altitude (from nominal sea level, EGM96) at which the delay measurements are made, scale factor 1m, if absent, the reference altitude is the zero nominal sea level */
+
+ kal_bool graRefPositionValid;
+ //LPP_EXT_Ellipsoid_Point graRefPosition; /* TBD: redefine internal structure? */ /* specify the origion for the spatial gradients gN and gE, if absent, the origin is taken as the middle point of the validity area */
+
+ gnss_ha_local_tropo_delay_time_list_struct delayList; /* specify the troposphere delays */
+} gnss_ha_local_tropo_delay_area_element_struct;
+
+
+typedef struct
+{
+ kal_uint8 numDelayAreaElement;
+ gnss_ha_local_tropo_delay_area_element_struct delayAreaElement[GNSS_HA_MAX_LOCAL_TROPO_DELAY_AREA_ELEMENT];
+} gnss_ha_troposphere_delay_list_struct;
+
+
+typedef struct
+{
+ gnss_ha_validity_period_struct validityPeriod; /* specify the start time and duration of the surface parameter validity period */
+
+ kal_int16 pressure; /* [-1024..1023], local atmospheric pressure measurement (hPa) at the altitude given by refAltitude, scale factor 0.1 hPa, the value is added to the nominal pressure of 1013hPa */
+ kal_int8 pressureRate; /* [-128..127], rate of change of pressure, when calculating the pressure, the origin of time is the begin time of the validity period, scale factor 10 Pa/hour */
+
+ kal_uint8 validityBitmap; /* gNpressureValid, gEpressureValid, temperatureValid, temperatureRateValid, gNtemperatureValid, gEtemperatureValid, use GNSS_HA_LOCAL_SURF_PARAMS_TIME_ELEMENT_BIT_* */
+ /* optional */
+ kal_int8 gNpressure; /* [-128..127], specify the northward gradient of the atmospheric pressure, if this field is present, but gE is not given, the eastward gradient is zero, scale factor 10 Pa/km */
+ /* optional */
+ kal_int8 gEpressure; /* [-128..127], specify the eastward gradient of the atmospheric pressure, if this field is present, but gN is not given, the nothward gradient is zero, scale factor 10 Pa/km */
+ /* optional */
+ kal_int8 temperature; /* [-64..63], local temperature measurement at the reference altitude refAltitude, scale factor 1K, the value is added to 273K */
+ /* optional */
+ kal_int8 temperatureRate; /* [-16..16], local temperature change rate, the scale factor 1K/hour */
+ /* optional */
+ kal_int8 gNtemperature; /* [-8..7], specify the northward gradient of the temperature, if this field is present, but gE is not given, the eastward gradient is zero, scale factor 1 K/km */
+ /* optional*/
+ kal_int8 gEtemperature; /* [-8..7], specify the eastward gradient of the temperature, if this field is present, but gN is not given, the nothward gradient is zero, scale factor 1 K/km */
+
+ gnss_ha_mapping_func_params_struct mappingFuncParams; /* coefficients of the mapping functions */
+} gnss_ha_local_surface_params_time_element_struct;
+
+
+typedef struct
+{
+ kal_uint8 numParamsTimeElements;
+ gnss_ha_local_surface_params_time_element_struct paramsTimeElement[GNSS_HA_MAX_LOCAL_SURFACE_PARAMS_TIME_ELEMENT];
+} gnss_ha_local_surface_params_struct;
+
+
+typedef struct
+{
+ gnss_ha_validity_area_struct validityArea; /* specify the geographical validity area of the local troposphere model parameters */
+
+ kal_bool refAltitudeValid;
+ kal_int16 refAltitude; /* [-1000..8192], specify the reference altitude (from nominal sea level, EGM96) at which the surface measurements are made, scale factor 1m, if absent, the reference altitude is the zero nominal sea level EGM96 */
+
+ kal_bool graRefPositionValid;
+ //LPP_EXT_Ellipsoid_Point graRefPosition; /* TBD: redefine internal structure? */ /* specify the origion for the spatial gradients gN and gE, if absent, the origin is taken as the middle point of the validity area */
+
+ gnss_ha_local_surface_params_struct paramsList; /* specify the surface parameters */
+} gnss_ha_local_surface_params_element_struct;
+
+
+typedef struct
+{
+ kal_uint8 numParamsElements;
+ gnss_ha_local_surface_params_element_struct paramsElement[GNSS_HA_MAX_LOCAL_SURFACE_PARAMS_ELEMENT];
+} gnss_ha_local_surface_params_list_struct;
+
+
+typedef struct
+{
+ kal_uint16 transactionID;
+ kal_bool tropoDelayListValid;
+ gnss_ha_troposphere_delay_list_struct tropoDelayList; /* provide the zenith troposphere delay components determined in a given location and the needed parameters to adjust the delay to the target's altitude */
+ kal_bool surfaceParamListValid;
+ gnss_ha_local_surface_params_list_struct surfaceParametersList; /* provide the surface pressure and optionally temperature that allow the target to compute the tropospheric delay using one of the known atmosphere models, such as the Hopfield or Saastamoinen model */
+} gnss_ha_common_troposphere_model_struct;
+/* end of gnss_ha_troposphere_model */
+
+
+/* begin of gnss_ha_altitude_assist */
+typedef struct
+{
+ gnss_ha_validity_period_struct validityPeriod; /* specify the start time and duration of the altitude assistance validity period */
+
+ kal_int16 pressure; /* [-1024..1023], local atmospheric pressure measurement (hPa) at the altitude given by refAltitude, scale factor 10 Pa, the value is added to the nominal pressure of 1013hPa */
+ kal_bool pressureRateValid;
+ kal_int8 pressureRate; /* [-128..127], rate of change of pressure, when calculating the pressure, the origin of time is the begin time of the validity period, scale factor 10 Pa/hour */
+
+ kal_bool gNValid;
+ kal_int8 gN; /* [-128..127], specify the northward gradient of the atmospheric pressure, scale factor 10 Pa/km */
+ kal_bool gEValid;
+ kal_int8 gE; /* [-128..127], specify the eastward gradient of the atmospheric pressure, scale factor 10 Pa/km */
+} gnss_ha_pressure_assist_element_struct;
+
+
+typedef struct
+{
+ kal_uint8 numPressureElements;
+ gnss_ha_pressure_assist_element_struct pressureElement[GNSS_HA_MAX_PRESSURE_ASSIST_ELEMENT];
+} gnss_ha_pressure_assist_list_struct;
+
+
+typedef struct
+{
+ gnss_ha_validity_area_struct validityArea; /* specify the geographical validity area of the altitude assistance */
+
+ kal_bool gradRefPositionValid;
+ gnss_reference_location_struct gradRefPosition; /* specify the origin for the spatial gradients gN and gE, if absent, the origin is taken as the middle point of the validity area */
+
+ kal_bool refAltitudeValid;
+ kal_int16 refAltitude; /* specify the reference altitude (from nominal sea level, [EGM96]) at which the surface measurements are made, scale factor 1m, if absent, the reference altitude is the zero nominal sea level */
+
+ gnss_ha_pressure_assist_list_struct pressureAssistanceList; /* specify the set of pressure assistance elements for different periods of time */
+} gnss_ha_altitude_assist_area_element_struct;
+
+
+typedef struct
+{
+ kal_uint16 transactionID;
+ kal_uint8 numAltitudeAreaElement;
+ gnss_ha_altitude_assist_area_element_struct altitudeAreaElement[GNSS_HA_MAX_ALTITUDE_ASSIST_AREA_ELEMENT];
+} gnss_ha_common_altitude_assist_struct;
+/* end of gnss_ha_altitude_assist */
+
+
+/* begin of gnss_ha_altitude_assist */
+typedef struct
+{
+ kal_uint16 transactionID;
+ kal_uint16 solarRad; /* specifies the solar radiation at one AU from the Sun, scale factor 1 Wm^(-2) */
+} gnss_ha_common_solar_radiation_struct;
+/* end of gnss_ha_altitude_assist */
+
+
+/* begin of gnss_ha_common_ccp_assist */
+typedef struct
+{
+ MTK_GNSS_ID_ENUM gnssID; /* specify the GNSS type */
+ kal_uint8 gnssSignals; /* specify the GNSS signal types for which CCP assistance can be provided in the area, GNSS Signal(s), map to GNSS_SGN_ID_BITMAP_* */
+} gnss_ha_ccp_signal_supp_element_struct;
+
+
+typedef struct
+{
+ kal_uint8 numSigSuppElement;
+ gnss_ha_ccp_signal_supp_element_struct sigSuppElement[GNSS_HA_MAX_CCP_SIGNAL_SUPP_ELEMENT];
+} gnss_ha_ccp_signal_supp_struct;
+
+
+typedef struct
+{
+ gnss_ha_validity_area_struct areaDescr; /* provide the description of the area */
+ gnss_ha_ccp_signal_supp_struct sigSupp; /* provide the GNSS signal support information */
+} gnss_ha_ccp_support_area_struct;
+
+
+typedef struct
+{
+ kal_uint16 refStationID; /* define the ID of the reference station */
+ gnss_ha_high_accu_3d_position_struct refStationLoc; /* define the location of the reference station, of which ID is refStationID */
+ kal_bool antennaDescrValid;
+ //LPP_EXT_OMA_LPPe_AGNSS_AntennaDescription antennaDescr; /* TBD: redefine internal structure? */ /* specify the antenna type used at the reference station */
+} gnss_ha_ccp_pref_station_list_element_struct;
+
+
+typedef struct
+{
+
+ kal_uint8 numPrefStationElement;
+ gnss_ha_ccp_pref_station_list_element_struct prefStationElement[GNSS_HA_MAX_CCP_PREF_STATION_LIST_ELEMENT];
+} gnss_ha_ccp_pref_station_list_struct;
+
+
+typedef struct
+{
+ kal_bool supportAreaValid;
+ gnss_ha_ccp_support_area_struct supportArea; /* provide information on the area, in which CCP is supported */
+
+ kal_bool nbrListValid;
+ gnss_ha_ccp_pref_station_list_struct nbrList; /* provide information on the possible neighbour reference stations */
+
+ kal_bool durationValid;
+ gnss_ha_duration duration; /* specify the length of the continuous periodic assistance session */
+
+ kal_bool rateValid;
+ kal_uint8 rate; /* [1..64], specify the interval between the assistance data deliveries in seconds */
+
+ kal_bool refStationListValid;
+ gnss_ha_ccp_pref_station_list_struct refStationList; /* provide the locations of the reference stations for which CCP assistance is being provided */
+} gnss_ha_ccp_assist_common_ctrl_params_struct;
+
+
+typedef struct
+{
+ kal_uint16 transactionID;
+ gnss_ha_ccp_assist_common_type_enum type;
+ union
+ {
+ gnss_system_time_struct commParamsRefSysTime; /* define the CCP-specific common parameters (reference time) */
+ gnss_ha_ccp_assist_common_ctrl_params_struct ctrlParams; /* define the CCP-specific control parameters */
+ } data;
+} gnss_ha_common_ccp_assist_struct;
+/* end of gnss_ha_common_ccp_assist */
+
+
+/* begin of gnss_ha_req_ionospheric_model */
+typedef struct
+{
+ kal_uint8 ionoReq; /* specify which ionosphere models are being requested for, mapping to GNSS_HA_COMM_AD_REQ_IONO_BIT_* */
+
+ kal_bool reqBeginTimeValid;
+ gnss_system_time_struct reqBeginTime; /* specify the first time instant when an ionosphere model is needed, if absent, begin time is the current time */
+
+ gnss_ha_duration duration; /* specify for how long period the ionospheric model is requested */
+} gnss_ha_req_ionospheric_static_model_struct;
+
+
+typedef struct
+{
+ kal_bool durationValid;
+ gnss_ha_duration duration; /* specify the length of the continuous periodic assistance session */
+
+ kal_bool rateValid;
+ kal_uint8 rate; /* [0..64], specify the interval between the assistance data deliveries in seconds */
+} gnss_ha_req_ionospheric_periodic_model_struct;
+
+
+typedef struct
+{
+ gnss_ha_iono_model_type_enum type;
+ union
+ {
+ gnss_ha_req_ionospheric_static_model_struct staticModelReq; /* request for the one-shot ionosphere models */
+ gnss_ha_req_ionospheric_periodic_model_struct periodicWAIonoReq; /* request for periodic ionosphere models */
+ } data;
+} gnss_ha_req_ionospheric_model_struct;
+/* end of gnss_ha_req_ionospheric_model */
+
+
+/* begin of gnss_ha_req_troposphere_model */
+typedef struct
+{
+ kal_uint8 tropoModelReq; /* specify the desired model or models, mapping to GNSS_HA_COMM_AD_REQ_TROPO_BIT_* */
+
+ kal_bool supportMultiGridPoints; /* indicate if the target is requesting parameter sets originating from multiple locations around it (TRUE)
+ FALSE means that only the nearest grid point parameters are requested */
+
+ kal_bool reqBeginTimeValid;
+ gnss_system_time_struct reqBeginTime; /* specify the first time instant when a valid troposphere model is needed, if absent, the begin time is the current time */
+
+ gnss_ha_duration duration; /* specify how long time the tropospheric model is requested for */
+} gnss_ha_req_troposphere_model_struct;
+/* end of gnss_ha_req_troposphere_model */
+
+
+/* begin of gnss_ha_req_altitude_assist */
+typedef struct
+{
+ kal_bool reqBeginTimeValid;
+ gnss_system_time_struct reqBeginTime; /* specify the first time instant when altitude assistance is needed, if absent, the begin time is the current time */
+
+ kal_bool durationValid;
+ gnss_ha_duration duration; /* specify how long time the altitude assistance is requested for, if absent, altitude assistance is requested for the current moment */
+} gnss_ha_req_altitude_assist_struct;
+/* end of gnss_ha_req_altitude_assist */
+
+
+/* begin of gnss_ha_req_ccp_ctrl_params */
+typedef struct
+{
+ gnss_ha_high_accu_3d_position_struct reqRefStationLoc; /* request for a new reference station based on the position. The position may or may not be the target position */
+ gnss_ha_agnss_qor_type_enum qor; /* QoR (Quality-of-Reference station) defines how close to the requested location the closest reference station must be
+ In case the closest reference station is within the uncertainty area of the target location, the QoR parameter is neglected */
+} gnss_ha_req_ccp_pos_based_ref_station_struct;
+
+
+typedef struct
+{
+ kal_uint8 numRefStationIDElement;
+ kal_uint16 refStationIDElement[GNSS_HA_MAX_CCP_PREF_STATION_LIST_ELEMENT]; /* [0..65535], contain the reference station ID list */
+} gnss_ha_req_ccp_ref_station_list_struct;
+
+
+typedef struct
+{
+ gnss_ha_req_ccp_ref_station_type_enum type;
+ union
+ {
+ gnss_ha_req_ccp_pos_based_ref_station_struct posBasedRefStationReq;
+ gnss_ha_req_ccp_ref_station_list_struct idBasedRefStationReq; /* request for CCP AD for a new reference station based on the reference station ID */
+ gnss_ha_req_ccp_ref_station_list_struct refStationKillList; /* terminate CCP AD deliveries for selected reference stations based on their reference station IDs */
+ } data;
+} gnss_ha_req_ccp_ref_station_struct;
+
+
+typedef struct
+{
+ kal_bool durationValid;
+ gnss_ha_duration duration; /* specify the length of the continuous periodic assistance session */
+
+ kal_bool rateValid;
+ kal_uint8 rate; /* [1..64], specify the interval between the assistance data deliveries in seconds */
+
+ kal_bool refStationValid;
+ gnss_ha_req_ccp_ref_station_struct refStation; /* specify the request/modification of the active reference station set */
+} gnss_ha_req_ccp_common_req_struct;
+
+
+typedef struct
+{
+ kal_bool ccpSuppAreaReq; /* TRUE if request for the information on the CCP assistance availability in the target area */
+ kal_bool ccpNbrListReq; /* TRUE if request for the information on the reference stations in the vicinity of the target */
+
+ gnss_ha_req_ccp_common_req_struct ccpCommonRequest; /* request for a new reference station or stopping CCP AD delivery for a reference station */
+} gnss_ha_req_ccp_ctrl_params_struct;
+/* end of gnss_ha_req_ccp_ctrl_params */
+
+
+/* begin of gnss_ha_degradation_model */
+typedef struct
+{
+ kal_uint8 clockRMS0; /* specify the constant term of the clock model degradation model by cRMS0 =((1+0.1)^clockRMS0 -1) meters,
+ where clockRMS0 = 31 denotes 'Use At Own Risk', the range is [0, 16.45) meters, refer to OMA-TS-LPPe Appendix C.6.1 */
+ kal_bool clockRMS1Valid;
+ kal_uint8 clockRMS1; /* specify the first order term of the clock model degradation model, cRMS1, scale factor 2^(-14) m/s,
+ range [0, 4.3e-4) m/s, refer to OMA-TS-LPPe Appendix C.6.1 */
+} gnss_ha_clock_model_degrad_model_struct;
+
+
+typedef struct
+{
+ kal_uint8 orbitRMS0; /* specify the constant term of the orbit model degradation model by oRMS0 =((1+0.1)^orbitRMS0 -1) meters,
+ where orbitRMS0 = 31 denotes 'Use At Own Risk', the range is [0, 16.45) meters, refer to OMA-TS-LPPe Appendix C.6.2 */
+ kal_bool orbitRMS1Valid;
+ kal_uint8 orbitRMS1; /* specify the first order term of the orbit model degradation model, oRMS1, scale factor 2^(-14) m/s, range [0, 4.3e-4) m/s,
+ refer to OMA-TS-LPPe Appendix C.6.2 */
+} gnss_ha_orbit_model_degrad_model_struct;
+
+
+typedef struct
+{
+ kal_uint8 svID; /* [0..63], specify the SV for which degradation models are provided */
+ gnss_ha_clock_model_degrad_model_struct clockDegradationModel; /* provide the degradation model for the clock model */
+ gnss_ha_orbit_model_degrad_model_struct orbitDegradationModel; /* provide the degradation model for the orbit model */
+} gnss_ha_degrad_model_element_struct;
+
+
+typedef struct
+{
+ kal_uint16 transactionID;
+ MTK_GNSS_ID_ENUM gnssId;
+
+ kal_uint8 numDegradModelElement;
+ gnss_ha_degrad_model_element_struct degradModelElement[GNSS_HA_MAX_DEGRAD_MODEL_ELEMENT];
+} gnss_ha_generic_degradation_model_struct;
+/* end of gnss_ha_degradation_model */
+
+
+/* begin of gnss_ha_generic_ccp_assist */
+typedef struct
+{
+ gnss_ha_code_phase_err_type_enum type;
+ union
+ {
+ kal_uint8 codePhaseRMSError; /* contain the pseudorange RMS error value, representation refer to TS 36.355 floating-point representation of GNSS-MeasurementList field descriptions */
+ kal_uint8 cnr; /* carrier-to-noise ratio, scale factor 0.25 dB-Hz, range [0, 63.75] dB-Hz */
+ } data;
+} gnss_ha_code_phase_error_struct;
+
+
+typedef struct
+{
+ kal_uint8 svID; /* [0..63], identify the SV for which CCP assistance is being provided */
+
+ kal_bool intCodePhaseValid;
+ kal_uint8 intCodePhase; /* [0..255], indicate the integer milli-second part of the code phase */
+
+ kal_uint32 codePhase; /* [0.. 14989622], contain the sub-millisecond part of the code phase observation
+ for the particular satellite signal at the reference time, scale factor 0.02 meters, range [0, 299792.44] meters */
+
+ kal_bool codePhaseErrorValid;
+ gnss_ha_code_phase_error_struct codePhaseError; /* code phase error */
+
+ kal_int32 phaseRangeDelta; /* [-524288.. 524287], define the (Phase Range V Pseudorange), scale factor 0.5 mm, range [-262.144, 262.1435] meters */
+
+ kal_bool phaseRangeRMSErrorValid;
+ kal_uint8 phaseRangeRMSerror; /* [0..127], contain the RMS error of the continuous carrier phase, scale factor 2^(-10) meters, in the range [0, 0.12403) meters */
+
+ kal_bool lockIndicator; /* TRUE: if the carrier phase tracking has been continuous between the previous and the current assistance
+ data delivery. FALSE: a cycle slip has occurred */
+} gnss_ha_ccp_sv_element_struct;
+
+
+typedef struct
+{
+ kal_uint8 numCCPPerSVElement;
+ gnss_ha_ccp_sv_element_struct ccpPerSVElement[GNSS_HA_MAX_CCP_PER_SV_ELEMENT];
+} gnss_ha_ccp_per_sv_list_struct;
+
+
+typedef struct
+{
+ kal_uint8 signalID; /* indicate the signal id, map to GNSS_SGN_ID_VALUE_* */
+ gnss_ha_ccp_per_sv_list_struct ccpPerSVlist;
+} gnss_ha_ccp_per_signal_element_struct;
+
+
+typedef struct
+{
+ kal_uint8 numCCPPerSigElement;
+ gnss_ha_ccp_per_signal_element_struct ccpPerSigElement[GNSS_HA_MAX_CCP_PER_SIG_ELEMENT];
+} gnss_ha_ccp_per_signal_list_struct;
+
+
+typedef struct
+{
+ kal_uint16 refStationID; /* define the ID of the reference station to which the CCP assistance is provided */
+ gnss_ha_ccp_per_signal_list_struct ccpPerSignalList;
+} gnss_ha_ccp_generic_element_struct;
+
+
+typedef struct
+{
+ kal_uint16 transactionID;
+ MTK_GNSS_ID_ENUM gnssId;
+ kal_uint8 numCCPGenericElement;
+ gnss_ha_ccp_generic_element_struct ccpGenericElement[GNSS_HA_MAX_CCP_GENERIC_ELEMENT];
+} gnss_ha_generic_ccp_assist_struct;
+/* end of gnss_ha_generic_ccp_assist */
+
+
+/* begin of gnss_ha_req_ccp_generic_struct */
+typedef struct
+{
+ kal_uint8 ccpGnssSignalsReq; /* specify the GNSS signal types for which the CCP assistance is requested by the target device, GNSS Signal(s), map to GNSS_SGN_ID_BITMAP_* */
+} gnss_ha_req_ccp_generic_struct;
+/* end of gnss_ha_req_ccp_generic_struct */
+
+typedef struct
+{
+ MTK_GNSS_ID_ENUM gnssId;
+ //kal_bool waIonoSurfaceReq; /* TRUE if wide area ionosphere correction surface is requested for the SVs of this GNSS */
+ //gnss_ha_req_mechanics_struct mechanicsReq; /* request the SV mechanics information */
+ //gnss_ha_req_dcb_struct dcbReq; /* request the differential code biases to gain higher accuracy */
+ kal_bool degradModelReq; /* TRUE if request the accuracy models for the SV orbit and clock models to get a better understanding of the accuracy of the computed position */
+ gnss_ha_req_ccp_generic_struct ccpAssistGenericReq; /* request for the CCP reference assistance data for high accuracy */
+ //gnss_ha_req_nav_model_struct navigationModelReq; /* TBD. request for the navigation models defined in LPPe */
+
+} gnss_ha_generic_assist_struct;
+
+typedef struct
+{
+ kal_uint16 transactionID;
+
+ /* Common assistance data*/
+ kal_bool ionoModelReqValid;
+ gnss_ha_req_ionospheric_model_struct ionoModelReq; /* request for ionosphere models */
+
+ kal_bool tropoModelReqValid;
+ gnss_ha_req_troposphere_model_struct tropoModelReq; /* request troposphere models */
+
+ kal_bool altAssistReqValid;
+ gnss_ha_req_altitude_assist_struct altAssistReq; /* request altitude assistance for improved availability */
+
+ kal_bool solarRadReq; /* TRUE if request the solar radiation intensity */
+
+ kal_bool ccpCtrlParamsReqValid;
+ gnss_ha_req_ccp_ctrl_params_struct ccpCtrlParamsReq; /* request for the control parameters of the CCP AD session.*/
+
+ /* Generic assistance data */
+ kal_uint8 numGnssSupport;
+ gnss_ha_generic_assist_struct genericAssistReq[16];
+} gnss_ha_assist_data_request_ind_struct;
+
+typedef struct
+{
+ kal_int32 type; /* refer to agps_md_huge_data_type */
+} gnss_ha_assist_ack_struct;
+
+typedef struct
+{
+ unsigned int u4_lppe_assis_data_bitmap;
+ gnss_ha_ionospheric_static_model_struct *ionospheric_static_model;
+ gnss_ha_ionospheric_periodic_model_struct *ionospheric_periodic_model;
+ gnss_ha_common_troposphere_model_struct *troposphere_model;
+ gnss_ha_common_altitude_assist_struct *altitude_assist;
+ gnss_ha_common_solar_radiation_struct *solar_radiation;
+ gnss_system_time_struct *ccp_specific_common_para_ref_time;
+ gnss_ha_ccp_assist_common_ctrl_params_struct* ctrlParams;
+ gnss_ha_generic_ccp_assist_struct *ccp_generic_assist_struct;
+ gnss_ha_generic_degradation_model_struct *generic_degradation_model;
+} gnss_lppe_database;
+typedef struct
+{
+ /*LPPE_enabled is for agent to management lppe assistant data, can be setted by driver*/
+ kal_uint8 LPPE_enabled;
+ /*ionospher must choose one, can't require both according to spec*/
+ kal_bool prefer_ionospheric_static_model;
+ /*common ccp must choose one, can't require both according to spec*/
+ kal_bool prefer_ccp_common_ctrl_params;
+}agent_lppe_config;
+
+
+
+/*for PMTK763*/
+typedef struct
+{
+ kal_uint8 adrRMSerror;
+ kal_bool lockIndicator;
+}gnss_ha_Measure_struct;
+
+
+/*for PMTK761*/
+
+typedef struct
+{
+ kal_uint8 cep; /* [0..255] */
+ kal_uint8 confidenceHorizontal; /* [0..99] */
+ kal_uint8 confidenceVertical; /* [0..99] */
+} gnss_ha_3Dposition_struct;
+typedef struct
+{
+ kal_uint16 eastComponent; /* [0..511] */
+ kal_uint16 northComponent; /* [0..511] */
+ kal_uint16 upComponent; /* [0..511] */
+ kal_uint8 cepV; /* [0..255] */
+ kal_uint8 uncertaintySemiMajor; /* [0..255] */
+ kal_uint8 uncertaintySemiMinor; /* [0..255] */
+ kal_uint8 offsetAngle; /* [0..179] */
+ kal_uint8 confidenceHorizontal; /* [0..99] */
+ kal_uint8 uncertaintyUpComponent; /* [0..255] */
+ kal_uint8 confidenceUp; /* [0..99] */
+} gnss_ha_3Dvelocity_struct;
+
+enum
+{
+ EPO_CUR_FILE_SMPHR = 0,
+ EPO_NEW_FILE_SMPHR,
+ QEPO_CUR_FILE_SMPHR = 2,
+ QEPO_NEW_FILE_SMPHR,
+ QEPO_BD_CUR_FILE_SMPHR = 4,
+ QEPO_BD_NEW_FILE_SMPHR,
+ MTKNAV_CUR_FILE_SMPHR = 6,
+ MTKNAV_NEW_FILE_SMPHR,
+ QEPO_GA_CUR_FILE_SMPHR = 8,
+ QEPO_GA_NEW_FILE_SMPHR,
+ MTK_SYS_SEMAPHORE_NUM_FOR_EPO
+};
+
+
+/*below used for GNSS MD Time aiding*/
+
+#define GNSS_TC_RX_STATE_INVALID 0 /* Invalid value, default value */
+#define GNSS_TC_RX_STATE_IDLE 1 /* Indicate rx idle state */
+#define GNSS_TC_RX_STATE_CONNECT 2 /*Indicate rx connect state */
+#define GNSS_TC_RX_STATE_OUTOFSYNC 3 /* Indicate radio link fail scenario */
+
+
+/* To avoid AP modem alignment issue */
+
+#pragma pack(push)
+
+#pragma pack(8)
+
+typedef struct{
+ kal_uint64 timeinfo_utc; /*Follow 38.331, counts the number of UTC seconds in 10 ms units since 00:00:00 on Gregorian calendar date 1 January, 1990. */
+ kal_uint8 dayLightSavingTime[2]; /* Indicate if and how daylight-saving time is applied to obtain the local time */
+ kal_uint8 is_leap_seconds_valid; /* Indicate the validity of leap_sconds */
+ kal_int16 leap_seconds; /* Number of leap seconds offset between GPS Time and UTC */
+ kal_int16 localTimeOffset; /* Offset between UTC and local time in units of 15 minutes.*/
+ kal_uint64 sib_time_diff; /* Time diff between pulse GPS timing and SIB frame boundary.Unit: microseconds */
+} gnss_tc_utc_time_struct;
+
+
+typedef struct{
+ kal_uint16 md_cellHandOverNumber; /* 0...65535. Number of handovers UE experienced from cell which UE received the latest time synchronization information to the cell UE camp on currently */
+ kal_uint64 md_absTimeOrigin; /* 0...0xFFFFFFFFFFFFFFFF (milli-sec). MD abs-time with 64 bit corresponding to the latest GNSS timing feedback. (Used by LTE and NR) */
+ kal_uint64 md_absTimeStart; /* MD abs-time with 64 bit corresponding to start time of current cell UE camp on. (Used by LTE and NR) */
+ kal_uint64 md_absTimeTrigger; /* MD abs-time with 64 bit corresponding to the HW pulse.(Used by LTE and NR) */
+ kal_uint16 md_eNobeFreqDrift; /* 0...65535 (unit: 0.001ppm). This field specifies the maximum frequency bias of base station defined in 3GPP spec for each RAT. For LTE: 0.05ppm, NR: 0.05ppm */
+} md_cellUncertainty_struct;
+
+
+typedef struct{
+ kal_uint8 gnss_timeID; /* refer to GNSS_TC_TIMEID_* */
+ kal_uint16 gnss_dayNumber; /* 0...32767 (Day) */
+ kal_uint32 gnss_timeOfDay; /* 0...86399 sec */
+ kal_uint32 gnss_timeOfDayFrac_nsec; /* 0...999999999 nano-sec */
+ kal_uint8 gnss_leapSecond; /* 0...255 sec */
+} gnss_timeOfDay_struct;
+
+
+typedef struct {
+ //kal_uint8 fix_type;
+ gnss_timeOfDay_struct tod;
+ kal_uint32 uncertainty;
+} gnss_timeOfDay_with_unc;
+
+
+typedef struct
+{
+ kal_uint16 gnss_weekNum; /* unit: Week */
+ kal_uint32 gnss_timeOfWeek_ms; /* 0...604800000, unit: ms */
+ kal_uint32 gnss_timeOfWeek_subms_picosec; /* 0...999999999, uint: pico-sec */
+} gnss_timeOfWeek_struct;
+
+
+
+typedef struct{
+ kal_uint16 tac; /* 0...65535 */
+ kal_uint16 mnc; /* 0...999 */
+ kal_uint16 mcc; /* 0...999 */
+ kal_uint32 cellId; /* 0...0x0FFFFFFF */
+ kal_uint8 is_2_digit_mnc; /* refer to GNSS_TC_BIT_* (0...1)*/
+} globalCellId_struct;
+
+
+typedef struct
+{
+ kal_uint16 mnc; /* 0...999 */
+ kal_uint16 mcc; /* 0...999 */
+ kal_uint8 cellId[5]; /* The parameter is bit string of 36 bits. The MSB of 'cell_identity[0]' is the first bit of the bit string, and so on */
+ kal_uint8 is_2_digit_mnc; /* refer to GNSS_TC_BIT_* (0...1)*/
+} nrGlobalCellId_struct;
+
+typedef struct
+{
+ kal_uint8 ratMode; /* refer to GNSS_TC_RAT_* */
+ kal_uint8 isGciAvailable; /* refer to GNSS_TC_BIT_* (0: not available. 1: available.) */
+ globalCellId_struct globalCellId;
+ kal_uint8 isNrGciAvailable; /* refer to GNSS_TC_BIT_* (0: not available. 1: available.) */
+ nrGlobalCellId_struct nrGlobalCellId;
+ kal_uint8 isPciAvailable; /* refer to GNSS_TC_BIT_* (0: not available. 1: available.) */
+ kal_uint16 phyCellId; /* LTE = 0...503. NR = 0...1007 */
+ kal_uint8 isPscAvailable; /* refer to GNSS_TC_BIT_* (0: not available. 1: available.)*/
+ kal_uint16 psc; /* 0...512 */
+ kal_uint8 rxStatus; /* refer to GNSS_TC_RX_STATE_*. Indicate EL1 and NL1 rx status */
+} md_cellId_struct;
+
+
+typedef struct{
+ kal_uint16 md_frame_number; /* 0...1023 (10 milli-sec). The Frame number of target cells corresponding to the HW pulse (Used by LTE)*/
+ kal_uint8 md_subframe_number; /* 0...9 (milli-sec). The sub-frame number of target cells corresponding to the HW pulse (Used by LTE) */
+} md_sf_time_lte_struct;
+
+typedef struct{
+ kal_uint16 md_frame_number; /* 0...1023 (10 milli-sec). The Frame number of target cells corresponding to the HW pulse (Used by NR) */
+ kal_uint8 md_subframe_number; /* 0...9 (milli-sec). The sub-frame number of target cells corresponding to the HW pulse (Used by NR) */
+} md_sf_time_nr_struct;
+
+
+typedef struct{
+ kal_uint8 ratModeType; /* refer to GNSS_TC_RAT_* */
+ md_sf_time_lte_struct md_sf_time_lte;
+ md_sf_time_nr_struct md_sf_time_nr; /* [TBD] md_sf_time_wcdma_struct md_sf_time_wcdma; */
+} md_frameInformation_struct;
+
+typedef struct{
+ kal_uint8 md_propogationDelay_valid; /* refer to GNSS_TC_BIT_* (0: the PropogationDelay is not valid. 1: the PropogationDelay is valid.) */
+ kal_uint32 md_currentPropogationDelay; /* 0...4294967295 nano-sec. Propagation delay time(UINT32) from a particular cell to UE. Use Time advance to determine (equal to 1/2 TA) */
+ kal_uint64 md_absTimeOfPropogationDelay; /* MD abs-time with 64 bit corresponding to md receiving md-CurrentPropogationDelay. (Used by LTE and NR) */
+ kal_uint32 md_propogationDelayUncertainty; /* 0...4294967295 nano-sec. This filed specifis the uncertainty caused by the resolution of propogation delay */
+} md_propagationInformation_struct;
+
+typedef struct{
+ kal_uint32 md_hwInferfaceUncertainty; /* 0...4294967295 nano-sec. The fields specifies the uncertainty caused by the HW interface between MD and GNSS and the uc */
+ kal_uint64 md_subframeboundary; /* 0...0xFFFFFFFFFFFFFFFF subframe boundary corresponding to HW pulse triggered */
+ kal_uint32 md_scntToFrcFractionalPart; /* 0...0Xffffffff fractional part due to scnt convert to FRC. For Marga and after Marga, this value is 0. unit:nano-sec */
+ md_propagationInformation_struct md_propagationInfo;
+} md_pulseInformation_struct;
+
+
+
+typedef struct{
+ kal_uint8 md_cellInfo_Valid; /* 0: the cell-Information is not valid. 1: the cell-information is valid */
+ md_cellId_struct md_cellId;
+ md_pulseInformation_struct md_pulseInfo;
+ md_frameInformation_struct md_frameInfo;
+ md_cellUncertainty_struct md_cellUncertainty;
+} cell_information_struct;
+
+typedef struct{
+ kal_uint8 gnss_timeInfo_valid; /* 0: the GNSS-TimeInformation is not valid. 1: the GNSS-TimeInformation is valid. */
+ kal_uint8 time_info_source; /* 0: reserved. 1: LTE SIB8. 2: LTE SIB16. 3: NR SIB9. 4-7: reserved. 8: reserved for GSM - GNSS fine time.
+ 9: reserved for WCDMA - GNSS fine time. 10: reserved for TD-SCDMA - GNSS fine time. 11: reserved for CDMA2000 - GNSS fine time.
+ 12: LTE - GNSS fine time. 13: NR FR1 - GNSS fine time. 14: reserved for NR FR2-GNSS fine time.15: reserved */
+ kal_uint8 time_infoType; /* 1: TOD time, 2: TOW time, 3: UTC time; refer to GNSS_TC_TIMETYPE_ . Indicate which time format is used */
+ gnss_timeOfDay_struct gnss_tod;
+ gnss_timeOfWeek_struct gnss_tow;
+ gnss_tc_utc_time_struct utc_time;
+ kal_uint32 gnss_timeUncertainty; /* 0...4294967295 nano-sec */
+} gnss_timeInformation_struct;
+
+typedef enum {
+ MD_TIME_REQUIRE_STOP = 0,
+ MD_TIME_REQUIRE_START = 1,
+ MD_TIME_REQUIRE_TESTMODE = 2
+} md_time_require_action;
+
+//#define MD_TIME_UT "MD_TIME_UT"
+/*MNL->MD MNL request MD time aiding*/
+typedef struct{
+ kal_uint16 transactionID; /* 0...65535 */
+ kal_uint8 ctrlFlag; /* 0: Disable/request to STOP. 1: Enable/request to START. 2: Test Mode Enable */
+ kal_uint32 pulsePeriod; /* 100~300000 msec, effective when ctrlFlag:2 */
+ kal_uint16 pulseNumber; /* 0,1~7200. 0: Periodic mode, 1~7200 none-Periodic Number of pulse */
+} mnl_md_time_sync_req_struct;
+
+/*MNL->MD used for MNLD to MD ack*/
+typedef struct{
+ kal_uint16 transactionID; /* 0...65535 */
+} mnl_md_time_sync_rsp_struct;
+
+/*MNL->MD used for MNLD send back time to MD*/
+typedef struct{
+ kal_uint16 transactionID; /* 0...65535 */
+ cell_information_struct cell_info;
+ gnss_timeInformation_struct gnss_timeInfo;
+} mnl_md_time_info_rsp_struct;
+
+/*MD->MNL used for MD to MNL ack*/
+typedef struct{
+ kal_uint16 transactionID; /* 0...65535 */
+} mnl_md_time_sync_cnf_struct;
+
+/*MD->MNL Time sync*/
+typedef struct{
+ kal_uint16 transactionID; /* 0...65535 */
+ cell_information_struct cell_info;
+ gnss_timeInformation_struct gnss_timeInfo;
+} mnl_md_time_sync_ind_struct;
+
+typedef struct{
+ INT32 fix_type; // Fix tpye, 1:no fix 2:2D 3:3D
+ double latitude; // Latitude (degree)
+ double longitude; //Longitude (degree)
+ double altitude; //Height Mean Sea Level (m)
+ float speed; //2D ground speed (m/s)
+ float heading; //track angle (deg)
+ float h_acc; //Position Accuracy in Horizontal Direction [m]
+ double h_err_majoraxis; //semi-major axis of error ellipse [m]
+ double h_err_minoraxis; //semi-minor axis of error ellipse [m]
+ double h_err_angle; //bearing of the semi-major axis [degrees]
+ float hor_conf; //Horizontal confidence in meter with 1-sigma accuracy
+ float pdop; //position dilution of precision
+ float hdop; //Horizontal dilution of precision
+ float vdop; //Vertical dilution of precision
+ MTK_GPS_TIME utc_time; //UTC time information
+}mtk_geofence_position_info;
+
+#pragma pack(pop) /* Restore the alignment configuration */
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* MTK_GPS_TYPE_H */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/src/mnl_simulator.c b/src/connectivity/gps/2.0/mtk_mnld/mnl/src/mnl_simulator.c
new file mode 100644
index 0000000..a328e50
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/src/mnl_simulator.c
@@ -0,0 +1,265 @@
+#include "mtk_gps.h"
+#include "mtk_gps_type.h"
+#include "mtk_gps_sys_fp.h"
+//#include "mtk_gps_sys_fp_macro.h"
+#include "mtk_lbs_utility.h"
+#include<time.h>
+#include<sys/time.h>
+#include<errno.h>
+
+#define MNL_START_TIME 500
+#define MNL_NMEA_INTERVAL 1000
+#define MNL_STOP_TIME 500
+
+extern INT32 mtk_gps_sys_agps_disaptcher_callback(UINT16 type, UINT16 length, char *data);
+extern INT32 mtk_gps_sys_gps_mnl_callback(MTK_GPS_NOTIFICATION_TYPE msg);
+extern INT32 mtk_gps_sys_nmea_output_to_mnld(const char * buffer, UINT32 length);
+
+static void mnl_start_done();
+static void mnl_nmea_report();
+static void mnl_stop_done();
+
+timer_t mnl_open_timer;
+timer_t mnl_nmea_timer;
+//timer_t mnl_close_timer;
+
+MTK_GPS_SYS_FUNCTION_PTR_T mnl_cb_func;
+
+static void mnl_start_done() {
+ char i1Assist_Req = 0;
+ mtk_gps_sys_agps_disaptcher_callback(MTK_AGPS_CB_START_REQ, 1, &i1Assist_Req);
+
+ start_timer(mnl_nmea_timer, MNL_START_TIME);
+}
+
+int gNmeaCount = 0;
+static void mnl_nmea_report() {
+ #define NMEA_BUFFER_LEN 10*1024
+ int ret = 0;
+ char buffer_not_fix[NMEA_BUFFER_LEN] = {"$GNGGA,092152.975,3032.4269,N,10403.7720,E,0,0,,534.9,M,-31.9,M,,*79\r\n$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,1.00*01\r\n$GPGSV,3,1,10,06,65,337,,19,61,033,,17,52,071,,02,37,268,*7A\r\n$GNRMC,092152.975,V,3032.4269,N,10403.7720,E,0.000,0.00,260617,,,N*55\r\n$GNACCURACY,7.1*10\r\n"};
+ char nmea_fixed[NMEA_BUFFER_LEN] = {"$GNGGA,065826.000,2446.3072,N,12101.2991,E,1,22,0.52,115.1,M,15.1,M,,*79\r\n$GNGSA,A,3,15,21,10,12,13,,,,,,,,0.88,0.52,0.71,1*07\r\n$GNGSA,A,3,71,72,80,70,86,,,,,,,,0.88,0.52,0.71,2*01\r\n$GNGSA,A,3,12,01,04,33,,,,,,,,,0.88,0.52,0.71,3*04\r\n$GNGSA,A,3,12,37,22,35,08,09,38,,,,,,0.88,0.52,0.71,4*0E\r\n$GNGSA,A,3,195,,,,,,,,,,,,0.88,0.52,0.71,5*39\r\n$GPGSV,3,1,11,24,77,159,,21,51,290,20.1,15,48,024,11.7,20,33,321,,1*69\r\n$GPGSV,3,2,11,05,21,106,,13,19,046,14.1,12,10,151,19.0,29,09,211,,1*67\r\n$GPGSV,3,3,11,10,08,310,17.9,32,02,256,,51,,,,1*78\r\n$GPGSV,1,1,3,26,83,193,45.2,03,35,296,39.5,32,34,120,38.3,7*72\r\n$GLGSV,2,1,8,73,49,093,,71,39,015,10.7,86,37,246,28.4,72,24,317,11.8,1*5A\r\n$GLGSV,2,2,8,87,21,312,,70,18,068,12.3,80,12,033,16.9,85,10,192,,1*4F\r\n$GAGSV,3,1,12,18,52,000,,19,52,000,,12,47,266,5.0,20,37,109,,7*54\r\n$GAGSV,3,2,12,21,37,109,,32,35,195,,33,35,195,8.7,04,26,289,18.3,7*49\r\n$GAGSV,3,3,12,01,21,166,16.9,27,17,055,,10,15,316,,11,15,316,,7*61\r\n$GAGSV,1,1,3,12,47,266,20.0,33,35,195,16.0,04,26,289,12.9,1*6D\r\n$BDGSV,6,1,24,18,69,334,,13,66,241,,38,61,203,,06,60,333,,1*7D\r\n$BDGSV,6,2,24,03,59,204,,16,57,319,,08,54,188,11.0,01,53,142,,1*66\r\n$BDGSV,6,3,24,39,49,195,,59,49,136,,09,48,286,14.8,36,44,171,,1*61\r\n$BDGSV,6,4,24,02,40,242,,04,38,118,,20,29,079,,35,26,247,18.9,1*6E\r\n$BDGSV,6,5,24,22,25,310,11.9,57,22,273,,07,19,169,,05,17,259,,1*6A\r\n$BDGSV,6,6,24,29,14,196,,12,13,299,12.9,37,12,041,13.6,10,06,191,,1*72\r\n$BDGSV,1,1,2,38,61,203,11.7,35,26,247,22.3,4*48\r\n$QZGSV,1,1,4,199,83,359,,193,66,053,,194,49,131,,195,17,170,19.0,1*5D\r\n$GNRMC,065826.000,A,2446.3072,N,12101.2991,E,0.000,0.00,181019,,,A,V*37\r\n$GNVTG,0.00,T,,M,0.000,N,0.000,K,A*23\r\n$PMTKTSX1,323163,-16493.935,42.431,40.172,55ae0000,-1.664871,-1.649394,-0.250522,-0.273268,0.600247,-1.622,1.0*5E\r\n$PMTKGEPH,32,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1*35\r\n$PMTKGALM,31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1*2A\r\n$GNACCURACY,2.5,163.6,1.6,25.4*25\r\n"};
+ char log_time[NMEA_BUFFER_LEN];
+ time_t tm;
+ struct tm *p = NULL;
+ char *gps_debuglog_file_name_format_str;
+
+ if (time(&tm)==((time_t)-1)) {
+ LOGE("time() fail(%s)!!\r\n", strerror(errno));
+ }
+ p = localtime(&tm);
+
+ if(p == NULL) {
+ LOGE("Get localtime fail:[%s]%d", strerror(errno), errno);
+ }
+
+ mtk_gps_sys_gps_mnl_callback(MTK_GPS_MSG_FIX_READY);
+
+ gps_debuglog_file_name_format_str = "[%04d_%02d%02d_%02d%02d%02d]";
+ memset(log_time, 0x00, sizeof(log_time));
+ MNLD_SNPRINTF(log_time, sizeof(log_time), gps_debuglog_file_name_format_str,
+ 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday,
+ p->tm_hour, p->tm_min, p->tm_sec);
+ if(mnl_cb_func.sys_alps_gps_dbg2file_mnld != NULL) {
+ mnl_cb_func.sys_alps_gps_dbg2file_mnld(log_time, strlen(log_time));
+ }
+ if(gNmeaCount++ < 3) {
+ int length = strlen(buffer_not_fix);
+ mtk_gps_sys_nmea_output_to_mnld(buffer_not_fix, length);
+ if(mnl_cb_func.sys_alps_gps_dbg2file_mnld != NULL) {
+ mnl_cb_func.sys_alps_gps_dbg2file_mnld(buffer_not_fix, strlen(buffer_not_fix));
+ }
+ } else {
+ int length = strlen(nmea_fixed);
+ mtk_gps_sys_nmea_output_to_mnld(nmea_fixed, length);
+ if(mnl_cb_func.sys_alps_gps_dbg2file_mnld != NULL) {
+ mnl_cb_func.sys_alps_gps_dbg2file_mnld(nmea_fixed, strlen(nmea_fixed));
+ }
+ }
+
+ ret = start_timer(mnl_nmea_timer, MNL_NMEA_INTERVAL);
+ LOGD("start_timer ret:%d, gNmeaCount:%d", ret, gNmeaCount);
+}
+
+static void mnl_stop_done() {
+
+}
+
+MTK_GPS_BOOT_STATUS
+mtk_gps_mnl_run(const MTK_GPS_INIT_CFG* default_cfg, const MTK_GPS_DRIVER_CFG* driver_dfg) {
+ mnl_open_timer = init_timer(mnl_start_done);
+ mnl_nmea_timer = init_timer(mnl_nmea_report);
+ //mnl_close_timer = init_timer(mnl_stop_done);
+ start_timer(mnl_open_timer, MNL_START_TIME);
+ gNmeaCount = 0;
+
+ return MNL_INIT_SUCCESS;
+}
+
+void
+mtk_gps_mnl_stop(void) {
+ LOGD("");
+ stop_timer(mnl_open_timer);
+ stop_timer(mnl_nmea_timer);
+}
+
+INT32
+mtk_gps_set_param(MTK_GPS_PARAM key, const void* value) {
+ start_timer(mnl_open_timer, MNL_START_TIME);
+ return 0;
+}
+
+INT32
+mtk_gps_get_param(MTK_GPS_PARAM key, void* value) {
+ return 0;
+}
+
+INT32
+mtk_gps_get_mnl_info(MTK_GPS_MNL_INFO* lib_info) {
+ return 0;
+}
+
+void mtk_gps_mnl_create_dbg_port(UINT32 port_num) {
+
+}
+
+INT32 mtk_gps_delete_nv_data(UINT32 assist_data_bit_map) {
+ return 0;
+}
+
+INT32 mtk_gps_inject_ntp_time(MTK_GPS_NTP_T* ntp) {
+ return 0;
+}
+
+INT32 mtk_gps_inject_nlp_location(MTK_GPS_NLP_T* nlp) {
+ return 0;
+}
+
+void
+mtk_gnss_get_measurement(Gnssmeasurement GpQzMeasurement[MTK_GPS_SV_MAX_PRN+MTK_QZS_SV_MAX_PRN], Gnssmeasurement GloMeasurement[MTK_GLON_SV_MAX_NUM],
+Gnssmeasurement BDMeasurement[MTK_BEDO_SV_MAX_NUM], Gnssmeasurement GalMeasurement[MTK_GLEO_SV_MAX_NUM],Gnssmeasurement SBASMeasurement[MTK_SBAS_SV_MAX_NUM],
+INT8 GpQz_Ch_Proc_Ord_PRN[MTK_GPS_SV_MAX_PRN+MTK_QZS_SV_MAX_PRN],INT8 Glo_Ch_Proc_Ord_PRN[MTK_GLON_SV_MAX_NUM],INT8 BD_Ch_Proc_Ord_PRN[MTK_BEDO_SV_MAX_NUM],
+INT8 Gal_Ch_Proc_Ord_PRN[MTK_GLEO_SV_MAX_NUM],INT8 SBAS_Ch_Proc_Ord_PRN[MTK_SBAS_SV_MAX_NUM]) {
+
+}
+
+INT32
+mtk_gnss_get_clock(Gnssclock *GnssClock){
+ return 0;
+}
+
+INT32
+mtk_gnss_get_navigation_event (GnssNavigationmessage *NavEvent, UINT8 SVID, UINT8 SV_type){
+ return 0;
+}
+
+UINT16
+mtk_gps_set_mpe_info(UINT8 *msg){
+ return 0;
+}
+
+int
+mtk_gps_mnl_mpe_callback_reg(MPECallBack *name){
+ return 0;
+}
+
+INT32
+mtk_gps_set_debug_type(const UINT8 debug_type){
+ return 0;
+}
+
+INT32
+mtk_gps_get_position_accuracy(double *Lat, double *Lon, int *accuracy){
+ return 0;
+}
+
+void
+mtk_gps_mnl_get_sensor_info(UINT8 *msg, int len){}
+
+void
+mtk_gps_mnl_set_sensor_info(UINT8 *msg, int len){}
+
+int
+mtk_gps_mnl_trigger_mpe(void) {
+ return 0;
+}
+
+INT32 mtk_agps_agent_qepo_file_update() {
+ return 0;
+}
+
+INT32 mtk_agps_agent_mtknav_file_update() {
+ return 0;
+}
+
+INT32 mtk_gps_ofl_set_option(UINT32 cfg_bitmask) {
+ return 0;
+}
+
+INT32 mtk_gps_ofl_set_user(UINT32 user_bitmask) {
+ return 0;
+}
+
+INT32 mtk_gps_ofl_rst_stpgps_begin_ntf() {
+ return 0;
+}
+
+INT32 mtk_gps_ofl_send_flp_data(UINT8 *buf, UINT32 len) {
+ return 0;
+}
+
+INT32 mtk_gps_flp_get_location(void *buf, UINT32 buf_len, UINT32 *p_get_len) {
+ return 0;
+}
+
+UINT32 mtk_gps_log_line_enc_inplace(char *buffer, UINT32 length) {
+ return 0;
+}
+
+unsigned char mtk_gps_get_MNL_Config_XML_param (char MNL_Config_File_Path[], MTK_GPS_MNL_CONFIG_XML_PARAM *mnl_config_xml) {
+ return 0;
+}
+
+void mtk_gps_set_MNL_Config_XML_param (char MNL_Config_File_Path[], MTK_GPS_MNL_CONFIG_XML_PARAM *mnl_config_xml){}
+
+INT32
+mtk_agps_set_param (MTK_GPS_PARAM key, const void* value, UINT16 srcMod, UINT16 dstMod) {
+ return 0;
+}
+
+INT32
+mtk_agps_set_param_with_payload_len (MTK_GPS_PARAM key, const void* value, UINT16 srcMod, UINT16 dstMod, int len) {
+ return 0;
+}
+
+INT32
+mtk_agps_agent_epo_file_update() {
+ return 0;
+}
+
+INT32
+mtk_agps_agent_qepo_bd_file_update() {
+ return 0;
+}
+
+INT32
+mtk_agps_agent_qepo_ga_file_update() {
+ return 0;
+}
+
+INT32
+mtk_agps_agent_qepo_get_rqst_time(UINT16 *wn, UINT32 *tow, UINT32 *sys_time) {
+ return 0;
+}
+
+//int SUPL_encrypt(unsigned char *plain, unsigned char *cipher, unsigned int length) {}
+//int SUPL_decrypt(unsigned char *plain, unsigned char *cipher, unsigned int length) {}
+INT32
+mtk_gps_sys_function_register (MTK_GPS_SYS_FUNCTION_PTR_T *fp_t) {
+ mnl_cb_func.sys_alps_gps_dbg2file_mnld = fp_t->sys_alps_gps_dbg2file_mnld;
+ return 0;
+}
+
+INT32 mtk_gps_geofence_get_position (mtk_geofence_position_info* pos_data)
+{
+ return -1;
+}
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl/src/pseudo_mnl.c b/src/connectivity/gps/2.0/mtk_mnld/mnl/src/pseudo_mnl.c
new file mode 100644
index 0000000..8b5bdca
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl/src/pseudo_mnl.c
@@ -0,0 +1,282 @@
+#include <errno.h> /* Error number definitions */
+#include <fcntl.h>
+#include <stdio.h> /* Standard input/output definitions */
+#include <string.h> /* String function definitions */
+#include <unistd.h> /* UNIX standard function definitions */
+#include <sys/ioctl.h>
+#include <time.h>
+
+#if defined(__ANDROID_OS__)
+#include <cutils/properties.h>
+#include <cutils/android_filesystem_config.h>
+#endif
+
+#include "mtk_prop_util.h"
+#include "mtk_gps_sys_fp.h"
+#include "nmea_parser.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_gps_agps.h"
+#include "gps_dbg_log.h"
+#include "mnld_utile.h"
+
+#include "mtk_mnld_log.h"
+
+// for read NVRAM
+#if MTK_GPS_NVRAM
+#include "libnvram.h"
+#include "CFG_GPS_File.h"
+#include "CFG_GPS_Default.h"
+#include "CFG_file_lid.h"
+#include "Custom_NvRam_LID.h"
+#endif
+#include "SUPL_encryption.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "pseudo"
+
+// #define LIB_MQUEUE
+
+#define MAX_RETRY_COUNT 20
+#define PMTK_FS_REQ_MEAS 736
+#define PMTK_FRAME_TIME_ACK 737
+#define PMTK_FS_SLEEPMODE 738
+#define MTK_GPS_HIDE_PRINT_MAX 17
+
+#if defined(LIB_MQUEU)
+// message queue file descriptor
+static mqd_t mnl_agps_mq_fd = -1;
+struct mq_attr mnl_agps_mq_attr;
+#endif
+
+MTK_GPS_BOOL enable_dbg_log = MTK_GPS_TRUE;
+
+// for read NVRAM
+#if MTK_GPS_NVRAM
+extern ap_nvram_gps_config_struct stGPSReadback;
+extern int gps_nvram_valid;
+#if ANDROID_MNLD_PROP_SUPPORT
+char nvram_init_val[PROPERTY_VALUE_MAX];
+#else
+char nvram_init_val[100];
+#endif
+#endif
+int mtk_gps_sys_init() {
+#if MTK_GPS_NVRAM
+ F_ID gps_nvram_fd;
+ int file_lid = AP_CFG_CUSTOM_FILE_GPS_LID;
+#endif
+ int rec_size;
+ int rec_num;
+ int read_nvram_ready_retry = 0;
+ int ret;
+ /* create message queue */
+#if defined(LIB_MQUEUE)
+ mnl_agps_mq_attr.mq_maxmsg = 72;
+ mnl_agps_mq_attr.mq_msgsize = sizeof(MTK_GPS_AGPS_AGENT_MSG);
+ mnl_agps_mq_attr.mq_flags = 0;
+ mnl_agps_mq_fd = mq_open(MNL_AGPS_MQ_NAME, O_CREAT|O_RDWR|O_EXCL, PMODE, &mnl_agps_mq_attr);
+
+ if (mnl_agps_mq_fd == -1) {
+ LOGD("Fail to create mnl_agps_msg_queue, errno=%s\n", strerror(errno));
+ if (errno == EEXIST) {
+ LOGD("mnl_agps_msg_queue already exists, unlink it now ...\n");
+ mq_unlink(MNL_AGPS_MQ_NAME);
+ }
+ return MTK_GPS_ERROR;
+ }
+#else
+#endif
+#if MTK_GPS_NVRAM
+ //LOGD("Start to read nvram");
+ while (read_nvram_ready_retry < MAX_RETRY_COUNT) {
+ read_nvram_ready_retry++;
+ #if ANDROID_MNLD_PROP_SUPPORT
+ property_get("vendor.service.nvram_init", nvram_init_val, NULL);
+ if (strcmp(nvram_init_val, "Ready") == 0 || strcmp(nvram_init_val, "Pre_Ready") == 0) {
+ LOGD("nvram_init_val Ready");
+ break;
+ } else {
+ LOGD("nvram_init_val not Ready,sleep 500ms");
+ usleep(500*1000);
+ }
+ #endif
+ }
+ //LOGD("Get nvram restore ready retry cc=%d\n", read_nvram_ready_retry);
+ if (read_nvram_ready_retry >= MAX_RETRY_COUNT) {
+ LOGD("Get nvram restore ready faild, return\n");
+ return MTK_GPS_ERROR;
+ }
+
+ memset(&stGPSReadback, 0, sizeof(stGPSReadback));
+
+ gps_nvram_fd = NVM_GetFileDesc(file_lid, &rec_size, &rec_num, ISREAD);
+ if (gps_nvram_fd.iFileDesc >= 0) {
+ ret = read(gps_nvram_fd.iFileDesc, &stGPSReadback , rec_size*rec_num);
+ if (ret < 0){
+ LOGW("Read GPS NVRam Fail");
+ }
+ NVM_CloseFileDesc(gps_nvram_fd);
+ stGPSReadback.dsp_dev[sizeof(stGPSReadback.dsp_dev) - 1] = '\0';
+
+ if (strlen(stGPSReadback.dsp_dev) != 0) {
+ gps_nvram_valid = 1;
+ // strncpy(mnl_config.dev_dsp, stGPSReadback.dsp_dev, sizeof(mnl_config.dev_dsp));
+
+ LOGD_ENG("GPS NVRam :(%d * %d), dsp_dev(/dev/stpgps) : %s\n", rec_size, rec_num, stGPSReadback.dsp_dev);
+ LOGD_ENG("gps_tcxo_hz : %d,gps_tcxo_ppb : %d,gps_tcxo_type : %d, gps_lna_mode : %d\n",
+ stGPSReadback.gps_tcxo_hz,
+ stGPSReadback.gps_tcxo_ppb,
+ stGPSReadback.gps_tcxo_type,
+ stGPSReadback.gps_lna_mode);
+ } else {
+ LOGD("GPS NVRam mnl_config.dev_dsp == NULL \n");
+ }
+ }
+ else {
+ LOGD("GPS NVRam gps_nvram_fd == NULL \n");
+ }
+#endif
+ return MTK_GPS_SUCCESS;
+}
+int mtk_gps_sys_uninit() {
+#if defined(LIB_MQUEUE)
+ mq_close(mnl_mq_fd); /* Close message queue in parent */
+ mq_unlink(MNL_MQ_NAME); /* Unlink message queue */
+ mq_close(mnl_agps_mq_fd); /* Close message queue in parent */
+ mq_unlink(MNL_AGPS_MQ_NAME); /* Unlink message queue */
+#else
+#endif
+ return MTK_GPS_SUCCESS;
+}
+
+int mtk_gps_sys_strncmp(const char * str1,const char * str2){
+ return strncmp(str1,str2,strlen(str2));
+}
+
+//Log filter for NMEA sentence
+MTK_GPS_BOOL mtk_gps_sys_nmea_log_filter(const char * buffer) {
+ MTK_GPS_BOOL ret = MTK_GPS_FALSE;
+
+ if('$' == buffer[0]
+ && ((mtk_gps_sys_strncmp(&buffer[3],"GGA")==0) || (mtk_gps_sys_strncmp(&buffer[3],"RMC")==0))){// NMEA sentence
+ ret = MTK_GPS_TRUE;
+ }else{
+ ret = MTK_GPS_FALSE;
+ }
+
+ return ret;
+}
+//Log filter for Offload printing
+MTK_GPS_BOOL mtk_gps_sys_ofl_log_filter(const char * buffer, UINT32 length) {
+ MTK_GPS_BOOL ret = MTK_GPS_FALSE;
+ UNUSED(length);
+ if(mtk_gps_sys_strncmp(buffer,"gfns_tx,dump") == 0){
+ ret = MTK_GPS_TRUE;
+ }else if(mtk_gps_sys_strncmp(buffer,"DUMP,GFNS") == 0){
+ ret = MTK_GPS_TRUE;
+ }else if(mtk_gps_sys_strncmp(buffer,"[FLP]") == 0){// FLP
+ ret = MTK_GPS_TRUE;
+ }else{
+ ret = MTK_GPS_FALSE;
+ //LOGD("len:%d, %s", length, buffer);
+ }
+
+ return ret;
+}
+
+INT32 mtk_gps_sys_nmea_output_to_app(const char * buffer, UINT32 length) {
+ if (enable_dbg_log == MTK_GPS_TRUE) { // Need to use prop to control debug on/of
+ char buf_print[MTK_GPS_HIDE_PRINT_MAX+1] = {0};
+ if (mtk_gps_sys_nmea_log_filter(buffer) == MTK_GPS_TRUE) {
+ MNLD_STRNCPY(buf_print, buffer, MTK_GPS_HIDE_PRINT_MAX);
+ buf_print[MTK_GPS_HIDE_PRINT_MAX] = '\0';
+ LOGD("len:%d, [NMEA]%s...", length, buf_print);
+ } else if (mtk_gps_sys_ofl_log_filter(buffer, length) == MTK_GPS_TRUE) {
+ if (mtk_gps_log_is_hide()) {
+ // Forbit to print location log
+ MNLD_STRNCPY(buf_print, buffer, MTK_GPS_HIDE_PRINT_MAX);
+ buf_print[MTK_GPS_HIDE_PRINT_MAX] = '\0';
+ LOGD("len:%d, [OFL]%s...", length, buf_print);
+ } else {
+ LOGDX("len:%d, %s", length, buffer);
+ }
+ } else {
+ // No limitation, print directly
+ LOGD("len:%d, %s", length, buffer);
+ }
+ }
+ return MTK_GPS_SUCCESS;
+}
+
+INT32 mtk_gps_sys_nmea_output_to_mnld(const char * buffer, UINT32 length) {
+ LOGD("received %d bytes:\n", length);
+ mtk_mnl_nmea_parser_process(buffer, length);
+ return MTK_GPS_SUCCESS;
+}
+
+static unsigned char calc_nmea_checksum1(const char* sentence) {
+ unsigned char checksum = 0;
+
+ while (*sentence) {
+ checksum ^= (unsigned char)*sentence++;
+ }
+ return checksum;
+}
+
+INT32 mtk_gps_sys_frame_sync_meas_req(MTK_GPS_FS_WORK_MODE mode) {
+ char szBuf_cipher[64];
+ char sztmp[64];
+ char outbuf[64];
+
+ memset(outbuf, 0, sizeof(outbuf));
+ memset(sztmp, 0, sizeof(sztmp));
+ memset(szBuf_cipher, 0, sizeof(szBuf_cipher));
+ MNLD_SPRINTF(sztmp, "PMTK%d,1,%d", PMTK_FS_REQ_MEAS, mode);
+ MNLD_SPRINTF(outbuf, "$%s*%02X\r\n", sztmp, calc_nmea_checksum1(sztmp));
+
+ // SUPL_encrypt((unsigned char *)outbuf, (unsigned char *)szBuf_cipher, strlen(outbuf));
+ MNLD_STRNCPY(szBuf_cipher, outbuf, sizeof(szBuf_cipher));
+ mtk_gps_sys_agps_disaptcher_callback(MTK_AGPS_CB_SUPL_PMTK, strlen(szBuf_cipher), szBuf_cipher);
+
+ return MTK_GPS_SUCCESS;
+}
+
+INT32 mtk_gps_sys_frame_sync_enable_sleep_mode(unsigned char mode) {
+ char szBuf_cipher[64];
+ char sztmp[64];
+ char outbuf[64];
+
+ memset(outbuf, 0, sizeof(outbuf));
+ memset(sztmp, 0, sizeof(sztmp));
+ memset(szBuf_cipher, 0, sizeof(szBuf_cipher));
+ MNLD_SPRINTF(sztmp, "PMTK%d,%d", PMTK_FS_SLEEPMODE, mode);
+ MNLD_SPRINTF(outbuf, "$%s*%02X\r\n", sztmp, calc_nmea_checksum1(sztmp));
+
+ // SUPL_encrypt((unsigned char *)outbuf, (unsigned char *)szBuf_cipher, strlen(outbuf));
+ MNLD_STRNCPY(szBuf_cipher, outbuf, sizeof(outbuf));
+ mtk_gps_sys_agps_disaptcher_callback(MTK_AGPS_CB_SUPL_PMTK, strlen(szBuf_cipher), szBuf_cipher);
+
+ return MTK_GPS_SUCCESS;
+}
+
+INT32 mtk_gps_sys_frame_sync_meas_req_by_network(void) {
+ char szBuf_cipher[64];
+ char sztmp[64];
+ char outbuf[64];
+
+ memset(outbuf, 0, sizeof(outbuf));
+ memset(sztmp, 0, sizeof(sztmp));
+ memset(szBuf_cipher, 0, sizeof(szBuf_cipher));
+ MNLD_SPRINTF(sztmp, "PMTK%d,0,0", PMTK_FS_REQ_MEAS);
+ MNLD_SPRINTF(outbuf, "$%s*%02X\r\n", sztmp, calc_nmea_checksum1(sztmp));
+
+ // SUPL_encrypt((unsigned char *)outbuf, (unsigned char *)szBuf_cipher, strlen(outbuf));
+ MNLD_STRNCPY(szBuf_cipher, outbuf, sizeof(outbuf));
+ mtk_gps_sys_agps_disaptcher_callback(MTK_AGPS_CB_SUPL_PMTK, strlen(szBuf_cipher), szBuf_cipher);
+
+ return MTK_GPS_SUCCESS;
+}
+
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/inc/agps2mnl_interface.h b/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/inc/agps2mnl_interface.h
new file mode 100644
index 0000000..badb400
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/inc/agps2mnl_interface.h
@@ -0,0 +1,105 @@
+
+#ifndef __AGPS2GPS_INTERFACE_H__
+#define __AGPS2GPS_INTERFACE_H__
+
+#include "mnl_agps_interface.h"
+
+typedef struct {
+ void (*mnl_reboot)();
+
+ void (*open_gps_done)();
+ void (*close_gps_done)();
+ void (*reset_gps_done)();
+
+ void (*gps_init)();
+ void (*gps_cleanup)();
+ void (*set_server)(int type, const char* hostname, int port);
+ void (*delete_aiding_data)(int flags);
+ void (*gps_open)(int assist_req);
+ void (*gps_close)();
+ void (*data_conn_open)(const char* apn);
+ void (*data_conn_failed)();
+ void (*data_conn_closed)();
+
+ void (*ni_message)(const char* msg, int len);
+ void (*ni_respond)(int session_id, int user_response);
+
+ void (*set_ref_loc)(int type, int mcc, int mnc, int lac, int cid);
+ void (*set_set_id)(int type, const char* setid);
+
+ void (*update_network_state)(int connected, int type, int roaming, const char* extra_info);
+ void (*update_network_availability)(int avaiable, const char* apn);
+
+ void (*rcv_pmtk)(const char* pmtk);
+ void (*raw_dbg)(int enabled);
+ void (*reaiding_req)();
+ void (*data_conn_open_ip_type)(const char* apn, int ip_type, bool network_handle_valid, uint64_t network_handle);
+ void (*install_certificates)(int index, int total, const char* data, int len);
+ void (*revoke_certificates)(const char* data, int len);
+ void (*location_sync)(double lat, double lng, int acc, bool alt_valid, float alt, bool source_valid, bool source_gnss, bool source_nlp, bool source_sensor, bool utc_time_valid, unsigned long long utc_time);
+ void (*agps_settings_ack) (mnl_agps_gnss_settings* settings);
+ void (*vzw_debug_screen_enable) (int enabled);
+ void (*set_server_extension) (int type, const char* hostname, int port, int ssl, int ssl_version, int ssl_type);
+ void (*update_configuration) (const char* config_data, int length);
+ void (*supl_host_ip) (const char* ip);
+ void (*tc10_lpp_support) (int support_bitmask);
+ void (*lppe_assist_data_req) (const char* data, int len); // refer to gnss_ha_assist_data_req_struct
+ void (*lppe_assist_data_provide_ack) (const char* data, int len); // refer to gnss_ha_assist_ack_struct
+ void (*set_position_mode)(int pos_mode);
+ void (*update_gnss_access_control)(bool allowed);
+ void (*md_time_sync_req)(const char* data, int len);
+ void (*md_time_sync_rsp)(const char* data, int len);
+ void (*md_time_info_rsp)(const char* data, int len);
+ void (*update_network_state_with_handle)(uint64_t network_handle, bool is_connected, unsigned short capabilities, const char* apn);
+ void (*gnss_time_sync)(unsigned long long utc_time); // For SIM unlock. Provide the GNSS Time in UTC (in 1ms units since January 1, 1970) when GNSS Visibility Control does not allow MNL_AGPS_TYPE_LOCATION_SYNC
+} mnl2agps_interface;
+
+int agps2mnl_agps_reboot();
+
+int agps2mnl_agps_open_gps_req(int show_gps_icon, mnl_agps_open_type open_type,
+ mnl_agps_open_requestor requestor_type, const char* requestor_id,
+ bool emergency_call);
+int agps2mnl_agps_close_gps_req();
+int agps2mnl_agps_reset_gps_req(int flags);
+int agps2mnl_agps_open_gps_rejected(mnl_agps_open_type open_type,
+ mnl_agps_open_requestor requestor_type, const char* requestor_id,
+ bool emergency_call);
+
+int agps2mnl_agps_session_done();
+
+int agps2mnl_ni_notify(int session_id, mnl_agps_ni_type ni_type, mnl_agps_notify_type type, const char* requestor_id, const char* client_name);
+int agps2mnl_ni_notify2(int session_id, mnl_agps_ni_type ni_type, mnl_agps_notify_type type, const char* requestor_id, const char* client_name,
+ mnl_agps_ni_encoding_type requestor_id_encoding, mnl_agps_ni_encoding_type client_name_encoding);
+int agps2mnl_data_conn_req(int ipaddr, int is_emergency);
+int agps2mnl_data_conn_req2(struct sockaddr_storage* addr, int is_emergency,
+ mnl_agps_data_connection_type agps_type);
+int agps2mnl_data_conn_release(mnl_agps_data_connection_type agps_type);
+// flags refer to REQUEST_SETID_IMSI and REQUEST_SETID_MSISDN
+int agps2mnl_set_id_req(int flags);
+// flags refer to REQUEST_REFLOC_CELLID and REQUEST_REFLOC_MAC
+int agps2mnl_ref_loc_req(int flags);
+
+int agps2mnl_pmtk(const char* pmtk);
+int agps2mnl_gpevt(gpevt_type type);
+
+int agps2mnl_agps_location(mnl_agps_agps_location2* location);
+int agps2mnl_cell_location(mnl_agps_agps_location2* location);
+
+int agps2mnl_agps_settings_sync(mnl_agps_agps_settings* settings);
+int agps2mnl_vzw_debug_screen_output(const char* str);
+int agps2mnl_supl_dns_req(const char* fqdn);
+int agps2mnl_lppe_assist_data_provide_common_iono(const char* data, int len); // refer to gnss_ha_common_ionospheric_model_struct
+int agps2mnl_lppe_assist_data_provide_common_trop(const char* data, int len); // refer to gnss_ha_common_troposphere_model_struct
+int agps2mnl_lppe_assist_data_provide_common_alt(const char* data, int len); // refer to gnss_ha_common_altitude_assist_struct
+int agps2mnl_lppe_assist_data_provide_common_solar(const char* data, int len); // refer to gnss_ha_common_solar_radiation_struct
+int agps2mnl_lppe_assist_data_provide_common_ccp(const char* data, int len); // refer to gnss_ha_common_ccp_assist_struct
+int agps2mnl_lppe_assist_data_provide_generic_ccp(const char* data, int len); // refer to gnss_ha_generic_ccp_assist_struct
+int agps2mnl_lppe_assist_data_provide_generic_dm(const char* data, int len); // refer to gnss_ha_generic_degradation_model_struct
+int agps2mnl_md_time_sync_ind(const char* data, int len);
+int agps2mnl_md_time_sync_cnf(const char* data, int len);
+void mnl2agps_hdlr(int fd, mnl2agps_interface* agps_interface);
+
+int create_mnl2agps_fd(const char* agps2mnl_path, const char* mnl2agps_path);
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/inc/mnl2agps_interface.h b/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/inc/mnl2agps_interface.h
new file mode 100644
index 0000000..d61d7dd
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/inc/mnl2agps_interface.h
@@ -0,0 +1,106 @@
+
+#ifndef __GPS2AGPS_INTERFACE_H__
+#define __GPS2AGPS_INTERFACE_H__
+
+#include <sys/socket.h>
+#include "mnl_agps_interface.h"
+
+typedef struct {
+ void (*agps_reboot)();
+
+ void (*agps_open_gps_req)(int show_gps_icon, mnl_agps_open_type open_type,
+ mnl_agps_open_requestor requestor_type, const char* requestor_id,
+ bool emergency_call);
+ void (*agps_close_gps_req)();
+ void (*agps_reset_gps_req)(int flags);
+ void (*agps_open_gps_rejected)(mnl_agps_open_type open_type,
+ mnl_agps_open_requestor requestor_type, const char* requestor_id,
+ bool emergency_call);
+
+ void (*agps_session_done)();
+
+ void (*ni_notify)(int session_id, mnl_agps_ni_type ni_type, mnl_agps_notify_type type,
+ const char* requestor_id, const char* client_name);
+ void (*data_conn_req)(int ipaddr, int is_emergency);
+ void (*data_conn_release)(mnl_agps_data_connection_type agps_type);
+
+ void (*set_id_req)(int flags);
+ void (*ref_loc_req)(int flags);
+
+ void (*rcv_pmtk)(const char* pmtk);
+ void (*gpevt)(gpevt_type type);
+
+ void (*agps_location)(mnl_agps_agps_location2* location);
+ void (*cell_location)(mnl_agps_agps_location2* location);
+ void (*ni_notify2)(int session_id, mnl_agps_ni_type ni_type, mnl_agps_notify_type type,
+ const char* requestor_id, const char* client_name,
+ mnl_agps_ni_encoding_type requestor_id_encoding, mnl_agps_ni_encoding_type client_name_encoding);
+ void (*data_conn_req2)(struct sockaddr_storage* addr, int is_emergency, mnl_agps_data_connection_type agps_type);
+ void (*agps_settings_sync)(mnl_agps_agps_settings* settings);
+ void (*vzw_debug_screen_output)(const char* str);
+ void (*lppe_assist_common_iono) (const char* data, int len); // refer to gnss_ha_common_ionospheric_model_struct
+ void (*lppe_assist_common_trop) (const char* data, int len); // refer to gnss_ha_common_troposphere_model_struct
+ void (*lppe_assist_common_alt) (const char* data, int len); // refer to gnss_ha_common_altitude_assist_struct
+ void (*lppe_assist_common_solar) (const char* data, int len); // refer to gnss_ha_common_solar_radiation_struct
+ void (*lppe_assist_common_ccp) (const char* data, int len); // refer to gnss_ha_common_ccp_assist_struct
+ void (*lppe_assist_generic_ccp) (const char* data, int len); // refer to gnss_ha_generic_ccp_assist_struct
+ void (*lppe_assist_generic_dm) (const char* data, int len); // refer to gnss_ha_generic_degradation_model_struct
+ void (*md_time_sync_ind) (const char* data, int len); // refer to mnl_md_time_sync_ind_struct
+ void (*md_time_sync_cnf) (const char* data, int len); // refer to mnl_md_time_sync_cnf_struct
+} agps2mnl_interface;
+
+// MNL -> AGPS
+int mnl2agps_mnl_reboot();
+
+int mnl2agps_open_gps_done();
+int mnl2agps_close_gps_done();
+int mnl2agps_reset_gps_done();
+
+int mnl2agps_gps_init();
+int mnl2agps_gps_cleanup();
+// type:AGpsType
+int mnl2agps_set_server(int type, const char* hostname, int port);
+// flags:GpsAidingData
+int mnl2agps_delete_aiding_data(int flags);
+int mnl2agps_gps_open(int assist_req);
+int mnl2agps_gps_close();
+int mnl2agps_data_conn_open(const char* apn);
+int mnl2agps_data_conn_open_ip_type(const char* apn, int ip_type, bool network_handle_valid, uint64_t network_handle);
+int mnl2agps_data_conn_failed();
+int mnl2agps_data_conn_closed();
+int mnl2agps_ni_message(const char* msg, int len);
+int mnl2agps_ni_respond(int session_id, int user_response);
+int mnl2agps_set_ref_loc(int type, int mcc, int mnc, int lac, int cid);
+int mnl2agps_set_set_id(int type, const char* setid);
+int mnl2agps_update_network_state(int connected, int type, int roaming, const char* extra_info);
+int mnl2agps_update_network_availability(int avaiable, const char* apn);
+int mnl2agps_install_certificates(int index, int total, const char* data, int len);
+int mnl2agps_revoke_certificates(const char* data, int len);
+int mnl2agps_update_gnss_access_control(bool allowed);
+
+int mnl2agps_pmtk(const char* pmtk);
+int mnl2agps_raw_dbg(int enabled);
+int mnl2agps_reaiding_req();
+int mnl2agps_location_sync(mnl_agps_location_time* location_sync_data);
+int mnl2agps_agps_settings_ack(mnl_agps_gnss_settings* settings);
+int mnl2agps_vzw_debug_screen_enable(int enabled);
+int mnl2agps_set_server_extension(int type, const char* hostname, int port, int ssl, int ssl_version, int ssl_type);
+int mnl2agps_update_configuration(const char* config_data, int length);
+int mnl2agps_supl_host_ip(const char* ip);
+int mnl2agps_tc10_lpp_support(int support_bitmask);
+int mnl2agps_lppe_assist_data_req(const char* data, int len); // refer to gnss_ha_assist_data_req_struct
+int mnl2agps_lppe_assist_data_provide_ack(const char* data, int len); // refer to gnss_ha_assist_ack_struct
+int mnl2agps_set_position_mode(int pos_mode);
+int mnl2agps_md_time_sync_req(const char* data, int len);
+int mnl2agps_md_time_sync_rsp(const char* data, int len);
+int mnl2agps_md_time_info_rsp(const char* data, int len);
+int mnl2agps_update_network_state_with_handle(uint64_t network_handle, bool is_connected, unsigned short capabilities, const char* apn);
+int mnl2agps_gnss_time_sync(long long utc_time); // For SIM unlock. Provide the GNSS Time in UTC (in 1ms units since January 1, 1970) when GNSS Visibility Control does not allow MNL_AGPS_TYPE_LOCATION_SYNC
+
+void agps2mnl_hdlr(int fd, agps2mnl_interface* mnl_interface);
+
+
+int create_agps2mnl_fd();
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/inc/mnl_agps_interface.h b/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/inc/mnl_agps_interface.h
new file mode 100644
index 0000000..f6d8c81
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/inc/mnl_agps_interface.h
@@ -0,0 +1,305 @@
+#ifndef __GPS_AGPS_INTERFACE_H__
+#define __GPS_AGPS_INTERFACE_H__
+
+// #include <hardware/gps.h>
+
+#if defined(__ANDROID_OS__)
+#include <android/log.h>
+#endif
+#include <stdbool.h>
+
+#if defined(ANDROID)
+#define AGPS_TO_MNL "/data/agps_supl/agps_to_mnl"
+#define MNL_TO_AGPS "/data/agps_supl/mnl_to_agps"
+#else
+#define AGPS_TO_MNL "agps_to_mnl"
+#define MNL_TO_AGPS "mnl_to_agps"
+#endif
+
+#define MNL_AGPS_MAX_BUFF_SIZE (10 * 1024)
+#define MNL_AGPS_MAX_BUFF_RCV_SIZE (32 * 1024)
+
+#define MNL_AGPS_INTERFACE_VERSION 1
+
+#define REQUEST_SETID_IMSI (1<<0L)
+#define REQUEST_SETID_MSISDN (1<<1L)
+
+#define REQUEST_REFLOC_CELLID (1<<0L)
+#define REQUEST_REFLOC_MAC (1<<1L) // not ready
+
+typedef enum {
+ MNL_AGPS_NI_TYPE_VOICE = 1,
+ MNL_AGPS_NI_TYPE_UMTS_SUPL,
+ MNL_AGPS_NI_TYPE_UMTS_CTRL_PLANE,
+ MNL_AGPS_NI_TYPE_EMERGENCY_SUPL,
+} mnl_agps_ni_type;
+
+typedef enum {
+ MNL_AGPS_NOTIFY_TYPE_NONE = 0,
+ MNL_AGPS_NOTIFY_TYPE_NOTIFY_ONLY,
+ MNL_AGPS_NOTIFY_TYPE_NOTIFY_ALLOW_NO_ANSWER,
+ MNL_AGPS_NOTIFY_TYPE_NOTIFY_DENY_NO_ANSWER,
+ MNL_AGPS_NOTIFY_TYPE_PRIVACY,
+} mnl_agps_notify_type;
+
+typedef enum {
+ MNL_AGPS_NI_ENCODING_TYPE_NONE = 0,
+ MNL_AGPS_NI_ENCODING_TYPE_GSM7,
+ MNL_AGPS_NI_ENCODING_TYPE_UTF8,
+ MNL_AGPS_NI_ENCODING_TYPE_UCS2,
+} mnl_agps_ni_encoding_type;
+
+typedef enum {
+ GPEVT_TYPE_UNKNOWN = 0, // 0
+ GPEVT_SUPL_SLP_CONNECT_BEGIN, // 1
+ GPEVT_SUPL_SLP_CONNECTED, // 2
+ GPEVT_SUPL_SSL_CONNECT_BEGIN, // 3
+ GPEVT_SUPL_SSL_CONNECTED, // 4
+ GPEVT_SUPL_ASSIST_DATA_RECEIVED, // 5
+ GPEVT_SUPL_ASSIST_DATA_VALID, // 6
+ GPEVT_SUPL_FIRST_POS_FIX, // 7
+ GPEVT_SUPL_MEAS_TIME_OUT, // 8
+ GPEVT_SUPL_MEAS_RESPONSE_SENT, // 9
+ GPEVT_SUPL_SSL_CLOSED, // 10
+ GPEVT_SUPL_SLP_DISCONNECTED, // 11
+
+ GPEVT_CP_MOLR_SENT, // 12
+ GPEVT_CP_MTLR_RECEIVED, // 13
+ GPEVT_CP_ASSIST_DATA_RECEIVED, // 14
+ GPEVT_CP_ASSIST_DATA_VALID, // 15
+ GPEVT_CP_FIRST_POS_FIX, // 16
+ GPEVT_CP_MEAS_TIME_OUT, // 17
+ GPEVT_CP_MEAS_RESPONSE_SENT, // 18
+
+ GPEVT_GNSS_HW_START, // 19
+ GPEVT_GNSS_HW_STOP, // 20
+ GPEVT_GNSS_RESET_STORED_SATELLITE_DATA, // 21
+
+ GPEVT_EPO_SERVER_CONNECT_BEGIN, // 22
+ GPEVT_EPO_SERVER_CONNECTED, // 23
+ GPEVT_EPO_DATA_RECEIVED, // 24
+ GPEVT_EPO_SERVER_DISCONNECTED, // 25
+ GPEVT_EPO_DATA_VALID, // 26
+
+ GPEVT_HOT_STILL_DATA_VALID, // 27
+
+ GPEVT_TYPE_MAX // 28
+}gpevt_type;
+
+typedef enum {
+ MNL_AGPS_OPEN_TYPE_UNKNOWN = 0, // 0 (i.e., old agpsd)
+
+ MNL_AGPS_OPEN_TYPE_C2K = 0x10, // 0x10
+
+ MNL_AGPS_OPEN_TYPE_SUPL = 0x20, // 0x20
+
+ MNL_AGPS_OPEN_TYPE_CP_NILR = 0x30, // 0x30
+ MNL_AGPS_OPEN_TYPE_CP_MTLR, // 0x31
+ MNL_AGPS_OPEN_TYPE_CP_MOLR, // 0x32
+ MNL_AGPS_OPEN_TYPE_CP_QUERY, // 0x33
+ MNL_AGPS_OPEN_TYPE_CP_MLR // 0x34
+} mnl_agps_open_type;
+
+typedef enum {
+ MNL_AGPS_OPEN_REQUESTOR_UNKNOWN = 0, // 0
+ MNL_AGPS_OPEN_REQUESTOR_CARRIER, // 1
+ MNL_AGPS_OPEN_REQUESTOR_OEM, // 2
+ MNL_AGPS_OPEN_REQUESTOR_MODEM_CHIPSET_VENDOR, // 3
+ MNL_AGPS_OPEN_REQUESTOR_GNSS_CHIPSET_VENDOR, // 4
+ MNL_AGPS_OPEN_REQUESTOR_OTHER_CHIPSET_VENDOR, // 5
+ MNL_AGPS_OPEN_REQUESTOR_AUTOMOBILE_CLIENT, // 6
+ MNL_AGPS_OPEN_REQUESTOR_OTHER_REQUESTOR // 7
+} mnl_agps_open_requestor; // 8
+
+typedef enum {
+ MNL_AGPS_DATA_CONNECT_TYPE_SUPL = 1,
+ MNL_AGPS_DATA_CONNECT_TYPE_C2K = 2,
+ MNL_AGPS_DATA_CONNECT_TYPE_SUPL_EIMS = 3,
+ MNL_AGPS_DATA_CONNECT_TYPE_SUPL_IMS = 4,
+} mnl_agps_data_connection_type;
+
+typedef enum {
+ MNL_AGPS_NETWORK_CAPABILITY_NOT_METERED = 1, // Network is not metered.
+ MNL_AGPS_NETWORK_CAPABILITY_NOT_ROAMING = 2, // Network is not roaming.
+} mnl_agps_network_capability_type;
+
+typedef enum {
+ //---------------------------------------
+ // MNL -> AGPS
+ MNL_AGPS_TYPE_MNL_REBOOT = 100,
+
+ MNL_AGPS_TYPE_AGPS_OPEN_GPS_DONE = 110,
+ MNL_AGPS_TYPE_AGPS_CLOSE_GPS_DONE,
+ MNL_AGPS_TYPE_AGPS_RESET_GPS_DONE,
+
+ MNL_AGPS_TYPE_GPS_INIT = 120,
+ MNL_AGPS_TYPE_GPS_CLEANUP,
+ MNL_AGPS_TYPE_DELETE_AIDING_DATA,
+ MNL_AGPS_TYPE_GPS_OPEN,
+ MNL_AGPS_TYPE_GPS_CLOSE,
+ MNL_AGPS_TYPE_DATA_CONN_OPEN,
+ MNL_AGPS_TYPE_DATA_CONN_FAILED,
+ MNL_AGPS_TYPE_DATA_CONN_CLOSED,
+ MNL_AGPS_TYPE_NI_MESSAGE,
+ MNL_AGPS_TYPE_NI_RESPOND,
+ MNL_AGPS_TYPE_SET_REF_LOC,
+ MNL_AGPS_TYPE_SET_SET_ID,
+ MNL_AGPS_TYPE_SET_SERVER,
+ MNL_AGPS_TYPE_UPDATE_NETWORK_STATE,
+ MNL_AGPS_TYPE_UPDATE_NETWORK_AVAILABILITY,
+ MNL_AGPS_TYPE_DATA_CONN_OPEN_IP_TYPE,
+ MNL_AGPS_TYPE_INSTALL_CERTIFICATES,
+ MNL_AGPS_TYPE_REVOKE_CERTIFICATES,
+ MNL_AGPS_TYPE_UPDATE_GNSS_ACCESS_CONTROL,
+
+ MNL_AGPS_TYPE_MNL2AGPS_PMTK = 150,
+ MNL_AGPS_TYPE_RAW_DBG,
+ MNL_AGPS_TYPE_REAIDING,
+ MNL_AGPS_TYPE_LOCATION_SYNC,
+ MNL_AGPS_TYPE_SETTINGS_ACK,
+ MNL_AGPS_TYPE_VZW_DEBUG_SCREEN_ENABLE,
+ MNL_AGPS_TYPE_SET_SERVER_EXTENSION,
+ MNL_AGPS_TYPE_UPDATE_CONFIGURATION,
+ MNL_AGPS_TYPE_SUPL_HOST_IP,
+ MNL_AGPS_TYPE_TC10_LPP_SUPPORT,
+ MNL_AGPS_TYPE_LPPE_ASSIST_DATA_REQ, // 160, refer to gnss_ha_assist_data_request_ind_struct
+ MNL_AGPS_TYPE_LPPE_ASSIST_DATA_PROVIDE_ACK, // refer to gnss_ha_assist_ack_struct
+ MNL_AGPS_TYPE_SET_POSITION_MODE,
+
+ MNL_AGPS_TYPE_MD_TIME_SYNC_REQ, // Case 1: MNL-Initiated
+ MNL_AGPS_TYPE_MD_TIME_SYNC_RSP, // Case 2: ack to MD-Initiated
+ MNL_AGPS_TYPE_MD_TIME_INFO_RSP, // OK to have a location with time sync
+ MNL_AGPS_TYPE_UPDATE_NETWORK_STATE_WITH_HANDLE, // for GNSS HIDL 2.0 to update network state with handler
+
+ MNL_AGPS_TYPE_GNSS_TIME_SYNC, // For SIM unlock. Provide the GNSS Time in UTC (in 1ms units since January 1, 1970) when GNSS Visibility Control does not allow MNL_AGPS_TYPE_LOCATION_SYNC
+
+ // ---------------------------------------
+ // AGPS -> MNL
+ MNL_AGPS_TYPE_AGPS_REBOOT = 200,
+
+ MNL_AGPS_TYPE_AGPS_OPEN_GPS_REQ = 210,
+ MNL_AGPS_TYPE_AGPS_CLOSE_GPS_REQ,
+ MNL_AGPS_TYPE_AGPS_RESET_GPS_REQ,
+ MNL_AGPS_TYPE_AGPS_OPEN_GPS_REJECTED,
+
+ MNL_AGPS_TYPE_AGPS_SESSION_DONE = 220,
+
+ MNL_AGPS_TYPE_NI_NOTIFY = 230,
+ MNL_AGPS_TYPE_DATA_CONN_REQ,
+ MNL_AGPS_TYPE_DATA_CONN_RELEASE,
+ MNL_AGPS_TYPE_SET_ID_REQ,
+ MNL_AGPS_TYPE_REF_LOC_REQ,
+ MNL_AGPS_TYPE_AGPS_LOC,
+ MNL_AGPS_TYPE_NI_NOTIFY_2,
+ MNL_AGPS_TYPE_DATA_CONN_REQ2,
+ MNL_AGPS_TYPE_SUPL_DNS_REQ,
+
+ MNL_AGPS_TYPE_AGPS2MNL_PMTK = 250,
+ MNL_AGPS_TYPE_GPEVT,
+ MNL_AGPS_TYPE_SETTINGS_SYNC,
+ MNL_AGPS_TYPE_VZW_DEBUG_SCREEN_OUTPUT,
+ MNL_AGPS_TYPE_CELL_LOCATION,
+ MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_IONO, // refer to gnss_ha_common_ionospheric_model_struct
+ MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_TROP, // refer to gnss_ha_common_troposphere_model_struct
+ MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_ALT, // refer to gnss_ha_common_altitude_assist_struct
+ MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_SOLAR,// refer to gnss_ha_common_solar_radiation_struct
+ MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_CCP, // refer to gnss_ha_common_ccp_assist_struct
+ MNL_AGPS_TYPE_LPPE_ASSIST_GENERIC_CCP, // refer to gnss_ha_generic_ccp_assist_struct
+ MNL_AGPS_TYPE_LPPE_ASSIST_GENERIC_DM, // refer to gnss_ha_generic_degradation_model_struct
+ MNL_AGPS_TYPE_MD_TIME_SYNC_IND, // Case 2: MD-Initiated (similar to PMTK768)
+ MNL_AGPS_TYPE_MD_TIME_SYNC_CNF, // Case 1: ack to the MNL-Initiated
+} mnl_agps_type;
+typedef enum{
+ AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_IONO = 610, //MD -> AP gnss_ha_common_ionospheric_model_struct
+ AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_TROP = 611, //MD -> AP gnss_ha_common_troposphere_model_struct
+ AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_ALT = 612, //MD -> AP gnss_ha_common_altitude_assist_struct
+ AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_SOLAR = 613, //MD -> AP gnss_ha_common_solar_radiation_struct
+ AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_CCP = 614, //MD -> AP gnss_ha_common_ccp_assist_struct
+ AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_GENERIC_CCP = 630, //MD -> AP gnss_ha_generic_ccp_assist_struct
+ AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_GENERIC_DM = 631, //MD -> AP gnss_ha_generic_degradation_model_struct
+ AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_ACK = 650, //AP -> MD lpp_lppe_ha_gn
+}lppe_ack_type;
+
+// AGPSD sends a location to MNL
+typedef enum {
+ MNL_AGPS_AGPS_LOC_TYPE_AFLT = 0, // From C2K AFLT flow
+ MNL_AGPS_AGPS_LOC_TYPE_CDMA_CELL = 1, // From C2K Cell
+ MNL_AGPS_AGPS_LOC_TYPE_MOLR_BEGIN_RSP = 2, // For CP MOLR after UE provides MSA result, the network will send CISS_FACILITY to provide UE a MSA location. Refer to 3GPP TS37.571-2 7.2.2.2
+ MNL_AGPS_AGPS_LOC_TYPE_SUPL_END = 3, // From the SUPL END in a supl session. It may be the result of MSA, E-CID, OTDOA, or their hybrid.
+ MNL_AGPS_AGPS_LOC_TYPE_SUPL_REF_LOC = 4, // For Reference Location assistance data in SUPL flow (equivalent to PMTK713 in SUPL flow)
+ MNL_AGPS_AGPS_LOC_TYPE_CP_REF_LOC = 5, // For Reference Location assistance data in CP AGPS flow (equivalent to PMTK713 in CP AGPS flow)
+} mnl_agps_agps_location_type;
+
+// MNL sends a cell info to AGPSD, refer to AGPS_REF_LOCATION_TYPE_xxx_CELLID in gnss-base.h and xxx_CELLID in IAGnssRil.hal
+typedef enum {
+ MNL_AGPS_REF_LOCATION_TYPE_INVALID = 0, // For AGPSD only, it means the cell info is not initialized
+ MNL_AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1,
+ MNL_AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2,
+ MNL_AGPS_REF_LOCATION_TYPE_LTE_CELLID = 4, // For KK ~ R, Java/JNI will not send the cell info of this type
+} mnl_agps_ref_location_type;
+
+typedef struct {
+ double latitude; // Represents latitude in degrees
+ double longitude; // Represents longitude in degrees
+ char altitude_used; // 0=disabled 1=enabled
+ double altitude; // Represents altitude in meters above the WGS 84 reference
+ char speed_used; // 0=disabled 1=enabled
+ float speed; // Represents speed in meters per second
+ char bearing_used; // 0=disabled 1=enabled
+ float bearing; // Represents heading in degrees
+ char accuracy_used; // 0=disabled 1=enabled
+ float accuracy; // Represents expected accuracy in meters
+ char timestamp_used; // 0=disabled 1=enabled
+ long long timestamp; // Milliseconds since January 1, 1970
+} mnl_agps_agps_location;
+
+typedef struct {
+ mnl_agps_agps_location loc; // old and using put_binary / get_binary
+ char source_used; // 0=disabled 1=enabled
+ mnl_agps_agps_location_type source;
+} mnl_agps_agps_location2;
+
+typedef struct {
+ char sib8_16_enable;
+ char gps_satellite_enable;
+ char glonass_satellite_enable;
+ char beidou_satellite_enable;
+ char galileo_satellite_enable;
+ char a_glonass_satellite_enable;
+ char a_gps_satellite_enable;
+ char a_beidou_satellite_enable;
+ char a_galileo_satellite_enable;
+ char lppe_enable;
+} mnl_agps_agps_settings;
+
+typedef struct {
+ bool utc_time_valid;
+ long long utc_time;
+} mnl_agps_time;
+
+typedef struct {
+ double lat;
+ double lng;
+ int acc;
+ bool alt_valid;
+ float alt;
+ bool source_valid;
+ bool source_gnss;
+ bool source_nlp;
+ bool source_sensor;
+ mnl_agps_time utc_time_sync;
+ bool sv_inuse_num_valid;
+ int sv_inuse_num;
+} mnl_agps_location_time;
+
+typedef struct {
+ char gps_satellite_support;
+ char glonass_satellite_support;
+ char beidou_satellite_support;
+ char galileo_satellite_support;
+} mnl_agps_gnss_settings;
+
+const char* get_mnl_agps_type_str(mnl_agps_type input);
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/src/agps2mnl_interface.c b/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/src/agps2mnl_interface.c
new file mode 100644
index 0000000..4a67253
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/src/agps2mnl_interface.c
@@ -0,0 +1,1027 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h> //usleep
+
+#include <arpa/inet.h> // inet_addr
+#include <sys/un.h> // struct sockaddr_un
+
+#if defined(__ANDROID_OS__)
+#include <cutils/properties.h>
+#endif
+
+#include "mtk_prop_util.h"
+
+#if defined(__TIZEN_OS__)
+#include <dlog/dlog.h>
+#endif
+
+#include "mtk_mnld_log.h"
+
+#include "agps2mnl_interface.h"
+#include "data_coder.h"
+
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+//#define MNL_TO_AGPS "/data/agps_supl/mnl_to_agps"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#ifndef MNLD_STRNCPY
+#define MNLD_STRNCPY(dst,src,size) do{\
+ strncpy((char *)(dst), (char *)(src), (size - 1));\
+ (dst)[size - 1] = '\0';\
+ }while(0)
+#endif
+
+#define LOG_TAG "agps"
+
+#define HIDE_LOG_PROP "ro.vendor.mtk_log_hide_gps"
+// -1 means failure
+static int safe_recvfrom(int sockfd, char* buf, int len) {
+ int ret = 0;
+ int retry = 10;
+
+ while ((ret = recvfrom(sockfd, buf, len, 0,
+ NULL, NULL)) == -1) {
+ LOGW("ret=%d len=%d\n", ret, len);
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("sendto reason=[%s]\n", strerror(errno));
+ break;
+ }
+ return ret;
+}
+
+// -1 means failure
+static int set_socket_blocking(int fd, int blocking) {
+ if (fd < 0) {
+ LOGE("set_socket_blocking invalid fd=%d\n", fd);
+ return -1;
+ }
+
+ int flags = fcntl(fd, F_GETFL, 0);
+ if (flags < 0) {
+ LOGE("set_socket_blocking invalid flags=%d\n", flags);
+ return -1;
+ }
+
+ flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);
+ return (fcntl(fd, F_SETFL, flags) == 0) ? 0 : -1;
+}
+
+// -1 means failure
+static int safe_sendto(int sockfd, const char* dest, const char* buf, int size) {
+ int len = 0;
+ struct sockaddr_un soc_addr;
+ socklen_t addr_len;
+ int retry = 10;
+
+ MNLD_STRNCPY(soc_addr.sun_path, dest,sizeof(soc_addr.sun_path));
+ soc_addr.sun_family = AF_UNIX;
+ addr_len = (offsetof(struct sockaddr_un, sun_path) + strlen(soc_addr.sun_path) + 1);
+
+ while ((len = sendto(sockfd, buf, size, 0,
+ (const struct sockaddr *)&soc_addr, (socklen_t)addr_len)) == -1) {
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("sendto dest=[%s] len=%d reason=[%s]\n",
+ dest, size, strerror(errno));
+ break;
+ }
+ return len;
+}
+
+static int is_path_exist(const char* path) {
+ struct stat s;
+ int err = stat(path, &s);
+ if(-1 == err) {
+ if(ENOENT == errno) {
+ // does not exist
+ return 0;
+ } else {
+ // perror("stat");
+ return 0;
+ }
+ } else {
+ if(S_ISDIR(s.st_mode)) {
+ // it's a dir
+ return 1;
+ } else {
+ // it's a file
+ return 2;
+ }
+ }
+ return 0;
+}
+
+static void utils_strncpy(char* dest, const char* src, size_t n) {
+ if (dest && n > 0) {
+ // Use strncat for performance because strncpy will always fill n bytes in dest
+ dest[0] = '\0'; // Let dest be an empty string
+ strncat(dest, src, --n); // n-1 because strncat may fill n+1 bytes
+ }
+}
+
+// -1 mean fail or clientfd is returned
+static int sock_udp_client_create_local(bool is_abstract, const char* name) {
+ int fd = -1;
+ 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(is_abstract) {
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, name, strlen(name));
+ } else {
+ utils_strncpy(addr.sun_path, name, sizeof(addr.sun_path));
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ LOGE("socket() failed, reason=[%s]%d", strerror(errno), errno);
+ return -1;
+ }
+ if(connect(fd, (struct sockaddr *)&addr, size) == -1) {
+ LOGE("connect() failed, abstract=%d name=[%s] reason=[%s]%d",
+ is_abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+// -1 mean fail or return the number of byte are written
+static int fd_write(int fd, const void* buff, uint32_t len) {
+ int ret;
+ if(buff == NULL) {
+ LOGE("buff is NULL");
+ return -1;
+ }
+ if(len == 0) {
+ LOGE("fd_write() len=%d is invalid", len);
+ return -1;
+ }
+ ret = write(fd, buff, len);
+ if(ret == -1) {
+ LOGE("fd_write() write() failed, fd=%d len=%d reason=[%s]%d",
+ fd, len, strerror(errno), errno);
+ return -1;
+ }
+ return ret;
+}
+
+// -1 mean fail or serverfd is returned
+static int sock_udp_server_bind_local(bool is_abstract, const char* name) {
+ int fd = -1;
+ 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(is_abstract) {
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, name, strlen(name));
+ } else {
+ utils_strncpy(addr.sun_path, name, sizeof(addr.sun_path));
+ if(unlink(addr.sun_path) == -1) {
+ LOGE("unlink() failed, reason=[%s]%d", strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (fd == -1) {
+ LOGE("socket() failed, reason=[%s]%d", strerror(errno), errno);
+ return -1;
+ }
+ if (bind(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("bind() failed, abstract=%d name=[%s] reason=[%s]%d",
+ is_abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+static char g_agps2mnl_path[128] = AGPS_TO_MNL;
+
+// -1 means failure
+static int send2mnl(const char* buff, int len) {
+ int ret = 0;
+ //Android P0, /data folder cannot be used anymore, use the abstract socket instead
+ if(is_path_exist(AGPS_TO_MNL) == 2) {
+ int fd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ return -1;
+ }
+ ret = safe_sendto(fd, g_agps2mnl_path, buff, len);
+ close(fd);
+ } else {
+ int fd = sock_udp_client_create_local(true, "mtk_agps2mnl");
+ if(fd == -1) {
+ return -1;
+ }
+ ret = fd_write(fd, buff, len);
+ close(fd);
+ }
+ return ret;
+}
+
+static int bind_udp_socket(char* path) {
+ int sockfd;
+ struct sockaddr_un soc_addr;
+ socklen_t addr_len;
+
+ sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+ if (sockfd < 0) {
+ LOGE("socket failed reason=[%s]\n", strerror(errno));
+ return -1;
+ }
+
+ MNLD_STRNCPY(soc_addr.sun_path, path,sizeof(soc_addr.sun_path));
+ soc_addr.sun_family = AF_UNIX;
+ addr_len = (offsetof(struct sockaddr_un, sun_path) + strlen(soc_addr.sun_path) + 1);
+
+ unlink(soc_addr.sun_path);
+ if (bind(sockfd, (struct sockaddr *)&soc_addr, addr_len) < 0) {
+ LOGE("bind failed path=[%s] reason=[%s]\n", path, strerror(errno));
+ close(sockfd);
+ return -1;
+ }
+
+ if (chmod(path, 0660) < 0) {
+ LOGE("chmod err = [%s]\n", strerror(errno));
+ }
+ return sockfd;
+}
+
+int agps2mnl_agps_reboot() {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write agps_reboot\n");
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_REBOOT);
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_agps_open_gps_req(int show_gps_icon, mnl_agps_open_type open_type,
+ mnl_agps_open_requestor requestor_type, const char* requestor_id,
+ bool emergency_call) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write agps_open_gps_req show_gps_icon=%d open_type=%d requestor_type=%d requestor_id=%s emergency_call=%d\n",
+ show_gps_icon, open_type, requestor_type, requestor_id, emergency_call);
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_OPEN_GPS_REQ);
+ put_int(buff, &offset, show_gps_icon);
+ put_int(buff, &offset, open_type);
+ put_int(buff, &offset, requestor_type);
+ put_string(buff, &offset, requestor_id, sizeof(buff));
+ put_byte(buff, &offset, emergency_call);
+
+ return send2mnl(buff, offset);
+}
+int agps2mnl_agps_close_gps_req() {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write agps_close_gps_req\n");
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_CLOSE_GPS_REQ);
+
+ return send2mnl(buff, offset);
+}
+int agps2mnl_agps_reset_gps_req(int flags) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write agps_reset_gps_req flags=0x%x\n", flags);
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_RESET_GPS_REQ);
+ put_int(buff, &offset, flags);
+
+ return send2mnl(buff, offset);
+}
+int agps2mnl_agps_open_gps_rejected(mnl_agps_open_type open_type,
+ mnl_agps_open_requestor requestor_type, const char* requestor_id,
+ bool emergency_call) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write agps_open_gps_rejected open_type=%d requestor_type=%d requestor_id=%s emergency_call=%d\n",
+ open_type, requestor_type, requestor_id, emergency_call);
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_OPEN_GPS_REJECTED);
+ put_int(buff, &offset, open_type);
+ put_int(buff, &offset, requestor_type);
+ put_string(buff, &offset, requestor_id, sizeof(buff));
+ put_byte(buff, &offset, emergency_call);
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_agps_session_done() {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write agps_session_done\n");
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_SESSION_DONE);
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_ni_notify(int session_id, mnl_agps_ni_type ni_type, mnl_agps_notify_type type,
+ const char* requestor_id, const char* client_name) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write ni_notify session_id=%d ni_type=%d type=%d requestor_id=[%s] client_name=[%s]\n",
+ session_id, ni_type, type, requestor_id, client_name);
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_NI_NOTIFY);
+ put_int(buff, &offset, session_id);
+ put_int(buff, &offset, type);
+ put_string(buff, &offset, requestor_id, sizeof(buff));
+ put_string(buff, &offset, client_name, sizeof(buff));
+ put_int(buff, &offset, ni_type);
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_ni_notify2(int session_id, mnl_agps_ni_type ni_type, mnl_agps_notify_type type,
+ const char* requestor_id, const char* client_name,
+ mnl_agps_ni_encoding_type requestor_id_encoding,
+ mnl_agps_ni_encoding_type client_name_encoding) {
+
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write ni_notify2 session_id=%d ni_type=%d type=%d requestor_id=[%s] type=%d client_name=[%s] type=%d\n",
+ session_id, ni_type, type, requestor_id, requestor_id_encoding, client_name, client_name_encoding);
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_NI_NOTIFY_2);
+ put_int(buff, &offset, session_id);
+ put_int(buff, &offset, type);
+ put_string(buff, &offset, requestor_id, sizeof(buff));
+ put_string(buff, &offset, client_name, sizeof(buff));
+ put_int(buff, &offset, requestor_id_encoding);
+ put_int(buff, &offset, client_name_encoding);
+ put_int(buff, &offset, ni_type);
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_data_conn_req(int ipaddr, int is_emergency) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write data_conn_req ipaddr=0x%x is_emergency=%d\n", ipaddr, is_emergency);
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_DATA_CONN_REQ);
+ put_int(buff, &offset, ipaddr);
+ put_int(buff, &offset, is_emergency);
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_data_conn_req2(struct sockaddr_storage* addr, int is_emergency,
+ mnl_agps_data_connection_type agps_type) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write data_conn_req2 is_emergency=%d\n", is_emergency);
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_DATA_CONN_REQ2);
+ put_binary(buff, &offset, (const char*)addr, sizeof(*addr));
+ put_int(buff, &offset, is_emergency);
+ put_int(buff, &offset, agps_type);
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_data_conn_release(mnl_agps_data_connection_type agps_type) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write data_conn_release\n");
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_DATA_CONN_RELEASE);
+ put_int(buff, &offset, agps_type);
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_set_id_req(int flags) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write set_id_req flags=0x%x\n", flags);
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_SET_ID_REQ);
+ put_int(buff, &offset, flags);
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_ref_loc_req(int flags) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write ref_loc_req flags=0x%x\n", flags);
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_REF_LOC_REQ);
+ put_int(buff, &offset, flags);
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_pmtk(const char* pmtk) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write pmtk [%s]\n", pmtk);
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_AGPS2MNL_PMTK);
+ put_string(buff, &offset, pmtk, sizeof(buff));
+
+ return send2mnl(buff, offset);
+}
+int agps2mnl_gpevt(gpevt_type type) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("write gpevt type=%d\n", type);
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_GPEVT);
+ put_int(buff, &offset, type);
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_agps_location(mnl_agps_agps_location2* location) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_LOC);
+ put_binary(buff, &offset, (const char*)&location->loc, sizeof(location->loc));
+ put_byte(buff, &offset, location->source_used);
+ put_int(buff, &offset, location->source);
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_cell_location(mnl_agps_agps_location2* location) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_CELL_LOCATION);
+ put_binary(buff, &offset, (const char*)&location->loc, sizeof(location->loc));
+ put_byte(buff, &offset, location->source_used);
+ put_int(buff, &offset, location->source);
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_vzw_debug_screen_output(const char* str) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ LOGD("write vzw_debug_screen_output [%s]\n", str);
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_VZW_DEBUG_SCREEN_OUTPUT);
+ put_string(buff, &offset, str, sizeof(buff));
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_supl_dns_req(const char* fqdn) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ LOGD("write agps2mnl_supl_dns_req [%s]\n", fqdn);
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_SUPL_DNS_REQ);
+ put_string(buff, &offset, fqdn, sizeof(buff));
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_lppe_assist_data_provide_common_iono(const char* data, int len) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ LOGD("write agps2mnl_lppe_assist_data_provide_common_iono\n");
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_IONO);
+ put_binary(buff, &offset, data, len); // refer to gnss_ha_common_ionospheric_model_struct
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_lppe_assist_data_provide_common_trop(const char* data, int len) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ LOGD("write agps2mnl_lppe_assist_data_provide_common_trop\n");
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_TROP);
+ put_binary(buff, &offset, data, len); // refer to gnss_ha_common_troposphere_model_struct
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_lppe_assist_data_provide_common_alt(const char* data, int len) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ LOGD("write agps2mnl_lppe_assist_data_provide_common_alt\n");
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_ALT);
+ put_binary(buff, &offset, data, len); // refer to gnss_ha_common_altitude_assist_struct
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_lppe_assist_data_provide_common_solar(const char* data, int len) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ LOGD("write agps2mnl_lppe_assist_data_provide_common_solar\n");
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_SOLAR);
+ put_binary(buff, &offset, data, len); // refer to gnss_ha_common_solar_radiation_struct
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_lppe_assist_data_provide_common_ccp(const char* data, int len) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ LOGD("write agps2mnl_lppe_assist_data_provide_common_ccp\n");
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_CCP);
+ put_binary(buff, &offset, data, len); // refer to gnss_ha_common_ccp_assist_struct
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_lppe_assist_data_provide_generic_ccp(const char* data, int len) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ LOGD("write agps2mnl_lppe_assist_data_provide_generic_ccp\n");
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_LPPE_ASSIST_GENERIC_CCP);
+ put_binary(buff, &offset, data, len); // refer to gnss_ha_generic_ccp_assist_struct
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_lppe_assist_data_provide_generic_dm(const char* data, int len) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ LOGD("write agps2mnl_lppe_assist_data_provide_generic_dm\n");
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_LPPE_ASSIST_GENERIC_DM);
+ put_binary(buff, &offset, data, len); // refer to gnss_ha_generic_degradation_model_struct
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_md_time_sync_ind(const char* data, int len) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ LOGD("write agps2mnl_md_time_sync_ind\n");
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_MD_TIME_SYNC_IND);
+ put_binary(buff, &offset, data, len); // refer to mnl_md_time_sync_ind_struct
+
+ return send2mnl(buff, offset);
+}
+
+int agps2mnl_md_time_sync_cnf(const char* data, int len) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ LOGD("write agps2mnl_md_time_sync_cnf\n");
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_MD_TIME_SYNC_CNF);
+ put_binary(buff, &offset, data, len); // refer to mnl_md_time_sync_cnf_struct
+
+ return send2mnl(buff, offset);
+}
+void mnl2agps_hdlr(int fd, mnl2agps_interface* agps_interface) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int ret;
+
+ ret = safe_recvfrom(fd, buff, sizeof(buff));
+ if (ret <= 0) {
+ LOGE("agps2mnl_handler() safe_recvfrom() failed ret=%d", ret);
+ return;
+ }
+
+ int version = get_int(buff, &offset, sizeof(buff));
+
+ if (version != MNL_AGPS_INTERFACE_VERSION) {
+ LOGE("mnl_ver=%d agps_ver=%d\n",
+ version, MNL_AGPS_INTERFACE_VERSION);
+ }
+
+ mnl_agps_type type = get_int(buff, &offset, sizeof(buff));
+
+ switch (type) {
+ case MNL_AGPS_TYPE_MNL_REBOOT: {
+ if (agps_interface->mnl_reboot) {
+ agps_interface->mnl_reboot();
+ } else {
+ LOGE("mnl_reboot is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_AGPS_OPEN_GPS_DONE: {
+ if (agps_interface->open_gps_done) {
+ agps_interface->open_gps_done();
+ } else {
+ LOGE("open_gps_done is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_AGPS_CLOSE_GPS_DONE: {
+ if (agps_interface->close_gps_done) {
+ agps_interface->close_gps_done();
+ } else {
+ LOGE("close_gps_done is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_AGPS_RESET_GPS_DONE: {
+ if (agps_interface->reset_gps_done) {
+ agps_interface->reset_gps_done();
+ } else {
+ LOGE("reset_gps_done is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_GPS_INIT: {
+ if (agps_interface->gps_init) {
+ agps_interface->gps_init();
+ } else {
+ LOGE("gps_init is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_GPS_CLEANUP: {
+ if (agps_interface->gps_cleanup) {
+ agps_interface->gps_cleanup();
+ } else {
+ LOGE("gps_cleanup is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_SET_SERVER: {
+ int type = get_int(buff, &offset, sizeof(buff));
+ const char* hostname = get_string(buff, &offset, sizeof(buff));
+ int port = get_int(buff, &offset, sizeof(buff));
+ if (agps_interface->set_server) {
+ agps_interface->set_server(type, hostname, port);
+ } else {
+ LOGE("set_server is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_DELETE_AIDING_DATA: {
+ int flags = get_int(buff, &offset, sizeof(buff));
+ if (agps_interface->delete_aiding_data) {
+ agps_interface->delete_aiding_data(flags);
+ } else {
+ LOGE("delete_aiding_data is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_GPS_OPEN: {
+ int assist_req = get_int(buff, &offset, sizeof(buff));
+ if (agps_interface->gps_open) {
+ agps_interface->gps_open(assist_req);
+ } else {
+ LOGE("gps_open is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_GPS_CLOSE: {
+ if (agps_interface->gps_close) {
+ agps_interface->gps_close();
+ } else {
+ LOGE("gps_close is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_DATA_CONN_OPEN: {
+ const char* apn = get_string(buff, &offset, sizeof(buff));
+ if (agps_interface->data_conn_open) {
+ agps_interface->data_conn_open(apn);
+ } else {
+ LOGE("data_conn_open is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_DATA_CONN_OPEN_IP_TYPE: {
+ const char* apn = get_string(buff, &offset, sizeof(buff));
+ int ip_type = get_int(buff, &offset, sizeof(buff));
+ bool network_handle_valid = get_byte(buff, &offset, sizeof(buff));
+ uint64_t network_handle = get_long(buff, &offset, sizeof(buff));
+ if (agps_interface->data_conn_open_ip_type) {
+ agps_interface->data_conn_open_ip_type(apn, ip_type,
+ network_handle_valid, network_handle);
+ } else {
+ LOGE("data_conn_open_ip_type is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_INSTALL_CERTIFICATES: {
+ int index = get_int(buff, &offset, sizeof(buff));
+ int total = get_int(buff, &offset, sizeof(buff));
+ char data[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int len = get_binary(buff, &offset, data, sizeof(buff), sizeof(data));
+ if (agps_interface->install_certificates) {
+ agps_interface->install_certificates(index, total, data, len);
+ } else {
+ LOGE("install_certificates is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_REVOKE_CERTIFICATES: {
+ char data[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int len = get_binary(buff, &offset, data, sizeof(buff), sizeof(data));
+ if (agps_interface->revoke_certificates) {
+ agps_interface->revoke_certificates(data, len);
+ } else {
+ LOGE("revoke_certificates is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_UPDATE_GNSS_ACCESS_CONTROL: {
+ bool allowed = get_byte(buff, &offset, sizeof(buff));
+ if(agps_interface->update_gnss_access_control) {
+ agps_interface->update_gnss_access_control(allowed);
+ } else {
+ LOGE("update_gnss_access_control is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_DATA_CONN_FAILED: {
+ if (agps_interface->data_conn_failed) {
+ agps_interface->data_conn_failed();
+ } else {
+ LOGE("data_conn_failed is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_DATA_CONN_CLOSED: {
+ if (agps_interface->data_conn_closed) {
+ agps_interface->data_conn_closed();
+ } else {
+ LOGE("data_conn_closed is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_NI_MESSAGE: {
+ char msg[1024] = {0};
+ int len;
+ len = get_binary(buff, &offset, msg, sizeof(buff), sizeof(msg));
+ if (agps_interface->ni_message) {
+ agps_interface->ni_message(msg, len);
+ } else {
+ LOGE("ni_message is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_NI_RESPOND: {
+ int session_id = get_int(buff, &offset, sizeof(buff));
+ int user_response = get_int(buff, &offset, sizeof(buff));
+ if (agps_interface->ni_respond) {
+ agps_interface->ni_respond(session_id, user_response);
+ } else {
+ LOGE("ni_respond is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_SET_REF_LOC: {
+ int type = get_int(buff, &offset, sizeof(buff));
+ int mcc = get_int(buff, &offset, sizeof(buff));
+ int mnc = get_int(buff, &offset, sizeof(buff));
+ int lac = get_int(buff, &offset, sizeof(buff));
+ int cid = get_int(buff, &offset, sizeof(buff));
+ if (agps_interface->set_ref_loc) {
+ agps_interface->set_ref_loc(type, mcc, mnc, lac, cid);
+ } else {
+ LOGE("set_ref_loc is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_SET_SET_ID: {
+ int type = get_int(buff, &offset, sizeof(buff));
+ const char* setid = get_string(buff, &offset, sizeof(buff));
+ if (agps_interface->set_set_id) {
+ agps_interface->set_set_id(type, setid);
+ } else {
+ LOGE("set_set_id is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_UPDATE_NETWORK_STATE: {
+ int connected = get_int(buff, &offset, sizeof(buff));
+ int type = get_int(buff, &offset, sizeof(buff));
+ int roaming = get_int(buff, &offset, sizeof(buff));
+ const char* extra_info = get_string(buff, &offset, sizeof(buff));
+ if (agps_interface->update_network_state) {
+ agps_interface->update_network_state(connected, type, roaming, extra_info);
+ } else {
+ LOGE("update_network_state is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_UPDATE_NETWORK_AVAILABILITY: {
+ int avaiable = get_int(buff, &offset, sizeof(buff));
+ const char* apn = get_string(buff, &offset, sizeof(buff));
+ if (agps_interface->update_network_availability) {
+ agps_interface->update_network_availability(avaiable, apn);
+ } else {
+ LOGE("update_network_availability is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_MNL2AGPS_PMTK: {
+ const char* pmtk = get_string(buff, &offset, sizeof(buff));
+ if (agps_interface->rcv_pmtk) {
+ agps_interface->rcv_pmtk(pmtk);
+ } else {
+ LOGE("rcv_pmtk is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_RAW_DBG: {
+ int enabled = get_int(buff, &offset, sizeof(buff));
+ if (agps_interface->raw_dbg) {
+ agps_interface->raw_dbg(enabled);
+ } else {
+ LOGE("raw_dbg is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_REAIDING: {
+ if (agps_interface->reaiding_req) {
+ agps_interface->reaiding_req();
+ } else {
+ LOGE("reaiding_req is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_LOCATION_SYNC: {
+ if (agps_interface->location_sync) {
+ double lat = get_double(buff, &offset, sizeof(buff));
+ double lng = get_double(buff, &offset, sizeof(buff));
+ int acc = get_int(buff, &offset, sizeof(buff));
+ bool alt_valid = get_byte(buff, &offset, sizeof(buff));
+ float alt = get_float(buff, &offset, sizeof(buff));
+ bool source_valid = get_byte(buff, &offset, sizeof(buff));
+ bool source_gnss = get_byte(buff, &offset, sizeof(buff));
+ bool source_nlp = get_byte(buff, &offset, sizeof(buff));
+ bool source_sensor = get_byte(buff, &offset, sizeof(buff));
+ bool utc_time_valid = get_byte(buff, &offset, sizeof(buff));
+ unsigned long long utc_time = (unsigned long long)get_long(buff, &offset, sizeof(buff));
+ agps_interface->location_sync(lat, lng, acc, alt_valid, alt, source_valid, source_gnss, source_nlp, source_sensor, utc_time_valid, utc_time);
+ } else {
+ LOGE("location_sync is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_SET_POSITION_MODE: {
+ if(agps_interface->set_position_mode) {
+ int pos_mode = get_int(buff, &offset, sizeof(buff));
+ agps_interface->set_position_mode(pos_mode);
+ } else {
+ LOGE("set_position_mode is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_UPDATE_NETWORK_STATE_WITH_HANDLE: {
+ uint64_t network_handle = get_long(buff, &offset, sizeof(buff));
+ char connected = get_byte(buff, &offset, sizeof(buff));
+ unsigned short capabilities = get_short(buff, &offset, sizeof(buff));
+ const char* apn = get_string(buff, &offset, sizeof(buff));
+ if(agps_interface->update_network_state_with_handle) {
+ agps_interface->update_network_state_with_handle(network_handle, connected, capabilities, apn);
+ } else {
+ LOGE("update_network_state_with_handle is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_MD_TIME_SYNC_REQ: {
+ if(agps_interface->md_time_sync_req) {
+ char data[MNL_AGPS_MAX_BUFF_SIZE/8] = {0};
+ int len = get_binary(buff, &offset, data, MNL_AGPS_MAX_BUFF_SIZE/8, sizeof(data));
+ agps_interface->md_time_sync_req(data, len);
+ } else {
+ LOGE("md_time_sync_req is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_MD_TIME_SYNC_RSP: {
+ if(agps_interface->md_time_sync_rsp) {
+ char data[MNL_AGPS_MAX_BUFF_SIZE/8] = {0};
+ int len = get_binary(buff, &offset, data, MNL_AGPS_MAX_BUFF_SIZE/8, sizeof(data));
+ agps_interface->md_time_sync_rsp(data, len);
+ } else {
+ LOGE("md_time_sync_rsp is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_MD_TIME_INFO_RSP: {
+ if(agps_interface->md_time_info_rsp) {
+ char data[MNL_AGPS_MAX_BUFF_SIZE/8] = {0};
+ int len = get_binary(buff, &offset, data, MNL_AGPS_MAX_BUFF_SIZE/8, sizeof(data));
+ agps_interface->md_time_info_rsp(data, len);
+ } else {
+ LOGE("md_time_info_rsp is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_GNSS_TIME_SYNC: {
+ if(agps_interface->gnss_time_sync) {
+ unsigned long long utc_time = (unsigned long long)get_long(buff, &offset, sizeof(buff));
+ agps_interface->gnss_time_sync(utc_time);
+ } else {
+ LOGE("gnss_time_sync is NULL\n");
+ }
+ break;
+ }
+ default:
+ LOGE("mnl2agps unknown type=%d\n", type);
+ break;
+ }
+}
+
+int create_mnl2agps_fd(const char* agps2mnl_path, const char* mnl2agps_path) {
+ int fd = bind_udp_socket((char *)mnl2agps_path);
+ if(fd == -1) {
+ //Android P0, /data folder cannot be used anymore, use the abstract socket instead
+ LOGD("it's a Android P version, bind mtk_mnl2agps instead");
+ fd = sock_udp_server_bind_local(true, "mtk_mnl2agps");
+ if(fd == -1) {
+ return -1;
+ }
+ }
+ set_socket_blocking(fd, 0);
+ MNLD_STRNCPY(g_agps2mnl_path, agps2mnl_path, sizeof(g_agps2mnl_path));
+ return fd;
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/src/mnl2agps_interface.c b/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/src/mnl2agps_interface.c
new file mode 100644
index 0000000..7c47014
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/src/mnl2agps_interface.c
@@ -0,0 +1,1117 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include <arpa/inet.h> // inet_addr
+#include <sys/un.h> // struct sockaddr_un
+#include <inttypes.h> //PRId64
+#include <unistd.h> //usleep
+
+#if defined(__TIZEN_OS__)
+#include <dlog/dlog.h>
+#endif
+
+#include "mtk_mnld_log.h"
+
+#include "mnl2agps_interface.h"
+#include "data_coder.h"
+
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+static char g_mnl2agps_path[128] = MNL_TO_AGPS;
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#ifndef MNLD_STRNCPY
+#define MNLD_STRNCPY(dst,src,size) do{\
+ strncpy((char *)(dst), (char *)(src), (size - 1));\
+ (dst)[size - 1] = '\0';\
+ }while(0)
+#endif
+
+#define LOG_TAG "MNL2AGPS"
+
+// -1 means failure
+static int safe_recvfrom(int sockfd, char* buf, int len) {
+ int ret = 0;
+ int retry = 10;
+
+ while ((ret = recvfrom(sockfd, buf, len, 0,
+ NULL, NULL)) == -1) {
+ LOGW("ret=%d len=%d\n", ret, len);
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("sendto reason=[%s]\n", strerror(errno));
+ break;
+ }
+ return ret;
+}
+
+// -1 means failure
+static int set_socket_blocking(int fd, int blocking) {
+ if (fd < 0) {
+ LOGE("set_socket_blocking invalid fd=%d\n", fd);
+ return -1;
+ }
+
+ int flags = fcntl(fd, F_GETFL, 0);
+ if (flags < 0) {
+ LOGE("set_socket_blocking invalid flags=%d\n", flags);
+ return -1;
+ }
+
+ flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);
+ return (fcntl(fd, F_SETFL, flags) == 0) ? 0 : -1;
+}
+
+// -1 means failure
+static int safe_sendto(int sockfd, const char* dest, const char* buf, int size) {
+ int len = 0;
+ struct sockaddr_un soc_addr;
+ socklen_t addr_len;
+ int retry = 10;
+
+ MNLD_STRNCPY(soc_addr.sun_path, dest,sizeof(soc_addr.sun_path));
+ soc_addr.sun_family = AF_UNIX;
+ addr_len = (offsetof(struct sockaddr_un, sun_path) + strlen(soc_addr.sun_path) + 1);
+
+ while ((len = sendto(sockfd, buf, size, 0,
+ (const struct sockaddr *)&soc_addr, (socklen_t)addr_len)) == -1) {
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("sendto dest=[%s] len=%d reason=[%s]\n",
+ dest, size, strerror(errno));
+ break;
+ }
+ return len;
+}
+
+static int is_path_exist(const char* path) {
+ struct stat s;
+ int err = stat(path, &s);
+ if(-1 == err) {
+ if(ENOENT == errno) {
+ // does not exist
+ return 0;
+ } else {
+ // perror("stat");
+ return 0;
+ }
+ } else {
+ if(S_ISDIR(s.st_mode)) {
+ // it's a dir
+ return 1;
+ } else {
+ // it's a file
+ return 2;
+ }
+ }
+ return 0;
+}
+
+static void utils_strncpy(char* dest, const char* src, size_t n) {
+ if (dest && n > 0) {
+ // Use strncat for performance because strncpy will always fill n bytes in dest
+ dest[0] = '\0'; // Let dest be an empty string
+ strncat(dest, src, --n); // n-1 because strncat may fill n+1 bytes
+ }
+}
+
+// -1 mean fail or clientfd is returned
+static int sock_udp_client_create_local(bool is_abstract, const char* name) {
+ int fd = -1;
+ 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(is_abstract) {
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, name, strlen(name));
+ } else {
+ utils_strncpy(addr.sun_path, name, sizeof(addr.sun_path));
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd == -1) {
+ LOGE("socket() failed, reason=[%s]%d", strerror(errno), errno);
+ return -1;
+ }
+ if(connect(fd, (struct sockaddr *)&addr, size) == -1) {
+ LOGE("connect() failed, abstract=%d name=[%s] reason=[%s]%d",
+ is_abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+// -1 mean fail or return the number of byte are written
+static int fd_write(int fd, const void* buff, uint32_t len) {
+ int ret;
+ if(buff == NULL) {
+ LOGE("buff is NULL");
+ return -1;
+ }
+ if(len == 0) {
+ LOGE("fd_write() len=%d is invalid", len);
+ return -1;
+ }
+ ret = write(fd, buff, len);
+ if(ret == -1) {
+ LOGE("fd_write() write() failed, fd=%d len=%d reason=[%s]%d",
+ fd, len, strerror(errno), errno);
+ return -1;
+ }
+ return ret;
+}
+
+// -1 means failure
+static int mnl2agps_socket_set_reuse_addr(int fd, bool reuse) {
+ int val = (int)reuse;
+ int newval;
+ socklen_t intlen = sizeof(newval);
+
+ if (0 != setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) {
+ LOGE("setsockopt(SO_REUSEADDR) fail %s(%d)", strerror(errno), errno);
+ return -1;
+ }
+
+ if (0 != getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &newval, &intlen)) {
+ LOGE("getsockopt(SO_REUSEADDR) fail %s(%d)", strerror(errno), errno);
+ return -1;
+ }
+
+ if (newval != val) {
+ LOGE("Failed to set SO_REUSEADDR");
+ return -1;
+ }
+
+ return 0;
+}
+
+// -1 mean fail or serverfd is returned
+static int sock_udp_server_bind_local(bool is_abstract, const char* name) {
+ int fd = -1;
+ 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(is_abstract) {
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, name, strlen(name));
+ } else {
+ utils_strncpy(addr.sun_path, name, sizeof(addr.sun_path));
+ if(unlink(addr.sun_path) == -1) {
+ LOGE("unlink() failed, reason=[%s]%d", strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (fd == -1) {
+ LOGE("socket() failed, reason=[%s]%d", strerror(errno), errno);
+ return -1;
+ }
+
+ if(mnl2agps_socket_set_reuse_addr(fd, true) == -1) {
+ LOGE("sock_udp_server_bind_local() mnl2agps_socket_set_reuse_addr() failed path=[%s] reason=[%s]%d",
+ name, strerror(errno), errno);
+ }
+
+ if (bind(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("bind() failed, abstract=%d name=[%s] reason=[%s]%d",
+ is_abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+// -1 means failure
+static int send2agps(const char* buff, int len) {
+ int ret = 0;
+
+ int fd = sock_udp_client_create_local(true, "mtk_mnl2agps");
+ if(fd == -1) {
+ return -1;
+ }
+ ret = fd_write(fd, buff, len);
+ close(fd);
+ return ret;
+}
+
+static int bind_udp_socket(char* path) {
+ int fd;
+ struct sockaddr_un addr;
+ socklen_t addr_len;
+
+ fd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ LOGE("socket_bind_udp() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ MNLD_STRNCPY(addr.sun_path, path,sizeof(addr.sun_path));
+ addr.sun_family = AF_UNIX;
+ addr_len = (offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1);
+ unlink(addr.sun_path);
+
+ if(mnl2agps_socket_set_reuse_addr(fd, true) == -1) {
+ LOGE("bind_udp_socket() mnl2agps_socket_set_reuse_addr() failed path=[%s] reason=[%s]%d",
+ path, strerror(errno), errno);
+ }
+
+ if (bind(fd, (struct sockaddr *)&addr, addr_len) < 0) {
+ LOGE("bind failed path=[%s] reason=[%s]\n", path, strerror(errno));
+ close(fd);
+ return -1;
+ }
+ if (chmod(path, 0660) < 0) {
+ LOGE("chmod err = [%s]\n", strerror(errno));
+ }
+
+ return fd;
+}
+
+int mnl2agps_mnl_reboot() {
+ LOGD("mnl2agps_mnl_reboot");
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_MNL_REBOOT);
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_open_gps_done() {
+ LOGD("mnl2agps_open_gps_done");
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_OPEN_GPS_DONE);
+
+ return send2agps(buff, offset);
+}
+int mnl2agps_close_gps_done() {
+ LOGD("mnl2agps_close_gps_done");
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_CLOSE_GPS_DONE);
+
+ return send2agps(buff, offset);
+}
+int mnl2agps_reset_gps_done() {
+ LOGD("mnl2agps_reset_gps_done");
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_RESET_GPS_DONE);
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_gps_init() {
+ LOGD("mnl2agps_gps_init");
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_GPS_INIT);
+ return send2agps(buff, offset);
+}
+int mnl2agps_gps_cleanup() {
+ LOGD("mnl2agps_gps_cleanup");
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_GPS_CLEANUP);
+
+ return send2agps(buff, offset);
+}
+// type:AGpsType
+int mnl2agps_set_server(int type, const char* hostname, int port) {
+ //LOGD("mnl2agps_set_server, hostname = %s, port = %d\n", hostname, port);
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_SET_SERVER);
+ put_int(buff, &offset, type);
+ put_string(buff, &offset, hostname, sizeof(buff));
+ put_int(buff, &offset, port);
+
+ return send2agps(buff, offset);
+}
+// flags:GpsAidingData
+int mnl2agps_delete_aiding_data(int flags) {
+ //LOGD("mnl2agps_delete_aiding_data");
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_DELETE_AIDING_DATA);
+ put_int(buff, &offset, flags);
+
+ return send2agps(buff, offset);
+}
+int mnl2agps_gps_open(int assist_req) {
+ LOGD("mnl2agps_gps_open");
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_GPS_OPEN);
+ put_int(buff, &offset, assist_req);
+
+ return send2agps(buff, offset);
+}
+int mnl2agps_gps_close() {
+ LOGD("mnl2agps_gps_close");
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_GPS_CLOSE);
+
+ return send2agps(buff, offset);
+}
+int mnl2agps_data_conn_open(const char* apn) {
+ //LOGD("mnl2agps_data_conn_open, apn = %s\n", apn);
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_DATA_CONN_OPEN);
+ put_string(buff, &offset, apn, sizeof(buff));
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_data_conn_open_ip_type(const char* apn, int ip_type,
+ bool network_handle_valid, uint64_t network_handle) {
+ LOGD("mnl2agps_data_conn_open apn=%s ip_type=%d network_handle=[%"PRId64"]%d\n",
+ apn, ip_type, network_handle, network_handle_valid);
+
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_DATA_CONN_OPEN_IP_TYPE);
+ put_string(buff, &offset, apn, sizeof(buff));
+ put_int(buff, &offset, ip_type);
+
+ put_byte(buff, &offset, network_handle_valid);
+ put_long(buff, &offset, network_handle);
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_install_certificates(int index, int total, const char* data, int len) {
+ LOGD("mnl2agps_install_certificates (%d/%d) len=%d\n", index, total, len);
+
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_INSTALL_CERTIFICATES);
+ put_int(buff, &offset, index);
+ put_int(buff, &offset, total);
+ put_binary(buff, &offset, data, len);
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_revoke_certificates(const char* data, int len) {
+ LOGD("mnl2agps_revoke_certificates len=%d item=%d\n", len, len/20);
+
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_REVOKE_CERTIFICATES);
+ put_binary(buff, &offset, data, len);
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_update_gnss_access_control(bool allowed) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("mnl2agps_update_gnss_access_control allowed=%d\n", allowed);
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_UPDATE_GNSS_ACCESS_CONTROL);
+ put_byte(buff, &offset, allowed);
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_data_conn_failed() {
+ LOGD("mnl2agps_data_conn_failed");
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_DATA_CONN_FAILED);
+
+ return send2agps(buff, offset);
+}
+int mnl2agps_data_conn_closed() {
+ //LOGD("mnl2agps_data_conn_closed");
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_DATA_CONN_CLOSED);
+
+ return send2agps(buff, offset);
+}
+int mnl2agps_ni_message(const char* msg, int len) {
+ //LOGD("mnl2agps_ni_message");
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_NI_MESSAGE);
+ put_binary(buff, &offset, msg, len);
+
+ return send2agps(buff, offset);
+}
+
+/*
+ACCEPT = 1
+DENY = 2
+NO_RSP = 3
+*/
+int mnl2agps_ni_respond(int session_id, int user_response) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ //LOGD("session_id: %d, user_response: %d\n", session_id, user_response);
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_NI_RESPOND);
+ put_int(buff, &offset, session_id);
+ put_int(buff, &offset, user_response);
+
+ return send2agps(buff, offset);
+}
+int mnl2agps_set_ref_loc(int type, int mcc, int mnc, int lac, int cid) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ //LOGD("type=%d, mcc=%d, mnc=%d, lac=%d, cid=%d\n", type, mcc, mnc, lac, cid);
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_SET_REF_LOC);
+ put_int(buff, &offset, type);
+ put_int(buff, &offset, mcc);
+ put_int(buff, &offset, mnc);
+ put_int(buff, &offset, lac);
+ put_int(buff, &offset, cid);
+
+ return send2agps(buff, offset);
+}
+int mnl2agps_set_set_id(int type, const char* setid) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ //LOGD("type=%d, setid = %s\n", type, setid);
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_SET_SET_ID);
+ put_int(buff, &offset, type);
+ put_string(buff, &offset, setid, sizeof(buff));
+
+ return send2agps(buff, offset);
+}
+int mnl2agps_update_network_state(int connected, int type, int roaming, const char* extra_info) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ //LOGD("connected=%d, type = %d, roaming=%d, extra_info=%s\n", connected, type, roaming, extra_info);
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_UPDATE_NETWORK_STATE);
+ put_int(buff, &offset, connected);
+ put_int(buff, &offset, type);
+ put_int(buff, &offset, roaming);
+ put_string(buff, &offset, extra_info, sizeof(buff));
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_update_network_availability(int avaiable, const char* apn) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ //LOGD("avaiable=%d, apn=%s\n", avaiable, apn);
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_UPDATE_NETWORK_AVAILABILITY);
+ put_int(buff, &offset, avaiable);
+ put_string(buff, &offset, apn, sizeof(buff));
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_pmtk(const char* pmtk) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_MNL2AGPS_PMTK);
+ put_string(buff, &offset, pmtk, sizeof(buff));
+
+ return send2agps(buff, offset);
+}
+int mnl2agps_raw_dbg(int enabled) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_RAW_DBG);
+ put_int(buff, &offset, enabled);
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_reaiding_req() {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_REAIDING);
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_location_sync(mnl_agps_location_time* location_sync_data) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_LOCATION_SYNC);
+ put_double(buff, &offset, location_sync_data->lat);
+ put_double(buff, &offset, location_sync_data->lng);
+ put_int(buff, &offset, location_sync_data->acc);
+ put_byte(buff, &offset, location_sync_data->alt_valid);
+ put_float(buff, &offset, location_sync_data->alt);
+ put_byte(buff, &offset, location_sync_data->source_valid);
+ put_byte(buff, &offset, location_sync_data->source_gnss);
+ put_byte(buff, &offset, location_sync_data->source_nlp);
+ put_byte(buff, &offset, location_sync_data->source_sensor);
+ put_byte(buff, &offset, location_sync_data->utc_time_sync.utc_time_valid);
+ put_long(buff, &offset, location_sync_data->utc_time_sync.utc_time);
+ put_byte(buff, &offset, location_sync_data->sv_inuse_num_valid);
+ put_int(buff, &offset, location_sync_data->sv_inuse_num);
+
+ return send2agps(buff, offset);
+}
+int mnl2agps_agps_settings_ack(mnl_agps_gnss_settings* settings) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_SETTINGS_ACK);
+ put_int(buff, &offset, settings->gps_satellite_support);
+ put_int(buff, &offset, settings->glonass_satellite_support);
+ put_int(buff, &offset, settings->beidou_satellite_support);
+ put_int(buff, &offset, settings->galileo_satellite_support);
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_vzw_debug_screen_enable(int enabled) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_VZW_DEBUG_SCREEN_ENABLE);
+ put_int(buff, &offset, enabled);
+
+ return send2agps(buff, offset);
+}
+int mnl2agps_lppe_assist_data_req(const char* data, int len) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_LPPE_ASSIST_DATA_REQ);
+ put_binary(buff, &offset, data, len); // refer to gnss_ha_assist_data_req_struct
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_lppe_assist_data_provide_ack(const char* data, int len) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_LPPE_ASSIST_DATA_PROVIDE_ACK);
+ put_binary(buff, &offset, data, len); // refer to gnss_ha_assist_ack_struct
+
+ return send2agps(buff, offset);
+}
+void mnl2fake_agpsd_hdlr(int fd) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ int ret;
+
+ ret = safe_recvfrom(fd, buff, sizeof(buff));
+ if (ret <= 0) {
+ LOGE("mnl2agps_handler() safe_recvfrom() failed ret=%d", ret);
+ return;
+ }
+ int version = get_int(buff, &offset, sizeof(buff));
+
+ if (version != MNL_AGPS_INTERFACE_VERSION) {
+ LOGE("agps_ver=%d mnl_ver=%d\n",
+ version, MNL_AGPS_INTERFACE_VERSION);
+ }
+ mnl_agps_type type = get_int(buff, &offset, sizeof(buff));
+ LOGE("*#*#type:%d\n",type);
+}
+
+int mnl2agps_update_configuration(const char* config_data, int length) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_UPDATE_CONFIGURATION);
+ put_string(buff, &offset, config_data, sizeof(buff));
+ put_int(buff, &offset, length);
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_set_position_mode(int pos_mode) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+ LOGD_ENG("mnl2agps_set_position_mode, pos_mode = %d", pos_mode);
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_SET_POSITION_MODE);
+ put_int(buff, &offset, pos_mode);
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_md_time_sync_req(const char* data, int len) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_MD_TIME_SYNC_REQ);
+ put_binary(buff, &offset, data, len); // refer to mnl_md_time_sync_req_struct
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_md_time_sync_rsp(const char* data, int len) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_MD_TIME_SYNC_RSP);
+ put_binary(buff, &offset, data, len); // refer to mnl_md_time_sync_rsp_struct
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_md_time_info_rsp(const char* data, int len) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_MD_TIME_INFO_RSP);
+ put_binary(buff, &offset, data, len); // refer to mnl_md_time_info_rsp_struct
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_update_network_state_with_handle(uint64_t network_handle,
+ bool is_connected, unsigned short capabilities, const char* apn) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ LOGD("update network with handle=%"PRId64" connected=%d, capabilities = %d, apn=%s\n",
+ network_handle, is_connected, capabilities, apn);
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_UPDATE_NETWORK_STATE_WITH_HANDLE);
+ put_long(buff, &offset, network_handle);
+ put_byte(buff, &offset, is_connected);
+ put_short(buff, &offset, capabilities);
+ put_string(buff, &offset, apn, sizeof(buff));
+
+ return send2agps(buff, offset);
+}
+
+int mnl2agps_gnss_time_sync(long long utc_time) {
+ char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL_AGPS_TYPE_GNSS_TIME_SYNC);
+ put_long(buff, &offset, utc_time);
+
+ return send2agps(buff, offset);
+}
+
+void agps2mnl_hdlr(int fd, agps2mnl_interface* mnl_interface) {
+ char buff[MNL_AGPS_MAX_BUFF_RCV_SIZE] = {0};
+ int offset = 0;
+ int ret;
+
+ ret = safe_recvfrom(fd, buff, sizeof(buff));
+ if (ret <= 0) {
+ LOGE("mnl2agps_handler() safe_recvfrom() failed ret=%d", ret);
+ return;
+ }
+ int version = get_int(buff, &offset, sizeof(buff));
+
+ if (version != MNL_AGPS_INTERFACE_VERSION) {
+ LOGE("agps_ver=%d mnl_ver=%d\n",
+ version, MNL_AGPS_INTERFACE_VERSION);
+ }
+
+ mnl_agps_type type = get_int(buff, &offset, sizeof(buff));
+ // LOGD("agps2mnl [%s]\n", get_mnl_agps_type_str(type));
+
+ switch (type) {
+ case MNL_AGPS_TYPE_AGPS_REBOOT: {
+ if (mnl_interface->agps_reboot) {
+ mnl_interface->agps_reboot();
+ } else {
+ LOGE("agps_reboot is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_AGPS_OPEN_GPS_REQ: {
+ int show_gps_icon = get_int(buff, &offset, sizeof(buff));
+ mnl_agps_open_type open_type = get_int(buff, &offset, sizeof(buff));
+ mnl_agps_open_requestor requestor_type = get_int(buff, &offset, sizeof(buff));
+ const char* requestor_id = get_string(buff, &offset, sizeof(buff));
+ bool emergency_call = get_byte(buff, &offset, sizeof(buff));
+ if (mnl_interface->agps_open_gps_req) {
+ mnl_interface->agps_open_gps_req(show_gps_icon, open_type,
+ requestor_type, requestor_id, emergency_call);
+ } else {
+ LOGE("agps_open_gps_req is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_AGPS_CLOSE_GPS_REQ: {
+ if (mnl_interface->agps_close_gps_req) {
+ mnl_interface->agps_close_gps_req();
+ } else {
+ LOGE("agps_close_gps_req is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_AGPS_RESET_GPS_REQ: {
+ int flags = get_int(buff, &offset, sizeof(buff));
+ if (mnl_interface->agps_reset_gps_req) {
+ mnl_interface->agps_reset_gps_req(flags);
+ } else {
+ LOGE("agps_reset_gps_req is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_AGPS_OPEN_GPS_REJECTED: {
+ mnl_agps_open_type open_type = get_int(buff, &offset, sizeof(buff));
+ mnl_agps_open_requestor requestor_type = get_int(buff, &offset, sizeof(buff));
+ const char* requestor_id = get_string(buff, &offset, sizeof(buff));
+ bool emergency_call = get_byte(buff, &offset, sizeof(buff));
+ if(mnl_interface->agps_open_gps_rejected) {
+ mnl_interface->agps_open_gps_rejected(open_type, requestor_type, requestor_id, emergency_call);
+ } else {
+ LOGE("agps_open_gps_rejected is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_AGPS_SESSION_DONE: {
+ if (mnl_interface->agps_session_done) {
+ mnl_interface->agps_session_done();
+ } else {
+ LOGE("agps_session_done is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_NI_NOTIFY: {
+ int session_id = get_int(buff, &offset, sizeof(buff));
+ mnl_agps_notify_type type = get_int(buff, &offset, sizeof(buff));
+ const char* requestor_id = get_string(buff, &offset, sizeof(buff));
+ const char* client_name = get_string(buff, &offset, sizeof(buff));
+ mnl_agps_ni_type ni_type = get_int(buff, &offset, sizeof(buff));
+ if (mnl_interface->ni_notify) {
+ mnl_interface->ni_notify(session_id, ni_type, type, requestor_id, client_name);
+ } else {
+ LOGE("ni_notify is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_NI_NOTIFY_2: {
+ int session_id = get_int(buff, &offset, sizeof(buff));
+ mnl_agps_notify_type type = get_int(buff, &offset, sizeof(buff));
+ const char* requestor_id = get_string(buff, &offset, sizeof(buff));
+ const char* client_name = get_string(buff, &offset, sizeof(buff));
+ int requestor_id_encoding = get_int(buff, &offset, sizeof(buff));
+ int client_name_encoding = get_int(buff, &offset, sizeof(buff));
+ mnl_agps_ni_type ni_type = get_int(buff, &offset, sizeof(buff));
+ if (mnl_interface->ni_notify2) {
+ mnl_interface->ni_notify2(session_id, ni_type, type, requestor_id,
+ client_name, requestor_id_encoding, client_name_encoding);
+ } else {
+ LOGE("ni_notify2 is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_DATA_CONN_REQ: {
+ int ipaddr = get_int(buff, &offset, sizeof(buff));
+ int is_emergency = get_int(buff, &offset, sizeof(buff));
+ if (mnl_interface->data_conn_req) {
+ mnl_interface->data_conn_req(ipaddr, is_emergency);
+ } else {
+ LOGE("data_conn_req is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_DATA_CONN_REQ2: {
+ struct sockaddr_storage addr;
+ get_binary(buff, &offset, (char*)&addr, sizeof(buff), sizeof(addr));
+ int is_emergency = get_int(buff, &offset, sizeof(buff));
+ mnl_agps_data_connection_type agps_type = get_int(buff, &offset, sizeof(buff));
+ if (mnl_interface->data_conn_req2) {
+ mnl_interface->data_conn_req2(&addr, is_emergency, agps_type);
+ } else {
+ LOGE("data_conn_req2 is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_DATA_CONN_RELEASE: {
+ mnl_agps_data_connection_type agps_type = get_int(buff, &offset, sizeof(buff));
+ if (mnl_interface->data_conn_release) {
+ mnl_interface->data_conn_release(agps_type);
+ } else {
+ LOGE("data_conn_release is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_SET_ID_REQ: {
+ int flags = get_int(buff, &offset, sizeof(buff));
+ if (mnl_interface->set_id_req) {
+ mnl_interface->set_id_req(flags);
+ } else {
+ LOGE("set_id_req is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_REF_LOC_REQ: {
+ int flags = get_int(buff, &offset, sizeof(buff));
+ if (mnl_interface->ref_loc_req) {
+ mnl_interface->ref_loc_req(flags);
+ } else {
+ LOGE("ref_loc_req is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_AGPS2MNL_PMTK: {
+ const char* pmtk = get_string(buff, &offset, sizeof(buff));
+ if (mnl_interface->rcv_pmtk) {
+ mnl_interface->rcv_pmtk(pmtk);
+ } else {
+ LOGE("rcv_pmtk is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_GPEVT: {
+ gpevt_type type = get_int(buff, &offset, sizeof(buff));
+ if (mnl_interface->gpevt) {
+ mnl_interface->gpevt(type);
+ } else {
+ LOGE("gpevt is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_AGPS_LOC: {
+ mnl_agps_agps_location2 agps_location;
+ get_binary(buff, &offset, (char*)&(agps_location.loc), sizeof(buff), sizeof(mnl_agps_agps_location));
+ agps_location.source_used = get_byte(buff, &offset, sizeof(buff));
+ agps_location.source = get_int(buff, &offset, sizeof(buff));
+ if (mnl_interface->agps_location) {
+ mnl_interface->agps_location(&agps_location);
+ } else {
+ LOGE("agps_location is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_CELL_LOCATION: {
+ mnl_agps_agps_location2 cell_location;
+ get_binary(buff, &offset, (char*)&(cell_location.loc), sizeof(buff), sizeof(mnl_agps_agps_location));
+ cell_location.source_used = get_byte(buff, &offset, sizeof(buff));
+ cell_location.source = get_int(buff, &offset, sizeof(buff));
+ if (mnl_interface->cell_location) {
+ mnl_interface->cell_location(&cell_location);
+ } else {
+ LOGE("cell_location is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_SETTINGS_SYNC: {
+ mnl_agps_agps_settings agps_settings;
+ agps_settings.sib8_16_enable = get_int(buff, &offset, sizeof(buff));
+ agps_settings.gps_satellite_enable = get_int(buff, &offset, sizeof(buff));
+ agps_settings.glonass_satellite_enable = get_int(buff, &offset, sizeof(buff));
+ agps_settings.beidou_satellite_enable = get_int(buff, &offset, sizeof(buff));
+ agps_settings.galileo_satellite_enable = get_int(buff, &offset, sizeof(buff));
+ agps_settings.a_glonass_satellite_enable = get_int(buff, &offset, sizeof(buff));
+ agps_settings.a_gps_satellite_enable = get_int(buff, &offset, sizeof(buff));
+ agps_settings.a_beidou_satellite_enable = get_int(buff, &offset, sizeof(buff));
+ agps_settings.a_galileo_satellite_enable = get_int(buff, &offset, sizeof(buff));
+ agps_settings.lppe_enable = get_int(buff, &offset, sizeof(buff));
+ if (mnl_interface->agps_settings_sync) {
+ mnl_interface->agps_settings_sync(&agps_settings);
+ } else {
+ LOGE("agps_settings_sync is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_VZW_DEBUG_SCREEN_OUTPUT: {
+ const char* str = get_string(buff, &offset, sizeof(buff));
+ if (mnl_interface->vzw_debug_screen_output) {
+ mnl_interface->vzw_debug_screen_output(str);
+ } else {
+ LOGE("vzw_debug_screen_output is NULL\n");
+ }
+ break;
+ }
+
+ case MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_IONO: {
+ if(mnl_interface->lppe_assist_common_iono) {
+ int lppe_len=get_int(buff, &offset, sizeof(buff));
+ LOGE("mnld rec lppe data ,len=%d,offset=%d\n",lppe_len,offset);
+ mnl_interface->lppe_assist_common_iono(buff+offset, lppe_len);
+ } else {
+ LOGE("lppe_assist_data_provide_common_iono is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_TROP: {
+ if(mnl_interface->lppe_assist_common_trop) {
+ int lppe_len=get_int(buff, &offset, sizeof(buff));
+ mnl_interface->lppe_assist_common_trop(buff+offset, lppe_len);
+ } else {
+ LOGE("lppe_assist_data_provide_common_trop is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_ALT: {
+ if(mnl_interface->lppe_assist_common_alt) {
+ int lppe_len=get_int(buff, &offset, sizeof(buff));
+ mnl_interface->lppe_assist_common_alt(buff+offset, lppe_len);
+ } else {
+ LOGE("lppe_assist_data_provide_common_alt is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_SOLAR: {
+ if(mnl_interface->lppe_assist_common_solar) {
+ int lppe_len=get_int(buff, &offset, sizeof(buff));
+ mnl_interface->lppe_assist_common_solar(buff+offset, lppe_len);
+ } else {
+ LOGE("lppe_assist_data_provide_common_solar is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_CCP: {
+ if(mnl_interface->lppe_assist_common_ccp) {
+ int lppe_len=get_int(buff, &offset, sizeof(buff));
+ mnl_interface->lppe_assist_common_ccp(buff+offset, lppe_len);
+ } else {
+ LOGE("lppe_assist_data_provide_common_ccp is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_LPPE_ASSIST_GENERIC_CCP: {
+ if(mnl_interface->lppe_assist_generic_ccp) {
+ int lppe_len=get_int(buff, &offset, sizeof(buff));
+ mnl_interface->lppe_assist_generic_ccp(buff+offset, lppe_len);
+ } else {
+ LOGE("lppe_assist_data_provide_generic_ccp is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_LPPE_ASSIST_GENERIC_DM: {
+ if(mnl_interface->lppe_assist_generic_dm) {
+ int lppe_len=get_int(buff, &offset, sizeof(buff));
+ mnl_interface->lppe_assist_generic_dm(buff+offset, lppe_len);
+ } else {
+ LOGE("lppe_assist_data_provide_generic_dm is NULL\n");
+ }
+ break;
+ }
+
+ case MNL_AGPS_TYPE_MD_TIME_SYNC_IND: {
+ if(mnl_interface->md_time_sync_ind) {
+ char data[MNL_AGPS_MAX_BUFF_SIZE/8] = {0};
+ int len = get_binary(buff, &offset, data, MNL_AGPS_MAX_BUFF_SIZE/8, sizeof(data));
+ mnl_interface->md_time_sync_ind(data, len);
+ } else {
+ LOGE("md_time_sync_ind is NULL\n");
+ }
+ break;
+ }
+ case MNL_AGPS_TYPE_MD_TIME_SYNC_CNF: {
+ if(mnl_interface->md_time_sync_cnf) {
+ char data[MNL_AGPS_MAX_BUFF_SIZE/8] = {0};
+ int len = get_binary(buff, &offset, data, MNL_AGPS_MAX_BUFF_SIZE/8, sizeof(data));
+ mnl_interface->md_time_sync_cnf(data, len);
+ } else {
+ LOGE("md_time_sync_cnf is NULL\n");
+ }
+ break;
+ }
+ default:
+ LOGE("agps2mnl unknown type=%d\n", type);
+ break;
+ }
+}
+
+int create_agps2mnl_fd() {
+ int fd = -1;
+ LOGD("bind mtk_agps2mnl");
+ fd = sock_udp_server_bind_local(true, "mtk_agps2mnl");
+ if(fd == -1) {
+ return -1;
+ }
+ set_socket_blocking(fd, 0);
+ return fd;
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/src/mnl_agps_interface.c b/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/src/mnl_agps_interface.c
new file mode 100644
index 0000000..977d379
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_agps_interface/src/mnl_agps_interface.c
@@ -0,0 +1,95 @@
+
+#include "mnl_agps_interface.h"
+
+const char* get_mnl_agps_type_str(mnl_agps_type input) {
+ switch (input) {
+ case MNL_AGPS_TYPE_MNL_REBOOT:
+ return "MNL_REBOOT";
+ case MNL_AGPS_TYPE_AGPS_OPEN_GPS_DONE:
+ return "AGPS_OPEN_GPS_DONE";
+ case MNL_AGPS_TYPE_AGPS_CLOSE_GPS_DONE:
+ return "AGPS_CLOSE_GPS_DONE";
+ case MNL_AGPS_TYPE_AGPS_RESET_GPS_DONE:
+ return "AGPS_RESET_GPS_DONE";
+ case MNL_AGPS_TYPE_GPS_INIT:
+ return "GPS_INIT";
+ case MNL_AGPS_TYPE_GPS_CLEANUP:
+ return "GPS_CLEANUP";
+ case MNL_AGPS_TYPE_SET_SERVER:
+ return "SET_SERVER";
+ case MNL_AGPS_TYPE_DELETE_AIDING_DATA:
+ return "DELETE_AIDING_DATA";
+ case MNL_AGPS_TYPE_GPS_OPEN:
+ return "GPS_OPEN";
+ case MNL_AGPS_TYPE_GPS_CLOSE:
+ return "GPS_CLOSE";
+ case MNL_AGPS_TYPE_DATA_CONN_OPEN:
+ return "DATA_CONN_OPEN";
+ case MNL_AGPS_TYPE_DATA_CONN_FAILED:
+ return "DATA_CONN_FAILED";
+ case MNL_AGPS_TYPE_DATA_CONN_CLOSED:
+ return "DATA_CONN_CLOSED";
+ case MNL_AGPS_TYPE_NI_MESSAGE:
+ return "NI_MESSAGE";
+ case MNL_AGPS_TYPE_NI_RESPOND:
+ return "NI_RESPOND";
+ case MNL_AGPS_TYPE_SET_REF_LOC:
+ return "SET_REF_LOC";
+ case MNL_AGPS_TYPE_SET_SET_ID:
+ return "SET_SET_ID";
+ case MNL_AGPS_TYPE_UPDATE_NETWORK_STATE:
+ return "UPDATE_NETWORK_STATE";
+ case MNL_AGPS_TYPE_UPDATE_NETWORK_AVAILABILITY:
+ return "UPDATE_NETWORK_AVAILABILITY";
+ case MNL_AGPS_TYPE_DATA_CONN_OPEN_IP_TYPE:
+ return "DATA_CONN_OPEN_IP_TYPE";
+ case MNL_AGPS_TYPE_INSTALL_CERTIFICATES:
+ return "INSTALL_CERTIFICATES";
+ case MNL_AGPS_TYPE_REVOKE_CERTIFICATES:
+ return "REVOKE_CERTIFICATES";
+ case MNL_AGPS_TYPE_UPDATE_GNSS_ACCESS_CONTROL:
+ return "UPDATE_GNSS_ACCESS_CONTROL";
+ case MNL_AGPS_TYPE_MNL2AGPS_PMTK:
+ return "MNL2AGPS_PMTK";
+ case MNL_AGPS_TYPE_RAW_DBG:
+ return "RAW_DBG";
+ case MNL_AGPS_TYPE_REAIDING:
+ return "REAIDING_REQ";
+ case MNL_AGPS_TYPE_AGPS_REBOOT:
+ return "AGPS_REBOOT";
+ case MNL_AGPS_TYPE_AGPS_OPEN_GPS_REQ:
+ return "AGPS_OPEN_GPS_REQ";
+ case MNL_AGPS_TYPE_AGPS_CLOSE_GPS_REQ:
+ return "AGPS_CLOSE_GPS_REQ";
+ case MNL_AGPS_TYPE_AGPS_RESET_GPS_REQ:
+ return "AGPS_RESET_GPS_REQ";
+ case MNL_AGPS_TYPE_AGPS_OPEN_GPS_REJECTED:
+ return "AGPS_OPEN_GPS_REJECTED";
+ case MNL_AGPS_TYPE_AGPS_SESSION_DONE:
+ return "AGPS_SESSION_DONE";
+ case MNL_AGPS_TYPE_NI_NOTIFY:
+ return "NI_NOTIFY";
+ case MNL_AGPS_TYPE_NI_NOTIFY_2:
+ return "NI_NOTIFY2";
+ case MNL_AGPS_TYPE_DATA_CONN_REQ:
+ return "DATA_CONN_REQ";
+ case MNL_AGPS_TYPE_DATA_CONN_REQ2:
+ return "DATA_CONN_REQ2";
+ case MNL_AGPS_TYPE_DATA_CONN_RELEASE:
+ return "DATA_CONN_RELEASE";
+ case MNL_AGPS_TYPE_SET_ID_REQ:
+ return "SET_ID_REQ";
+ case MNL_AGPS_TYPE_REF_LOC_REQ:
+ return "REF_LOC_REQ";
+ case MNL_AGPS_TYPE_AGPS2MNL_PMTK:
+ return "AGPS2MNL_PMTK";
+ case MNL_AGPS_TYPE_GPEVT:
+ return "GPEVT";
+ case MNL_AGPS_TYPE_AGPS_LOC:
+ return "AGPS_LOC";
+ default:
+ break;
+ }
+ return "UNKNOWN";
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_at_cmd_interface/inc/mnl_at_interface.h b/src/connectivity/gps/2.0/mtk_mnld/mnl_at_cmd_interface/inc/mnl_at_interface.h
new file mode 100644
index 0000000..48589dc
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_at_cmd_interface/inc/mnl_at_interface.h
@@ -0,0 +1,45 @@
+#ifndef __MNL_AT_INTERFACE_H__
+#define __MNL_AT_INTERFACE_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+
+#include "nmea_parser.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//======================================================
+// GPS AT -> MNLD
+//======================================================
+#define GPS_AT_COMMAND_SOCK "/data/server" // For receive AT command
+
+int mnl2at_send_data();
+
+int at_test2mnl_gps_start(void);
+int at_test2mnl_gps_stop(void);
+void at_command_send_cno(char* cmdline);
+int at_command_parse_test_num(char* cmdline);
+void at_command_send_ack(const char* ack, int len);
+void at_command_send_test_result();
+void at_cw_test_command_send_test_result();
+void at_cw_test_command_test_result(int snr, float clk_drift);
+void gps_at_command_test_proc(NmeaReader* const r);
+void nmea_parser_at_cmd_pre(void);
+
+void at_cmd2mnl_hdlr(int fd);
+
+// -1 means failure
+int create_at2mnl_fd();
+//======================================================
+// MNLD -> GPS AT CMD
+//======================================================
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_at_cmd_interface/src/mnl_at_interface.c b/src/connectivity/gps/2.0/mtk_mnld/mnl_at_cmd_interface/src/mnl_at_interface.c
new file mode 100644
index 0000000..b0a4d74
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_at_cmd_interface/src/mnl_at_interface.c
@@ -0,0 +1,1034 @@
+#include <time.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <math.h>
+#include <unistd.h> //for alarm function
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "mnl_at_interface.h"
+#include "nmea_parser.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_gps_type.h"
+#include "mtk_gps.h"
+
+#include "mtk_mnld_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "mnl2at"
+
+/*AT command test state*/
+#define GPS_TEST_PRN 1
+int MNL_AT_TEST_FLAG = 0;
+int MNL_AT_SIGNAL_MODE = 0;
+int MNL_AT_CW_MODE = 0;
+int MNL_AT_FM_MODE = 0;
+
+static int MNL_AT_SIGNAL_TEST_BEGIN = 0;
+
+int MNL_AT_SET_ALARM = 0;
+int MNL_AT_CANCEL_ALARM = 0;
+
+enum {
+ MNL_AT_TEST_UNKNOWN = -1,
+ MNL_AT_TEST_START = 0x00,
+ MNL_AT_TEST_STOP = 0x01,
+ MNL_AT_TEST_INPROGRESS = 0x02,
+ MNL_AT_TEST_DONE = 0x03,
+ MNL_AT_TEST_RESULT_DONE = 0x04,
+};
+int MNL_AT_TEST_STATE = MNL_AT_TEST_UNKNOWN;
+typedef struct {
+ int test_num;
+ int prn_num;
+ int time_delay;
+}HAL_AT_TEST_T;
+
+static HAL_AT_TEST_T hal_test_data = {
+ .test_num = 0,
+ .prn_num = 0,
+ .time_delay = 0,
+};
+
+#define MNL_AT_SV_STRING_LEN 128
+#define MNL_AT_REPORT_SV_NUM_EACH_SYS 3
+#define tolower(c) ((('A' <= (c)) && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
+typedef struct {
+ unsigned int searched;
+ char sys_str[MNL_AT_SV_STRING_LEN];
+ char svs_str[MNL_AT_SV_STRING_LEN];
+} svs;
+
+int* Dev_CNr = NULL;
+int prn[MTK_SV_NUMBER] = {0};
+int snr[MTK_SV_NUMBER] = {0};
+int cn = 0;
+/*
+* Test result array: error_code, theta(0), phi(0), Success_Num,
+* Complete_Num, Avg_CNo, Dev_CNo, Avg_Speed(0)
+*/
+static int result[8] = {1, 0, 0, 0, 0, 0, 0, 0};
+static int test_num = 0;
+static int CNo, DCNo;
+static int Avg_CNo = 0;
+static int Dev_CNo = 0;
+static int Completed_Num = 0;
+static int Success_Num = 0;
+static int Failure_Num = 0;
+static int Wait_Num = 0;
+static int sig_suc_num = 0;
+static int Err_Code = 1;
+#define MAX_VALID_STATUS_WAIT_COUNT 20 // 12
+int test_mode_flag = 1; // 0: USB mode, 1: SMS mode
+
+static int fd_at_test = 0;
+static struct sockaddr_un remote;
+static socklen_t remotelen;
+static time_t start_time;
+
+static int CNR = -1;
+static float ClkDrift = 0.0f;
+
+#define GPS_OP "AT%GPS"
+#define GNSS_OP "AT%GNSS"
+#define GPS_CW_TEST "AT%CWGPS"
+#define GPS_AT_ACK_SIZE 60
+
+
+/*for GPS AT command test*/
+int gpsinf_mtk_gps_test_stop() {
+ int err;
+ test_mode_flag = 1;
+
+ if ((err = at_test2mnl_gps_stop())) {
+ LOGE("at_test2mnl_gps_stop err = %d", err);
+ return -1;
+ }
+
+// gps_state_test_stop(s);
+
+ hal_test_data.test_num = 0;
+ hal_test_data.prn_num = 0;
+ hal_test_data.time_delay = 0;
+ MNL_AT_TEST_FLAG = 0;
+ MNL_AT_SIGNAL_MODE = 0;
+ MNL_AT_CW_MODE = 0;
+ MNL_AT_FM_MODE = 0;
+ MNL_AT_TEST_STATE = MNL_AT_TEST_UNKNOWN;
+
+ MNL_AT_SET_ALARM = 0;
+ MNL_AT_CANCEL_ALARM = 0;
+ MNL_AT_SIGNAL_TEST_BEGIN = 0;
+
+ // release the variable
+ Success_Num = 0;
+ Completed_Num = 0;
+ Wait_Num = 0;
+ CNo = 0;
+ DCNo = 0;
+ Dev_CNo = 0;
+ Err_Code = 1;
+ test_num = 0;
+
+ if (NULL != Dev_CNr) {
+ LOGD("Free Dev_CNr");
+ free(Dev_CNr);
+ Dev_CNr = NULL;
+ }
+ return 0;
+}
+
+int gpsinf_mtk_gps_test_start(int test_num, int prn_num, int time_delay, int test_mode) {
+ int err;
+
+ if ((MNL_AT_TEST_STATE != MNL_AT_TEST_UNKNOWN) && test_mode_flag) {
+ LOGD("[SMS test mode] Timeout, test_stop() before test_start()");
+ gpsinf_mtk_gps_test_stop();
+ }
+
+ hal_test_data.test_num = test_num;
+ hal_test_data.prn_num = prn_num;
+ hal_test_data.time_delay = time_delay;
+ time(&start_time);
+
+ // ithis code is moved from stop function to here to keep avg value for AT%GPS(GNSS) or AT%GPS=?(GNSS=?)
+ Avg_CNo = 0;
+
+ if ((0 == hal_test_data.test_num) && (0 == test_mode)) {
+ LOGE("%s: test number is 0!!", __FUNCTION__);
+ return -1;
+ }
+
+ if (hal_test_data.test_num > 0) { //Only malloc and memset Dev_CNr when test num > 0
+ Dev_CNr = (int*)malloc(sizeof(int)*hal_test_data.test_num);
+ if (Dev_CNr == NULL){
+ LOGE("gpsinf_mtk_gps_test_start malloc fail");
+ } else {
+ memset(Dev_CNr, 0, test_num*sizeof(int));
+ }
+ }
+
+ if (1 == test_mode) {
+ LOGD("Signal test mode");
+ MNL_AT_SIGNAL_MODE = 1;
+ } else if (2 == test_mode) {
+ LOGD("CW test mode");
+ MNL_AT_CW_MODE = 1;
+ } else if(3 == test_mode) {
+ MNL_AT_FM_MODE = 1;
+ } else {
+ LOGD("Normal test mode");
+ MNL_AT_TEST_FLAG = 1;
+ }
+
+ MNL_AT_TEST_STATE = MNL_AT_TEST_INPROGRESS;
+
+ if ((err = at_test2mnl_gps_start())) {
+ LOGE("at_test2mnl_gps_start err = %d", err);
+ MNL_AT_TEST_STATE = MNL_AT_TEST_UNKNOWN;
+ MNL_AT_TEST_FLAG = 0;
+ MNL_AT_SIGNAL_MODE = 0;
+ MNL_AT_CW_MODE = 0;
+ MNL_AT_FM_MODE = 0;
+ return -1;
+ }
+
+ // gps_state_test_start(s);
+ return 0;
+}
+
+int gpsinf_mtk_gps_test_inprogress() {
+ int ret = -1;
+
+ if ((MNL_AT_TEST_STATE == MNL_AT_TEST_DONE) || (MNL_AT_TEST_STATE == MNL_AT_TEST_RESULT_DONE)) {
+ LOGD("**AT Command test done!!");
+ ret = MNL_AT_TEST_DONE;
+ } else if (MNL_AT_TEST_STATE == MNL_AT_TEST_INPROGRESS) {
+ LOGD("**AT Command test is in progress!!");
+ ret = MNL_AT_TEST_INPROGRESS;
+ } else {
+ LOGD("**AT Command test status unknown!!");
+ ret = MNL_AT_TEST_UNKNOWN;
+ }
+ return ret;
+}
+
+void at_gps_command_parser(char* cmdline) {
+ char* command = cmdline;
+ test_mode_flag = 0;
+ Wait_Num = 0;
+
+ if (MNL_AT_CW_MODE == 1){
+ LOGD("** GPS CW test is ongoing! **");
+ char buff[] = "GPS CW test is ongoing, please wait";
+ at_command_send_ack(buff, sizeof(buff));
+ return;
+ }
+
+ if (!memcmp(command+6, "=", 1)) {
+ if ((!memcmp(command+7, "?", 1)) && (!memcmp(command+8, "\0", 1))) {
+ // AT%GPS=?
+ LOGD("** AT Command Parse: AT GPS=?**");
+ at_command_send_cno(command);
+ } else if (((!memcmp(command+7, "E", 1)) ||(!memcmp(command+7, "e", 1))) && (!memcmp(command+8, "\0", 1))) {
+ // AT%GPS=E
+ LOGD("Open AGPS raw data");
+ } else if (((!memcmp(command+7, "D", 1)) ||(!memcmp(command+7, "d", 1))) && (!memcmp(command+8, "\0", 1))) {
+ // AT%GNS=D
+ LOGD("Close AGPS raw data");
+ } else {
+ // AT%GPS=n
+ LOGD("** AT Command Parse: AT GPS=num**");
+ int test_num = at_command_parse_test_num(command);
+ if (test_num >= 0) {
+ int ret = gpsinf_mtk_gps_test_start(test_num, GPS_TEST_PRN, 2, 0);
+ if (0 == ret) {
+ LOGD("** AT Command gps test start success **");
+ char buff[] = "GPS TEST START OK";
+ at_command_send_ack(buff, sizeof(buff));
+ } else {
+ LOGD("** AT Command gps test start fail **");
+ char buff[] = "GPS ERROR";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+ } else {
+ char buff[] = "Invalid Test Num =0";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+ }
+ } else if (!memcmp(command+6, "?", 1) && (!memcmp(command+7, "\0", 1))) {
+ // AT%GPS?
+ LOGD("** AT Command Parse: AT GPS? **");
+ int ret = gpsinf_mtk_gps_test_inprogress();
+
+ if (MNL_AT_TEST_INPROGRESS == ret) {
+ LOGD("** AT Command test is inprogress **");
+ char buff[] = "GPS Test In Progress";
+ at_command_send_ack(buff, sizeof(buff));
+ } else if (MNL_AT_TEST_DONE == ret) {
+ LOGD("** AT Command test done");
+ char buff[GPS_AT_ACK_SIZE];
+ MNLD_SPRINTF(buff, "<%d, %d, %d, %d, %d, %d, %d, %d>",
+ result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7]);
+ at_command_send_ack(buff, sizeof(buff));
+ } else {
+ LOGD("** AT Command test status unknown");
+ char buff[] = "ERROR";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+ } else if (!memcmp(command+6, "\0", 1)) {
+ // AT%GPS
+ LOGD("** AT Command Parse: AT GPS **");
+ at_command_send_cno(command);
+ } else {
+ LOGD("** AT Command Parse: illegal command **");
+ char buff[] = "GPS ERROR";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+}
+
+void at_gnss_command_parser(char* cmdline) {
+ char* command = cmdline;
+ test_mode_flag = 0;
+ char cmd_fm[3] = "fm";
+
+ if (MNL_AT_CW_MODE == 1){
+ LOGD("** GPS CW test is ongoing! **");
+ char buff[] = "GPS CW test is ongoing, please wait";
+ at_command_send_ack(buff, sizeof(buff));
+ return;
+ }
+
+ if (!memcmp(command+7, "=", 1)) {
+ if ((!memcmp(command+8, "?", 1)) && (!memcmp(command+9, "\0", 1))) {
+ // AT%GNSS=?
+ LOGD("** AT Command Parse: AT GNSS=?**");
+ // at_command_send_cno(command);
+ at_command_send_test_result();
+ } else if (((!memcmp(command+8, "S", 1)) || (!memcmp(command+8, "s", 1))) && (!memcmp(command+9, "\0", 1))) {
+ LOGD("AT GNSS=S is set!!");
+ int ret = 0;
+ if (0 == MNL_AT_TEST_FLAG) {
+ LOGD("Open GPS and set signal test mode");
+ ret = gpsinf_mtk_gps_test_start(0, 1, 2, 1);
+ } else {
+ LOGD("GPS driver is opened, change mode");
+ MNL_AT_SIGNAL_MODE = 1;
+ MNL_AT_TEST_FLAG = 0;
+ // Cancel alarm if needed
+ if (0 == MNL_AT_CANCEL_ALARM) {
+ LOGD("Cancel alarm!!");
+ alarm(0);
+ MNL_AT_CANCEL_ALARM = 0;
+ MNL_AT_SET_ALARM = 0;
+ }
+ }
+
+ if (0 == ret) {
+ LOGD("** AT GNSS=S set success ! **");
+ char buff[] = "GNSS START START OK";
+ at_command_send_ack(buff, sizeof(buff));
+ } else {
+ LOGD("** AT GNSS=S set fail **");
+ char buff[] = "GNSS START START FAIL";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+ } else if (((!memcmp(command+8, "E", 1)) || (!memcmp(command+8, "e", 1))) && (!memcmp(command+9, "\0", 1))) {
+ LOGD("AT GNSS=E is set, stop test!!");
+ if (MNL_AT_TEST_STATE == MNL_AT_TEST_UNKNOWN) {
+ LOGD("** MNL_AT_TEST_UNKNOWN **");
+ char buff[] = "GNSS Test is Not In Progress";
+ at_command_send_ack(buff, sizeof(buff));
+ } else {
+ // if (MNL_AT_TEST_STATE != MNL_AT_TEST_UNKNOWN) { // To avoid close gps driver many times
+ int ret = gpsinf_mtk_gps_test_stop();
+ if (0 == ret) {
+ LOGD("** AT GNSS=E set success ! **");
+ char buff[] = "GNSS TEST END OK";
+ at_command_send_ack(buff, sizeof(buff));
+ } else {
+ LOGD("** AT GNSS=E set fail **");
+ char buff[] = "GNSS TEST END FAIL";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+ // }
+ }
+ } else if ((tolower(*(command+8)) == cmd_fm[0]) && (tolower(*(command+9)) == cmd_fm[1]) && (*(command+10) == cmd_fm[2])) { //factory mode
+ if(MNL_AT_TEST_STATE == MNL_AT_TEST_UNKNOWN || MNL_AT_TEST_STATE == MNL_AT_TEST_STOP)
+ {
+ int ret = gpsinf_mtk_gps_test_start(0, 0, 60, 3);
+ if (0 == ret) {
+ LOGD("** AT Command gps factory test start success **");
+ //char buff[] = "[GNSS Factory]:testing...";
+ //at_command_send_ack(buff, sizeof(buff));
+ } else {
+ LOGD("** AT Command gps factory test start fail **");
+ char buff[] = "[GNSS Factory]:Open fail\r\nERROR";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+ } else {
+ LOGD("** MNL_AT_TEST_STATE:%d **", MNL_AT_TEST_STATE);
+ char buff[] = "GNSS Test state incorrect...\r\nERROR";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+ } else {
+ // AT%GNSS = n
+ LOGD("** AT Command Parse: AT GNSS=n**");
+ int test_num = at_command_parse_test_num(command);
+ // initialzation of result whenever starting test again.
+ memset(result, 0, sizeof(int)*8);
+ result[0] = 1;
+ Avg_CNo = 0;
+ Success_Num = 0;
+ Completed_Num = 0;
+ CNo = 0;
+ DCNo = 0;
+ Dev_CNo = 0;
+ cn = 0;
+ // initialzation of result whenever starting test again.
+
+ if (MNL_AT_SIGNAL_MODE == 1) { // && (test_num != 0)) {
+ if (test_num <= 0) {
+ char buff[] = "Invalid Test Num = 0";
+ at_command_send_ack(buff, sizeof(buff));
+ if (MNL_AT_TEST_STATE != MNL_AT_TEST_UNKNOWN)
+ gpsinf_mtk_gps_test_stop();
+ } else {
+ LOGD("MNL_AT_SIGNAL_MODE_BEGIN");
+ MNL_AT_SIGNAL_TEST_BEGIN = 1;
+ MNL_AT_TEST_STATE = MNL_AT_TEST_INPROGRESS; // Brian test
+ char buff[] = "GNSS TEST START OK";
+ at_command_send_ack(buff, sizeof(buff));
+ time(&start_time);
+ }
+ } else {
+ if (test_num >= 0) {
+ int ret = gpsinf_mtk_gps_test_start(test_num, GPS_TEST_PRN, 2, 0);
+ if (0 == ret) {
+ LOGD("** AT Command gps test start success **");
+ char buff[] = "GNSS TEST START OK";
+ at_command_send_ack(buff, sizeof(buff));
+ } else {
+ LOGD("** AT Command gps test start fail **");
+ char buff[] = "GNSS ERROR";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+ } else {
+ char buff[] = "Invalid Test Num =0";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+ }
+ }
+ } else if (!memcmp(command+7, "?", 1) && (!memcmp(command+8, "\0", 1))) {
+ // AT%GNSS?
+ LOGD("** AT Command Parse: AT GNSS? **");
+ at_command_send_test_result();
+
+ } else if (!memcmp(command+7, "\0", 1)) {
+ // AT%GNSS
+ LOGD("** AT Command Parse: AT GNSS **");
+ at_command_send_cno(command);
+ } else {
+ LOGD("** AT Command Parse: illegal command **");
+ char buff[] = "GNSS ERROR";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+}
+
+void at_cw_test_command_parser(char* cmdline) {
+ int ret = 0;
+
+ LOGD("** AT Command: %s **\n", cmdline);
+ test_mode_flag = 0;
+
+ if (MNL_AT_TEST_FLAG == 1 || MNL_AT_SIGNAL_MODE == 1){
+ LOGD("** AT GPS or AT GNSS is ongoing! **");
+ char buff[] = "AT GPS or AT GNSS is ongoing, please wait";
+ at_command_send_ack(buff, sizeof(buff));
+ return;
+ }
+
+ if (!memcmp(cmdline + 8, "=", 1))
+ {
+ //AT%CWGPS=E, close GPS for error handle.
+ if (((!memcmp(cmdline + 9, "E", 1)) || (!memcmp(cmdline + 9, "e", 1))) && (!memcmp(cmdline + 10, "\0", 1)))
+ {
+ LOGD("AT CWGPS=E is set, stop test!!");
+ if (MNL_AT_TEST_STATE == MNL_AT_TEST_UNKNOWN)
+ {
+ LOGD("** MNL_AT_TEST_UNKNOWN **");
+ char buff[] = "CWGPS Test is not in progress";
+ at_command_send_ack(buff, sizeof(buff));
+ return;
+ }
+ else
+ {
+ int ret = gpsinf_mtk_gps_test_stop();
+ if (0 == ret) {
+ LOGD("** AT CWGPS=E set success ! **");
+ char buff[] = "CWGPS test end success";
+ at_command_send_ack(buff, sizeof(buff));
+ return;
+ } else {
+ LOGD("** AT CWGPS=E set fail **");
+ char buff[] = "CWGPS test end fail";
+ at_command_send_ack(buff, sizeof(buff));
+ return;
+ }
+ }
+ }
+ //AT%CWGPS=T, start GPS CW test.
+ else if ((!memcmp(cmdline + 9, "?", 1)) && (!memcmp(cmdline + 10, "\0", 1)))
+ {
+ //Avoid customer input more than one AT%CWGPS=T.
+ if (MNL_AT_CW_MODE == 1){
+ LOGD("** AT CWGPS is ongoing! **");
+ char buff[] = "AT CWGPS is ongoing, please wait";
+ at_command_send_ack(buff, sizeof(buff));
+ return;
+ }
+
+ ret = gpsinf_mtk_gps_test_start(0, GPS_TEST_PRN, 1, 2);
+ CNR = -1;
+ ClkDrift = 0.0f;
+
+ if (0 == ret) {
+ LOGD("** AT CWGPS set success ! **");
+ char buff[] = "GPS Open Success";
+ at_command_send_ack(buff, sizeof(buff));
+ return;
+ } else {
+ LOGD("** AT CWGPS set fail **");
+ char buff[] = "GPS Open fail";
+ at_command_send_ack(buff, sizeof(buff));
+ return;
+ }
+ }
+ else
+ {
+ LOGD("** AT Command Parse: illegal command **");
+ char buff[] = "Invalid CWGPS Command";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+ }
+ else if (!memcmp(cmdline + 8, "?", 1) && (!memcmp(cmdline + 9, "\0", 1)))
+ {
+ // AT%CWGPS?
+ LOGD("** AT Command Parse: AT CWGPS? **");
+ at_cw_test_command_send_test_result();
+ }
+ else
+ {
+ LOGD("** AT Command Parse: illegal command **");
+ char buff[] = "Invalid CWGPS Command";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+}
+
+void at_cw_test_command_test_result(int snr, float clk_drift) {
+ int ret;
+
+ ret = gpsinf_mtk_gps_test_inprogress();
+ if (MNL_AT_TEST_UNKNOWN == ret) {
+ LOGD("** AT Command test is not inprogress **");
+ return;
+ }
+
+ //sprintf(buff, "SNR: %d Clock drift: %.2f", snr, clk_drift);
+ //at_command_send_ack(buff, sizeof(buff));
+ LOGD("** AT cw test result = %d %.2f**", snr, clk_drift);
+ CNR = snr;
+ ClkDrift = clk_drift;
+
+ MNL_AT_TEST_STATE = MNL_AT_TEST_RESULT_DONE;
+
+ if ((MNL_AT_TEST_STATE == MNL_AT_TEST_RESULT_DONE) && (1 == MNL_AT_CW_MODE)) {
+ gpsinf_mtk_gps_test_stop();
+ }
+}
+
+void at_cw_test_command_send_test_result() {
+ char buff[64];
+
+ //AT test is inprogress
+ if (MNL_AT_TEST_INPROGRESS == MNL_AT_TEST_STATE || MNL_AT_TEST_DONE == MNL_AT_TEST_STATE) {
+ LOGD("** AT Command test is inprogress **");
+ char buff[] = "AT Command test In Progress";
+ at_command_send_ack(buff, sizeof(buff));
+ return;
+ }
+
+ //There is no valid CW test result.
+ if (CNR == -1){
+ LOGD("** There is no valid result **");
+ char buff[] = "CW Test no valid result";
+ at_command_send_ack(buff, sizeof(buff));
+ return;
+ }
+
+ MNLD_SPRINTF(buff, "SNR: %d Clock drift: %.2f", CNR, ClkDrift);
+ at_command_send_ack(buff, sizeof(buff));
+}
+
+bool gps_at_nmea_sv_searched(NmeaReader* const r) {
+ int index = 0;
+ bool searched_l1 = false;
+ bool searched_l5 = false;
+ gnss_sv *sv_list = r->sv_status.sv_list;
+ LOGD("gps_at_nmea_sv_searched:sv_count:%d", r->sv_count);
+ for(index = 0; index < r->sv_count; index++) {
+ LOGD("gps_at_nmea_sv_searched: sv:%d, system:%d, freq:%f", sv_list[index].svid, sv_list[index].constellation, sv_list[index].carrier_frequency);
+ if(nmea_freq_l1_signal(sv_list[index].carrier_frequency)) {
+ LOGD("searched_l1:%d, searched_l5:%d", searched_l1, searched_l5);
+ searched_l1 = true;
+ }
+ if(mtk_gps_support_l5_get()) { //Support L1+L5
+ if(nmea_freq_l5_signal(sv_list[index].carrier_frequency)) {
+ searched_l5 = true;
+ }
+ if(searched_l1 && searched_l5) { //Searched L1 & L5 SVs
+ LOGD("searched_l1:%d, searched_l5:%d", searched_l1, searched_l5);
+ return true;
+ }
+ } else { //L1 only
+ if(searched_l1) { //Searched L1 SVs
+ LOGD("searched_l1:%d, searched_l5:%d", searched_l1, searched_l5);
+ return true;
+ }
+ }
+ }
+ LOGD("searched_l1:%d, searched_l5:%d", searched_l1, searched_l5);
+ return false;
+}
+
+void gps_at_command_fm_pass_ack(NmeaReader* const r) {
+ int index = 0;
+ gnss_sv *sv_list = r->sv_status.sv_list;
+ svs sv_str_list[SV_SYSTEM_NUMBER];
+ SV_SYSTEM sv_system = SV_SYSTEM_UNKNOWN;
+ char ack_buff[MNL_AT_SV_STRING_LEN] = {0};
+
+ memset(sv_str_list, 0, sizeof(sv_str_list));
+ for(index = 0; index < SV_SYSTEM_NUMBER; index++ ) {
+ MNLD_STRNCPY(sv_str_list[index].sys_str, nmea_sv_system_to_string(index), MNL_AT_SV_STRING_LEN);
+ }
+ for(index = 0; index < r->sv_count; index++) {
+ sv_system = nmea_constellation_to_system_index(sv_list[index].constellation, sv_list[index].carrier_frequency);
+ if(sv_system < SV_SYSTEM_NUMBER) {
+ sv_str_list[sv_system].searched += 1;
+ if(sv_str_list[sv_system].searched <= MNL_AT_REPORT_SV_NUM_EACH_SYS) {
+ char sv_str[MNL_AT_SV_STRING_LEN] = {0};
+ MNLD_SNPRINTF(sv_str, MNL_AT_SV_STRING_LEN, " %d", sv_list[index].svid);
+ strncat(sv_str_list[sv_system].svs_str, sv_str, MNL_AT_SV_STRING_LEN - strlen(sv_str_list[sv_system].svs_str) - 1);
+ }
+ }
+ }
+
+ MNLD_SNPRINTF(ack_buff, MNL_AT_SV_STRING_LEN, "[GNSS Factory]:");
+ for(index = 0; index < SV_SYSTEM_NUMBER; index++) {
+ if(sv_str_list[index].searched > 0) {
+ char buff[MNL_AT_SV_STRING_LEN] = {0};
+ MNLD_SNPRINTF(buff, MNL_AT_SV_STRING_LEN, "[%s][%d][%s%s];",
+ sv_str_list[index].sys_str, sv_str_list[index].searched, sv_str_list[index].svs_str, (sv_str_list[index].searched > 3)?"...":"");
+ strncat(ack_buff, buff, MNL_AT_SV_STRING_LEN - strlen(ack_buff) - 1);
+ }
+ }
+ strncat(ack_buff, "\r\nOK", MNL_AT_SV_STRING_LEN - strlen(ack_buff) - 1);
+ at_command_send_ack(ack_buff, sizeof(ack_buff));
+}
+
+void gps_at_command_fm_fail_ack(void) {
+ char ack_buff[MNL_AT_SV_STRING_LEN] = {0};
+
+ MNLD_SNPRINTF(ack_buff, MNL_AT_SV_STRING_LEN, "[GNSS Factory]:%ds timeout\r\nERROR", hal_test_data.time_delay);
+ at_command_send_ack(ack_buff, sizeof(ack_buff));
+}
+
+void gps_at_command_fm_test_proc(NmeaReader* const r) {
+ if(gps_at_nmea_sv_searched(r)) {
+ gps_at_command_fm_pass_ack(r);
+ gpsinf_mtk_gps_test_stop();
+ }
+}
+
+static void at_command_parser(char* cmdline) {
+ char* command = cmdline;
+ LOGD("** AT Command, receive command %s**", command);
+ /* begin to parse the command */
+ if (!memcmp(command, GPS_OP, 6)) {
+ at_gps_command_parser(command);
+ } else if (!memcmp(command, GNSS_OP, 7)) {
+ at_gnss_command_parser(command);
+ } else if (!memcmp(command, GPS_CW_TEST, 8)) {
+ at_cw_test_command_parser(command);
+ }else {
+ LOGD("** AT Command Parse: Not GPS/GNSS AT Command **");
+ char buff[] = "GPS ERROR";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+}
+
+void at_command_send_ack(const char* ack, int len) {
+ remotelen = sizeof(remote);
+ LOGD("fd:%d, ack:%s, len:%d", fd_at_test, ack, len);
+ if (fd_at_test != 0) {
+ if (sendto(fd_at_test, ack, len, 0, (struct sockaddr*)&remote, remotelen) < 0) {
+ LOGD("** AT Command send ack to USB failed: %s**", strerror(errno));
+ } else {
+ LOGD("** AT Command send ack to USB sucess **");
+ }
+ }
+}
+
+void at_command_send_cno(char* cmdline) {
+ char* command = cmdline;
+
+ int ret = gpsinf_mtk_gps_test_inprogress();
+ if (MNL_AT_TEST_INPROGRESS == ret) {
+ LOGD("** AT Command test is inprogress **");
+ char buff[] = "GNSS Test In Progress";
+ at_command_send_ack(buff, sizeof(buff));
+ return;
+ }
+
+
+ if (MNL_AT_SIGNAL_MODE == 1) {
+ if (0 == cn) {
+ LOGD("** AT Command, cn is invalid **");
+ char buff[] = "0, NA";
+ at_command_send_ack(buff, sizeof(buff));
+ } else {
+ LOGD("** AT Command, CN is valid **");
+ char buff[32];
+ // sprintf(buff, "%d", Avg_CNo/10); // unit of AT%GNSS, AT%GNSS=? is 1dB
+ MNLD_SPRINTF(buff, "%d", cn/10);
+ if (!memcmp(command, GNSS_OP, 7)) {
+ LOGD("** GNSS test, report CN and NA**");
+ int size = strlen(buff);
+ MNLD_STRNCPY(buff+size, ", NA",sizeof(buff)-size);
+ LOGD("** result = %s**", buff);
+ }
+ at_command_send_ack(buff, sizeof(buff));
+ }
+ } else {
+ if (0 == Avg_CNo) {
+ LOGD("** AT Command, cn is invalid **");
+ char buff[] = "0, NA";
+ at_command_send_ack(buff, sizeof(buff));
+ } else {
+ LOGD("** AT Command, CN is valid **");
+ char buff[32];
+ MNLD_SPRINTF(buff, "%d", Avg_CNo/10); // unit of AT%GNSS, AT%GNSS=? is 1dB
+ // sprintf(buff, "%d", cn/10);
+ if (!memcmp(command, GNSS_OP, 7)) {
+ LOGD("** GNSS test, report CN and NA**");
+ int size = strlen(buff);
+ MNLD_STRNCPY(buff+size, ", NA",sizeof(buff)-size);
+ LOGD("** result = %s**", buff);
+ }
+ at_command_send_ack(buff, sizeof(buff));
+ }
+ }
+}
+
+void at_command_send_test_result() {
+ int ret = gpsinf_mtk_gps_test_inprogress();
+ if (MNL_AT_TEST_INPROGRESS == ret) {
+ LOGD("** AT Command test is inprogress **");
+ char buff[] = "GNSS Test In Progress";
+ at_command_send_ack(buff, sizeof(buff));
+ } else if (MNL_AT_TEST_DONE == ret || MNL_AT_TEST_RESULT_DONE == ret) {
+ LOGD("** AT Command test done");
+ char buff[GPS_AT_ACK_SIZE];
+ MNLD_SPRINTF(buff, "[%d, %d, %d, %d, %d, %d, %d, %d][0, 0, 0, 0, 0, 0, 0, 0]",
+ result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7]);
+ at_command_send_ack(buff, sizeof(buff));
+ } else {
+ LOGD("** AT Command test status unknown");
+ if (result[0] !=0) { // Brian test
+ char buff[GPS_AT_ACK_SIZE]={0};
+ LOGD("Normal: Return the result");
+ MNLD_SPRINTF(buff, "[%d, %d, %d, %d, %d, %d, %d, %d][0, 0, 0, 0, 0, 0, 0, 0]",
+ result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7]);
+ LOGD("** result =[%s] **\n", buff);
+ at_command_send_ack(buff, sizeof(buff));
+ } else if ((result[5] != 0) && (!(MNL_AT_SIGNAL_MODE || MNL_AT_SIGNAL_TEST_BEGIN))) {
+ LOGD("Normal: Return the result");
+ char buff[GPS_AT_ACK_SIZE]={0};
+ MNLD_SPRINTF(buff, "[%d, %d, %d, %d, %d, %d, %d, %d][0, 0, 0, 0, 0, 0, 0, 0]",
+ result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7]);
+ LOGD("** result =[%s] **\n", buff);
+ at_command_send_ack(buff, sizeof(buff));
+ } else {
+ char buff[] = "[0, 0, 0, 0, 0, 0, 0, 0][0, 0, 0, 0, 0, 0, 0, 0]";
+ at_command_send_ack(buff, sizeof(buff));
+ }
+ }
+}
+
+int at_command_parse_test_num(char* cmdline) {
+ int res;
+ char* command = cmdline;
+ char* pos = NULL;
+
+ if (!memcmp(command, GNSS_OP, 7)) {
+ // AT%GNSS=n
+ res = (int)strtol(command+8, &pos, 10);
+ } else {
+ // AT%GPS=n
+ res = (int)strtol(command+7, &pos, 10);
+ }
+
+ if ((res != 0) && ((*pos) == '\0')) {
+ LOGD("** AT Command Parse: get test_num = %d success!**", res);
+ } else {
+ LOGD("** AT Command Parse: the test num may incorrect**");
+ res = -1;
+ }
+
+ return res;
+}
+
+void nmea_parser_at_cmd_pre(void) {
+ int time_diff;
+ time_t current_time;
+ static int prev_success_num = 0;
+
+ if ((1 == MNL_AT_TEST_FLAG) ||(1 == MNL_AT_SIGNAL_TEST_BEGIN)) {
+ // (1 == MNL_AT_SIGNAL_MODE)) {
+ LOGD("MNL_AT_TEST_FLAG = %d, MNL_AT_SIGNAL_TEST_BEGIN = %d", MNL_AT_TEST_FLAG, MNL_AT_SIGNAL_TEST_BEGIN);
+ time(¤t_time);
+ time_diff = current_time - start_time;
+ if (time_diff >= hal_test_data.time_delay) {
+ LOGD("MNL_AT_SET_ALARM == 1, gps_nmea_end_tag(%d)", get_gps_nmea_parser_end_status());
+ if (get_gps_nmea_parser_end_status()) {
+ int test_stopped = 0;
+ LOGD("Success_Num = %d, Prev_Success_Num = %d, Wait_Num = %d, \
+ Failure_Num = %d, Completed_Num = %d, Avg_CNo = %d, \
+ Dev_CNo = %d, Err_Code = %d, MNL_AT_TEST_STATE = %d",
+ Success_Num, prev_success_num, Wait_Num, Failure_Num, Completed_Num,
+ Avg_CNo, Dev_CNo, Err_Code, MNL_AT_TEST_STATE);
+ if (Success_Num > 0) {
+ if (prev_success_num == Success_Num) {
+ Failure_Num++;
+ }
+ Completed_Num = Success_Num + Failure_Num;
+ if (Completed_Num == hal_test_data.test_num) {
+ // 1. Call reportTestResult callback with detected SNR info
+ // sms_airtest_no_signal_report(Err_Code, Success_Num, Completed_Num, Avg_CNo, Dev_CNo);
+ // 2. Test Stop
+ test_stopped = 1;
+ }
+ }
+ else {
+ Wait_Num++;
+ if (Wait_Num == MAX_VALID_STATUS_WAIT_COUNT) {
+ // 1. Call reportTestResult callback with <32, 0, 0, 0, 0, 0>
+ LOGD("TimeOut!! Wait_Num = %d", Wait_Num);
+ Completed_Num = hal_test_data.test_num;
+ Err_Code = (1 << 5);
+ Completed_Num = 1;
+ // sms_airtest_no_signal_report(Err_Code, Success_Num, Completed_Num, 0, 0);
+ // 2. Test Stop
+ test_stopped = 1;
+ }
+ }
+ prev_success_num = Success_Num;
+
+ if (test_stopped == 1) {
+ result[0] = Err_Code;
+ result[3] = Success_Num;
+ result[4] = Completed_Num;
+ result[5] = Avg_CNo;
+ result[6] = Dev_CNo;
+ Wait_Num = 0;
+ MNL_AT_TEST_STATE = MNL_AT_TEST_DONE;
+
+ LOGD("**AT Command test_start done, Success_Num = %d, Completed_Num = %d, \
+ Avg_CNo = %d, Dev_CNo = %d, Err_Code = %d, test_num = %d, MNL_AT_TEST_STATE = %d",
+ Success_Num, Completed_Num, Avg_CNo, Dev_CNo, Err_Code, test_num, MNL_AT_TEST_STATE);
+ Err_Code = 1;
+ if ((MNL_AT_TEST_STATE == MNL_AT_TEST_DONE) && (1 == MNL_AT_TEST_FLAG)) {
+ LOGD("** AT Command test done, stop GPS driver **");
+ gpsinf_mtk_gps_test_stop();
+ Failure_Num = 0;
+ prev_success_num = 0;
+ }
+ }
+ }
+ } else { // 2sec waiting
+ LOGD("static time, return...");
+ return;
+ }
+ } else if (MNL_AT_CW_MODE == 1) {
+ if (MNL_AT_TEST_STATE != MNL_AT_TEST_INPROGRESS) {
+ return;
+ }
+
+ time(¤t_time);
+ time_diff = current_time - start_time;
+ if (time_diff >= hal_test_data.time_delay) {
+ int ret = 0;
+ MTK_GPS_PARAM_TESTMODE param_test_config;
+ memset(¶m_test_config, 0x00, sizeof(param_test_config));
+ param_test_config.svid = 1;
+ param_test_config.test_mode = MTK_TESTMODE_CW_MODE;
+ param_test_config.threshold = 0; // 0:GPS Band(1575.42MHz)
+
+ if ((ret = mtk_gps_set_param(MTK_PARAM_CMD_TESTMODE, ¶m_test_config))) {
+ LOGE("set MTK_PARAM_CMD_TESTMODE to mnl fail, %d", ret);
+ } else {
+ LOGD("set MTK_PARAM_CMD_TESTMODE to mnl success, %d", ret);
+ }
+ MNL_AT_TEST_STATE = MNL_AT_TEST_DONE;
+ } else {
+ LOGD("static time, return...");
+ }
+ } else if (MNL_AT_FM_MODE == 1) {
+ LOGD("MNL_AT_TEST_STATE:%d", MNL_AT_TEST_STATE);
+ if (MNL_AT_TEST_STATE != MNL_AT_TEST_INPROGRESS) {
+ return;
+ }
+
+ time(¤t_time);
+ time_diff = current_time - start_time;
+ LOGD("time_diff:%d", time_diff);
+ if (time_diff >= hal_test_data.time_delay) {
+ gps_at_command_fm_fail_ack();
+ gpsinf_mtk_gps_test_stop();
+ }
+ }
+}
+/*****************************************
+AT test -> MNL Testing
+*****************************************/
+// No use now
+static void
+gps_at_command_search_satellite(NmeaReader* r) {
+ int i = 0, j = 0;
+ for (i = 0; i < r->sv_count; i++) {
+ if (prn[i] == hal_test_data.prn_num) {
+ LOGD("**AT Command test SvID: %d", prn[i]);
+ if (snr[i] != 0) {
+ if (MNL_AT_SIGNAL_MODE && (!MNL_AT_SIGNAL_TEST_BEGIN)) {
+ LOGD("Set state to MNL_AT_TEST_INPROGRESS for read result");
+ MNL_AT_TEST_STATE = MNL_AT_TEST_INPROGRESS;
+ }
+
+ if (MNL_AT_SIGNAL_MODE && MNL_AT_SIGNAL_TEST_BEGIN) {
+ LOGD("Set state to MNL_AT_TEST_RESULT_DONE for read result");
+ MNL_AT_TEST_STATE = MNL_AT_TEST_RESULT_DONE;
+ sig_suc_num = 1;
+ // sig_com_num = 1;
+ }
+
+ if (MNL_AT_TEST_FLAG) {
+ Err_Code = 0;
+ LOGD("cn = %d", cn);
+ CNo += snr[i]*10;
+ Dev_CNr[Success_Num] = snr[i]*10;
+ Success_Num++;
+ Avg_CNo = CNo / Success_Num;
+ // test_num++;
+ LOGD("CNo = %d, Avg_CNo /= %d, Success_Num = %d", CNo, Avg_CNo, Success_Num);
+ }
+ cn = snr[i]*10;
+ LOGD("cn = %d", cn);
+ } else {
+ LOGD("**SNR is 0, ignore!!!");
+ if (MNL_AT_CANCEL_ALARM == 1) { // It's not timeout, just no signal after 12s
+ if (MNL_AT_TEST_FLAG == 1)
+ test_num++;
+ }
+ sig_suc_num = 0;
+ }
+
+ if (Success_Num != 0) {
+ for (j = 0; j < Success_Num; j++) {
+ DCNo += (Dev_CNr[j]-Avg_CNo) * (Dev_CNr[j]-Avg_CNo);
+ LOGD("Dev_CNr[%d] = %d, Dev_CNo2 += %d", j, Dev_CNr[j], DCNo);
+ }
+ Dev_CNo = DCNo / Success_Num;
+ DCNo = 0;
+ Dev_CNo = sqrt(Dev_CNo);
+ }
+ LOGD("**AT Command find SvID: %d, exit", prn[i]);
+ break;
+ } else {
+ LOGD("**AT Command ignore SvID: %d", prn[i]);
+ }
+ }
+}
+
+void
+gps_at_command_test_proc(NmeaReader* const r) {
+ // For AT command test
+
+ if (MNL_AT_TEST_STATE != MNL_AT_TEST_DONE) {
+ LOGD("**AT Command test mode!!");
+
+ if (MNL_AT_SIGNAL_MODE == 1) {
+ if (MNL_AT_SIGNAL_TEST_BEGIN) {
+ gps_at_command_search_satellite(r);
+ LOGD("Update test result per second");
+ result[0] = 0;
+ result[3] = sig_suc_num;
+ result[4] = 1;
+ result[5]= cn;
+ LOGD("result[5] = %d", result[5]);
+ result[6] = 0;
+ } else {
+ LOGD("Wait AT GNSS=1...");
+ return;
+ }
+ } else if(MNL_AT_FM_MODE == 1) {
+ LOGD("**AT Command factory test mode!!");
+ gps_at_command_fm_test_proc(r);
+ } else {
+ LOGD("Not in MNL_AT_SIGNAL_MODE");
+ LOGD("**AT Command Continue, search satellites...");
+ // Search satellites
+ gps_at_command_search_satellite(r);
+ }
+
+ } else {
+ LOGD("**AT Command test, test mode is MNL_AT_TEST_DONE");
+ }
+}
+
+void at_cmd2mnl_hdlr(int fd) {
+ char cmd[20];
+
+ fd_at_test = fd;
+ LOGD("** AT Command received **");
+ /* receive and parse ATCM here */
+ for (;;) {
+ int ret;
+
+ remotelen = sizeof(remote);
+ ret = recvfrom(fd, cmd, sizeof(cmd) - 1, 0, (struct sockaddr *)&remote, &remotelen);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ if (errno != EWOULDBLOCK)
+ LOGE("error while reading AT Command socket: %s", strerror(errno));
+ break;
+ }
+ cmd[ret] = 0x00;
+ LOGD("received %d bytes:%s", ret, cmd);
+ at_command_parser(cmd); // need redefine
+ }
+ LOGD("** AT Command event done **");
+}
+
+int create_at2mnl_fd() {
+ int fd = socket_bind_udp(GPS_AT_COMMAND_SOCK);
+ socket_set_blocking(fd, 0);
+ return fd;
+}
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_debug_interface/inc/Debug2MnldInterface.h b/src/connectivity/gps/2.0/mtk_mnld/mnl_debug_interface/inc/Debug2MnldInterface.h
new file mode 100644
index 0000000..91139e0
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_debug_interface/inc/Debug2MnldInterface.h
@@ -0,0 +1,68 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __Debug2MnldInterface_H__
+#define __Debug2MnldInterface_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DEBUG2MNLD_INTERFACE_PROTOCOL_TYPE 305
+#define DEBUG2MNLD_INTERFACE_BUFF_SIZE 23
+
+/**
+ * The interface from Debug to Mnld
+ */
+typedef enum {
+ DEBUG2MNLD_INTERFACE_DEBUG_REQ_MNLD_MSG = 0,
+ DEBUG2MNLD_INTERFACE_DEBUG_MNLD_NE_MSG = 1,
+ DEBUG2MNLD_INTERFACE_DEBUG_MNLD_RADIO_MSG = 2,
+} Debug2MnldInterface_message_id;
+
+
+typedef enum {
+ DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_STOP_DEBUG = 0,
+ DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_START_DEBUG = 1,
+ DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_END = 2147483647,
+} Debug2MnldInterface_DebugReqStatusCategory;
+
+
+// Debug2MnldInterface_DebugReqStatusCategory
+const char* Debug2MnldInterface_DebugReqStatusCategory_to_string(Debug2MnldInterface_DebugReqStatusCategory data);
+void Debug2MnldInterface_DebugReqStatusCategory_array_dump(Debug2MnldInterface_DebugReqStatusCategory data[], int size);
+
+void Debug2MnldInterface_DebugReqStatusCategory_array_init(Debug2MnldInterface_DebugReqStatusCategory output[], int max_size);
+
+bool Debug2MnldInterface_DebugReqStatusCategory_is_equal(Debug2MnldInterface_DebugReqStatusCategory data1, Debug2MnldInterface_DebugReqStatusCategory data2);
+bool Debug2MnldInterface_DebugReqStatusCategory_array_is_equal(Debug2MnldInterface_DebugReqStatusCategory data1[], int size1, Debug2MnldInterface_DebugReqStatusCategory data2[], int size2);
+
+bool Debug2MnldInterface_DebugReqStatusCategory_encode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory data);
+bool Debug2MnldInterface_DebugReqStatusCategory_array_encode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory data[], int size);
+
+void Debug2MnldInterface_DebugReqStatusCategory_decode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory* output);
+int Debug2MnldInterface_DebugReqStatusCategory_array_decode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory output[], int max_size);
+
+// Sender
+bool Debug2MnldInterface_debugReqMnldMsg(mtk_socket_fd* client_fd, Debug2MnldInterface_DebugReqStatusCategory status);
+
+bool Debug2MnldInterface_debugMnldNeMsg(mtk_socket_fd* client_fd, bool enabled);
+
+bool Debug2MnldInterface_debugMnldRadioMsg(mtk_socket_fd* client_fd, const char* value);
+
+// Receiver
+typedef struct {
+ void (*Debug2MnldInterface_debugReqMnldMsg_handler) (Debug2MnldInterface_DebugReqStatusCategory status);
+ void (*Debug2MnldInterface_debugMnldNeMsg_handler) (bool enabled);
+ void (*Debug2MnldInterface_debugMnldRadioMsg_handler) (char* value);
+} Debug2MnldInterface_callbacks;
+
+bool Debug2MnldInterface_receiver_decode(char* _buff, Debug2MnldInterface_callbacks* callbacks);
+bool Debug2MnldInterface_receiver_read_and_decode(int server_fd, Debug2MnldInterface_callbacks* callbacks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_debug_interface/inc/Mnld2DebugInterface.h b/src/connectivity/gps/2.0/mtk_mnld/mnl_debug_interface/inc/Mnld2DebugInterface.h
new file mode 100644
index 0000000..e96bb32
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_debug_interface/inc/Mnld2DebugInterface.h
@@ -0,0 +1,72 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __Mnld2DebugInterface_H__
+#define __Mnld2DebugInterface_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MNLD2DEBUG_INTERFACE_PROTOCOL_TYPE 304
+#define MNLD2DEBUG_INTERFACE_BUFF_SIZE 269
+
+/**
+ * The interface from Mnld to Debug
+ */
+typedef enum {
+ MNLD2DEBUG_INTERFACE_MNLD_ACK_DEBUG_REQ = 0,
+ MNLD2DEBUG_INTERFACE_MNLD_UPDATE_REBOOT = 1,
+ MNLD2DEBUG_INTERFACE_MNLD_UPDATE_GPS_STATUS = 2,
+ MNLD2DEBUG_INTERFACE_MNLD_UPDATE_MESSAGE_INFO = 3,
+} Mnld2DebugInterface_message_id;
+
+
+typedef enum {
+ MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STOPPED = 0,
+ MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STARTED = 1,
+ MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_END = 2147483647,
+} Mnld2DebugInterface_MnldGpsStatusCategory;
+
+
+// Mnld2DebugInterface_MnldGpsStatusCategory
+const char* Mnld2DebugInterface_MnldGpsStatusCategory_to_string(Mnld2DebugInterface_MnldGpsStatusCategory data);
+void Mnld2DebugInterface_MnldGpsStatusCategory_array_dump(Mnld2DebugInterface_MnldGpsStatusCategory data[], int size);
+
+void Mnld2DebugInterface_MnldGpsStatusCategory_array_init(Mnld2DebugInterface_MnldGpsStatusCategory output[], int max_size);
+
+bool Mnld2DebugInterface_MnldGpsStatusCategory_is_equal(Mnld2DebugInterface_MnldGpsStatusCategory data1, Mnld2DebugInterface_MnldGpsStatusCategory data2);
+bool Mnld2DebugInterface_MnldGpsStatusCategory_array_is_equal(Mnld2DebugInterface_MnldGpsStatusCategory data1[], int size1, Mnld2DebugInterface_MnldGpsStatusCategory data2[], int size2);
+
+bool Mnld2DebugInterface_MnldGpsStatusCategory_encode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory data);
+bool Mnld2DebugInterface_MnldGpsStatusCategory_array_encode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory data[], int size);
+
+void Mnld2DebugInterface_MnldGpsStatusCategory_decode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory* output);
+int Mnld2DebugInterface_MnldGpsStatusCategory_array_decode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory output[], int max_size);
+
+// Sender
+bool Mnld2DebugInterface_mnldAckDebugReq(mtk_socket_fd* client_fd);
+
+bool Mnld2DebugInterface_mnldUpdateReboot(mtk_socket_fd* client_fd);
+
+bool Mnld2DebugInterface_mnldUpdateGpsStatus(mtk_socket_fd* client_fd, Mnld2DebugInterface_MnldGpsStatusCategory status);
+
+bool Mnld2DebugInterface_mnldUpdateMessageInfo(mtk_socket_fd* client_fd, const char* msg);
+
+// Receiver
+typedef struct {
+ void (*Mnld2DebugInterface_mnldAckDebugReq_handler) ();
+ void (*Mnld2DebugInterface_mnldUpdateReboot_handler) ();
+ void (*Mnld2DebugInterface_mnldUpdateGpsStatus_handler) (Mnld2DebugInterface_MnldGpsStatusCategory status);
+ void (*Mnld2DebugInterface_mnldUpdateMessageInfo_handler) (char* msg);
+} Mnld2DebugInterface_callbacks;
+
+bool Mnld2DebugInterface_receiver_decode(char* _buff, Mnld2DebugInterface_callbacks* callbacks);
+bool Mnld2DebugInterface_receiver_read_and_decode(int server_fd, Mnld2DebugInterface_callbacks* callbacks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_debug_interface/src/Debug2MnldInterface.c b/src/connectivity/gps/2.0/mtk_mnld/mnl_debug_interface/src/Debug2MnldInterface.c
new file mode 100644
index 0000000..c90cd5e
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_debug_interface/src/Debug2MnldInterface.c
@@ -0,0 +1,245 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "Debug2MnldInterface.h"
+#include "mtk_socket_data_coder.h"
+
+// Debug2MnldInterface_DebugReqStatusCategory
+const char* Debug2MnldInterface_DebugReqStatusCategory_to_string(Debug2MnldInterface_DebugReqStatusCategory data) {
+ switch(data) {
+ case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_STOP_DEBUG:
+ return "stopDebug";
+ case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_START_DEBUG:
+ return "startDebug";
+ case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_END:
+ return "end";
+ default:
+ break;
+ }
+ return "UNKNOWN";
+}
+void Debug2MnldInterface_DebugReqStatusCategory_array_dump(Debug2MnldInterface_DebugReqStatusCategory data[], int size) {
+ int i = 0;
+ SOCK_LOGD("Debug2MnldInterface_DebugReqStatusCategory_array_dump() size=[%d]", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%s]", i, Debug2MnldInterface_DebugReqStatusCategory_to_string(data[i]));
+ }
+}
+
+void Debug2MnldInterface_DebugReqStatusCategory_array_init(Debug2MnldInterface_DebugReqStatusCategory output[], int max_size) {
+ int i = 0;
+ for(i = 0; i < max_size; i++) {
+ output[i] = DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_STOP_DEBUG;
+ }
+}
+
+bool Debug2MnldInterface_DebugReqStatusCategory_is_equal(Debug2MnldInterface_DebugReqStatusCategory data1, Debug2MnldInterface_DebugReqStatusCategory data2) {
+ return (data1 == data2)? true : false;
+}
+bool Debug2MnldInterface_DebugReqStatusCategory_array_is_equal(Debug2MnldInterface_DebugReqStatusCategory data1[], int size1, Debug2MnldInterface_DebugReqStatusCategory data2[], int size2) {
+ int i = 0;
+ if(size1 != size2) return false;
+ for(i = 0; i < size1; i++) {
+ if(data1[i] != data2[i]) return false;
+ }
+ return true;
+}
+
+bool Debug2MnldInterface_DebugReqStatusCategory_encode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory data) {
+ switch(data) {
+ case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_STOP_DEBUG:
+ case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_START_DEBUG:
+ case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_END:
+ break;
+ default:
+ SOCK_LOGE("Debug2MnldInterface_DebugReqStatusCategory_encode() unknown data=%d", data);
+ return false;
+ }
+ mtk_socket_put_int(buff, offset, data);
+ return true;
+}
+bool Debug2MnldInterface_DebugReqStatusCategory_array_encode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory data[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ if(!Debug2MnldInterface_DebugReqStatusCategory_encode(buff, offset, data[i])) {
+ SOCK_LOGE("Debug2MnldInterface_DebugReqStatusCategory_array_encode() Debug2MnldInterface_DebugReqStatusCategory_encode() failed at i=%d", i);
+ return false;
+ }
+ }
+ return true;
+}
+
+void Debug2MnldInterface_DebugReqStatusCategory_decode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory* output) {
+ *output = mtk_socket_get_int(buff, offset);
+}
+int Debug2MnldInterface_DebugReqStatusCategory_array_decode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ if(i < max_size) {
+ Debug2MnldInterface_DebugReqStatusCategory_decode(buff, offset, &output[i]);
+ } else {
+ Debug2MnldInterface_DebugReqStatusCategory data;
+ Debug2MnldInterface_DebugReqStatusCategory_decode(buff, offset, &data);
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+
+// Sender
+bool Debug2MnldInterface_debugReqMnldMsg(mtk_socket_fd* client_fd, Debug2MnldInterface_DebugReqStatusCategory status) {
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("Debug2MnldInterface_debugReqMnldMsg() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ char _buff[DEBUG2MNLD_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, DEBUG2MNLD_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, DEBUG2MNLD_INTERFACE_DEBUG_REQ_MNLD_MSG);
+ if(!Debug2MnldInterface_DebugReqStatusCategory_encode(_buff, &_offset, status)) {
+ SOCK_LOGE("Debug2MnldInterface_debugReqMnldMsg() Debug2MnldInterface_DebugReqStatusCategory_encode() fail on status");
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("Debug2MnldInterface_debugReqMnldMsg() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+bool Debug2MnldInterface_debugMnldNeMsg(mtk_socket_fd* client_fd, bool enabled) {
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("Debug2MnldInterface_debugMnldNeMsg() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ char _buff[DEBUG2MNLD_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, DEBUG2MNLD_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, DEBUG2MNLD_INTERFACE_DEBUG_MNLD_NE_MSG);
+ mtk_socket_put_bool(_buff, &_offset, enabled);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("Debug2MnldInterface_debugMnldNeMsg() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+bool Debug2MnldInterface_debugMnldRadioMsg(mtk_socket_fd* client_fd, const char* value) {
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("Debug2MnldInterface_debugMnldRadioMsg() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ char _buff[DEBUG2MNLD_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, DEBUG2MNLD_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, DEBUG2MNLD_INTERFACE_DEBUG_MNLD_RADIO_MSG);
+ if(strlen(value) > 10) {
+ SOCK_LOGE("Debug2MnldInterface_debugMnldRadioMsg() strlen of value=[%zu] is over 10", strlen(value));
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_put_string(_buff, &_offset, value);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("Debug2MnldInterface_debugMnldRadioMsg() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+// Receiver
+bool Debug2MnldInterface_receiver_decode(char* _buff, Debug2MnldInterface_callbacks* callbacks) {
+ int _ret = 0;
+ int _offset = 0;
+ _ret = mtk_socket_get_int(_buff, &_offset);
+ if(_ret != DEBUG2MNLD_INTERFACE_PROTOCOL_TYPE) {
+ SOCK_LOGE("Debug2MnldInterface_receiver_decode() protocol_type=[%d] is not equals to [%d]",
+ _ret, DEBUG2MNLD_INTERFACE_PROTOCOL_TYPE);
+ return false;
+ }
+ _ret = mtk_socket_get_int(_buff, &_offset);
+ switch(_ret) {
+ case DEBUG2MNLD_INTERFACE_DEBUG_REQ_MNLD_MSG: {
+ if(callbacks->Debug2MnldInterface_debugReqMnldMsg_handler == NULL) {
+ SOCK_LOGE("Debug2MnldInterface_receiver_decode() Debug2MnldInterface_debugReqMnldMsg_handler() is NULL");
+ return false;
+ }
+ Debug2MnldInterface_DebugReqStatusCategory status;
+ Debug2MnldInterface_DebugReqStatusCategory_decode(_buff, &_offset, &status);
+ callbacks->Debug2MnldInterface_debugReqMnldMsg_handler(status);
+ break;
+ }
+ case DEBUG2MNLD_INTERFACE_DEBUG_MNLD_NE_MSG: {
+ if(callbacks->Debug2MnldInterface_debugMnldNeMsg_handler == NULL) {
+ SOCK_LOGE("Debug2MnldInterface_receiver_decode() Debug2MnldInterface_debugMnldNeMsg_handler() is NULL");
+ return false;
+ }
+ bool enabled = mtk_socket_get_bool(_buff, &_offset);
+ callbacks->Debug2MnldInterface_debugMnldNeMsg_handler(enabled);
+ break;
+ }
+ case DEBUG2MNLD_INTERFACE_DEBUG_MNLD_RADIO_MSG: {
+ if(callbacks->Debug2MnldInterface_debugMnldRadioMsg_handler == NULL) {
+ SOCK_LOGE("Debug2MnldInterface_receiver_decode() Debug2MnldInterface_debugMnldRadioMsg_handler() is NULL");
+ return false;
+ }
+ char value[10];
+ mtk_socket_get_string(_buff, &_offset, value, 10);
+ callbacks->Debug2MnldInterface_debugMnldRadioMsg_handler(value);
+ break;
+ }
+ default: {
+ SOCK_LOGE("Debug2MnldInterface_receiver_decode() unknown msgId=[%d]", _ret);
+ return false;
+ }
+ }
+ return true;
+}
+bool Debug2MnldInterface_receiver_read_and_decode(int server_fd, Debug2MnldInterface_callbacks* callbacks) {
+ int _ret;
+ char _buff[DEBUG2MNLD_INTERFACE_BUFF_SIZE] = {0};
+
+ _ret = mtk_socket_read(server_fd, _buff, sizeof(_buff) - 1);
+ if(_ret == -1) {
+ SOCK_LOGE("Debug2MnldInterface_receiver_read_and_decode() mtk_socket_read() failed, fd=%d err=[%s]%d",
+ server_fd, strerror(errno), errno);
+ return false;
+ }
+ _buff[_ret] = 0;
+ return Debug2MnldInterface_receiver_decode(_buff, callbacks);
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_debug_interface/src/Mnld2DebugInterface.c b/src/connectivity/gps/2.0/mtk_mnld/mnl_debug_interface/src/Mnld2DebugInterface.c
new file mode 100644
index 0000000..8c7a540
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_debug_interface/src/Mnld2DebugInterface.c
@@ -0,0 +1,277 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "Mnld2DebugInterface.h"
+#include "mtk_socket_data_coder.h"
+
+// Mnld2DebugInterface_MnldGpsStatusCategory
+const char* Mnld2DebugInterface_MnldGpsStatusCategory_to_string(Mnld2DebugInterface_MnldGpsStatusCategory data) {
+ switch(data) {
+ case MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STOPPED:
+ return "gpsStopped";
+ case MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STARTED:
+ return "gpsStarted";
+ case MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_END:
+ return "end";
+ default:
+ break;
+ }
+ return "UNKNOWN";
+}
+void Mnld2DebugInterface_MnldGpsStatusCategory_array_dump(Mnld2DebugInterface_MnldGpsStatusCategory data[], int size) {
+ int i = 0;
+ SOCK_LOGD("Mnld2DebugInterface_MnldGpsStatusCategory_array_dump() size=[%d]", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%s]", i, Mnld2DebugInterface_MnldGpsStatusCategory_to_string(data[i]));
+ }
+}
+
+void Mnld2DebugInterface_MnldGpsStatusCategory_array_init(Mnld2DebugInterface_MnldGpsStatusCategory output[], int max_size) {
+ int i = 0;
+ for(i = 0; i < max_size; i++) {
+ output[i] = MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STOPPED;
+ }
+}
+
+bool Mnld2DebugInterface_MnldGpsStatusCategory_is_equal(Mnld2DebugInterface_MnldGpsStatusCategory data1, Mnld2DebugInterface_MnldGpsStatusCategory data2) {
+ return (data1 == data2)? true : false;
+}
+bool Mnld2DebugInterface_MnldGpsStatusCategory_array_is_equal(Mnld2DebugInterface_MnldGpsStatusCategory data1[], int size1, Mnld2DebugInterface_MnldGpsStatusCategory data2[], int size2) {
+ int i = 0;
+ if(size1 != size2) return false;
+ for(i = 0; i < size1; i++) {
+ if(data1[i] != data2[i]) return false;
+ }
+ return true;
+}
+
+bool Mnld2DebugInterface_MnldGpsStatusCategory_encode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory data) {
+ switch(data) {
+ case MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STOPPED:
+ case MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STARTED:
+ case MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_END:
+ break;
+ default:
+ SOCK_LOGE("Mnld2DebugInterface_MnldGpsStatusCategory_encode() unknown data=%d", data);
+ return false;
+ }
+ mtk_socket_put_int(buff, offset, data);
+ return true;
+}
+bool Mnld2DebugInterface_MnldGpsStatusCategory_array_encode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory data[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ if(!Mnld2DebugInterface_MnldGpsStatusCategory_encode(buff, offset, data[i])) {
+ SOCK_LOGE("Mnld2DebugInterface_MnldGpsStatusCategory_array_encode() Mnld2DebugInterface_MnldGpsStatusCategory_encode() failed at i=%d", i);
+ return false;
+ }
+ }
+ return true;
+}
+
+void Mnld2DebugInterface_MnldGpsStatusCategory_decode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory* output) {
+ *output = mtk_socket_get_int(buff, offset);
+}
+int Mnld2DebugInterface_MnldGpsStatusCategory_array_decode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ if(i < max_size) {
+ Mnld2DebugInterface_MnldGpsStatusCategory_decode(buff, offset, &output[i]);
+ } else {
+ Mnld2DebugInterface_MnldGpsStatusCategory data;
+ Mnld2DebugInterface_MnldGpsStatusCategory_decode(buff, offset, &data);
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+
+// Sender
+bool Mnld2DebugInterface_mnldAckDebugReq(mtk_socket_fd* client_fd) {
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("Mnld2DebugInterface_mnldAckDebugReq() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ char _buff[MNLD2DEBUG_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_MNLD_ACK_DEBUG_REQ);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("Mnld2DebugInterface_mnldAckDebugReq() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+bool Mnld2DebugInterface_mnldUpdateReboot(mtk_socket_fd* client_fd) {
+ SOCK_LOGE("Mnld2DebugInterface_mnldUpdateReboot");
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("Mnld2DebugInterface_mnldUpdateReboot() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ char _buff[MNLD2DEBUG_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_MNLD_UPDATE_REBOOT);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("Mnld2DebugInterface_mnldUpdateReboot() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+bool Mnld2DebugInterface_mnldUpdateGpsStatus(mtk_socket_fd* client_fd, Mnld2DebugInterface_MnldGpsStatusCategory status) {
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("Mnld2DebugInterface_mnldUpdateGpsStatus() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ char _buff[MNLD2DEBUG_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_MNLD_UPDATE_GPS_STATUS);
+ if(!Mnld2DebugInterface_MnldGpsStatusCategory_encode(_buff, &_offset, status)) {
+ SOCK_LOGE("Mnld2DebugInterface_mnldUpdateGpsStatus() Mnld2DebugInterface_MnldGpsStatusCategory_encode() fail on status");
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("Mnld2DebugInterface_mnldUpdateGpsStatus() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+bool Mnld2DebugInterface_mnldUpdateMessageInfo(mtk_socket_fd* client_fd, const char* msg) {
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("Mnld2DebugInterface_mnldUpdateMessageInfo() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ char _buff[MNLD2DEBUG_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_MNLD_UPDATE_MESSAGE_INFO);
+ if(strlen(msg) > 256) {
+ SOCK_LOGE("Mnld2DebugInterface_mnldUpdateMessageInfo() strlen of msg=[%zu] is over 256", strlen(msg));
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_put_string(_buff, &_offset, msg);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("Mnld2DebugInterface_mnldUpdateMessageInfo() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+// Receiver
+bool Mnld2DebugInterface_receiver_decode(char* _buff, Mnld2DebugInterface_callbacks* callbacks) {
+ int _ret = 0;
+ int _offset = 0;
+ _ret = mtk_socket_get_int(_buff, &_offset);
+ if(_ret != MNLD2DEBUG_INTERFACE_PROTOCOL_TYPE) {
+ SOCK_LOGE("Mnld2DebugInterface_receiver_decode() protocol_type=[%d] is not equals to [%d]",
+ _ret, MNLD2DEBUG_INTERFACE_PROTOCOL_TYPE);
+ return false;
+ }
+ _ret = mtk_socket_get_int(_buff, &_offset);
+ switch(_ret) {
+ case MNLD2DEBUG_INTERFACE_MNLD_ACK_DEBUG_REQ: {
+ if(callbacks->Mnld2DebugInterface_mnldAckDebugReq_handler == NULL) {
+ SOCK_LOGE("Mnld2DebugInterface_receiver_decode() Mnld2DebugInterface_mnldAckDebugReq_handler() is NULL");
+ return false;
+ }
+ callbacks->Mnld2DebugInterface_mnldAckDebugReq_handler();
+ break;
+ }
+ case MNLD2DEBUG_INTERFACE_MNLD_UPDATE_REBOOT: {
+ if(callbacks->Mnld2DebugInterface_mnldUpdateReboot_handler == NULL) {
+ SOCK_LOGE("Mnld2DebugInterface_receiver_decode() Mnld2DebugInterface_mnldUpdateReboot_handler() is NULL");
+ return false;
+ }
+ callbacks->Mnld2DebugInterface_mnldUpdateReboot_handler();
+ break;
+ }
+ case MNLD2DEBUG_INTERFACE_MNLD_UPDATE_GPS_STATUS: {
+ if(callbacks->Mnld2DebugInterface_mnldUpdateGpsStatus_handler == NULL) {
+ SOCK_LOGE("Mnld2DebugInterface_receiver_decode() Mnld2DebugInterface_mnldUpdateGpsStatus_handler() is NULL");
+ return false;
+ }
+ Mnld2DebugInterface_MnldGpsStatusCategory status;
+ Mnld2DebugInterface_MnldGpsStatusCategory_decode(_buff, &_offset, &status);
+ callbacks->Mnld2DebugInterface_mnldUpdateGpsStatus_handler(status);
+ break;
+ }
+ case MNLD2DEBUG_INTERFACE_MNLD_UPDATE_MESSAGE_INFO: {
+ if(callbacks->Mnld2DebugInterface_mnldUpdateMessageInfo_handler == NULL) {
+ SOCK_LOGE("Mnld2DebugInterface_receiver_decode() Mnld2DebugInterface_mnldUpdateMessageInfo_handler() is NULL");
+ return false;
+ }
+ char msg[256];
+ mtk_socket_get_string(_buff, &_offset, msg, 256);
+ callbacks->Mnld2DebugInterface_mnldUpdateMessageInfo_handler(msg);
+ break;
+ }
+ default: {
+ SOCK_LOGE("Mnld2DebugInterface_receiver_decode() unknown msgId=[%d]", _ret);
+ return false;
+ }
+ }
+ return true;
+}
+bool Mnld2DebugInterface_receiver_read_and_decode(int server_fd, Mnld2DebugInterface_callbacks* callbacks) {
+ int _ret;
+ char _buff[MNLD2DEBUG_INTERFACE_BUFF_SIZE] = {0};
+
+ _ret = mtk_socket_read(server_fd, _buff, sizeof(_buff) - 1);
+ if(_ret == -1) {
+ SOCK_LOGE("Mnld2DebugInterface_receiver_read_and_decode() mtk_socket_read() failed, fd=%d err=[%s]%d",
+ server_fd, strerror(errno), errno);
+ return false;
+ }
+ _buff[_ret] = 0;
+ return Mnld2DebugInterface_receiver_decode(_buff, callbacks);
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/inc/geofence.h b/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/inc/geofence.h
new file mode 100755
index 0000000..31d98b2
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/inc/geofence.h
@@ -0,0 +1,118 @@
+#ifndef __GEOFENCE_H__
+#define __GEOFENCE_H__
+
+// Ex.GNSS Adaptor --> MNLD Message
+//-------------------------------------------------------
+//|Message Type(int) | Message Length(int) | Message Structure |
+//-------------------------------------------------------
+// Case 1 - Message Type: ADD_GEOFENCE_AREA Message Structure:mtk_geofence_property
+// [Return Msg Type]:GEOFENCE_RESPONSE_INFO
+// Corresponding ATCMD(IN):Ex,AT+EGEOADDCIRCLE=3,0,24.123456,121.012345,200.000000,10000\r\n
+
+// Case 2 - Message Type: REMOVE_GEOFENCE Message Structure:Id(int)
+// [Return Msg Type]:EXCUTE_RESULT
+// Corresponding ATCMD(IN):Ex,AT+EGEODEL,1\r\n
+
+// Case 3 - Message Type: CLEAR_GEOFENCE Message Structure:NONE
+// [Return Msg Type]:EXCUTE_RESULT
+// Corresponding ATCMD(IN):Ex,AT+EGEODELALL=\r\n
+
+// Case 4 - Message Type: QUERY_GEOFENCE_NUM Message Structure:NONE
+// [Return Msg Type]:GEOFENCE_NUM
+// Corresponding ATCMD(IN):Ex,AT+EGEOMAX?\r\n
+
+// MNLD Message --> GNSS Adaptor
+//-------------------------------------------------------
+//|Message Type(int) | Message Length(int) | Message Structure |
+//-------------------------------------------------------
+// Message Type: EXCUTE_RESULT Message Structure:mtk_geofence_result
+// Corresponding ATCMD(OUT):Ex,OK\r\n or ERROR\r\n
+
+// Message Type: GEOFENCE_NUM Message Structure:Number(int)
+// Corresponding ATCMD(OUT):Ex,+EGEOMAX: 100\r\n
+
+// Message Type: GEOFENCE_RESPONSE_INFO Message Structure:mtk_geofence_create_status
+// Corresponding ATCMD(OUT):Ex,+EGEOADD: 0,1\r\n
+
+// Message Type: GEOFENCE_ALERT_INFO Message Structure:mtk_geofence_alert
+// Corresponding ATCMD(OUT):Ex,+EGEORESP: 1,1,24.125465,121.365496,100.23,1.23,3.54,3,6,2,6,3,2.52,1.32,2.12\r\n
+
+// Message Type: GNSS_TRACKING_STATUS Message Structure:mtk_gnss_tracking_status
+// Corresponding ATCMD(OUT):Ex,+EGEOTRACK: 0,"2019/12/1,21:06:23"\r\n
+
+#pragma pack(push)
+#pragma pack(4)
+
+typedef struct {
+ bool geofence_support;
+}mtk_geofence_client_capability;
+
+typedef struct {
+ bool geofence_support;
+}mtk_geofence_server_capability;
+
+typedef enum {
+ GEOFENCE_CLIENT_CAP,//geofence client capability
+ INIT_GEOFENCE,//Reserved
+ ADD_GEOFENCE_AREA,
+ PAUSE_GEOFENCE,//Reserved
+ RESUME_GEOFENCE,//Reserved
+ REMOVE_GEOFENCE,
+ RECOVER_GEOFENCE,//Reserved
+ CLEAR_GEOFENCE,
+ QUERY_GEOFENCE_NUM
+} mtk_geofence_command;
+
+typedef enum {
+ GEOFENCE_UNKNOWN = 0,
+ GEOFENCE_ENTERED = 1,
+ GEOFENCE_EXITED = 2,
+} mtk_geofence_status;
+
+typedef int mtk_monitor_transition;
+#define MTK_GEOFENCE_ENTER 0x01
+#define MTK_GEOFENCE_EXIT 0x02
+#define MTK_GEOFENCE_UNCERTAIN 0x04//Reserved
+
+typedef struct mtk_geofence_area {
+ double latitude;
+ double longitude;
+ double radius;
+ int latest_state; /*current state(mtk_geofence_status), most cases is GEOFENCE_UNKNOWN*/
+ mtk_monitor_transition monitor_transition; /*bitwise , MTK_GEOFENCE_EXIT/MTK_GEOFENCE_ENTER/MTK_GEOFENCE_UNCERTAIN*/
+ int unknown_timer;/*The time limit after which the UNCERTAIN transition should be triggered. This paramter is defined in milliseconds.*/
+} mtk_geofence_property;
+
+typedef struct mtk_geofence_alert {
+ int id;
+ int alert_state;//mtk_geofence_status
+ double latitude;
+ double longitude;
+ double altitude;
+ double speed;
+ double heading;
+ int h_acc;
+ int h_err_majoraxis;
+ int h_err_minoraxis;
+ int h_err_angle;
+ int hor_conf;
+ double pdop;
+ double hdop;
+ double vdop;
+}mtk_geofence_alert;
+
+typedef struct mtk_gnss_tracking_status {
+ int status; //GNSS service tracking OK = 0,GNSS service tracking failure = -1
+ int year;
+ int month;
+ int day;
+ int hour;
+ int minute;
+ int second;
+}mtk_gnss_tracking_status;
+
+#define MTK_GFC_SUCCESS (0)
+#define MTK_GFC_ERROR (-1)
+#pragma pack(pop)
+
+#endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/inc/mtk_geofence_controller.h b/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/inc/mtk_geofence_controller.h
new file mode 100755
index 0000000..5d280cc
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/inc/mtk_geofence_controller.h
@@ -0,0 +1,36 @@
+#ifndef __MTK_GEOFENCE_CONTROLLER_H__
+#define __MTK_GEOFENCE_CONTROLLER_H__
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+#include "mtk_gps_type.h"
+#include "geofence.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ void (*mnld_gfc_hbd_gps_open)();
+ void (*mnld_gfc_hbd_gps_close)();
+} gfc2mnl_interface;
+
+#define MAX_CLIENT_NUM 10
+
+void mtk_geofence_epoll_server_hdlr(int fd, int epfd);
+void mtk_geofence_epoll_control_server_hdlr(int fd, int epfd);
+void mtk_geofence_epoll_client_hdlr(int fd, gfc2mnl_interface* hdlr);
+void mtk_geofence_epoll_client_control_hdlr(int fd, gfc2mnl_interface* hdlr) ;
+int mtk_geofence_controller_process(mtk_geofence_msg *prmsg) ;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/inc/mtk_geofence_main.h b/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/inc/mtk_geofence_main.h
new file mode 100755
index 0000000..2c789a2
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/inc/mtk_geofence_main.h
@@ -0,0 +1,121 @@
+#ifndef __MTK_GEOFENCE_MAIN_H__
+#define __MTK_GEOFENCE_MAIN_H__
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+#include "mtk_gps_type.h"
+#include "geofence.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GEOFENCE_VERSION_HEAD 'G','F','C','_','V','E','R','_'
+#define GEOFENCE_MAJOR_VERSION '1','7','0','6','1','9','0','1' // y,y,m,m,d,d,rev,rev
+#define GEOFENCE_BRANCH_INFO '_','0','.','5','8','_'
+#define GEOFENCE_MINER_VERSION 'N','1'
+#define GEOFENCE_VER_INFO GEOFENCE_VERSION_HEAD,GEOFENCE_MAJOR_VERSION,GEOFENCE_BRANCH_INFO,GEOFENCE_MINER_VERSION
+
+#define GEOFENCEADP_MNL_TCP_DATA "mtk_geofenceadp_mnl_data"
+#define GEOFENCEADP_MNL_TCP_CONTROL "mtk_geofenceadp_mnl_control"
+
+//======================================================
+// GEOFENCE -> GPS/GEOFENCE HAL
+//======================================================
+#define MAX_GOEFENCE 100
+#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 MTK_GEOFENCE_TRANSITION_ENTERED 0x01
+#define MTK_GEOFENCE_TRANSITION_EXITED 0x02
+#define MTK_GEOFENCE_TRANSITION_UNCERTAIN 0x04
+#define MTK_GEOFENCE_TRANSITION_NO_CHANGE 0xff
+
+#define GEOFENCE_BUFF_SIZE (1 * 1024)
+#define GEOFENCE_DATAPATH_SIZE (10*1024)
+
+#define WGS84_MAJA (6378137.00) // Semi-Major Axis [m]
+#define PI (3.1415926535898)
+
+#define TRACKING_STATUS_CHANGE_THREASHOLD 3
+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 client 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; // success : 0,error : -1
+} mtk_geofence_result;
+
+typedef struct {
+ double latitude;
+ double longitude;
+ double radius;
+ int latest_state; /*current state(mtk_geofence_status), most cases is GPS_GEOFENCE_UNCERTAIN*/
+ int monitor_transition; /*bitwise or of enter/exit*/
+ int unknown_timer;/*continue positioning time limitied while positioning*/
+ int last_transition;
+} mtk_geofence_property_db;
+
+typedef struct {
+ mtk_geofence_property_db geofence_prop;
+ bool is_used;
+ int fd;
+}mtk_geofence_db;
+
+typedef struct
+{
+ UINT32 unknown_init_ttick; //record the ttick of fence starting time
+ int64_t unknown_elapsed_ttick; //update the ttick elapsed time since the starting time
+ int geofence_operating_mode; //[start, stop/ pause] = [0,1]
+}geofence_new_alarm;
+
+typedef struct {
+ mtk_geofence_db geofence_property[MAX_GOEFENCE];
+ geofence_new_alarm geofence_new_timer[MAX_GOEFENCE];
+ int fence_number;
+}mtk_geofence_ctx;
+
+void mtk_geofence_init(void);
+int mtk_geofence2mnl_hdlr (int fd, char *buff, int length);
+int create_geofence2mnl_data_fd();
+int create_geofence2mnl_control_fd();
+int mtk_geofence2mnl_get_valid_fence_num();
+void mtk_geofence_clear_fence(int fd) ;
+int mtk_geofence_clear_geofences_by_msg(int fd);
+int mtk_geofence_server_capability_send(int fd) ;
+int mtk_geofence2mnl_geofence_tracking_status(int fd, int tracking_stat, mtk_geofence_position_info *pos);
+void mtk_geofence_location_expire(mtk_geofence_position_info coordinate_loc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_controller.c b/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_controller.c
new file mode 100755
index 0000000..e5af431
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_controller.c
@@ -0,0 +1,197 @@
+#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"
+#include "mtk_geofence_main.h"
+#include "mtk_geofence_controller.h"
+#include "mtk_mnld_log.h"
+#include "mtk_lbs_utility.h"
+
+#define GEOFENCEADP_VERSION "2.02"
+
+//---------------------------------- channel -------------------------------------------
+client_list g_geofence_client_list;
+client_list g_geofence_client_control_list;
+
+gfc2mnl_interface* gfc2mnl_hdlr_cb;
+
+static int mtk_geofence_hbd_open_gps()
+{
+ int ret;
+
+ if (gfc2mnl_hdlr_cb != NULL && gfc2mnl_hdlr_cb->mnld_gfc_hbd_gps_open) {
+ mtk_geofence_init();
+ gfc2mnl_hdlr_cb->mnld_gfc_hbd_gps_open();
+ ret = MTK_GFC_SUCCESS;
+ } else {
+ LOGE("gfc2mnl_hdlr() mnld_gfc_hbd_gps_open is NULL");
+ ret = MTK_GFC_ERROR;
+ }
+
+ return ret;
+}
+
+static int mtk_geofence_hbd_close_gps()
+{
+ int ret;
+
+ if (gfc2mnl_hdlr_cb != NULL && gfc2mnl_hdlr_cb->mnld_gfc_hbd_gps_close) {
+ gfc2mnl_hdlr_cb->mnld_gfc_hbd_gps_close();
+ ret = MTK_GFC_SUCCESS;
+ } else {
+ LOGE("gfc2mnl_hdlr() mnld_gfc_hbd_gps_open is NULL");
+ ret = MTK_GFC_ERROR;
+ }
+
+ return ret;
+}
+
+void mtk_geofence_epoll_server_hdlr(int fd, int epfd) {
+ int new_fd = socket_tcp_server_new_connect(fd);
+ if(new_fd == -1) {
+ LOGE("socket new client connection failure");
+ } else {
+ if(client_list_add(&g_geofence_client_list, new_fd)) {
+ epoll_add_fd(epfd, new_fd);
+ mtk_geofence_server_capability_send(new_fd);
+ LOGW("socket new client connected fd=[%d] list num=[%d]", new_fd, g_geofence_client_list.num);
+ } else {
+ LOGE("mtk_geofence_epoll_server_hdlr() client num is reached to max");
+ close(new_fd);
+ }
+ }
+}
+
+void mtk_geofence_epoll_control_server_hdlr(int fd, int epfd) {
+ int new_fd = socket_tcp_server_new_connect(fd);
+ if(new_fd == -1) {
+ LOGE("socket new client connection failure");
+ } else {
+ if(client_list_add(&g_geofence_client_control_list, new_fd)) {
+ epoll_add_fd(epfd, new_fd);
+ LOGW("socket new client connected fd=[%d] list num=[%d]", new_fd, g_geofence_client_control_list.num);
+ } else {
+ LOGE("mtk_geofence_epoll_server_hdlr() client num is reached to max");
+ close(new_fd);
+ }
+ }
+}
+
+void mtk_geofence_epoll_client_hdlr(int fd, gfc2mnl_interface* hdlr) {
+ char buff[8192] = {0};
+ int len = read(fd, buff, sizeof(buff));
+ if(len == -1) {
+ close(fd);
+ mtk_geofence_clear_geofences_by_msg(fd);
+ client_list_remove(&g_geofence_client_list, fd);
+ LOGW("mtk_geofence_epoll_client_hdlr() read() fd=[%d] failed, reason=[%s]%d, list num=[%d]", fd, strerror(errno), errno, g_geofence_client_list.num);
+ } else if(len == 0) {
+ close(fd);
+ mtk_geofence_clear_geofences_by_msg(fd);
+ client_list_remove(&g_geofence_client_list, fd);
+ LOGW("mtk_geofence_epoll_client_hdlr() read() fd=[%d] find the remote side has closed the session, list num=[%d]", fd, g_geofence_client_list.num);
+ } else {
+ //TCP packets are combined together, need to extract them
+ //LOGD("fd:%d pkt_len:%d\r\n", fd, len);
+ //if(hdlr != NULL) {
+ // gfc2mnl_hdlr_cb = hdlr;
+ //} else {
+ // LOGE("gfc2mnl_hdlr_cb = NULL");
+ // return;
+ //}
+ //mtk_geofence2mnl_hdlr(fd, buff, len);
+ }
+}
+
+void mtk_geofence_epoll_client_control_hdlr(int fd, gfc2mnl_interface* hdlr) {
+ char buff[8192] = {0};
+ int len = read(fd, buff, sizeof(buff));
+ if(len == -1) {
+ close(fd);
+ client_list_remove(&g_geofence_client_control_list, fd);
+ LOGW("mtk_geofence_epoll_client_control_hdlr() read() fd=[%d] failed, reason=[%s]%d, list num=[%d]", fd, strerror(errno), errno, g_geofence_client_list.num);
+ } else if(len == 0) {
+ close(fd);
+ client_list_remove(&g_geofence_client_control_list, fd);
+ LOGW("mtk_geofence_epoll_client_control_hdlr() read() fd=[%d] find the remote side has closed the session, list num=[%d]", fd, g_geofence_client_list.num);
+ } else {
+ if(hdlr != NULL) {
+ gfc2mnl_hdlr_cb = hdlr;
+ } else {
+ LOGE("gfc2mnl_hdlr_cb = NULL");
+ return;
+ }
+ mtk_geofence2mnl_hdlr(fd, buff, len);
+ }
+}
+
+int mtk_geofence_gnss_state_process(mtk_geofence_msg *prmsg)
+{
+ int ret = MTK_GFC_SUCCESS;
+
+ if(prmsg == NULL) {
+ LOGE("mtk_geofence_gnss_state_process, recv prmsg is null pointer\r\n");
+ return MTK_GFC_ERROR;
+ }
+
+ if (prmsg->type == ADD_GEOFENCE_AREA){
+ if (mtk_geofence2mnl_get_valid_fence_num() == 0){
+ ret = mtk_geofence_hbd_open_gps();
+ }
+ } else if (prmsg->type == REMOVE_GEOFENCE){
+ if (mtk_geofence2mnl_get_valid_fence_num() == 0){
+ ret = mtk_geofence_hbd_close_gps();
+ }
+ } else if (prmsg->type == CLEAR_GEOFENCE){
+ if (mtk_geofence2mnl_get_valid_fence_num() == 0){
+ ret = mtk_geofence_hbd_close_gps();
+ }
+ } else if (prmsg->type == QUERY_GEOFENCE_NUM){
+ //Do nothing
+ } else {
+ LOGE("mtk_geofence_gnss_state_process, unknown action:%d\r\n", prmsg->type);
+ ret = MTK_GFC_ERROR;
+ }
+
+ return ret;
+}
+
+int mtk_geofence_controller_process(mtk_geofence_msg *prmsg) {
+ int ret;
+ if(prmsg == NULL) {
+ LOGE("mtk_gfc_controller_process, recv prmsg is null pointer\r\n");
+ return MTK_GFC_ERROR;
+ }
+
+ ret = mtk_geofence_gnss_state_process(prmsg);
+ return ret;
+}
+
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_main.c b/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_main.c
new file mode 100755
index 0000000..c5b0b72
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_main.c
@@ -0,0 +1,1049 @@
+#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 <math.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"
+#include "mtk_mnld_log.h"
+#include "mtk_geofence_main.h"
+#include "mtk_geofence_controller.h"
+#include "mtk_lbs_utility.h"
+
+//----------------------------------------------------------------------------------
+static char geofence_raw_data[GEOFENCE_DATAPATH_SIZE] = {0};
+static cyclical_buffer_t g_cyclical_buffer; // cyclic buffer
+static mtk_geofence_ctx geofence_ctx; /*used to keep every geofence property*/
+static int tracking_stat;/*GNSS tracking status, 0:tracking OK, -1:tracking failure*/
+static int continue_trk_points;/*continue tracking points*/
+#ifdef MTK_GNSS_GEOFENCE_UT
+timer_t g_geofence_start_timer;
+#endif
+//static mtk_geofence_client_capability geofence_client_cap;
+static mtk_geofence_server_capability geofence_server_cap;
+
+extern client_list g_geofence_client_list;
+extern client_list g_geofence_client_control_list;
+
+static int state_lookup_table[3][3] =
+{
+ {MTK_GEOFENCE_TRANSITION_UNCERTAIN, MTK_GEOFENCE_TRANSITION_ENTERED, MTK_GEOFENCE_TRANSITION_EXITED},
+ {MTK_GEOFENCE_TRANSITION_UNCERTAIN, MTK_GEOFENCE_TRANSITION_NO_CHANGE, MTK_GEOFENCE_TRANSITION_EXITED},
+ {MTK_GEOFENCE_TRANSITION_UNCERTAIN, MTK_GEOFENCE_TRANSITION_ENTERED, MTK_GEOFENCE_TRANSITION_NO_CHANGE}
+};
+
+int mtk_geofence2mnl_geofence_alert(int fd, int fence_id, int alet_stat, mtk_geofence_position_info* pos_data);
+
+#ifdef MTK_GNSS_GEOFENCE_UT
+static void geofence_timer_fence_alert(int id)
+{
+ int i, j;
+ int fd;
+ int fd_pool[MAX_GOEFENCE] = {0};
+ LOGD("Timer timeout");
+ for (i = 0; i < MAX_GOEFENCE; i++)
+ {
+ if ((fd = geofence_ctx.geofence_property[i].fd) > 0){
+ mtk_geofence2mnl_geofence_alert(geofence_ctx.geofence_property[i].fd, (i+1), GEOFENCE_ENTERED, NULL);
+ for (j = 0; j < MAX_GOEFENCE; j++){
+ if (fd_pool[j] == fd){
+ break;
+ } else if (fd_pool[j] == 0){
+ fd_pool[j] = fd;
+ mtk_geofence2mnl_geofence_tracking_status(fd, 0, NULL);
+ break;
+ }
+ }
+ }
+ }
+ start_timer(g_geofence_start_timer, 10000);
+}
+#endif
+static void 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;
+}
+
+//*****************************************************************************
+//
+// Horiz_Diff_Sqd_ofl : Compute the Horizontal position Difference Squared [m^2]
+// between a pair of Latitude and Longitudes [rads].
+//
+// Ideally the cosine Latitude input should be for the mean Latitude of the
+// two input positions. However, in practice it will most likely be for
+// one of them (either the first computed or the best determined) as only
+// a crude estimate of "Horiz_Diff_Sqd" is required for gross error checks.
+//
+//*****************************************************************************
+static float Horiz_Diff_Sqd_ofl(
+ const double LLpos1[], // i - 1st position Latitude, Longitude [radians]
+ const double LLpos2[], // i - 2nd position Latitude, Longitude [radians]
+ const float cosLat ) // i - cosine of Latitude
+{
+ // Return argument definition.
+ float Horiz_Diff_Sqd; // Horizontal position Difference Squared [m^2]
+ // Local data definitions
+ float dN; // Delta Northing [m]
+ float dE; // Delta Easting [m]
+
+ // Compute the Northing difference from the Latitudes [m]
+ dN = (float)( LLpos1[0] - LLpos2[0] ) * (float)WGS84_MAJA;
+ // Compute the Easting difference from the Longitudes [m]
+ dE = (float)( LLpos1[1] - LLpos2[1] ) * (float)WGS84_MAJA * cosLat;
+ // Horizontal position Difference Squared [m^2]
+ Horiz_Diff_Sqd = dN*dN + dE*dE;
+ return( Horiz_Diff_Sqd );
+}
+
+static double calculate_two_circle_intersection_area(double distance,double radius1,double radius2)
+{
+ double r1 = radius1,r2 = radius2;
+
+ if(r1 > r2){
+ double temp = r1;
+
+ r1 = r2;
+ r2 = temp;
+ }
+
+ if(r1+r2 <= distance) {
+ return 0;
+ }
+ else if(r2-r1>=distance) {
+ return PI*r1*r1;
+ }
+ else {
+ double a1=acos((r1*r1+distance*distance-r2*r2)/(2.0*r1*distance));
+ double a2=acos((r2*r2+distance*distance-r1*r1)/(2.0*r2*distance));
+
+ return (a1*r1*r1+a2*r2*r2-r1*distance*sin(a1));
+ }
+}
+
+/* Not used
+static double get_fence_distance(const double latitude,const double longitude,
+ const gpslocation set_position){
+ float horiz_diff_sqd,cosLat;
+ double distance;
+ const double llpos1[2]={latitude*PI/180 ,longitude*PI/180};
+ const double llpos2[2]={set_position.latitude*PI/180,set_position.longitude*PI/180};
+
+ cosLat = cos(latitude*PI/180);
+ horiz_diff_sqd = Horiz_Diff_Sqd_ofl(llpos1,llpos2,cosLat);
+ distance = sqrt(horiz_diff_sqd);
+ return distance;
+}
+*/
+
+static mtk_geofence_status fence_state(const double latitude,const double longitude,
+ const double radius_meters, const mtk_geofence_position_info set_position) {
+ float horiz_diff_sqd,cosLat;
+ double distance,insec_area,circle_area;
+ const double llpos1[2]={latitude*PI/180 ,longitude*PI/180};
+ const double llpos2[2]={set_position.latitude*PI/180,set_position.longitude*PI/180};
+ double hacc_2sigma;
+
+ if(set_position.fix_type != MTK_GPS_FIX_TYPE_3D)// 3: means 3D fix. 2: means 2D fix. 1:means no fix
+ {
+ //LOGD("not 3D fix, it's uncertain\n");
+ return GEOFENCE_UNKNOWN;
+ }
+
+ hacc_2sigma = (1.7*set_position.h_acc);//convert accuracy from 67% to 95%
+ cosLat = cos(latitude*PI/180);
+ horiz_diff_sqd = Horiz_Diff_Sqd_ofl(llpos1,llpos2,cosLat);
+ distance = sqrt(horiz_diff_sqd);
+
+ //LOGD("fence ll: %lf, %lf, loc ll: %lf %lf",latitude,longitude,set_position.latitude,set_position.longitude);
+ //LOGD("distance =%lf, radius_meters=%lf,accuracy=%f\n",distance,radius_meters,set_position.h_acc);
+ insec_area = calculate_two_circle_intersection_area(distance,radius_meters,hacc_2sigma);
+
+ //restrict accuracy to make sure both low accuracy & no fix case can enter "uncertain" state
+ circle_area = PI * (hacc_2sigma) * (hacc_2sigma);
+ LOGD("insec_are:%lf, circle area: %lf",insec_area,circle_area);
+
+ if(insec_area > ( circle_area* 0.95)) //intersection area >95% of the fence area or intersection area >95% of the location accuracy area
+ {
+ if( circle_area >= (PI * radius_meters * radius_meters)) //location accuracy wrapped up the fence
+ {
+ //LOGD("big accuracy, it's uncertain\n");
+ return GEOFENCE_UNKNOWN;
+ }
+ else
+ {
+ //LOGD("circle_area <= insec_area, it's inside\n");
+ return GEOFENCE_ENTERED;
+ }
+ }
+ else if(insec_area < ( circle_area* 0.05))//intersection area <95% of the fence area
+ {
+ //LOGD("circle_area > insec_area, it's outside\n");
+ return GEOFENCE_EXITED;
+ }
+ else
+ {
+ return GEOFENCE_UNKNOWN;
+ }
+}
+
+static int mtk_geofence_get_avalibale_item(){
+ int i = 0;
+
+ while(i < MAX_GOEFENCE && geofence_ctx.geofence_property[i].is_used == true){
+ i++;
+ }
+
+ if(i == MAX_GOEFENCE){
+ return -1;
+ }
+
+ return i;
+}
+
+static bool mtk_geofence_check_avalibale_item(int fd, int item){
+ if (item >= MAX_GOEFENCE || item < 0){
+ return false;
+ }
+
+ if (geofence_ctx.geofence_property[item].is_used && (geofence_ctx.geofence_property[item].fd == fd)){
+ return true;
+ }
+
+ return false;
+}
+
+static int mtk_geofence_check_fence_vadility(mtk_geofence_property *fence){
+ return 0;
+}
+
+static bool mtk_geofence_check_data_fd_exist(int fd){
+ return client_list_contains(&g_geofence_client_list, fd);
+}
+
+static int mtk_geofence_set_one_geofence_unknown_alarm(int idx){
+ if(geofence_ctx.geofence_property[idx].is_used) {
+ geofence_ctx.geofence_new_timer[idx].unknown_init_ttick = 0;
+ geofence_ctx.geofence_new_timer[idx].unknown_elapsed_ttick = 0;
+ }
+ return 0;
+}
+
+static void mtk_geofence_tracking_status_changed_hdlr(int new_trk_stat, mtk_geofence_position_info *pos){
+ int i, j;
+ int fd_pool[MAX_GOEFENCE] = {0};
+ int fd;
+
+ for (i = 0; i < MAX_GOEFENCE; i++)
+ {
+ if ((fd = geofence_ctx.geofence_property[i].fd) > 0){
+ for (j = 0; j < MAX_GOEFENCE; j++){
+ if (fd_pool[j] == fd){
+ break;
+ } else if (fd_pool[j] == 0){
+ fd_pool[j] = fd;
+ mtk_geofence2mnl_geofence_tracking_status(fd, new_trk_stat, pos);
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void mtk_geofence_check_tracking_status(mtk_geofence_position_info *pos){
+ int new_trk_stat;
+
+ if (pos->fix_type == MTK_GPS_FIX_TYPE_3D){
+ new_trk_stat = 0;
+ } else {
+ new_trk_stat = -1;
+ }
+
+ if (new_trk_stat != tracking_stat){
+ continue_trk_points++;
+ if (continue_trk_points >= TRACKING_STATUS_CHANGE_THREASHOLD){
+ //Notify user tracking status changed
+ tracking_stat = new_trk_stat;
+ continue_trk_points = 0;
+ mtk_geofence_tracking_status_changed_hdlr(new_trk_stat, pos);
+ }
+ } else {
+ continue_trk_points = 0;
+ }
+}
+
+static int mtk_geofence_add_new_fence(int fd, mtk_geofence_property * fence){
+ int item;
+ int fence_id;
+ mtk_geofence_property_db fence_data;
+
+ item = mtk_geofence_get_avalibale_item();
+
+ if(item < 0)
+ {
+ return -1;
+ }
+
+ fence_data.latitude = fence->latitude;
+ fence_data.longitude = fence->longitude;
+ fence_data.radius = fence->radius;
+ fence_data.latest_state = fence->latest_state;
+ fence_data.monitor_transition = fence->monitor_transition;
+ fence_data.unknown_timer = fence->unknown_timer;
+ if (fence->latest_state == GEOFENCE_UNKNOWN){
+ fence_data.last_transition = MTK_GEOFENCE_TRANSITION_UNCERTAIN;
+ } else if (fence->latest_state == GEOFENCE_ENTERED) {
+ fence_data.last_transition = MTK_GEOFENCE_TRANSITION_ENTERED;
+ } else if (fence->latest_state == GEOFENCE_EXITED) {
+ fence_data.last_transition = MTK_GEOFENCE_TRANSITION_EXITED;
+ } else {
+ fence_data.last_transition = MTK_GEOFENCE_TRANSITION_UNCERTAIN;
+ }
+
+ memcpy(&geofence_ctx.geofence_property[item].geofence_prop, &fence_data, sizeof(mtk_geofence_property_db));
+ geofence_ctx.geofence_property[item].is_used = true;
+ geofence_ctx.geofence_property[item].fd = fd;
+ geofence_ctx.fence_number++;
+ //set unknown timer
+ mtk_geofence_set_one_geofence_unknown_alarm(item);
+
+ fence_id = item + 1;
+ return fence_id;
+}
+
+static int mtk_geofence_remove_fence(int fd, int fence_id) {
+ int item;
+
+ item = fence_id - 1;
+ if (!mtk_geofence_check_avalibale_item(fd, item)){
+ return -1;
+ }
+
+ memset(&geofence_ctx.geofence_property[item].geofence_prop, 0, sizeof(mtk_geofence_property_db));
+ geofence_ctx.geofence_property[item].is_used = false;
+ geofence_ctx.geofence_property[item].fd = -1;
+ geofence_ctx.fence_number--;
+
+ return 0;
+}
+
+void mtk_geofence_clear_fence_db(int fd) {
+ int item;
+
+ for (item = 0; item < MAX_GOEFENCE; item++) {
+ if (geofence_ctx.geofence_property[item].is_used && (geofence_ctx.geofence_property[item].fd == fd)) {
+ memset(&geofence_ctx.geofence_property[item].geofence_prop, 0, sizeof(mtk_geofence_property_db));
+ geofence_ctx.geofence_property[item].is_used = false;
+ geofence_ctx.geofence_property[item].fd = -1;
+ geofence_ctx.fence_number--;
+ }
+ }
+}
+
+int mtk_geofence_clear_geofences_by_msg(int fd) {
+ mtk_geofence_msg *prmsg=NULL;
+ unsigned int msg_len;
+ char geo_data[GEOFENCE_BUFF_SIZE] = {0};
+
+ LOGD("geofence_clear_geofences,fd:%d\r\n", fd);
+ //construct remove fence cmd
+ msg_len = sizeof(mtk_geofence_msg);
+ prmsg = (mtk_geofence_msg *)&geo_data[0];
+ if (msg_len > GEOFENCE_BUFF_SIZE){
+ LOGE("geofence main message length too long:%d", msg_len);
+ return MTK_GFC_ERROR;
+ }
+
+ prmsg->type = CLEAR_GEOFENCE;
+ prmsg->length = msg_len;
+ mtk_geofence_clear_fence_db(fd);
+ mtk_geofence_controller_process(prmsg);
+ return MTK_GFC_SUCCESS;
+
+}
+
+int mtk_geofence_add_rawdata_to_buffer(char *data, int length) {
+ int i;
+
+ 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");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int mtk_geofence_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 create_geofence2mnl_data_fd() {
+ int fd = socket_tcp_server_bind_local(true, GEOFENCEADP_MNL_TCP_DATA);
+ memset(&g_geofence_client_list, 0, sizeof(g_geofence_client_list));
+ return fd;
+}
+
+int create_geofence2mnl_control_fd() {
+ int fd = socket_tcp_server_bind_local(true, GEOFENCEADP_MNL_TCP_CONTROL);
+ memset(&g_geofence_client_control_list, 0, sizeof(g_geofence_client_control_list));
+ return fd;
+}
+
+int mtk_geofence2mnl_get_valid_fence_num()
+{
+ return geofence_ctx.fence_number;
+}
+
+int mtk_geofence_send2adpator(int fd, const char* buff, int len) {
+ int ret = write(fd, buff, len);
+ if(ret == -1) {
+ LOGE("geofence_send2adpator() write() failed, reason=[%s]%d", strerror(errno), errno);
+ }
+ return ret;
+}
+
+int mtk_geofence_server_capability_send(int fd) {
+ int ret;
+ mtk_geofence_msg *geo_header=NULL;
+ unsigned int msg_len;
+ mtk_geofence_server_init_msg init_msg;
+ char geo_data[GEOFENCE_BUFF_SIZE] = {0};
+
+ LOGD("mtk_geofence_server_capability_send fd:%d %lu", fd, sizeof(mtk_geofence_server_init_msg));
+ //construct add fence cmd
+ msg_len = sizeof(mtk_geofence_msg) + sizeof(mtk_geofence_server_init_msg);
+ geo_header = (mtk_geofence_msg *)&geo_data[0];
+ if (msg_len > GEOFENCE_BUFF_SIZE){
+ LOGE("geofence main message length too long:%d", msg_len);
+ return MTK_GFC_ERROR;
+ }
+
+ geo_header->type = GEOFENCE_SERVER_CAP;
+ geo_header->length = msg_len;
+ init_msg.geofence_support = geofence_server_cap.geofence_support;
+ init_msg.server_data_fd = fd;
+
+ memcpy( ((char*)geo_header) + sizeof(mtk_geofence_msg),&init_msg, sizeof(mtk_geofence_server_init_msg));
+ ret = mtk_geofence_send2adpator(fd, (char*)geo_header, msg_len);
+ if(ret < 0) {
+ LOGE("MTK mnl to adaptor send error return error");
+ return MTK_GFC_ERROR;
+ }
+ return MTK_GFC_SUCCESS;
+}
+
+void mtk_geofence_location_expire(mtk_geofence_position_info coordinate_loc)
+{
+ int i;
+ mtk_geofence_status state;
+ int transiton = MTK_GEOFENCE_TRANSITION_NO_CHANGE;
+ LOGD("Fix_type:%d lat:%.6f lon:%.6f hacc:%.1f UTC:%02d%02d%02d",
+ coordinate_loc.fix_type, coordinate_loc.latitude, coordinate_loc.longitude, coordinate_loc.h_acc,
+ coordinate_loc.utc_time.hour, coordinate_loc.utc_time.min, coordinate_loc.utc_time.sec);
+ //Check tracking status
+ mtk_geofence_check_tracking_status(&coordinate_loc);
+
+ for ( i = 0; i < MAX_GOEFENCE; i++ )
+ {
+ if(geofence_ctx.geofence_property[i].is_used)
+ {
+ state = fence_state(geofence_ctx.geofence_property[i].geofence_prop.latitude,
+ geofence_ctx.geofence_property[i].geofence_prop.longitude,
+ geofence_ctx.geofence_property[i].geofence_prop.radius,
+ coordinate_loc);
+ transiton = state_lookup_table[geofence_ctx.geofence_property[i].geofence_prop.latest_state][state];
+ LOGD("fence_id:%d latest_state:%d state:%d transition:%d",
+ (i+1), geofence_ctx.geofence_property[i].geofence_prop.latest_state, state, transiton);
+ geofence_ctx.geofence_property[i].geofence_prop.latest_state = state;
+ if((geofence_ctx.geofence_property[i].geofence_prop.last_transition != transiton)
+ && (transiton != MTK_GEOFENCE_TRANSITION_NO_CHANGE)
+ && (state != GEOFENCE_UNKNOWN))
+ {
+ if (geofence_ctx.geofence_property[i].geofence_prop.monitor_transition & transiton) {
+ mtk_geofence2mnl_geofence_alert(geofence_ctx.geofence_property[i].fd, (i+1), state, &coordinate_loc);
+ LOGD("fence id %d transition update from %x -> %x\n", (i + 1), geofence_ctx.geofence_property[i].geofence_prop.monitor_transition, transiton);
+ } else {
+ LOGD("fence id %d transition update from %x -> %x bypass\n",(i + 1), geofence_ctx.geofence_property[i].geofence_prop.monitor_transition, transiton);
+ }
+ geofence_ctx.geofence_new_timer[i].unknown_init_ttick = 0; //reset unknown timer init ttick
+ geofence_ctx.geofence_new_timer[i].unknown_elapsed_ttick =0; //reset unknown timer elapsed time
+ geofence_ctx.geofence_property[i].geofence_prop.latest_state = state;/*update latest state*/
+ geofence_ctx.geofence_property[i].geofence_prop.last_transition = transiton; /*update latest transition*/
+ }
+ else
+ {
+ if(state == GEOFENCE_UNKNOWN)
+ {
+ //FLP_TRC("fence id %d,current state == uncertain",i);
+ if(geofence_ctx.geofence_new_timer[i].unknown_init_ttick == 0) //check if it is the first time entering uncertain state
+ {
+ //FLP_TRC("unknown ttick =0; elapsed = %d, init ttick=%d",geofence_new_timer[i].unknown_elapsed_ttick,geofence_new_timer[i].unknown_init_ttick );
+ if(geofence_ctx.geofence_new_timer[i].unknown_elapsed_ttick == 0 ) //check if already inform the state transition NTF to AP
+ {
+ geofence_ctx.geofence_new_timer[i].unknown_init_ttick = get_time_in_millisecond(); //record the initial time of unknown timer
+ //FLP_TRC("unknown init ttick ==%d",geofence_new_timer[i].unknown_init_ttick);
+ }
+ else
+ {
+ //FLP_TRC("no update");
+ //do nothing, the transition was dated to AP already
+ }
+ }
+ else //update unknown timer elapsed time
+ {
+ geofence_ctx.geofence_new_timer[i].unknown_elapsed_ttick = get_time_in_millisecond() - geofence_ctx.geofence_new_timer[i].unknown_init_ttick; //update unknown counter
+ LOGD("unknown timer elapsed: %ld", geofence_ctx.geofence_new_timer[i].unknown_elapsed_ttick);
+ if( (geofence_ctx.geofence_new_timer[i].unknown_elapsed_ttick
+ >= geofence_ctx.geofence_property[i].geofence_prop.unknown_timer)
+ && (geofence_ctx.geofence_property[i].geofence_prop.unknown_timer > 0)) //Check if unknown counter reach user defined value
+ {
+ //Notify transition state: from in/out to uncertain
+ mtk_geofence2mnl_geofence_alert(geofence_ctx.geofence_property[i].fd, (i+1), GEOFENCE_UNKNOWN, &coordinate_loc);
+ LOGD("fence id %d transition update from %x -> %x uncertain\n",(i+1), geofence_ctx.geofence_property[i].geofence_prop.last_transition, transiton);
+ geofence_ctx.geofence_new_timer[i].unknown_init_ttick = 0; //only reset init ttick, elapsed time will not reset to keep a record of the update of transition state
+ geofence_ctx.geofence_property[i].geofence_prop.latest_state = GEOFENCE_UNKNOWN;/*update latest state*/
+ geofence_ctx.geofence_property[i].geofence_prop.last_transition = MTK_GEOFENCE_TRANSITION_UNCERTAIN; /*update latest transition*/
+ }
+ }
+ } else {
+ geofence_ctx.geofence_new_timer[i].unknown_init_ttick = 0; //reset unknown timer init ttick
+ geofence_ctx.geofence_new_timer[i].unknown_elapsed_ttick =0; //reset unknown timer elapsed time
+ }
+ }
+ }
+ }
+}
+
+int mtk_geofence2mnl_geofence_alert(int fd, int fence_id, int alet_stat, mtk_geofence_position_info* pos_data)
+{
+ int ret;
+ mtk_geofence_msg *geo_header=NULL;
+ unsigned int msg_len;
+ mtk_geofence_alert fence_alert;
+ char geo_data[GEOFENCE_BUFF_SIZE] = {0};
+
+ //construct add fence cmd
+ msg_len = sizeof(mtk_geofence_msg) + sizeof(mtk_geofence_alert);
+ geo_header = (mtk_geofence_msg *)&geo_data[0];
+ if (msg_len > GEOFENCE_BUFF_SIZE){
+ LOGE("geofence main message length too long:%d", msg_len);
+ return MTK_GFC_ERROR;
+ }
+
+ geo_header->type = GEOFENCE_ALERT_INFO;
+ geo_header->length = msg_len;
+ if (pos_data == NULL){//For mock UT test if pos_data is NULL
+ //+EGEORESP: 1,1,24.125465,121.365496,100.23,1.23,3.54,3,6,2,6,3,2.52,1.32,2.12\r\n
+ fence_alert.id = fence_id;
+ fence_alert.alert_state = 1;
+ fence_alert.latitude = 24.125465;
+ fence_alert.longitude = 121.365496;
+ fence_alert.altitude = 100.23;
+ fence_alert.speed = 1.23;
+ fence_alert.heading = 3.54;
+ fence_alert.h_acc = 3;
+ fence_alert.h_err_majoraxis = 6;
+ fence_alert.h_err_minoraxis = 2;
+ fence_alert.h_err_angle = 6;
+ fence_alert.hor_conf = 3;
+ fence_alert.pdop = 2.52;
+ fence_alert.hdop = 1.32;
+ fence_alert.vdop = 2.12;
+ } else {
+ fence_alert.id = fence_id;
+ fence_alert.alert_state = alet_stat;
+ fence_alert.latitude = pos_data->latitude;
+ fence_alert.longitude = pos_data->longitude;
+ fence_alert.altitude = pos_data->altitude;
+ fence_alert.speed = pos_data->speed;
+ fence_alert.heading = pos_data->heading;
+ fence_alert.h_acc = (int)pos_data->h_acc;
+ fence_alert.h_err_majoraxis = (int)pos_data->h_err_majoraxis;
+ fence_alert.h_err_minoraxis = (int)pos_data->h_err_minoraxis;
+ fence_alert.h_err_angle = (int)pos_data->h_err_angle;
+ fence_alert.hor_conf = (int)pos_data->h_acc;
+ fence_alert.pdop = (int)pos_data->pdop;
+ fence_alert.hdop = (int)pos_data->hdop;
+ fence_alert.vdop = (int)pos_data->vdop;
+ }
+ memcpy(((char*)geo_header) + sizeof(mtk_geofence_msg),&fence_alert, sizeof(mtk_geofence_alert));
+ ret = mtk_geofence_send2adpator(fd, (char*)geo_header, msg_len);
+ if(ret < 0) {
+ LOGE("MTK mnl to adaptor send error return error");
+ return MTK_GFC_ERROR;
+ }
+ return MTK_GFC_SUCCESS;
+}
+
+int mtk_geofence2mnl_geofence_tracking_status(int fd, int tracking_stat, mtk_geofence_position_info *pos) {
+ int ret;
+ mtk_geofence_msg *geo_header=NULL;
+ unsigned int msg_len;
+ mtk_gnss_tracking_status tracking_status;
+ char geo_data[GEOFENCE_BUFF_SIZE] = {0};
+
+ //construct add fence cmd
+ msg_len = sizeof(mtk_geofence_msg) + sizeof(mtk_gnss_tracking_status);
+ geo_header = (mtk_geofence_msg *)&geo_data[0];
+ if (msg_len > GEOFENCE_BUFF_SIZE){
+ LOGE("geofence main message length too long:%d", msg_len);
+ return MTK_GFC_ERROR;
+ }
+
+ geo_header->type = GNSS_TRACKING_STATUS;
+ geo_header->length = msg_len;
+ if (pos == NULL){//UT test case if pos == null
+ tracking_status.status = tracking_stat;
+ tracking_status.year =2020;
+ tracking_status.month = 5;
+ tracking_status.day = 10;
+ tracking_status.hour = 21;
+ tracking_status.minute = 6;
+ tracking_status.second = 23;
+ } else {
+ tracking_status.status = tracking_stat;
+ tracking_status.year = (int)(pos->utc_time.year + 1900);
+ tracking_status.month = (int)(pos->utc_time.month + 1);
+ tracking_status.day = (int)pos->utc_time.mday;
+ tracking_status.hour = (int)pos->utc_time.hour;
+ tracking_status.minute = (int)pos->utc_time.min;
+ tracking_status.second = (int)pos->utc_time.sec;
+ }
+ LOGD("geofence tracking status change:stat:%d time:%d %d %d %d %d %d",
+ tracking_stat, tracking_status.year, tracking_status.month, tracking_status.day, tracking_status.hour, tracking_status.minute, tracking_status.second);
+ memcpy( ((char*)geo_header) + sizeof(mtk_geofence_msg),&tracking_status, sizeof(mtk_gnss_tracking_status));
+ ret = mtk_geofence_send2adpator(fd, (char*)geo_header, msg_len);
+ if(ret < 0) {
+ LOGE("MTK mnl to adaptor send error return error");
+ return MTK_GFC_ERROR;
+ }
+ return MTK_GFC_SUCCESS;
+}
+
+int mtk_geofence2mnl_add_geofence_result(int fd, int fence_id, int result) {
+ int ret;
+ mtk_geofence_msg *geo_header=NULL;
+ unsigned int msg_len;
+ mtk_geofence_create_status fence_ret;
+ char geo_data[GEOFENCE_BUFF_SIZE] = {0};
+
+ //construct add fence cmd
+ msg_len = sizeof(mtk_geofence_msg) + sizeof(mtk_geofence_create_status);
+ geo_header = (mtk_geofence_msg *)&geo_data[0];
+ if (msg_len > GEOFENCE_BUFF_SIZE){
+ LOGE("geofence main message length too long:%d", msg_len);
+ return MTK_GFC_ERROR;
+ }
+
+ geo_header->type = GEOFENCE_RESPONSE_INFO;
+ geo_header->length = msg_len;
+ fence_ret.createstat = result;
+ fence_ret.id = fence_id;
+ memcpy( ((char*)geo_header) + sizeof(mtk_geofence_msg),&fence_ret, sizeof(mtk_geofence_create_status));
+ ret = mtk_geofence_send2adpator(fd, (char*)geo_header, msg_len);
+ if(ret < 0) {
+ LOGE("MTK mnl to adaptor send error return error");
+ return MTK_GFC_ERROR;
+ }
+ return MTK_GFC_SUCCESS;
+}
+
+int mtk_geofence2mnl_geofence_remove_result(int fd, int result) {
+ int ret;
+ mtk_geofence_msg *geo_header=NULL;
+ unsigned int msg_len;
+ mtk_geofence_result rlt;
+ char geo_data[GEOFENCE_BUFF_SIZE] = {0};
+
+ //construct add fence cmd
+ msg_len = sizeof(mtk_geofence_msg) + sizeof(mtk_geofence_result);
+ geo_header = (mtk_geofence_msg *)&geo_data[0];
+ if (msg_len > GEOFENCE_BUFF_SIZE){
+ LOGE("geofence main message length too long:%d", msg_len);
+ return MTK_GFC_ERROR;
+ }
+
+ geo_header->type = EXCUTE_RESULT;
+ geo_header->length = msg_len;
+ rlt.cmdtype = REMOVE_GEOFENCE;
+ rlt.result = result;
+ memcpy( ((char*)geo_header) + sizeof(mtk_geofence_msg),&rlt, sizeof(mtk_geofence_result));
+ ret = mtk_geofence_send2adpator(fd, (char*)geo_header, msg_len);
+ if(ret < 0) {
+ LOGE("MTK mnl to adaptor send error return error");
+ return MTK_GFC_ERROR;
+ }
+ return MTK_GFC_SUCCESS;
+}
+
+int mtk_geofence2mnl_geofence_clear_result(int fd, int result) {
+ int ret;
+ mtk_geofence_msg *geo_header=NULL;
+ unsigned int msg_len;
+ mtk_geofence_result rlt;
+ char geo_data[GEOFENCE_BUFF_SIZE] = {0};
+
+ //construct add fence cmd
+ msg_len = sizeof(mtk_geofence_msg) + sizeof(mtk_geofence_result);
+ geo_header = (mtk_geofence_msg *)&geo_data[0];
+ if (msg_len > GEOFENCE_BUFF_SIZE){
+ LOGE("geofence main message length too long:%d", msg_len);
+ return MTK_GFC_ERROR;
+ }
+
+ geo_header->type = EXCUTE_RESULT;
+ geo_header->length = msg_len;
+ rlt.cmdtype = CLEAR_GEOFENCE;
+ rlt.result = result;
+ memcpy( ((char*)geo_header) + sizeof(mtk_geofence_msg),&rlt, sizeof(mtk_geofence_result));
+ ret = mtk_geofence_send2adpator(fd, (char*)geo_header, msg_len);
+ if(ret < 0) {
+ LOGE("MTK mnl to adaptor send error return error");
+ return MTK_GFC_ERROR;
+ }
+ return MTK_GFC_SUCCESS;
+}
+
+int mtk_geofence2mnl_geofence_query_result(int fd, int result) {
+ int ret;
+ mtk_geofence_msg *geo_header=NULL;
+ unsigned int msg_len;
+ int fence_num;
+ char geo_data[GEOFENCE_BUFF_SIZE] = {0};
+
+ //construct add 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("geofence main message length too long:%d", msg_len);
+ return MTK_GFC_ERROR;
+ }
+
+ geo_header->type = GEOFENCE_NUM;
+ geo_header->length = msg_len;
+ if (result == 0){
+ fence_num = MAX_GOEFENCE;
+ } else {
+ fence_num = -1;
+ }
+ memcpy( ((char*)geo_header) + sizeof(mtk_geofence_msg),&fence_num, sizeof(int));
+ ret = mtk_geofence_send2adpator(fd, (char*)geo_header, msg_len);
+ if(ret < 0) {
+ LOGE("MTK mnl to adaptor send error return error");
+ return MTK_GFC_ERROR;
+ }
+ return MTK_GFC_SUCCESS;
+}
+
+void mtk_geofence2mnl_geofence_add_area(int fd, mtk_geofence_msg *prmsg)
+{
+ mtk_geofence_property fence;
+ unsigned int msg_len;
+ char data[GEOFENCE_BUFF_SIZE] = {0};
+ int ret;
+ int fence_id;
+ int server_data_id;
+
+ msg_len = sizeof(mtk_geofence_msg) + sizeof(int) + sizeof(mtk_geofence_property);
+ if (prmsg->length == msg_len){
+ memcpy(&server_data_id, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(int));
+ memcpy(&fence, (((char*)prmsg)+sizeof(mtk_geofence_msg)+sizeof(int)), sizeof(mtk_geofence_property));
+ } else if (prmsg->length > msg_len) {
+ memcpy(&server_data_id, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(int));
+ memcpy(&fence, (((char*)prmsg)+sizeof(mtk_geofence_msg)+sizeof(int)), sizeof(mtk_geofence_property));
+ 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(&server_data_id, (((char*)data)+sizeof(mtk_geofence_msg)), sizeof(int));
+ memcpy(&fence, (((char*)data)+sizeof(mtk_geofence_msg)+sizeof(int)), sizeof(mtk_geofence_property));
+ LOGD("mnl msg len:%d < struct len:%d", prmsg->length, msg_len);
+ }
+
+ if (!mtk_geofence_check_data_fd_exist(server_data_id)){
+ mtk_geofence2mnl_add_geofence_result(fd, 0, MTK_ADD_GEOFENCE_ERROR);
+ LOGE("mtk_geofence2mnl_geofence_add_area:server data fd don't exist %d", server_data_id);
+ return;
+ }
+
+ ret = mtk_geofence_check_fence_vadility(&fence);
+ if (ret == 0) {
+ if ((fence_id = mtk_geofence_add_new_fence(server_data_id, &fence)) > 0){
+ mtk_geofence2mnl_add_geofence_result(fd, fence_id, MTK_ADD_GEOFENCE_SUCCESS);
+ } else if (fence_id == -1){
+ mtk_geofence2mnl_add_geofence_result(fd, 0, MTK_ADD_GEOFENCE_TOO_MANY);
+ }
+ } else {
+ mtk_geofence2mnl_add_geofence_result(fd, 0, MTK_ADD_GEOFENCE_ERROR);
+ }
+
+ LOGD("geofence_add_area,fd:%d lat:%.6f lon%.6f rad:%.2f InitStat:%d AlertType:%d UnknownTime:%d\r\n",
+ fd,
+ fence.latitude,
+ fence.longitude,
+ fence.radius,
+ fence.latest_state,
+ fence.monitor_transition,
+ fence.unknown_timer);
+}
+
+void mtk_geofence2mnl_geofence_remove_fence(int fd, mtk_geofence_msg *prmsg)
+{
+ int id;
+ unsigned int msg_len;
+ char data[GEOFENCE_BUFF_SIZE] = {0};
+ int server_data_id;
+
+ msg_len = sizeof(mtk_geofence_msg)+ sizeof(int) + sizeof(int);
+ if (prmsg->length == msg_len){
+ memcpy(&server_data_id, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(int));
+ memcpy(&id, (((char*)prmsg)+sizeof(mtk_geofence_msg)+ sizeof(int)), sizeof(int));
+ } else if (prmsg->length > msg_len) {
+ memcpy(&server_data_id, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(int));
+ memcpy(&id, (((char*)prmsg)+sizeof(mtk_geofence_msg)+ sizeof(int)), 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(&server_data_id, (((char*)data)+sizeof(mtk_geofence_msg)), sizeof(int));
+ memcpy(&id, (((char*)data)+sizeof(mtk_geofence_msg)+ sizeof(int)), sizeof(int));
+ LOGD("mnl msg len:%d < struct len:%d", prmsg->length, msg_len);
+ }
+
+ if (!mtk_geofence_check_data_fd_exist(server_data_id)){
+ mtk_geofence2mnl_geofence_remove_result(fd, -1);
+ LOGE("mtk_geofence2mnl_geofence_remove_fence:server data fd don't exist %d", server_data_id);
+ return;
+ }
+
+ LOGD("geofence_remove_fence,fd:%d %d\r\n",fd, id);
+ if (mtk_geofence_remove_fence(server_data_id, id) >= 0){
+ mtk_geofence2mnl_geofence_remove_result(fd, 0);
+ } else {
+ mtk_geofence2mnl_geofence_remove_result(fd, -1);
+ }
+}
+
+void mtk_geofence2mnl_geofence_clear_fence(int fd, mtk_geofence_msg *prmsg)
+{
+ int server_data_id;
+ unsigned int msg_len;
+ char data[GEOFENCE_BUFF_SIZE] = {0};
+
+ msg_len = sizeof(mtk_geofence_msg) + sizeof(int);
+ if (prmsg->length == msg_len){
+ memcpy(&server_data_id, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(int));
+ } else if (prmsg->length > msg_len) {
+ memcpy(&server_data_id, (((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(&server_data_id, (((char*)data)+sizeof(mtk_geofence_msg)), sizeof(int));
+ LOGD("mnl msg len:%d < struct len:%d", prmsg->length, msg_len);
+ }
+
+ if (!mtk_geofence_check_data_fd_exist(server_data_id)){
+ mtk_geofence2mnl_geofence_clear_result(fd, -1);
+ LOGE("mtk_geofence2mnl_geofence_clear_fence:server data fd don't exist %d", server_data_id);
+ return;
+ }
+
+ LOGD("geofence_clear_fence,fd:%d\r\n",fd);
+ mtk_geofence_clear_fence_db(server_data_id);
+ mtk_geofence2mnl_geofence_clear_result(fd, 0);
+}
+
+void mtk_geofence2mnl_geofence_query_num(int fd, mtk_geofence_msg *prmsg)
+{
+ int server_data_id;
+ unsigned int msg_len;
+ char data[GEOFENCE_BUFF_SIZE] = {0};
+
+ LOGD("geofence_query_num,fd:%d\r\n",fd);
+ msg_len = sizeof(mtk_geofence_msg) + sizeof(int);
+ if (prmsg->length == msg_len){
+ memcpy(&server_data_id, (((char*)prmsg)+sizeof(mtk_geofence_msg)), sizeof(int));
+ } else if (prmsg->length > msg_len) {
+ memcpy(&server_data_id, (((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(&server_data_id, (((char*)data)+sizeof(mtk_geofence_msg)), sizeof(int));
+ LOGD("mnl msg len:%d < struct len:%d", prmsg->length, msg_len);
+ }
+
+ if (!mtk_geofence_check_data_fd_exist(server_data_id)){
+ mtk_geofence2mnl_geofence_query_result(fd, -1);
+ LOGE("mtk_geofence2mnl_geofence_query_num:server data fd don't exist %d", server_data_id);
+ return;
+ }
+
+ mtk_geofence2mnl_geofence_query_result(fd, 0);
+}
+
+int mtk_geofence2mnl_hdlr (int fd, char *buff, int length) {
+ char data[GEOFENCE_BUFF_SIZE] = {0};
+ int ret = MTK_GFC_ERROR, len;
+ unsigned int msg_len;
+ mtk_geofence_command cmd;
+ mtk_geofence_msg *prmsg = NULL;
+
+ if(buff == NULL) {
+ LOGE("mnl2gfchal_hdlr, recv prmsg is null pointer\r\n");
+ return MTK_GFC_ERROR;
+ }
+
+ if (mtk_geofence_add_rawdata_to_buffer(buff, length) < 0){
+ //error handle
+ }
+
+ while ( (len = mtk_geofence_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 ret;
+ }
+ cmd = prmsg->type;
+ msg_len = prmsg->length;
+
+ LOGD("cmd %d, len %d\r\n", cmd, msg_len);
+
+ switch (cmd) {
+ case ADD_GEOFENCE_AREA:
+ mtk_geofence_controller_process(prmsg);
+ mtk_geofence2mnl_geofence_add_area(fd, prmsg);
+ break;
+ case REMOVE_GEOFENCE:
+ mtk_geofence2mnl_geofence_remove_fence(fd,prmsg);
+ mtk_geofence_controller_process(prmsg);
+ break;
+ case CLEAR_GEOFENCE:
+ mtk_geofence2mnl_geofence_clear_fence(fd, prmsg);
+ mtk_geofence_controller_process(prmsg);
+ break;
+ case QUERY_GEOFENCE_NUM:
+ mtk_geofence2mnl_geofence_query_num(fd, prmsg);
+ break;
+ case GEOFENCE_CLIENT_CAP:
+ //currenttly do nothing
+ break;
+ default:
+ LOGE("invalid geofence cmd:%d",cmd);
+ break;
+ }
+
+ memset(data, 0, GEOFENCE_BUFF_SIZE);
+ len = 0;
+ }
+ return MTK_GFC_SUCCESS;
+}
+
+void mtk_geofence_init(void)
+{
+ g_cyclical_buffer.start_buffer = &geofence_raw_data[0];
+ buffer_initialize(&g_cyclical_buffer, GEOFENCE_DATAPATH_SIZE);
+ tracking_stat = -1;
+ continue_trk_points = 0;
+ #ifdef MTK_GNSS_GEOFENCE_UT
+ g_geofence_start_timer = init_timer(geofence_timer_fence_alert);
+ start_timer(g_geofence_start_timer, 10000);
+ #endif
+}
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_log_interface/inc/LbsLogInterface.h b/src/connectivity/gps/2.0/mtk_mnld/mnl_log_interface/inc/LbsLogInterface.h
new file mode 100644
index 0000000..c447095
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_log_interface/inc/LbsLogInterface.h
@@ -0,0 +1,69 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __LbsLogInterface_H__
+#define __LbsLogInterface_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LBS_LOG_INTERFACE_PROTOCOL_TYPE 307
+#define LBS_LOG_INTERFACE_BUFF_SIZE (10*1000)
+#define LBS_LOG_INTERFACE_HEADER_SIZE (16)
+
+/**
+ * The LBS log interface from vendor to system
+ */
+typedef enum {
+ LBS_LOG_INTERFACE_OPEN_LOG = 0,
+ LBS_LOG_INTERFACE_CLOSE_LOG = 1,
+ LBS_LOG_INTERFACE_WRITE_LOG = 2,
+} LbsLogInterface_message_id;
+
+
+typedef enum {
+ LBS_LOG_INTERFACE_LOG_CATEGORY_GPS_LOG = 0,
+ LBS_LOG_INTERFACE_LOG_CATEGORY_MPE_LOG = 1,
+ LBS_LOG_INTERFACE_LOG_CATEGORY_DUMP_LOG = 2,
+} LbsLogInterface_LogCategory;
+
+
+// LbsLogInterface_LogCategory
+const char* LbsLogInterface_LogCategory_to_string(LbsLogInterface_LogCategory data);
+void LbsLogInterface_LogCategory_array_dump(LbsLogInterface_LogCategory data[], int size);
+
+void LbsLogInterface_LogCategory_array_init(LbsLogInterface_LogCategory output[], int max_size);
+
+bool LbsLogInterface_LogCategory_is_equal(LbsLogInterface_LogCategory data1, LbsLogInterface_LogCategory data2);
+bool LbsLogInterface_LogCategory_array_is_equal(LbsLogInterface_LogCategory data1[], int size1, LbsLogInterface_LogCategory data2[], int size2);
+
+bool LbsLogInterface_LogCategory_encode(char* buff, int* offset, LbsLogInterface_LogCategory data);
+bool LbsLogInterface_LogCategory_array_encode(char* buff, int* offset, LbsLogInterface_LogCategory data[], int size);
+
+void LbsLogInterface_LogCategory_decode(char* buff, int* offset, LbsLogInterface_LogCategory* output);
+int LbsLogInterface_LogCategory_array_decode(char* buff, int* offset, LbsLogInterface_LogCategory output[], int max_size);
+
+// Sender
+bool LbsLogInterface_openLog(mtk_socket_fd* client_fd, LbsLogInterface_LogCategory type, const char* filePath);
+
+bool LbsLogInterface_closeLog(mtk_socket_fd* client_fd, LbsLogInterface_LogCategory type);
+
+bool LbsLogInterface_writeLog(mtk_socket_fd* client_fd, LbsLogInterface_LogCategory type, char log[], int log_size);
+
+// Receiver
+typedef struct {
+ void (*LbsLogInterface_openLog_handler) (LbsLogInterface_LogCategory type, char* filePath);
+ void (*LbsLogInterface_closeLog_handler) (LbsLogInterface_LogCategory type);
+ void (*LbsLogInterface_writeLog_handler) (LbsLogInterface_LogCategory type, char log[], int log_size);
+} LbsLogInterface_callbacks;
+
+bool LbsLogInterface_receiver_decode(char* _buff, LbsLogInterface_callbacks* callbacks);
+bool LbsLogInterface_receiver_read_and_decode(int server_fd, LbsLogInterface_callbacks* callbacks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_log_interface/src/LbsLogInterface.c b/src/connectivity/gps/2.0/mtk_mnld/mnl_log_interface/src/LbsLogInterface.c
new file mode 100644
index 0000000..2290c0e
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_log_interface/src/LbsLogInterface.c
@@ -0,0 +1,263 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "LbsLogInterface.h"
+#include "mtk_socket_data_coder.h"
+
+// LbsLogInterface_LogCategory
+const char* LbsLogInterface_LogCategory_to_string(LbsLogInterface_LogCategory data) {
+ switch(data) {
+ case LBS_LOG_INTERFACE_LOG_CATEGORY_GPS_LOG:
+ return "gpsLog";
+ case LBS_LOG_INTERFACE_LOG_CATEGORY_MPE_LOG:
+ return "mpeLog";
+ case LBS_LOG_INTERFACE_LOG_CATEGORY_DUMP_LOG:
+ return "dumpLog";
+ default:
+ break;
+ }
+ return "UNKNOWN";
+}
+void LbsLogInterface_LogCategory_array_dump(LbsLogInterface_LogCategory data[], int size) {
+ int i = 0;
+ SOCK_LOGD("LbsLogInterface_LogCategory_array_dump() size=[%d]", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%s]", i, LbsLogInterface_LogCategory_to_string(data[i]));
+ }
+}
+
+void LbsLogInterface_LogCategory_array_init(LbsLogInterface_LogCategory output[], int max_size) {
+ int i = 0;
+ for(i = 0; i < max_size; i++) {
+ output[i] = LBS_LOG_INTERFACE_LOG_CATEGORY_GPS_LOG;
+ }
+}
+
+bool LbsLogInterface_LogCategory_is_equal(LbsLogInterface_LogCategory data1, LbsLogInterface_LogCategory data2) {
+ return (data1 == data2)? true : false;
+}
+bool LbsLogInterface_LogCategory_array_is_equal(LbsLogInterface_LogCategory data1[], int size1, LbsLogInterface_LogCategory data2[], int size2) {
+ int i = 0;
+ if(size1 != size2) return false;
+ for(i = 0; i < size1; i++) {
+ if(data1[i] != data2[i]) return false;
+ }
+ return true;
+}
+
+bool LbsLogInterface_LogCategory_encode(char* buff, int* offset, LbsLogInterface_LogCategory data) {
+ switch(data) {
+ case LBS_LOG_INTERFACE_LOG_CATEGORY_GPS_LOG:
+ case LBS_LOG_INTERFACE_LOG_CATEGORY_MPE_LOG:
+ case LBS_LOG_INTERFACE_LOG_CATEGORY_DUMP_LOG:
+ break;
+ default:
+ SOCK_LOGE("LbsLogInterface_LogCategory_encode() unknown data=%d", data);
+ return false;
+ }
+ mtk_socket_put_int(buff, offset, data);
+ return true;
+}
+bool LbsLogInterface_LogCategory_array_encode(char* buff, int* offset, LbsLogInterface_LogCategory data[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ if(!LbsLogInterface_LogCategory_encode(buff, offset, data[i])) {
+ SOCK_LOGE("LbsLogInterface_LogCategory_array_encode() LbsLogInterface_LogCategory_encode() failed at i=%d", i);
+ return false;
+ }
+ }
+ return true;
+}
+
+void LbsLogInterface_LogCategory_decode(char* buff, int* offset, LbsLogInterface_LogCategory* output) {
+ *output = mtk_socket_get_int(buff, offset);
+}
+int LbsLogInterface_LogCategory_array_decode(char* buff, int* offset, LbsLogInterface_LogCategory output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ if(i < max_size) {
+ LbsLogInterface_LogCategory_decode(buff, offset, &output[i]);
+ } else {
+ LbsLogInterface_LogCategory data;
+ LbsLogInterface_LogCategory_decode(buff, offset, &data);
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+
+// Sender
+bool LbsLogInterface_openLog(mtk_socket_fd* client_fd, LbsLogInterface_LogCategory type, const char* filePath) {
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("LbsLogInterface_openLog() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ char _buff[LBS_LOG_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, LBS_LOG_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, LBS_LOG_INTERFACE_OPEN_LOG);
+ if(!LbsLogInterface_LogCategory_encode(_buff, &_offset, type)) {
+ SOCK_LOGE("LbsLogInterface_openLog() LbsLogInterface_LogCategory_encode() fail on type");
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ if(strlen(filePath) > 256) {
+ SOCK_LOGE("LbsLogInterface_openLog() strlen of filePath=[%zu] is over 256", strlen(filePath));
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_put_string(_buff, &_offset, filePath);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("LbsLogInterface_openLog() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+bool LbsLogInterface_closeLog(mtk_socket_fd* client_fd, LbsLogInterface_LogCategory type) {
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("LbsLogInterface_closeLog() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ char _buff[LBS_LOG_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, LBS_LOG_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, LBS_LOG_INTERFACE_CLOSE_LOG);
+ if(!LbsLogInterface_LogCategory_encode(_buff, &_offset, type)) {
+ SOCK_LOGE("LbsLogInterface_closeLog() LbsLogInterface_LogCategory_encode() fail on type");
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("LbsLogInterface_closeLog() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+bool LbsLogInterface_writeLog(mtk_socket_fd* client_fd, LbsLogInterface_LogCategory type, char log[], int log_size) {
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("LbsLogInterface_writeLog() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ char _buff[LBS_LOG_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, LBS_LOG_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, LBS_LOG_INTERFACE_WRITE_LOG);
+ if(!LbsLogInterface_LogCategory_encode(_buff, &_offset, type)) {
+ SOCK_LOGE("LbsLogInterface_writeLog() LbsLogInterface_LogCategory_encode() fail on type");
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ ASSERT_LESS_EQUAL_THAN_FOR_MSG(log_size, 15360);
+ mtk_socket_put_char_array(_buff, &_offset, log, log_size);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("LbsLogInterface_writeLog() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+// Receiver
+bool LbsLogInterface_receiver_decode(char* _buff, LbsLogInterface_callbacks* callbacks) {
+ int _ret = 0;
+ int _offset = 0;
+ _ret = mtk_socket_get_int(_buff, &_offset);
+ if(_ret != LBS_LOG_INTERFACE_PROTOCOL_TYPE) {
+ SOCK_LOGE("LbsLogInterface_receiver_decode() protocol_type=[%d] is not equals to [%d]",
+ _ret, LBS_LOG_INTERFACE_PROTOCOL_TYPE);
+ return false;
+ }
+ _ret = mtk_socket_get_int(_buff, &_offset);
+ switch(_ret) {
+ case LBS_LOG_INTERFACE_OPEN_LOG: {
+ if(callbacks->LbsLogInterface_openLog_handler == NULL) {
+ SOCK_LOGE("LbsLogInterface_receiver_decode() LbsLogInterface_openLog_handler() is NULL");
+ return false;
+ }
+ LbsLogInterface_LogCategory type;
+ LbsLogInterface_LogCategory_decode(_buff, &_offset, &type);
+ char filePath[256];
+ mtk_socket_get_string(_buff, &_offset, filePath, 256);
+ callbacks->LbsLogInterface_openLog_handler(type, filePath);
+ break;
+ }
+ case LBS_LOG_INTERFACE_CLOSE_LOG: {
+ if(callbacks->LbsLogInterface_closeLog_handler == NULL) {
+ SOCK_LOGE("LbsLogInterface_receiver_decode() LbsLogInterface_closeLog_handler() is NULL");
+ return false;
+ }
+ LbsLogInterface_LogCategory type;
+ LbsLogInterface_LogCategory_decode(_buff, &_offset, &type);
+ callbacks->LbsLogInterface_closeLog_handler(type);
+ break;
+ }
+ case LBS_LOG_INTERFACE_WRITE_LOG: {
+ if(callbacks->LbsLogInterface_writeLog_handler == NULL) {
+ SOCK_LOGE("LbsLogInterface_receiver_decode() LbsLogInterface_writeLog_handler() is NULL");
+ return false;
+ }
+ LbsLogInterface_LogCategory type;
+ LbsLogInterface_LogCategory_decode(_buff, &_offset, &type);
+ char log[LBS_LOG_INTERFACE_BUFF_SIZE] = {0};
+ int log_size = mtk_socket_get_char_array(_buff, &_offset, log, LBS_LOG_INTERFACE_BUFF_SIZE);
+ callbacks->LbsLogInterface_writeLog_handler(type, log, log_size);
+ break;
+ }
+ default: {
+ SOCK_LOGE("LbsLogInterface_receiver_decode() unknown msgId=[%d]", _ret);
+ return false;
+ }
+ }
+ return true;
+}
+bool LbsLogInterface_receiver_read_and_decode(int server_fd, LbsLogInterface_callbacks* callbacks) {
+ int _ret;
+ char _buff[LBS_LOG_INTERFACE_BUFF_SIZE] = {0};
+
+ _ret = mtk_socket_read(server_fd, _buff, sizeof(_buff) - 1);
+ if(_ret == -1) {
+ SOCK_LOGE("LbsLogInterface_receiver_read_and_decode() mtk_socket_read() failed, fd=%d err=[%s]%d",
+ server_fd, strerror(errno), errno);
+ return false;
+ }
+ _buff[_ret] = 0;
+ return LbsLogInterface_receiver_decode(_buff, callbacks);
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_meta_interface/inc/Meta2MnldInterface.h b/src/connectivity/gps/2.0/mtk_mnld/mnl_meta_interface/inc/Meta2MnldInterface.h
new file mode 100644
index 0000000..605136d
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_meta_interface/inc/Meta2MnldInterface.h
@@ -0,0 +1,52 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __Meta2MnldInterface_H__
+#define __Meta2MnldInterface_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define META2MNLD_INTERFACE_PROTOCOL_TYPE 303
+#define META2MNLD_INTERFACE_BUFF_SIZE 12
+#define META_TO_MNLD_SOCKET "mtk_meta2mnld"
+
+/**
+ * The interface from Meta to Mnld
+ */
+typedef enum {
+ META2MNLD_INTERFACE_REQ_GNSS_LOCATION = 0,
+ META2MNLD_INTERFACE_CANCEL_GNSS_LOCATION = 1,
+} Meta2MnldInterface_message_id;
+
+
+
+// Sender
+bool Meta2MnldInterface_reqGnssLocation(mtk_socket_fd* client_fd, int source);
+
+bool Meta2MnldInterface_cancelGnssLocation(mtk_socket_fd* client_fd, int source);
+
+// Receiver
+typedef struct {
+ void (*Meta2MnldInterface_reqGnssLocation_handler) (int source);
+ void (*Meta2MnldInterface_cancelGnssLocation_handler) (int source);
+} Meta2MnldInterface_callbacks;
+
+typedef struct {
+ void (*Meta2MnldInterface_start_log_handler) ();
+ void (*Meta2MnldInterface_stop_log_handler) ();
+ void (*Meta2MnldInterface_pull_log_start_handler) ();
+ void (*Meta2MnldInterface_pull_log_stop_handler) ();
+} Meta2MnldLogctrlInterface_callbacks;
+
+bool Meta2MnldInterface_receiver_decode(char* _buff, Meta2MnldInterface_callbacks* callbacks);
+bool Meta2MnldInterface_receiver_read_and_decode(int server_fd, Meta2MnldInterface_callbacks* callbacks);
+int create_meta2mnld_fd();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_meta_interface/inc/Meta2Mnld_logctrl_Interface.h b/src/connectivity/gps/2.0/mtk_mnld/mnl_meta_interface/inc/Meta2Mnld_logctrl_Interface.h
new file mode 100644
index 0000000..791a71a
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_meta_interface/inc/Meta2Mnld_logctrl_Interface.h
@@ -0,0 +1,48 @@
+#ifndef __Meta2Mnld_logctrl_Interface_H__
+#define __Meta2Mnld_logctrl_Interface_H__
+
+#include "Meta2MnldInterface.h"
+
+typedef enum {
+ ATM_WIFI_MODE = 0,
+ ATM_USB_MODE
+} ATM_ONLINE_MODE;
+
+#define META2MNLD_INTERFACE_PROTOCOL_TYPE 303
+#define META2MNLD_INTERFACE_BUFF_SIZE 12
+#define META2MNLD_LOGCTRL_INTERFACE_BUFF_SIZE 1024
+
+#define GPSLOG_START "meta_gpslog_start"
+#define GPSLOG_STOP "meta_gpslog_stop"
+#define GPSLOG_PULL_START "pull_gpslog_start"
+#define GPSLOG_PULL_STOP "pull_gpslog_stop"
+
+extern ATM_ONLINE_MODE transfer_mode;
+
+extern int pull_stop_flag;
+
+void mnld2pc_log_closeUSBPort();
+
+bool mnld2pc_log_openUSBPort();
+
+bool mnld_sendLogDataToPC(const char *data, unsigned int len);
+
+int mnld_checkConnectType();
+
+bool mnld_TransferFile(char* logPath, const char* fileName);
+
+signed int mnld2pc_wifi_createSocket();
+
+void mnld2pc_wifi_disconnect();
+
+int mnld2pc_connect_wifi();
+
+void mnld2pc_wifi_socketClose();
+
+void mnld2pc_wifi_WaitConnect();
+bool mnld2pc_log_sendSourceFile(char* folder_path,ATM_ONLINE_MODE mode);
+int Meta2Mnld_logctrl_hdlr(int fd, Meta2MnldLogctrlInterface_callbacks* hdlr);
+int mtk_socket_tcp_startListening(const char* path, mtk_socket_namespace sock_namespace);
+
+
+#endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_meta_interface/src/Meta2MnldInterface.c b/src/connectivity/gps/2.0/mtk_mnld/mnl_meta_interface/src/Meta2MnldInterface.c
new file mode 100644
index 0000000..0f26586
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_meta_interface/src/Meta2MnldInterface.c
@@ -0,0 +1,123 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "Meta2MnldInterface.h"
+#include "mtk_socket_data_coder.h"
+#include "mtk_lbs_utility.h"
+
+
+// Sender
+bool Meta2MnldInterface_reqGnssLocation(mtk_socket_fd* client_fd, int source) {
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("Meta2MnldInterface_reqGnssLocation() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ char _buff[META2MNLD_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, META2MNLD_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, META2MNLD_INTERFACE_REQ_GNSS_LOCATION);
+ mtk_socket_put_int(_buff, &_offset, source);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("Meta2MnldInterface_reqGnssLocation() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+bool Meta2MnldInterface_cancelGnssLocation(mtk_socket_fd* client_fd, int source) {
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("Meta2MnldInterface_cancelGnssLocation() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ char _buff[META2MNLD_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, META2MNLD_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, META2MNLD_INTERFACE_CANCEL_GNSS_LOCATION);
+ mtk_socket_put_int(_buff, &_offset, source);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("Meta2MnldInterface_cancelGnssLocation() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+// Receiver
+bool Meta2MnldInterface_receiver_decode(char* _buff, Meta2MnldInterface_callbacks* callbacks) {
+ int _ret = 0;
+ int _offset = 0;
+ _ret = mtk_socket_get_int(_buff, &_offset);
+ if(_ret != META2MNLD_INTERFACE_PROTOCOL_TYPE) {
+ SOCK_LOGE("Meta2MnldInterface_receiver_decode() protocol_type=[%d] is not equals to [%d]",
+ _ret, META2MNLD_INTERFACE_PROTOCOL_TYPE);
+ return false;
+ }
+ _ret = mtk_socket_get_int(_buff, &_offset);
+ switch(_ret) {
+ case META2MNLD_INTERFACE_REQ_GNSS_LOCATION: {
+ if(callbacks->Meta2MnldInterface_reqGnssLocation_handler == NULL) {
+ SOCK_LOGE("Meta2MnldInterface_receiver_decode() Meta2MnldInterface_reqGnssLocation_handler() is NULL");
+ return false;
+ }
+ int source = mtk_socket_get_int(_buff, &_offset);
+ callbacks->Meta2MnldInterface_reqGnssLocation_handler(source);
+ break;
+ }
+ case META2MNLD_INTERFACE_CANCEL_GNSS_LOCATION: {
+ if(callbacks->Meta2MnldInterface_cancelGnssLocation_handler == NULL) {
+ SOCK_LOGE("Meta2MnldInterface_receiver_decode() Meta2MnldInterface_cancelGnssLocation_handler() is NULL");
+ return false;
+ }
+ int source = mtk_socket_get_int(_buff, &_offset);
+ callbacks->Meta2MnldInterface_cancelGnssLocation_handler(source);
+ break;
+ }
+ default: {
+ SOCK_LOGE("Meta2MnldInterface_receiver_decode() unknown msgId=[%d]", _ret);
+ return false;
+ }
+ }
+ return true;
+}
+bool Meta2MnldInterface_receiver_read_and_decode(int server_fd, Meta2MnldInterface_callbacks* callbacks) {
+ int read_len;
+ char _buff[META2MNLD_INTERFACE_BUFF_SIZE] = {0};
+
+ read_len = safe_recvfrom(server_fd, _buff, sizeof((_buff)));
+
+ if(read_len < 0) {
+ SOCK_LOGE("Meta2MnldInterface_receiver_read_and_decode() mtk_socket_read() failed, fd=%d err=[%s]%d",
+ server_fd, strerror(errno), errno);
+ return false;
+ }
+ return Meta2MnldInterface_receiver_decode(_buff, callbacks);
+}
+/*********************************************************/
+/* META to MNLD socket */
+/*********************************************************/
+int create_meta2mnld_fd() {
+ int fd = socket_bind_udp(META_TO_MNLD_SOCKET);
+ socket_set_blocking(fd, 0);
+ return fd;
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_meta_interface/src/Meta2Mnld_logctrl_Interface.c b/src/connectivity/gps/2.0/mtk_mnld/mnl_meta_interface/src/Meta2Mnld_logctrl_Interface.c
new file mode 100644
index 0000000..6326ba0
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_meta_interface/src/Meta2Mnld_logctrl_Interface.c
@@ -0,0 +1,649 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include <fcntl.h>
+#include <sys/epoll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <termios.h>
+#if defined(__ANDROID_OS__)
+#include <cutils/properties.h>
+#endif
+#include "mtk_prop_util.h"
+#include "gps_dbg_log.h"
+#include "mtk_lbs_utility.h"
+#include "Mnld2DebugInterface.h"
+#include "Meta2MnldInterface.h"
+#include "Meta2Mnld_logctrl_Interface.h"
+
+#define FULL_DIR_FILE "%s%s"
+#define PROP_META_CONN_TYPE "persist.vendor.meta.connecttype"
+#define PROP_WIFI_ADDR "persist.vendor.atm.ipaddress"
+#define LOG_BUFFER_SIZE (1024*256)
+extern unsigned int meta_logctrl;
+extern unsigned int log_mode_bitmap;
+extern char gps_debuglog_file_name[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+extern char storagePath_mtklogger_set[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+extern char storagePath[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+
+typedef struct {
+ char file_name[64];
+ unsigned int file_len;
+} FILE_HEADER;
+typedef struct {
+ FILE_HEADER file_head[1024];
+ unsigned int file_num;
+} LOG_LIST;
+ATM_ONLINE_MODE transfer_mode = ATM_USB_MODE;
+FILE_HEADER file_header_info;
+char pre_fix[16] = {0};
+char post_fix[16] = {0};
+int log_port = -1;
+int usb_port_fd = -1;
+LOG_LIST m_logFilelist;
+char m_DataLogBuf[LOG_BUFFER_SIZE] = {0};
+int m_nSockFd = -1;
+bool m_nConnect = false;
+int m_nClientFd = -1;
+static const int WIFI_SOCKET_PORT = 10007;
+static const int BACKLOG = 32;
+int pull_stop_flag = 0;
+int file_count = 0;
+int mSockListenId = -1;
+int clientConnect = -1;
+
+void mnld2pc_log_closeUSBPort() {
+ int err;
+ SOCK_LOGD("mnld begin mnld2pc_log_closeUSBPort");
+ if (usb_port_fd != -1) {
+ err = close(usb_port_fd);
+ if (err != 0) {
+ SOCK_LOGW("mnld2pc_log_closeUSBPort: close err=%d", err);
+ }
+ usb_port_fd = -1;
+ SOCK_LOGD(" close USB port fd.");
+ }
+}
+
+bool mnld2pc_log_openUSBPort() {
+ mnld2pc_log_closeUSBPort();
+ const char *vcom_dev_name = "/dev/ttyGS3";
+
+ usb_port_fd = open(vcom_dev_name, O_RDWR | O_NOCTTY);
+ SOCK_LOGD("open USB dev %s", vcom_dev_name);
+
+ if (usb_port_fd == -1) {
+ SOCK_LOGE("Cannot open USB fd, err=%d", errno);
+ return false;
+ }
+
+ struct termios termOptions;
+ if(fcntl(usb_port_fd, F_SETFL, 0) == -1) {
+ SOCK_LOGE("fcntl fail, %s, usb_port_fd:%d", strerror(errno), usb_port_fd);
+ }
+ tcgetattr(usb_port_fd, &termOptions);
+
+ // Raw mode
+ termOptions.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF | IXANY);
+ termOptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+ termOptions.c_oflag &= ~OPOST;
+
+ tcflush(usb_port_fd, TCIFLUSH);
+ termOptions.c_cc[VTIME] = 1;
+ termOptions.c_cc[VMIN] = 0;
+
+ tcsetattr(usb_port_fd, TCSANOW, &termOptions);
+ return true;
+}
+#ifdef META_LOG_CTRL_TEST
+int fd_test;
+char testlogpath[1024] = "/data/vendor/log/testlog";
+#endif
+bool mnld_sendLogDataToPC(const char *data, unsigned int len) {
+ int bytes_left = (int) len;
+ char *data_ptr = (char *) data;
+ int bytes_written;
+
+ while(bytes_left > 0) {
+ bytes_written = write(log_port, data_ptr, bytes_left);
+#ifdef META_LOG_CTRL_TEST
+ write(fd_test, data_ptr, bytes_left);
+#endif
+ if (bytes_written == -1) {
+ if (errno == EAGAIN) {
+ SOCK_LOGE("mnld_sendLogDataToPC: EAGAIN");
+ return true;
+ }
+ SOCK_LOGE("mnld_sendLogDataToPC: write failed, errno=%d, strerror=%s, len=%d, left=%d", errno, strerror(errno), len, bytes_left);
+ if (errno == 5 || errno == 9) {
+ if(transfer_mode == ATM_USB_MODE) {
+ mnld2pc_log_openUSBPort();
+ }
+ }
+ return false;
+ }
+ data_ptr += bytes_written;
+ bytes_left -= bytes_written;
+ }
+ return true;
+}
+
+int mnld_checkConnectType() {
+ char connectType[PROPERTY_VALUE_MAX] = {0};
+ property_get(PROP_META_CONN_TYPE, connectType, "");
+ if (!strncmp("wifi", connectType, strlen("wifi"))) {
+ return 0;
+ }
+ return 1;
+}
+
+bool mnld_TransferFile(char* logPath, const char* fileName) {
+ memset(file_header_info.file_name, 0, 64);
+ file_header_info.file_len = 0;
+ FILE *fp = NULL;
+ char full_path[256];
+ memset(full_path, 0, 256);
+ sprintf(full_path, FULL_DIR_FILE, logPath, fileName);
+ SOCK_LOGD("file be pulled is : %s", full_path);
+ fp = fopen(full_path, "rb");
+ if (fp != NULL) {
+ int ret = fseek(fp, 0, SEEK_END);
+ if (ret == -1) {
+ SOCK_LOGE("fseek end file error:%s", strerror(errno));
+ fclose(fp);
+ return false;
+ }
+ int file_size = ftell(fp);
+ if (file_size == -1) {
+ SOCK_LOGE("ftell file error:%s", strerror(errno));
+ fclose(fp);
+ return false;
+ }
+ MNLD_STRNCPY(file_header_info.file_name, fileName, sizeof(file_header_info.file_name));
+ file_header_info.file_len = file_size;
+ // send file_header data
+ SOCK_LOGE("file_name %s, file_size %d", file_header_info.file_name, file_header_info.file_len);
+ mnld_sendLogDataToPC((char*)(&file_header_info), sizeof(file_header_info));
+ ret = fseek(fp, 0, SEEK_SET);
+ if (ret == -1) {
+ SOCK_LOGE("fseek end file error:%s", strerror(errno));
+ fclose(fp);
+ return false;
+ }
+ while(!feof(fp)) {
+ if (pull_stop_flag == 0) {
+ memset(m_DataLogBuf, 0, LOG_BUFFER_SIZE);
+ ssize_t read_len = fread(m_DataLogBuf, sizeof(char), LOG_BUFFER_SIZE, fp);
+ if (-1 == read_len) {
+ SOCK_LOGE("Failed to read data from file, errno=%d", errno);
+ fclose(fp);
+ return false;
+ } else if (read_len > 0) {
+ mnld_sendLogDataToPC(m_DataLogBuf, read_len);
+ SOCK_LOGE("send logdata, len = %ld", read_len);
+ } else {
+ SOCK_LOGE("read data from file, size = 0 .errno=%d", errno);
+ }
+ } else {
+ pull_stop_flag = 0;
+ break;
+ }
+ }
+ fclose(fp);
+ } else {
+ SOCK_LOGE("Failed to open file %s, errno=%d", full_path, errno);
+ return false;
+ }
+ return true;
+}
+
+signed int mnld2pc_wifi_createSocket()
+{
+ // int ret = -1;
+ int sock_opt = 1;
+ int enable = 1;
+ if (m_nSockFd != -1) {
+ SOCK_LOGE("connsyslogger Wifi Socket already created.");
+ return m_nSockFd;
+ }
+ //Create socket
+ if((m_nSockFd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ SOCK_LOGE("connsyslogger Wifi Socket created fail. errno=%d", errno);
+ return -1;
+ }
+
+ SOCK_LOGD("connsyslogger Wifi Socket created success m_nSockFd:%d",m_nSockFd);
+
+ // SET SOCKET REUSE Address
+ if(setsockopt(m_nSockFd, SOL_SOCKET, SO_REUSEADDR, (void*)&sock_opt, sizeof(sock_opt)) < 0)
+ {
+ SOCK_LOGE("connsyslogger Wifi Socket setsockopt failed. errno=%d", errno);
+ close(m_nSockFd);
+ return -1;
+ }
+
+ //SET TCP_NODELAY
+ if(setsockopt(m_nSockFd, IPPROTO_TCP, TCP_NODELAY, (void*)&enable, sizeof(enable)) < 0)
+ {
+ SOCK_LOGE("connsyslogger Wifi Socket setsockopt TCP_NODELAY failed. errno=%d", errno);
+ }
+ //Prepare the sockaddr_in structure
+ struct sockaddr_in serverAddr;
+
+ memset(&serverAddr, 0, sizeof(serverAddr));
+
+ serverAddr.sin_family = AF_INET;
+ serverAddr.sin_port = htons(WIFI_SOCKET_PORT);
+ char strIpAddr[128] = {0};
+ property_get(PROP_WIFI_ADDR,strIpAddr,"0.0.0.0");
+ SOCK_LOGD("connsyslogger Wifi Socket IP Addr:%s", strIpAddr);
+ serverAddr.sin_addr.s_addr = inet_addr(strIpAddr);
+ bzero(&(serverAddr.sin_zero),8);
+ //Bind
+ if(bind(m_nSockFd,(struct sockaddr*)&serverAddr, sizeof(struct sockaddr)) < 0)
+ {
+ SOCK_LOGE("connsyslogger Wifi Socket bind failed. errno=%d", errno);
+ goto errout;
+ }
+ SOCK_LOGD("connsyslogger Wifi Socket bind done");
+
+ //Listen
+ if (listen(m_nSockFd, BACKLOG) == -1)
+ {
+ SOCK_LOGE("connsyslogger Wifi Socket Failed to listen Socket port, errno=%d", errno);
+ goto errout;
+ }
+ SOCK_LOGD("connsyslogger Wifi Socket listen done");
+ return m_nSockFd;
+
+errout:
+ close(m_nSockFd);
+ m_nSockFd = -1;
+ return -1;
+}
+
+void mnld2pc_wifi_disconnect() {
+ if (m_nConnect) {
+ if (m_nClientFd != -1) {
+ m_nConnect = false;
+ close(m_nClientFd);
+ m_nClientFd = -1;
+ SOCK_LOGD("connsyslogger wifi Socket disconnect client");
+ }
+ } else{
+ SOCK_LOGD("connsyslogger wifi Socket already disconnect client");
+ }
+}
+
+int mnld2pc_connect_wifi() {
+ if (-1 == m_nSockFd) {
+ SOCK_LOGE("connsyslogger wifi Socket server not create");
+ return -1;
+ }
+
+ if (m_nConnect) {
+ SOCK_LOGD("connsyslogger wifi Socket already conencted");
+ return 0;
+ }
+
+ struct sockaddr_in clientAddr;
+ memset(&clientAddr, 0, sizeof(clientAddr));
+
+ socklen_t alen = sizeof(struct sockaddr);
+
+ while(1) {
+ SOCK_LOGD("connsyslogger wifi Socket connect, accept the connection........");
+ if ((m_nClientFd = accept(m_nSockFd, (struct sockaddr*)&clientAddr, &alen)) == -1)
+ {
+ SOCK_LOGE("connsyslogger Socket accept error, errno=%d,m_nSockFd = %d", errno,m_nSockFd);
+
+ if(errno == EAGAIN)
+ {
+ usleep(200*1000);
+ continue;
+ }
+ m_nConnect = false;
+ return -1;
+ }
+ else
+ {
+ m_nConnect = true;
+ SOCK_LOGD("connsyslogger Socket connect, Received a connection from %s, m_nClientFd = %d",
+ (char*)inet_ntoa(clientAddr.sin_addr), m_nClientFd);
+ return 0;
+ }
+ }
+}
+
+void mnld2pc_wifi_socketClose() {
+ mnld2pc_wifi_disconnect();
+ if (m_nSockFd != -1)
+ {
+ close(m_nSockFd);
+ m_nSockFd = -1;
+ }
+}
+
+void mnld2pc_wifi_WaitConnect() {
+ if (m_nConnect) {
+ SOCK_LOGE("connsyslogger WaitConnect, already connected");
+ return;
+ }
+ fd_set rfds;
+ while (1) {
+ FD_ZERO(&rfds);
+ if(m_nSockFd > 0) {
+ FD_SET(m_nSockFd, &rfds);
+ }
+ int maxfd = 0;
+ int rc = 0;
+ maxfd = m_nSockFd+1;
+ if((rc = select(maxfd, &rfds, NULL, NULL, NULL)) < 0) {
+ SOCK_LOGE("WaitConnect select failed (%s), errno = %d", strerror(errno), errno);
+ sleep(1);
+ continue;
+ }
+ if(FD_ISSET(m_nSockFd, &rfds)) {
+ SOCK_LOGD("begin to accept client connection socketFd=%d", m_nSockFd);
+ if (-1 == mnld2pc_connect_wifi()) {
+ SOCK_LOGD("accept client connection failed.");
+ sleep(1);
+ continue;
+ }
+ SOCK_LOGD("accept client connection done.");
+ break;
+ }
+ }
+ return ;
+}
+bool mnld2pc_log_sendSourceFile(char* folder_path,ATM_ONLINE_MODE mode){
+ if (mode == ATM_WIFI_MODE) {
+ mnld2pc_wifi_WaitConnect();
+ }
+ SOCK_LOGD("sendSourceFile log folder: %s", folder_path);
+ DIR* dp = NULL;
+ transfer_mode = mode;
+ struct dirent* dirp = NULL;
+ dp = opendir(folder_path);
+ if (dp == NULL) {
+ SOCK_LOGE("can not open log folder: %s", folder_path);
+ if (mode == 0) {
+ mnld2pc_wifi_socketClose();
+ }
+ return false;
+ }
+ while ((dirp = readdir(dp)) != NULL) {
+ if ((strstr(dirp->d_name,".nma") != NULL) || (strstr(dirp->d_name,".nma.curf") != NULL)) {
+ MNLD_STRNCPY(m_logFilelist.file_head[m_logFilelist.file_num].file_name, dirp->d_name, sizeof(m_logFilelist.file_head[m_logFilelist.file_num].file_name));
+ m_logFilelist.file_num++;
+ }
+ }
+ closedir(dp);
+ ///////begin transfer files
+ if (mode == ATM_USB_MODE){
+ mnld2pc_log_openUSBPort();
+ log_port = usb_port_fd;
+ }else {
+ mnld2pc_wifi_WaitConnect();
+ log_port = m_nClientFd;
+ }
+#ifdef META_LOG_CTRL_TEST
+ fd_test = open(testlogpath, O_RDWR| O_CREAT | O_NOCTTY, 0755);
+ if (fd_test == -1) {
+ SOCK_LOGE("open /data/vender/log/testlog fail, errorno is %d ,%s", errno, strerror(errno));
+ }
+#endif
+ SOCK_LOGD("mode = %d,log_port = %d,total files be pulled is : %u", mode,log_port,m_logFilelist.file_num);
+
+ memset(pre_fix,0,16);
+ MNLD_STRNCPY(pre_fix, "GPSlog_start", sizeof(pre_fix));
+ pre_fix[sizeof(pre_fix) - 1] = '\0';
+ file_count = m_logFilelist.file_num;
+
+ /////send prefix
+ mnld_sendLogDataToPC(pre_fix,sizeof(pre_fix));
+ SOCK_LOGE("prefix %s", pre_fix);
+ mnld_sendLogDataToPC((char*)&file_count,sizeof(file_count));
+ SOCK_LOGE("file_count %d", file_count);
+ for (int i = 0; i < m_logFilelist.file_num; i++) {
+ mnld_TransferFile(folder_path,m_logFilelist.file_head[i].file_name);
+ }
+ memset(post_fix,0,16);
+ MNLD_STRNCPY(post_fix, "GPSlog_end", sizeof(post_fix));
+ post_fix[sizeof(post_fix) - 1] = '\0';
+ SOCK_LOGE("post_fix %s", post_fix);
+ mnld_sendLogDataToPC(post_fix,sizeof(post_fix));
+ if (mode == ATM_USB_MODE)
+ mnld2pc_log_closeUSBPort();
+ else
+ mnld2pc_wifi_socketClose(); // close cocket
+ //////end transfer
+ return true;
+}
+
+
+void mnld2meta_reply_result(char* cmd, char result) {
+ char reply[META2MNLD_LOGCTRL_INTERFACE_BUFF_SIZE] = {0};
+
+ sprintf(reply, "%s,%d", cmd, result);
+ SOCK_LOGD("mnld2meta_reply, str=%s, len=%lu", reply, strlen(reply));
+ write(clientConnect, reply, strlen(reply));
+}
+
+static void meta_logctrl_start_log() {
+ meta_logctrl = META_LOGCTRL_ENGBLE;
+ gps_dbg_log_mode_set(MNLD_WRITE_LOG_TOFILE);
+ MNLD_STRNCPY(gps_debuglog_file_name, GPS_DBGLOG_FILE_NAME ,GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ MNLD_STRNCPY(storagePath, GPS_DBGLOG_PATH ,GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ MNLD_STRNCPY(storagePath_mtklogger_set, GPS_DBGLOG_PATH ,GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ SOCK_LOGD("Meta enable GPS debug log\n");
+ gps_dbg_log_state_set_output_enable();
+ mnld2meta_reply_result(GPSLOG_START, 1);
+}
+static void meta_logctrl_stop_log() {
+ meta_logctrl = META_LOGCTRL_DISABLE;
+ gps_dbg_log_output2file_clean();
+ SOCK_LOGD("Meta disable GPS debug log\n");
+ gps_dbg_log_state_set_output_disable();
+ mnld2meta_reply_result(GPSLOG_STOP, 1);
+}
+static void meta_logctrl_pull_log_start() {
+ if (mnld_checkConnectType() == ATM_WIFI_MODE) {
+ if(mnld2pc_wifi_createSocket() == -1) {
+ SOCK_LOGE("mnld2pc_wifi_createSocket fail");
+ }
+ if(mnld2pc_log_sendSourceFile(storagePath, ATM_WIFI_MODE) == false) {
+ SOCK_LOGE("ATM_WIFI_MODE, mnld2pc_log_sendSourceFile fail");
+ }
+ } else {
+ if(mnld2pc_log_sendSourceFile(storagePath, ATM_USB_MODE) == false) {
+ SOCK_LOGE("ATM_USB_MODE, mnld2pc_log_sendSourceFile fail");
+ }
+ }
+ mnld2meta_reply_result(GPSLOG_PULL_START, 1);
+}
+static void meta_logctrl_pull_log_stop() {
+ //pull_stop_flag = 1;
+ mnld2meta_reply_result(GPSLOG_PULL_STOP, 1);
+}
+
+static Meta2MnldLogctrlInterface_callbacks g_meta2mnl_logctrl_callbacks = {
+ meta_logctrl_start_log,
+ meta_logctrl_stop_log,
+ meta_logctrl_pull_log_start,
+ meta_logctrl_pull_log_stop,
+};
+int Meta2Mnld_logctrl_hdlr(int fd, Meta2MnldLogctrlInterface_callbacks* hdlr)
+{
+ char buff[META2MNLD_LOGCTRL_INTERFACE_BUFF_SIZE] = {0};
+ int read_len;
+ int ret = 0;
+
+ read_len = read(fd, buff, sizeof(buff)-1);
+ if (read_len <= 0) {
+ usleep(1000);
+ SOCK_LOGE("Meta2Mnld_logctrl_hdlr() read_len<=0,read_len = %d\n", read_len);
+ ret = -1;
+ }
+
+ if (!strcmp(buff, GPSLOG_START)) {
+ if (hdlr->Meta2MnldInterface_start_log_handler) {
+ SOCK_LOGE("Meta2Mnld_logctrl_hdlr() GPSLOG_START");
+ hdlr->Meta2MnldInterface_start_log_handler();
+ } else {
+ SOCK_LOGE("Meta2Mnld_logctrl_hdlr() GPSLOG_START is NULL");
+ ret = -1;
+ }
+ } else if (!strcmp(buff, GPSLOG_STOP)) {
+ if (hdlr->Meta2MnldInterface_stop_log_handler) {
+ SOCK_LOGE("Meta2Mnld_logctrl_hdlr() GPSLOG_STOP");
+ hdlr->Meta2MnldInterface_stop_log_handler();
+ } else {
+ SOCK_LOGE("Meta2Mnld_logctrl_hdlr() GPSLOG_STOP is NULL");
+ ret = -1;
+ }
+ } else if (!strcmp(buff, GPSLOG_PULL_START)) {
+ if (hdlr->Meta2MnldInterface_pull_log_start_handler) {
+ SOCK_LOGE("Meta2Mnld_logctrl_hdlr() GPSLOG_PULL_START");
+ hdlr->Meta2MnldInterface_pull_log_start_handler();
+ } else {
+ SOCK_LOGE("Meta2Mnld_logctrl_hdlr() GPSLOG_PULL_START is NULL");
+ ret = -1;
+ }
+ } else if (!strcmp(buff, GPSLOG_PULL_STOP)) {
+ if (hdlr->Meta2MnldInterface_pull_log_stop_handler) {
+ SOCK_LOGE("Meta2Mnld_logctrl_hdlr() GPSLOG_PULL_STOP");
+ hdlr->Meta2MnldInterface_pull_log_stop_handler();
+ } else {
+ SOCK_LOGE("Meta2Mnld_logctrl_hdlr() GPSLOG_PULL_STOP is NULL");
+ ret = -1;
+ }
+ } else {
+ SOCK_LOGE("Meta2Mnld_logctrl_hdlr() unknown cmd=%s", buff);
+ }
+
+ return ret;
+
+}
+
+void *mtk_tcp_listener() {
+ #define MAX_EPOLL_EVENT 50
+ int maxFd = 0;
+ int ret = 0;
+ struct epoll_event events[MAX_EPOLL_EVENT];
+
+ int epfd = epoll_create(MAX_EPOLL_EVENT);
+ if (epfd == -1) {
+ SOCK_LOGE("mtk_tcp_listener() epoll_create failure reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ if (epoll_add_fd(epfd, mSockListenId) == -1) {
+ SOCK_LOGE("mtk_tcp_listener() epoll_add_fd() failed for fd_agps failed");
+ }
+ while (1) {
+ int n = 0;
+ int i = 0;
+ n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+ if (n > 1) {
+ SOCK_LOGD("n=%d\n", n);
+ } else if (n == -1) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ SOCK_LOGE("mtk_tcp_listener() epoll_wait failure reason=[%s]%d",
+ strerror(errno), errno);
+ continue;
+ }
+ }
+ for (i = 0; i < n; i++) {
+ if (events[i].data.fd == mSockListenId) {
+ // deal with new connection
+ if (events[i].events & EPOLLIN) {
+ struct sockaddr addr;
+ socklen_t alen = sizeof(addr);
+ int connectfd = -1;
+ if ((connectfd = accept(mSockListenId, &addr, &alen)) < 0) {
+ SOCK_LOGE("accept failed (%s) , errno = %d", strerror(errno), errno);
+ sleep(1);
+ continue;
+ }
+
+ SOCK_LOGD("consyslgger accept connection done connectfd=%d",connectfd);
+
+ if (connectfd != clientConnect) {
+ if(clientConnect > 0) {
+ epoll_del_fd(epfd, clientConnect);
+ close(clientConnect);
+ }
+ clientConnect = connectfd;
+
+ if (clientConnect > 0) {
+ if (epoll_add_fd(epfd, clientConnect) == -1) {
+ SOCK_LOGE("mtk_tcp_listener() epoll_add_fd() failed for fd_agps failed");
+ continue;
+ }
+ }
+ }
+ }
+ } else if (events[i].data.fd == clientConnect) {
+ // socket channel command
+ if (events[i].events & EPOLLIN) {
+ if (Meta2Mnld_logctrl_hdlr(clientConnect, &g_meta2mnl_logctrl_callbacks) == -1) {
+ epoll_del_fd(epfd, clientConnect);
+ close(clientConnect);
+ clientConnect = -1;
+ continue;
+ }
+ continue;
+ }
+ } else {
+ LOGE("mnld_main_thread() unknown fd=%d",
+ events[i].data.fd);
+ }
+ }
+ }
+
+ return 0;
+}
+
+int mtk_socket_tcp_startListening(const char* path, mtk_socket_namespace sock_namespace) {
+ int ret;
+ pthread_t pthread_tcp_listener;
+ UNUSED(sock_namespace);
+ do {
+ mSockListenId = socket_local_server(path,
+ SOCK_STREAM);
+
+ if (mSockListenId < 0) {
+ SOCK_LOGE("mSockListenId<0 ,errno=%d",errno);
+ break;
+ }
+ SOCK_LOGE("mSockListenId ok\n");
+
+ ret = listen(mSockListenId, 4);
+ if (ret < 0) {
+ SOCK_LOGE("listen error.errno=%d",errno);
+ break;
+ }
+ pthread_create(&pthread_tcp_listener, NULL, mtk_tcp_listener, NULL);
+ SOCK_LOGD("Success to setup socket local server");
+ return 1;
+ } while (0);
+ SOCK_LOGD("Fail to setup socket local server, exit");
+ if (mSockListenId > 0) {
+ shutdown(mSockListenId, 2);
+ close(mSockListenId);
+ mSockListenId = -1;
+ }
+ return 0;
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_nlp_interface/inc/Mnld2NlpUtilsInterface.h b/src/connectivity/gps/2.0/mtk_mnld/mnl_nlp_interface/inc/Mnld2NlpUtilsInterface.h
new file mode 100644
index 0000000..ea048ef
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_nlp_interface/inc/Mnld2NlpUtilsInterface.h
@@ -0,0 +1,43 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __Mnld2NlpUtilsInterface_H__
+#define __Mnld2NlpUtilsInterface_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MNLD2NLP_UTILS_INTERFACE_PROTOCOL_TYPE 302
+#define MNLD2NLP_UTILS_INTERFACE_BUFF_SIZE 12
+
+/**
+ * The interface from Mnld to NlpUtils
+ */
+typedef enum {
+ MNLD2NLP_UTILS_INTERFACE_REQ_NLP_LOCATION = 0,
+ MNLD2NLP_UTILS_INTERFACE_CANCEL_NLP_LOCATION = 1,
+} Mnld2NlpUtilsInterface_message_id;
+
+
+
+// Sender
+bool Mnld2NlpUtilsInterface_reqNlpLocation(mtk_socket_fd* client_fd, int source);
+
+bool Mnld2NlpUtilsInterface_cancelNlpLocation(mtk_socket_fd* client_fd, int source);
+
+// Receiver
+typedef struct {
+ void (*Mnld2NlpUtilsInterface_reqNlpLocation_handler) (int source);
+ void (*Mnld2NlpUtilsInterface_cancelNlpLocation_handler) (int source);
+} Mnld2NlpUtilsInterface_callbacks;
+
+bool Mnld2NlpUtilsInterface_receiver_decode(char* _buff, Mnld2NlpUtilsInterface_callbacks* callbacks);
+bool Mnld2NlpUtilsInterface_receiver_read_and_decode(int server_fd, Mnld2NlpUtilsInterface_callbacks* callbacks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnl_nlp_interface/src/Mnld2NlpUtilsInterface.c b/src/connectivity/gps/2.0/mtk_mnld/mnl_nlp_interface/src/Mnld2NlpUtilsInterface.c
new file mode 100644
index 0000000..f37b037
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnl_nlp_interface/src/Mnld2NlpUtilsInterface.c
@@ -0,0 +1,112 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "Mnld2NlpUtilsInterface.h"
+#include "mtk_socket_data_coder.h"
+
+// Sender
+bool Mnld2NlpUtilsInterface_reqNlpLocation(mtk_socket_fd* client_fd, int source) {
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("Mnld2NlpUtilsInterface_reqNlpLocation() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ char _buff[MNLD2NLP_UTILS_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, MNLD2NLP_UTILS_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, MNLD2NLP_UTILS_INTERFACE_REQ_NLP_LOCATION);
+ mtk_socket_put_int(_buff, &_offset, source);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("Mnld2NlpUtilsInterface_reqNlpLocation() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+bool Mnld2NlpUtilsInterface_cancelNlpLocation(mtk_socket_fd* client_fd, int source) {
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("Mnld2NlpUtilsInterface_cancelNlpLocation() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ char _buff[MNLD2NLP_UTILS_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ mtk_socket_put_int(_buff, &_offset, MNLD2NLP_UTILS_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, MNLD2NLP_UTILS_INTERFACE_CANCEL_NLP_LOCATION);
+ mtk_socket_put_int(_buff, &_offset, source);
+ _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+ if(_ret == -1) {
+ SOCK_LOGE("Mnld2NlpUtilsInterface_cancelNlpLocation() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+// Receiver
+bool Mnld2NlpUtilsInterface_receiver_decode(char* _buff, Mnld2NlpUtilsInterface_callbacks* callbacks) {
+ int _ret = 0;
+ int _offset = 0;
+ _ret = mtk_socket_get_int(_buff, &_offset);
+ if(_ret != MNLD2NLP_UTILS_INTERFACE_PROTOCOL_TYPE) {
+ SOCK_LOGE("Mnld2NlpUtilsInterface_receiver_decode() protocol_type=[%d] is not equals to [%d]",
+ _ret, MNLD2NLP_UTILS_INTERFACE_PROTOCOL_TYPE);
+ return false;
+ }
+ _ret = mtk_socket_get_int(_buff, &_offset);
+ switch(_ret) {
+ case MNLD2NLP_UTILS_INTERFACE_REQ_NLP_LOCATION: {
+ if(callbacks->Mnld2NlpUtilsInterface_reqNlpLocation_handler == NULL) {
+ SOCK_LOGE("Mnld2NlpUtilsInterface_receiver_decode() Mnld2NlpUtilsInterface_reqNlpLocation_handler() is NULL");
+ return false;
+ }
+ int source = mtk_socket_get_int(_buff, &_offset);
+ callbacks->Mnld2NlpUtilsInterface_reqNlpLocation_handler(source);
+ break;
+ }
+ case MNLD2NLP_UTILS_INTERFACE_CANCEL_NLP_LOCATION: {
+ if(callbacks->Mnld2NlpUtilsInterface_cancelNlpLocation_handler == NULL) {
+ SOCK_LOGE("Mnld2NlpUtilsInterface_receiver_decode() Mnld2NlpUtilsInterface_cancelNlpLocation_handler() is NULL");
+ return false;
+ }
+ int source = mtk_socket_get_int(_buff, &_offset);
+ callbacks->Mnld2NlpUtilsInterface_cancelNlpLocation_handler(source);
+ break;
+ }
+ default: {
+ SOCK_LOGE("Mnld2NlpUtilsInterface_receiver_decode() unknown msgId=[%d]", _ret);
+ return false;
+ }
+ }
+ return true;
+}
+bool Mnld2NlpUtilsInterface_receiver_read_and_decode(int server_fd, Mnld2NlpUtilsInterface_callbacks* callbacks) {
+ int _ret;
+ char _buff[MNLD2NLP_UTILS_INTERFACE_BUFF_SIZE] = {0};
+
+ _ret = mtk_socket_read(server_fd, _buff, sizeof(_buff));
+ if(_ret == -1) {
+ SOCK_LOGE("Mnld2NlpUtilsInterface_receiver_read_and_decode() mtk_socket_read() failed, fd=%d err=[%s]%d",
+ server_fd, strerror(errno), errno);
+ return false;
+ }
+ return Mnld2NlpUtilsInterface_receiver_decode(_buff, callbacks);
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld.service b/src/connectivity/gps/2.0/mtk_mnld/mnld.service
new file mode 100644
index 0000000..43a1b3d
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=MNL Daemon
+
+[Service]
+ExecStart=/usr/bin/mnld
+Restart=always
+#StandardOutput=kmsg+console
+
+[Install]
+WantedBy=basic.target
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/adc_capture.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/adc_capture.h
new file mode 100644
index 0000000..8663326
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/adc_capture.h
@@ -0,0 +1,29 @@
+#ifndef __MNL_FLP_TEST_INTERFACE_H__
+#define __MNL_FLP_TEST_INTERFACE_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define IOCTL_EMI_MEMORY_INIT 1
+#define IOCTL_MNL_NVRAM_FILE_TO_MEM 2
+#define IOCTL_MNL_NVRAM_MEM_TO_FILE 3
+#define IOCTL_ADC_CAPTURE_ADDR_GET 4
+#define ADC_CAPTURE_BUFF_SIZE 0x50000
+
+//======================================================
+// GPS FLP test -> MNLD
+//======================================================
+void mnld_gps_emi_init(int type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/epo.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/epo.h
new file mode 100644
index 0000000..fcd85e8
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/epo.h
@@ -0,0 +1,64 @@
+#ifndef __EPO_H__
+#define __EPO_H__
+
+#include "curl.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EPO_PATH MTK_GPS_DATA_PATH
+#define EPO_FILE MTK_GPS_DATA_PATH"EPO.DAT"
+#define EPO_UPDATE_FILE MTK_GPS_DATA_PATH"EPOTMP.DAT"
+#define EPO_UPDATE_HAL MTK_GPS_DATA_PATH"EPOHAL.DAT"
+#define MTK_EPO_ONE_SV_SIZE 72
+#define SECONDS_PER_HOUR (60*60)
+#define EPO_DL_MAX_RETRY_TIME 3 //The max retry time of curl_easy_download fail
+#define EPO_INVALIDE_DL_MAX_RETRY_TIME 3 //The max retry time of whole download process
+#define EPO_INVALIDE_DL_RETRY_SLEEP (100*1000) //100 ms
+#define MAX_EPO_PIECE 10
+#define EPO_MERGE_FULL_FILE -1
+#define EPO_MD5_AVAILABLE_BIT (1<<0)
+#define EPO_DAT_AVAILABLE_BIT (1<<1)
+#define EPO_FILE_NAME_MAX_SIZE 60
+#define EPO_MD5_FILE_MAX_SIZE 50
+#define GPS_EPO_FILE_LEN MTK_GPS_EPO_FILE_NAME_LEN
+#define GPS_EPO_URL_LEN 256
+
+#define EPO_URL_HOME_C "https://qepodownload.mediatek.com/"
+#define EPO_URL_HOME_G "https://qgepodownload.mediatek.com/"
+
+typedef struct EPO_Status {
+ unsigned int EPO_piece_flag[MAX_EPO_PIECE];
+ int last_DL_Date;
+ int today_retry_time;
+} EPO_Status_T;
+
+#define mnld_curl_easy_setopt(handle, opt, param) do { \
+ if(curl_easy_setopt(handle, opt, param) != CURLE_OK) { \
+ LOGE("FUNC[%s], Line[%d], curl_easy_setopt fail, %s(%d)", __func__, __LINE__, strerror(errno), errno); \
+ } \
+ } while(0)
+
+int epo_downloader_init();
+int epo_read_cust_config();
+int epo_downloader_is_file_invalid();
+int epo_downloader_start();
+void epo_update_epo_file();
+int epo_is_wifi_trigger_enabled();
+int epo_is_epo_download_enabled();
+CURLcode curl_easy_download(char* url, char* filename);
+int mtk_gps_sys_epo_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond);
+int mtk_gps_sys_epo_bd_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond);
+int mtk_gps_sys_epo_ga_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond);
+void GpsToUtcTime(int i2Wn, double dfTow, time_t* uSecond);
+void getEpoUrl(const char * filename, char * url);
+void epo_write_cfg(char* key, char* val);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/gps_controller.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/gps_controller.h
new file mode 100644
index 0000000..0d44a5f
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/gps_controller.h
@@ -0,0 +1,81 @@
+#ifndef __GPS_CONTROLER_H__
+#define __GPS_CONTROLER_H__
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MNLD_VERSION "MTK_MNLD_6_0_0_20040301"
+#define GNSS_NAME_LEN (255)
+
+#define MNL_CFG_XML_DEFAULT_PATH MTK_GPS_DATA_DEFAULT_PATH
+#define MNL_READ_WRITE_PATH MTK_GPS_DATA_PATH
+#define MNLD_MGPSID MGPSID
+#define MNLD_MQZSSID 7
+#define MNLD_MGLONID 24
+#define MNLD_MBD2ID 63
+#define MNLD_MGLEOID 36
+#define MNLD_SBAS_BUN_PRN 19
+#define MNLD_MNAVICID 14
+
+
+int gps_control_init();
+
+int gps_control_gps_start(int delete_aiding_data_flags);
+int gps_control_gps_stop();
+int gps_control_gps_reset(int delete_aiding_data_flags);
+#if defined(GPS_SUSPEND_SUPPORT)
+int gps_control_gps_suspend();
+int gps_control_gps_suspend_to_close();
+int gps_control_gps_suspend_to_close_by_rst();
+#endif
+
+void gps_control_kernel_wakelock_init();
+void gps_control_kernel_wakelock_take();
+void gps_control_kernel_wakelock_give();
+void gps_control_kernel_wakelock_uninit();
+
+int mnld_adc_capture_is_enabled(void);
+#if defined(GPS_SUSPEND_SUPPORT)
+void mnld_gps_suspend_check_capability(void);
+bool mnld_gps_suspend_is_enabled();
+int mnld_gps_suspend_get_timeout_sec();
+bool mnld_gps_suspend_ext_is_enabled();
+bool mnld_gps_suspend_ext_is_available();
+int mnld_gps_suspend_ext_get_timeout_sec();
+void mtk_gps_suspend_extention_available_set(INT32 available);
+int mnld_gps_suspend_done(void);
+#endif
+int mnl_init(void);
+void linux_signal_handler(int signo);
+int mnld_factory_test_entry(int argc, char** argv);
+int linux_setup_signal_handler(void);
+
+void gps_controller_rcv_pmtk(const char* pmtk);
+
+void get_chip_sv_support_capability(unsigned char* sv_type);
+
+#if ANDROID_MNLD_PROP_SUPPORT
+int get_gps_cmcc_log_enabled();
+#endif
+
+void get_chip_gnss_op_mode(void);
+
+bool mnld_timeout_ne_enabled(void);
+void mnld_gps_update_name(void);
+
+bool mnld_nfw_ctrl_nlp_enabled();
+bool mnld_nfw_ctrl_gnss_enabled();
+
+bool mtk_gps_support_l5_get();
+void mtk_gps_support_l5_set(bool support_l5);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/gps_dbg_log.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/gps_dbg_log.h
new file mode 100644
index 0000000..b45bd14
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/gps_dbg_log.h
@@ -0,0 +1,151 @@
+#ifndef __GPS_DBG_LOG_H__
+#define __GPS_DBG_LOG_H__
+
+#include "mtk_gps_type.h"
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MAX
+#define MAX(A,B) ((A)>(B)?(A):(B))
+#endif
+#ifndef MIN
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#endif
+
+#define LOG_FILE MTK_GPS_DATA_PATH"gpsdebug.log"
+#define LOG_FILE_PATH MTK_GPS_DATA_PATH
+#define PATH_SUFFIX "debuglogger/connsyslog/gpshost/"
+#define LOG_FILE_EXTEN_NAME ".nma"
+#define LOG_FILE_WRITING_EXTEN_NAME ".nma.curf"
+#define GPS_LOG_PERSIST_STATE "vendor.gpsdbglog.enable"
+#define GPS_LOG_PERSIST_PATH "vendor.gpsdbglog.path"
+#define GPS_LOG_PERSIST_FLNM "vendor.gpsdbglog.file"
+
+#define GPS_LOG_PERSIST_VALUE_ENABLE "1"
+#define GPS_LOG_PERSIST_VALUE_DISABLE "0"
+#define GPS_LOG_PERSIST_VALUE_NONE "none"
+
+#define GPS_DBG_LOG_FILE_NUM_LIMIT 1000
+#define MAX_DBG_LOG_FILE_SIZE MIN(48*1024*1024,(g_dbglog_file_size_in_config<1024*1024?25*1024*1024:g_dbglog_file_size_in_config))
+#define MAX_DBG_LOG_DIR_SIZE MIN(512*1024*1024,MAX(g_dbglog_folder_size_in_config,MAX_DBG_LOG_FILE_SIZE*12))
+
+#define MNLD2MTKLOGGER_ANS_BUFF_SIZE 256
+#define MTKLOGGER2MNLD_READ_BUFF_SIZE 253
+
+#define MNLD_WRITE_LOG_TOFILE 0x01
+#define MNLD_WRITE_LOG_SOCKET 0x02
+#define META_LOGCTRL_ENGBLE 0x01
+#define META_LOGCTRL_DISABLE 0x00
+
+#define GPS_DBGLOG_PATH "/etc/gnss/"
+#define GPS_DBGLOG_FILE_NAME_SUFFIX "gpsdebug.log"
+#define GPS_DBGLOG_FILE_NAME "/etc/gnss/gpsdebug.log"
+
+enum {
+ MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNL = 0x00,
+ MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNL = 0x01,
+ MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD = 0x10,
+ MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD = 0x11,
+ MTK_GPS_ENCRYPT_DEBUG_MSG_BY_MNL = 0x20, //Valid only when MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD set
+};
+// Note: the bellow gps_dbg_log_state* APIs are defined for two purpose:
+// 1. Use mutex to protect set/clear bitmask operations of gps_debuglog_state
+// (note: currently read gps_debuglog_state is thread-safe)
+//
+// 2. The MTK_GPS_*_BY_MNL* definition has legacy and confusing meaning,
+// so we wrapper it in the APIs for easy usage
+//
+// So, it's not recommand to direclty manipuate gps_debuglog_state in new code
+void gps_dbg_log_state_init();
+void gps_dbg_log_state_set_bitmask(unsigned int bitmask);
+void gps_dbg_log_state_set_output_enable();
+void gps_dbg_log_state_set_output_disable();
+
+// Note: currently the bit 0x10 in gps_debuglog_state is always true,
+// then "!is_output_enabled" should equal "is_output_disabled".
+// However, we keep the two different APIs for "0x10 not true"(legacy) case for compablity.
+bool gps_dbg_log_state_is_output_enabled(); //Just use it for new code
+bool gps_dbg_log_state_is_output_disabled(); //For legacy, not recommnad for new
+
+void gps_dbg_log_state_set_encrypt_enable();
+void gps_dbg_log_state_set_encrypt_disable();
+bool gps_dbg_log_state_is_encrypt_enabled();
+bool mnld2logd_open_gpslog(char* file);
+bool mnld2logd_write_gpslog(char * data, int len);
+bool mnld2logd_close_gpslog(void);
+
+bool mnld2logd_open_mpelog(char* file);
+bool mnld2logd_write_mpelog(char * data, int len);
+bool mnld2logd_close_mpelog(void);
+
+bool mnld2logd_open_dumplog(char* file);
+bool mnld2logd_write_dumplog(char * data, int len);
+bool mnld2logd_close_dumplog(void);
+// Task synchronization related type
+typedef enum{
+ MNLD_MUTEX_PINGPANG_WRITE = 0,
+ MNLD_MUTEX_GPS_DBG_LOG_STATE = 1,
+ MNLD_MUTEX_MAX
+} mnld_mutex_enum;
+
+int gps_dbg_log_thread_init();
+
+int create_mtklogger2mnl_fd();
+
+int mtklogger2mnl_hdlr(int fd, mtk_socket_fd* client_fd);
+
+INT32 gps_log_dir_check(char * dirname);
+
+void gps_stop_dbglog_release_condition(void);
+
+#ifdef MTK_MPE_SUPPORT
+void mtklogger_mped_reboot_message_update(void);
+#endif
+//Rename gpsdebug name, .nmac to .nma
+void gps_log_file_rename(char *filename_cur);
+
+void gps_dbg_log_property_load(void);
+
+void gps_dbg_log_exit_flush(int force_exit) ;
+
+void gps_dbg_log_mode_set(unsigned int bitmap);
+
+bool gps_dbg_log_output2file();
+
+bool gps_dbg_log_output2socket();
+
+void gps_dbg_log_output2file_clean();
+
+void gps_dbg_log_output2socket_clean();
+
+typedef enum
+{
+ LV_DEBUG,
+ LV_VERBOSE,
+ LV_INFO,
+ LV_WARN,
+ LV_ERROR,
+}
+mnld_log_level_t;
+
+extern void mnld_log_printx(mnld_log_level_t log_lv, int skip_chars, char *fmt, ...);
+
+//#define LOGD(fmt, arg ...) ALOGD("%s: " fmt, __FUNCTION__ , ##arg)
+// Put XXLOGX as the leading mark so that our decryptor can find it easily, skip the 1st X char
+#define LOGDX(fmt, arg ...) mnld_log_printx(LV_DEBUG, 1, "XXLOGX %s: " fmt, __FUNCTION__ , ##arg)
+#define LOGVX(fmt, arg ...) mnld_log_printx(LV_VERBOSE, 1, "XXLOGX %s: " fmt, __FUNCTION__ , ##arg)
+#define LOGIX(fmt, arg ...) mnld_log_printx(LV_INFO, 1, "XXLOGX %s: " fmt, __FUNCTION__ , ##arg)
+#define LOGWX(fmt, arg ...) mnld_log_printx(LV_WARN, 1, "XXLOGX %s: " fmt, __FUNCTION__ , ##arg)
+#define LOGEX(fmt, arg ...) mnld_log_printx(LV_ERROR, 1, "XXLOGX %s: " fmt, __FUNCTION__ , ##arg)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/hal_mnl_interface_common.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/hal_mnl_interface_common.h
new file mode 100644
index 0000000..dcc636d
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/hal_mnl_interface_common.h
@@ -0,0 +1,1783 @@
+#ifndef __HAL_MNL_INTERFACE_COMMON_H__
+#define __HAL_MNL_INTERFACE_COMMON_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define HAL_MNL_BUFF_SIZE (10 * 1000)
+#define HAL_MNL_BUFF_SIZE_SND (32 * 1000)
+#define HAL_MNL_INTERFACE_VERSION 1
+
+//======================================================
+// GPS HAL -> MNLD
+//======================================================
+#define MTK_HAL2MNL "mtk_hal2mnl"
+
+#define MTK_HAL2MNL_BASIC_SERVER "mnldinf_basic"
+#define MTK_HAL2MNL_EXT_SERVER "mnldinf_ext"
+
+typedef enum {
+ HAL2MNL_HAL_REBOOT = 0,
+ HAL2MNL_GPS_INIT = 101,
+ HAL2MNL_GPS_START = 102,
+ HAL2MNL_GPS_STOP = 103,
+ HAL2MNL_GPS_CLEANUP = 104,
+ HAL2MNL_GPS_INJECT_TIME = 105,
+ HAL2MNL_GPS_INJECT_LOCATION = 106,
+ HAL2MNL_GPS_DELETE_AIDING_DATA = 107,
+ HAL2MNL_GPS_SET_POSITION_MODE = 108,
+ HAL2MNL_DATA_CONN_OPEN = 201,
+ HAL2MNL_DATA_CONN_OPEN_WITH_APN_IP_TYPE = 202,
+ HAL2MNL_DATA_CONN_CLOSED = 203,
+ HAL2MNL_DATA_CONN_FAILED = 204,
+ HAL2MNL_SET_SERVER = 301,
+ HAL2MNL_SET_REF_LOCATION = 302,
+ HAL2MNL_SET_ID = 303,
+ HAL2MNL_NI_MESSAGE = 401,
+ HAL2MNL_NI_RESPOND = 402,
+ HAL2MNL_UPDATE_NETWORK_STATE = 501,
+ HAL2MNL_UPDATE_NETWORK_AVAILABILITY = 502,
+ HAL2MNL_GPS_MEASUREMENT = 601,
+ HAL2MNL_GPS_NAVIGATION = 602,
+ HAL2MNL_VZW_DEBUG = 603,
+ HAL2MNL_GNSS_CONFIG = 604,
+ HAL2MNL_SV_BLACKLIST = 605,
+ HAL2MNL_CORRECTION = 606,
+ HAL2MNL_NFW_ACCESS = 607,
+ HAL2MNL_FULL_TRACKING = 701,
+ HAL2MNL_SEND_PMTK = 702,
+ HAL2MNL_EPO_ENABLE = 703,
+ HAL2MNL_SET_TTFF_ACC = 704,
+ HAL2MNL_BASIC_CAP_SYNC = 705,
+ HAL2MNL_EXT_CAP_SYNC = 706,
+} hal2mnl_cmd;
+
+typedef int gps_pos_mode;
+#define GPS_POS_MODE_STANDALONE 0
+#define GPS_POS_MODE_MSB 1
+
+typedef int gps_pos_recurrence;
+#define GPS_POS_RECURRENCE_PERIODIC 0
+#define GPS_POS_RECURRENCE_SINGLE 1
+
+typedef int ni_user_response_type;
+#define NI_USER_RESPONSE_ACCEPT 1
+#define NI_USER_RESPONSE_DENY 2
+#define NI_USER_RESPONSE_NORESP 3
+
+typedef int cell_type;
+#define CELL_TYPE_GSM 1
+#define CELL_TYPE_UMTS 2
+
+typedef int agps_id_type;
+#define AGPS_ID_TYPE_NONE 0
+#define AGPS_ID_TYPE_IMSI 1
+#define AGPS_ID_TYPE_MSISDN 2
+
+typedef int network_type;
+#define NETWORK_TYPE_MOBILE 0
+#define NETWORK_TYPE_WIFI 1
+#define NETWORK_TYPE_MOBILE_MMS 2
+#define NETWORK_TYPE_MOBILE_SUPL 3
+#define NETWORK_TYPE_MOBILE_DUN 4
+#define NETWORK_TYPE_MOBILE_HIPRI 5
+#define NETWORK_TYPE_WIMAX 6
+
+typedef int apn_ip_type;
+#define MTK_APN_IP_INVALID 0
+#define MTK_APN_IP_IPV4 1
+#define MTK_APN_IP_IPV6 2
+#define MTK_APN_IP_IPV4V6 3
+
+typedef int agps_type;
+#define MTK_AGPS_TYPE_SUPL 1
+#define MTK_AGPS_TYPE_C2K 2
+#define MTK_AGPS_TYPE_SUPL_EIMS 3
+#define MTK_AGPS_TYPE_SUPL_IMS 4
+
+typedef int epo_bitmap;
+#define MTK_EPO_CFG_EPO (1U<<0)
+#define MTK_EPO_CFG_QEPO (1U<<1)
+
+typedef unsigned short network_capability;
+#define NOT_METERED (1 << 0)
+#define NOT_ROAMING (1 << 1)
+
+typedef int ttff_acc;
+#define MTK_TTFF_ACC_LOW 0
+#define MTK_TTFF_ACC_MID 1
+#define MTK_TTFF_ACC_HIGH 2
+
+typedef int gnss_delete_flag;
+#define MTK_GNSS_DELETE_EPHEMERIS 0x0001
+#define MTK_GNSS_DELETE_ALMANAC 0x0002
+#define MTK_GNSS_DELETE_POSITION 0x0004
+#define MTK_GNSS_DELETE_TIME 0x0008
+#define MTK_GNSS_DELETE_IONO 0x0010
+#define MTK_GNSS_DELETE_UTC 0x0020
+#define MTK_GNSS_DELETE_HEALTH 0x0040
+#define MTK_GNSS_DELETE_SVDIR 0x0080
+#define MTK_GNSS_DELETE_SVSTEER 0x0100
+#define MTK_GNSS_DELETE_SADATA 0x0200
+#define MTK_GNSS_DELETE_RTI 0x0400
+#define MTK_GNSS_DELETE_CLK 0x0800
+#define MTK_GNSS_DELETE_CELLDB_INFO 0x8000
+#define MTK_GNSS_DELETE_ALL 0xFFFF
+//======================================================
+// MNLD -> GPS HAL
+//======================================================
+#define MTK_MNL2HAL "mtk_mnl2hal"
+
+typedef enum {
+ MNL2HAL_MNLD_REBOOT = 1,
+ MNL2HAL_LOCATION = 101,
+ MNL2HAL_GPS_STATUS = 102,
+ MNL2HAL_GPS_SV = 103,
+ MNL2HAL_NMEA = 104,
+ MNL2HAL_GPS_CAPABILITIES = 105,
+ MNL2HAL_GPS_MEASUREMENTS = 106,
+ MNL2HAL_GPS_NAVIGATION = 107,
+ MNL2HAL_GNSS_MEASUREMENTS = 108,
+ MNL2HAL_GNSS_NAVIGATION = 109,
+ MNL2HAL_REQUEST_WAKELOCK = 201,
+ MNL2HAL_RELEASE_WAKELOCK = 202,
+ MNL2HAL_REQUEST_UTC_TIME = 301,
+ MNL2HAL_REQUEST_DATA_CONN = 302,
+ MNL2HAL_RELEASE_DATA_CONN = 303,
+ MNL2HAL_REQUEST_NI_NOTIFY = 304,
+ MNL2HAL_REQUEST_SET_ID = 305,
+ MNL2HAL_REQUEST_REF_LOC = 306,
+ MNL2HAL_VZW_DEBUG_OUTPUT = 307,
+ MNL2HAL_UPDATE_GNSS_NAME = 308,
+ MNL2HAL_REQUEST_NLP = 309,
+ MNL2HAL_NFW_NOTIFY = 310,
+ MNL2HAL_BASIC_CAP_SYNC = 311,
+ MNL2HAL_EXT_CAP_SYNC = 312,
+ MNL2HAL_NMEA_DONE = 313,
+ MNL2HAL_AGPS_LOCATION = 314,
+} mnl2hal_cmd;
+
+#define MTK_MNLD_GNSS_MAX_SVS (32+7+24+63+36+19+14) //195, GPS+QZSS+Glonass+Beidou+Galileo+SBAS+IRNSS_SV
+#define GPS_MAX_MEASUREMENT 32
+#define MTK_MNLD_GNSS_MAX_MEASUREMENT (100) //181 will over size 16KB
+
+typedef unsigned int gps_location_flags;
+#define MTK_GPS_LOCATION_HAS_LAT_LONG 0x0001
+#define MTK_GPS_LOCATION_HAS_ALT 0x0002
+#define MTK_GPS_LOCATION_HAS_SPEED 0x0004
+#define MTK_GPS_LOCATION_HAS_BEARING 0x0008
+#define MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY 0x0010
+#define MTK_GPS_LOCATION_HAS_VERTICAL_ACCURACY 0x0020
+#define MTK_GPS_LOCATION_HAS_SPEED_ACCURACY 0x0040
+#define MTK_GPS_LOCATION_HAS_BEARING_ACCURACY 0x0080
+#define MTK_GPS_LOCATION_HAS_PDOP 0x0100
+#define MTK_GPS_LOCATION_HAS_HDOP 0x0200
+#define MTK_GPS_LOCATION_HAS_VDOP 0x0400
+
+typedef int request_setid;
+#define REQUEST_SETID_IMSI (1<<0L)
+#define REQUEST_SETID_MSISDN (1<<1L)
+
+typedef int request_refloc;
+#define REQUEST_REFLOC_CELLID (1<<0L)
+#define REQUEST_REFLOC_MAC (1<<1L) // not ready
+
+typedef short gps_clock_flags;
+#define GPS_CLK_HAS_LEAP_SECOND (1<<0)
+#define GPS_CLK_HAS_TIME_UNCERTAINTY (1<<1)
+#define GPS_CLK_HAS_FULL_BIAS (1<<2)
+#define GPS_CLK_HAS_BIAS (1<<3)
+#define GPS_CLK_HAS_BIAS_UNCERTAINTY (1<<4)
+#define GPS_CLK_HAS_DRIFT (1<<5)
+#define GPS_CLK_HAS_DRIFT_UNCERTAINTY (1<<6)
+
+typedef char gps_clock_type;
+#define GPS_CLOCK_TYPE_UNKNOWN 0
+#define GPS_CLOCK_TYPE_LOCAL_HW_TIME 1
+#define GPS_CLOCK_TYPE_GPS_TIME 2
+
+typedef int gps_measurement_flags;
+#define GPS_MEASUREMENT_HAS_SNR (1<<0)
+#define GPS_MEASUREMENT_HAS_ELEVATION (1<<1)
+#define GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY (1<<2)
+#define GPS_MEASUREMENT_HAS_AZIMUTH (1<<3)
+#define GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY (1<<4)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE (1<<5)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY (1<<6)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE (1<<7)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY (1<<8)
+#define GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9)
+#define GPS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12)
+#define GPS_MEASUREMENT_HAS_BIT_NUMBER (1<<13)
+#define GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT (1<<14)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT (1<<15)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY (1<<16)
+#define GPS_MEASUREMENT_HAS_USED_IN_FIX (1<<17)
+
+typedef short gps_measurement_state;
+#define GPS_MEASUREMENT_STATE_UNKNOWN 0
+#define GPS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define GPS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define GPS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define GPS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+#define GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4)
+
+typedef short gps_accumulated_delta_range_state;
+#define GPS_ADR_STATE_UNKNOWN 0
+#define GPS_ADR_STATE_VALID (1<<0)
+#define GPS_ADR_STATE_RESET (1<<1)
+#define GPS_ADR_STATE_CYCLE_SLIP (1<<2)
+
+typedef char gps_loss_of_lock;
+#define GPS_LOSS_OF_LOCK_UNKNOWN 0
+#define GPS_LOSS_OF_LOCK_OK 1
+#define GPS_LOSS_OF_LOCK_CYCLE_SLIP 2
+
+typedef char gps_multipath_indicator;
+#define GPS_MULTIPATH_INDICATOR_UNKNOWN 0
+#define GPS_MULTIPATH_INDICATOR_DETECTED 1
+#define GPS_MULTIPATH_INDICATOR_NOT_USED 2
+
+typedef char gps_nav_msg_type;
+#define GPS_NAV_MSG_TYPE_UNKNOWN 0
+#define GPS_NAV_MSG_TYPE_L1CA 1
+#define GPS_NAV_MSG_TYPE_L2CNAV 2
+#define GPS_NAV_MSG_TYPE_L5CNAV 3
+#define GPS_NAV_MSG_TYPE_CNAV2 4
+
+typedef short nav_msg_status;
+#define NAV_MSG_STATUS_UNKONW 0
+#define NAV_MSG_STATUS_PARITY_PASSED (1<<0)
+#define NAV_MSG_STATUS_PARITY_REBUILT (1<<1)
+
+typedef int gps_status;
+#define MTK_GPS_STATUS_SESSION_BEGIN 1
+#define MTK_GPS_STATUS_SESSION_END 2
+#define MTK_GPS_STATUS_SESSION_ENGINE_ON 3
+#define MTK_GPS_STATUS_SESSION_ENGINE_OFF 4
+
+typedef int agps_ni_type;
+#define AGPS_NI_TYPE_VOICE 1
+#define AGPS_NI_TYPE_UMTS_SUPL 2
+#define AGPS_NI_TYPE_UMTS_CTRL_PLANE 3
+#define AGPS_NI_TYPE_EMERGENCY_SUPL 4
+
+typedef int agps_notify_type;
+#define AGPS_NOTIFY_TYPE_NONE 0
+#define AGPS_NOTIFY_TYPE_NOTIFY_ONLY 1
+#define AGPS_NOTIFY_TYPE_NOTIFY_ALLOW_NO_ANSWER 2
+#define AGPS_NOTIFY_TYPE_NOTIFY_DENY_NO_ANSWER 3
+#define AGPS_NOTIFY_TYPE_PRIVACY 4
+
+typedef int ni_encoding_type;
+#define NI_ENCODING_TYPE_NONE 0
+#define NI_ENCODING_TYPE_GSM7 1
+#define NI_ENCODING_TYPE_UTF8 2
+#define NI_ENCODING_TYPE_UCS2 3
+
+/**
+ * Flags that indicate information about the satellite
+ */
+typedef uint8_t gnss_sv_flags;
+#define MTK_GNSS_SV_FLAGS_NONE 0
+#define MTK_GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA (1 << 0)
+#define MTK_GNSS_SV_FLAGS_HAS_ALMANAC_DATA (1 << 1)
+#define MTK_GNSS_SV_FLAGS_USED_IN_FIX (1 << 2)
+
+typedef struct {
+ /**
+ * A set of flags indicating the validity of each field in this data structure.
+ *
+ * Fields may have invalid information in them, if not marked as valid by the
+ * corresponding bit in flags.
+ */
+ uint16_t flags;
+
+ /**
+ * Estimate of the elapsed time since boot value for the corresponding event in nanoseconds.
+ */
+ uint64_t timestampNs;
+
+ /**
+ * Estimate of the relative precision of the alignment of this SystemClock
+ * timestamp, with the reported measurements in nanoseconds (68% confidence).
+ */
+ uint64_t timeUncertaintyNs;
+}elapsedrealtime ;
+
+typedef unsigned int loc_type;
+#define MTK_LOC_TYPE_AGPS_AFLT 0 // From C2K AFLT flow
+#define MTK_LOC_TYPE_AGPS_CDMA_CELL 1 // From C2K Cell
+#define MTK_LOC_TYPE_AGPS_MOLR_BEGIN_RSP 2 // For CP MOLR after UE provides MSA result, the network will send CISS_FACILITY to provide UE a MSA location. Refer to 3GPP TS37.571-2 7.2.2.2
+#define MTK_LOC_TYPE_AGPS_SUPL_END 3 // From the SUPL END in a supl session. It may be the result of MSA, E-CID, OTDOA, or their hybrid.
+#define MTK_LOC_TYPE_AGPS_SUPL_REF_LOC 4 // For Reference Location assistance data in SUPL flow (equivalent to PMTK713 in SUPL flow)
+#define MTK_LOC_TYPE_AGPS_CP_REF_LOC 5 // For Reference Location assistance data in CP AGPS flow (equivalent to PMTK713 in CP AGPS flow)
+#define MTK_LOC_TYPE_GNSS_STANDALONE 0xfe // GNSS Standalone
+#define MTK_LOC_TYPE_GNSS_UNKNOWN 0xff // Unknown
+
+typedef struct {
+ gps_location_flags flags;
+ double lat;
+ double lng;
+ double alt;
+ float speed;
+ float bearing;
+ float h_accuracy; //horizontal
+ float v_accuracy; //vertical
+ float s_accuracy; //spedd
+ float b_accuracy; //bearing
+ int64_t timestamp;
+ float pdop;
+ float hdop;
+ float vdop;
+ loc_type type;
+} gps_location;
+
+typedef struct {
+ int16_t svid;
+ uint8_t constellation;
+ float c_n0_dbhz;
+ float elevation;
+ float azimuth;
+ gnss_sv_flags flags;
+ float carrier_frequency; //Hz
+ double basebandCN0DbHz;
+} gnss_sv;
+
+typedef struct {
+ int num_svs;
+ gnss_sv sv_list[MTK_MNLD_GNSS_MAX_SVS];
+} gnss_sv_info;
+
+typedef struct {
+ int prn;
+ bool has_ephemeris_data;
+ bool has_almanac_data;
+ bool used_in_fix;
+} NmeaCash;
+
+typedef uint16_t MTK_MNLD_NavigationMessageStatus;
+#define MTK_NAV_MESSAGE_STATUS_UNKNOWN 0
+#define MTK_NAV_MESSAGE_STATUS_PARITY_PASSED (1<<0)
+#define MTK_NAV_MESSAGE_STATUS_PARITY_REBUILT (1<<1)
+
+typedef int16_t MTK_MNLD_GnssNavigationMessageType;
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN 0
+/** GPS L1 C/A message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA 0x0101
+/** GPS L2-CNAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV 0x0102
+/** GPS L5-CNAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV 0x0103
+/** GPS CNAV-2 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2 0x0104
+/** Glonass L1 CA message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA 0x0301
+/** Beidou D1 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1 0x0501
+/** Beidou D2 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2 0x0502
+/** Galileo I/NAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I 0x0601
+/** Galileo F/NAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F 0x0602
+
+typedef uint8_t MTK_MNLD_GnssMultipathIndicator;
+/** The indicator is not available or unknown. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_UNKNOWN 0
+/** The measurement is indicated to be affected by multipath. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_PRESENT 1
+/** The measurement is indicated to be not affected by multipath. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_NOT_PRESENT 2
+
+typedef uint16_t MTK_MNLD_GnssAccumulatedDeltaRangeState;
+#define MTK_GNSS_ADR_STATE_UNKNOWN 0
+#define MTK_GNSS_ADR_STATE_VALID (1<<0)
+#define MTK_GNSS_ADR_STATE_RESET (1<<1)
+#define MTK_GNSS_ADR_STATE_CYCLE_SLIP (1<<2)
+
+typedef uint32_t MTK_MNLD_GnssMeasurementState;
+#define MTK_GNSS_MEASUREMENT_STATE_UNKNOWN 0
+#define MTK_GNSS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define MTK_GNSS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define MTK_GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define MTK_GNSS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+#define MTK_GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4)
+#define MTK_GNSS_MEASUREMENT_STATE_SYMBOL_SYNC (1<<5)
+#define MTK_GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC (1<<6)
+#define MTK_GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED (1<<7)
+#define MTK_GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC (1<<8)
+#define MTK_GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC (1<<9)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK (1<<10)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK (1<<11)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC (1<<12)
+#define MTK_GNSS_MEASUREMENT_STATE_SBAS_SYNC (1<<13)
+
+typedef uint8_t MTK_MNLD_GnssConstellationType;
+#define MTK_GNSS_CONSTELLATION_UNKNOWN 0
+#define MTK_GNSS_CONSTELLATION_GPS 1
+#define MTK_GNSS_CONSTELLATION_SBAS 2
+#define MTK_GNSS_CONSTELLATION_GLONASS 3
+#define MTK_GNSS_CONSTELLATION_QZSS 4
+#define MTK_GNSS_CONSTELLATION_BEIDOU 5
+#define MTK_GNSS_CONSTELLATION_GALILEO 6
+
+typedef uint32_t MTK_MNLD_GnssMeasurementFlags;
+/** A valid 'snr' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_SNR (1<<0)
+/** A valid 'carrier frequency' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9)
+/** A valid 'carrier cycles' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10)
+/** A valid 'carrier phase' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11)
+/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12)
+
+typedef uint16_t MTK_MNLD_GnssClockFlags;
+/** A valid 'leap second' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_LEAP_SECOND (1<<0)
+/** A valid 'time uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_TIME_UNCERTAINTY (1<<1)
+/** A valid 'full bias' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_FULL_BIAS (1<<2)
+/** A valid 'bias' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_BIAS (1<<3)
+/** A valid 'bias uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_BIAS_UNCERTAINTY (1<<4)
+/** A valid 'drift' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_DRIFT (1<<5)
+/** A valid 'drift uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY (1<<6)
+
+typedef struct {
+ /** A set of flags indicating the validity of the fields in this data structure. */
+ gps_clock_flags flags;
+
+ /**
+ * Leap second data.
+ * The sign of the value is defined by the following equation:
+ * utc_time_ns = time_ns + (full_bias_ns + bias_ns) - leap_second * 1,000,000,000
+ *
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_LEAP_SECOND.
+ */
+ short leap_second;
+
+ /**
+ * Indicates the type of time reported by the 'time_ns' field.
+ */
+ gps_clock_type type;
+
+ /**
+ * The GPS receiver internal clock value. This can be either the local hardware clock value
+ * (GPS_CLOCK_TYPE_LOCAL_HW_TIME), or the current GPS time derived inside GPS receiver
+ * (GPS_CLOCK_TYPE_GPS_TIME). The field 'type' defines the time reported.
+ *
+ * For local hardware clock, this value is expected to be monotonically increasing during
+ * the reporting session. The real GPS time can be derived by compensating the 'full bias'
+ * (when it is available) from this value.
+ *
+ * For GPS time, this value is expected to be the best estimation of current GPS time that GPS
+ * receiver can achieve. Set the 'time uncertainty' appropriately when GPS time is specified.
+ *
+ * Sub-nanosecond accuracy can be provided by means of the 'bias' field.
+ * The value contains the 'time uncertainty' in it.
+ */
+ int64_t time_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * This value should be set if GPS_CLOCK_TYPE_GPS_TIME is set.
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_TIME_UNCERTAINTY.
+ */
+ double time_uncertainty_ns;
+
+ /**
+ * The difference between hardware clock ('time' field) inside GPS receiver and the true GPS
+ * time since 0000Z, January 6, 1980, in nanoseconds.
+ * This value is used if and only if GPS_CLOCK_TYPE_LOCAL_HW_TIME is set, and GPS receiver
+ * has solved the clock for GPS time.
+ * The caller is responsible for using the 'bias uncertainty' field for quality check.
+ *
+ * The sign of the value is defined by the following equation:
+ * true time (GPS time) = time_ns + (full_bias_ns + bias_ns)
+ *
+ * This value contains the 'bias uncertainty' in it.
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_FULL_BIAS.
+
+ */
+ int64_t full_bias_ns;
+
+ /**
+ * Sub-nanosecond bias.
+ * The value contains the 'bias uncertainty' in it.
+ *
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_BIAS.
+ */
+ double bias_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's bias in nanoseconds.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_BIAS_UNCERTAINTY.
+ */
+ double bias_uncertainty_ns;
+
+ /**
+ * The clock's drift in nanoseconds (per second).
+ * A positive value means that the frequency is higher than the nominal frequency.
+ *
+ * The value contains the 'drift uncertainty' in it.
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_DRIFT.
+ *
+ * If GpsMeasurement's 'flags' field contains GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE,
+ * it is encouraged that this field is also provided.
+ */
+ double drift_nsps;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available 'flags' must contain GPS_CLOCK_HAS_DRIFT_UNCERTAINTY.
+ */
+ double drift_uncertainty_nsps;
+} gps_clock;
+
+/**
+ * Represents an estimate of the GPS clock time.
+ */
+typedef struct {
+ MTK_MNLD_GnssConstellationType constellation;
+ double carrierFrequencyHz;
+ uint8_t codeType[8];
+}MTK_MNLD_GnssSignalType;
+
+typedef struct {
+ /**
+ * A set of flags indicating the validity of the fields in this data
+ * structure.
+ */
+ MTK_MNLD_GnssClockFlags flags;
+
+ /**
+ * Leap second data.
+ * The sign of the value is defined by the following equation:
+ * utc_time_ns = time_ns - (full_bias_ns + bias_ns) - leap_second *
+ * 1,000,000,000
+ *
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_LEAP_SECOND.
+ */
+ int16_t leap_second;
+
+ /**
+ * The GNSS receiver internal clock value. This is the local hardware clock
+ * value.
+ *
+ * For local hardware clock, this value is expected to be monotonically
+ * increasing while the hardware clock remains power on. (For the case of a
+ * HW clock that is not continuously on, see the
+ * hw_clock_discontinuity_count field). The receiver's estimate of GPS time
+ * can be derived by substracting the sum of full_bias_ns and bias_ns (when
+ * available) from this value.
+ *
+ * This GPS time is expected to be the best estimate of current GPS time
+ * that GNSS receiver can achieve.
+ *
+ * Sub-nanosecond accuracy can be provided by means of the 'bias_ns' field.
+ * The value contains the 'time uncertainty' in it.
+ *
+ * This field is mandatory.
+ */
+ int64_t time_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_CLOCK_HAS_TIME_UNCERTAINTY. This value is effectively zero (it is
+ * the reference local clock, by which all other times and time
+ * uncertainties are measured.) (And thus this field can be not provided,
+ * per GNSS_CLOCK_HAS_TIME_UNCERTAINTY flag, or provided & set to 0.)
+ */
+ double time_uncertainty_ns;
+
+ /**
+ * The difference between hardware clock ('time' field) inside GPS receiver
+ * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
+ *
+ * The sign of the value is defined by the following equation:
+ * local estimate of GPS time = time_ns - (full_bias_ns + bias_ns)
+ *
+ * This value is mandatory if the receiver has estimated GPS time. If the
+ * computed time is for a non-GPS constellation, the time offset of that
+ * constellation to GPS has to be applied to fill this value. The error
+ * estimate for the sum of this and the bias_ns is the bias_uncertainty_ns,
+ * and the caller is responsible for using this uncertainty (it can be very
+ * large before the GPS time has been solved for.) If the data is available
+ * 'flags' must contain GNSS_CLOCK_HAS_FULL_BIAS.
+ */
+ int64_t full_bias_ns;
+
+ /**
+ * Sub-nanosecond bias.
+ * The error estimate for the sum of this and the full_bias_ns is the
+ * bias_uncertainty_ns
+ *
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_BIAS. If GPS
+ * has computed a position fix. This value is mandatory if the receiver has
+ * estimated GPS time.
+ */
+ double bias_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the local estimate of GPS time (clock
+ * bias) in nanoseconds. The uncertainty is represented as an absolute
+ * (single sided) value.
+ *
+ * If the data is available 'flags' must contain
+ * GNSS_CLOCK_HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+ * has estimated GPS time.
+ */
+ double bias_uncertainty_ns;
+
+ /**
+ * The clock's drift in nanoseconds (per second).
+ *
+ * A positive value means that the frequency is higher than the nominal
+ * frequency, and that the (full_bias_ns + bias_ns) is growing more positive
+ * over time.
+ *
+ * The value contains the 'drift uncertainty' in it.
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_DRIFT.
+ *
+ * This value is mandatory if the receiver has estimated GNSS time
+ */
+ double drift_nsps;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available 'flags' must contain
+ * GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY. If GPS has computed a position fix this
+ * field is mandatory and must be populated.
+ */
+ double drift_uncertainty_nsps;
+
+ /**
+ * When there are any discontinuities in the HW clock, this field is
+ * mandatory.
+ *
+ * A "discontinuity" is meant to cover the case of a switch from one source
+ * of clock to another. A single free-running crystal oscillator (XO)
+ * should generally not have any discontinuities, and this can be set and
+ * left at 0.
+ *
+ * If, however, the time_ns value (HW clock) is derived from a composite of
+ * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+ * restarted, then this value shall be incremented each time a discontinuity
+ * occurs. (E.g. this value may start at zero at device boot-up and
+ * increment each time there is a change in clock continuity. In the
+ * unlikely event that this value reaches full scale, rollover (not
+ * clamping) is required, such that this value continues to change, during
+ * subsequent discontinuity events.)
+ *
+ * While this number stays the same, between GnssClock reports, it can be
+ * safely assumed that the time_ns value has been running continuously, e.g.
+ * derived from a single, high quality clock (XO like, or better, that's
+ * typically used during continuous GNSS signal sampling.)
+ *
+ * It is expected, esp. during periods where there are few GNSS signals
+ * available, that the HW clock be discontinuity-free as long as possible,
+ * as this avoids the need to use (waste) a GNSS measurement to fully
+ * re-solve for the GPS clock bias and drift, when using the accompanying
+ * measurements, from consecutive GnssData reports.
+ */
+ uint32_t hw_clock_discontinuity_count;
+ MTK_MNLD_GnssSignalType referenceSignalTypeForIsb;
+} gnss_clock;
+
+typedef struct {
+ /** A set of flags indicating the validity of the fields in this data structure. */
+ gps_measurement_flags flags;
+
+ /**
+ * Pseudo-random number in the range of [1, 32]
+ * This is a Mandatory value.
+ */
+ int8_t prn;
+
+ /**
+ * Time offset at which the measurement was taken in nanoseconds.
+ * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+ * interpreted in the same way as indicated by GpsClock::type.
+ *
+ * The sign of time_offset_ns is given by the following equation:
+ * measurement time = GpsClock::time_ns + time_offset_ns
+ *
+ * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+ * This is a Mandatory value.
+ */
+ double time_offset_ns;
+
+ /**
+ * Per satellite sync state. It represents the current sync state for the associated satellite.
+ * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+ * This is a Mandatory value.
+ */
+ gps_measurement_state state;
+
+ /**
+ * Received GPS Time-of-Week at the measurement time, in nanoseconds.
+ * The value is relative to the beginning of the current GPS week.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : GPS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : GPS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync : [ 0 20ms ] : GPS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe sync : [ 0 6s ] : GPS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * TOW decoded : [ 0 1week ] : GPS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * However, if there is any ambiguity in integer millisecond,
+ * GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+ * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+ */
+ int64_t received_gps_tow_ns;
+
+ /**
+ * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+ * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+ */
+ int64_t received_gps_tow_uncertainty_ns;
+
+ /**
+ * Carrier-to-noise density in dB-Hz, in the range [0, 63].
+ * It contains the measured C/N0 value for the signal at the antenna input.
+ * This is a Mandatory value.
+ */
+ double c_n0_dbhz;
+
+ /**
+ * Pseudorange rate at the timestamp in m/s.
+ * The value also includes the effects of the receiver clock frequency and satellite clock
+ * frequency errors.
+ *
+ * The value includes the 'pseudorange rate uncertainty' in it.
+ * A positive value indicates that the pseudorange is getting larger.
+ * This is a Mandatory value.
+ */
+ double pseudorange_rate_mps;
+
+ /**
+ * 1-Sigma uncertainty of the pseudurange rate in m/s.
+ * The uncertainty is represented as an absolute (single sided) value.
+ * This is a Mandatory value.
+ */
+ double pseudorange_rate_uncertainty_mps;
+
+ /**
+ * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+ * (indicating loss of lock).
+ * This is a Mandatory value.
+ */
+ gps_accumulated_delta_range_state accumulated_delta_range_state;
+
+ /**
+ * Accumulated delta range since the last channel reset in meters.
+ * A positive value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+ * is given by the equation:
+ * accumulated delta range = -k * carrier phase (where k is a constant)
+ *
+ * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ * However, it is expected that the data is only accurate when:
+ * 'accumulated delta range state' == GPS_ADR_STATE_VALID.
+ */
+ double accumulated_delta_range_m;
+
+ /**
+ * 1-Sigma uncertainty of the accumulated delta range in meters.
+ * The data is available if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ */
+ double accumulated_delta_range_uncertainty_m;
+
+ /**
+ * Best derived Pseudorange by the chip-set, in meters.
+ * The value contains the 'pseudorange uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_PSEUDORANGE.
+ */
+ double pseudorange_m;
+
+ /**
+ * 1-Sigma uncertainty of the pseudorange in meters.
+ * The value contains the 'pseudorange' and 'clock' uncertainty in it.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY.
+ */
+ double pseudorange_uncertainty_m;
+
+ /**
+ * A fraction of the current C/A code cycle, in the range [0.0, 1023.0]
+ * This value contains the time (in Chip units) since the last C/A code cycle (GPS Msec epoch).
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'code-phase uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CODE_PHASE.
+ */
+ double code_phase_chips;
+
+ /**
+ * 1-Sigma uncertainty of the code-phase, in a fraction of chips.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY.
+ */
+ double code_phase_uncertainty_chips;
+
+ /**
+ * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+ * If the field is not set, the carrier frequency is assumed to be L1.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+ */
+ float carrier_frequency_hz;
+
+ /**
+ * The number of full carrier cycles between the satellite and the receiver.
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_CYCLES.
+ */
+ int64_t carrier_cycles;
+
+ /**
+ * The RF phase detected by the receiver, in the range [0.0, 1.0].
+ * This is usually the fractional part of the complete carrier phase measurement.
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'carrier-phase uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_PHASE.
+ */
+ double carrier_phase;
+
+ /**
+ * 1-Sigma uncertainty of the carrier-phase.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+ */
+ double carrier_phase_uncertainty;
+
+ /**
+ * An enumeration that indicates the 'loss of lock' state of the event.
+ */
+ gps_loss_of_lock loss_of_lock;
+
+ /**
+ * The number of GPS bits transmitted since Sat-Sun midnight (GPS week).
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_BIT_NUMBER.
+ */
+ int32_t bit_number;
+
+ /**
+ * The elapsed time since the last received bit in milliseconds, in the range [0, 20]
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT.
+ */
+ int16_t time_from_last_bit_ms;
+
+ /**
+ * Doppler shift in Hz.
+ * A positive value indicates that the SV is moving toward the receiver.
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'doppler shift uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_DOPPLER_SHIFT.
+ */
+ double doppler_shift_hz;
+
+ /**
+ * 1-Sigma uncertainty of the doppler shift in Hz.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY.
+ */
+ double doppler_shift_uncertainty_hz;
+
+ /**
+ * An enumeration that indicates the 'multipath' state of the event.
+ */
+ gps_multipath_indicator multipath_indicator;
+
+ /**
+ * Signal-to-noise ratio in dB.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_SNR.
+ */
+ double snr_db;
+
+ /**
+ * Elevation in degrees, the valid range is [-90, 90].
+ * The value contains the 'elevation uncertainty' in it.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_ELEVATION.
+ */
+ double elevation_deg;
+
+ /**
+ * 1-Sigma uncertainty of the elevation in degrees, the valid range is [0, 90].
+ * The uncertainty is represented as the absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY.
+ */
+ double elevation_uncertainty_deg;
+
+ /**
+ * Azimuth in degrees, in the range [0, 360).
+ * The value contains the 'azimuth uncertainty' in it.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_AZIMUTH.
+ * */
+ double azimuth_deg;
+
+ /**
+ * 1-Sigma uncertainty of the azimuth in degrees, the valid range is [0, 180].
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY.
+ */
+ double azimuth_uncertainty_deg;
+
+ /**
+ * Whether the GPS represented by the measurement was used for computing the most recent fix.
+ * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_USED_IN_FIX.
+ */
+ bool used_in_fix;
+} gps_measurement;
+
+/**
+ * Represents a GNSS Measurement, it contains raw and computed information.
+ *
+ * Independence - All signal measurement information (e.g. sv_time,
+ * pseudorange_rate, multipath_indicator) reported in this struct should be
+ * based on GNSS signal measurements only. You may not synthesize measurements
+ * by calculating or reporting expected measurements based on known or estimated
+ * position, velocity, or time.
+ */
+typedef struct {
+ /** A set of flags indicating the validity of the fields in this data structure. */
+ MTK_MNLD_GnssMeasurementFlags flags;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ * This is a mandatory value.
+ */
+ int16_t svid;
+
+ /**
+ * Defines the constellation of the given SV. Value should be one of those
+ * GNSS_CONSTELLATION_* constants
+ */
+ MTK_MNLD_GnssConstellationType constellation;
+
+ /**
+ * Time offset at which the measurement was taken in nanoseconds.
+ * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+ * interpreted in the same way as indicated by GpsClock::type.
+ *
+ * The sign of time_offset_ns is given by the following equation:
+ * measurement time = GpsClock::time_ns + time_offset_ns
+ *
+ * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+ * This is a mandatory value.
+ */
+ double time_offset_ns;
+
+ /**
+ * Per satellite sync state. It represents the current sync state for the associated satellite.
+ * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+ *
+ * This is a mandatory value.
+ */
+ MTK_MNLD_GnssMeasurementState state;
+
+ /**
+ * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+ * Ensure that this field is independent (see comment at top of
+ * GnssMeasurement struct.)
+ *
+ * For GPS & QZSS, this is:
+ * Received GPS Time-of-Week at the measurement time, in nanoseconds.
+ * The value is relative to the beginning of the current GPS week.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range
+ * for this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync : [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe sync : [ 0 6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * TOW decoded : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * Note well: if there is any ambiguity in integer millisecond,
+ * GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+ *
+ * This value must be populated if 'state' != GNSS_MEASUREMENT_STATE_UNKNOWN.
+ *
+ * For Glonass, this is:
+ * Received Glonass time of day, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 10ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+ * Bit sync : [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * String sync : [ 0 2s ] : GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC is set
+ * Time of day : [ 0 1day ] : GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED is set
+ *
+ * For Beidou, this is:
+ * Received Beidou time of week, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync (D2): [ 0 2ms ] : GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC is set
+ * Bit sync (D1): [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe (D2): [ 0 0.6s ] : GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC is set
+ * Subframe (D1): [ 0 6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * Time of week : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * For Galileo, this is:
+ * Received Galileo time of week, at the measurement time in nanoseconds.
+ *
+ * E1BC code lock : [ 0 4ms ] : GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK is set
+ * E1C 2nd code lock: [ 0 100ms ] :
+ * GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is set
+ *
+ * E1B page : [ 0 2s ] : GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC is set
+ * Time of week: [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * For SBAS, this is:
+ * Received SBAS time, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite,
+ * valid range for this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 2ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+ * Message : [ 0 1s ] : GNSS_MEASUREMENT_STATE_SBAS_SYNC is set
+ */
+ int64_t received_sv_time_in_ns;
+
+ /**
+ * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+ *
+ * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+ */
+ int64_t received_sv_time_uncertainty_in_ns;
+
+ /**
+ * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+ * It contains the measured C/N0 value for the signal at the antenna port.
+ *
+ * This is a mandatory value.
+ */
+ double c_n0_dbhz;
+
+ /**
+ * Pseudorange rate at the timestamp in m/s. The correction of a given
+ * Pseudorange Rate value includes corrections for receiver and satellite
+ * clock frequency errors. Ensure that this field is independent (see
+ * comment at top of GnssMeasurement struct.)
+ *
+ * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
+ * 'drift' field as well (When providing the uncorrected pseudorange rate, do not apply the
+ * corrections described above.)
+ *
+ * The value includes the 'pseudorange rate uncertainty' in it.
+ * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler
+ * shift' is given by the equation:
+ * pseudorange rate = -k * doppler shift (where k is a constant)
+ *
+ * This should be the most accurate pseudorange rate available, based on
+ * fresh signal measurements from this channel.
+ *
+ * It is mandatory that this value be provided at typical carrier phase PRR
+ * quality (few cm/sec per second of uncertainty, or better) - when signals
+ * are sufficiently strong & stable, e.g. signals from a GPS simulator at >=
+ * 35 dB-Hz.
+ */
+ double pseudorange_rate_mps;
+
+ /**
+ * 1-Sigma uncertainty of the pseudorange_rate_mps.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * This is a mandatory value.
+ */
+ double pseudorange_rate_uncertainty_mps;
+
+ /**
+ * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+ * (indicating loss of lock).
+ *
+ * This is a mandatory value.
+ */
+ MTK_MNLD_GnssAccumulatedDeltaRangeState accumulated_delta_range_state;
+
+ /**
+ * Accumulated delta range since the last channel reset in meters.
+ * A positive value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+ * is given by the equation:
+ * accumulated delta range = -k * carrier phase (where k is a constant)
+ *
+ * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ * However, it is expected that the data is only accurate when:
+ * 'accumulated delta range state' == GPS_ADR_STATE_VALID.
+ */
+ double accumulated_delta_range_m;
+
+ /**
+ * 1-Sigma uncertainty of the accumulated delta range in meters.
+ * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ */
+ double accumulated_delta_range_uncertainty_m;
+
+ /**
+ * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+ * If the field is not set, the carrier frequency is assumed to be L1.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+ */
+ float carrier_frequency_hz;
+
+ /**
+ * The number of full carrier cycles between the satellite and the receiver.
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * Indications of possible cycle slips and resets in the accumulation of
+ * this value can be inferred from the accumulated_delta_range_state flags.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
+ */
+ int64_t carrier_cycles;
+
+ /**
+ * The RF phase detected by the receiver, in the range [0.0, 1.0].
+ * This is usually the fractional part of the complete carrier phase measurement.
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'carrier-phase uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_PHASE.
+ */
+ double carrier_phase;
+
+ /**
+ * 1-Sigma uncertainty of the carrier-phase.
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+ */
+ double carrier_phase_uncertainty;
+
+ /**
+ * An enumeration that indicates the 'multipath' state of the event.
+ *
+ * The multipath Indicator is intended to report the presence of overlapping
+ * signals that manifest as distorted correlation peaks.
+ *
+ * - if there is a distorted correlation peak shape, report that multipath
+ * is GNSS_MULTIPATH_INDICATOR_PRESENT.
+ * - if there is not a distorted correlation peak shape, report
+ * GNSS_MULTIPATH_INDICATOR_NOT_PRESENT
+ * - if signals are too weak to discern this information, report
+ * GNSS_MULTIPATH_INDICATOR_UNKNOWN
+ *
+ * Example: when doing the standardized overlapping Multipath Performance
+ * test (3GPP TS 34.171) the Multipath indicator should report
+ * GNSS_MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+ * contain multipath, and GNSS_MULTIPATH_INDICATOR_NOT_PRESENT for those
+ * signals that are tracked and do not contain multipath.
+ */
+ MTK_MNLD_GnssMultipathIndicator multipath_indicator;
+
+ /**
+ * Signal-to-noise ratio at correlator output in dB.
+ * If the data is available, 'flags' must contain GNSS_MEASUREMENT_HAS_SNR.
+ * This is the power ratio of the "correlation peak height above the
+ * observed noise floor" to "the noise RMS".
+ */
+ double snr_db;
+ /**
+ * The full inter-signal bias (ISB) in nanoseconds.
+ *
+ * This value is the sum of the estimated receiver-side and the space-segment-side
+ * inter-system bias, inter-frequency bias and inter-code bias, including
+ *
+ * - Receiver inter-constellation bias (with respect to the constellation in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Receiver inter-frequency bias (with respect to the carrier frequency in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Receiver inter-code bias (with respect to the code type in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPS-UTC Time Offset
+ * (TauGps), BDS-GLO Time Offset (BGTO)) (with respect to the constellation in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Group delay (e.g., Total Group Delay (TGD))
+ * - Satellite inter-frequency bias (GLO only) (with respect to the carrier frequency in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Satellite inter-code bias (e.g., Differential Code Bias (DCB)) (with respect to the
+ * code type in GnssClock.referenceSignalTypeForIsb)
+ *
+ * If a component of the above is already compensated in the provided
+ * GnssMeasurement.receivedSvTimeInNs, then it must not be included in the reported full
+ * ISB.
+ *
+ * The value does not include the inter-frequency Ionospheric bias.
+ *
+ * The full ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
+ */
+ double fullInterSignalBiasNs;
+ /**
+ * 1-sigma uncertainty associated with the full inter-signal bias in nanoseconds.
+ */
+ double fullInterSignalBiasUncertaintyNs;
+ /**
+ * The satellite inter-signal bias in nanoseconds.
+ *
+ * This value is the satellite-and-control-segment-side inter-system (different from the
+ * constellation in GnssClock.referenceSignalTypeForIsb) bias and inter-frequency (different
+ * from the carrier frequency in GnssClock.referenceSignalTypeForIsb) bias, including:
+ *
+ * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPT-UTC Time Offset (TauGps),
+ * BDS-GLO Time Offset (BGTO))
+ * - Group delay (e.g., Total Group Delay (TGD))
+ * - Satellite inter-signal bias, which includes satellite inter-frequency bias (GLO only),
+ * and satellite inter-code bias (e.g., Differential Code Bias (DCB)).
+ *
+ * The receiver ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
+ */
+ double satelliteInterSignalBiasNs;
+ /**
+ * 1-sigma uncertainty associated with the satellite inter-signal bias in nanoseconds.
+ */
+ double satelliteInterSignalBiasUncertaintyNs;
+ /**
+ * Baseband Carrier-to-noise density in dB-Hz, typically in the range [0, 63]. It contains
+ * the measured C/N0 value for the signal measured at the baseband.
+ *
+ * This is typically a few dB weaker than the value estimated for C/N0 at the antenna port,
+ * which is reported in cN0DbHz.
+ *
+ * If a signal has separate components (e.g. Pilot and Data channels) and the receiver only
+ * processes one of the components, then the reported basebandCN0DbHz reflects only the
+ * component that is processed.
+ *
+ * This value is mandatory.
+ */
+ double basebandCN0DbHz;
+
+ /**
+ * Automatic gain control (AGC) level. AGC acts as a variable gain
+ * amplifier adjusting the power of the incoming signal. The AGC level
+ * may be used to indicate potential interference. When AGC is at a
+ * nominal level, this value must be set as 0. Higher gain (and/or lower
+ * input power) must be output as a positive number. Hence in cases of
+ * strong jamming, in the band of this signal, this value must go more
+ * negative.
+ */
+ double agc_level_db;
+
+ /// v2.0
+ char codeType[8];
+} gnss_measurement;
+
+typedef struct {
+ /** Number of measurements. */
+ size_t measurement_count;
+
+ /** The array of measurements. */
+ gps_measurement measurements[GPS_MAX_MEASUREMENT];
+
+ /** The GPS clock time reading. */
+ gps_clock clock;
+} gps_data;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+ /** Number of measurements. */
+ size_t measurement_count;
+
+ /** The array of measurements. */
+ gnss_measurement measurements[MTK_MNLD_GNSS_MAX_MEASUREMENT];
+
+ /** The GPS clock time reading. */
+ gnss_clock clock;
+} gnss_data;
+
+#define MAX_NAV_DATA_LEN 40
+
+typedef struct {
+ /**
+ * Pseudo-random number in the range of [1, 32]
+ * This is a Mandatory value.
+ */
+ int8_t prn;
+
+ /**
+ * The type of message contained in the structure.
+ * This is a Mandatory value.
+ */
+ gps_nav_msg_type type;
+
+ /**
+ * The status of the received navigation message.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+ nav_msg_status status;
+
+ /**
+ * Message identifier.
+ * It provides an index so the complete Navigation Message can be assembled. i.e. fo L1 C/A
+ * subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message.
+ * Subframe 1, 2, 3 does not contain a 'frame id' and this value can be set to -1.
+ */
+ short message_id;
+
+ /**
+ * Sub-message identifier.
+ * If required by the message 'type', this value contains a sub-index within the current
+ * message (or frame) that is being transmitted.
+ * i.e. for L1 C/A the submessage id corresponds to the sub-frame id of the navigation message.
+ */
+ short submessage_id;
+
+ /**
+ * The length of the data (in bytes) contained in the current message.
+ * If this value is different from zero, 'data' must point to an array of the same size.
+ * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+ * This is a Mandatory value.
+ */
+ size_t data_length;
+
+ /**
+ * The data of the reported GPS message.
+ * The bytes (or words) specified using big endian format (MSB first).
+ *
+ * For L1 C/A, each subframe contains 10 30-bit GPS words. Each GPS word (30 bits) should be
+ * fitted into the last 30 bits in a 4-byte word (skip B31 and B32), with MSB first.
+ */
+ char data[MAX_NAV_DATA_LEN];
+} gps_nav_msg;
+
+/** Represents a GPS navigation message (or a fragment of it). */
+typedef struct {
+ /** set to sizeof(GnssNavigationMessage) */
+ size_t size;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ * This is a mandatory value.
+ */
+ int16_t svid;
+
+ /**
+ * The type of message contained in the structure.
+ * This is a mandatory value.
+ */
+ MTK_MNLD_GnssNavigationMessageType type;
+
+ /**
+ * The status of the received navigation message.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+ MTK_MNLD_NavigationMessageStatus status;
+
+ /**
+ * Message identifier. It provides an index so the complete Navigation
+ * Message can be assembled.
+ *
+ * - For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+ * id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+ * does not contain a 'frame id' and this value can be set to -1.)
+ *
+ * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+ *
+ * - For BeiDou D1, this refers to the frame number in the range of 1-24
+ *
+ * - For Beidou D2, this refers to the frame number, in the range of 1-120
+ *
+ * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+ * number, in the range of 1-12
+ *
+ * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+ * number in the range of 1-24
+ */
+ int16_t message_id;
+
+ /**
+ * Sub-message identifier. If required by the message 'type', this value
+ * contains a sub-index within the current message (or frame) that is being
+ * transmitted.
+ *
+ * - For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to
+ * the subframe number of the navigation message, in the range of 1-5.
+ *
+ * - For Glonass L1 C/A, this refers to the String number, in the range from
+ * 1-15
+ *
+ * - For Galileo F/NAV, this refers to the page type in the range 1-6
+ *
+ * - For Galileo I/NAV, this refers to the word type in the range 1-10+
+ */
+ int16_t submessage_id;
+
+ /**
+ * The length of the data (in bytes) contained in the current message.
+ * If this value is different from zero, 'data' must point to an array of the same size.
+ * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+ *
+ * This is a mandatory value.
+ */
+ size_t data_length;
+
+ /**
+ * The data of the reported GPS message. The bytes (or words) specified
+ * using big endian format (MSB first).
+ *
+ * - For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+ * words. Each word (30 bits) should be fit into the last 30 bits in a
+ * 4-byte word (skip B31 and B32), with MSB first, for a total of 40
+ * bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
+ *
+ * - For Glonass L1 C/A, each string contains 85 data bits, including the
+ * checksum. These bits should be fit into 11 bytes, with MSB first (skip
+ * B86-B88), covering a time period of 2 seconds.
+ *
+ * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+ * excluded). Each word should be fit into 30-bytes, with MSB first (skip
+ * B239, B240), covering a time period of 10 seconds.
+ *
+ * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+ * a total of 2x114 = 228 bits, (sync & tail excluded) that should be fit
+ * into 29 bytes, with MSB first (skip B229-B232).
+ */
+ uint8_t data[MAX_NAV_DATA_LEN];
+} gnss_nav_msg;
+
+typedef struct {
+ /** Represents latitude of the reflecting plane in degrees. */
+ double latitudeDegrees;
+
+ /** Represents longitude of the reflecting plane in degrees. */
+ double longitudeDegrees;
+
+ /**
+ * Represents altitude of the reflecting point in the plane in meters above the WGS 84 reference
+ * ellipsoid.
+ */
+ double altitudeMeters;
+
+ /** Represents azimuth clockwise from north of the reflecting plane in degrees. */
+ double azimuthDegrees;
+} reflecting_plane ;
+
+typedef struct {
+
+ /** Contains GnssSingleSatCorrectionFlags bits. */
+ uint16_t singleSatCorrectionFlags;
+
+ /**
+ * Defines the constellation of the given satellite.
+ */
+ MTK_MNLD_GnssConstellationType constellation;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ */
+ uint16_t svid;
+
+ /**
+ * Carrier frequency of the signal to be corrected, for example it can be the
+ * GPS center frequency for L1 = 1,575,420,000 Hz, varying GLO channels, etc.
+ *
+ * For a receiver with capabilities to track multiple frequencies for the same satellite,
+ * multiple corrections for the same satellite may be provided.
+ */
+ float carrierFrequencyHz;
+
+ /**
+ * The probability that the satellite is estimated to be in Line-of-Sight condition at the given
+ * location.
+ */
+ float probSatIsLos;
+
+ /**
+ * Excess path length to be subtracted from pseudorange before using it in calculating location.
+ *
+ * Note this value is NOT to be used to adjust the GnssMeasurementCallback outputs.
+ */
+ float excessPathLengthMeters;
+
+ /** Error estimate (1-sigma) for the Excess path length estimate */
+ float excessPathLengthUncertaintyMeters;
+
+ /**
+ * Defines the reflecting plane characteristics such as location and azimuth
+ *
+ * The value is only valid if HAS_REFLECTING_PLANE flag is set. An invalid reflecting plane
+ * means either reflection planes serving is not supported or the satellite signal has gone
+ * through multiple reflections.
+ */
+ reflecting_plane reflectingPlane;
+}single_sat_correction;
+
+/**
+ * A struct containing a set of measurement corrections for all used GNSS satellites at the location
+ * specified by latitudeDegrees, longitudeDegrees, altitudeMeters and at the time of week specified
+ * toaGpsNanosecondsOfWeek
+ */
+typedef struct {
+ /** Represents latitude in degrees at which the corrections are computed.. */
+ double latitudeDegrees;
+
+ /** Represents longitude in degrees at which the corrections are computed.. */
+ double longitudeDegrees;
+
+ /**
+ * Represents altitude in meters above the WGS 84 reference ellipsoid at which the corrections
+ * are computed.
+ */
+ double altitudeMeters;
+
+ /**
+ * Represents the horizontal uncertainty (68% confidence) in meters on the device position at
+ * which the corrections are provided.
+ *
+ * This value is useful for example to judge how accurate the provided corrections are.
+ */
+ double horizontalPositionUncertaintyMeters;
+
+ /**
+ * Represents the vertical uncertainty (68% confidence) in meters on the device position at
+ * which the corrections are provided.
+ *
+ * This value is useful for example to judge how accurate the provided corrections are.
+ */
+ double verticalPositionUncertaintyMeters;
+
+ /** Time Of Applicability, GPS time of week in nanoseconds. */
+ uint64_t toaGpsNanosecondsOfWeek;
+
+ /** Number of singleSatCorrection */
+ uint64_t num_satCorrection;
+
+ /**
+ * A set of SingleSatCorrection each containing measurement corrections for a satellite in view
+ */
+ single_sat_correction satCorrections[MTK_MNLD_GNSS_MAX_SVS];
+ bool hasEnvironmentBearing;
+ float environmentBearingDegrees;
+ float environmentBearingUntertaintyDegrees;
+} measurement_corrections;
+
+/**
+ * Protocol stack that is requesting the non-framework location information.
+ */
+enum {
+ /** Cellular control plane requests */
+ NFW_PS_CTRL_PLANE = 0,
+ /** All types of SUPL requests */
+ NFW_PS_SUPL = 1,
+
+ /** All types of requests from IMS */
+ NFW_PS_IMS = 10,
+ /** All types of requests from SIM */
+ NFW_PS_SIM = 11,
+
+ /** Requests from other protocol stacks */
+ NFW_PS_OTHER = 100
+};
+typedef uint8_t nfw_protocal_stack;
+
+/*
+ * Entity that is requesting/receiving the location information.
+ */
+enum { //NfwRequestor : uint8_t {
+ /** Wireless service provider */
+ NFW_REQUESTOR_CARRIER = 0,
+ /** Device manufacturer */
+ NFW_REQUESTOR_OEM = 10,
+ /** Modem chipset vendor */
+ NFW_REQUESTOR_MODEM_CHIPSET_VENDOR = 11,
+ /** GNSS chipset vendor */
+ NFW_REQUESTOR_GNSS_CHIPSET_VENDOR = 12,
+ /** Other chipset vendor */
+ NFW_REQUESTOR_OTHER_CHIPSET_VENDOR = 13,
+ /** Automobile client */
+ NFW_REQUESTOR_AUTOMOBILE_CLIENT = 20,
+ /** Other sources */
+ NFW_REQUESTOR_OTHER = 100
+ };
+typedef uint8_t nfw_requestor;
+
+/**
+ * GNSS response type for non-framework location requests.
+ */
+enum {//NfwResponseType : uint8_t {
+ /** Request rejected because framework has not given permission for this use case */
+ NFW_RESPONSE_TYPE_REJECTED = 0,
+
+ /** Request accepted but could not provide location because of a failure */
+ NFW_RESPONSE_TYPE_ACCEPTED_NO_LOCATION_PROVIDED = 1,
+
+ /** Request accepted and location provided */
+ NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED = 2,
+};
+typedef uint8_t nfw_response_type;
+
+#define MTK_MNLD_STRING_MAXLEN (256)
+/**
+ * Represents a non-framework location information request/response notification.
+ */
+typedef struct {
+ /**
+ * Package name of the Android proxy application representing the non-framework
+ * entity that requested location. Set to empty string if unknown.
+ */
+ char proxy_app_package_name[MTK_MNLD_STRING_MAXLEN];
+
+ /** Protocol stack that initiated the non-framework location request. */
+ uint8_t protocol_stack;
+
+ /**
+ * Name of the protocol stack if protocol_stack field is set to OTHER_PROTOCOL_STACK.
+ * Otherwise, set to empty string.
+ *
+ * This field is opaque to the framework and used for logging purposes.
+ */
+ char other_protocol_stack_name[MTK_MNLD_STRING_MAXLEN];
+
+ /** Source initiating/receiving the location information. */
+ uint8_t requestor;
+
+ /**
+ * Identity of the endpoint receiving the location information. For example, carrier
+ * name, OEM name, SUPL SLP/E-SLP FQDN, chipset vendor name, etc.
+ *
+ * This field is opaque to the framework and used for logging purposes.
+ */
+ char requestor_id[MTK_MNLD_STRING_MAXLEN];
+
+ /** Indicates whether location information was provided for this request. */
+ uint8_t response_type;
+
+ /** Is the device in user initiated emergency session. */
+ bool in_emergency_mode;
+
+ /** Is cached location provided */
+ bool is_cached_location;
+} nfw_notification;
+
+/*
+*mnld basic interface support capability.
+*This structure is dedicated for mnld interface's compatibility.
+*MUST upgrade this structure,if Add a new feature or upgrade an uncompatible feature
+*/
+typedef struct {
+ /*An example for initialization version*/
+ bool support_gnss;
+ /**MUST add new support capability to the end**/
+} mnl_hal_basic_client_cap;
+
+/*
+*mnld extension interface support capability.
+*This structure is dedicated for mnld interface's compatibility.
+*MUST upgrade this structure,if Add a new feature or upgrade an uncompatible feature
+*/
+typedef struct {
+ /*An example for initialization version*/
+ bool support_gnss;
+ /**MUST add new support capability to the end**/
+} mnl_hal_ext_client_cap;
+
+/*
+*mnld server support capability.
+*This structure is dedicated for mnld interface's compatibility.
+*MUST upgrade this structure,if Add a new feature or upgrade an uncompatible feature
+*/
+typedef struct {
+ /*An example for initialization version*/
+ bool support_gnss;
+ /**MUST add new support capability to the end**/
+} mnl_hal_basic_server_cap;
+
+/*
+*mnld server support capability.
+*This structure is dedicated for mnld interface's compatibility.
+*MUST upgrade this structure,if Add a new feature or upgrade an uncompatible feature
+*/
+typedef struct {
+ /*An example for initialization version*/
+ bool support_gnss;
+ /**MUST add new support capability to the end**/
+} mnl_hal_ext_server_cap;
+
+typedef unsigned int mnl_hal_agps_loc_type;
+#define MNL_HAL_AGPS_LOC_TYPE_AFLT 0 // From C2K AFLT flow
+#define MNL_HAL_AGPS_LOC_TYPE_CDMA_CELL 1 // From C2K Cell
+#define MNL_HAL_AGPS_LOC_TYPE_MOLR_BEGIN_RSP 2 // For CP MOLR after UE provides MSA result, the network will send CISS_FACILITY to provide UE a MSA location. Refer to 3GPP TS37.571-2 7.2.2.2
+#define MNL_HAL_AGPS_LOC_TYPE_SUPL_END 3 // From the SUPL END in a supl session. It may be the result of MSA, E-CID, OTDOA, or their hybrid.
+#define MNL_HAL_AGPS_LOC_TYPE_SUPL_REF_LOC 4 // For Reference Location assistance data in SUPL flow (equivalent to PMTK713 in SUPL flow)
+#define MNL_HAL_AGPS_LOC_TYPE_CP_REF_LOC 5 // For Reference Location assistance data in CP AGPS flow (equivalent to PMTK713 in CP AGPS flow)
+
+typedef struct {
+ double latitude; // Represents latitude in degrees
+ double longitude; // Represents longitude in degrees
+ char altitude_used; // 0=disabled 1=enabled
+ double altitude; // Represents altitude in meters above the WGS 84 reference
+ char speed_used; // 0=disabled 1=enabled
+ float speed; // Represents speed in meters per second
+ char bearing_used; // 0=disabled 1=enabled
+ float bearing; // Represents heading in degrees
+ char accuracy_used; // 0=disabled 1=enabled
+ float accuracy; // Represents expected accuracy in meters
+ char timestamp_used; // 0=disabled 1=enabled
+ long long timestamp; // Milliseconds since January 1, 1970
+ char type_used; // 0=disabled 1=enabled
+ mnl_hal_agps_loc_type type; // Reference location source type
+} mnl_hal_agps_location;
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/hardware/gps.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/hardware/gps.h
new file mode 100644
index 0000000..ac749c1
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/hardware/gps.h
@@ -0,0 +1,2238 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_H
+
+#ifdef __LINUX_OS__
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+
+__BEGIN_DECLS
+
+#ifndef u_char
+#define u_char unsigned char
+#endif
+
+/*
+ * Enums defined in HIDL in hardware/interfaces are auto-generated and present
+ * in gnss-base.h.
+ */
+
+/* for compatibility */
+
+/*#define GPS_REQUEST_AGPS_DATA_CONN GNSS_REQUEST_AGNSS_DATA_CONN
+#define GPS_RELEASE_AGPS_DATA_CONN GNSS_RELEASE_AGNSS_DATA_CONN
+#define GPS_AGPS_DATA_CONNECTED GNSS_AGNSS_DATA_CONNECTED
+#define GPS_AGPS_DATA_CONN_DONE GNSS_AGNSS_DATA_CONN_DONE
+#define GPS_AGPS_DATA_CONN_FAILED GNSS_AGNSS_DATA_CONN_FAILED
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_MMS AGPS_RIL_NETWORK_TYPE_MMS
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL AGPS_RIL_NETWORK_TYPE_SUPL
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN AGPS_RIL_NETWORK_TYPE_DUN
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI AGPS_RIL_NETWORK_TYPE_HIPRI
+#define AGPS_RIL_NETWORK_TTYPE_WIMAX AGPS_RIL_NETWORK_TYPE_WIMAX
+#define GNSS_MULTIPATH_INDICATOR_NOT_PRESENT GNSS_MULTIPATH_INDICATIOR_NOT_PRESENT
+#define AGPS_SETID_TYPE_MSISDN AGPS_SETID_TYPE_MSISDM
+#define GPS_MEASUREMENT_OPERATION_SUCCESS GPS_MEASUREMENT_SUCCESS
+#define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS GPS_NAVIGATION_MESSAGE_SUCCESS
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L1CA
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L2CNAV
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L5CNAV
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2 GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_CNAV2
+#define GPS_LOCATION_HAS_ACCURACY GPS_LOCATION_HAS_HORIZONTAL_ACCURACY
+*/
+/**
+ * The id of this module
+ */
+#define GPS_HARDWARE_MODULE_ID "gps"
+
+#define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS 0
+#define GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT -100
+#define GPS_NAVIGATION_MESSAGE_ERROR_GENERIC -101
+
+/** Milliseconds since January 1, 1970 */
+typedef int64_t GpsUtcTime;
+
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GPS_MAX_SVS 32
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GNSS_MAX_SVS 64
+
+/** Maximum number of Measurements in gps_measurement_callback(). */
+#define GPS_MAX_MEASUREMENT 32
+
+/** Maximum number of Measurements in gnss_measurement_callback(). */
+#define GNSS_MAX_MEASUREMENT 64
+
+/** Requested operational mode for GPS operation. */
+typedef uint32_t GpsPositionMode;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** Mode for running GPS standalone (no assistance). */
+#define GPS_POSITION_MODE_STANDALONE 0
+/** AGPS MS-Based mode. */
+#define GPS_POSITION_MODE_MS_BASED 1
+/**
+ * AGPS MS-Assisted mode. This mode is not maintained by the platform anymore.
+ * It is strongly recommended to use GPS_POSITION_MODE_MS_BASED instead.
+ */
+#define GPS_POSITION_MODE_MS_ASSISTED 2
+
+/** Requested recurrence mode for GPS operation. */
+typedef uint32_t GpsPositionRecurrence;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** Receive GPS fixes on a recurring basis at a specified period. */
+#define GPS_POSITION_RECURRENCE_PERIODIC 0
+/** Request a single shot GPS fix. */
+#define GPS_POSITION_RECURRENCE_SINGLE 1
+
+/** GPS status event values. */
+typedef uint16_t GpsStatusValue;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** GPS status unknown. */
+#define GPS_STATUS_NONE 0
+/** GPS has begun navigating. */
+#define GPS_STATUS_SESSION_BEGIN 1
+/** GPS has stopped navigating. */
+#define GPS_STATUS_SESSION_END 2
+/** GPS has powered on but is not navigating. */
+#define GPS_STATUS_ENGINE_ON 3
+/** GPS is powered off. */
+#define GPS_STATUS_ENGINE_OFF 4
+
+/** Flags to indicate which values are valid in a GpsLocation. */
+typedef uint16_t GpsLocationFlags;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** GpsLocation has valid latitude and longitude. */
+#define GPS_LOCATION_HAS_LAT_LONG 0x0001
+/** GpsLocation has valid altitude. */
+#define GPS_LOCATION_HAS_ALTITUDE 0x0002
+/** GpsLocation has valid speed. */
+#define GPS_LOCATION_HAS_SPEED 0x0004
+/** GpsLocation has valid bearing. */
+#define GPS_LOCATION_HAS_BEARING 0x0008
+/** GpsLocation has valid accuracy. */
+#define GPS_LOCATION_HAS_ACCURACY 0x0010
+
+/**
+ * GPS HAL schedules fixes for GPS_POSITION_RECURRENCE_PERIODIC mode. If this is
+ * not set, then the framework will use 1000ms for min_interval and will start
+ * and call start() and stop() to schedule the GPS.
+ */
+#define GPS_CAPABILITY_SCHEDULING (1 << 0)
+/** GPS supports MS-Based AGPS mode */
+#define GPS_CAPABILITY_MSB (1 << 1)
+/** GPS supports MS-Assisted AGPS mode */
+#define GPS_CAPABILITY_MSA (1 << 2)
+/** GPS supports single-shot fixes */
+#define GPS_CAPABILITY_SINGLE_SHOT (1 << 3)
+/** GPS supports on demand time injection */
+#define GPS_CAPABILITY_ON_DEMAND_TIME (1 << 4)
+/** GPS supports Geofencing */
+#define GPS_CAPABILITY_GEOFENCING (1 << 5)
+/** GPS supports Measurements. */
+#define GPS_CAPABILITY_MEASUREMENTS (1 << 6)
+/** GPS supports Navigation Messages */
+#define GPS_CAPABILITY_NAV_MESSAGES (1 << 7)
+
+/**
+ * Flags used to specify which aiding data to delete when calling
+ * delete_aiding_data().
+ */
+typedef uint16_t GpsAidingData;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+#define GPS_DELETE_EPHEMERIS 0x0001
+#define GPS_DELETE_ALMANAC 0x0002
+#define GPS_DELETE_POSITION 0x0004
+#define GPS_DELETE_TIME 0x0008
+#define GPS_DELETE_IONO 0x0010
+#define GPS_DELETE_UTC 0x0020
+#define GPS_DELETE_HEALTH 0x0040
+#define GPS_DELETE_SVDIR 0x0080
+#define GPS_DELETE_SVSTEER 0x0100
+#define GPS_DELETE_SADATA 0x0200
+#define GPS_DELETE_RTI 0x0400
+#define GPS_DELETE_CELLDB_INFO 0x8000
+#define GPS_DELETE_ALL 0xFFFF
+
+/** AGPS type */
+typedef uint16_t AGpsType;
+#define AGPS_TYPE_SUPL 1
+#define AGPS_TYPE_C2K 2
+
+typedef uint16_t AGpsSetIDType;
+#define AGPS_SETID_TYPE_NONE 0
+#define AGPS_SETID_TYPE_IMSI 1
+#define AGPS_SETID_TYPE_MSISDN 2
+
+typedef uint16_t ApnIpType;
+#define APN_IP_INVALID 0
+#define APN_IP_IPV4 1
+#define APN_IP_IPV6 2
+#define APN_IP_IPV4V6 3
+
+/**
+ * String length constants
+ */
+#define GPS_NI_SHORT_STRING_MAXLEN 256
+#define GPS_NI_LONG_STRING_MAXLEN 2048
+
+/**
+ * GpsNiType constants
+ */
+typedef uint32_t GpsNiType;
+#define GPS_NI_TYPE_VOICE 1
+#define GPS_NI_TYPE_UMTS_SUPL 2
+#define GPS_NI_TYPE_UMTS_CTRL_PLANE 3
+
+/**
+ * GpsNiNotifyFlags constants
+ */
+typedef uint32_t GpsNiNotifyFlags;
+/** NI requires notification */
+#define GPS_NI_NEED_NOTIFY 0x0001
+/** NI requires verification */
+#define GPS_NI_NEED_VERIFY 0x0002
+/** NI requires privacy override, no notification/minimal trace */
+#define GPS_NI_PRIVACY_OVERRIDE 0x0004
+
+/**
+ * GPS NI responses, used to define the response in
+ * NI structures
+ */
+typedef int GpsUserResponseType;
+#define GPS_NI_RESPONSE_ACCEPT 1
+#define GPS_NI_RESPONSE_DENY 2
+#define GPS_NI_RESPONSE_NORESP 3
+
+/**
+ * NI data encoding scheme
+ */
+typedef int GpsNiEncodingType;
+#define GPS_ENC_NONE 0
+#define GPS_ENC_SUPL_GSM_DEFAULT 1
+#define GPS_ENC_SUPL_UTF8 2
+#define GPS_ENC_SUPL_UCS2 3
+#define GPS_ENC_UNKNOWN -1
+
+/** AGPS status event values. */
+typedef uint16_t AGpsStatusValue;
+/** GPS requests data connection for AGPS. */
+#define GPS_REQUEST_AGPS_DATA_CONN 1
+/** GPS releases the AGPS data connection. */
+#define GPS_RELEASE_AGPS_DATA_CONN 2
+/** AGPS data connection initiated */
+#define GPS_AGPS_DATA_CONNECTED 3
+/** AGPS data connection completed */
+#define GPS_AGPS_DATA_CONN_DONE 4
+/** AGPS data connection failed */
+#define GPS_AGPS_DATA_CONN_FAILED 5
+
+typedef uint16_t AGpsRefLocationType;
+#define AGPS_REF_LOCATION_TYPE_GSM_CELLID 1
+#define AGPS_REF_LOCATION_TYPE_UMTS_CELLID 2
+#define AGPS_REF_LOCATION_TYPE_MAC 3
+#define AGPS_REF_LOCATION_TYPE_LTE_CELLID 4
+
+/* Deprecated, to be removed in the next Android release. */
+#define AGPS_REG_LOCATION_TYPE_MAC 3
+
+/** Network types for update_network_state "type" parameter */
+#define AGPS_RIL_NETWORK_TYPE_MOBILE 0
+#define AGPS_RIL_NETWORK_TYPE_WIFI 1
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_MMS 2
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL 3
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN 4
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI 5
+#define AGPS_RIL_NETWORK_TTYPE_WIMAX 6
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsClockFlags;
+#define GPS_CLOCK_HAS_LEAP_SECOND (1<<0)
+#define GPS_CLOCK_HAS_TIME_UNCERTAINTY (1<<1)
+#define GPS_CLOCK_HAS_FULL_BIAS (1<<2)
+#define GPS_CLOCK_HAS_BIAS (1<<3)
+#define GPS_CLOCK_HAS_BIAS_UNCERTAINTY (1<<4)
+#define GPS_CLOCK_HAS_DRIFT (1<<5)
+#define GPS_CLOCK_HAS_DRIFT_UNCERTAINTY (1<<6)
+
+/**
+ * Flags to indicate what fields in GnssClock are valid.
+ */
+typedef uint16_t GnssClockFlags;
+/** A valid 'leap second' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_LEAP_SECOND (1<<0)
+/** A valid 'time uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_TIME_UNCERTAINTY (1<<1)
+/** A valid 'full bias' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_FULL_BIAS (1<<2)
+/** A valid 'bias' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_BIAS (1<<3)
+/** A valid 'bias uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_BIAS_UNCERTAINTY (1<<4)
+/** A valid 'drift' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_DRIFT (1<<5)
+/** A valid 'drift uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY (1<<6)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsClockType;
+#define GPS_CLOCK_TYPE_UNKNOWN 0
+#define GPS_CLOCK_TYPE_LOCAL_HW_TIME 1
+#define GPS_CLOCK_TYPE_GPS_TIME 2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint32_t GpsMeasurementFlags;
+#define GPS_MEASUREMENT_HAS_SNR (1<<0)
+#define GPS_MEASUREMENT_HAS_ELEVATION (1<<1)
+#define GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY (1<<2)
+#define GPS_MEASUREMENT_HAS_AZIMUTH (1<<3)
+#define GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY (1<<4)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE (1<<5)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY (1<<6)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE (1<<7)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY (1<<8)
+#define GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9)
+#define GPS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12)
+#define GPS_MEASUREMENT_HAS_BIT_NUMBER (1<<13)
+#define GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT (1<<14)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT (1<<15)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY (1<<16)
+#define GPS_MEASUREMENT_HAS_USED_IN_FIX (1<<17)
+#define GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE (1<<18)
+
+/**
+ * Flags to indicate what fields in GnssMeasurement are valid.
+ */
+typedef uint32_t GnssMeasurementFlags;
+/** A valid 'snr' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_SNR (1<<0)
+/** A valid 'carrier frequency' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9)
+/** A valid 'carrier cycles' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10)
+/** A valid 'carrier phase' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11)
+/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsLossOfLock;
+#define GPS_LOSS_OF_LOCK_UNKNOWN 0
+#define GPS_LOSS_OF_LOCK_OK 1
+#define GPS_LOSS_OF_LOCK_CYCLE_SLIP 2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. Use GnssMultipathIndicator instead.
+ */
+typedef uint8_t GpsMultipathIndicator;
+#define GPS_MULTIPATH_INDICATOR_UNKNOWN 0
+#define GPS_MULTIPATH_INDICATOR_DETECTED 1
+#define GPS_MULTIPATH_INDICATOR_NOT_USED 2
+
+/**
+ * Enumeration of available values for the GNSS Measurement's multipath
+ * indicator.
+ */
+typedef uint8_t GnssMultipathIndicator;
+/** The indicator is not available or unknown. */
+#define GNSS_MULTIPATH_INDICATOR_UNKNOWN 0
+/** The measurement is indicated to be affected by multipath. */
+#define GNSS_MULTIPATH_INDICATOR_PRESENT 1
+/** The measurement is indicated to be not affected by multipath. */
+#define GNSS_MULTIPATH_INDICATOR_NOT_PRESENT 2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsMeasurementState;
+#define GPS_MEASUREMENT_STATE_UNKNOWN 0
+#define GPS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define GPS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define GPS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define GPS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+#define GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4)
+
+/**
+ * Flags indicating the GNSS measurement state.
+ *
+ * The expected behavior here is for GPS HAL to set all the flags that applies.
+ * For example, if the state for a satellite is only C/A code locked and bit
+ * synchronized, and there is still millisecond ambiguity, the state should be
+ * set as:
+ *
+ * GNSS_MEASUREMENT_STATE_CODE_LOCK | GNSS_MEASUREMENT_STATE_BIT_SYNC |
+ * GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS
+ *
+ * If GNSS is still searching for a satellite, the corresponding state should be
+ * set to GNSS_MEASUREMENT_STATE_UNKNOWN(0).
+ */
+typedef uint32_t GnssMeasurementState;
+#define GNSS_MEASUREMENT_STATE_UNKNOWN 0
+#define GNSS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define GNSS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define GNSS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+#define GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4)
+#define GNSS_MEASUREMENT_STATE_SYMBOL_SYNC (1<<5)
+#define GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC (1<<6)
+#define GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED (1<<7)
+#define GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC (1<<8)
+#define GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC (1<<9)
+#define GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK (1<<10)
+#define GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK (1<<11)
+#define GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC (1<<12)
+#define GNSS_MEASUREMENT_STATE_SBAS_SYNC (1<<13)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsAccumulatedDeltaRangeState;
+#define GPS_ADR_STATE_UNKNOWN 0
+#define GPS_ADR_STATE_VALID (1<<0)
+#define GPS_ADR_STATE_RESET (1<<1)
+#define GPS_ADR_STATE_CYCLE_SLIP (1<<2)
+
+/**
+ * Flags indicating the Accumulated Delta Range's states.
+ */
+typedef uint16_t GnssAccumulatedDeltaRangeState;
+#define GNSS_ADR_STATE_UNKNOWN 0
+#define GNSS_ADR_STATE_VALID (1<<0)
+#define GNSS_ADR_STATE_RESET (1<<1)
+#define GNSS_ADR_STATE_CYCLE_SLIP (1<<2)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsNavigationMessageType;
+#define GPS_NAVIGATION_MESSAGE_TYPE_UNKNOWN 0
+#define GPS_NAVIGATION_MESSAGE_TYPE_L1CA 1
+#define GPS_NAVIGATION_MESSAGE_TYPE_L2CNAV 2
+#define GPS_NAVIGATION_MESSAGE_TYPE_L5CNAV 3
+#define GPS_NAVIGATION_MESSAGE_TYPE_CNAV2 4
+
+/**
+ * Enumeration of available values to indicate the GNSS Navigation message
+ * types.
+ *
+ * For convenience, first byte is the GnssConstellationType on which that signal
+ * is typically transmitted
+ */
+typedef int16_t GnssNavigationMessageType;
+
+#define GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN 0
+/** GPS L1 C/A message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA 0x0101
+/** GPS L2-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV 0x0102
+/** GPS L5-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV 0x0103
+/** GPS CNAV-2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2 0x0104
+/** Glonass L1 CA message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA 0x0301
+/** Beidou D1 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1 0x0501
+/** Beidou D2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2 0x0502
+/** Galileo I/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I 0x0601
+/** Galileo F/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F 0x0602
+
+/**
+ * Status of Navigation Message
+ * When a message is received properly without any parity error in its navigation words, the
+ * status should be set to NAV_MESSAGE_STATUS_PARITY_PASSED. But if a message is received
+ * with words that failed parity check, but GPS is able to correct those words, the status
+ * should be set to NAV_MESSAGE_STATUS_PARITY_REBUILT.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+typedef uint16_t NavigationMessageStatus;
+#define NAV_MESSAGE_STATUS_UNKNOWN 0
+#define NAV_MESSAGE_STATUS_PARITY_PASSED (1<<0)
+#define NAV_MESSAGE_STATUS_PARITY_REBUILT (1<<1)
+
+/* This constant is deprecated, and will be removed in the next release. */
+#define NAV_MESSAGE_STATUS_UNKONW 0
+
+/**
+ * Flags that indicate information about the satellite
+ */
+typedef uint8_t GnssSvFlags;
+#define GNSS_SV_FLAGS_NONE 0
+#define GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA (1 << 0)
+#define GNSS_SV_FLAGS_HAS_ALMANAC_DATA (1 << 1)
+#define GNSS_SV_FLAGS_USED_IN_FIX (1 << 2)
+
+/**
+ * Constellation type of GnssSvInfo
+ */
+typedef uint8_t GnssConstellationType;
+#define GNSS_CONSTELLATION_UNKNOWN 0
+#define GNSS_CONSTELLATION_GPS 1
+#define GNSS_CONSTELLATION_SBAS 2
+#define GNSS_CONSTELLATION_GLONASS 3
+#define GNSS_CONSTELLATION_QZSS 4
+#define GNSS_CONSTELLATION_BEIDOU 5
+#define GNSS_CONSTELLATION_GALILEO 6
+
+/**
+ * Name for the GPS XTRA interface.
+ */
+#define GPS_XTRA_INTERFACE "gps-xtra"
+
+/**
+ * Name for the GPS DEBUG interface.
+ */
+#define GPS_DEBUG_INTERFACE "gps-debug"
+
+/**
+ * Name for the AGPS interface.
+ */
+#define AGPS_INTERFACE "agps"
+
+/**
+ * Name of the Supl Certificate interface.
+ */
+#define SUPL_CERTIFICATE_INTERFACE "supl-certificate"
+
+/**
+ * Name for NI interface
+ */
+#define GPS_NI_INTERFACE "gps-ni"
+
+/**
+ * Name for the AGPS-RIL interface.
+ */
+#define AGPS_RIL_INTERFACE "agps_ril"
+
+/**
+ * Name for the GPS_Geofencing interface.
+ */
+#define GPS_GEOFENCING_INTERFACE "gps_geofencing"
+
+/**
+ * Name of the GPS Measurements interface.
+ */
+#define GPS_MEASUREMENT_INTERFACE "gps_measurement"
+
+/**
+ * Name of the GPS navigation message interface.
+ */
+#define GPS_NAVIGATION_MESSAGE_INTERFACE "gps_navigation_message"
+
+/**
+ * Name of the GNSS/GPS configuration interface.
+ */
+#define GNSS_CONFIGURATION_INTERFACE "gnss_configuration"
+
+/** Represents a location. */
+typedef struct {
+ /** set to sizeof(GpsLocation) */
+ size_t size;
+ /** Contains GpsLocationFlags bits. */
+ uint16_t flags;
+ /** Represents latitude in degrees. */
+ double latitude;
+ /** Represents longitude in degrees. */
+ double longitude;
+ /**
+ * Represents altitude in meters above the WGS 84 reference ellipsoid.
+ */
+ double altitude;
+ /** Represents speed in meters per second. */
+ float speed;
+ /** Represents heading in degrees. */
+ float bearing;
+ /** Represents expected accuracy in meters. */
+ float accuracy;
+ /** Timestamp for the location fix. */
+ GpsUtcTime timestamp;
+} GpsLocation;
+
+/** Represents the status. */
+typedef struct {
+ /** set to sizeof(GpsStatus) */
+ size_t size;
+ GpsStatusValue status;
+} GpsStatus;
+
+/**
+ * Legacy struct to represents SV information.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssSvInfo instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsSvInfo) */
+ size_t size;
+ /** Pseudo-random number for the SV. */
+ int prn;
+ /** Signal to noise ratio. */
+ float snr;
+ /** Elevation of SV in degrees. */
+ float elevation;
+ /** Azimuth of SV in degrees. */
+ float azimuth;
+} GpsSvInfo;
+
+typedef struct {
+ /** set to sizeof(GnssSvInfo) */
+ size_t size;
+
+ /**
+ * Pseudo-random number for the SV, or FCN/OSN number for Glonass. The
+ * distinction is made by looking at constellation field. Values should be
+ * in the range of:
+ *
+ * - GPS: 1-32
+ * - SBAS: 120-151, 183-192
+ * - GLONASS: 1-24, the orbital slot number (OSN), if known. Or, if not:
+ * 93-106, the frequency channel number (FCN) (-7 to +6) offset by + 100
+ * i.e. report an FCN of -7 as 93, FCN of 0 as 100, and FCN of +6 as 106.
+ * - QZSS: 193-200
+ * - Galileo: 1-36
+ * - Beidou: 1-37
+ */
+ int16_t svid;
+
+ /**
+ * Defines the constellation of the given SV. Value should be one of those
+ * GNSS_CONSTELLATION_* constants
+ */
+ GnssConstellationType constellation;
+
+ /**
+ * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+ * It contains the measured C/N0 value for the signal at the antenna port.
+ *
+ * This is a mandatory value.
+ */
+ float c_n0_dbhz;
+
+ /** Elevation of SV in degrees. */
+ float elevation;
+
+ /** Azimuth of SV in degrees. */
+ float azimuth;
+
+ /**
+ * Contains additional data about the given SV. Value should be one of those
+ * GNSS_SV_FLAGS_* constants
+ */
+ GnssSvFlags flags;
+
+} GnssSvInfo;
+
+/**
+ * Legacy struct to represents SV status.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssSvStatus instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsSvStatus) */
+ size_t size;
+ int num_svs;
+ GpsSvInfo sv_list[GPS_MAX_SVS];
+ uint32_t ephemeris_mask;
+ uint32_t almanac_mask;
+ uint32_t used_in_fix_mask;
+} GpsSvStatus;
+
+/**
+ * Represents SV status.
+ */
+typedef struct {
+ /** set to sizeof(GnssSvStatus) */
+ size_t size;
+
+ /** Number of GPS SVs currently visible, refers to the SVs stored in sv_list */
+ int num_svs;
+ /**
+ * Pointer to an array of SVs information for all GNSS constellations,
+ * except GPS, which is reported using sv_list
+ */
+ GnssSvInfo gnss_sv_list[GNSS_MAX_SVS];
+
+} GnssSvStatus;
+
+/* CellID for 2G, 3G and LTE, used in AGPS. */
+typedef struct {
+ AGpsRefLocationType type;
+ /** Mobile Country Code. */
+ uint16_t mcc;
+ /** Mobile Network Code .*/
+ uint16_t mnc;
+ /** Location Area Code in 2G, 3G and LTE. In 3G lac is discarded. In LTE,
+ * lac is populated with tac, to ensure that we don't break old clients that
+ * might rely in the old (wrong) behavior.
+ */
+ uint16_t lac;
+ /** Cell id in 2G. Utran Cell id in 3G. Cell Global Id EUTRA in LTE. */
+ uint32_t cid;
+ /** Tracking Area Code in LTE. */
+ uint16_t tac;
+ /** Physical Cell id in LTE (not used in 2G and 3G) */
+ uint16_t pcid;
+} AGpsRefLocationCellID;
+
+typedef struct {
+ uint8_t mac[6];
+} AGpsRefLocationMac;
+
+/** Represents ref locations */
+typedef struct {
+ AGpsRefLocationType type;
+ union {
+ AGpsRefLocationCellID cellID;
+ AGpsRefLocationMac mac;
+ } u;
+} AGpsRefLocation;
+
+/**
+ * Callback with location information. Can only be called from a thread created
+ * by create_thread_cb.
+ */
+typedef void (* gps_location_callback)(GpsLocation* location);
+
+/**
+ * Callback with status information. Can only be called from a thread created by
+ * create_thread_cb.
+ */
+typedef void (* gps_status_callback)(GpsStatus* status);
+
+/**
+ * Legacy callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_sv_status_callback() instead.
+ */
+typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info);
+
+/**
+ * Callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* gnss_sv_status_callback)(GnssSvStatus* sv_info);
+
+/**
+ * Callback for reporting NMEA sentences. Can only be called from a thread
+ * created by create_thread_cb.
+ */
+typedef void (* gps_nmea_callback)(GpsUtcTime timestamp, const char* nmea, int length);
+
+/**
+ * Callback to inform framework of the GPS engine's capabilities. Capability
+ * parameter is a bit field of GPS_CAPABILITY_* flags.
+ */
+typedef void (* gps_set_capabilities)(uint32_t capabilities);
+
+/**
+ * Callback utility for acquiring the GPS wakelock. This can be used to prevent
+ * the CPU from suspending while handling GPS events.
+ */
+typedef void (* gps_acquire_wakelock)();
+
+/** Callback utility for releasing the GPS wakelock. */
+typedef void (* gps_release_wakelock)();
+
+/** Callback for requesting NTP time */
+typedef void (* gps_request_utc_time)();
+
+/**
+ * Callback for creating a thread that can call into the Java framework code.
+ * This must be used to create any threads that report events up to the
+ * framework.
+ */
+typedef pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg);
+
+/**
+ * Provides information about how new the underlying GPS/GNSS hardware and
+ * software is.
+ *
+ * This information will be available for Android Test Applications. If a GPS
+ * HAL does not provide this information, it will be considered "2015 or
+ * earlier".
+ *
+ * If a GPS HAL does provide this information, then newer years will need to
+ * meet newer CTS standards. E.g. if the date are 2016 or above, then N+ level
+ * GpsMeasurement support will be verified.
+ */
+typedef struct {
+ /** Set to sizeof(GnssSystemInfo) */
+ size_t size;
+ /* year in which the last update was made to the underlying hardware/firmware
+ * used to capture GNSS signals, e.g. 2016 */
+ uint16_t year_of_hw;
+} GnssSystemInfo;
+
+/**
+ * Callback to inform framework of the engine's hardware version information.
+ */
+typedef void (*gnss_set_system_info)(const GnssSystemInfo* info);
+
+/** New GPS callback structure. */
+typedef struct {
+ /** set to sizeof(GpsCallbacks) */
+ size_t size;
+ gps_location_callback location_cb;
+ gps_status_callback status_cb;
+ gps_sv_status_callback sv_status_cb;
+ gps_nmea_callback nmea_cb;
+ gps_set_capabilities set_capabilities_cb;
+ gps_acquire_wakelock acquire_wakelock_cb;
+ gps_release_wakelock release_wakelock_cb;
+ gps_create_thread create_thread_cb;
+ gps_request_utc_time request_utc_time_cb;
+
+ gnss_set_system_info set_system_info_cb;
+ gnss_sv_status_callback gnss_sv_status_cb;
+} GpsCallbacks;
+
+/** Represents the standard GPS interface. */
+typedef struct {
+ /** set to sizeof(GpsInterface) */
+ size_t size;
+ /**
+ * Opens the interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ int (*init)( GpsCallbacks* callbacks );
+
+ /** Starts navigating. */
+ int (*start)( void );
+
+ /** Stops navigating. */
+ int (*stop)( void );
+
+ /** Closes the interface. */
+ void (*cleanup)( void );
+
+ /** Injects the current time. */
+ int (*inject_time)(GpsUtcTime time, int64_t timeReference,
+ int uncertainty);
+
+ /**
+ * Injects current location from another location provider (typically cell
+ * ID). Latitude and longitude are measured in degrees expected accuracy is
+ * measured in meters
+ */
+ int (*inject_location)(double latitude, double longitude, float accuracy);
+
+ /**
+ * Specifies that the next call to start will not use the
+ * information defined in the flags. GPS_DELETE_ALL is passed for
+ * a cold start.
+ */
+ void (*delete_aiding_data)(GpsAidingData flags);
+
+ /**
+ * min_interval represents the time between fixes in milliseconds.
+ * preferred_accuracy represents the requested fix accuracy in meters.
+ * preferred_time represents the requested time to first fix in milliseconds.
+ *
+ * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASED
+ * or GPS_POSITION_MODE_STANDALONE.
+ * It is allowed by the platform (and it is recommended) to fallback to
+ * GPS_POSITION_MODE_MS_BASED if GPS_POSITION_MODE_MS_ASSISTED is passed in, and
+ * GPS_POSITION_MODE_MS_BASED is supported.
+ */
+ int (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+ uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
+
+ /** Get a pointer to extension information. */
+ const void* (*get_extension)(const char* name);
+} GpsInterface;
+
+/**
+ * Callback to request the client to download XTRA data. The client should
+ * download XTRA data and inject it by calling inject_xtra_data(). Can only be
+ * called from a thread created by create_thread_cb.
+ */
+typedef void (* gps_xtra_download_request)();
+
+/** Callback structure for the XTRA interface. */
+typedef struct {
+ gps_xtra_download_request download_request_cb;
+ gps_create_thread create_thread_cb;
+} GpsXtraCallbacks;
+
+/** Extended interface for XTRA support. */
+typedef struct {
+ /** set to sizeof(GpsXtraInterface) */
+ size_t size;
+ /**
+ * Opens the XTRA interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ int (*init)( GpsXtraCallbacks* callbacks );
+ /** Injects XTRA data into the GPS. */
+ int (*inject_xtra_data)( char* data, int length );
+} GpsXtraInterface;
+
+/** Extended interface for DEBUG support. */
+typedef struct {
+ /** set to sizeof(GpsDebugInterface) */
+ size_t size;
+
+ /**
+ * This function should return any information that the native
+ * implementation wishes to include in a bugreport.
+ */
+ size_t (*get_internal_state)(char* buffer, size_t bufferSize);
+} GpsDebugInterface;
+
+/*
+ * Represents the status of AGPS augmented to support IPv4 and IPv6.
+ */
+typedef struct {
+ /** set to sizeof(AGpsStatus) */
+ size_t size;
+
+ AGpsType type;
+ AGpsStatusValue status;
+
+ /**
+ * Must be set to a valid IPv4 address if the field 'addr' contains an IPv4
+ * address, or set to INADDR_NONE otherwise.
+ */
+ uint32_t ipaddr;
+
+ /**
+ * Must contain the IPv4 (AF_INET) or IPv6 (AF_INET6) address to report.
+ * Any other value of addr.ss_family will be rejected.
+ */
+ struct sockaddr_storage addr;
+} AGpsStatus;
+
+/**
+ * Callback with AGPS status information. Can only be called from a thread
+ * created by create_thread_cb.
+ */
+typedef void (* agps_status_callback)(AGpsStatus* status);
+
+/** Callback structure for the AGPS interface. */
+typedef struct {
+ agps_status_callback status_cb;
+ gps_create_thread create_thread_cb;
+} AGpsCallbacks;
+
+/**
+ * Extended interface for AGPS support, it is augmented to enable to pass
+ * extra APN data.
+ */
+typedef struct {
+ /** set to sizeof(AGpsInterface) */
+ size_t size;
+
+ /**
+ * Opens the AGPS interface and provides the callback routines to the
+ * implementation of this interface.
+ */
+ void (*init)(AGpsCallbacks* callbacks);
+ /**
+ * Deprecated.
+ * If the HAL supports AGpsInterface_v2 this API will not be used, see
+ * data_conn_open_with_apn_ip_type for more information.
+ */
+ int (*data_conn_open)(const char* apn);
+ /**
+ * Notifies that the AGPS data connection has been closed.
+ */
+ int (*data_conn_closed)();
+ /**
+ * Notifies that a data connection is not available for AGPS.
+ */
+ int (*data_conn_failed)();
+ /**
+ * Sets the hostname and port for the AGPS server.
+ */
+ int (*set_server)(AGpsType type, const char* hostname, int port);
+
+ /**
+ * Notifies that a data connection is available and sets the name of the
+ * APN, and its IP type, to be used for SUPL connections.
+ */
+ int (*data_conn_open_with_apn_ip_type)(
+ const char* apn,
+ ApnIpType apnIpType);
+} AGpsInterface;
+
+/** Error codes associated with certificate operations */
+#define AGPS_CERTIFICATE_OPERATION_SUCCESS 0
+#define AGPS_CERTIFICATE_ERROR_GENERIC -100
+#define AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES -101
+
+/** A data structure that represents an X.509 certificate using DER encoding */
+typedef struct {
+ size_t length;
+ u_char* data;
+} DerEncodedCertificate;
+
+/**
+ * A type definition for SHA1 Fingerprints used to identify X.509 Certificates
+ * The Fingerprint is a digest of the DER Certificate that uniquely identifies it.
+ */
+typedef struct {
+ u_char data[20];
+} Sha1CertificateFingerprint;
+
+/** AGPS Interface to handle SUPL certificate operations */
+typedef struct {
+ /** set to sizeof(SuplCertificateInterface) */
+ size_t size;
+
+ /**
+ * Installs a set of Certificates used for SUPL connections to the AGPS server.
+ * If needed the HAL should find out internally any certificates that need to be removed to
+ * accommodate the certificates to install.
+ * The certificates installed represent a full set of valid certificates needed to connect to
+ * AGPS SUPL servers.
+ * The list of certificates is required, and all must be available at the same time, when trying
+ * to establish a connection with the AGPS Server.
+ *
+ * Parameters:
+ * certificates - A pointer to an array of DER encoded certificates that are need to be
+ * installed in the HAL.
+ * length - The number of certificates to install.
+ * Returns:
+ * AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully
+ * AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES if the HAL cannot store the number of
+ * certificates attempted to be installed, the state of the certificates stored should
+ * remain the same as before on this error case.
+ *
+ * IMPORTANT:
+ * If needed the HAL should find out internally the set of certificates that need to be
+ * removed to accommodate the certificates to install.
+ */
+ int (*install_certificates) ( const DerEncodedCertificate* certificates, size_t length );
+
+ /**
+ * Notifies the HAL that a list of certificates used for SUPL connections are revoked. It is
+ * expected that the given set of certificates is removed from the internal store of the HAL.
+ *
+ * Parameters:
+ * fingerprints - A pointer to an array of SHA1 Fingerprints to identify the set of
+ * certificates to revoke.
+ * length - The number of fingerprints provided.
+ * Returns:
+ * AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully.
+ *
+ * IMPORTANT:
+ * If any of the certificates provided (through its fingerprint) is not known by the HAL,
+ * it should be ignored and continue revoking/deleting the rest of them.
+ */
+ int (*revoke_certificates) ( const Sha1CertificateFingerprint* fingerprints, size_t length );
+} SuplCertificateInterface;
+
+/** Represents an NI request */
+typedef struct {
+ /** set to sizeof(GpsNiNotification) */
+ size_t size;
+
+ /**
+ * An ID generated by HAL to associate NI notifications and UI
+ * responses
+ */
+ int notification_id;
+
+ /**
+ * An NI type used to distinguish different categories of NI
+ * events, such as GPS_NI_TYPE_VOICE, GPS_NI_TYPE_UMTS_SUPL, ...
+ */
+ GpsNiType ni_type;
+
+ /**
+ * Notification/verification options, combinations of GpsNiNotifyFlags constants
+ */
+ GpsNiNotifyFlags notify_flags;
+
+ /**
+ * Timeout period to wait for user response.
+ * Set to 0 for no time out limit.
+ */
+ int timeout;
+
+ /**
+ * Default response when time out.
+ */
+ GpsUserResponseType default_response;
+
+ /**
+ * Requestor ID
+ */
+ char requestor_id[GPS_NI_SHORT_STRING_MAXLEN];
+
+ /**
+ * Notification message. It can also be used to store client_id in some cases
+ */
+ char text[GPS_NI_LONG_STRING_MAXLEN];
+
+ /**
+ * Client name decoding scheme
+ */
+ GpsNiEncodingType requestor_id_encoding;
+
+ /**
+ * Client name decoding scheme
+ */
+ GpsNiEncodingType text_encoding;
+
+ /**
+ * A pointer to extra data. Format:
+ * key_1 = value_1
+ * key_2 = value_2
+ */
+ char extras[GPS_NI_LONG_STRING_MAXLEN];
+
+} GpsNiNotification;
+
+/**
+ * Callback with NI notification. Can only be called from a thread created by
+ * create_thread_cb.
+ */
+typedef void (*gps_ni_notify_callback)(GpsNiNotification *notification);
+
+/** GPS NI callback structure. */
+typedef struct
+{
+ /**
+ * Sends the notification request from HAL to GPSLocationProvider.
+ */
+ gps_ni_notify_callback notify_cb;
+ gps_create_thread create_thread_cb;
+} GpsNiCallbacks;
+
+/**
+ * Extended interface for Network-initiated (NI) support.
+ */
+typedef struct
+{
+ /** set to sizeof(GpsNiInterface) */
+ size_t size;
+
+ /** Registers the callbacks for HAL to use. */
+ void (*init) (GpsNiCallbacks *callbacks);
+
+ /** Sends a response to HAL. */
+ void (*respond) (int notif_id, GpsUserResponseType user_response);
+} GpsNiInterface;
+
+#if defined(__ANDROID_OS__)
+struct gps_device_t {
+ struct hw_device_t common;
+
+ /**
+ * Set the provided lights to the provided values.
+ *
+ * Returns: 0 on succes, error code on failure.
+ */
+ const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);
+};
+#elif defined(__LINUX_OS__)
+struct gps_device_t {
+ const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);
+};
+#endif
+
+#define AGPS_RIL_REQUEST_REFLOC_CELLID (1<<0L)
+#define AGPS_RIL_REQUEST_REFLOC_MAC (1<<1L)
+
+typedef void (*agps_ril_request_set_id)(uint32_t flags);
+typedef void (*agps_ril_request_ref_loc)(uint32_t flags);
+
+typedef struct {
+ agps_ril_request_set_id request_setid;
+ agps_ril_request_ref_loc request_refloc;
+ gps_create_thread create_thread_cb;
+} AGpsRilCallbacks;
+
+/** Extended interface for AGPS_RIL support. */
+typedef struct {
+ /** set to sizeof(AGpsRilInterface) */
+ size_t size;
+ /**
+ * Opens the AGPS interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ void (*init)( AGpsRilCallbacks* callbacks );
+
+ /**
+ * Sets the reference location.
+ */
+ void (*set_ref_location) (const AGpsRefLocation *agps_reflocation, size_t sz_struct);
+ /**
+ * Sets the set ID.
+ */
+ void (*set_set_id) (AGpsSetIDType type, const char* setid);
+
+ /**
+ * Send network initiated message.
+ */
+ void (*ni_message) (uint8_t *msg, size_t len);
+
+ /**
+ * Notify GPS of network status changes.
+ * These parameters match values in the android.net.NetworkInfo class.
+ */
+ void (*update_network_state) (int connected, int type, int roaming, const char* extra_info);
+
+ /**
+ * Notify GPS of network status changes.
+ * These parameters match values in the android.net.NetworkInfo class.
+ */
+ void (*update_network_availability) (int avaiable, const char* apn);
+} AGpsRilInterface;
+
+/**
+ * GPS Geofence.
+ * There are 3 states associated with a Geofence: Inside, Outside, Unknown.
+ * There are 3 transitions: ENTERED, EXITED, UNCERTAIN.
+ *
+ * An example state diagram with confidence level: 95% and Unknown time limit
+ * set as 30 secs is shown below. (confidence level and Unknown time limit are
+ * explained latter)
+ * ____________________________
+ * | Unknown (30 secs) |
+ * """"""""""""""""""""""""""""
+ * ^ | | ^
+ * UNCERTAIN| |ENTERED EXITED| |UNCERTAIN
+ * | v v |
+ * ________ EXITED _________
+ * | Inside | -----------> | Outside |
+ * | | <----------- | |
+ * """""""" ENTERED """""""""
+ *
+ * Inside state: We are 95% confident that the user is inside the geofence.
+ * Outside state: We are 95% confident that the user is outside the geofence
+ * Unknown state: Rest of the time.
+ *
+ * The Unknown state is better explained with an example:
+ *
+ * __________
+ * | c|
+ * | ___ | _______
+ * | |a| | | b |
+ * | """ | """""""
+ * | |
+ * """"""""""
+ * In the diagram above, "a" and "b" are 2 geofences and "c" is the accuracy
+ * circle reported by the GPS subsystem. Now with regard to "b", the system is
+ * confident that the user is outside. But with regard to "a" is not confident
+ * whether it is inside or outside the geofence. If the accuracy remains the
+ * same for a sufficient period of time, the UNCERTAIN transition would be
+ * triggered with the state set to Unknown. If the accuracy improves later, an
+ * appropriate transition should be triggered. This "sufficient period of time"
+ * is defined by the parameter in the add_geofence_area API.
+ * In other words, Unknown state can be interpreted as a state in which the
+ * GPS subsystem isn't confident enough that the user is either inside or
+ * outside the Geofence. It moves to Unknown state only after the expiry of the
+ * timeout.
+ *
+ * The geofence callback needs to be triggered for the ENTERED and EXITED
+ * transitions, when the GPS system is confident that the user has entered
+ * (Inside state) or exited (Outside state) the Geofence. An implementation
+ * which uses a value of 95% as the confidence is recommended. The callback
+ * should be triggered only for the transitions requested by the
+ * add_geofence_area call.
+ *
+ * Even though the diagram and explanation talks about states and transitions,
+ * the callee is only interested in the transistions. The states are mentioned
+ * here for illustrative purposes.
+ *
+ * Startup Scenario: When the device boots up, if an application adds geofences,
+ * and then we get an accurate GPS location fix, it needs to trigger the
+ * appropriate (ENTERED or EXITED) transition for every Geofence it knows about.
+ * By default, all the Geofences will be in the Unknown state.
+ *
+ * When the GPS system is unavailable, gps_geofence_status_callback should be
+ * called to inform the upper layers of the same. Similarly, when it becomes
+ * available the callback should be called. This is a global state while the
+ * UNKNOWN transition described above is per geofence.
+ *
+ * An important aspect to note is that users of this API (framework), will use
+ * other subsystems like wifi, sensors, cell to handle Unknown case and
+ * hopefully provide a definitive state transition to the third party
+ * application. GPS Geofence will just be a signal indicating what the GPS
+ * subsystem knows about the Geofence.
+ *
+ */
+#define GPS_GEOFENCE_ENTERED (1<<0L)
+#define GPS_GEOFENCE_EXITED (1<<1L)
+#define GPS_GEOFENCE_UNCERTAIN (1<<2L)
+
+#define GPS_GEOFENCE_UNAVAILABLE (1<<0L)
+#define GPS_GEOFENCE_AVAILABLE (1<<1L)
+
+#define GPS_GEOFENCE_OPERATION_SUCCESS 0
+#define GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES -100
+#define GPS_GEOFENCE_ERROR_ID_EXISTS -101
+#define GPS_GEOFENCE_ERROR_ID_UNKNOWN -102
+#define GPS_GEOFENCE_ERROR_INVALID_TRANSITION -103
+#define GPS_GEOFENCE_ERROR_GENERIC -149
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ * geofence_id - The id associated with the add_geofence_area.
+ * location - The current GPS location.
+ * transition - Can be one of GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED,
+ * GPS_GEOFENCE_UNCERTAIN.
+ * timestamp - Timestamp when the transition was detected.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the GPS
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*gps_geofence_transition_callback) (int32_t geofence_id, GpsLocation* location,
+ int32_t transition, GpsUtcTime timestamp);
+
+/**
+ * The callback associated with the availability of the GPS system for geofencing
+ * monitoring. If the GPS system determines that it cannot monitor geofences
+ * because of lack of reliability or unavailability of the GPS signals, it will
+ * call this callback with GPS_GEOFENCE_UNAVAILABLE parameter.
+ *
+ * Parameters:
+ * status - GPS_GEOFENCE_UNAVAILABLE or GPS_GEOFENCE_AVAILABLE.
+ * last_location - Last known location.
+ */
+typedef void (*gps_geofence_status_callback) (int32_t status, GpsLocation* last_location);
+
+/**
+ * The callback associated with the add_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ * GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES - geofence limit has been reached.
+ * GPS_GEOFENCE_ERROR_ID_EXISTS - geofence with id already exists
+ * GPS_GEOFENCE_ERROR_INVALID_TRANSITION - the monitorTransition contains an
+ * invalid transition
+ * GPS_GEOFENCE_ERROR_GENERIC - for other errors.
+ */
+typedef void (*gps_geofence_add_callback) (int32_t geofence_id, int32_t status);
+
+/**
+ * The callback associated with the remove_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ * GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ * GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_remove_callback) (int32_t geofence_id, int32_t status);
+
+
+/**
+ * The callback associated with the pause_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ * GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ * GPS_GEOFENCE_ERROR_INVALID_TRANSITION -
+ * when monitor_transitions is invalid
+ * GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_pause_callback) (int32_t geofence_id, int32_t status);
+
+/**
+ * The callback associated with the resume_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ * GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ * GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_resume_callback) (int32_t geofence_id, int32_t status);
+
+typedef struct {
+ gps_geofence_transition_callback geofence_transition_callback;
+ gps_geofence_status_callback geofence_status_callback;
+ gps_geofence_add_callback geofence_add_callback;
+ gps_geofence_remove_callback geofence_remove_callback;
+ gps_geofence_pause_callback geofence_pause_callback;
+ gps_geofence_resume_callback geofence_resume_callback;
+ gps_create_thread create_thread_cb;
+} GpsGeofenceCallbacks;
+
+/** Extended interface for GPS_Geofencing support */
+typedef struct {
+ /** set to sizeof(GpsGeofencingInterface) */
+ size_t size;
+
+ /**
+ * Opens the geofence interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ void (*init)( GpsGeofenceCallbacks* callbacks );
+
+ /**
+ * Add a geofence area. This api currently supports circular geofences.
+ * Parameters:
+ * geofence_id - The id for the geofence. If a geofence with this id
+ * already exists, an error value (GPS_GEOFENCE_ERROR_ID_EXISTS)
+ * should be returned.
+ * latitude, longtitude, radius_meters - The lat, long and radius
+ * (in meters) for the geofence
+ * last_transition - The current state of the geofence. For example, if
+ * the system already knows that the user is inside the geofence,
+ * this will be set to GPS_GEOFENCE_ENTERED. In most cases, it
+ * will be GPS_GEOFENCE_UNCERTAIN.
+ * monitor_transition - Which transitions to monitor. Bitwise OR of
+ * GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+ * GPS_GEOFENCE_UNCERTAIN.
+ * notification_responsiveness_ms - Defines the best-effort description
+ * of how soon should the callback be called when the transition
+ * associated with the Geofence is triggered. For instance, if set
+ * to 1000 millseconds with GPS_GEOFENCE_ENTERED, the callback
+ * should be called 1000 milliseconds within entering the geofence.
+ * This parameter is defined in milliseconds.
+ * NOTE: This is not to be confused with the rate that the GPS is
+ * polled at. It is acceptable to dynamically vary the rate of
+ * sampling the GPS for power-saving reasons; thus the rate of
+ * sampling may be faster or slower than this.
+ * unknown_timer_ms - The time limit after which the UNCERTAIN transition
+ * should be triggered. This parameter is defined in milliseconds.
+ * See above for a detailed explanation.
+ */
+ void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude,
+ double radius_meters, int last_transition, int monitor_transitions,
+ int notification_responsiveness_ms, int unknown_timer_ms);
+
+ /**
+ * Pause monitoring a particular geofence.
+ * Parameters:
+ * geofence_id - The id for the geofence.
+ */
+ void (*pause_geofence) (int32_t geofence_id);
+
+ /**
+ * Resume monitoring a particular geofence.
+ * Parameters:
+ * geofence_id - The id for the geofence.
+ * monitor_transitions - Which transitions to monitor. Bitwise OR of
+ * GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+ * GPS_GEOFENCE_UNCERTAIN.
+ * This supersedes the value associated provided in the
+ * add_geofence_area call.
+ */
+ void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+ /**
+ * Remove a geofence area. After the function returns, no notifications
+ * should be sent.
+ * Parameter:
+ * geofence_id - The id for the geofence.
+ */
+ void (*remove_geofence_area) (int32_t geofence_id);
+} GpsGeofencingInterface;
+
+/**
+ * Legacy struct to represent an estimate of the GPS clock time.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssClock instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsClock) */
+ size_t size;
+ GpsClockFlags flags;
+ int16_t leap_second;
+ GpsClockType type;
+ int64_t time_ns;
+ double time_uncertainty_ns;
+ int64_t full_bias_ns;
+ double bias_ns;
+ double bias_uncertainty_ns;
+ double drift_nsps;
+ double drift_uncertainty_nsps;
+} GpsClock;
+
+/**
+ * Represents an estimate of the GPS clock time.
+ */
+typedef struct {
+ /** set to sizeof(GnssClock) */
+ size_t size;
+
+ /**
+ * A set of flags indicating the validity of the fields in this data
+ * structure.
+ */
+ GnssClockFlags flags;
+
+ /**
+ * Leap second data.
+ * The sign of the value is defined by the following equation:
+ * utc_time_ns = time_ns - (full_bias_ns + bias_ns) - leap_second *
+ * 1,000,000,000
+ *
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_LEAP_SECOND.
+ */
+ int16_t leap_second;
+
+ /**
+ * The GNSS receiver internal clock value. This is the local hardware clock
+ * value.
+ *
+ * For local hardware clock, this value is expected to be monotonically
+ * increasing while the hardware clock remains power on. (For the case of a
+ * HW clock that is not continuously on, see the
+ * hw_clock_discontinuity_count field). The receiver's estimate of GPS time
+ * can be derived by substracting the sum of full_bias_ns and bias_ns (when
+ * available) from this value.
+ *
+ * This GPS time is expected to be the best estimate of current GPS time
+ * that GNSS receiver can achieve.
+ *
+ * Sub-nanosecond accuracy can be provided by means of the 'bias_ns' field.
+ * The value contains the 'time uncertainty' in it.
+ *
+ * This field is mandatory.
+ */
+ int64_t time_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_CLOCK_HAS_TIME_UNCERTAINTY. This value is effectively zero (it is
+ * the reference local clock, by which all other times and time
+ * uncertainties are measured.) (And thus this field can be not provided,
+ * per GNSS_CLOCK_HAS_TIME_UNCERTAINTY flag, or provided & set to 0.)
+ */
+ double time_uncertainty_ns;
+
+ /**
+ * The difference between hardware clock ('time' field) inside GPS receiver
+ * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
+ *
+ * The sign of the value is defined by the following equation:
+ * local estimate of GPS time = time_ns - (full_bias_ns + bias_ns)
+ *
+ * This value is mandatory if the receiver has estimated GPS time. If the
+ * computed time is for a non-GPS constellation, the time offset of that
+ * constellation to GPS has to be applied to fill this value. The error
+ * estimate for the sum of this and the bias_ns is the bias_uncertainty_ns,
+ * and the caller is responsible for using this uncertainty (it can be very
+ * large before the GPS time has been solved for.) If the data is available
+ * 'flags' must contain GNSS_CLOCK_HAS_FULL_BIAS.
+ */
+ int64_t full_bias_ns;
+
+ /**
+ * Sub-nanosecond bias.
+ * The error estimate for the sum of this and the full_bias_ns is the
+ * bias_uncertainty_ns
+ *
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_BIAS. If GPS
+ * has computed a position fix. This value is mandatory if the receiver has
+ * estimated GPS time.
+ */
+ double bias_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the local estimate of GPS time (clock
+ * bias) in nanoseconds. The uncertainty is represented as an absolute
+ * (single sided) value.
+ *
+ * If the data is available 'flags' must contain
+ * GNSS_CLOCK_HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+ * has estimated GPS time.
+ */
+ double bias_uncertainty_ns;
+
+ /**
+ * The clock's drift in nanoseconds (per second).
+ *
+ * A positive value means that the frequency is higher than the nominal
+ * frequency, and that the (full_bias_ns + bias_ns) is growing more positive
+ * over time.
+ *
+ * The value contains the 'drift uncertainty' in it.
+ * If the data is available 'flags' must contain GNSS_CLOCK_HAS_DRIFT.
+ *
+ * This value is mandatory if the receiver has estimated GNSS time
+ */
+ double drift_nsps;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available 'flags' must contain
+ * GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY. If GPS has computed a position fix this
+ * field is mandatory and must be populated.
+ */
+ double drift_uncertainty_nsps;
+
+ /**
+ * When there are any discontinuities in the HW clock, this field is
+ * mandatory.
+ *
+ * A "discontinuity" is meant to cover the case of a switch from one source
+ * of clock to another. A single free-running crystal oscillator (XO)
+ * should generally not have any discontinuities, and this can be set and
+ * left at 0.
+ *
+ * If, however, the time_ns value (HW clock) is derived from a composite of
+ * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+ * restarted, then this value shall be incremented each time a discontinuity
+ * occurs. (E.g. this value may start at zero at device boot-up and
+ * increment each time there is a change in clock continuity. In the
+ * unlikely event that this value reaches full scale, rollover (not
+ * clamping) is required, such that this value continues to change, during
+ * subsequent discontinuity events.)
+ *
+ * While this number stays the same, between GnssClock reports, it can be
+ * safely assumed that the time_ns value has been running continuously, e.g.
+ * derived from a single, high quality clock (XO like, or better, that's
+ * typically used during continuous GNSS signal sampling.)
+ *
+ * It is expected, esp. during periods where there are few GNSS signals
+ * available, that the HW clock be discontinuity-free as long as possible,
+ * as this avoids the need to use (waste) a GNSS measurement to fully
+ * re-solve for the GPS clock bias and drift, when using the accompanying
+ * measurements, from consecutive GnssData reports.
+ */
+ uint32_t hw_clock_discontinuity_count;
+
+} GnssClock;
+
+/**
+ * Legacy struct to represent a GPS Measurement, it contains raw and computed
+ * information.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssMeasurement instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsMeasurement) */
+ size_t size;
+ GpsMeasurementFlags flags;
+ int8_t prn;
+ double time_offset_ns;
+ GpsMeasurementState state;
+ int64_t received_gps_tow_ns;
+ int64_t received_gps_tow_uncertainty_ns;
+ double c_n0_dbhz;
+ double pseudorange_rate_mps;
+ double pseudorange_rate_uncertainty_mps;
+ GpsAccumulatedDeltaRangeState accumulated_delta_range_state;
+ double accumulated_delta_range_m;
+ double accumulated_delta_range_uncertainty_m;
+ double pseudorange_m;
+ double pseudorange_uncertainty_m;
+ double code_phase_chips;
+ double code_phase_uncertainty_chips;
+ float carrier_frequency_hz;
+ int64_t carrier_cycles;
+ double carrier_phase;
+ double carrier_phase_uncertainty;
+ GpsLossOfLock loss_of_lock;
+ int32_t bit_number;
+ int16_t time_from_last_bit_ms;
+ double doppler_shift_hz;
+ double doppler_shift_uncertainty_hz;
+ GpsMultipathIndicator multipath_indicator;
+ double snr_db;
+ double elevation_deg;
+ double elevation_uncertainty_deg;
+ double azimuth_deg;
+ double azimuth_uncertainty_deg;
+ bool used_in_fix;
+} GpsMeasurement;
+
+/**
+ * Represents a GNSS Measurement, it contains raw and computed information.
+ *
+ * Independence - All signal measurement information (e.g. sv_time,
+ * pseudorange_rate, multipath_indicator) reported in this struct should be
+ * based on GNSS signal measurements only. You may not synthesize measurements
+ * by calculating or reporting expected measurements based on known or estimated
+ * position, velocity, or time.
+ */
+typedef struct {
+ /** set to sizeof(GpsMeasurement) */
+ size_t size;
+
+ /** A set of flags indicating the validity of the fields in this data structure. */
+ GnssMeasurementFlags flags;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ * This is a mandatory value.
+ */
+ int16_t svid;
+
+ /**
+ * Defines the constellation of the given SV. Value should be one of those
+ * GNSS_CONSTELLATION_* constants
+ */
+ GnssConstellationType constellation;
+
+ /**
+ * Time offset at which the measurement was taken in nanoseconds.
+ * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+ * interpreted in the same way as indicated by GpsClock::type.
+ *
+ * The sign of time_offset_ns is given by the following equation:
+ * measurement time = GpsClock::time_ns + time_offset_ns
+ *
+ * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+ * This is a mandatory value.
+ */
+ double time_offset_ns;
+
+ /**
+ * Per satellite sync state. It represents the current sync state for the associated satellite.
+ * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+ *
+ * This is a mandatory value.
+ */
+ GnssMeasurementState state;
+
+ /**
+ * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+ * Ensure that this field is independent (see comment at top of
+ * GnssMeasurement struct.)
+ *
+ * For GPS & QZSS, this is:
+ * Received GPS Time-of-Week at the measurement time, in nanoseconds.
+ * The value is relative to the beginning of the current GPS week.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range
+ * for this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync : [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe sync : [ 0 6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * TOW decoded : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * Note well: if there is any ambiguity in integer millisecond,
+ * GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+ *
+ * This value must be populated if 'state' != GNSS_MEASUREMENT_STATE_UNKNOWN.
+ *
+ * For Glonass, this is:
+ * Received Glonass time of day, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 10ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+ * Bit sync : [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * String sync : [ 0 2s ] : GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC is set
+ * Time of day : [ 0 1day ] : GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED is set
+ *
+ * For Beidou, this is:
+ * Received Beidou time of week, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync (D2): [ 0 2ms ] : GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC is set
+ * Bit sync (D1): [ 0 20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe (D2): [ 0 0.6s ] : GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC is set
+ * Subframe (D1): [ 0 6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * Time of week : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * For Galileo, this is:
+ * Received Galileo time of week, at the measurement time in nanoseconds.
+ *
+ * E1BC code lock : [ 0 4ms ] : GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK is set
+ * E1C 2nd code lock: [ 0 100ms ] :
+ * GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is set
+ *
+ * E1B page : [ 0 2s ] : GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC is set
+ * Time of week: [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * For SBAS, this is:
+ * Received SBAS time, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite,
+ * valid range for this field can be:
+ * Searching : [ 0 ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 2ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+ * Message : [ 0 1s ] : GNSS_MEASUREMENT_STATE_SBAS_SYNC is set
+ */
+ int64_t received_sv_time_in_ns;
+
+ /**
+ * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+ *
+ * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+ */
+ int64_t received_sv_time_uncertainty_in_ns;
+
+ /**
+ * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+ * It contains the measured C/N0 value for the signal at the antenna port.
+ *
+ * This is a mandatory value.
+ */
+ double c_n0_dbhz;
+
+ /**
+ * Pseudorange rate at the timestamp in m/s. The correction of a given
+ * Pseudorange Rate value includes corrections for receiver and satellite
+ * clock frequency errors. Ensure that this field is independent (see
+ * comment at top of GnssMeasurement struct.)
+ *
+ * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
+ * 'drift' field as well (When providing the uncorrected pseudorange rate, do not apply the
+ * corrections described above.)
+ *
+ * The value includes the 'pseudorange rate uncertainty' in it.
+ * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler
+ * shift' is given by the equation:
+ * pseudorange rate = -k * doppler shift (where k is a constant)
+ *
+ * This should be the most accurate pseudorange rate available, based on
+ * fresh signal measurements from this channel.
+ *
+ * It is mandatory that this value be provided at typical carrier phase PRR
+ * quality (few cm/sec per second of uncertainty, or better) - when signals
+ * are sufficiently strong & stable, e.g. signals from a GPS simulator at >=
+ * 35 dB-Hz.
+ */
+ double pseudorange_rate_mps;
+
+ /**
+ * 1-Sigma uncertainty of the pseudorange_rate_mps.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * This is a mandatory value.
+ */
+ double pseudorange_rate_uncertainty_mps;
+
+ /**
+ * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+ * (indicating loss of lock).
+ *
+ * This is a mandatory value.
+ */
+ GnssAccumulatedDeltaRangeState accumulated_delta_range_state;
+
+ /**
+ * Accumulated delta range since the last channel reset in meters.
+ * A positive value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+ * is given by the equation:
+ * accumulated delta range = -k * carrier phase (where k is a constant)
+ *
+ * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ * However, it is expected that the data is only accurate when:
+ * 'accumulated delta range state' == GPS_ADR_STATE_VALID.
+ */
+ double accumulated_delta_range_m;
+
+ /**
+ * 1-Sigma uncertainty of the accumulated delta range in meters.
+ * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+ */
+ double accumulated_delta_range_uncertainty_m;
+
+ /**
+ * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+ * If the field is not set, the carrier frequency is assumed to be L1.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+ */
+ float carrier_frequency_hz;
+
+ /**
+ * The number of full carrier cycles between the satellite and the receiver.
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * Indications of possible cycle slips and resets in the accumulation of
+ * this value can be inferred from the accumulated_delta_range_state flags.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
+ */
+ int64_t carrier_cycles;
+
+ /**
+ * The RF phase detected by the receiver, in the range [0.0, 1.0].
+ * This is usually the fractional part of the complete carrier phase measurement.
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'carrier-phase uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_PHASE.
+ */
+ double carrier_phase;
+
+ /**
+ * 1-Sigma uncertainty of the carrier-phase.
+ * If the data is available, 'flags' must contain
+ * GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+ */
+ double carrier_phase_uncertainty;
+
+ /**
+ * An enumeration that indicates the 'multipath' state of the event.
+ *
+ * The multipath Indicator is intended to report the presence of overlapping
+ * signals that manifest as distorted correlation peaks.
+ *
+ * - if there is a distorted correlation peak shape, report that multipath
+ * is GNSS_MULTIPATH_INDICATOR_PRESENT.
+ * - if there is not a distorted correlation peak shape, report
+ * GNSS_MULTIPATH_INDICATOR_NOT_PRESENT
+ * - if signals are too weak to discern this information, report
+ * GNSS_MULTIPATH_INDICATOR_UNKNOWN
+ *
+ * Example: when doing the standardized overlapping Multipath Performance
+ * test (3GPP TS 34.171) the Multipath indicator should report
+ * GNSS_MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+ * contain multipath, and GNSS_MULTIPATH_INDICATOR_NOT_PRESENT for those
+ * signals that are tracked and do not contain multipath.
+ */
+ GnssMultipathIndicator multipath_indicator;
+
+ /**
+ * Signal-to-noise ratio at correlator output in dB.
+ * If the data is available, 'flags' must contain GNSS_MEASUREMENT_HAS_SNR.
+ * This is the power ratio of the "correlation peak height above the
+ * observed noise floor" to "the noise RMS".
+ */
+ double snr_db;
+} GnssMeasurement;
+
+/**
+ * Legacy struct to represents a reading of GPS measurements.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssData instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsData) */
+ size_t size;
+ size_t measurement_count;
+ GpsMeasurement measurements[GPS_MAX_MEASUREMENT];
+
+ /** The GPS clock time reading. */
+ GpsClock clock;
+} GpsData;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+ /** set to sizeof(GnssData) */
+ size_t size;
+
+ /** Number of measurements. */
+ size_t measurement_count;
+
+ /** The array of measurements. */
+ GnssMeasurement measurements[GNSS_MAX_MEASUREMENT];
+
+ /** The GPS clock time reading. */
+ GnssClock clock;
+} GnssData;
+
+/**
+ * The legacy callback for to report measurements from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_measurement_callback() instead.
+ *
+ * Parameters:
+ * data - A data structure containing the measurements.
+ */
+typedef void (*gps_measurement_callback) (GpsData* data);
+
+/**
+ * The callback for to report measurements from the HAL.
+ *
+ * Parameters:
+ * data - A data structure containing the measurements.
+ */
+typedef void (*gnss_measurement_callback) (GnssData* data);
+
+typedef struct {
+ /** set to sizeof(GpsMeasurementCallbacks) */
+ size_t size;
+ gps_measurement_callback measurement_callback;
+ gnss_measurement_callback gnss_measurement_callback;
+} GpsMeasurementCallbacks;
+
+/**
+ * Extended interface for GPS Measurements support.
+ */
+typedef struct {
+ /** Set to sizeof(GpsMeasurementInterface) */
+ size_t size;
+
+ /**
+ * Initializes the interface and registers the callback routines with the HAL.
+ * After a successful call to 'init' the HAL must begin to provide updates at its own phase.
+ *
+ * Status:
+ * GPS_MEASUREMENT_OPERATION_SUCCESS
+ * GPS_MEASUREMENT_ERROR_ALREADY_INIT - if a callback has already been registered without a
+ * corresponding call to 'close'
+ * GPS_MEASUREMENT_ERROR_GENERIC - if any other error occurred, it is expected that the HAL
+ * will not generate any updates upon returning this error code.
+ */
+ int (*init) (GpsMeasurementCallbacks* callbacks);
+
+ /**
+ * Stops updates from the HAL, and unregisters the callback routines.
+ * After a call to stop, the previously registered callbacks must be considered invalid by the
+ * HAL.
+ * If stop is invoked without a previous 'init', this function should perform no work.
+ */
+ void (*close) ();
+
+} GpsMeasurementInterface;
+
+/**
+ * Legacy struct to represents a GPS navigation message (or a fragment of it).
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssNavigationMessage instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsNavigationMessage) */
+ size_t size;
+ int8_t prn;
+ GpsNavigationMessageType type;
+ NavigationMessageStatus status;
+ int16_t message_id;
+ int16_t submessage_id;
+ size_t data_length;
+ uint8_t* data;
+} GpsNavigationMessage;
+
+/** Represents a GPS navigation message (or a fragment of it). */
+typedef struct {
+ /** set to sizeof(GnssNavigationMessage) */
+ size_t size;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ * This is a mandatory value.
+ */
+ int16_t svid;
+
+ /**
+ * The type of message contained in the structure.
+ * This is a mandatory value.
+ */
+ GnssNavigationMessageType type;
+
+ /**
+ * The status of the received navigation message.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+ NavigationMessageStatus status;
+
+ /**
+ * Message identifier. It provides an index so the complete Navigation
+ * Message can be assembled.
+ *
+ * - For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+ * id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+ * does not contain a 'frame id' and this value can be set to -1.)
+ *
+ * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+ *
+ * - For BeiDou D1, this refers to the frame number in the range of 1-24
+ *
+ * - For Beidou D2, this refers to the frame number, in the range of 1-120
+ *
+ * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+ * number, in the range of 1-12
+ *
+ * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+ * number in the range of 1-24
+ */
+ int16_t message_id;
+
+ /**
+ * Sub-message identifier. If required by the message 'type', this value
+ * contains a sub-index within the current message (or frame) that is being
+ * transmitted.
+ *
+ * - For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to
+ * the subframe number of the navigation message, in the range of 1-5.
+ *
+ * - For Glonass L1 C/A, this refers to the String number, in the range from
+ * 1-15
+ *
+ * - For Galileo F/NAV, this refers to the page type in the range 1-6
+ *
+ * - For Galileo I/NAV, this refers to the word type in the range 1-10+
+ */
+ int16_t submessage_id;
+
+ /**
+ * The length of the data (in bytes) contained in the current message.
+ * If this value is different from zero, 'data' must point to an array of the same size.
+ * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+ *
+ * This is a mandatory value.
+ */
+ size_t data_length;
+
+ /**
+ * The data of the reported GPS message. The bytes (or words) specified
+ * using big endian format (MSB first).
+ *
+ * - For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+ * words. Each word (30 bits) should be fit into the last 30 bits in a
+ * 4-byte word (skip B31 and B32), with MSB first, for a total of 40
+ * bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
+ *
+ * - For Glonass L1 C/A, each string contains 85 data bits, including the
+ * checksum. These bits should be fit into 11 bytes, with MSB first (skip
+ * B86-B88), covering a time period of 2 seconds.
+ *
+ * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+ * excluded). Each word should be fit into 30-bytes, with MSB first (skip
+ * B239, B240), covering a time period of 10 seconds.
+ *
+ * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+ * a total of 2x114 = 228 bits, (sync & tail excluded) that should be fit
+ * into 29 bytes, with MSB first (skip B229-B232).
+ */
+ uint8_t* data;
+
+} GnssNavigationMessage;
+
+/**
+ * The legacy callback to report an available fragment of a GPS navigation
+ * messages from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_navigation_message_callback() instead.
+ *
+ * Parameters:
+ * message - The GPS navigation submessage/subframe representation.
+ */
+typedef void (*gps_navigation_message_callback) (GpsNavigationMessage* message);
+
+/**
+ * The callback to report an available fragment of a GPS navigation messages from the HAL.
+ *
+ * Parameters:
+ * message - The GPS navigation submessage/subframe representation.
+ */
+typedef void (*gnss_navigation_message_callback) (GnssNavigationMessage* message);
+
+typedef struct {
+ /** set to sizeof(GpsNavigationMessageCallbacks) */
+ size_t size;
+ gps_navigation_message_callback navigation_message_callback;
+ gnss_navigation_message_callback gnss_navigation_message_callback;
+} GpsNavigationMessageCallbacks;
+
+/**
+ * Extended interface for GPS navigation message reporting support.
+ */
+typedef struct {
+ /** Set to sizeof(GpsNavigationMessageInterface) */
+ size_t size;
+
+ /**
+ * Initializes the interface and registers the callback routines with the HAL.
+ * After a successful call to 'init' the HAL must begin to provide updates as they become
+ * available.
+ *
+ * Status:
+ * GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS
+ * GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT - if a callback has already been registered
+ * without a corresponding call to 'close'.
+ * GPS_NAVIGATION_MESSAGE_ERROR_GENERIC - if any other error occurred, it is expected that
+ * the HAL will not generate any updates upon returning this error code.
+ */
+ int (*init) (GpsNavigationMessageCallbacks* callbacks);
+
+ /**
+ * Stops updates from the HAL, and unregisters the callback routines.
+ * After a call to stop, the previously registered callbacks must be considered invalid by the
+ * HAL.
+ * If stop is invoked without a previous 'init', this function should perform no work.
+ */
+ void (*close) ();
+
+} GpsNavigationMessageInterface;
+
+/**
+ * Interface for passing GNSS configuration contents from platform to HAL.
+ */
+typedef struct {
+ /** Set to sizeof(GnssConfigurationInterface) */
+ size_t size;
+
+ /**
+ * Deliver GNSS configuration contents to HAL.
+ * Parameters:
+ * config_data - a pointer to a char array which holds what usually is expected from
+ file(/etc/gps.conf), i.e., a sequence of UTF8 strings separated by '\n'.
+ * length - total number of UTF8 characters in configuraiton data.
+ *
+ * IMPORTANT:
+ * GPS HAL should expect this function can be called multiple times. And it may be
+ * called even when GpsLocationProvider is already constructed and enabled. GPS HAL
+ * should maintain the existing requests for various callback regardless the change
+ * in configuration data.
+ */
+ void (*configuration_update) (const char* config_data, int32_t length);
+} GnssConfigurationInterface;
+
+__END_DECLS
+
+#endif
+
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_H */
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/hardware/gps_internal.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/hardware/gps_internal.h
new file mode 100644
index 0000000..67a16e8
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/hardware/gps_internal.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H
+
+#ifdef __LINUX_OS__
+//#include <hardware/gps.h>
+#include "gps.h"
+
+/****************************************************************************
+ * This file contains legacy structs that are deprecated/retired from gps.h *
+ ****************************************************************************/
+
+__BEGIN_DECLS
+
+/**
+ * Legacy GPS callback structure.
+ * Deprecated, to be removed in the next Android release.
+ * Use GpsCallbacks instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsCallbacks_v1) */
+ size_t size;
+ gps_location_callback location_cb;
+ gps_status_callback status_cb;
+ gps_sv_status_callback sv_status_cb;
+ gps_nmea_callback nmea_cb;
+ gps_set_capabilities set_capabilities_cb;
+ gps_acquire_wakelock acquire_wakelock_cb;
+ gps_release_wakelock release_wakelock_cb;
+ gps_create_thread create_thread_cb;
+ gps_request_utc_time request_utc_time_cb;
+} GpsCallbacks_v1;
+
+#pragma pack(push,4)
+// We need to keep the alignment of this data structure to 4-bytes, to ensure that in 64-bit
+// environments the size of this legacy definition does not collide with _v2. Implementations should
+// be using _v2 and _v3, so it's OK to pay the 'unaligned' penalty in 64-bit if an old
+// implementation is still in use.
+
+/**
+ * Legacy struct to represent the status of AGPS.
+ */
+typedef struct {
+ /** set to sizeof(AGpsStatus_v1) */
+ size_t size;
+ AGpsType type;
+ AGpsStatusValue status;
+} AGpsStatus_v1;
+
+#pragma pack(pop)
+
+/**
+ * Legacy struct to represent the status of AGPS augmented with a IPv4 address
+ * field.
+ */
+typedef struct {
+ /** set to sizeof(AGpsStatus_v2) */
+ size_t size;
+ AGpsType type;
+ AGpsStatusValue status;
+
+ /*-------------------- New fields in _v2 --------------------*/
+
+ uint32_t ipaddr;
+} AGpsStatus_v2;
+
+/**
+ * Legacy extended interface for AGPS support.
+ * See AGpsInterface_v2 for more information.
+ */
+typedef struct {
+ /** set to sizeof(AGpsInterface_v1) */
+ size_t size;
+ void (*init)( AGpsCallbacks* callbacks );
+ int (*data_conn_open)( const char* apn );
+ int (*data_conn_closed)();
+ int (*data_conn_failed)();
+ int (*set_server)( AGpsType type, const char* hostname, int port );
+} AGpsInterface_v1;
+
+__END_DECLS
+
+#endif
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H */
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/hardware/gps_mtk.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/hardware/gps_mtk.h
new file mode 100644
index 0000000..0e1c37c
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/hardware/gps_mtk.h
@@ -0,0 +1,1514 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_MTK_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_MTK_H
+
+#if defined (__ANDROID_OS__)
+#include <hardware/gps_internal.h>
+#elif defined (__LINUX_OS__)
+#include "gps_internal.h"
+#endif
+
+__BEGIN_DECLS
+
+// MTK extended GpsAidingData values.
+#define GPS_DELETE_HOT_STILL 0x2000
+#define GPS_DELETE_EPO 0x4000
+
+// ====================vzw debug screen API =================
+/**
+ * Name for the VZW debug interface.
+ */
+#define VZW_DEBUG_INTERFACE "vzw-debug"
+
+#define VZW_DEBUG_STRING_MAXLEN 200
+
+/** Represents data of VzwDebugData. */
+typedef struct {
+ /** set to sizeof(VzwDebugData) */
+ size_t size;
+
+ char vzw_msg_data[VZW_DEBUG_STRING_MAXLEN];
+} VzwDebugData;
+
+
+typedef void (* vzw_debug_callback)(VzwDebugData* vzw_message);
+
+/** Callback structure for the Vzw debug interface. */
+typedef struct {
+ vzw_debug_callback vzw_debug_cb;
+} VzwDebugCallbacks;
+
+
+/** Extended interface for VZW DEBUG support. */
+typedef struct {
+ /** set to sizeof(VzwDebugInterface) */
+ size_t size;
+
+ /** Registers the callbacks for Vzw debug message. */
+ int (*init)( VzwDebugCallbacks* callbacks );
+
+ /** Set Vzw debug screen enable/disable **/
+ void (*set_vzw_debug_screen)(bool enabled);
+} VzwDebugInterface;
+
+////////////////////// GNSS HIDL v1.0 ////////////////////////////
+
+enum { // ElapsedRealtimeFlags : uint16_t {
+ /** A valid timestampNs is stored in the data structure. */
+ HAS_TIMESTAMP_NS = 1 << 0,
+ /** A valid timeUncertaintyNs is stored in the data structure. */
+ HAS_TIME_UNCERTAINTY_NS = 1 << 1,
+};
+typedef uint16_t ElapsedRealtimeFlags;
+
+typedef struct {
+ /**
+ * A set of flags indicating the validity of each field in this data structure.
+ *
+ * Fields may have invalid information in them, if not marked as valid by the
+ * corresponding bit in flags.
+ */
+ uint16_t flags;
+
+ /**
+ * Estimate of the elapsed time since boot value for the corresponding event in nanoseconds.
+ */
+ uint64_t timestampNs;
+
+ /**
+ * Estimate of the relative precision of the alignment of this SystemClock
+ * timestamp, with the reported measurements in nanoseconds (68% confidence).
+ */
+ uint64_t timeUncertaintyNs;
+}ElapsedRealtime ;
+
+typedef unsigned int loc_type;
+#define MTK_LOC_TYPE_AGPS_AFLT 0 // From C2K AFLT flow
+#define MTK_LOC_TYPE_AGPS_CDMA_CELL 1 // From C2K Cell
+#define MTK_LOC_TYPE_AGPS_MOLR_BEGIN_RSP 2 // For CP MOLR after UE provides MSA result, the network will send CISS_FACILITY to provide UE a MSA location. Refer to 3GPP TS37.571-2 7.2.2.2
+#define MTK_LOC_TYPE_AGPS_SUPL_END 3 // From the SUPL END in a supl session. It may be the result of MSA, E-CID, OTDOA, or their hybrid.
+#define MTK_LOC_TYPE_AGPS_SUPL_REF_LOC 4 // For Reference Location assistance data in SUPL flow (equivalent to PMTK713 in SUPL flow)
+#define MTK_LOC_TYPE_AGPS_CP_REF_LOC 5 // For Reference Location assistance data in CP AGPS flow (equivalent to PMTK713 in CP AGPS flow)
+#define MTK_LOC_TYPE_GNSS_STANDALONE 0xfe // GNSS Standalone
+#define MTK_LOC_TYPE_GNSS_UNKNOWN 0xff // Unknown
+
+/** Represents a location. */
+typedef struct {
+ GpsLocation legacyLocation;
+ /**
+ * Represents expected horizontal position accuracy, radial, in meters
+ * (68% confidence).
+ */
+ float horizontalAccuracyMeters;
+
+ /**
+ * Represents expected vertical position accuracy in meters
+ * (68% confidence).
+ */
+ float verticalAccuracyMeters;
+
+ /**
+ * Represents expected speed accuracy in meter per seconds
+ * (68% confidence).
+ */
+ float speedAccuracyMetersPerSecond;
+
+ /**
+ * Represents expected bearing accuracy in degrees
+ * (68% confidence).
+ */
+ float bearingAccuracyDegrees;
+
+ /// v2.0
+ ElapsedRealtime elapsedRealtime;
+
+ loc_type type;
+
+} GpsLocation_ext;
+
+
+typedef struct {
+ GnssSvInfo legacySvInfo;
+
+ /// v1.0 ///
+ float carrier_frequency;
+
+ /// v2.1 ///
+ double basebandCN0DbHz;
+
+} GnssSvInfo_ext;
+
+/**
+ * Represents SV status.
+ */
+typedef struct {
+ /** set to sizeof(GnssSvStatus) */
+ size_t size;
+
+ /** Number of GPS SVs currently visible, refers to the SVs stored in sv_list */
+ int num_svs;
+ /**
+ * Pointer to an array of SVs information for all GNSS constellations,
+ * except GPS, which is reported using sv_list
+ */
+ GnssSvInfo_ext gnss_sv_list[GNSS_MAX_SVS];
+
+} GnssSvStatus_ext;
+
+/**
+ * Callback with location information. Can only be called from a thread created
+ * by create_thread_cb.
+ */
+typedef void (* gps_location_ext_callback)(GpsLocation_ext* location);
+
+/**
+ * Callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* gnss_sv_status_ext_callback)(GnssSvStatus_ext* sv_info);
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ * geofence_id - The id associated with the add_geofence_area.
+ * location - The current GPS location.
+ * transition - Can be one of GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED,
+ * GPS_GEOFENCE_UNCERTAIN.
+ * timestamp - Timestamp when the transition was detected.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the GPS
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*gps_geofence_transition_ext_callback) (int32_t geofence_id,
+ GpsLocation_ext* location, int32_t transition, GpsUtcTime timestamp);
+
+/**
+ * The callback associated with the availability of the GPS system for geofencing
+ * monitoring. If the GPS system determines that it cannot monitor geofences
+ * because of lack of reliability or unavailability of the GPS signals, it will
+ * call this callback with GPS_GEOFENCE_UNAVAILABLE parameter.
+ *
+ * Parameters:
+ * status - GPS_GEOFENCE_UNAVAILABLE or GPS_GEOFENCE_AVAILABLE.
+ * last_location - Last known location.
+ */
+typedef void (*gps_geofence_status_ext_callback) (int32_t status,
+ GpsLocation_ext* last_location);
+
+typedef struct {
+ gps_geofence_transition_ext_callback geofence_transition_callback;
+ gps_geofence_status_ext_callback geofence_status_callback;
+ gps_geofence_add_callback geofence_add_callback;
+ gps_geofence_remove_callback geofence_remove_callback;
+ gps_geofence_pause_callback geofence_pause_callback;
+ gps_geofence_resume_callback geofence_resume_callback;
+ gps_create_thread create_thread_cb;
+} GpsGeofenceCallbacks_ext;
+
+/** Extended interface for GPS_Geofencing support */
+typedef struct {
+ /** set to sizeof(GpsGeofencingInterface) */
+ size_t size;
+
+ /**
+ * Opens the geofence interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ void (*init)( GpsGeofenceCallbacks_ext* callbacks );
+
+ /**
+ * Add a geofence area. This api currently supports circular geofences.
+ * Parameters:
+ * geofence_id - The id for the geofence. If a geofence with this id
+ * already exists, an error value (GPS_GEOFENCE_ERROR_ID_EXISTS)
+ * should be returned.
+ * latitude, longtitude, radius_meters - The lat, long and radius
+ * (in meters) for the geofence
+ * last_transition - The current state of the geofence. For example, if
+ * the system already knows that the user is inside the geofence,
+ * this will be set to GPS_GEOFENCE_ENTERED. In most cases, it
+ * will be GPS_GEOFENCE_UNCERTAIN.
+ * monitor_transition - Which transitions to monitor. Bitwise OR of
+ * GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+ * GPS_GEOFENCE_UNCERTAIN.
+ * notification_responsiveness_ms - Defines the best-effort description
+ * of how soon should the callback be called when the transition
+ * associated with the Geofence is triggered. For instance, if set
+ * to 1000 millseconds with GPS_GEOFENCE_ENTERED, the callback
+ * should be called 1000 milliseconds within entering the geofence.
+ * This parameter is defined in milliseconds.
+ * NOTE: This is not to be confused with the rate that the GPS is
+ * polled at. It is acceptable to dynamically vary the rate of
+ * sampling the GPS for power-saving reasons; thus the rate of
+ * sampling may be faster or slower than this.
+ * unknown_timer_ms - The time limit after which the UNCERTAIN transition
+ * should be triggered. This parameter is defined in milliseconds.
+ * See above for a detailed explanation.
+ */
+ void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude,
+ double radius_meters, int last_transition, int monitor_transitions,
+ int notification_responsiveness_ms, int unknown_timer_ms);
+
+ /**
+ * Pause monitoring a particular geofence.
+ * Parameters:
+ * geofence_id - The id for the geofence.
+ */
+ void (*pause_geofence) (int32_t geofence_id);
+
+ /**
+ * Resume monitoring a particular geofence.
+ * Parameters:
+ * geofence_id - The id for the geofence.
+ * monitor_transitions - Which transitions to monitor. Bitwise OR of
+ * GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+ * GPS_GEOFENCE_UNCERTAIN.
+ * This supersedes the value associated provided in the
+ * add_geofence_area call.
+ */
+ void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+ /**
+ * Remove a geofence area. After the function returns, no notifications
+ * should be sent.
+ * Parameter:
+ * geofence_id - The id for the geofence.
+ */
+ void (*remove_geofence_area) (int32_t geofence_id);
+} GpsGeofencingInterface_ext;
+
+enum {
+ STATE_UNKNOWN = 0,
+ STATE_CODE_LOCK = 1 << 0,
+ STATE_BIT_SYNC = 1 << 1,
+ STATE_SUBFRAME_SYNC = 1 << 2,
+ STATE_TOW_DECODED = 1 << 3,
+ STATE_MSEC_AMBIGUOUS = 1 << 4,
+ STATE_SYMBOL_SYNC = 1 << 5,
+ STATE_GLO_STRING_SYNC = 1 << 6,
+ STATE_GLO_TOD_DECODED = 1 << 7,
+ STATE_BDS_D2_BIT_SYNC = 1 << 8,
+ STATE_BDS_D2_SUBFRAME_SYNC = 1 << 9,
+ STATE_GAL_E1BC_CODE_LOCK = 1 << 10,
+ STATE_GAL_E1C_2ND_CODE_LOCK = 1 << 11,
+ STATE_GAL_E1B_PAGE_SYNC = 1 << 12,
+ STATE_SBAS_SYNC = 1 << 13,
+ STATE_TOW_KNOWN = 1 << 14,
+ STATE_GLO_TOD_KNOWN = 1 << 15,
+ STATE_2ND_CODE_LOCK = 1 << 16,
+};
+//typedef uint32_t GnssMeasurementState;
+
+/// extension to GnssConstellationType;
+enum {
+ /** Indian Regional Navigation Satellite System. */
+ GNSS_CONSTELLATION_IRNSS = 7,
+ GNSS_CONSTELLATION_SIZE = 8,
+};
+//typedef uint8_t GnssConstellationType;
+
+typedef struct {
+ GnssMeasurement legacyMeasurement;
+
+ /**
+ * Automatic gain control (AGC) level. AGC acts as a variable gain
+ * amplifier adjusting the power of the incoming signal. The AGC level
+ * may be used to indicate potential interference. When AGC is at a
+ * nominal level, this value must be set as 0. Higher gain (and/or lower
+ * input power) must be output as a positive number. Hence in cases of
+ * strong jamming, in the band of this signal, this value must go more
+ * negative.
+ *
+ * Note: Different hardware designs (e.g. antenna, pre-amplification, or
+ * other RF HW components) may also affect the typical output of of this
+ * value on any given hardware design in an open sky test - the
+ * important aspect of this output is that changes in this value are
+ * indicative of changes on input signal power in the frequency band for
+ * this measurement.
+ */
+ /// v1.1
+ double agc_level_db;
+
+ /// v2.0
+ char codeType[8];
+ // uint32_t state; direct use original field
+ //GnssConstellationType constellation; direct use original field
+
+ /// v2.1
+ //GnssMeasurementFlags flags; directly use original field
+
+ /**
+ * The full inter-signal bias (ISB) in nanoseconds.
+ *
+ * This value is the sum of the estimated receiver-side and the space-segment-side
+ * inter-system bias, inter-frequency bias and inter-code bias, including
+ *
+ * - Receiver inter-constellation bias (with respect to the constellation in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Receiver inter-frequency bias (with respect to the carrier frequency in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Receiver inter-code bias (with respect to the code type in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPS-UTC Time Offset
+ * (TauGps), BDS-GLO Time Offset (BGTO)) (with respect to the constellation in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Group delay (e.g., Total Group Delay (TGD))
+ * - Satellite inter-frequency bias (GLO only) (with respect to the carrier frequency in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Satellite inter-code bias (e.g., Differential Code Bias (DCB)) (with respect to the
+ * code type in GnssClock.referenceSignalTypeForIsb)
+ *
+ * If a component of the above is already compensated in the provided
+ * GnssMeasurement.receivedSvTimeInNs, then it must not be included in the reported full
+ * ISB.
+ *
+ * The value does not include the inter-frequency Ionospheric bias.
+ *
+ * The full ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
+ */
+ double fullInterSignalBiasNs;
+
+ /**
+ * 1-sigma uncertainty associated with the full inter-signal bias in nanoseconds.
+ */
+ double fullInterSignalBiasUncertaintyNs;
+
+ /**
+ * The satellite inter-signal bias in nanoseconds.
+ *
+ * This value is the satellite-and-control-segment-side inter-system (different from the
+ * constellation in GnssClock.referenceSignalTypeForIsb) bias and inter-frequency (different
+ * from the carrier frequency in GnssClock.referenceSignalTypeForIsb) bias, including:
+ *
+ * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPT-UTC Time Offset (TauGps),
+ * BDS-GLO Time Offset (BGTO))
+ * - Group delay (e.g., Total Group Delay (TGD))
+ * - Satellite inter-signal bias, which includes satellite inter-frequency bias (GLO only),
+ * and satellite inter-code bias (e.g., Differential Code Bias (DCB)).
+ *
+ * The receiver ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
+ */
+ double satelliteInterSignalBiasNs;
+
+ /**
+ * 1-sigma uncertainty associated with the satellite inter-signal bias in nanoseconds.
+ */
+ double satelliteInterSignalBiasUncertaintyNs;
+
+ /**
+ * Baseband Carrier-to-noise density in dB-Hz, typically in the range [0, 63]. It contains
+ * the measured C/N0 value for the signal measured at the baseband.
+ *
+ * This is typically a few dB weaker than the value estimated for C/N0 at the antenna port,
+ * which is reported in cN0DbHz.
+ *
+ * If a signal has separate components (e.g. Pilot and Data channels) and the receiver only
+ * processes one of the components, then the reported basebandCN0DbHz reflects only the
+ * component that is processed.
+ *
+ * This value is mandatory.
+ */
+ double basebandCN0DbHz;
+
+} GnssMeasurement_ext;
+
+typedef struct {
+ GnssConstellationType constellation;
+ double carrierFrequencyHz;
+ char codeType[8];
+} GnssSignalType;
+
+typedef struct {
+ GnssClock legacyClock;
+ GnssSignalType referenceSignalTypeForIsb;
+} GnssClock_ext;
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+ /** set to sizeof(GnssData) */
+ size_t size;
+
+ /** Number of measurements. */
+ size_t measurement_count;
+
+ /** The array of measurements. */
+ GnssMeasurement_ext measurements[GNSS_MAX_MEASUREMENT];
+
+ /** The GPS clock time reading. */
+ /// v2.1
+ GnssClock_ext clock;
+
+ /// v2.0
+ ElapsedRealtime elapsedRealtime;
+} GnssData_ext;
+
+/**
+ * The callback for to report measurements from the HAL.
+ *
+ * Parameters:
+ * data - A data structure containing the measurements.
+ */
+typedef void (*gnss_measurement_ext_callback) (GnssData_ext* data);
+
+typedef struct {
+ /** set to sizeof(GpsMeasurementCallbacks) */
+ size_t size;
+ gps_measurement_callback measurement_callback;
+ gnss_measurement_ext_callback gnss_measurement_callback;
+} GpsMeasurementCallbacks_ext;
+
+
+/////// Gnss debug ////
+
+/** Milliseconds since January 1, 1970 */
+typedef int64_t GnssUtcTime;
+
+typedef enum {
+ /** Ephemeris is known for this satellite. */
+ EPHEMERIS,
+ /**
+ * Ephemeris is not known, but Almanac (approximate location) is known.
+ */
+ ALMANAC_ONLY,
+ /**
+ * Both ephemeris & almanac are not known (e.g. during a cold start
+ * blind search.)
+ */
+ NOT_AVAILABLE
+} SatelliteEphemerisType;
+
+typedef enum {
+ /**
+ * The ephemeris (or almanac only) information was demodulated from the
+ * signal received on the device
+ */
+ DEMODULATED,
+ /**
+ * The ephemeris (or almanac only) information was received from a SUPL
+ * server.
+ */
+ SUPL_PROVIDED,
+ /**
+ * The ephemeris (or almanac only) information was provided by another
+ * server.
+ */
+ OTHER_SERVER_PROVIDED,
+ /**
+ * The ephemeris (or almanac only) information was provided by another
+ * method, e.g. injected via a local debug tool, from build defaults
+ * (e.g. almanac), or is from a satellite
+ * with SatelliteEphemerisType::NOT_AVAILABLE.
+ */
+ OTHER
+} SatelliteEphemerisSource;
+
+typedef enum {
+ /** The ephemeris is known good. */
+ GOOD,
+ /** The ephemeris is known bad. */
+ BAD,
+ /** The ephemeris is unknown to be good or bad. */
+ UNKNOWN
+} SatelliteEphemerisHealth;
+
+/**
+ * Provides the current best known position from any
+ * source (GNSS or injected assistance).
+ */
+typedef struct {
+ /**
+ * Validity of the data in this struct. False only if no
+ * latitude/longitude information is known.
+ */
+ bool valid;
+ /** Latitude expressed in degrees */
+ double latitudeDegrees;
+ /** Longitude expressed in degrees */
+ double longitudeDegrees;
+ /** Altitude above ellipsoid expressed in meters */
+ float altitudeMeters;
+ /** Represents horizontal speed in meters per second. */
+ float speedMetersPerSec;
+ /** Represents heading in degrees. */
+ float bearingDegrees;
+ /**
+ * Estimated horizontal accuracy of position expressed in meters,
+ * radial, 68% confidence.
+ */
+ double horizontalAccuracyMeters;
+ /**
+ * Estimated vertical accuracy of position expressed in meters, with
+ * 68% confidence.
+ */
+ double verticalAccuracyMeters;
+ /**
+ * Estimated speed accuracy in meters per second with 68% confidence.
+ */
+ double speedAccuracyMetersPerSecond;
+ /**
+ * estimated bearing accuracy degrees with 68% confidence.
+ */
+ double bearingAccuracyDegrees;
+ /**
+ * Time duration before this report that this position information was
+ * valid. This can, for example, be a previous injected location with
+ * an age potentially thousands of seconds old, or
+ * extrapolated to the current time (with appropriately increased
+ * accuracy estimates), with a (near) zero age.
+ */
+ float ageSeconds;
+} PositionDebug;
+
+/**
+ * Provides the current best known UTC time estimate.
+ * If no fresh information is available, e.g. after a delete all,
+ * then whatever the effective defaults are on the device must be
+ * provided (e.g. Jan. 1, 2017, with an uncertainty of 5 years) expressed
+ * in the specified units.
+ */
+typedef struct {
+ /** UTC time estimate. */
+ GnssUtcTime timeEstimate;
+ /** 68% error estimate in time. */
+ float timeUncertaintyNs;
+ /**
+ * 68% error estimate in local clock drift,
+ * in nanoseconds per second (also known as parts per billion - ppb.)
+ */
+ float frequencyUncertaintyNsPerSec;
+} TimeDebug;
+
+/**
+ * Provides a single satellite info that has decoded navigation data.
+ */
+typedef struct {
+ /** Satellite vehicle ID number */
+ int16_t svid;
+ /** Defines the constellation type of the given SV. */
+ GnssConstellationType constellation;
+
+ /**
+ * Defines the standard broadcast ephemeris or almanac availability for
+ * the satellite. To report status of predicted orbit and clock
+ * information, see the serverPrediction fields below.
+ */
+ SatelliteEphemerisType ephemerisType;
+ /** Defines the ephemeris source of the satellite. */
+ SatelliteEphemerisSource ephemerisSource;
+ /**
+ * Defines whether the satellite is known healthy
+ * (safe for use in location calculation.)
+ */
+ SatelliteEphemerisHealth ephemerisHealth;
+ /**
+ * Time duration from this report (current time), minus the
+ * effective time of the ephemeris source (e.g. TOE, TOA.)
+ * Set to 0 when ephemerisType is NOT_AVAILABLE.
+ */
+ float ephemerisAgeSeconds;
+
+ /**
+ * True if a server has provided a predicted orbit and clock model for
+ * this satellite.
+ */
+ bool serverPredictionIsAvailable;
+ /**
+ * Time duration from this report (current time) minus the time of the
+ * start of the server predicted information. For example, a 1 day
+ * old prediction would be reported as 86400 seconds here.
+ */
+ float serverPredictionAgeSeconds;
+} SatelliteData;
+
+/**
+ * Provides a set of debug information that is filled by the GNSS chipset
+ * when the method getDebugData() is invoked.
+ */
+typedef struct {
+ /** Current best known position. */
+ PositionDebug position;
+ /** Current best know time estimate */
+ TimeDebug time;
+ /**
+ * Provides a list of the available satellite data, for all
+ * satellites and constellations the device can track,
+ * including GnssConstellationType UNKNOWN.
+ */
+ SatelliteData satelliteDataArray[GNSS_MAX_SVS];
+} DebugData;
+
+
+/** Extended interface for DEBUG support. */
+typedef struct {
+ /** set to sizeof(GpsDebugInterface) */
+ size_t size;
+
+ /**
+ * This function should return any information that the native
+ * implementation wishes to include in a bugreport.
+ */
+ // size_t (*get_internal_state)(char* buffer, size_t bufferSize);
+ /// v1.0 ///
+ bool (*get_internal_state)(DebugData* debugData);
+} GpsDebugInterface_ext;
+
+
+////////////////////// GNSS HIDL v1.1 ////////////////////////////
+
+/**
+ * Callback for reporting driver name information.
+ */
+typedef void (* gnss_set_name_callback)(const char* name, int length);
+
+/**
+ * Callback for requesting framework NLP or Fused location injection.
+ */
+typedef void (* gnss_request_location_callback)(bool independentFromGnss, bool isUserEmergency);
+
+/** New GPS callback structure. */
+typedef struct {
+ /** set to sizeof(GpsCallbacks) */
+ size_t size;
+ gps_location_ext_callback location_cb;
+ gps_status_callback status_cb;
+ gps_sv_status_callback sv_status_cb;
+ gps_nmea_callback nmea_cb;
+ gps_set_capabilities set_capabilities_cb;
+ gps_acquire_wakelock acquire_wakelock_cb;
+ gps_release_wakelock release_wakelock_cb;
+ gps_create_thread create_thread_cb;
+ gps_request_utc_time request_utc_time_cb;
+
+ gnss_set_system_info set_system_info_cb;
+ gnss_sv_status_ext_callback gnss_sv_status_cb;
+
+ /////v1.1////
+ gnss_set_name_callback set_name_cb;
+ ///// v2.0 ///
+ gnss_request_location_callback request_location_cb;
+
+ gps_location_ext_callback agps_location_cb;
+} GpsCallbacks_ext;
+
+
+/** Represents the standard GPS interface. */
+typedef struct {
+ /** set to sizeof(GpsInterface) */
+ size_t size;
+ /**
+ * Opens the interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ /// v1.0 ///
+// int (*init)( GpsCallbacks* callbacks );
+ /// v1.1 ///
+ int (*init)( GpsCallbacks_ext* callbacks );
+
+ /** Starts navigating. */
+ int (*start)( void );
+
+ /** Stops navigating. */
+ int (*stop)( void );
+
+ /** Closes the interface. */
+ void (*cleanup)( void );
+
+ /** Injects the current time. */
+ int (*inject_time)(GpsUtcTime time, int64_t timeReference,
+ int uncertainty);
+
+ /**
+ * Injects current location from another location provider (typically cell
+ * ID). Latitude and longitude are measured in degrees expected accuracy is
+ * measured in meters
+ */
+ int (*inject_location)(double latitude, double longitude, float accuracy);
+
+ /**
+ * Specifies that the next call to start will not use the
+ * information defined in the flags. GPS_DELETE_ALL is passed for
+ * a cold start.
+ */
+ void (*delete_aiding_data)(GpsAidingData flags);
+
+ /**
+ * min_interval represents the time between fixes in milliseconds.
+ * preferred_accuracy represents the requested fix accuracy in meters.
+ * preferred_time represents the requested time to first fix in milliseconds.
+ *
+ * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASED
+ * or GPS_POSITION_MODE_STANDALONE.
+ * It is allowed by the platform (and it is recommended) to fallback to
+ * GPS_POSITION_MODE_MS_BASED if GPS_POSITION_MODE_MS_ASSISTED is passed in, and
+ * GPS_POSITION_MODE_MS_BASED is supported.
+ */
+ /// v1.0 ///
+// int (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+// uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
+ /// v1.1 ///
+ int (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+ uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time,
+ bool lowPowerMode);
+
+
+ /** Get a pointer to extension information. */
+ const void* (*get_extension)(const char* name);
+
+ /// v1.1 ///
+ int (*inject_fused_location)(double latitude, double longitude, float accuracy);
+
+} GpsInterface_ext;
+
+
+/**
+ * Extended interface for GPS Measurements support.
+ */
+typedef struct {
+ /** Set to sizeof(GpsMeasurementInterface_ext) */
+ size_t size;
+
+ /**
+ * Initializes the interface and registers the callback routines with the HAL.
+ * After a successful call to 'init' the HAL must begin to provide updates at its own phase.
+ *
+ * Status:
+ * GPS_MEASUREMENT_OPERATION_SUCCESS
+ * GPS_MEASUREMENT_ERROR_ALREADY_INIT - if a callback has already been registered without a
+ * corresponding call to 'close'
+ * GPS_MEASUREMENT_ERROR_GENERIC - if any other error occurred, it is expected that the HAL
+ * will not generate any updates upon returning this error code.
+ */
+ /// v1.0 ///
+// int (*init) (GpsMeasurementCallbacks* callbacks);
+ /// v1.1 ///
+ int (*init) (GpsMeasurementCallbacks_ext* callbacks, bool enableFullTracking);
+
+ /**
+ * Stops updates from the HAL, and unregisters the callback routines.
+ * After a call to stop, the previously registered callbacks must be considered invalid by the
+ * HAL.
+ * If stop is invoked without a previous 'init', this function should perform no work.
+ */
+ void (*close) ();
+
+} GpsMeasurementInterface_ext;
+
+
+/**
+ * Interface for passing GNSS configuration contents from platform to HAL.
+ */
+typedef struct {
+ /** Set to sizeof(GnssConfigurationInterface) */
+ size_t size;
+
+ /**
+ * Deliver GNSS configuration contents to HAL.
+ * Parameters:
+ * config_data - a pointer to a char array which holds what usually is expected from
+ file(/etc/gps.conf), i.e., a sequence of UTF8 strings separated by '\n'.
+ * length - total number of UTF8 characters in configuraiton data.
+ *
+ * IMPORTANT:
+ * GPS HAL should expect this function can be called multiple times. And it may be
+ * called even when GpsLocationProvider is already constructed and enabled. GPS HAL
+ * should maintain the existing requests for various callback regardless the change
+ * in configuration data.
+ */
+ void (*configuration_update) (const char* config_data, int32_t length);
+
+ //// v1.1 ////
+ void (*setBlacklist) (long long* blacklist, int32_t size);
+
+ //// v2.0 ////
+ void (*set_es_extension_sec) (uint32_t emergencyExtensionSeconds);
+} GnssConfigurationInterface_ext;
+
+////////////////////// GNSS HIDL v2.0 ////////////////////////////
+
+#define STRING_MAXLEN 256
+
+/**
+ * Name for the GNSS measurement correction interface.
+ */
+#define GNSS_MEASUREMENT_CORRECTION_INTERFACE "gnss_measurement_correction"
+
+/**
+ * Name for the GNSS visibility control interface.
+ */
+#define GNSS_VISIBILITY_CONTROL_INTERFACE "gnss_visiblity_control"
+
+//// GNSS capabilities extension
+enum {
+ /** GNSS supports low power mode */
+ GPS_CAPABILITY_LOW_POWER_MODE = 1 << 8,
+ /** GNSS supports blacklisting satellites */
+ GPS_CAPABILITY_SATELLITE_BLACKLIST = 1 << 9,
+ /** GNSS supports measurement corrections */
+ MEASUREMENT_CORRECTIONS = 1 << 10,
+ /** GNSS supports measurement corrections */
+ ANTENNA_INFO = 1 << 11
+};
+typedef uint32_t GnssCapabilities;
+
+enum {
+ // SUPL = 1, // already defined
+ // C2K = 2, // already defined
+ AGPS_TYPE_SUPL_EIMS = 3,
+ AGPS_TYPE_SUPL_IMS = 4,
+};
+typedef uint8_t AGnssType;
+
+enum {
+ /** GNSS requests data connection for AGNSS. */
+ REQUEST_AGNSS_DATA_CONN = 1,
+ /** GNSS releases the AGNSS data connection. */
+ RELEASE_AGNSS_DATA_CONN = 2,
+ /** AGNSS data connection initiated */
+ AGNSS_DATA_CONNECTED = 3,
+ /** AGNSS data connection completed */
+ AGNSS_DATA_CONN_DONE = 4,
+ /** AGNSS data connection failed */
+ AGNSS_DATA_CONN_FAILED = 5
+};
+typedef uint8_t AGnssStatusValue;
+
+/**
+ * Extended interface for AGPS support, it is augmented to enable to pass
+ * extra APN data.
+ */
+typedef struct {
+ /** set to sizeof(AGpsInterface) */
+ size_t size;
+
+ /**
+ * Opens the AGPS interface and provides the callback routines to the
+ * implementation of this interface.
+ */
+ void (*init)(AGpsCallbacks* callbacks);
+ /**
+ * Deprecated.
+ * If the HAL supports AGpsInterface_v2 this API will not be used, see
+ * data_conn_open_with_apn_ip_type for more information.
+ */
+ int (*data_conn_open)(const char* apn);
+ /**
+ * Notifies that the AGPS data connection has been closed.
+ */
+ int (*data_conn_closed)();
+ /**
+ * Notifies that a data connection is not available for AGPS.
+ */
+ int (*data_conn_failed)();
+ /**
+ * Sets the hostname and port for the AGPS server.
+ */
+ int (*set_server)(AGpsType type, const char* hostname, int port);
+
+ /**
+ * Notifies that a data connection is available and sets the name of the
+ * APN, and its IP type, to be used for SUPL connections.
+ */
+ int (*data_conn_open_with_apn_ip_type)(
+ uint64_t networkHandle,
+ const char* apn,
+ ApnIpType apnIpType);
+} AGpsInterface_ext;
+
+/** Flags to indicate capabilities of the network */
+enum { //NetworkCapability : uint16_t {
+ /** Network is not metered. */
+ NOT_METERED = 1 << 0,
+ /** Network is not roaming. */
+ NOT_ROAMING = 1 << 1
+};
+typedef uint16_t NetworkCapability;
+
+
+/** Extended interface for AGPS_RIL support. */
+typedef struct {
+ /** set to sizeof(AGpsRilInterface_ext) */
+ size_t size;
+ /**
+ * Opens the AGPS interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ void (*init)( AGpsRilCallbacks* callbacks );
+
+ /**
+ * Sets the reference location.
+ */
+ void (*set_ref_location) (const AGpsRefLocation *agps_reflocation, size_t sz_struct);
+ /**
+ * Sets the set ID.
+ */
+ void (*set_set_id) (AGpsSetIDType type, const char* setid);
+
+ /**
+ * Send network initiated message.
+ */
+ void (*ni_message) (uint8_t *msg, size_t len);
+
+ /**
+ * Notify GPS of network status changes.
+ * These parameters match values in the android.net.NetworkInfo class.
+ */
+ //// v2.0 ///
+ void (*update_network_state_ext) (uint64_t networkHandle, bool isConnected,
+ uint16_t capabilities, const char* apn);
+
+ /**
+ * Notify GPS of network status changes.
+ * These parameters match values in the android.net.NetworkInfo class.
+ */
+ void (*update_network_availability) (int avaiable, const char* apn);
+} AGpsRilInterface_ext;
+
+
+/** Bit mask to indicate which values are valid in a SingleSatCorrection object. */
+enum { //GnssSingleSatCorrectionFlags : uint16_t {
+ /** GnssSingleSatCorrectionFlags has valid satellite-is-line-of-sight-probability field. */
+ HAS_SAT_IS_LOS_PROBABILITY = 0x0001,
+ /** GnssSingleSatCorrectionFlags has valid Excess Path Length field. */
+ HAS_EXCESS_PATH_LENGTH = 0x0002,
+ /** GnssSingleSatCorrectionFlags has valid Excess Path Length Uncertainty field. */
+ HAS_EXCESS_PATH_LENGTH_UNC = 0x0004,
+ /** GnssSingleSatCorrectionFlags has valid Reflecting Plane field. */
+ HAS_REFLECTING_PLANE = 0x0008
+};
+typedef uint16_t GnssSingleSatCorrectionFlags;
+
+/**
+ * A struct containing the characteristics of the reflecting plane that the satellite signal has
+ * bounced from.
+ *
+ * The value is only valid if HAS_REFLECTING_PLANE flag is set. An invalid reflecting plane
+ * means either reflection planes serving is not supported or the satellite signal has gone
+ * through multiple reflections.
+ */
+typedef struct {
+ /** Represents latitude of the reflecting plane in degrees. */
+ double latitudeDegrees;
+
+ /** Represents longitude of the reflecting plane in degrees. */
+ double longitudeDegrees;
+
+ /**
+ * Represents altitude of the reflecting point in the plane in meters above the WGS 84 reference
+ * ellipsoid.
+ */
+ double altitudeMeters;
+
+ /** Represents azimuth clockwise from north of the reflecting plane in degrees. */
+ double azimuthDegrees;
+} ReflectingPlane ;
+
+
+typedef struct {
+
+ /** Contains GnssSingleSatCorrectionFlags bits. */
+ uint16_t singleSatCorrectionFlags;
+
+ /**
+ * Defines the constellation of the given satellite.
+ */
+ GnssConstellationType constellation;
+
+ /**
+ * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+ */
+ uint16_t svid;
+
+ /**
+ * Carrier frequency of the signal to be corrected, for example it can be the
+ * GPS center frequency for L1 = 1,575,420,000 Hz, varying GLO channels, etc.
+ *
+ * For a receiver with capabilities to track multiple frequencies for the same satellite,
+ * multiple corrections for the same satellite may be provided.
+ */
+ float carrierFrequencyHz;
+
+ /**
+ * The probability that the satellite is estimated to be in Line-of-Sight condition at the given
+ * location.
+ */
+ float probSatIsLos;
+
+ /**
+ * Excess path length to be subtracted from pseudorange before using it in calculating location.
+ *
+ * Note this value is NOT to be used to adjust the GnssMeasurementCallback outputs.
+ */
+ float excessPathLengthMeters;
+
+ /** Error estimate (1-sigma) for the Excess path length estimate */
+ float excessPathLengthUncertaintyMeters;
+
+ /**
+ * Defines the reflecting plane characteristics such as location and azimuth
+ *
+ * The value is only valid if HAS_REFLECTING_PLANE flag is set. An invalid reflecting plane
+ * means either reflection planes serving is not supported or the satellite signal has gone
+ * through multiple reflections.
+ */
+ ReflectingPlane reflectingPlane;
+}SingleSatCorrection;
+
+/**
+ * A struct containing a set of measurement corrections for all used GNSS satellites at the location
+ * specified by latitudeDegrees, longitudeDegrees, altitudeMeters and at the time of week specified
+ * toaGpsNanosecondsOfWeek
+ */
+typedef struct {
+ /** Represents latitude in degrees at which the corrections are computed.. */
+ double latitudeDegrees;
+
+ /** Represents longitude in degrees at which the corrections are computed.. */
+ double longitudeDegrees;
+
+ /**
+ * Represents altitude in meters above the WGS 84 reference ellipsoid at which the corrections
+ * are computed.
+ */
+ double altitudeMeters;
+
+ /**
+ * Represents the horizontal uncertainty (68% confidence) in meters on the device position at
+ * which the corrections are provided.
+ *
+ * This value is useful for example to judge how accurate the provided corrections are.
+ */
+ double horizontalPositionUncertaintyMeters;
+
+ /**
+ * Represents the vertical uncertainty (68% confidence) in meters on the device position at
+ * which the corrections are provided.
+ *
+ * This value is useful for example to judge how accurate the provided corrections are.
+ */
+ double verticalPositionUncertaintyMeters;
+
+ /** Time Of Applicability, GPS time of week in nanoseconds. */
+ uint64_t toaGpsNanosecondsOfWeek;
+
+ /** Number of singleSatCorrection */
+ size_t num_satCorrection;
+
+ /**
+ * A set of SingleSatCorrection each containing measurement corrections for a satellite in view
+ */
+ SingleSatCorrection satCorrections[MTK_MAX_SV_COUNT];
+
+ /// v1.1
+ /*** Boolean indicating if environment bearing is available. */
+ bool hasEnvironmentBearing;
+ float environmentBearingDegrees;
+ float environmentBearingUncertaintyDegrees;
+ /// directly use original field
+ //SingleSatCorrection satCorrections[MTK_MAX_SV_COUNT];
+} MeasurementCorrections;
+
+
+enum { //MeasurementCorrectionCapabilities : uint32_t {
+ /** GNSS supports line-of-sight satellite identification measurement corrections */
+ LOS_SATS = 1 << 0,
+ /** GNSS supports per satellite excess-path-length measurement corrections */
+ EXCESS_PATH_LENGTH = 1 << 1,
+ /** GNSS supports reflecting planes measurement corrections */
+ REFLECTING_PLANE = 1 << 2
+};
+typedef uint32_t MeasurementCorrectionCapabilities;
+
+
+/**
+ * Callback to inform framework the measurement correction specific capabilities of the GNSS
+ * HAL implementation.
+ *
+ * The GNSS HAL must call this method immediately after the framework opens the measurement
+ * corrections interface.
+ *
+ * @param capabilities Supported measurement corrections capabilities. It is mandatory to
+ * support either LOS_STATS or EXCESS_PATH_LENGTH capability.
+ *
+ */
+typedef void (*meac_set_capabilities_cb) (uint32_t capabilities);
+
+typedef struct {
+ /** set to sizeof(GpsMeasurementCorrectionCallbacks) */
+ size_t size;
+ meac_set_capabilities_cb set_capabilities_cb;
+} MeasurementCorrectionCallbacks_ext;
+
+
+
+typedef struct {
+
+ /** Set to sizeof(GpsMeasurementCorrectionInterface) */
+ size_t size;
+
+ bool (*meac_set_callback) (MeasurementCorrectionCallbacks_ext* callbacks);
+
+ bool (*meac_set_corrections) (MeasurementCorrections* corrections);
+
+}MeasurementCorrectionInterface;
+
+
+/**
+ * Protocol stack that is requesting the non-framework location information.
+ */
+enum {
+ /** Cellular control plane requests */
+ CTRL_PLANE = 0,
+ /** All types of SUPL requests */
+ SUPL = 1,
+
+ /** All types of requests from IMS */
+ IMS = 10,
+ /** All types of requests from SIM */
+ SIM = 11,
+
+ /** Requests from other protocol stacks */
+ OTHER_PROTOCOL_STACK = 100
+};
+typedef uint8_t NfwProtocolStack;
+
+/*
+ * Entity that is requesting/receiving the location information.
+ */
+enum { //NfwRequestor : uint8_t {
+ /** Wireless service provider */
+ CARRIER = 0,
+ /** Device manufacturer */
+ OEM = 10,
+ /** Modem chipset vendor */
+ MODEM_CHIPSET_VENDOR = 11,
+ /** GNSS chipset vendor */
+ GNSS_CHIPSET_VENDOR = 12,
+ /** Other chipset vendor */
+ OTHER_CHIPSET_VENDOR = 13,
+ /** Automobile client */
+ AUTOMOBILE_CLIENT = 20,
+ /** Other sources */
+ OTHER_REQUESTOR = 100
+ };
+typedef uint8_t NfwRequestor;
+
+/**
+ * GNSS response type for non-framework location requests.
+ */
+enum {//NfwResponseType : uint8_t {
+ /** Request rejected because framework has not given permission for this use case */
+ REJECTED = 0,
+
+ /** Request accepted but could not provide location because of a failure */
+ ACCEPTED_NO_LOCATION_PROVIDED = 1,
+
+ /** Request accepted and location provided */
+ ACCEPTED_LOCATION_PROVIDED = 2,
+};
+typedef uint8_t NfwResponseType;
+
+/**
+ * Represents a non-framework location information request/response notification.
+ */
+typedef struct {
+ /**
+ * Package name of the Android proxy application representing the non-framework
+ * entity that requested location. Set to empty string if unknown.
+ */
+ char proxyAppPackageName[STRING_MAXLEN];
+
+ /** Protocol stack that initiated the non-framework location request. */
+ NfwProtocolStack protocolStack;
+
+ /**
+ * Name of the protocol stack if protocolStack field is set to OTHER_PROTOCOL_STACK.
+ * Otherwise, set to empty string.
+ *
+ * This field is opaque to the framework and used for logging purposes.
+ */
+ char otherProtocolStackName[STRING_MAXLEN];
+
+ /** Source initiating/receiving the location information. */
+ NfwRequestor requestor;
+
+ /**
+ * Identity of the endpoint receiving the location information. For example, carrier
+ * name, OEM name, SUPL SLP/E-SLP FQDN, chipset vendor name, etc.
+ *
+ * This field is opaque to the framework and used for logging purposes.
+ */
+ char requestorId[STRING_MAXLEN];
+
+ /** Indicates whether location information was provided for this request. */
+ NfwResponseType responseType;
+
+ /** Is the device in user initiated emergency session. */
+ bool inEmergencyMode;
+
+ /** Is cached location provided */
+ bool isCachedLocation;
+} NfwNotification;
+
+/**
+ * Callback to report a non-framework delivered location.
+ *
+ * The GNSS HAL implementation must call this method to notify the framework whenever
+ * a non-framework location request is made to the GNSS HAL.
+ *
+ * Non-framework entities like low power sensor hubs that request location from GNSS and
+ * only pass location information through Android framework controls are exempt from this
+ * power-spending reporting. However, low power sensor hubs or other chipsets which may send
+ * the location information to anywhere other than Android framework (which provides user
+ * visibility and control), must report location information use through this API whenever
+ * location information (or events driven by that location such as "home" location detection)
+ * leaves the domain of that low power chipset.
+ *
+ * To avoid overly spamming the framework, high speed location reporting of the exact same
+ * type may be throttled to report location at a lower rate than the actual report rate, as
+ * long as the location is reported with a latency of no more than the larger of 5 seconds,
+ * or the next the Android processor awake time. For example, if an Automotive client is
+ * getting location information from the GNSS location system at 20Hz, this method may be
+ * called at 1Hz. As another example, if a low power processor is getting location from the
+ * GNSS chipset, and the Android processor is asleep, the notification to the Android HAL may
+ * be delayed until the next wake of the Android processor.
+ *
+ * @param notification Non-framework delivered location request/response description.
+ */
+typedef void (*vc_nfw_notify_cb) (NfwNotification notification);
+
+/**
+ * Tells if the device is currently in an emergency session.
+ *
+ * Emergency session is defined as the device being actively in a user initiated emergency
+ * call or in post emergency call extension time period.
+ *
+ * If the GNSS HAL implementation cannot determine if the device is in emergency session
+ * mode, it must call this method to confirm that the device is in emergency session before
+ * serving network initiated emergency SUPL and Control Plane location requests.
+ *
+ * @return success True if the framework determines that the device is in emergency session.
+ */
+typedef bool (*vc_is_in_emergency_session) ();
+
+typedef struct {
+ /** set to sizeof(GpsMeasurementCorrectionCallbacks) */
+ size_t size;
+ vc_nfw_notify_cb nfw_notify_cb;
+ vc_is_in_emergency_session is_in_emergency_session;
+} GnssVisibilityControlCallback_ext;
+
+
+
+typedef struct {
+
+ /** Set to sizeof(GnssVisibilityControlInterface) */
+ size_t size;
+
+ /**
+ * Registers the callback for HAL implementation to use.
+ *
+ * @param callback Handle to IGnssVisibilityControlCallback interface.
+ */
+ bool (*vc_set_callback) (GnssVisibilityControlCallback_ext* callbacks);
+
+ /**
+ * Enables/disables non-framework entity location access permission in the GNSS HAL.
+ *
+ * The framework will call this method to update GNSS HAL implementation every time the
+ * framework user, through the given proxy application(s) and/or device location settings,
+ * explicitly grants/revokes the location access permission for non-framework, non-user
+ * initiated emergency use cases.
+ *
+ * Whenever the user location information is delivered to non-framework entities, the HAL
+ * implementation must call the method IGnssVisibilityControlCallback.nfwNotifyCb() to notify
+ * the framework for user visibility.
+ *
+ * @param proxyApps Full list of package names of proxy Android applications representing
+ * the non-framework location access entities (on/off the device) for which the framework
+ * user has granted non-framework location access permission. The GNSS HAL implementation
+ * must provide location information only to non-framework entities represented by these
+ * proxy applications.
+ *
+ * The package name of the proxy Android application follows the standard Java language
+ * package naming format. For example, com.example.myapp.
+ *
+ * @return success True if the operation was successful.
+ */
+ bool (*vc_enable_nfw_location_access) (const char* proxyApps, int32_t length);
+
+}GnssVisibilityControlInterface;
+
+////////////////////// GNSS HIDL v2.1 ////////////////////////////
+
+/**
+ * Name for the GNSS measurement correction interface.
+ */
+#define GNSS_ANTENNA_INFO_INTERFACE "gnss_antenna_info"
+
+enum { //GnssMeasurementFlags
+ // v1.0
+ /** A valid 'snr' is stored in the data structure. */
+ HAS_SNR = 1 << 0,
+ /** A valid 'carrier frequency' is stored in the data structure. */
+ HAS_CARRIER_FREQUENCY = 1 << 9,
+ /** A valid 'carrier cycles' is stored in the data structure. */
+ HAS_CARRIER_CYCLES = 1 << 10,
+ /** A valid 'carrier phase' is stored in the data structure. */
+ HAS_CARRIER_PHASE = 1 << 11,
+ /** A valid 'carrier phase uncertainty' is stored in the data structure. */
+ HAS_CARRIER_PHASE_UNCERTAINTY = 1 << 12,
+ /** A valid automatic gain control is stored in the data structure. */
+ HAS_AUTOMATIC_GAIN_CONTROL = 1 << 13,
+
+ //v2.1
+ /*** A valid receiver inter-signal bias is stored in the data structure. */
+ HAS_RECEIVER_ISB = 1 << 16,
+ /*** A valid receiver inter-signal bias uncertainty is stored in the data structure. */
+ HAS_RECEIVER_ISB_UNCERTAINTY = 1 << 17,
+ /*** A valid satellite inter-signal bias is stored in the data structure. */
+ HAS_SATELLITE_ISB = 1 << 18,
+ /*** A valid satellite inter-signal bias uncertainty is stored in the data structure. */
+ HAS_SATELLITE_ISB_UNCERTAINTY = 1 << 19,
+};
+
+/**
+ * A row of doubles. This is used to represent a row in a 2D array, which are used to
+ * characterize the phase center variation corrections and signal gain corrections.
+ */
+typedef struct{
+ double row[6];
+} Row;
+
+/**
+ * A point in 3D space, with associated uncertainty.
+ */
+typedef struct {
+ double x;
+ double xUncertainty;
+ double y;
+ double yUncertainty;
+ double z;
+ double zUncertainty;
+} Coord;
+
+typedef struct {
+ /** The carrier frequency in MHz. */
+ double carrierFrequencyMHz;
+
+ /**
+ * Phase center offset (PCO) with associated 1-sigma uncertainty. PCO is defined with
+ * respect to the origin of the Android sensor coordinate system, e.g., center of primary
+ * screen for mobiles - see sensor or form factor documents for details.
+ */
+ Coord phaseCenterOffsetCoordinateMillimeters;
+
+ /**
+ * 2D vectors representing the phase center variation (PCV) corrections, in
+ * millimeters, at regularly spaced azimuthal angle (theta) and zenith angle
+ * (phi). The PCV correction is added to the phase measurement to obtain the
+ * corrected value.*/
+ Row phaseCenterVariationCorrectionMillimeters[3];
+
+ /**
+ * 2D vectors of 1-sigma uncertainty in millimeters associated with the PCV
+ * correction values.
+ *
+ * This field is optional, i.e., an empty vector.
+ */
+ Row phaseCenterVariationCorrectionUncertaintyMillimeters[3];
+
+ /**
+ * 2D vectors representing the signal gain corrections at regularly spaced
+ * azimuthal angle (theta) and zenith angle (phi). The values are calculated or
+ * measured at the antenna feed point without considering the radio and receiver
+ * noise figure and path loss contribution, in dBi, i.e., decibel over isotropic
+ * antenna with the same total power. The signal gain correction is added the
+ * signal gain measurement to obtain the corrected value.*/
+ Row signalGainCorrectionDbi[3];
+
+ /**
+ * 2D vectors of 1-sigma uncertainty in dBi associated with the signal
+ * gain correction values.
+ *
+ * This field is optional, i.e., an empty vector.
+ */
+ Row signalGainCorrectionUncertaintyDbi[3];
+} GnssAntennaInfo_ext;
+
+typedef struct {
+ /** The array of GnssAntennaInfo. */
+ GnssAntennaInfo_ext antennaInfos[2];
+} GnssAntennaInfos_ext;
+
+
+typedef void (*gnss_antenna_info_callback) (GnssAntennaInfos_ext* data);
+
+typedef struct {
+ /** set to sizeof(GnssAntennaInfoCallbacks) */
+ size_t size;
+ gnss_antenna_info_callback antenna_info_callback;
+} GnssAntennaInfoCallbacks;
+
+
+typedef struct {
+ /** Set to sizeof(GnssAntennaInfoInterface) */
+ size_t size;
+
+ int (*setCallback) (GnssAntennaInfoCallbacks* callbacks);
+
+ void (*close) ();
+
+} GnssAntennaInfoInterface;
+
+#if defined (__ANDROID_OS__)
+struct gps_device_t_ext {
+ struct hw_device_t common;
+
+ /**
+ * Set the provided lights to the provided values.
+ *
+ * Returns: 0 on succes, error code on failure.
+ */
+ const GpsInterface_ext* (*get_gps_interface)(struct gps_device_t_ext* dev);
+};
+#elif defined (__LINUX_OS__)
+struct gps_device_t_ext {
+ /**
+ * Set the provided lights to the provided values.
+ *
+ * Returns: 0 on succes, error code on failure.
+ */
+ const GpsInterface_ext* (*get_gps_interface)(struct gps_device_t_ext* dev);
+};
+#endif
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_MTK_H */
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnl2hal_basic_interface.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnl2hal_basic_interface.h
new file mode 100644
index 0000000..22e9749
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnl2hal_basic_interface.h
@@ -0,0 +1,50 @@
+#ifndef __MNL2HAL_BASIC_INTERFACE_H__
+#define __MNL2HAL_BASIC_INTERFACE_H__
+
+#include "hal_mnl_interface_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DUMP_BASIC_SERVER_CAP(pcap) do {\
+ LOGD("[%s]:mnl_hal_basic_server_cap size:%lu, gnss_support=%d", __func__, sizeof(mnl_hal_basic_server_cap), (pcap)->support_gnss);\
+} while(0)
+
+#define DUMP_BASIC_CLIENT_CAP(pcap) do {\
+ LOGD("[%s]:mnl_hal_basic_client_cap size:%lu, gnss_support=%d", __func__, sizeof(mnl_hal_basic_client_cap), (pcap)->support_gnss);\
+} while(0)
+
+typedef struct {
+ void (*gnss_init)(int fd);
+ void (*gnss_start)(int fd);
+ void (*gnss_stop)(int fd);
+ void (*gnss_cleanup)(int fd);
+ void (*set_measurement_enable)(bool enabled, int fd);
+ void (*client_capability_update)(int fd, mnl_hal_basic_client_cap *cap);
+} hal2mnl_basic_interface;
+
+int mnl2hal_location(gps_location location);
+int mnl2hal_gnss_status(gps_status status);
+int mnl2hal_gnss_status_one_client(gps_status status, int fd);
+int mnl2hal_gnss_sv(gnss_sv_info *sv);
+int mnl2hal_nmea(int64_t timestamp, const char* nmea, int length);
+int mnl2hal_nmea_done(void);
+int mnl2hal_gnss_measurements(gnss_data *data);
+
+int create_hal2mnl_basic_fd();
+
+int create_hal2mnl_ext_fd();
+
+void hal2mnl_basic_server_hdlr(int fd, int epfd);
+void hal2mnl_ext_server_hdlr(int fd, int epfd);
+void hal2mnl_basic_client_hdlr(int fd, hal2mnl_basic_interface* hdlr);
+
+void mnl_hal_basic_client_capability_query(int fd, mnl_hal_basic_client_cap *cap);
+void mnl_hal_basic_server_capability_query(int fd, mnl_hal_basic_server_cap *cap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnl2hal_ext_interface.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnl2hal_ext_interface.h
new file mode 100644
index 0000000..266c165
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnl2hal_ext_interface.h
@@ -0,0 +1,90 @@
+#ifndef __MNL2HAL_EXT_INTERFACE_H__
+#define __MNL2HAL_EXT_INTERFACE_H__
+
+#include "hal_mnl_interface_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DUMP_EXT_SERVER_CAP(pcap) do {\
+ LOGD("[%s]:mnl_hal_ext_server_cap size:%lu, gnss_support=%d", __func__, sizeof(mnl_hal_ext_server_cap), (pcap)->support_gnss);\
+} while(0)
+
+#define DUMP_EXT_CLIENT_CAP(pcap) do {\
+ LOGD("[%s]:mnl_hal_ext_client_cap size:%lu, gnss_support=%d", __func__, sizeof(mnl_hal_ext_client_cap), (pcap)->support_gnss);\
+} while(0)
+
+typedef struct {
+ void (*gnss_inject_time)(int64_t time, int64_t time_reference, int uncertainty);
+ void (*gnss_inject_location)(double lat, double lng, float acc);
+ void (*gnss_delete_aiding_data)(int flags);
+ void (*gnss_set_position_mode)(gps_pos_mode mode, gps_pos_recurrence recurrence,
+ int min_interval, int preferred_acc, int preferred_time, bool lowPowerMode);
+
+ void (*data_conn_open)(const char* apn);
+ void (*data_conn_open_with_apn_ip_type)(uint64_t network_handle, const char* apn, apn_ip_type ip_type);
+ void (*data_conn_closed)();
+ void (*data_conn_failed)();
+
+ void (*set_server)(agps_type type, const char* hostname, int port);
+ void (*set_ref_location)(cell_type type, int mcc, int mnc, int lac, int cid);
+ void (*set_id)(agps_id_type type, const char* setid);
+
+ void (*ni_message)(const char* msg, int len);
+ void (*ni_respond)(int notif_id, ni_user_response_type user_response);
+
+ void (*update_network_state)(uint64_t networkHandle, bool isConnected,
+ unsigned short capabilities, const char* apn);
+ void (*update_network_availability)(int available, const char* apn);
+
+ void (*set_gnss_full_tracking_enable)(bool enabled);
+ void (*set_gnss_navigation_enable)(bool enabled);
+ void (*set_vzw_debug)(bool enabled);
+ void (*update_gnss_config)(const char* config_data, int length);
+ void (*set_sv_blacklist)(long long* blacklist, int size);
+ void (*set_correction)(measurement_corrections* corrections);
+ void (*set_nfw_access)(char* proxyApps, int length);
+ void (*send_pmtk)(char* msg, int len);
+ void (*set_epo_enable)(epo_bitmap epo_cfg);
+ void (*set_ttff_acc)(ttff_acc acc_mode);
+ void (*client_capability_update)(int fd, mnl_hal_ext_client_cap *cap);
+} hal2mnl_ext_interface;
+
+int mnl2hal_mnld_reboot();
+
+int mnl2hal_gnss_navigation(gnss_nav_msg msg);
+
+int mnl2hal_request_wakelock();
+int mnl2hal_release_wakelock();
+
+int mnl2hal_request_utc_time();
+
+int mnl2hal_request_data_conn(struct sockaddr_storage addr, agps_type type);
+int mnl2hal_release_data_conn(agps_type type);
+int mnl2hal_request_ni_notify(int session_id, agps_ni_type ni_type, agps_notify_type type,
+ const char* requestor_id, const char* client_name, ni_encoding_type requestor_id_encoding,
+ ni_encoding_type client_name_encoding);
+int mnl2hal_request_set_id(request_setid flags);
+int mnl2hal_request_ref_loc(request_refloc flags);
+int mnl2hal_vzw_debug_screen_output(const char* str);
+int mnl2hal_update_gnss_name(const char* str, int len);
+int mnl2hal_request_nlp(bool type, bool fgemergency);
+int mnl2hal_agps_location(mnl_hal_agps_location *location);
+
+// -1 means failure
+void hal2mnl_ext_client_hdlr(int fd, hal2mnl_ext_interface* hdlr);
+
+// -1 means failure
+int create_hal2mnl_ext_fd();
+
+int mnl2hal_nfw_notify(nfw_notification *nfw_notify);
+
+void mnl_hal_ext_client_capability_query(int fd, mnl_hal_ext_client_cap *cap);
+void mnl_hal_ext_server_capability_query(int fd, mnl_hal_ext_server_cap *cap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnl2hal_interface.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnl2hal_interface.h
new file mode 100644
index 0000000..ea21146
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnl2hal_interface.h
@@ -0,0 +1,8 @@
+#ifndef __MNL2HAL_INTERFACE_H__
+#define __MNL2HAL_INTERFACE_H__
+
+#include "hal_mnl_interface_common.h"
+#include "mnl2hal_basic_interface.h"
+#include "mnl2hal_ext_interface.h"
+
+#endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnl_common.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnl_common.h
new file mode 100644
index 0000000..8240880
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnl_common.h
@@ -0,0 +1,241 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef _MNL_COMMON_H_
+#define _MNL_COMMON_H_
+/*******************************************************************************
+* Dependency
+*******************************************************************************/
+#ifdef MTK_LOG_ENABLE
+#undef MTK_LOG_ENABLE
+#endif
+#define MTK_LOG_ENABLE 1
+
+
+// #include <time.h>
+// #include <log/log.h>
+
+#if defined(__ANDROID_OS__)
+#include <hardware/gps.h>
+#elif defined(__LINUX_OS__)
+#include "gps.h"
+#endif
+#include "mtk_gps_type.h"
+
+#define FLAG_HOT_START 0x0
+#define FLAG_WARM_START MTK_GPS_DELETE_EPHEMERIS
+#define FLAG_COLD_START (MTK_GPS_DELETE_EPHEMERIS | MTK_GPS_DELETE_POSITION)
+#define FLAG_FULL_START (MTK_GPS_DELETE_ALL)
+#define FLAG_AGPS_START (MTK_GPS_DELETE_ALL&(~MTK_GPS_DELETE_CLK))
+#define FLAG_DELETE_EPH_ALM_START (MTK_GPS_DELETE_EPHEMERIS | MTK_GPS_DELETE_ALMANAC)
+#define FLAG_DELETE_TIME_START MTK_GPS_DELETE_TIME
+
+#define FLAG_AGPS_HOT_START MTK_GPS_DELETE_RTI
+#define FLAG_AGPS_WARM_START MTK_GPS_DELETE_EPHEMERIS
+#define FLAG_AGPS_COLD_START (MTK_GPS_DELETE_EPHEMERIS | MTK_GPS_DELETE_POSITION | MTK_GPS_DELETE_TIME\
+ | MTK_GPS_DELETE_IONO | MTK_GPS_DELETE_UTC | MTK_GPS_DELETE_HEALTH)
+#define FLAG_AGPS_FULL_START MTK_GPS_DELETE_ALL
+#define FLAG_AGPS_AGPS_START (MTK_GPS_DELETE_EPHEMERIS | MTK_GPS_DELETE_ALMANAC | MTK_GPS_DELETE_POSITION\
+ | MTK_GPS_DELETE_TIME | MTK_GPS_DELETE_IONO | MTK_GPS_DELETE_UTC)
+
+// extern UINT32 assist_data_bit_map;
+/******************************************************************************
+ * Definition
+******************************************************************************/
+#define C_INVALID_PID -1 /*invalid process id*/
+#define C_INVALID_TID (pthread_t)(-1) /*invalid thread id*/
+#define C_INVALID_FD -1 /*invalid file handle*/
+#define C_INVALID_SOCKET -1 /*invalid socket id*/
+#define C_INVALID_TIMER -1 /*invalid timer */
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+#define PMTK_CONNECTION_SOCKET 1
+#define PMTK_CONNECTION_SERIAL 2
+#define PMTK_CONNECTION_SOCKET_PORT 7000
+/******************************************************************************
+ * Function Configuration
+******************************************************************************/
+#define READ_PROPERTY_FROM_FILE
+/******************************************************************************/
+
+/*enumeration for NEMA debug level*/
+typedef enum {
+ MNL_NMEA_DEBUG_NONE = 0x0000,
+ MNL_NEMA_DEBUG_SENTENCE = 0x0001, /*only output sentence*/
+ MNL_NMEA_DEBUG_RX_PARTIAL = 0x0002,
+ MNL_NMEA_DEBUG_RX_FULL = 0x0004,
+ MNL_NMEA_DEBUG_TX_FULL = 0x0008,
+ MNL_NMEA_DEBUG_STORAGE = 0x0010,
+ MNL_NMEA_DEBUG_MESSAGE = 0x0020, /*mtk_sys_msg_send/mtk_sys_msg_recv*/
+
+ MNL_NMEA_DISABLE_NOTIFY = 0x1000,
+ /*output sentence and brief RX data*/
+ MNL_NMEA_DEBUG_NORMAL = MNL_NEMA_DEBUG_SENTENCE | MNL_NMEA_DEBUG_RX_PARTIAL,
+ /*output sentence and full RX/TX data*/
+ MNL_NMEA_DEBUG_FULL = 0x00FF,
+} MNL_NMEA_DEBUG;
+
+#define MNL_NFW_CTRL_MAIN_BIT (0x01)
+#define MNL_NFW_CTRL_GNSS_BIT (0x02)
+#define MNL_NFW_CTRL_NLP_BIT (0x04)
+
+typedef struct {
+ GpsUtcTime time;
+ int64_t timeReference;
+ int uncertainty;
+} ntp_context;
+
+typedef struct {
+ double latitude;
+ double longitude;
+ float accuracy;
+ struct timespec ts;
+ unsigned char type;
+ unsigned char started;
+} nlp_context;
+
+/*******************************************************************************/
+/* configruation property */
+typedef struct {
+ /*used by mnl_process.c*/
+ int init_speed;
+ int link_speed;
+ int debug_nmea;
+ int debug_mnl;
+ int pmtk_conn; /*PMTK_CONNECTION_SOCKET | PMTK_CONNECTION_SERIAL*/
+ int socket_port; /*PMTK_CONNECTION_SOCKET*/
+ char dev_dbg[32]; /*PMTK_CONNECTION_SERAIL*/
+ char dev_dsp[32];
+ char dev_dsp2[32]; //For GPS L5
+ char dev_gps[32];
+ char bee_path[32];
+ char epo_file[30];
+ char epo_update_file[30];
+ char qepo_file[30];
+ char qepo_update_file[30];
+ char mnl_cfg_xml_default_path[32];
+ char mnl_read_write_path[32];
+ int delay_reset_dsp; /*the delay time after issuing MTK_PARAM_CMD_RESET_DSP*/
+ int nmea2file;
+ int dbg2file;
+ int nmea2socket;
+ int dbg2socket;
+ UINT32 dbglog_file_max_size; // The max size limitation of one debug log file
+ UINT32 dbglog_folder_max_size; // The max size limitation of the debug log folder
+ char debug_file_name[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+
+ /*used by mnld.c*/
+ int timeout_init;
+ int timeout_monitor;
+ int timeout_wakeup;
+ int timeout_sleep;
+ int timeout_pwroff;
+ int timeout_ttff;
+
+ /*used by agent*/
+ int EPO_enabled;
+ int BEE_enabled;
+ int SUPL_enabled;
+ int SUPLSI_enabled;
+ int EPO_priority;
+ int BEE_priority;
+ int SUPL_priority;
+ int fgGpsAosp_Ver;
+
+ /*for FM TX*/
+ int AVAILIABLE_AGE;
+ int RTC_DRIFT;
+ int TIME_INTERVAL;
+ char u1AgpsMachine;
+ int ACCURACY_SNR;
+ int GNSSOPMode;
+ int OFFLOAD_enabled;
+ int OFFLOAD_testMode;
+ int OFFLOAD_switchMode; //0: always offload mode 1: Offload/Host-base auto switch mode
+ int log_hide; //overwrite mtk_gps_log_hide if mtk_gps_log_hide == 0
+ int adc_capture_enabled;
+ int fix_interval; /* fix interval in milliseconds */
+
+ #if defined(GPS_SUSPEND_SUPPORT)
+ int SUSPEND_enabled;
+ int SUSPEND_timeout;
+ int SUSPEND_ext_enabled; //Add for clock extension, request from libmnl
+ int SUSPEND_ext_timeout; //Add for clock extension
+ int SUSPEND_ext_available; //Add for clock extension, available for platform or not
+ #endif
+ int fast_HTTFF;
+ //bit0: Main switch of NFW visibility and notify mechanism, 0: disable NFW visibility and notify mechanism, always sync location to NFW user
+ //bit1: Switch of FW visibility and notify mechanism of GNSS location sycn to NFW user
+ //bit2: Switch of FW visibility and notify mechanism of NLP location sync to NFW user
+ int bitmap_nfw_ctrl;
+ float RfPathLossDb_Ap; //RF path loss
+
+ /*for pps*/
+ int pps_mode; /* 1PPS mode, Default: MTK_PPS_DISABLE */
+ int pps_delay; /* range: 0~2000 unit: ns */
+ int pps_polarity; /* pps polarity, Range: 0~1, Default: 0, 0: pps active low 1: pps active high */
+ int pps_duty; /* PPS pulse high duration (ms), Range: 0~2000, Default: 0 */
+
+int elev_mask; /* elevation angle mask in degree, Range: 0~90, Default: 5 */
+} MNL_CONFIG_T;
+/*---------------------------------------------------------------------------*/
+typedef struct {
+ time_t uSecond_start;
+ time_t uSecond_expire;
+}MNL_EPO_TIME_T;
+/*---------------------------------------------------------------------------*/
+typedef struct {
+ int notify_fd;
+ int port;
+} MNL_DEBUG_SOCKET_T;
+/*---------------------------------------------------------------------------*/
+#ifdef _MNL_COMMON_C_
+ #define C_EXT
+#else
+ #define C_EXT extern
+#endif
+/*---------------------------------------------------------------------------*/
+#ifdef READ_PROPERTY_FROM_FILE
+C_EXT int mnl_utl_load_property(MNL_CONFIG_T* prConfig);
+
+C_EXT void mnld_write_cfg(char* key, char* val);
+#endif
+/*---------------------------------------------------------------------------*/
+#undef C_EXT
+/*---------------------------------------------------------------------------*/
+
+int str2int(const char* p, const char* end);
+
+#endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnld.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnld.h
new file mode 100755
index 0000000..e5dd7dc
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnld.h
@@ -0,0 +1,342 @@
+#ifndef __MNLD_H__
+#define __MNLD_H__
+
+#include <time.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "mnl2hal_interface.h"
+#include "mtk_socket_utils.h"
+#include "mtk_gps_type.h"
+#include "mnl2agps_interface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MNLD_MAIN_SOCKET "mnld_main_socket"
+#define MNLD_GPS_CONTROL_SOCKET "mnld_gps_control_socket"
+#define MNLD_EPO_DOWNLOAD_SOCKET "mnld_epo_download_socket"
+#define MNLD_QEPO_DOWNLOAD_SOCKET "mnld_qepo_download_socket"
+#define MNLD_MTKNAV_DOWNLOAD_SOCKET "mnld_mtknav_download_socket"
+#define MNLD_OP01_LOG_WRITER_SOCKET "mnld_op01_log_write_socket"
+#define MNLD_TO_NLP_UTILS_SOCKET "mtk_mnld2nlputils"
+#define MNLD_MPE_SOCKET "mnld_mpe_socket"
+#define META_TO_MNLD_LOGCTRL_SOCKET "mtk_meta2mnld_logctrl"
+#define DEBUG_TO_MNLD_SOCKET "mtk_debugService2mnld"
+#define MNLD_TO_DEBUG_SOCKET "mtk_mnld2debugService"
+#define MNLD_TO_MTKLOGGER_SOCKET "mtk_mnld2mtklogger"
+#define MTKLOGGER_TO_MNLD_SOCKET "mtk_mtklogger2mnld"
+#define LOG_HIDL_INTERFACE "mtk_lbs_log_v2s"
+#define GPS_L5_SUPPORT_P "vendor.debug.gps.support.l5"
+#define MNLD_NFW_PROXY_NAME "com.mediatek.gnss.nonframeworklbs"
+
+#define NLP_REQUEST_SRC_MNL (1 << 0)
+#define NLP_REQUEST_SRC_APM (1 << 1)
+
+#if defined(__ANDROID_OS__)
+#define MNLD_OP01_LOG_PATH "/sdcard/GPS.LOG"
+#else
+#define MNLD_OP01_LOG_PATH "GPS.LOG"
+#endif
+
+#define MNLD_MAIN_HANDLER_TIMEOUT (30 * 1000)
+#define MNLD_GPS_HANDLER_TIMEOUT (30 * 1000)
+#define MNLD_EPO_HANDLER_TIMEOUT (120 * 60 * 1000)
+#define MNLD_EPO_RETRY_HANDLER_TIMEOUT (30 * 1000)
+#define MNLD_QEPO_HANDLER_TIMEOUT (120 * 60 * 1000)
+#define MNLD_OP01_HANDLER_TIMEOUT (20 * 1000)
+#define MNLD_MPE_HANDLER_TIMEOUT (30 * 1000)
+#define MNLD_GPS_START_TIMEOUT (35 * 1000)
+#define MNLD_GPS_STOP_TIMEOUT (30 * 1000)
+#define MNLD_GPS_RESET_TIMEOUT (30 * 1000)
+#define MNLD_GPS_NMEA_DATA_TIMEOUT (10 * 1000)
+#define MNLD_GPS_LOG_HANDLER_TIMEOUT (60 * 1000)
+//#define MNLD_GPS_SWITCH_OFL_MODE_TIMEOUT (30 * 1000)
+
+//Now it's 0, standing for change SUSPEND to CLOSE immediately when screen off
+#define MNLD_GPS_SUSPEND_TIMEOUT (0) //(120 * 1000)
+
+#define MNLD_INTERNAL_BUFF_SIZE (8 * 1024)
+#define MNLD_TO_APP_BUFF_SIZE (1023)
+
+#define MNLD_NFW_USER_NAME_LEN (64)
+#define MNLD_NFW_USER_NUM_MAX (10)
+
+#define MNLD_HAL_CLIENT_NUM (10)
+
+typedef enum {
+ MNLD_NFW_USER_AGPS = 0,
+ MNLD_NFW_USER_NUM
+} MNLD_NFW_USER;
+
+typedef enum {
+ MNLD_GPS_STATE_IDLE = 0,
+ MNLD_GPS_STATE_STARTING = 1,
+ MNLD_GPS_STATE_STARTED = 2,
+ MNLD_GPS_STATE_STOPPING = 3,
+ MNLD_GPS_STATE_OFL_STARTING = 4,
+ MNLD_GPS_STATE_OFL_STARTED = 5,
+ MNLD_GPS_STATE_OFL_STOPPING = 6,
+ MNLD_GPS_STATE_SUSPEND = 7,
+} mnld_gps_state;
+
+typedef enum {
+ GPS_EVENT_START = 0,
+ GPS_EVENT_STOP = 1,
+ GPS_EVENT_RESET = 2,
+ GPS_EVENT_START_DONE = 3,
+ GPS_EVENT_STOP_DONE = 4,
+ GPS_EVENT_OFFLOAD_START = 5,
+ GPS_EVENT_SUSPEND = 6,
+ GPS_EVENT_SUSPEND_DONE = 7,
+ GPS_EVENT_SUSPEND_CLOSE = 8,
+} mnld_gps_event;
+
+typedef enum {
+ MNLD_GPS_DO_HW_RESUME = 0,
+ MNLD_GPS_DO_HW_SUSPEND = 1,
+} mnld_gps_do_hw_ctrl_opcode;
+
+typedef enum {
+ GPS2MAIN_EVENT_START_DONE = 0,
+ GPS2MAIN_EVENT_STOP_DONE = 1,
+ GPS2MAIN_EVENT_RESET_DONE = 2,
+ GPS2MAIN_EVENT_NMEA_TIMEOUT = 3,
+ GPS2MAIN_EVENT_UPDATE_LOCATION = 4,
+ EPO2MAIN_EVENT_EPO_DONE = 5,
+ QEPO2MAIN_EVENT_QEPO_DONE = 6,
+ QEPO2MAIN_EVENT_QEPO_BD_DONE = 7,
+ MTKNAV2MAIN_EVENT_MTKNAV_DONE = 8,
+ QEPO2MAIN_EVENT_QEPO_GA_DONE = 9,
+ GPS2MAIN_EVENT_OUTPUT_DATA = 10,
+ SCREEN2MAIN_EVENT_SCREEN_ON = 11,
+ SCREEN2MAIN_EVENT_SCREEN_OFF = 12,
+ SCREEN2MAIN_EVENT_SCREEN_UNKNOWN = 13,
+ GPS2MAIN_EVENT_SUSPEND_DONE = 14,
+ GPS2MAIN_EVENT_SUSPEND_TIMEOUT = 15,
+ GPS2MAIN_EVENT_UPDATE_SV = 16,
+ GPS2MAIN_EVENT_NMEA_DONE = 17,
+} main_internal_event;
+
+typedef enum {
+ DATA_DEBUG2APP = 0,
+ DATA_ENDLIST
+} main_out_put_data_type;
+
+typedef enum {
+ EPO_DOWNLOAD_RESULT_SUCCESS = 0,
+ EPO_DOWNLOAD_RESULT_NO_UPDATE = 1,
+ EPO_DOWNLOAD_RESULT_FAIL = -1,
+ EPO_DOWNLOAD_RESULT_RETRY_TOO_MUCH = -2,
+} epo_download_result;
+
+typedef enum {
+ EPO_MD5_FILE_UPDATED = 0,
+ EPO_MD5_FILE_NO_UPDATE = 1,
+ EPO_MD5_DOWNLOAD_RESULT_FAIL = -1,
+} epo_md5_download_result;
+
+typedef struct {
+ int fd_hal_basic_server;
+ int fd_hal_ext_server;
+ int fd_agps;
+ //int fd_flp;
+ //int fd_flp_test;
+ int fd_geofence;
+ int fd_geofence_control;
+ int fd_at_cmd;
+ int fd_int;
+ int fd_mtklogger;
+ mtk_socket_fd fd_mtklogger_client;
+ int fd_meta;
+ int fd_meta_logctrl;
+ int fd_debug;
+#if defined(GPS_SUSPEND_SUPPORT)
+ int fd_suspend_timer;
+#endif
+ mtk_socket_fd fd_nlp_utils;
+ mtk_socket_fd fd_debug_client;
+} mnld_fds;
+
+typedef struct {
+ bool gps_used;
+ bool need_open_ack;
+ bool need_close_ack;
+ bool need_reset_ack;
+} mnld_gps_client;
+
+typedef struct {
+ mnld_gps_client hal;
+ mnld_gps_client agps;
+ mnld_gps_client flp;
+ mnld_gps_client flp_test;
+ mnld_gps_client geofence;
+ mnld_gps_client at_cmd_test;
+ mnld_gps_client factory;
+ mnld_gps_client raw_meas; //RAW measurement
+} mnld_gps_clients;
+
+typedef struct {
+ mnld_gps_clients clients;
+ mnld_gps_state gps_state;
+ bool is_gps_init;
+ bool is_gps_meas_enabled;
+ bool is_gps_navi_enabled;
+#if defined(GPS_SUSPEND_SUPPORT)
+ bool is_suspend_timer_running;
+#endif
+ bool is_in_nmea_timeout_handler;
+ unsigned int delete_aiding_flag;
+
+ timer_t timer_start;
+ timer_t timer_stop;
+ timer_t timer_reset;
+ timer_t timer_nmea_monitor;
+ timer_t timer_switch_ofl_mode;
+#if defined(GPS_SUSPEND_SUPPORT)
+ timer_t timer_suspend;
+#endif
+ time_t gps_start_time;
+ time_t gps_stop_time;
+ time_t gps_ttff;
+ bool wait_first_location;
+} mnld_gps_status;
+
+typedef struct {
+ bool is_network_connected;
+ bool is_wifi_connected;
+ bool is_epo_downloading;
+} mnl_epo_status;
+
+typedef enum {
+ SCREEN_STATUS_UNKNOWN = -1,
+ SCREEN_STATUS_OFF = 0,
+ SCREEN_STATUS_ON = 1,
+} mnld_screen_status;
+
+typedef struct {
+ mnld_fds fds;
+ mnld_gps_status gps_status;
+ mnl_epo_status epo_status;
+ mnld_screen_status screen_status;
+ bool nfw_user_visibility[MNLD_NFW_USER_NUM];
+} mnld_context;
+
+typedef enum {
+ MD_TIME_SYNC_IDLE = 0, //mnld begin run.
+ MD_TIME_SYNC_REQUESTING = 1, // mnl has already required time ,but did not receieve MD ack.
+ MD_TIME_SYNC_REQUESTED = 2, //mnl has already required time ,and receieve MD ack.
+ MD_TIME_SYNC_TIME_INJECTED = 3 //mnl has already received MD time aiding.
+} md_time_sync_status;
+
+
+typedef struct md_time_sync_context md_ts_context;
+
+struct md_time_sync_context {
+ pthread_mutex_t lock;
+ bool inited;
+ unsigned short transactionID;
+ md_time_sync_status status;
+ mnl_md_time_info_rsp_struct time;
+};
+
+typedef enum {
+ NLP_FRAMEWORK = 0,
+ NLP_C2K_CELL = 1,
+ NLP_ENDLIST
+} nlp_type;
+
+// GPS Control -> MAIN
+int sys_gps_mnl_data2mnld_callback(const char *data, unsigned int length);
+void mnld_gps_output_data_handle(char* buff, int off_set);
+int mnld_gps_start_done(bool is_assist_req);
+int mnld_gps_stop_done();
+int mnld_gps_reset_done();
+int mnld_gps_update_location(gps_location location, int fix_mod);
+int mnld_gps_update_sv(gnss_sv_info *sv_status);
+
+// EPO Download -> MAIN
+int mnld_epo_download_done(epo_download_result result);
+int mnld_qepo_download_done(epo_download_result result);
+int mnld_mtknav_download_done(epo_download_result result);
+int mnld_qepo_bd_download_done(epo_download_result result);
+int mnld_qepo_ga_download_done(epo_download_result result);
+
+void hal_start_gps_trigger_epo_download();
+bool is_network_connected();
+bool is_wifi_network_connected();
+
+// Provided for GPS Control to check the status
+bool mnld_is_gps_started();
+bool mnld_is_gps_or_ofl_started();
+bool mnld_is_gps_started_done();
+bool mnld_is_gps_or_ofl_started_done();
+bool mnld_is_gps_meas_enabled();
+bool mnld_is_gps_navi_enabled();
+bool mnld_is_gps_stopped();
+#if defined(GPS_SUSPEND_SUPPORT)
+bool mnld_is_gps_suspend();
+bool mnld_gps_suspend_mode_entry_check(void);
+#endif
+bool mnld_is_gps_and_ofl_stopped();
+bool mnld_is_epo_download_finished();
+
+int mnld_gps_controller_mnl_nmea_timeout(void);
+int mnld_gps_start_nmea_monitor(void);
+int mnld_gps_stop_nmea_monitor(void);
+void gps_mnld_restart_mnl_process(void);
+void mnld_gps_request_nlp(int src);
+
+unsigned int mtk_gps_get_gps_user(void);
+
+void factory_mnld_gps_start(void);
+void factory_mnld_gps_stop(void);
+
+void flp_test2mnl_gps_stop(void);
+
+int is_geofence_user_exist();
+
+int mnld_screen_on_notify();
+int mnld_screen_off_notify();
+int mnld_screen_unknown_notify();
+
+bool mtk_gps_get_nfw_visibility(MNLD_NFW_USER nfw_user);
+void mnld_nfw_set_default_notification(MNLD_NFW_USER usr);
+void mnld_nfw_notify2hal(MNLD_NFW_USER usr, nfw_response_type response_type);
+void mnld_nfw_notify2hal_default(MNLD_NFW_USER usr, nfw_response_type response_type);
+void mnld_nfw_mnl2agps_location_sync(mnl_agps_location_time* location_sync_data);
+void mtk_gps_set_nfw_visibility(int usr, bool set_value);
+void mtk_gps_set_nfw_visibility_all(bool set_value);
+
+void mtk_gps_dump_nfw_visibility(void);
+int mnld_show_icon_get(void);
+void mnld_show_icon_set(int show_gps_icon);
+void mnld_init_time_aiding_ctx(void);
+void mnld_feadback_time_to_MD(gnss_timeOfDay_with_unc* tod);
+void mnld_request_MD_time_sync(md_time_require_action action);
+void mnld_ACK_to_MD_time(unsigned short transactionID);
+void md_time_sync_ind (const char* data, int len);
+void md_time_sync_cnf (const char* data, int len);
+
+void hal_gnss_stop(int fd);
+void hal_gnss_cleanup(int fd);
+void hal_raw_meas_gps_stop(int fd);
+int mnld_gnss_nmea_done(void);
+
+void set_clk_ext_ni_only(int flag);
+bool is_clk_ext_ni_only();
+
+
+void mnld_set_sv_inuse_valid(bool valid);
+void mnld_set_sv_inuse_num(int num);
+bool mnld_get_sv_inuse_num_valid();
+int mnld_get_sv_inuse_num();
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnld_utile.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnld_utile.h
new file mode 100644
index 0000000..d4b9914
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mnld_utile.h
@@ -0,0 +1,264 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+ #define PMTK_MAX_PKT_LENGTH 256
+
+#ifdef MTK_GPS_DUAL_FREQ_SUPPORT /*Defined in Android.mk*/
+#define DSP_DEV "/dev/gpsdl0" /* device for L1 */
+#define DSP_DEV2 "/dev/gpsdl1" /* device for L5 */
+#else
+#define DSP_DEV "/dev/stpgps" /* stp-gps char dev*/
+#define DSP_DEV2 "none" /* DSP2 invalid*/
+#endif
+
+/*****************************************************************************
+ * FUNCTION
+ * power_on_3332
+ * DESCRIPTION
+ * power on MT3332 chip for chip detector.
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+void power_on_3332();
+
+/*****************************************************************************
+ * FUNCTION
+ * power_off_3332
+ * DESCRIPTION
+ * power off MT3332 chip when chip detect done.
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+void power_off_3332();
+
+
+/*****************************************************************************
+ * FUNCTION
+ * read_NVRAM
+ * DESCRIPTION
+ * Read NVRAM to check if the uart is for MT3332
+ * PARAMETERS
+ *
+ * RETURNS
+ * 1: NOT mt3332, -1: read error, 0:read ok
+ *****************************************************************************/
+int read_NVRAM();
+
+/*****************************************************************************
+ * FUNCTION
+ * init_3332_interface
+ * DESCRIPTION
+ * Init UART parameter.
+ * PARAMETERS
+ * fd [IN]: UART fd
+ * RETURNS
+ * success(0); failure (-1)
+ *****************************************************************************/
+int init_3332_interface(const int fd);
+
+
+/*****************************************************************************
+ * FUNCTION
+ * hw_test_3332
+ * DESCRIPTION
+ * Send command to MT3332 Chip and wait response to check if it is MT3332 CHIP
+ * PARAMETERS
+ * fd [IN]: UART fd
+ * RETURNS
+ * 0: means MT3332, 1 means not MT3332
+ *****************************************************************************/
+int hw_test_3332(const int fd);
+
+/*****************************************************************************
+ * FUNCTION
+ * hand_shake
+ * DESCRIPTION
+ * Hand shake with MT3332 chip
+ * PARAMETERS
+ *
+ * RETURNS
+ * 0: means MT3332, 1 means not MT3332
+ *****************************************************************************/
+int hand_shake();
+
+/*****************************************************************************
+ * FUNCTION
+ * confirm_if_3332
+ * DESCRIPTION
+ * confirm if it is MT3332
+ * PARAMETERS
+ *
+ * RETURNS
+ * 0: means MT3332, 1 means not MT3332
+ *****************************************************************************/
+int confirm_if_3332();
+
+/*****************************************************************************
+ * FUNCTION
+ * chip_detector
+ * DESCRIPTION
+ * To get GPS chip ID
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+void chip_detector();
+// confirm MT3332 chip - end
+
+/*****************************************************************************
+ * FUNCTION
+ * buff_get_int
+ * DESCRIPTION
+ * To get a INT data from buff.
+ * PARAMETERS
+ * buff [IN]: Store INT data
+ * offset [IN]: offset
+ * RETURNS
+ *
+ *****************************************************************************/
+int buff_get_int(const char* buff, int* offset);
+
+/*****************************************************************************
+ * FUNCTION
+ * buff_put_int
+ * DESCRIPTION
+ * To put a INT data to a buff.
+ * PARAMETERS
+ * input [IN]: Input data
+ * buff [IN]: Dest buffer
+ * offset [IN]: offset
+ * RETURNS
+ *
+ *****************************************************************************/
+void buff_put_int(int input, char* buff, int* offset);
+
+/*****************************************************************************
+ * FUNCTION
+ * buff_put_string
+ * DESCRIPTION
+ * To put CHAR data to a buff.
+ * PARAMETERS
+ * str [IN]: Input data
+ * buff [IN]: Dest buffer
+ * offset [IN]: offset
+ * RETURNS
+ *
+ *****************************************************************************/
+void buff_put_string(const char* str, char* buff, int* offset);
+
+/*****************************************************************************
+ * FUNCTION
+ * buff_put_struct
+ * DESCRIPTION
+ * To put struct data to a buff.
+ * PARAMETERS
+ * input [IN]: Input data
+ * size [IN]: Input struct size
+ * buff [IN]: Dest buffer
+ * offset [IN]: offset
+ * RETURNS
+ *
+ *****************************************************************************/
+void buff_put_struct(const void* input, int size, char* buff, int* offset);
+
+/*****************************************************************************
+ * FUNCTION
+ * buff_get_struct
+ * DESCRIPTION
+ * To get struct data from a buff.
+ * PARAMETERS
+ * input [OUT]: Dest buffer
+ * size [IN]: The length to get
+ * buff [IN]: Original buffer
+ * offset [IN]: offset
+ * RETURNS
+ *
+ *****************************************************************************/
+void buff_get_struct(char* output, int size, const char* buff, int* offset);
+
+/*****************************************************************************
+ * FUNCTION
+ * buff_get_binary
+ * DESCRIPTION
+ * To get binary data from a buff.
+ * PARAMETERS
+ * output [OUT]: Dest buffer
+ * buff [IN]: Original buffer
+ * offset [IN]: offset
+ * RETURNS
+ *
+ *****************************************************************************/
+int buff_get_binary(void* output, const char* buff, int* offset);
+
+/*****************************************************************************
+ * FUNCTION
+ * add_chksum
+ * DESCRIPTION
+ * To add checksum in a buff
+ * buff [IN]: buffer
+ * RETURNS
+ *
+ *****************************************************************************/
+int add_chksum(char *pBuf);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_log_is_hide
+ * DESCRIPTION
+ * To check hide the gps log or not
+ * buff [IN]: void
+ * RETURNS
+ * 0: Print GPS log normally; 1: not print location sensitivity log
+ * (include gps debug log);
+ *****************************************************************************/
+int mtk_gps_log_is_hide(void);
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_log_get_hide_opt
+ * DESCRIPTION
+ * To check gps log hide option
+ * buff [IN]: void
+ * RETURNS
+ * 0: Print GPS log normally; 1: not print location sensitivity log;
+ * 2: encrypt and print location sensitivity log;
+ *****************************************************************************/
+int mtk_gps_log_get_hide_opt(void);
+
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mpe.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mpe.h
new file mode 100644
index 0000000..3f28aa5
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mpe.h
@@ -0,0 +1,16 @@
+#ifndef __MPE_H__
+#define __MPE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int mpe_function_init(void);
+int mnl_mpe_thread_init();
+int mnl2mpe_set_log_path(const char* path, int status_flag, int mode_flag);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mtknav.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mtknav.h
new file mode 100644
index 0000000..a818666
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/mtknav.h
@@ -0,0 +1,31 @@
+#ifndef __MTKNAV_H__
+#define __MTKNAV_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MTKNAV_DL_RETRY_TIME 3
+#define MTKNAV_MD5_FILE MTK_GPS_DATA_PATH"MTKNAV.MD5"
+#define MTKNAV_MD5_FILE_HAL MTK_GPS_DATA_PATH"MTKNAVHAL.MD5"
+#define MTKNAV_DAT_FILE MTK_GPS_DATA_PATH"MTKNAV.DAT"
+#define MTKNAV_DAT_FILE_HAL MTK_GPS_DATA_PATH"MTKNAVHAL.DAT"
+
+extern bool mtknav_update_flag;
+extern int mtknav_res;
+
+int mtknav_downloader_init();
+
+int mtknav_downloader_start();
+
+void mtknav_update_mtknav_file(int mtknav_valid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/nmea_parser.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/nmea_parser.h
new file mode 100644
index 0000000..eee6508
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/nmea_parser.h
@@ -0,0 +1,228 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef __NMEA_PARSER_H__
+#define __NMEA_PARSER_H__
+
+#include "hal_mnl_interface_common.h"
+#include "mnl_common.h"
+
+// for different SV parse
+typedef enum {
+ UNKNOWN_SV = 0,
+ GPS_SV,
+ SBAS_SV,
+ GLONASS_SV,
+ QZSS_SV,
+ BDS_SV,
+ GALILEO_SV,
+ IRNSS_SV,
+} SV_TYPE;
+
+typedef enum {
+ GNSS_SYSTEM_ID_GP = 1,
+ GNSS_SYSTEM_ID_GL = 2,
+ GNSS_SYSTEM_ID_GA = 3,
+ GNSS_SYSTEM_ID_BD = 4,
+ GNSS_SYSTEM_ID_QZ = 5,
+ GNSS_SYSTEM_ID_IR = 6,
+ GNSS_SYSTEM_ID_SBAS = 7,
+ GNSS_SYSTEM_ID_MAX,
+} GNSS_SYSTEM_ID;
+
+typedef enum {
+ SIGNAL_ID_GP_ALL = 0,
+ SIGNAL_ID_GP_L1_CA = 1,
+ SIGNAL_ID_GP_L1_P = 2,
+ SIGNAL_ID_GP_L1_M = 3,
+ SIGNAL_ID_GP_L2_P = 4,
+ SIGNAL_ID_GP_L2C_M = 5,
+ SIGNAL_ID_GP_L2C_L = 6,
+ SIGNAL_ID_GP_L5_I = 7,
+ SIGNAL_ID_GP_L5_Q = 8,
+} SIGNAL_ID_GP;
+
+typedef enum {
+ SIGNAL_ID_QZ_ALL = 0,
+ SIGNAL_ID_QZ_L1_CA = 1,
+ SIGNAL_ID_QZ_L1_CD = 2,
+ SIGNAL_ID_QZ_L1_CP = 3,
+ SIGNAL_ID_QZ_LIS = 4,
+ SIGNAL_ID_QZ_L2_CM = 5,
+ SIGNAL_ID_QZ_L2_CL = 6,
+ SIGNAL_ID_QZ_L5_I = 7,
+ SIGNAL_ID_QZ_L5_Q = 8,
+ SIGNAL_ID_QZ_L6_D = 9,
+ SIGNAL_ID_QZ_L6_E = 10,
+
+} SIGNAL_ID_QZ;
+
+typedef enum {
+ SIGNAL_ID_GL_ALL = 0,
+ SIGNAL_ID_GL_G1_CA = 1,
+ SIGNAL_ID_GL_G1_P = 2,
+ SIGNAL_ID_GL_G2_CA = 3,
+ SIGNAL_ID_GL_G2_P = 4,
+} SIGNAL_ID_GL;
+
+typedef enum {
+ SIGNAL_ID_GA_ALL = 0,
+ SIGNAL_ID_GA_E5A = 1,
+ SIGNAL_ID_GA_E5B = 2,
+ SIGNAL_ID_GA_E5AB = 3,
+ SIGNAL_ID_GA_E6_A = 4,
+ SIGNAL_ID_GA_E6_BC = 5,
+ SIGNAL_ID_GA_L1_A = 6,
+ SIGNAL_ID_GA_L1_BC = 7,
+} SIGNAL_ID_GA;
+
+typedef enum {
+ SIGNAL_ID_BD_ALL = 0,
+ SIGNAL_ID_BD_B1_I = 1,
+ SIGNAL_ID_BD_B1_Q = 2,
+ SIGNAL_ID_BD_B1_C = 3,
+ SIGNAL_ID_BD_B1_A = 4,
+ SIGNAL_ID_BD_B2_a = 5,
+ SIGNAL_ID_BD_B2_b = 6,
+ SIGNAL_ID_BD_B2_ab = 7,
+ SIGNAL_ID_BD_B3_I = 8,
+ SIGNAL_ID_BD_B3_Q = 9,
+ SIGNAL_ID_BD_B3_A = 10,
+ SIGNAL_ID_BD_B2_I = 11,
+ SIGNAL_ID_BD_B2_Q = 12,
+} SIGNAL_ID_BD;
+
+#define MNLD_SV_STR_GPS_L1 "GPS L1"
+#define MNLD_SV_STR_GPS_L5 "GPS L5"
+#define MNLD_SV_STR_SBAS "SBAS"
+#define MNLD_SV_STR_GLONASS "Glonass"
+#define MNLD_SV_STR_QZSS_L1 "QZSS L1"
+#define MNLD_SV_STR_QZSS_L5 "QZSS L5"
+#define MNLD_SV_STR_BEIDOU_B1 "Beidou B1"
+#define MNLD_SV_STR_BEIDOU_B2A "Beidou B2a"
+#define MNLD_SV_STR_GALILEO_E1 "Galileo E1"
+#define MNLD_SV_STR_GALILEO_E5A "Galileo E5a"
+#define MNLD_SV_STR_IRNSS "IRNSS"
+
+typedef enum {
+ SV_SYSTEM_GPS_L1 = 0,
+ SV_SYSTEM_GPS_L5 = 1,
+ SV_SYSTEM_SBAS = 2,
+ SV_SYSTEM_GLONASS,
+ SV_SYSTEM_QZSS_L1,
+ SV_SYSTEM_QZSS_L5,
+ SV_SYSTEM_BEIDOU_B1,
+ SV_SYSTEM_BEIDOU_B2A,
+ SV_SYSTEM_GALILEO_E1,
+ SV_SYSTEM_GALILEO_E5A,
+ SV_SYSTEM_IRNSS,
+ SV_SYSTEM_NUMBER,
+ SV_SYSTEM_UNKNOWN = 255,
+} SV_SYSTEM;
+
+typedef enum {
+ SIGNAL_ID_IR_ALL = 0,
+ SIGNAL_ID_IR_L5_SPS = 1,
+ SIGNAL_ID_IR_S_SPS = 2,
+ SIGNAL_ID_IR_L5_RS = 3,
+ SIGNAL_ID_IR_S_RS = 4,
+ SIGNAL_ID_IR_L1_SPS = 5,
+} SIGNAL_ID_IR;
+
+/*****************************************************************/
+/*****************************************************************/
+/***** *****/
+/***** N M E A P A R S E R *****/
+/***** *****/
+/*****************************************************************/
+/*****************************************************************/
+#define MTK_SV_NUMBER 32
+
+#define NMEA_MAX_SIZE 255
+/*maximum number of SV information in GPGSV*/
+#define NMEA_MAX_SV_INFO 4
+#define LOC_FIXED(pNmeaReader) ((pNmeaReader->fix_mode == 2) || (pNmeaReader->fix_mode ==3))
+typedef struct {
+ int pos;
+ int overflow;
+ int utc_year;
+ int utc_mon;
+ int utc_day;
+ int utc_diff;
+ gps_location fix;
+
+ /*
+ * The fix flag extracted from GPGSA setence: 1: No fix; 2 = 2D; 3 = 3D
+ * if the fix mode is 0, no location will be reported via callback
+ * otherwise, the location will be reported via callback
+ */
+ int fix_mode;
+ /*
+ * Indicate that the status of callback handling.
+ * The flag is used to report GPS_STATUS_SESSION_BEGIN or GPS_STATUS_SESSION_END:
+ * (0) The flag will be set as true when callback setting is changed via nmea_reader_set_callback
+ * (1) GPS_STATUS_SESSION_BEGIN: receive location fix + flag set + callback is set
+ * (2) GPS_STATUS_SESSION_END: receive location fix + flag set + callback is null
+ */
+ int cb_status_changed;
+ int sv_count; /*used to count the number of received SV information*/
+ gnss_sv_info sv_status;
+ // GpsCallbacks callbacks;
+ char in[ NMEA_MAX_SIZE+1 ];
+} NmeaReader;
+
+typedef struct {
+ const char* p;
+ const char* end;
+} Token;
+
+#define MAX_NMEA_TOKENS 64
+
+typedef struct {
+ int count;
+ Token tokens[ MAX_NMEA_TOKENS ];
+} NmeaTokenizer;
+
+void mtk_mnl_nmea_parser_process(const char * buffer, UINT32 length);
+int get_gps_nmea_parser_end_status();
+void mnld_get_mnl_version(char *mnl_ver);
+
+char *nmea_constellation_to_string(SV_TYPE constellation, float freq);
+SV_SYSTEM nmea_constellation_to_system_index(SV_TYPE constellation, float freq);
+char *nmea_sv_system_to_string(SV_SYSTEM sv_sys);
+bool nmea_freq_l1_signal(float freq);
+bool nmea_freq_l5_signal(float freq);
+
+#endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/op01_log.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/op01_log.h
new file mode 100644
index 0000000..1e6c984
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/op01_log.h
@@ -0,0 +1,24 @@
+#ifndef __OP01_LOG_H__
+#define __OP01_LOG_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#define MTK_GNSS_OP01_LOG_SUPPORT
+
+int op01_log_init();
+
+int op01_log_gps_start();
+int op01_log_gps_stop();
+int op01_log_gps_location(double lat, double lng, int ttff);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/qepo.h b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/qepo.h
new file mode 100644
index 0000000..4cf9263
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/inc/qepo.h
@@ -0,0 +1,67 @@
+#ifndef __QEPO_H__
+#define __QEPO_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define QEPO_FILE MTK_GPS_DATA_PATH"QEPO.DAT"
+#define QEPO_UPDATE_FILE MTK_GPS_DATA_PATH"QEPOTMP.DAT"
+#define QEPO_BD_FILE MTK_GPS_DATA_PATH"QEPO_BD.DAT"
+#define QEPO_BD_UPDATE_FILE MTK_GPS_DATA_PATH"QEPOTMP_BD.DAT"
+#define QEPO_GA_FILE MTK_GPS_DATA_PATH"QEPO_GA.DAT"
+#define QEPO_GA_UPDATE_FILE MTK_GPS_DATA_PATH"QEPOTMP_GA.DAT"
+#define QEPO_UPDATE_HAL MTK_GPS_DATA_PATH"QEPOHAL.DAT"
+#define QEPO_BD_UPDATE_HAL MTK_GPS_DATA_PATH"QEPO_BD_HAL.DAT"
+#define QEPO_BD_HAS_EPO_BIT_MASK (0x00000001)
+#define MTK_QEPO_BD_HEADER_SIZE 72
+#define QEPO_BD_DL_RETRY_TIME 3
+#define QEPO_GA_UPDATE_HAL MTK_GPS_DATA_PATH"QEPO_GA_HAL.DAT"
+#define QEPO_GA_HAS_EPO_BIT_MASK (0x00000001)
+#define MTK_QEPO_GA_HEADER_SIZE 72
+#define QEPO_GA_DL_RETRY_TIME 3
+#define QEPO_GR_DL_RETRY_TIME 3
+#define QEPO_HEADER_HAS_EPO_FLAG_INDX 0
+#define QEPO_HEADER_SV_CNT_INDX 1
+#define QEPO_HEADER_SV_CNT_EXT_INDX 4
+
+extern bool qepo_update_flag;
+extern int qepo_dl_res;
+extern bool qepo_BD_update_flag;
+extern int qepo_bd_dl_res;
+extern bool qepo_GA_update_flag;
+extern int qepo_ga_dl_res;
+
+int qepo_downloader_init();
+
+int qepo_downloader_start();
+
+int qepo_bd_downloader_start();
+
+int qepo_ga_downloader_start();
+
+int is_qepo_download_finished();
+
+int is_qepo_bd_download_finished();
+
+int is_qepo_ga_download_finished();
+
+void qepo_update_quarter_epo_file(int qepo_valid);
+
+void qepo_update_quarter_epo_bd_file(int qepo_bd_valid);
+
+void qepo_update_quarter_epo_ga_file(int qepo_ga_valid);
+
+void gps_mnl_set_gps_time(int wn, int tow, int sys_time);
+
+void qepo_invalid_dl_cnt_clear(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/adc_capture.c b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/adc_capture.c
new file mode 100644
index 0000000..c4509e6
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/adc_capture.c
@@ -0,0 +1,61 @@
+#include <errno.h>
+#include <unistd.h> // for close
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <pthread.h>
+
+#include "adc_capture.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_gps_type.h"
+#include "mtk_mnld_log.h"
+
+extern UINT32 adc_emi_address;
+extern int gps_emi_fd;
+
+void *thread_adc_capture_init(void* arg) {
+ int count;
+ UNUSED(arg);
+ LOGD("EMI ADC thread start\n");
+ for (count = 1; count <= 10; count++) {
+ gps_emi_fd = open("/dev/gps_emi", O_RDWR);
+ if (gps_emi_fd == -1) {
+ LOGW("open_port: Unable to open /dev/gps_emi, retry:%d\n", count);
+ usleep(500*1000);
+ continue;
+ } else {
+ LOGD("open gps_emi successfully\n");
+ break;
+ }
+ }
+ if (count >= 10) {
+ LOGE("open gps_emi failed\n");
+ return 0;
+ }
+
+ errno = 0;
+ if (ioctl(gps_emi_fd, IOCTL_EMI_MEMORY_INIT, NULL) <= 0) {
+ LOGE("set IOCTL_EMI_MEMORY_INIT failed,(%s)\n", strerror(errno));
+ }
+ errno = 0;
+ if (ioctl(gps_emi_fd, IOCTL_ADC_CAPTURE_ADDR_GET, &adc_emi_address) < 0) {
+ LOGE("set IOCTL_ADC_CAPTURE_ADDR_GET failed,(%s)\n", strerror(errno));
+ }
+
+ LOGD("ADC init successful and thread exit done, ADC emi address:(0x%08x)\n", adc_emi_address);
+ pthread_exit(NULL);
+ return 0;
+}
+
+void mnld_gps_emi_init(int type) {
+ int ret = -1;
+ pthread_t emi_download_thread;
+
+ if (type == 1) {
+ ret = pthread_create(&emi_download_thread, NULL, thread_adc_capture_init, NULL);
+ }
+ if (0 != ret) {
+ LOGE("emi download thread create fail: %s\n", strerror(errno));
+ exit(1);
+ }
+}
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/epo.c b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/epo.c
new file mode 100644
index 0000000..1516179
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/epo.c
@@ -0,0 +1,1775 @@
+#include <errno.h> /* Error number definitions */
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include <openssl/md5.h>
+
+#include "agps_agent.h"
+#include "data_coder.h"
+#include "mnl_common.h"
+#include "mnld.h"
+#include "mtk_lbs_utility.h"
+#include "epo.h"
+#include "qepo.h"
+#include "curl.h"
+#include "easy.h"
+#include "gps_controller.h"
+
+#include "mtk_mnld_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "epo"
+
+#define MTK_EPO_MAX_DAY 30
+#define MTK_EPO_DEFAULT_DL_DAY 3
+//#define MTK_EPO_ONE_SV_SIZE 72 //Move to epo.h
+#define GPS_CONF_FILE_SIZE 100
+#define EPO_CONTROL_FILE_PATH MTK_GPS_DATA_PATH"gps.conf"
+#define IS_SPACE(ch) ((ch == ' ') || (ch == '\t') || (ch == '\n'))
+#define MTK_EPO_SET_GPS_SVNum 32
+#define MTK_EPO_SET_GLO_SVNum 24
+#define MTK_EPO_SET_GPS_MAX_SIZE (72*MTK_EPO_SET_GPS_SVNum) //72*32, One SET
+#define MTK_EPO_SET_GLO_MAX_SIZE (72*MTK_EPO_SET_GLO_SVNum) //72*24, One SET
+#define MTK_EPO_SET_GPS_GLO_MAX_SIZE (MTK_EPO_SET_GPS_MAX_SIZE + MTK_EPO_SET_GLO_MAX_SIZE) //72*(32+24), One SET for GPS+GLO
+#define MTK_EPO_MD5_STR_LEN (MD5_DIGEST_LENGTH*2+1)
+#define MTK_EPO_READ_BUFSIZE (72*56)
+
+static int gps_epo_period = 3;
+static int wifi_epo_period = 3;
+static int gps_epo_download_days = MTK_EPO_DEFAULT_DL_DAY;
+static int gps_epo_download_piece = 1;
+static int gps_epo_enable = 0;
+static int gps_epo_wifi_trigger = 0;
+static int gps_epo_file_count = 0;
+static char gps_epo_file_name[GPS_EPO_FILE_LEN] = {0};
+static char gps_epo_MD5_file_name[GPS_EPO_FILE_LEN] = {0};
+int gps_epo_type = 0; // 0 for G+G;1 for GPS only, default is G+G
+//static int epo_download_failed = 0;
+static int epo_download_retry = 1;
+static timer_t retry_download_timer;
+//static timer_t hdlr_timer;
+static EPO_Status_T epo_status = {
+ .last_DL_Date = -1,
+ .today_retry_time = 0,
+};
+
+static int mtk_epo_is_expired(int wifi_tragger);
+static void gps_download_epo_file_name(int count);
+static int mtk_gps_epo_file_time_hal(time_t uTime[]);
+int mtk_gps_epo_gen_md5_str(FILE *f, char *md_str, unsigned int str_len);
+int mtk_gps_epo_md5_match_check(char *file_epo, char *file_md5);
+int mtk_gps_md5_hex2str(unsigned char *md, char *md_str, unsigned int str_len);
+CURLcode curl_easy_download_epo_DAT(void);
+
+CURLcode curl_easy_download_epo_MD5(void);
+
+typedef enum {
+ MAIN2EPO_EVENT_START = 0,
+} main2epo_event;
+
+typedef enum
+{
+ MTK_EPO_GPS_GLO = 0,
+ MTK_EPO_GPS,
+ MTK_EPO_END
+} MTK_EPO_TYPE;
+
+static int g_fd_epo;
+
+/////////////////////////////////////////////////////////////////////////////////
+// static functions
+static MTK_FILE EPO_File_Open (const char *szFileName, MTK_INT32 i4Mode)
+{
+ FILE *fp = NULL;
+ char szMode[4];
+
+ // For system which treats binary mode and text mode differently,
+ // such as Windows / DOS, please make sure to open file in BINARY mode
+
+ switch (i4Mode)
+ {
+ case MTK_FS_READ: // 0
+ MNLD_SPRINTF(szMode, "rb");
+ break;
+ case MTK_FS_WRITE: // 1
+ MNLD_SPRINTF(szMode, "wb");
+ break;
+ case MTK_FS_APPEND: // 2
+ MNLD_SPRINTF(szMode, "ab");
+ break;
+ case MTK_FS_RW: // 3
+ MNLD_SPRINTF(szMode, "r+b");
+ break;
+ case MTK_FS_RW_DISCARD: // 4
+ MNLD_SPRINTF(szMode, "w+b");
+ break;
+ case MTK_FS_RW_APPEND: // 5
+ MNLD_SPRINTF(szMode, "a+b");
+ break;
+ default:
+ return 0;
+ }
+
+ fp = fopen(szFileName, szMode);
+
+ if (fp != NULL)
+ {
+ return (MTK_FILE)fp;
+ }
+
+ return 0;
+}
+
+static void EPO_File_Close (MTK_FILE hFile)
+{
+ MNLD_FCLOSE((FILE *)hFile);
+}
+
+static MTK_UINT32 EPO_File_Read (MTK_FILE hFile, void *DstBuf, MTK_UINT32 u4Length)
+{
+ if (hFile != 0)
+ {
+ return (MTK_UINT32)fread(DstBuf, 1, u4Length, (FILE *)hFile);
+ }
+
+ return 0;
+}
+
+void epo_update_epo_file() {
+ unlink(EPO_FILE);
+ if (mtk_agps_agent_epo_file_update() == MTK_GPS_ERROR) {
+ LOGE("EPO file updates fail\n");
+ } else {
+ unlink(EPO_UPDATE_HAL);
+ }
+}
+
+int mtk_gps_epo_md5_match_check(char *file_epo, char *file_md5)
+{
+ FILE *fp_epo = NULL, *fp_md5 = NULL;
+ char md5_data[MTK_EPO_MD5_STR_LEN] = {0};
+ char gen_md5_str[MTK_EPO_MD5_STR_LEN] = {0};
+ int read_len = 0;
+
+ if(file_epo == NULL || file_md5 == NULL)
+ {
+ return MTK_GPS_ERROR;
+ }
+
+ fp_epo = fopen(file_epo, "r");
+ if (fp_epo == NULL)
+ {
+ LOGE("epo file(%s) open fail(%s).", file_epo, strerror(errno));
+ return MTK_GPS_ERROR;
+ }
+ if (mtk_gps_epo_gen_md5_str(fp_epo, gen_md5_str, MTK_EPO_MD5_STR_LEN) == MTK_GPS_ERROR) {
+ LOGE("Gen md5 str failed");
+ MNLD_FCLOSE(fp_epo);
+ return MTK_GPS_ERROR;
+ }
+ MNLD_FCLOSE(fp_epo);
+
+ fp_md5 = fopen(file_md5, "r");
+ if(fp_md5 == NULL)
+ {
+ LOGE("md5 file(%s) open fail(%s).", file_md5, strerror(errno));
+ return MTK_GPS_ERROR;
+ }
+ read_len = fread(md5_data, 1, sizeof(md5_data), fp_md5);
+ md5_data[MTK_EPO_MD5_STR_LEN - 1] = '\0';
+ MNLD_FCLOSE(fp_md5);
+ if (read_len <= 0) {
+ return MTK_GPS_ERROR;
+ }
+
+ if(strncmp(gen_md5_str, md5_data, MTK_EPO_MD5_STR_LEN-1) == 0)
+ {
+ return MTK_GPS_SUCCESS;
+ }else{
+ LOGW("Gen:%s, MD5File:%s", gen_md5_str, md5_data);
+ return MTK_GPS_ERROR;
+ }
+}
+
+int mtk_gps_epo_gen_md5_str(FILE *f, char *md_str, unsigned int str_len)
+{
+ MD5_CTX c;
+ int read_len;
+ unsigned char buf[MTK_EPO_READ_BUFSIZE] = {0};
+ unsigned char md5[MD5_DIGEST_LENGTH] = {0};
+ int i;
+
+ if (f == NULL || md_str == NULL) {
+ LOGE("NULL pointer: f=0x%p, md_str=0x%p", f, md_str);
+ return MTK_GPS_ERROR;
+ }
+
+ if(str_len < MTK_EPO_MD5_STR_LEN)
+ {
+ LOGE("str_len: %d", str_len);
+ return MTK_GPS_ERROR;
+ }
+
+ MD5_Init(&c);
+ do
+ {
+ read_len = fread(buf, 1, MTK_EPO_READ_BUFSIZE, f);
+ if (read_len <= 0) break;
+ MD5_Update(&c,buf,(unsigned long)read_len);
+ }while(read_len > 0);
+ MD5_Final(&(md5[0]),&c);
+
+ for (i=0; i<MD5_DIGEST_LENGTH; i++)
+ {
+ MNLD_SNPRINTF(&(md_str[i*2]), 3, "%02x", md5[i]);
+ }
+ md_str[i*2] = '\0';
+
+ return MTK_GPS_SUCCESS;
+}
+
+int mtk_gps_md5_hex2str(unsigned char *md, char *md_str, unsigned int str_len)
+{
+ int i;
+
+ if(str_len < MTK_EPO_MD5_STR_LEN)
+ {
+ LOGE("str_len: %d", str_len);
+ return MTK_GPS_ERROR;
+ }
+
+ for (i=0; i<MD5_DIGEST_LENGTH; i++)
+ {
+ MNLD_SNPRINTF(&(md_str[i*2]), 3, "%02x", md[i]);
+ }
+ md_str[i*2] = '\0';
+
+ return MTK_GPS_SUCCESS;
+}
+
+static int epo_md5_update_retry(int retry_time) {
+ int ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+ UNUSED(retry_time);
+ if (mnld_is_gps_started() || (is_wifi_network_connected())) {
+ if (is_network_connected()) {
+ //LOGW("download epo MD5 file failed, retry resume after 10s.(times:%d)", retry_time);
+ usleep(10*1000*1000);
+ if (curl_easy_download_epo_MD5() == CURLE_OK) {
+ ret = EPO_MD5_FILE_UPDATED;
+ } else {
+ ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+ }
+ } else {
+ //LOGW("download epo MD5 file failed, no network connected, retry times:%d", retry_time);
+ }
+
+ } else {
+ //LOGW("download epo MD5 file failed, not meet retry condition, retry times:%d", retry_time);
+ }
+ return ret;
+}
+
+static int epo_MD5_download_process(void) {
+ int ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+ int md5_retry_cnt = 0;
+ int loop_cnt = 0;
+ int md5_DL_flag = 1;
+
+ while(1) {
+ if (is_qepo_download_finished()&&is_qepo_bd_download_finished()&&is_qepo_ga_download_finished()) {
+ if (md5_DL_flag == 1) {
+ if (curl_easy_download_epo_MD5() == CURLE_OK) {
+ LOGD("%s download success", gps_epo_MD5_file_name);
+ ret = EPO_MD5_FILE_UPDATED;
+ break;
+ } else {
+ //LOGD("download MD5 first time failed");
+ md5_DL_flag = 0;
+ }
+ } else if (md5_retry_cnt < EPO_DL_MAX_RETRY_TIME) {
+ md5_retry_cnt++;
+ if (epo_md5_update_retry(md5_retry_cnt) == EPO_MD5_FILE_UPDATED) {
+ LOGD("%s download success", gps_epo_MD5_file_name);
+ ret = EPO_MD5_FILE_UPDATED;
+ break;
+ }
+ } else {
+ LOGD_ENG("Meet max retry time(%d), give up download epo MD5", md5_retry_cnt);
+ ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+ break;
+ }
+ } else {
+ // Wait qepo download finish, Maximum wait 30s
+ if (loop_cnt < 300) {
+ loop_cnt++;
+ usleep(100*1000);
+ } else {
+ LOGW("qepo download hung!!! EPO download exit");
+ ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+static int epo_dat_update_retry(int retry_time) {
+ int ret = EPO_DOWNLOAD_RESULT_FAIL;
+ if (mnld_is_gps_started() || (is_wifi_network_connected())) {
+ if (is_network_connected()) {
+ LOGW("download epo DAT file failed, retry resume after 10s.(times:%d)", retry_time);
+ usleep(10*1000*1000);
+ if (curl_easy_download_epo_DAT() == CURLE_OK) {
+ ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+ } else {
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ }
+ } else {
+ usleep(10*1000*1000);
+ LOGW("download epo DAT file failed, no network connected, retry times:%d", retry_time);
+ }
+ } else {
+ LOGW("download epo DAT file failed, not meet retry condition, retry times:%d", retry_time);
+ }
+ return ret;
+}
+
+static int epo_DAT_download_process(void) {
+ int ret = EPO_DOWNLOAD_RESULT_FAIL;
+ int loop_cnt = 0;
+ int dat_retry_cnt = 0;
+ int dat_DL_flag = 1;
+
+ while(1) {
+ if (is_qepo_download_finished()&&is_qepo_bd_download_finished()) {
+ if (dat_DL_flag == 1) {
+ if (curl_easy_download_epo_DAT() == CURLE_OK) {
+ LOGD("%s download success", gps_epo_file_name);
+ ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+ break;
+ } else {
+ dat_DL_flag = 0;
+ }
+ } else if (dat_retry_cnt < EPO_DL_MAX_RETRY_TIME) {
+ dat_retry_cnt++;
+ if (epo_dat_update_retry(dat_retry_cnt) == EPO_DOWNLOAD_RESULT_SUCCESS) {
+ LOGD("%s download success", gps_epo_file_name);
+ ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+ break;
+ }
+ } else {
+ LOGE("Meet max retry time(%d), give up download epo DAT", dat_retry_cnt);
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ break;
+ }
+ } else {
+ // Wait qepo download finish, Maximum wait 60s
+ if (loop_cnt < 600) {
+ loop_cnt++;
+ usleep(100*1000);
+ } else {
+ LOGW("qepo download hung!!! EPO download exit");
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int epo_DAT_file_merge(int file_length) {
+ FILE *fp_temp = NULL;
+ FILE *fp = NULL;
+ int res_val;
+ char gps_epo_data_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+
+ memset(gps_epo_data_file_name, 0x00, sizeof(gps_epo_data_file_name));
+
+ strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ if (gps_epo_file_count == 0) {
+ LOGD("first piece to merge, delete old EPOHAL.DAT");
+ unlink(EPO_UPDATE_HAL);
+ }
+ LOGD("merge %s file to EPOHAL.DAT", gps_epo_data_file_name);
+ res_val = chmod(gps_epo_data_file_name, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ if (res_val < 0) {
+ LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+ }
+
+ fp_temp = fopen(EPO_UPDATE_HAL, "at");
+ if (fp_temp != NULL) {
+ fp = fopen(gps_epo_data_file_name, "r");
+ if (fp != NULL) {
+ #define buf_size 256
+ char data[buf_size] = {0};
+ int bytes_in = 0, bytes_out = 0;
+ int len = 0;
+
+ while ((bytes_in = fread(data, 1, sizeof(data), fp)) > 0
+ && (bytes_in <= (int)(buf_size* sizeof(char)))) {
+ bytes_out = fwrite(data, 1, bytes_in, fp_temp);
+ if (bytes_in != bytes_out) {
+ LOGD("bytes_in = %d,bytes_out = %d\n", bytes_in, bytes_out);
+ }
+ len += bytes_out;
+ if (file_length != EPO_MERGE_FULL_FILE && len >= file_length) {
+ break;
+ }
+ }
+ MNLD_FCLOSE(fp);
+ } else {
+ LOGE("Open merged file fp=NULL\n");
+ }
+ MNLD_FCLOSE(fp_temp);
+ }
+ else {
+ LOGE("Open merged file failed\n");
+ return -1;
+ }
+ res_val = chmod(EPO_UPDATE_HAL, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ if (res_val < 0) {
+ LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+ }
+ return 0;
+}
+
+static int mtk_epo_1sv_checksum_check( const UINT32 u4SVData[18] )
+{
+ UINT32 checksum = 0;
+ int i=0;
+ int fgRet = MTK_GPS_FALSE;
+
+ for (i = 0; i < (18-1); i++)
+ {
+ checksum = checksum ^ u4SVData[i]; // exclusive OR
+ }
+
+ //check data checksum
+ if (checksum == u4SVData[17])
+ {
+ fgRet = MTK_GPS_TRUE;
+ }
+ return fgRet;
+}
+
+static int mtk_extract_epo_data_1SV(MTK_FILE hFile, UINT32 u4SvEpoData[MTK_EPO_ONE_SV_SIZE/4])
+{
+ memset(u4SvEpoData, 0, MTK_EPO_ONE_SV_SIZE);
+
+ if ( EPO_File_Read(hFile, u4SvEpoData, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE )
+ {
+ LOGE("read 1 sv data error");
+ return MTK_GPS_ERROR;
+ }
+
+ return MTK_GPS_SUCCESS;
+}
+
+static int epo_DAT_checksum_check(void) {
+ MTK_GPS_PARAM_EPO_DATA_CFG epo_data;
+ char gps_epo_data_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+ MTK_FILE hFile = 0;
+ int u4FileSize;
+ int sv_cnt = 0;
+ unsigned int max_sv_num;
+ unsigned int max_segment_size;
+ unsigned int valid_file_length;
+
+ memset(gps_epo_data_file_name, 0x00, sizeof(gps_epo_data_file_name));
+
+ strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+
+ if ( (hFile = EPO_File_Open(gps_epo_data_file_name, MTK_FS_READ)) == 0)
+ {
+ LOGE("Open epo DAT file error");
+ return MTK_GPS_ERROR;
+ }
+
+ if ( (u4FileSize = get_file_size(gps_epo_data_file_name)) == -1) {
+ LOGE("get file size error");
+ EPO_File_Close(hFile);
+ return MTK_GPS_ERROR;
+ }
+
+ while (sv_cnt*MTK_EPO_ONE_SV_SIZE < u4FileSize) {
+ if ( MTK_GPS_ERROR == mtk_extract_epo_data_1SV(hFile, epo_data.u4EPOWORD) )
+ {
+ LOGE("extract GPS EPO 1 SV data error");
+ break;
+ } else {
+ if (mtk_epo_1sv_checksum_check(epo_data.u4EPOWORD) == MTK_GPS_TRUE) {
+ sv_cnt++;
+ } else {
+ LOGE("find checksum error sv");
+ break;
+ }
+ }
+ }
+
+ EPO_File_Close(hFile);
+
+ if (gps_epo_type == MTK_EPO_GPS) {
+ max_sv_num = MTK_EPO_SET_GPS_SVNum;
+ max_segment_size = MTK_EPO_SET_GPS_MAX_SIZE;
+ } else if (gps_epo_type == MTK_EPO_GPS_GLO) {
+ max_sv_num = MTK_EPO_SET_GPS_SVNum + MTK_EPO_SET_GLO_SVNum;
+ max_segment_size = MTK_EPO_SET_GPS_GLO_MAX_SIZE;
+ } else {
+ LOGE("gps epo type is error");
+ return MTK_GPS_ERROR;
+ }
+
+ if ((sv_cnt / max_sv_num > 8) || gps_epo_file_count > 0) { // check if valid epo set more than 2 days. (1 epo set is 6hours, 8 means 2days)
+ valid_file_length = (unsigned int)(sv_cnt / max_sv_num) * max_segment_size;
+ return valid_file_length;
+ } else {
+ LOGW("no enough epo exist, ignore this piece. sv_cnt(%d)", sv_cnt);
+ return MTK_GPS_ERROR;
+ }
+}
+
+
+static void check_epo_file_exist(void) {
+ int i;
+ char gps_epo_data_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+ char gps_epo_md5_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+ for(i = 0; i< gps_epo_download_piece; ++i) {
+ gps_download_epo_file_name(i);
+ memset(gps_epo_md5_file_name, 0x00, sizeof(gps_epo_md5_file_name));
+ memset(gps_epo_data_file_name, 0x00, sizeof(gps_epo_data_file_name));
+ strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ strncat(gps_epo_md5_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+ strncat(gps_epo_md5_file_name, gps_epo_MD5_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+ if ((epo_status.EPO_piece_flag[i] & EPO_MD5_AVAILABLE_BIT) == EPO_MD5_AVAILABLE_BIT) {
+ if (access(gps_epo_md5_file_name, F_OK) == -1) {
+ epo_status.EPO_piece_flag[i] &= (~EPO_MD5_AVAILABLE_BIT);
+ }
+ }
+ if ((epo_status.EPO_piece_flag[i] & EPO_DAT_AVAILABLE_BIT) == EPO_DAT_AVAILABLE_BIT) {
+ if (access(gps_epo_data_file_name, F_OK) == -1) {
+ epo_status.EPO_piece_flag[i] &= (~EPO_DAT_AVAILABLE_BIT);
+ }
+ }
+ }
+}
+
+static int epo_file_download_impl() {
+ int ret = EPO_DOWNLOAD_RESULT_SUCCESS; //DAT file download result
+ int ret_MD5 = EPO_MD5_DOWNLOAD_RESULT_FAIL; //MD5 file download result
+ int valid_file_length;
+ int i;
+ int dl_retry_cnt = 0;
+ char gps_epo_data_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+ char gps_epo_md5_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+ struct tm tm;
+ time_t now = time(NULL);
+ gmtime_r(&now, &tm);
+ unlink(EPO_UPDATE_HAL);
+
+ // Check how many pieces should be DL, based on download days of user config
+ gps_epo_download_piece = gps_epo_download_days / 3;
+ if ((gps_epo_download_days % 3) > 0) {
+ gps_epo_download_piece++;
+ }
+
+ LOGD_ENG("download info: download piece = %d, today retry time =%d, last_date=%d", gps_epo_download_piece, epo_status.today_retry_time, epo_status.last_DL_Date);
+ dl_retry_cnt = 0;
+ do{
+ // Check if a new day comes, reset flag to re-dl (have checked EPO expire before trigger dl)
+ if (epo_status.last_DL_Date != tm.tm_mday) {
+ memset(epo_status.EPO_piece_flag, 0x00, sizeof(unsigned int)*MAX_EPO_PIECE);
+ epo_status.today_retry_time = 0;
+ epo_status.last_DL_Date = tm.tm_mday;
+ LOGD_ENG("First epo request today, day is %d", epo_status.last_DL_Date);
+ for (i = 0; i < gps_epo_download_piece; i++) {
+ memset(gps_epo_md5_file_name, 0x00, sizeof(gps_epo_md5_file_name));
+ memset(gps_epo_data_file_name, 0x00, sizeof(gps_epo_data_file_name));
+ gps_download_epo_file_name(i);
+ strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ strncat(gps_epo_md5_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+ strncat(gps_epo_md5_file_name, gps_epo_MD5_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+ unlink(gps_epo_md5_file_name);
+ unlink(gps_epo_data_file_name);
+ }
+ }
+
+ check_epo_file_exist();
+
+ for(gps_epo_file_count = 0; gps_epo_file_count < gps_epo_download_piece; ++gps_epo_file_count) {
+ //LOGD("EPO begin download %d piece...", gps_epo_file_count);
+ gps_download_epo_file_name(gps_epo_file_count);
+ if (((epo_status.EPO_piece_flag[gps_epo_file_count] & EPO_MD5_AVAILABLE_BIT) == EPO_MD5_AVAILABLE_BIT) &&
+ ((epo_status.EPO_piece_flag[gps_epo_file_count] & EPO_DAT_AVAILABLE_BIT) == EPO_DAT_AVAILABLE_BIT)) {
+ LOGD_ENG("EPO MD5 DAT both valid, no need download %s", gps_epo_file_name);
+ if (epo_DAT_file_merge(EPO_MERGE_FULL_FILE) == -1) {
+ LOGE("Merge piece EPO to DAT file error");
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ break;
+ }
+ continue;
+ } else if ((epo_status.EPO_piece_flag[gps_epo_file_count] & EPO_MD5_AVAILABLE_BIT) != EPO_MD5_AVAILABLE_BIT) {
+ LOGD("EPO MD5 not valid, download %s ", gps_epo_MD5_file_name);
+ ret_MD5 = epo_MD5_download_process();
+ if (ret_MD5 == EPO_MD5_FILE_UPDATED) {
+ epo_status.EPO_piece_flag[gps_epo_file_count] |= EPO_MD5_AVAILABLE_BIT;
+ //LOGD("%s download success", gps_epo_file_name);
+ }else {
+ LOGD_ENG("%s download failed", gps_epo_MD5_file_name);
+ if (gps_epo_file_count == 0) {
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ }
+ break;
+ }
+ }
+
+ ret = epo_DAT_download_process();
+ if (ret == EPO_DOWNLOAD_RESULT_SUCCESS) {
+ memset(gps_epo_md5_file_name, 0x00, sizeof(gps_epo_md5_file_name));
+ memset(gps_epo_data_file_name, 0x00, sizeof(gps_epo_data_file_name));
+ strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ strncat(gps_epo_md5_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+ strncat(gps_epo_md5_file_name, gps_epo_MD5_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+ if (mtk_gps_epo_md5_match_check(gps_epo_data_file_name, gps_epo_md5_file_name) == MTK_GPS_ERROR) {
+ LOGE("EPO DAT MD5 match check failed, confirm checksum");
+ if ((valid_file_length = epo_DAT_checksum_check()) > 0) {
+ if (epo_DAT_file_merge(valid_file_length) == -1) {
+ LOGE("Merge piece EPO to DAT file error");
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ break;
+ } else {
+ ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+ LOGD("have more than 2days EPO(%d piece + valid file size:%d bytes), do inject", gps_epo_file_count, valid_file_length);
+ break;
+ }
+ } else {
+ epo_status.EPO_piece_flag[gps_epo_file_count] &= (~EPO_DAT_AVAILABLE_BIT);
+ epo_status.EPO_piece_flag[gps_epo_file_count] &= (~EPO_MD5_AVAILABLE_BIT);
+ epo_status.today_retry_time++;
+ unlink(gps_epo_md5_file_name);
+ unlink(gps_epo_data_file_name);
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ break;
+ }
+ } else {
+ LOGD("EPO MD5 check success: %d", gps_epo_file_count);
+ epo_status.EPO_piece_flag[gps_epo_file_count] |= EPO_DAT_AVAILABLE_BIT;
+ if (epo_DAT_file_merge(EPO_MERGE_FULL_FILE) == -1) { // 0 means merge all
+ LOGE("Merge piece EPO to DAT file error");
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ break;
+ }
+ }
+ }else {
+ LOGE("DAT file download failed");
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ break;
+ }
+ }
+
+ if (ret == EPO_DOWNLOAD_RESULT_SUCCESS) {
+ //LOGD("Merge EPOHAL.DAT success, delete piece files");
+ for (i = 0; i < gps_epo_download_piece; i++) {
+ memset(gps_epo_md5_file_name, 0x00, sizeof(gps_epo_md5_file_name));
+ memset(gps_epo_data_file_name, 0x00, sizeof(gps_epo_data_file_name));
+ gps_download_epo_file_name(i);
+ strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ strncat(gps_epo_md5_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+ strncat(gps_epo_md5_file_name, gps_epo_MD5_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+ unlink(gps_epo_md5_file_name);
+ unlink(gps_epo_data_file_name);
+ }
+ break;
+ } else { //Download fail
+ if (gps_epo_file_count == 0) //Only pice 1 need to retry
+ {
+ dl_retry_cnt ++;
+ if (dl_retry_cnt <= EPO_INVALIDE_DL_MAX_RETRY_TIME)
+ {
+ usleep(EPO_INVALIDE_DL_RETRY_SLEEP);
+ }
+ } else {
+ dl_retry_cnt = EPO_INVALIDE_DL_MAX_RETRY_TIME+1; //No need retry
+ }
+ LOGD_ENG("retry cnt:%d", dl_retry_cnt);
+ }
+ }while (dl_retry_cnt <= EPO_INVALIDE_DL_MAX_RETRY_TIME);
+
+ return ret;
+}
+
+/*****************************************************************************/
+static int get_val(char *pStr, char** ppKey, char** ppVal) {
+ int len = (int)strlen(pStr);
+ char *end = pStr + len;
+ char *key = NULL, *val = NULL;
+
+ LOGD("pStr = %s, len=%d!!\n", pStr, len);
+
+ if (!len) {
+ return -1; // no data
+ } else if (pStr[0] == '#') { /*ignore comment*/
+ *ppKey = *ppVal = NULL;
+ return 0;
+ } else if (pStr[len-1] != '\n') {
+ if (len >= GPS_CONF_FILE_SIZE-1) {
+ LOGD("buffer is not enough!!\n");
+ return -1;
+ } else {
+ pStr[len] = '\n';
+ }
+ }
+ key = pStr;
+
+ LOGD("key = %s!!\n", key);
+ while ((*pStr != '=') && (pStr < end)) pStr++;
+ if (pStr >= end) {
+ LOGW("'=' is not found!!\n");
+ *ppKey = *ppVal = NULL;
+ return 0; // format error
+ }
+
+ *pStr++ = '\0';
+ while (IS_SPACE(*pStr) && (pStr < end)) pStr++; // skip space chars
+ val = pStr;
+ while (!IS_SPACE(*pStr) && (pStr < end)) pStr++;
+ *pStr = '\0';
+ *ppKey = key;
+ *ppVal = val;
+
+ LOGD("val = %s!!\n", val);
+ return 0;
+}
+
+/*****************************************************************************/
+int epo_read_cust_config(void) {
+ char result[GPS_CONF_FILE_SIZE] = {0};
+
+ FILE *fp = fopen(EPO_CONTROL_FILE_PATH, "r");
+ char *key = NULL, *val = NULL;
+ if (!fp) {
+ // LOGD("%s: open %s fail!\n", __FUNCTION__, EPO_CONTROL_FILE_PATH);
+ return 1;
+ }
+
+ while (fgets(result, sizeof(result), fp)) {
+ if (get_val(result, &key, &val)) {
+ LOGD("%s: Get data fails!!\n", __FUNCTION__);
+ MNLD_FCLOSE(fp);
+ return 1;
+ }
+ if (!key || !val)
+ continue;
+ if (!strcmp(key, "EPO_ENABLE")) {
+ int len = strlen(val);
+
+ LOGD("gps_epo_enablebg = %d, len =%d\n", gps_epo_enable, len);
+ gps_epo_enable = str2int(val, val+len); // *val-'0';
+ if ((gps_epo_enable != 1) && (gps_epo_enable != 0)) {
+ gps_epo_enable = 1;
+ }
+ LOGD("gps_epo_enableend = %d\n", gps_epo_enable);
+ }
+ if (!strcmp(key, "DW_DAYS")) {
+ int len = strlen(val);
+ gps_epo_download_days = str2int(val, val+len); // *val-'0';
+ if (gps_epo_download_days > MTK_EPO_MAX_DAY || gps_epo_download_days < 0) {
+ gps_epo_download_days = MTK_EPO_DEFAULT_DL_DAY;
+ }
+ }
+ if (!strcmp(key, "EPO_WIFI_TRIGGER")) {
+ int len = strlen(val);
+ LOGD("gps_epo_wifi_triggerbg = %d, len =%d\n", gps_epo_wifi_trigger, len);
+ gps_epo_wifi_trigger = str2int(val, val+len); // *val-'0';
+ if ((gps_epo_wifi_trigger != 1) && (gps_epo_wifi_trigger != 0)) {
+ gps_epo_wifi_trigger = 0;
+ }
+ LOGD("gps_epo_wifi_triggerend = %d\n", gps_epo_wifi_trigger);
+ }
+ LOGD("gps_epo_enable = %d, gps_epo_period = %d, \
+ wifi_epo_period = %d, gps_epo_wifi_trigger = %d\n", gps_epo_enable, gps_epo_period,
+ wifi_epo_period, gps_epo_wifi_trigger);
+ }
+
+ MNLD_FCLOSE(fp);
+ return 1;
+}
+
+void epo_write_cfg(char* key, char* val) {
+ if (write_prop(EPO_CONTROL_FILE_PATH, key, val)) {
+ LOGE("Write EPO config fail, key:%s, val:%s", key, val);
+ }
+}
+
+/*****************************************************************************/
+static void gps_download_epo_file_name(int count) {
+ // LOGD("count is %d\n", count);
+ if (gps_epo_type == 1) {
+ if (count == 0) {
+ strncpy(gps_epo_file_name, "EPO_GPS_3_1.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_1.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 1) {
+ strncpy(gps_epo_file_name, "EPO_GPS_3_2.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_2.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 2) {
+ strncpy(gps_epo_file_name, "EPO_GPS_3_3.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_3.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 3) {
+ strncpy(gps_epo_file_name, "EPO_GPS_3_4.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_4.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 4) {
+ strncpy(gps_epo_file_name, "EPO_GPS_3_5.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_5.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 5) {
+ strncpy(gps_epo_file_name, "EPO_GPS_3_6.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_6.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 6) {
+ strncpy(gps_epo_file_name, "EPO_GPS_3_7.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_7.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 7) {
+ strncpy(gps_epo_file_name, "EPO_GPS_3_8.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_8.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 8) {
+ strncpy(gps_epo_file_name, "EPO_GPS_3_9.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_9.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 9) {
+ strncpy(gps_epo_file_name, "EPO_GPS_3_10.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_10.MD5", GPS_EPO_FILE_LEN);
+ }
+ }
+ else if (gps_epo_type == 0) {
+ if (count == 0) {
+ strncpy(gps_epo_file_name, "EPO_GR_3_1.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GR_3_1.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 1) {
+ strncpy(gps_epo_file_name, "EPO_GR_3_2.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GR_3_2.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 2) {
+ strncpy(gps_epo_file_name, "EPO_GR_3_3.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GR_3_3.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 3) {
+ strncpy(gps_epo_file_name, "EPO_GR_3_4.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GR_3_4.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 4) {
+ strncpy(gps_epo_file_name, "EPO_GR_3_5.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GR_3_5.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 5) {
+ strncpy(gps_epo_file_name, "EPO_GR_3_6.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GR_3_6.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 6) {
+ strncpy(gps_epo_file_name, "EPO_GR_3_7.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GR_3_7.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 7) {
+ strncpy(gps_epo_file_name, "EPO_GR_3_8.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GR_3_8.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 8) {
+ strncpy(gps_epo_file_name, "EPO_GR_3_9.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GR_3_9.MD5", GPS_EPO_FILE_LEN);
+ } else if (count == 9) {
+ strncpy(gps_epo_file_name, "EPO_GR_3_10.DAT", GPS_EPO_FILE_LEN);
+ strncpy(gps_epo_MD5_file_name, "EPO_GR_3_10.MD5", GPS_EPO_FILE_LEN);
+ }
+ }
+ //LOGD("download request for file %d, gps_epo_file_name=%s, gps_epo_MD5_file_name=%s\n",
+ // count, gps_epo_file_name, gps_epo_MD5_file_name);
+}
+
+/*****************************************************************************/
+int mtk_gps_sys_read_lock(int fd, off_t offset, int whence, off_t len) {
+ struct flock lock;
+
+ lock.l_type = F_RDLCK;
+ lock.l_start = offset;
+ lock.l_whence = whence;
+ lock.l_len = len;
+
+ if (fcntl(fd, F_SETLK, &lock) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+static unsigned int mtk_gps_sys_get_file_size() {
+ unsigned int fileSize;
+ int res_epo, res_epo_hal;
+ struct stat st;
+ char *epo_file = EPO_FILE;
+ char *epo_file_hal = EPO_UPDATE_HAL;
+ char epofile[GPS_EPO_FILE_LEN] = {0};
+ res_epo = access(EPO_FILE, F_OK);
+ res_epo_hal = access(EPO_UPDATE_HAL, F_OK);
+ if (res_epo < 0 && res_epo_hal < 0) {
+ LOGD("no EPO data yet\n");
+ return -1;
+ }
+ if (res_epo_hal == 0) { /*EPOHAL.DAT is here*/
+ // LOGD("find EPOHAL.DAT here\n");
+ MNLD_STRNCPY(epofile, epo_file_hal, GPS_EPO_FILE_LEN);
+ } else if (res_epo == 0) { /*EPO.DAT is here*/
+ // LOGD("find EPO.DAT here\n");
+ MNLD_STRNCPY(epofile, epo_file, GPS_EPO_FILE_LEN);
+ } else
+ LOGE("unknown error happened\n");
+
+ if (stat(epofile, &st) < 0) {
+ LOGE("Get file size error, return\n");
+ return 0;
+ }
+
+ fileSize = st.st_size;
+ // LOGD("EPO file size: %d\n", fileSize);
+ return fileSize;
+}
+
+/*****************************************************************************/
+void GpsToUtcTime(int i2Wn, double dfTow, time_t* uSecond) {
+ struct tm target_time;
+ int iYearsElapsed; // Years since 1980.
+ unsigned int iDaysElapsed; // Days elapsed since Jan 1, 1980.
+ double dfSecElapsed;
+ unsigned int fgLeapYear;
+ int pi2Yr = 0;
+ int pi2Mo = 0;
+ int pi2Day = 0;
+ int pi2Hr = 0;
+ int pi2Min = 0;
+ double pdfSec = 0;
+ int i = 0;
+
+
+ // Number of days into the year at the start of each month (ignoring leap
+ // years).
+ unsigned int doy[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+ // Convert time to GPS weeks and seconds
+ iDaysElapsed = i2Wn * 7 + ((int)dfTow / 86400) + 5;
+ dfSecElapsed = dfTow - ((int)dfTow / 86400) * 86400;
+
+
+ // decide year
+ iYearsElapsed = 0; // from 1980
+ while (iDaysElapsed >= 365) {
+ if ((iYearsElapsed % 100) == 20) { // if year % 100 == 0
+ if ((iYearsElapsed % 400) == 20) { // if year % 400 == 0
+ if (iDaysElapsed >= 366) {
+ iDaysElapsed -= 366;
+ } else {
+ break;
+ }
+ } else {
+ iDaysElapsed -= 365;
+ }
+ } else if ((iYearsElapsed % 4) == 0) { // if year % 4 == 0
+ if (iDaysElapsed >= 366) {
+ iDaysElapsed -= 366;
+ } else {
+ break;
+ }
+ } else {
+ iDaysElapsed -= 365;
+ }
+ iYearsElapsed++;
+ }
+ pi2Yr = 1980 + iYearsElapsed;
+
+
+ // decide month, day
+ fgLeapYear = 0;
+ if ((iYearsElapsed % 100) == 20) { // if year % 100 == 0
+ if ((iYearsElapsed % 400) == 20) { // if year % 400 == 0
+ fgLeapYear = 1;
+ }
+ }
+ else if ((iYearsElapsed % 4) == 0) { // if year % 4 == 0
+ fgLeapYear = 1;
+ }
+
+ if (fgLeapYear) {
+ for (i = 2; i < 12; i++) {
+ doy[i] += 1;
+ }
+ }
+ for (i = 0; i < 12; i++) {
+ if (iDaysElapsed < doy[i]) {
+ break;
+ }
+ }
+ pi2Mo = i;
+ if (i > 0) {
+ pi2Day = iDaysElapsed - doy[i-1] + 1;
+ }
+
+ // decide hour, min, sec
+ pi2Hr = dfSecElapsed / 3600;
+ pi2Min = ((int)dfSecElapsed % 3600) / 60;
+ pdfSec = dfSecElapsed - ((int)dfSecElapsed / 60) * 60;
+
+ // change the UTC time to seconds
+ memset(&target_time, 0, sizeof(target_time));
+ target_time.tm_year = pi2Yr - 1900;
+ target_time.tm_mon = pi2Mo - 1;
+ target_time.tm_mday = pi2Day;
+ target_time.tm_hour = pi2Hr;
+ target_time.tm_min = pi2Min;
+ target_time.tm_sec = pdfSec;
+ target_time.tm_isdst = -1;
+ *uSecond = mktime(&target_time);
+ if (*uSecond < 0) {
+ LOGE("Convert UTC time to seconds fail, return\n");
+ }
+}
+
+
+/*****************************************************************************/
+int mtk_gps_sys_epo_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond) { // no file lock
+ char szBuf[MTK_EPO_ONE_SV_SIZE];
+ int pi2WeekNo;
+ unsigned int pu4Tow;
+
+ // if (fread(szBuf, 1, MTK_EPO_ONE_SV_SIZE, pFile) != MTK_EPO_ONE_SV_SIZE) {
+ if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+ return -1;
+ }
+
+ *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+ pi2WeekNo = (*u4GpsSecs) / 604800;
+ pu4Tow = (*u4GpsSecs) % 604800;
+
+ // TRC();
+ // LOGD("pi2WeekNo = %d, pu4Tow = %d\n", pi2WeekNo, pu4Tow);
+ GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond); // to get UTC second
+ return 0;
+}
+
+/*****************************************************************************/
+int mtk_gps_sys_epo_bd_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond) { // no file lock
+ char szBuf[MTK_EPO_ONE_SV_SIZE];
+ int pi2WeekNo;
+ unsigned int pu4Tow;
+
+ if (-1 == lseek(fd, MTK_EPO_ONE_SV_SIZE, SEEK_SET)) { //Skip the header of BD QEPO file
+ LOGE("lseek error(%s)\n",strerror(errno));
+ return -1;
+ }
+
+ if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+ return -1;
+ }
+
+ *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+ pi2WeekNo = (*u4GpsSecs) / 604800;
+ pu4Tow = (*u4GpsSecs) % 604800;
+
+ GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond); // to get UTC second
+ return 0;
+}
+
+/*****************************************************************************/
+int mtk_gps_sys_epo_ga_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond) { // no file lock
+ char szBuf[MTK_EPO_ONE_SV_SIZE];
+ int pi2WeekNo;
+ unsigned int pu4Tow;
+
+ if (-1 == lseek(fd, MTK_EPO_ONE_SV_SIZE, SEEK_SET)) { //Skip the header of GA QEPO file
+ LOGE("lseek error(%s)\n",strerror(errno));
+ return -1;
+ }
+
+ if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+ return -1;
+ }
+
+ *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+ pi2WeekNo = (*u4GpsSecs) / 604800;
+ pu4Tow = (*u4GpsSecs) % 604800;
+
+ GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond); // to get UTC second
+ return 0;
+}
+
+/*****************************************************************************/
+static int mtk_gps_sys_epo_period_end(int fd, unsigned int *u4GpsSecs, time_t* uSecond) { // no file lock
+ int fileSize;
+ char szBuf[MTK_EPO_ONE_SV_SIZE];
+ int pi2WeekNo;
+ unsigned int pu4Tow;
+
+ fileSize = mtk_gps_sys_get_file_size();
+ if (fileSize < MTK_EPO_ONE_SV_SIZE) {
+ return -1;
+ }
+
+ if (-1 == lseek(fd, (fileSize - MTK_EPO_ONE_SV_SIZE), SEEK_SET)) {
+ LOGE("lseek error\n");
+ return -1;
+ }
+
+ if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+ return -1;
+ }
+
+ *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+ (*u4GpsSecs) += 21600;
+
+ pi2WeekNo = (*u4GpsSecs) / 604800;
+ pu4Tow = (*u4GpsSecs) % 604800;
+
+ // TRC();
+ // LOGD("pi2WeekNo = %d, pu4Tow = %d\n", pi2WeekNo, pu4Tow);
+ GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond);
+
+ return 0;
+}
+
+/*****************************************************************************/
+static int mtk_gps_epo_file_time_hal(time_t uTime[]) {
+ //LOGD("mtk_gps_epo_file_time_hal");
+ struct stat filestat;
+ int fd = 0;
+ int res_epo, res_epo_hal;
+ unsigned int u4GpsSecs_start; // GPS seconds
+ unsigned int u4GpsSecs_expire;
+ char *epo_file = EPO_FILE;
+ char *epo_file_hal = EPO_UPDATE_HAL;
+ char epofile[GPS_EPO_FILE_LEN] = {0};
+ time_t uSecond_start; // UTC seconds
+ time_t uSecond_expire;
+// int ret = 0;
+ // pthread_mutex_t mutx = PTHREAD_MUTEX_INITIALIZER;
+
+ res_epo = access(EPO_FILE, F_OK);
+ res_epo_hal = access(EPO_UPDATE_HAL, F_OK);
+ if (res_epo < 0 && res_epo_hal < 0) {
+ LOGD("no EPO data yet\n");
+// ret = pthread_mutex_unlock(&mutx);
+ return -1;
+ }
+ if (res_epo_hal== 0) { /*EPOHAL.DAT is here*/
+ // LOGD("find EPOHAL.DAT here\n");
+ MNLD_STRNCPY(epofile, epo_file_hal, GPS_EPO_FILE_LEN);
+ } else if (res_epo == 0) { /*EPO.DAT is here*/
+ // LOGD("find EPO.DAT here\n");
+ MNLD_STRNCPY(epofile, epo_file, GPS_EPO_FILE_LEN);
+ } else
+ LOGE("unknown error happened\n");
+
+ // open file
+ fd = open(epofile, O_RDONLY);
+ if (fd < 0) {
+ LOGE("Open EPO fail, return\n");
+// ret = pthread_mutex_unlock(&mutx);
+ return -1;
+ }
+
+ // Add file lock
+ if (mtk_gps_sys_read_lock(fd, 0, SEEK_SET, 0) < 0) {
+ LOGE("Add read lock failed, return\n");
+ close(fd);
+// ret = pthread_mutex_unlock(&mutx);
+ return -1;
+ }
+
+ // EPO start time
+ if (mtk_gps_sys_epo_period_start(fd, &u4GpsSecs_start, &uSecond_start)) {
+ LOGE("Get EPO file start time error, return\n");
+ close(fd);
+// ret = pthread_mutex_unlock(&mutx);
+ return -1;
+ } else {
+ uTime[0] = uSecond_start;
+ // LOGD("The Start time of EPO file is %lld", uTime[0]);
+ // LOGD("The start time of EPO file is %s", ctime(&uTime[0]));
+ }
+
+ // download time
+ if (stat(epofile, &filestat) == -1){
+ LOGE("stat get file information failed reason=[%s]\n", strerror(errno));
+ }
+
+ uTime[1] = filestat.st_mtime;
+ // uTime[1] = uTime[1] - 8 * 3600;
+ // LOGD("Download time of EPO file is %lld", uTime[1]);
+ // LOGD("Download time of EPO file is %s\n", ctime(&uTime[1]));
+
+ // EPO file expire time
+ if (mtk_gps_sys_epo_period_end(fd, &u4GpsSecs_expire, &uSecond_expire)) {
+ LOGE("Get EPO file expire time error, return\n");
+ close(fd);
+// ret = pthread_mutex_unlock(&mutx);
+ return -1;
+ } else {
+ uTime[2] = uSecond_expire;
+ // LOGD("The expire time of EPO file is %lld", uTime[2]);
+ // LOGD("The expire time of EPO file is %s", ctime(&uTime[2]));
+ }
+
+ close(fd);
+// ret = pthread_mutex_unlock(&mutx);
+ return 0;
+}
+
+size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
+ size_t written;
+ written = fwrite(ptr, size, nmemb, stream);
+ if(written != nmemb) {
+ LOGE("write fail, %s(%d)", strerror(errno), errno);
+ }
+ return written;
+}
+CURLcode curl_easy_download(char* url, char* filename) {
+ CURL *curl = NULL;
+ FILE *fp = NULL;
+ CURLcode res;
+
+ //LOGD("curl_easy_download url: %s to %s", url, filename);
+ if ((res = curl_global_init(CURL_GLOBAL_DEFAULT)) != 0) {
+ LOGE("curl_global_init fail, res = %d, curl_easy_download url: %s to %s", res, url, filename);
+ }
+ curl = curl_easy_init();
+ //LOGD("curl_easy_init done");
+ if (curl) {
+ fp = fopen(filename, "w+");
+ if (fp == NULL) {
+ curl_easy_cleanup(curl);
+ return CURLE_FAILED_INIT;
+ }
+
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
+ // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
+ curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ MNLD_FCLOSE(fp);
+ return res;
+ } else {
+ LOGE("curl_easy_init fail, curl_easy_download url: %s to %s", url, filename);
+ return CURLE_FAILED_INIT;
+ }
+}
+static int counter = 1;
+void getEpoUrl(const char* filename, char* url) {
+ char count_str[15] = {0};
+
+ if (counter <= 1) {
+ strncat(url, EPO_URL_HOME_G, GPS_EPO_URL_LEN - strlen(url));
+ } else {
+ strncat(url, EPO_URL_HOME_C, GPS_EPO_URL_LEN -strlen(url));
+ }
+
+ strncat(url, filename, GPS_EPO_URL_LEN - strlen(url));
+ strncat(url, "?retryCount=", GPS_EPO_URL_LEN - strlen(url));
+ MNLD_SPRINTF(count_str, "%d", counter-1);
+ strncat(url, count_str, GPS_EPO_URL_LEN - strlen(url));
+ //LOGD("url = %s\n", url);
+}
+
+CURLcode curl_easy_download_epo_MD5(void) {
+ int res_val;
+ CURLcode res;
+ char url[GPS_EPO_URL_LEN]={0};
+ char gps_epo_md5_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+ int filesize = 0;
+
+ //LOGD("curl_easy_download_epo_MD5:%s", gps_epo_MD5_file_name);
+ memset(gps_epo_md5_file_name, 0x00, sizeof(gps_epo_md5_file_name));
+ getEpoUrl(gps_epo_MD5_file_name, url);
+
+ strncat(gps_epo_md5_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+ strncat(gps_epo_md5_file_name, gps_epo_MD5_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+ res = curl_easy_download(url, gps_epo_md5_file_name);
+
+ filesize = get_file_size(gps_epo_md5_file_name);
+
+ if (filesize <= 0 || filesize > EPO_MD5_FILE_MAX_SIZE) {
+ res = CURLE_READ_ERROR;
+ LOGD_ENG("download file size error.");
+ }
+
+ //LOGD("epo MD5 file curl_easy_download res = %d\n", res);
+ if (res == CURLE_OK) {
+ counter = 1;
+ res_val = chmod(gps_epo_md5_file_name, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ if (res_val < 0) {
+ LOGD("chmod MD5 res_val = %d, %s\n", res_val, strerror(errno));
+ }
+ } else {
+ unlink(gps_epo_md5_file_name);
+ counter++;
+ LOGE("epo MD5 file download failed res:%d. curl_easy_download url: %s to %s", res, url, gps_epo_md5_file_name);
+ }
+ return res;
+}
+
+CURLcode curl_easy_download_epo_DAT(void) {
+ int res_val;
+ CURLcode res;
+ char gps_epo_data_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+ char url[GPS_EPO_URL_LEN]={0};
+ int filesize = 0;
+
+ //LOGD("curl_easy_download_epo_DAT:%s", gps_epo_file_name);
+ memset(gps_epo_data_file_name, 0x00, sizeof(gps_epo_data_file_name));
+ getEpoUrl(gps_epo_file_name, url);
+
+ strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ res = curl_easy_download(url, gps_epo_data_file_name);
+
+ filesize = get_file_size(gps_epo_data_file_name);
+
+ if (filesize <= 0) {
+ res = CURLE_PARTIAL_FILE;
+ LOGE("download file size error.");
+ }
+
+ if (res == CURLE_OK) {
+ counter = 1;
+ res_val = chmod(gps_epo_data_file_name, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ if (res_val < 0) {
+ LOGD("chmod DAT res_val = %d, %s\n", res_val, strerror(errno));
+ }
+ } else {
+ unlink(gps_epo_data_file_name);
+ counter++;
+ LOGD("epo DAT file curl_easy_download res = %d\n", res);
+ }
+ return res;
+}
+
+CURLcode curl_easy_download_epo(void) {
+ int res_val;
+ CURLcode res;
+ char gps_epo_data_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+ char url[GPS_EPO_URL_LEN]={0};
+
+ LOGD("curl_easy_download_epo");
+ getEpoUrl(gps_epo_file_name, url);
+
+ strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+
+ res = curl_easy_download(url, gps_epo_data_file_name);
+ LOGD("epo file curl_easy_download res = %d\n", res);
+ if (res == CURLE_OK) {
+ FILE *fp_temp = NULL;
+ FILE *fp = NULL;
+
+ counter = 1;
+ if (gps_epo_file_count == 0) {
+ unlink(EPO_UPDATE_HAL);
+ }
+ res_val = chmod(gps_epo_data_file_name, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+ fp_temp = fopen(EPO_UPDATE_HAL, "at");
+ if (fp_temp != NULL) {
+ fp = fopen(gps_epo_data_file_name, "r");
+ if (fp != NULL) {
+ #define buf_size 256
+ char data[buf_size] = {0};
+ int bytes_in = 0, bytes_out = 0;
+ int len = 0;
+
+ while ((bytes_in = fread(data, 1, sizeof(data), fp)) > 0
+ && (bytes_in <= (int)(buf_size* sizeof(char)))) {
+ bytes_out = fwrite(data, 1, bytes_in, fp_temp);
+ if (bytes_in != bytes_out) {
+ LOGD("bytes_in = %d,bytes_out = %d\n", bytes_in, bytes_out);
+ }
+ len += bytes_out;
+ // LOGD("copying file...%d bytes copied\n",len);
+ }
+ MNLD_FCLOSE(fp);
+ } else {
+ LOGE("Open merged file fp=NULL\n");
+ }
+ MNLD_FCLOSE(fp_temp);
+ }
+ else {
+ LOGE("Open merged file failed\n");
+ }
+ res_val = chmod(EPO_UPDATE_HAL, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+ } else {
+ unlink(gps_epo_data_file_name);
+ counter++;
+ }
+ return res;
+}
+
+#if 0
+static unsigned int mtk_gps_epo_get_piece_file_size() {
+ struct stat st;
+ unsigned int fileSize;
+ char gps_epo_data_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+
+ strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+ strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+
+ if (stat(gps_epo_data_file_name, &st) < 0) {
+ LOGE("Get file size error, return\n");
+ return 0;
+ }
+ fileSize = st.st_size;
+ LOGD("EPO piece file size: %d\n", fileSize);
+ return fileSize;
+}
+/*****************************************************************************/
+static int mtk_gps_epo_piece_data_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond) {
+ char szBuf[MTK_EPO_ONE_SV_SIZE];
+ int pi2WeekNo;
+ unsigned int pu4Tow;
+
+
+ // if (fread(szBuf, 1, MTK_EPO_ONE_SV_SIZE, pFile) != MTK_EPO_ONE_SV_SIZE) {
+ if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+ return -1;
+ }
+
+ *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+ pi2WeekNo = (*u4GpsSecs) / 604800;
+ pu4Tow = (*u4GpsSecs) % 604800;
+
+ LOGD("mtk_gps_epo_piece_data_start");
+ LOGD("pi2WeekNo = %d, pu4Tow = %d\n", pi2WeekNo, pu4Tow);
+ GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond); // to get UTC second
+ return 0;
+}
+/*****************************************************************************/
+static int mtk_gps_epo_piece_data_end(int fd, unsigned int *u4GpsSecs, time_t* uSecond) {
+ int fileSize = 0;
+ char szBuf[MTK_EPO_ONE_SV_SIZE] = {0};
+ int pi2WeekNo;
+ unsigned int pu4Tow;
+
+ if (-1 != fd) {
+ fileSize = mtk_gps_epo_get_piece_file_size();
+ if (fileSize < MTK_EPO_ONE_SV_SIZE) {
+ LOGE("Get file size is error\n");
+ return -1;
+ }
+ if (-1 == lseek(fd, (fileSize - MTK_EPO_ONE_SV_SIZE), SEEK_SET)) {
+ LOGE("lseek error\n");
+ return -1;
+ }
+
+ if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+ LOGE("read epo file end data faied\n");
+ return -1;
+ }
+
+ *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+ (*u4GpsSecs) += 21600;
+
+ pi2WeekNo = (*u4GpsSecs) / 604800;
+ pu4Tow = (*u4GpsSecs) % 604800;
+
+ LOGD("mtk_gps_epo_piece_data_end");
+ LOGD("pi2WeekNo = %d, pu4Tow = %d\n", pi2WeekNo, pu4Tow);
+ GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int mtk_gps_epo_server_data_is_changed() {
+ time_t uTime_end = 0;
+ time_t uTime_start = 0;
+ int fd_end = -1;
+ int fd_start = -1;
+ char gps_epo_data_file_name_end[EPO_FILE_NAME_MAX_SIZE] = {0};
+ char gps_epo_data_file_name_start[EPO_FILE_NAME_MAX_SIZE] = {0};
+ time_t uSecond_start;
+ time_t uSecond_end;
+ unsigned int u4GpsSecs_start;
+ unsigned int u4GpsSecs_end;
+ int ret = 0;
+
+ strncat(gps_epo_data_file_name_start, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name_start));
+ strncat(gps_epo_data_file_name_start, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name_start));
+
+ fd_start = open(gps_epo_data_file_name_start, O_RDONLY);
+ if (fd_start >= 0) {
+ int res = 0;
+ res = mtk_gps_epo_piece_data_start(fd_start, &u4GpsSecs_start, &uSecond_start);
+ if (res == 0) {
+ uTime_start = uSecond_start;
+ } else {
+ epo_download_failed = 1;
+ ret = 1;
+ LOGE("Get start time failed\n");
+ }
+ close(fd_start);
+ } else {
+ LOGE("Open start file failed\n");
+ }
+ if (gps_epo_file_count > 0) {
+ gps_download_epo_file_name(gps_epo_file_count - 1);
+ strncat(gps_epo_data_file_name_end, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name_end));
+ strncat(gps_epo_data_file_name_end, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name_end));
+
+ // open file
+ fd_end = open(gps_epo_data_file_name_end, O_RDONLY);
+ if (fd_end >= 0) {
+ int res = 0;
+ res = mtk_gps_epo_piece_data_end(fd_end, &u4GpsSecs_end, &uSecond_end);
+ if (res == 0) {
+ uTime_end = uSecond_end;
+ } else {
+ epo_download_failed = 1;
+ LOGE("Get end time failed\n");
+ ret = 1;
+ }
+ close(fd_end);
+ } else {
+ LOGE("Open end file failed\n");
+ }
+ } else if (gps_epo_file_count == 0) {
+ uTime_end = uTime_start;
+ }
+
+ // LOGD("gps_epo_data_file_start =%s, end =%s\n", gps_epo_data_file_name_start, gps_epo_data_file_name_end);
+ LOGD("The end time of EPO file is %s, The start time of EPO file is %s\n",
+ ctime(&uTime_end), ctime(&uTime_start));
+ if (uTime_start >= ((24*60*60) + uTime_end)) {
+ int i;
+ LOGD("The epo data is updated on the server!!!\n");
+ for (i = gps_epo_file_count; 0 <= i; i--) {
+ char gps_epo_piece_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+
+ gps_download_epo_file_name(i);
+ strncat(gps_epo_piece_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_piece_file_name));
+ strncat(gps_epo_piece_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_piece_file_name));
+ unlink(gps_epo_piece_file_name);
+ }
+ unlink(EPO_UPDATE_HAL);
+ gps_epo_file_count = 0;
+ return 1;
+ }
+ return ret;
+}
+#endif
+static int mtk_epo_is_expired(int wifi_tragger) {
+ time_t uTime[3]; // [0] epo start time, [1] download time, [2] expired time
+ memset(uTime, 0, sizeof(uTime));
+ time_t now = time(NULL);
+ struct tm tm_utc;
+ time_t time_utc;
+ long expired_set = 0;
+ int download_day = 0;
+
+ gmtime_r(&now, &tm_utc);
+ time_utc = mktime(&tm_utc);
+ mtk_gps_epo_file_time_hal(uTime);
+
+ if (wifi_tragger) {
+ expired_set = wifi_epo_period*24*60*60; // for wifi tragger we change checking expired time to 1 day.
+ } else {
+ download_day = (uTime[2] - uTime[0])/(24*60*60);
+ // LOGD("epo data downloaded dat: %d\n", download_day);
+ if (download_day < 3) {
+ expired_set = 0;
+ } else if (download_day < 6) {
+ expired_set = 3*24*60*60;
+ } else if ((6 <= download_day) && (download_day < 9)) {
+ expired_set = 5*24*60*60;
+ } else if ((9 <= download_day) && (download_day < 12)) {
+ expired_set = 7*24*60*60;
+ } else if ((12 <= download_day) && (download_day < 15)) {
+ expired_set = 7*24*60*60;
+ } else if ((15 <= download_day) && (download_day < 18)) {
+ expired_set = 7*24*60*60;
+ } else if (download_day >= 18) {
+ expired_set = 7*24*60*60;
+ }
+ }
+
+ LOGD("current time: %ld, current time:%s", time_utc, ctime(&time_utc));
+ LOGD("EPO start time: %ld, EPO start time: %s", uTime[0], ctime(&uTime[0]));
+ // LOGD("EPO expired_set: %lld", expired_set);
+ if ((time_utc - uTime[0]) >= expired_set) {
+ LOGD("EPO file is expired");
+ gps_epo_file_count = 0;
+ return 1;
+ } else if ((time_utc - uTime[0]) < 0) {
+ LOGD("Current time is invalid");
+ gps_epo_file_count = 0;
+ return 1;
+ } else {
+ LOGD("EPO file is valid, no need update");
+ return 0;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// MAIN -> EPO Download (handlers)
+static int mnld_epo_download() {
+ //LOGD("begin\n");
+ int ret = EPO_DOWNLOAD_RESULT_FAIL;
+
+ ret = epo_file_download_impl();
+
+ LOGD_ENG("download epo file completed!file count=%d, epo_download_result=%d\n",
+ gps_epo_file_count, ret);
+
+ if (mnld_epo_download_done(ret) == -1) {
+ LOGE("mnld_epo_download_done failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+
+ //LOGD("end\n");
+ return ret;
+}
+static int epo_event_hdlr(int fd) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ main2epo_event cmd;
+ int read_len;
+
+ read_len = safe_recvfrom(fd, buff, sizeof(buff));
+ if (read_len <= 0) {
+ LOGE("epo_event_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+ return -1;
+ }
+
+ cmd = get_int(buff, &offset, sizeof(buff));
+ switch (cmd) {
+ case MAIN2EPO_EVENT_START: {
+ LOGD_ENG("mnld_epo_download() before");
+ // need to call mnld_epo_download_done() when EPO download is done
+ mnld_epo_download();
+ LOGW("mnld_epo_download() after");
+ break;
+ }
+ default: {
+ LOGE("epo_event_hdlr() unknown cmd=%d", cmd);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+#if 0
+static void epo_downloader_thread_timeout() {
+ if (mnld_timeout_ne_enabled() == false) {
+ LOGE("epo_downloader_thread_timeout() dump and exit.");
+ gps_dbg_log_exit_flush(0);
+ mnld_block_exit();
+ } else {
+ LOGE("epo_downloader_thread_timeout() crash here for debugging");
+ CRASH_TO_DEBUG();
+ }
+}
+#endif
+
+static void retry_alarm_timeout_handler() {
+ epo_download_retry = 1;
+ LOGD("epo_download_retry is =%d\n", epo_download_retry);
+}
+
+static void* epo_downloader_thread(void *arg) {
+ #define MAX_EPOLL_EVENT 50
+ //hdlr_timer = init_timer(epo_downloader_thread_timeout);
+ retry_download_timer = init_timer(retry_alarm_timeout_handler);
+ struct epoll_event events[MAX_EPOLL_EVENT];
+ UNUSED(arg);
+
+ int epfd = epoll_create(MAX_EPOLL_EVENT);
+ if (epfd == -1) {
+ LOGE("epo_downloader_thread() epoll_create failure reason=[%s]%d\n",
+ strerror(errno), errno);
+ return 0;
+ }
+
+ if (epoll_add_fd(epfd, g_fd_epo) == -1) {
+ LOGE("epo_downloader_thread() epoll_add_fd() failed for g_fd_epo failed");
+ return 0;
+ }
+ while (1) {
+ int i;
+ int n;
+ LOGD_ENG("epo_downloader_thread wait");
+ memset(events, 0, sizeof(events));
+ n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+ if (n == -1) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ LOGE("epo_downloader_thread() epoll_wait failure reason=[%s]%d",
+ strerror(errno), errno);
+ return 0;
+ }
+ }
+ mnld_wake_lock_take();
+ //start_timer(hdlr_timer, MNLD_EPO_HANDLER_TIMEOUT);
+ for (i = 0; i < n; i++) {
+ if (events[i].data.fd == g_fd_epo) {
+ if (events[i].events & EPOLLIN) {
+ epo_event_hdlr(g_fd_epo);
+ }
+ } else {
+ LOGE("epo_downloader_thread() unknown fd=%d",
+ events[i].data.fd);
+ }
+ }
+ //stop_timer(hdlr_timer);
+ mnld_wake_lock_give();
+ }
+
+ LOGE("epo_downloader_thread() exit");
+ return 0;
+}
+
+int epo_downloader_is_file_invalid() {
+ return mtk_epo_is_expired(0);
+}
+
+int epo_is_wifi_trigger_enabled() {
+ return gps_epo_wifi_trigger;
+}
+
+int epo_is_epo_download_enabled() {
+ return gps_epo_enable;
+}
+
+int epo_downloader_start() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, MAIN2EPO_EVENT_START);
+ return safe_sendto(MNLD_EPO_DOWNLOAD_SOCKET, buff, offset);
+}
+
+int epo_downloader_init() {
+ pthread_t pthread_epo;
+ g_fd_epo = socket_bind_udp(MNLD_EPO_DOWNLOAD_SOCKET);
+ if (g_fd_epo < 0) {
+ LOGE("socket_bind_udp(MNLD_EPO_DOWNLOAD_SOCKET) failed");
+ return -1;
+ }
+
+ pthread_create(&pthread_epo, NULL, epo_downloader_thread, NULL);
+ return 0;
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/gps_controller.c b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/gps_controller.c
new file mode 100755
index 0000000..249d817
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/gps_controller.c
@@ -0,0 +1,3374 @@
+#include <stdio.h> /* Standard input/output definitions */
+#include <string.h> /* String function definitions */
+#include <unistd.h> /* UNIX standard function definitions */
+#include <fcntl.h> /* File control definitions */
+#include <errno.h> /* Error number definitions */
+#include <termios.h> /* POSIX terminal control definitions */
+#include <stdbool.h>
+#include <time.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/epoll.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#if defined(__ANDROID_OS__)
+#include <cutils/properties.h>
+#include <linux/fm.h>
+#endif
+#include <signal.h>
+#include <inttypes.h>
+#include "mtk_prop_util.h"
+
+#include "mtk_gps.h"
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#include "gps_controller.h"
+#include "mnld.h"
+#include "mnld_utile.h"
+#include "mnl2agps_interface.h"
+#include "mnl2hal_interface.h"
+#include "mtk_geofence_main.h"
+#include "gps_dbg_log.h"
+#include "mpe.h"
+
+#include "mtk_gps_agps.h"
+#include "mtk_gps_type.h"
+#include "mnl_common.h"
+#include "agps_agent.h"
+#include "mtk_gps_sys_fp.h"
+#include "SUPL_encryption.h"
+#if MTK_GPS_NVRAM
+#include "CFG_GPS_File.h"
+#endif
+#include "epo.h"
+#include "qepo.h"
+#include "mtknav.h"
+#include "nmea_parser.h"
+
+#include "mtk_mnld_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "gps_controlller"
+//%MNLD_Version%
+#define MNLD_VER "1.00"
+typedef enum {
+ MAIN2GPS_EVENT_START = 0,
+ MAIN2GPS_EVENT_STOP = 1,
+ MAIN2GPS_DELETE_AIDING_DATA = 2,
+ GPS2GPS_NMEA_DATA_TIMEOUT = 3,
+#if defined(GPS_SUSPEND_SUPPORT)
+ MAIN2GPS_EVENT_SUSPEND = 4,
+ MAIN2GPS_EVENT_SUSPEND_TO_CLOSE = 5,
+ RST2GPS_EVENT_SUSPEND_TO_CLOSE = 6,
+ MNL2GPS_EVENT_MNL_DO_RESUME_DONE = 7,
+#endif
+} main2gps_event;
+
+#define QEPO_BD 1
+#define QEPO_GA 1
+
+#ifdef MTK_GPS_CO_CLOCK_DATA_IN_MD
+#define GPS_CALI_DATA_PATH "/mnt/vendor/nvdata/md/NVRAM/CALIBRAT/ML4A_000"
+#define GPS_CALI_DATA_DENALI_PATH "/mnt/vendor/nvdata/md/NVRAM/CALIBRAT/EL6N_000"
+#endif
+
+enum {
+ GPS_MEASUREMENT_UNKNOWN = 0xFF,
+ GPS_MEASUREMENT_INIT = 0x00,
+ GPS_MEASUREMENT_CLOSE = 0x01,
+};
+enum {
+ GPS_NAVIGATION_UNKNOWN = 0xFF,
+ GPS_NAVIGATION_INIT = 0x00,
+ GPS_NAVIGATION_CLOSE = 0x01,
+};
+#define DBG_DEV "/dev/ttygserial"
+#define BEE_PATH MTK_GPS_DATA_PATH
+#define DSP_BIN_LOG_FILE MTK_GPS_DATA_PATH"DSPdebug.log"
+#define PARM_FILE MTK_GPS_DATA_PATH"gpsparm.dat"
+#define NV_FILE MTK_GPS_DATA_PATH"mtkgps.dat"
+#define OFL_NV_FILE MTK_GPS_DATA_PATH"mtkgps_ofl.dat"
+
+#define PATH_INTERNAL "internal_sd"
+#define PATH_EXTERNAL "external_sd"
+#define PATH_DEFAULT "/mnt/sdcard/"
+#define PATH_EX "/mnt/sdcard2/"
+#define SDCARD_SWITCH_PROP "persist.mtklog.log2sd.path"
+
+#define CARRIER_FREQ_GPS_L1_MIN ((1575.42-10)*1000000)
+#define CARRIER_FREQ_GPS_L1_MAX ((1575.42+10)*1000000)
+#define CARRIER_FREQ_GPS_L5_MIN ((1176.45-10)*1000000)
+#define CARRIER_FREQ_GPS_L5_MAX ((1176.45+10)*1000000)
+#define CARRIER_FREQ_GLO_L1_MIN ((1602-10)*1000000)
+#define CARRIER_FREQ_GLO_L1_MAX ((1602+10)*1000000)
+#define CARRIER_FREQ_GAL_E1_MIN ((1575.42-10)*1000000)
+#define CARRIER_FREQ_GAL_E1_MAX ((1575.42+10)*1000000)
+#define CARRIER_FREQ_GAL_E5A_MIN ((1176.45-10)*1000000)
+#define CARRIER_FREQ_GAL_E5A_MAX ((1176.45+10)*1000000)
+#define CARRIER_FREQ_BD_B1_MIN ((1561.098-10)*1000000)
+#define CARRIER_FREQ_BD_B1_MAX ((1561.098+10)*1000000)
+#define CARRIER_FREQ_BD_B2_MIN ((1207.14-10)*1000000)
+#define CARRIER_FREQ_BD_B2_MAX ((1207.14+10)*1000000)
+#define CARRIER_FREQ_BD_B3_MIN ((1268.52-10)*1000000)
+#define CARRIER_FREQ_BD_B3_MAX ((1268.52+10)*1000000)
+
+/*---------------------------------------------------------------------------*/
+
+#define GET_VER
+#ifdef TCXO
+#undef TCXO
+#endif
+#define TCXO 0
+#ifdef CO_CLOCK
+#undef CO_CLOCK
+#endif
+#define CO_CLOCK 1
+#ifdef CO_DCXO
+#undef CO_DCXO
+#endif
+#define CO_DCXO 2
+#define GPS_CLOCK_TYPE_P "vendor.gps.clock.type"
+#define COMBO_IOC_GPS_IC_HW_VERSION 7
+#define COMBO_IOC_GPS_IC_FW_VERSION 8
+
+#define COMBO_IOC_TRIGGER_WMT_ASSERT 12
+#define COMBO_IOC_TRIGGER_WMT_SUBSYS_RESET 13
+#define COMBO_IOC_TAKE_GPS_WAKELOCK 14
+#define COMBO_IOC_GIVE_GPS_WAKELOCK 15
+#define COMBO_IOC_GET_GPS_LNA_PIN 16
+#define COMBO_IOC_GPS_FWCTL 17
+#define COMBO_IOC_GPS_HW_SUSPEND 18
+#define COMBO_IOC_GPS_HW_RESUME 19
+#define COMBO_IOC_GPS_LISTEN_RST_EVT 20
+
+#define MNLD_GPS_HW_SUSPEND_MODE_DEEP_STOP 0
+#define MNLD_GPS_HW_SUSPEND_MODE_CLK_EXT 1
+
+#define ADC_CAPTURE_MAX_SIZE 0x50000
+static int g_fd_gps;
+/////////////// temporary defineded for Android ////////////
+//////////////////////////////////////////
+
+// for one binary
+#define RAW_DATA_SUPPORT 1
+#if RAW_DATA_SUPPORT
+#define GPS_CONF_FILE_SIZE 100
+#define RAW_DATA_CONTROL_FILE_PATH MTK_GPS_DATA_PATH"gps.conf"
+static int gps_raw_debug_mode = 0;
+static int mtk_msg_raw_meas_flag = 0;
+#define IS_SPACE(ch) ((ch == ' ') || (ch == '\t') || (ch == '\n'))
+#endif
+
+// static unsigned char gps_measurement_state = GPS_MEASUREMENT_UNKNOWN;
+// static unsigned char gps_navigation_state = GPS_NAVIGATION_UNKNOWN;
+extern unsigned char gps_debuglog_state;
+extern char gps_debuglog_file_name[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+extern bool g_gpsdbglogThreadExit;
+extern MTK_GPS_MNL_INFO mtk_gps_mnl_info;
+extern UINT32 g_dbglog_file_size_in_config; //Max dbg log file size read from config file
+extern UINT32 g_dbglog_folder_size_in_config; //Max dbg log folder size read from config file
+
+UINT32 adc_emi_address = 0;
+int gps_emi_fd = -1;
+
+UINT32 assist_data_bit_map = FLAG_HOT_START;
+static UINT32 delete_aiding_data;
+#if MTK_GPS_NVRAM
+int gps_nvram_valid = 0;
+ap_nvram_gps_config_struct stGPSReadback;
+#endif
+int g_is_1Hz = 1;
+int dsp_fd = -1;
+int dsp2_fd = -1;
+#if ANDROID_MNLD_PROP_SUPPORT
+char chip_id[PROPERTY_VALUE_MAX]={0};
+#else
+char chip_id[100]={0};
+#endif
+int epo_setconfig = 0;
+extern int gps_epo_type;
+int start_time_out = MNLD_GPS_START_TIMEOUT;
+int nmea_data_time_out = MNLD_GPS_NMEA_DATA_TIMEOUT;
+static int exit_meta_factory = 0;
+static int PDN_test_enable = 0;
+int in_meta_factory = 0;
+bool mnld_exiting = false;
+static int gps_restart = 0;
+#define M_RESTART 0
+static SYNC_LOCK_T lock_for_sync[] = {{PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0}};
+static int mtk_gps_log_hide = 0;
+bool g_mnl_init = false; // to check if MNL thread initialized. true: initialized. false: not initialized
+int g_agc_level = 0;
+bool g_enable_full_tracking = 0;
+int mnl_prop_configed_socketport = 0;
+
+#define HIDE_LOG_PROP "ro.vendor.mtk_log_hide_gps"
+
+#define fieldp_copy(dst, src, f) (dst)->f = (src)->f
+#define field_copy(dst, src, f) (dst).f = (src).f
+
+extern UINT8 sv_type_agps_set;
+extern UINT8 sib8_16_enable;
+extern UINT8 lppe_enable;
+extern UINT8 enable_debug2app;
+
+extern int mnld_init();
+extern int mtk_gps_sys_init();
+extern int mtk_gps_sys_uninit();
+static int mnld_gps_start_impl(void);
+static int mnld_gps_stop_impl(void);
+static int linux_gps_init(void);
+#if ANDROID_MNLD_PROP_SUPPORT
+static int get_prop(unsigned int index);
+#endif
+static int gps_raw_data_enable(void);
+#if 0 //gnss measurement API include gps info
+static void get_gps_measurement_clock_data();
+#endif
+static void get_gnss_measurement_clock_data();
+#if 0 //gnss navigation API include gps info
+static void get_gps_navigation_event();
+#endif
+static void get_gnss_navigation_event();
+
+#if defined(GPS_SUSPEND_SUPPORT)
+static pthread_t pthread_rst_listener = C_INVALID_TID;
+
+// Note: int for multi-thread/multi-core write-safty
+static volatile int pthread_rst_listener_rst_detected_flag = 0;
+static volatile int pthread_rst_listener_need_exit_flag = 0;
+static volatile int pthread_rst_listernr_is_joinable = 0;
+static volatile int gps_controller_suspend_done_flag = 0;
+static volatile unsigned int g_gps_controller_session_id = 0;
+
+static int gps_device_rst_listener_thread_init();
+static int gps_device_rst_listener_thread_exit_and_join();
+void gps_controller_session_id_update(void);
+unsigned long gps_controller_session_id_get(void);
+void mnl_gps_gps_close_fd(void);
+void mnl_gps_gps_close_fd2(void);
+bool mnld_do_gps_suspend_resume(int fd, mnld_gps_do_hw_ctrl_opcode op);
+static int mnld_gps_stop_or_suspend_impl(bool is_to_suspend);
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// MAIN -> GPS Control (handlers)
+static int mnld_gps_start(int delete_aiding_data_flags) {
+ LOGD_ENG("mnld_gps_start flag=0x%x", delete_aiding_data_flags);
+
+ int ret = 0;
+ assist_data_bit_map = delete_aiding_data_flags;
+
+ if ((ret = mnld_gps_start_impl())) {
+ LOGW("mnld_gps_start() fail, ret=%d", ret);
+ return ret;
+ } else {
+ LOGD("mnld_gps_start() success");
+ }
+
+ return 0;
+}
+
+static int mnld_gps_stop() {
+ LOGD_ENG("mnld_gps_stop begin");
+ int err = 0;
+
+ mnld_gps_stop_nmea_monitor();
+ if ((err = mnld_gps_stop_impl())) {
+ LOGD("mnld_gps_stop_impl: err = %d", err);
+ return err;
+ } else {
+ if (mnld_gps_stop_done() == -1) {
+ LOGE("mnld_gps_stop_done failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ LOGD("mnld_gps_stop_impl success");
+ }
+ //Stop nmea timeout monitor timer again, to stop timer started in GPS stop duration.
+ mnld_gps_stop_nmea_monitor();
+
+ return 0;
+}
+
+#if defined(GPS_SUSPEND_SUPPORT)
+static int mnld_gps_suspend() {
+ LOGD_ENG("mnld_gps_suspend begin");
+ int err = 0;
+
+ if ((err = mnld_gps_stop_nmea_monitor())) {
+ LOGE("mnld_gps_stop_nmea_monitor err = %d", err);
+ }
+ if ((err = mnld_gps_stop_or_suspend_impl(true))) {
+ LOGD("mnld_gps_stop_or_suspend_impl(true): err = %d", err);
+ return err;
+ }
+
+ if (gps_controller_suspend_done_flag) {
+ //Notify mnld main thread suspend done, mnld will goto "SUSPEND" state,
+ // which is almost same as "IDLE". The differences can be seen in
+ // fsm_gps_state_suspend and fsm_gps_state_idle, the only diff is that:
+ // fsm_gps_state_suspend has an handler for GPS_EVENT_SUSPEND_CLOSE and
+ // fsm_gps_state_idle not.
+ if (-1 == mnld_gps_suspend_done()) {
+ LOGE("mnld_gps_suspend_done() err = %d", err);
+ } else {
+ LOGD("mnld_gps_suspend success");
+ }
+ } else {
+ //Notify mnld main thread stop done, mnld will goto "IDLE" state
+ if (-1 == mnld_gps_stop_done()) {
+ LOGE("mnld_gps_stop_done() err = %d", err);
+ } else {
+ LOGW("mnld_gps_suspend change to close success");
+ }
+ }
+ return 0;
+}
+
+static bool mnld_gps_try_suspend_to_close(void) {
+ bool okay;
+ if (gps_controller_suspend_done_flag) {
+ gps_device_rst_listener_thread_exit_and_join();
+ mnl_gps_gps_close_fd();
+#ifdef MTK_GPS_DUAL_FREQ_SUPPORT /*Defined in Android.mk*/
+ mnl_gps_gps_close_fd2();
+#endif
+ gps_controller_suspend_done_flag = 0;
+ okay = true;
+ } else {
+ LOGD("already close or not suspend, do nothing");
+ okay = false;
+ }
+
+ return okay;
+}
+#endif
+
+static int mnld_gps_delete_aiding_data(int delete_aiding_data_flags) {
+ LOGD("mnld_gps_delete_aiding_data flag=0x%x", delete_aiding_data_flags);
+ MTK_GPS_PARAM_RESTART restart = {MTK_GPS_START_HOT};
+ int ret = 0;
+ if (delete_aiding_data_flags == FLAG_HOT_START) {
+ restart.restart_type = MTK_GPS_START_HOT;
+ } else if (delete_aiding_data_flags == FLAG_WARM_START) {
+ restart.restart_type = MTK_GPS_START_WARM;
+ } else if (delete_aiding_data_flags == FLAG_COLD_START) {
+ restart.restart_type = MTK_GPS_START_COLD;
+ } else if (delete_aiding_data_flags == FLAG_FULL_START) {
+ restart.restart_type = MTK_GPS_START_FULL;
+ } else if (delete_aiding_data_flags == FLAG_AGPS_START) {
+ restart.restart_type = MTK_GPS_START_AGPS;
+ } else if (delete_aiding_data_flags == FLAG_DELETE_EPH_ALM_START) {
+ restart.restart_type = MTK_GPS_START_D_EPH_ALM;
+ } else if (delete_aiding_data_flags == FLAG_DELETE_TIME_START) {
+ restart.restart_type = MTK_GPS_START_D_TIME;
+ } else if (delete_aiding_data_flags == FLAG_AGPS_HOT_START) {
+ restart.restart_type = MTK_GPS_START_HOT;
+ } else if (delete_aiding_data_flags == FLAG_AGPS_WARM_START) {
+ restart.restart_type = MTK_GPS_START_WARM;
+ } else if (delete_aiding_data_flags == FLAG_AGPS_COLD_START) {
+ restart.restart_type = MTK_GPS_START_COLD;
+ } else if (delete_aiding_data_flags == FLAG_AGPS_FULL_START) {
+ restart.restart_type = MTK_GPS_START_FULL;
+ } else if (delete_aiding_data_flags == FLAG_AGPS_AGPS_START) {
+ restart.restart_type = MTK_GPS_START_AGPS;
+ } else {
+ assist_data_bit_map = delete_aiding_data_flags;
+ mtk_gps_delete_nv_data(assist_data_bit_map);
+ }
+
+ if ((ret = mtk_gps_set_param(MTK_PARAM_CMD_RESTART, &restart))) {
+ LOGE("GPS restart fail %d", ret);
+ }
+
+ gps_restart = 1;
+ get_condition(&lock_for_sync[M_RESTART]);
+ gps_restart = 0;
+ if (mnld_gps_reset_done() == -1) {
+ LOGE("mnld_gps_reset_done failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ return 0;
+}
+/////////////////////////////////////////////////////////////////////////////
+
+/*****************************************************************************/
+MNL_CONFIG_T mnld_cfg = {
+ .timeout_init = MNLD_GPS_START_TIMEOUT,
+ .timeout_monitor = MNLD_GPS_NMEA_DATA_TIMEOUT,
+ .OFFLOAD_enabled = 0,
+ .OFFLOAD_switchMode = 0, //0: always offload mode 1: Offload/Host-base auto switch mode
+ .adc_capture_enabled = 1, //1: Enable adc capture; 0: Disable adc capture;
+#if defined(GPS_SUSPEND_SUPPORT)
+ //Note: set them @mnld_gps_suspend_check_capability
+ .SUSPEND_enabled = 0,
+ .SUSPEND_timeout = 0,
+ .SUSPEND_ext_enabled = 0,
+ .SUSPEND_ext_timeout = 0,
+ .SUSPEND_ext_available = 0,
+#endif
+ .bitmap_nfw_ctrl = 0,//MNL_NFW_CTRL_MAIN_BIT|MNL_NFW_CTRL_GNSS_BIT, //NLP not in scope as default
+ .RfPathLossDb_Ap = 0,
+};
+
+static MNL_CONFIG_T mnl_config = {
+ .init_speed = 38400,
+ .link_speed = 921600,
+ .debug_nmea = 1,
+ .debug_mnl = MNL_NEMA_DEBUG_SENTENCE, /*MNL_NMEA_DEBUG_NORMAL,*/
+ .pmtk_conn = PMTK_CONNECTION_SOCKET,
+ .socket_port = PMTK_CONNECTION_SOCKET_PORT,
+ .dev_dbg = DBG_DEV,
+ .dev_dsp = DSP_DEV,
+ .dev_dsp2 = DSP_DEV2,
+ .dev_gps = "UseCallback",
+ .bee_path = BEE_PATH,
+ .epo_file = EPO_FILE,
+ .epo_update_file = EPO_UPDATE_HAL,
+ .qepo_file = QEPO_FILE,
+ .qepo_update_file = QEPO_UPDATE_HAL,
+ .mnl_cfg_xml_default_path = MNL_CFG_XML_DEFAULT_PATH,
+ .mnl_read_write_path = MNL_READ_WRITE_PATH,
+ .delay_reset_dsp = 500,
+ .nmea2file = 0,
+ .dbg2file = 0,
+ .nmea2socket = 1,
+ .dbg2socket = 0,
+ .timeout_init = 0,
+ .timeout_monitor = 0,
+ .timeout_wakeup = 0,
+ .timeout_sleep = 0,
+ .timeout_pwroff = 0,
+ .timeout_ttff = 0,
+ .EPO_enabled = 0,
+ .BEE_enabled = 0,
+ .SUPL_enabled = 1,
+ .SUPLSI_enabled = 1,
+ .EPO_priority = 64,
+ .BEE_priority = 32,
+ .SUPL_priority = 96,
+ .fgGpsAosp_Ver = 1,
+ .AVAILIABLE_AGE = 2,
+ .RTC_DRIFT = 30,
+ .TIME_INTERVAL = 10,
+ .u1AgpsMachine = 0, // default use spirent "0"
+ .ACCURACY_SNR = 1,
+ .GNSSOPMode = MTK_CONFIG_GPS_GLONASS_BEIDOU_GALILEO_NAVIC, // 0: G+G; 1: G+B
+ .dbglog_file_max_size = 25*1024*1024,
+ .dbglog_folder_max_size = 300*1024*1024,
+ .fast_HTTFF = 1,
+ .debug_file_name = LOG_FILE,
+ .fix_interval = 1000,
+ .pps_mode = MTK_PPS_3D_FIX,
+ .pps_delay = 0,
+ .pps_polarity = 0,
+ .pps_duty = 100,
+ .elev_mask = 5
+};
+
+MTK_GPS_SV_BLACKLIST svBlacklist = {
+ .mode = 0,
+ .sv_list = {0}
+};
+
+void mtk_null(UINT16 a) {
+ LOGD_ENG("mtk_null a=%d\n", a);
+ return;
+}
+
+INT32 mtk_null_void(void) {
+ LOGD_ENG("mtk_null_void\n");
+ return 0;
+}
+
+INT32 mtk_null_buf(UINT8 *buf, UINT32 len) {
+ LOGD_ENG("mtk_null_buf buf=%p, len:%d\n", buf, len);
+ return 0;
+}
+
+INT32 mtk_null_type_buf(MTK_GPS_OFL_CB_TYPE type, UINT16 len, UINT8 * buf) {
+ LOGD_ENG("mtk_null_type_buf, type=%d, buf=%p, len:%d\n", type, buf, len);
+ return 0;
+}
+
+//Fix build error
+int SUPL_encrypt(unsigned char *plain, unsigned char *cipher, unsigned int length) {
+ LOGD_ENG("plain:%p, cipher:%p, len:%d", plain, cipher, length);
+ return 0;
+}
+int SUPL_decrypt(unsigned char *plain, unsigned char *cipher, unsigned int length) {
+ LOGD_ENG("plain:%p, cipher:%p, len:%d", plain, cipher, length);
+ return 0;
+}
+#if 0
+MTK_BEE_INT MTK_BEE_Have_Enough_Eph (short i2WeekNo, int i4Tow){}
+MTK_BEE_INT MTK_BEE_Get_Available_Info (short i2WeekNo, int i4Tow, unsigned char BeeAvail[32]){}
+MTK_BEE_VOID MTK_BEE_Proc_Eph (unsigned char u1SvId, unsigned int au4Word[24]){}
+MTK_BEE_INT MTK_BEE_Get_Data (unsigned char u1SvId, short i2WeekNo, int i4Tow, unsigned char BeeData[48]){}
+#endif
+
+int SUPL_encrypt_wrapper(unsigned char *plain,
+ unsigned char *cipher, unsigned int length) {
+ return SUPL_encrypt(plain, cipher, length);
+}
+
+int SUPL_decrypt_wrapper(unsigned char *plain,
+ unsigned char *cipher, unsigned int length) {
+ return SUPL_decrypt(plain, cipher, length);
+}
+
+void crypt_epo_data (char data[72]) {
+
+}
+
+MTK_GPS_SYS_FUNCTION_PTR_T porting_layer_callback = {
+ .sys_gps_mnl_callback = mtk_gps_sys_gps_mnl_callback,
+ .sys_nmea_output_to_app = mtk_gps_sys_nmea_output_to_app,
+ .sys_nmea_output_to_mnld = mtk_gps_sys_nmea_output_to_mnld,
+ .sys_frame_sync_enable_sleep_mode = mtk_gps_sys_frame_sync_enable_sleep_mode,
+ .sys_frame_sync_meas_req_by_network = mtk_gps_sys_frame_sync_meas_req_by_network,
+ .sys_frame_sync_meas_req = mtk_gps_sys_frame_sync_meas_req,
+ .sys_agps_disaptcher_callback = mtk_gps_sys_agps_disaptcher_callback,
+ .sys_pmtk_cmd_cb = mtk_null,
+ .encrypt = SUPL_encrypt_wrapper,
+ .decrypt = SUPL_decrypt_wrapper,
+ .ofl_sys_rst_stpgps_req = mtk_null_void,
+ .ofl_sys_submit_flp_data = mtk_null_buf,
+ .sys_alps_gps_dbg2file_mnld = mnl_sys_alps_gps_dbg2file_mnld,
+ .ofl_sys_mnl_offload_callback = mtk_null_type_buf,
+ .sys_gps_mnl_data2mnld_callback = sys_gps_mnl_data2mnld_callback,
+#if defined(GPS_SUSPEND_SUPPORT)
+ .sys_do_hw_suspend_resume = mtk_gps_sys_do_hw_suspend_resume,
+ .sys_clk_extention_set = mtk_gps_sys_suspend_extention_set,
+#endif
+};
+
+/*****************************************************************************/
+int mtk_gps_log_is_hide(void) {
+ return (!((mtk_gps_log_hide == 0) || (mtk_gps_log_hide == 2)));
+}
+
+int mtk_gps_log_get_hide_opt(void) {
+ return mtk_gps_log_hide;
+}
+
+void mtk_gps_log_set_hide_opt_by_mnl_config(void) {
+ int mtk_gps_log_hide_old = mtk_gps_log_hide;
+
+ //mtk_gps_log_hide can be changed by mnl.prop only when it equals zero
+ if ((mtk_gps_log_hide == 0) && (mnl_config.log_hide != 0)) {
+ mtk_gps_log_hide = mnl_config.log_hide;
+
+ if (mtk_gps_log_hide == 2) {
+ gps_dbg_log_state_set_encrypt_enable();
+ }
+
+ LOGD("mnl_config.log_hide = %d, mtk_gps_log_hide: %d -> %d",
+ mnl_config.log_hide, mtk_gps_log_hide_old, mtk_gps_log_hide);
+ }
+}
+
+int mnld_adc_capture_is_enabled() {
+ return !!(mnld_cfg.adc_capture_enabled);
+}
+
+#if defined(GPS_SUSPEND_SUPPORT)
+bool mnld_gps_suspend_is_enabled() {
+ return !!(mnld_cfg.SUSPEND_enabled);
+}
+
+int mnld_gps_suspend_get_timeout_sec() {
+ return mnld_cfg.SUSPEND_timeout;
+}
+
+bool mnld_gps_suspend_ext_is_enabled() {
+ return !!(mnld_cfg.SUSPEND_ext_available && mnld_cfg.SUSPEND_ext_enabled);
+}
+
+bool mnld_gps_suspend_ext_is_available() {
+ return !!(mnld_cfg.SUSPEND_ext_available);
+}
+
+int mnld_gps_suspend_ext_get_timeout_sec() {
+ return mnld_cfg.SUSPEND_ext_timeout;
+}
+
+void mtk_gps_suspend_extention_available_set(INT32 available) {
+ mnld_cfg.SUSPEND_ext_available = available;
+ LOGD("Clock extention available set from mnl:available->%d", mnld_cfg.SUSPEND_ext_available);
+}
+
+void mtk_gps_sys_suspend_extention_set(INT32 enable, INT32 ext_sec) {
+ mnld_cfg.SUSPEND_ext_enabled = enable;
+ mnld_cfg.SUSPEND_ext_timeout = ext_sec;
+ LOGD("Clock extention set from mnl:enable->%d, timeout->%d", mnld_cfg.SUSPEND_ext_enabled, mnld_cfg.SUSPEND_ext_timeout);
+}
+#endif
+
+bool mnld_nfw_ctrl_nlp_enabled() {
+ return (((unsigned int)mnld_cfg.bitmap_nfw_ctrl & MNL_NFW_CTRL_MAIN_BIT) && ((unsigned int)mnld_cfg.bitmap_nfw_ctrl & MNL_NFW_CTRL_NLP_BIT));
+}
+
+bool mnld_nfw_ctrl_gnss_enabled() {
+ return (((unsigned int)mnld_cfg.bitmap_nfw_ctrl & MNL_NFW_CTRL_MAIN_BIT) && ((unsigned int)mnld_cfg.bitmap_nfw_ctrl & MNL_NFW_CTRL_GNSS_BIT));
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * mnld_timeout_ne_enabled
+ * DESCRIPTION
+ * To get the property and check need to trigger MNLD ne or not
+ * If timeout NE trigger enabled, will trigger NE
+ * If timeout NE trigger disabled, will use "dump + exit" to instead NE(default)
+ * PARAMETERS
+ * None
+ * RETURNS
+ * None
+ *****************************************************************************/
+bool mnld_timeout_ne_enabled(void) {
+#if ANDROID_MNLD_PROP_SUPPORT
+ char result[PROPERTY_VALUE_MAX] = {0};
+
+ if((in_meta_factory == 1)
+ ||((property_get("vendor.debug.gps.mnld.ne", result, NULL) != 0) && (result[0] == '1'))) {
+ LOGD("mnld NE enabled!!!");
+ return true;
+ } else {
+ LOGD("mnld NE disabled!!!");
+ return false;
+ }
+#else
+ if(in_meta_factory == 1) {
+ LOGD("mnld NE enabled!!!");
+ return true;
+ } else {
+ LOGD("mnld NE enabled!!!");
+ return true;
+ }
+#endif
+}
+
+
+#if defined(GPS_SUSPEND_SUPPORT)
+void mnld_gps_suspend_check_capability(void) {
+ if (strcmp(chip_id, "0x6768") == 0) {
+ mnld_cfg.SUSPEND_enabled = 1; //Enable suspend mode, will go to deep stop mode directly until screen is on
+ mnld_cfg.SUSPEND_timeout = MNLD_GPS_SUSPEND_TIMEOUT;
+ mnld_cfg.SUSPEND_ext_available = 0;
+ mnld_cfg.SUSPEND_ext_enabled = 0;
+ mnld_cfg.SUSPEND_ext_timeout = 0; //MNLD_GPS_SUSPEND_TIMEOUT;,
+ } else if ((strcmp(chip_id, "0x6765") == 0) || (strcmp(chip_id, "0x6885") == 0) || (strcmp(chip_id, "0x6873") == 0) ||
+ strcmp(chip_id, "0x6880") == 0 || strcmp(chip_id, "0x6890") == 0) { //will be setted in libmnl
+ mnld_cfg.SUSPEND_enabled = 0; //Default disable suspend mode
+ mnld_cfg.SUSPEND_timeout = 0; //MNLD_GPS_SUSPEND_TIMEOUT;
+ mnld_cfg.SUSPEND_ext_available = 1; //Support clock extension feature
+ mnld_cfg.SUSPEND_ext_enabled = 0; //Request from libmnl
+ mnld_cfg.SUSPEND_ext_timeout = 0; //MNLD_GPS_SUSPEND_TIMEOUT;,
+ }
+}
+#endif
+
+void get_chip_gnss_op_mode() {
+ if (strcmp(chip_id, "0x6765") == 0 || strcmp(chip_id, "0x3967") == 0 ||
+ strcmp(chip_id, "0x6761") == 0 || strcmp(chip_id, "0x6779") == 0 ||
+ strcmp(chip_id, "0x6768") == 0 || strcmp(chip_id, "0x6873") == 0 ) {
+ mnl_config.GNSSOPMode = MTK_CONFIG_GPS_GLONASS_BEIDOU_GALILEO;
+ } else if (strcmp(chip_id, "0x6885") == 0 || strcmp(chip_id, "0x6880") == 0 ||
+ strcmp(chip_id, "0x6890") == 0) {
+ mnl_config.GNSSOPMode = MTK_CONFIG_GPS_GLONASS_BEIDOU_GALILEO_NAVIC;
+ } else {
+ mnl_config.GNSSOPMode = MTK_CONFIG_GPS_GLONASS_BEIDOU;
+ }
+}
+
+static int mnld_internal = 0;
+static void mnld_internal_check(void) {
+#if ANDROID_MNLD_PROP_SUPPORT
+ char result[PROPERTY_VALUE_MAX] = {0};
+ if(property_get("ro.vendor.mtklog_internal", result, NULL) != 0) {
+ if(result[0] == '1') {
+ mnld_internal = 1;
+ } else {
+ mnld_internal = 0;
+ }
+ }
+#endif
+}
+
+void set_mnl_prop_config_socket_port() {
+ mnl_prop_configed_socketport = 1;
+}
+
+bool is_mnl_prop_config_socket_port () {
+ if(mnl_prop_configed_socketport == 1) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static void mnld_set_default_debug_socket(void) {
+ if (!is_mnl_prop_config_socket_port()) {
+ if((mnl_config.debug_nmea != 1) && (!in_meta_factory)) {
+ mnl_config.socket_port = MTK_GPS_NMEA_SOCKET_DISABLE;
+ } else {
+ mnl_config.socket_port = PMTK_CONNECTION_SOCKET_PORT;
+ }
+ }
+}
+
+int mnl_init() {
+
+ gps_dbg_log_state_init();
+
+ memset(&mtk_gps_mnl_info, 0, sizeof(mtk_gps_mnl_info));
+ if(mtk_gps_get_mnl_info(&mtk_gps_mnl_info)) {
+ LOGE("get mnl ver infor fail\n");
+ }
+ lppe_enable=mtk_gps_mnl_info.support_lppe;
+ /*setup property*/
+ if (!mnl_utl_load_property(&mnld_cfg)) {
+ start_time_out = mnld_cfg.timeout_init;
+ nmea_data_time_out = mnld_cfg.timeout_monitor;
+ }
+
+ if(!mnld_nfw_ctrl_nlp_enabled() && !mnld_nfw_ctrl_gnss_enabled()) {
+ mtk_gps_set_nfw_visibility_all(true); //Default set visibility as true if nfw control is disabled
+ }
+
+ gps_dbg_log_property_load();
+ mnld_internal_check();
+
+ MTK_GPS_SYS_FUNCTION_PTR_T* mBEE_SYS_FP = &porting_layer_callback;
+ if (mtk_gps_sys_function_register(mBEE_SYS_FP) != MTK_GPS_SUCCESS) {
+ LOGE("register callback for mnl fail\n");
+ }
+ else {
+ LOGD("register callback for mnl okey, mtk_gps_sys_function_register=%p\n", mtk_gps_sys_function_register);
+ }
+ return 0;
+}
+void get_gps_version() {
+#if ANDROID_MNLD_PROP_SUPPORT
+ if (strcmp(chip_id, "0x0321") == 0 || strcmp(chip_id, "0x0335") == 0 ||
+ strcmp(chip_id, "0x0337") == 0 ||strcmp(chip_id, "0x6735") == 0) {
+ property_set("vendor.gps.gps.version", "0x6735"); // Denali1/2/3
+ } else {
+ property_set("vendor.gps.gps.version", chip_id);
+ }
+ return;
+#endif
+}
+void get_chip_sv_support_capability(unsigned char* sv_type) {
+ if (strcmp(chip_id, "0x6620") == 0 || strcmp(chip_id, "0x6628") == 0 ||
+ strcmp(chip_id, "0x3336") == 0 || strcmp(chip_id, "0x6572") == 0 ||
+ strcmp(chip_id, "0x6582") == 0 || strcmp(chip_id, "0x6592") == 0 ||
+ strcmp(chip_id, "0x6571") == 0 || strcmp(chip_id, "0x6580") == 0 ||
+ strcmp(chip_id, "0x0335") == 0 || strcmp(chip_id, "0x6570") == 0) {
+ *sv_type = 1; // GPS only
+ } else if (strcmp(chip_id, "0x3332") == 0 || strcmp(chip_id, "0x6752") == 0 ||
+ strcmp(chip_id, "0x0321") == 0 || strcmp(chip_id, "0x0337") == 0 ||
+ strcmp(chip_id, "0x6755") == 0 || strcmp(chip_id, "0x6757") == 0 ||
+ strcmp(chip_id, "0x6763") == 0 || strcmp(chip_id, "0x6739") == 0) {
+ *sv_type = 3; // GPS+Glonass
+ } else if (strcmp(chip_id, "0x6797") == 0 || strcmp(chip_id, "0x6630") == 0 ||
+ strcmp(chip_id, "0x6759") == 0 || strcmp(chip_id, "0x6758") == 0 ||
+ strcmp(chip_id, "0x6771") == 0 || strcmp(chip_id, "0x6775") == 0) {
+ *sv_type = 7; // GPS+Glonass+Beidou
+ } else if (strcmp(chip_id, "0x6632") == 0 || strcmp(chip_id, "0x6765") == 0 ||
+ strcmp(chip_id, "0x3967") == 0 || strcmp(chip_id, "0x6761") == 0 ||
+ strcmp(chip_id, "0x6779") == 0 || strcmp(chip_id, "0x6768") == 0 ||
+ strcmp(chip_id, "0x6885") == 0 || strcmp(chip_id, "0x6873") == 0 ||
+ strcmp(chip_id, "0x6880") == 0 || strcmp(chip_id, "0x6890") == 0) {
+ *sv_type = 15; // GPS+Glonass+Beidou+Galileo
+ }
+}
+
+int hasAlmanac() {
+#if ANDROID_MNLD_PROP_SUPPORT
+ char ch;
+ char* ptr = NULL;
+ int i = -1;
+ int size = -1;
+ FILE *fp;
+ char fileName[] = "/mnt/vendor/nvcfg/almanac.dat";
+ char str[32] = {0};
+ char strTime[32] = {0};
+ char strSatNum[32] = {0};
+ int almanac_sat_num = 0;
+
+ if ((fp = fopen(fileName, "r")) == NULL) {
+ LOGD_ENG("open file(%s) fail", fileName);
+ return 0;
+ }
+
+ fseek(fp, 0L, SEEK_END);
+ size = ftell(fp);
+ if (size == 0) {
+ LOGD("file(%s) is empty", fileName);
+ fclose(fp);
+ return 0;
+ }
+ if (fseek(fp, i, SEEK_END) == -1){
+ LOGE("fseek fail,offset:%d", i);
+ fclose(fp);
+ return 0;
+ }
+
+ ch = (char)fgetc(fp);
+ while ((ch != '\n') && (size != 0)) {
+ i--;
+ if (fseek(fp, i, SEEK_END) == -1){
+ LOGE("fseek fail,offset:%d", i);
+ fclose(fp);
+ return 0;
+ }
+ size = ftell(fp);
+ ch = (char)fgetc(fp);
+ }
+
+ i = 0;
+ ch = (char)fgetc(fp);
+
+ while (!feof(fp) && (i < 31) && (i >= 0)) {
+ if ((ch >= '0' && ch <= '9') || (ch == ',')) {
+ str[i] = ch;
+ i++;
+ }
+ ch = (char)fgetc(fp);
+ }
+ fclose(fp);
+ LOGD("almanac.dat last line, str=%s\n", str);
+
+ ptr = strchr(str, ',');
+ if (ptr) {
+ MNLD_STRNCPY(strTime, ptr + 1, sizeof(strTime));
+ *ptr = '\0';
+ MNLD_STRNCPY(strSatNum, str, sizeof(strSatNum));
+ LOGD("strSatNum=%s, strTime=%s\n", strSatNum, strTime);
+ } else {
+ LOGD("don't find dot in almanac.dat last line, return\n");
+ return 0;
+ }
+ if (strlen(strSatNum) > 0) {
+ almanac_sat_num = atoi(strSatNum);
+ }
+ if (almanac_sat_num >= 25) {
+ property_set("vendor.gps.almanac", strTime);
+ return 1;
+ } else {
+ property_set("vendor.gps.almanac", "0");
+ }
+#endif
+ return 0;
+}
+
+void mnld_gps_update_name(void) {
+ char name[GNSS_NAME_LEN] = MNLD_VERSION;
+ char mnl_ver_default[] = "MNL_VER_20042202ALPS05_6.10_99_DEF";
+ char *mnl_ver = NULL;
+ if(strlen(mtk_gps_mnl_info.vertion)) {
+ //mnld_get_mnl_version(mnl_ver);
+ mnl_ver = mtk_gps_mnl_info.vertion;
+ } else {
+ mnl_ver = mnl_ver_default;
+ }
+ strncat(name, ",", GNSS_NAME_LEN-strlen(name)-1);
+ strncat(name, mnl_ver, GNSS_NAME_LEN-strlen(name)-1);
+ // GNSS HIDL v1.1 update driver/mnl version
+ if (-1==mnl2hal_update_gnss_name(name, strlen(name))) {
+ LOGE("mnl2hal_update_gnss_name err \n");
+ }
+}
+
+bool mnld_support_l5 = false;
+
+bool mtk_gps_support_l5_get() {
+ return mnld_support_l5;
+}
+
+void mtk_gps_support_l5_set(bool support_l5) {
+ LOGD("mtk_gps_support_l5_set:%d", support_l5);
+ mnld_support_l5 = support_l5;
+}
+
+static int mnld_gps_start_impl(void) {
+ int ret = 0;
+ unsigned int gps_user = GPS_USER_UNKNOWN;
+ //LOGD("mnld_gps_start_impl");
+ mnl_prop_configed_socketport = 0;
+ mnl_utl_load_property(&mnl_config);
+ mnld_set_default_debug_socket();
+
+ g_dbglog_file_size_in_config = mnl_config.dbglog_file_max_size;
+ g_dbglog_folder_size_in_config = mnl_config.dbglog_folder_max_size;
+
+ gps_user = mtk_gps_get_gps_user();
+ LOGD("gps_user=0x%x\n", gps_user);
+ //mtk_gps_ofl_set_user(gps_user);
+
+ mnld_gps_update_name();
+
+ /*initialize system resource (message queue, mutex) used by library*/
+ if ((in_meta_factory == 0) && (ret = mtk_gps_sys_init())) {
+ LOGD("mtk_gps_sys_init err = %d\n", errno);
+ } else {
+ LOGD_ENG("mtk_gps_sys_init() success\n");
+ }
+ // mnld_gps_start_nmea_monitor();
+ // start library gps run
+ if ((ret = linux_gps_init())) {
+ LOGD("linux_gps_init err = %d\n", errno);
+ mnld_gps_stop_impl();
+ return ret;
+ } else {
+ LOGD_ENG("linux_gps_init() success\n");
+ }
+
+ if ((ret = linux_setup_signal_handler())) {
+ LOGD("linux_setup_signal_handler err = %d\n", errno);
+ mnld_gps_stop_impl();
+ return ret;
+ } else {
+ LOGD_ENG("linux_setup_signal_handler() success\n");
+ }
+
+ get_gps_version();
+ return ret;
+}
+
+/*****************************************************************************/
+static int linux_gps_init(void) {
+ UINT32 clock_type;
+ int gnss_mode_flag = 0;
+ INT32 status = MTK_GPS_SUCCESS;
+ static MTK_GPS_INIT_CFG init_cfg;
+ static MTK_GPS_DRIVER_CFG driver_cfg;
+ MTK_GPS_BOOT_STATUS mnl_status = 0;
+ double latitude, longitude;
+ int accuracy = 100;
+ int ret_val = 0;
+
+ memset(&init_cfg, 0, sizeof(MTK_GPS_INIT_CFG));
+ memset(&driver_cfg, 0, sizeof(MTK_GPS_DRIVER_CFG));
+ MTK_AGPS_USER_PROFILE userprofile;
+ memset(&userprofile, 0, sizeof(MTK_AGPS_USER_PROFILE));
+ // ====== default config ======
+ init_cfg.if_type = MTK_IF_UART_NO_HW_FLOW_CTRL;
+ init_cfg.if_link_spd = 115200; // 115200bps
+
+ init_cfg.pps_mode = mnl_config.pps_mode;
+ init_cfg.pps_delay= mnl_config.pps_delay;
+ init_cfg.pps_polarity= mnl_config.pps_polarity;
+ init_cfg.pps_duty = mnl_config.pps_duty;
+
+ init_cfg.elev_mask = mnl_config.elev_mask;
+
+ UINT32 hw_ver = 0;
+ UINT32 fw_ver = 0;
+ UINT32 lna_pin = 0;
+
+ mnl_agps_location_time mnl_agps_location_sync_data;
+ memset(&mnl_agps_location_sync_data, 0, sizeof(mnl_agps_location_time));
+#ifdef MTK_GPS_CO_CLOCK_DATA_IN_MD
+ typedef struct gps_nvram_t {
+ unsigned int C0;
+ unsigned int C1;
+ unsigned int initU;
+ unsigned int lastU;
+ }GPS_NVRAM_COCLOCK_T;
+ GPS_NVRAM_COCLOCK_T gps_clock_calidata;
+ int fd = -1;
+ int read_size;
+ if ((strcmp(chip_id, "0x6735") == 0) || (strcmp(chip_id, "0x0321") == 0)
+ || (strcmp(chip_id, "0x0335") == 0) || (strcmp(chip_id, "0x0337") == 0)) {
+ LOGD("6735 calibration,chip_id:%s",chip_id);
+ fd = open(GPS_CALI_DATA_DENALI_PATH, O_RDONLY);
+ } else {
+ LOGD("Other calibration,chip_id:%s",chip_id);
+ fd = open(GPS_CALI_DATA_PATH, O_RDONLY);
+ }
+
+ if (fd == -1) {
+ LOGD("open error is %s\n", strerror(errno));
+ gps_clock_calidata.C0 = 0x0;
+ gps_clock_calidata.C1 = 0x0;
+ gps_clock_calidata.initU = 0x0;
+ gps_clock_calidata.lastU = 0x0;
+ } else {
+ if ((strcmp(chip_id, "0x6763") == 0) || (strcmp(chip_id, "0x6739") == 0)
+ || (strcmp(chip_id, "0x6771") == 0) || (strcmp(chip_id, "0x6765") == 0)
+ || (strcmp(chip_id, "0x3967") == 0) || (strcmp(chip_id, "0x6761") == 0)
+ || (strcmp(chip_id, "0x6779") == 0) || (strcmp(chip_id, "0x6768") == 0)
+ || (strcmp(chip_id, "0x6885") == 0) || (strcmp(chip_id, "0x6873") == 0)
+ || (strcmp(chip_id, "0x6880") == 0) || (strcmp(chip_id, "0x6890") == 0)) {
+ LOGD("lseek calibration file for 93MD");
+ if (lseek(fd, 0x40, SEEK_SET) < 0) {
+ LOGW("MD NVRam file lseek failed!!\n");
+ }
+ }
+ read_size = read(fd, &gps_clock_calidata, sizeof(GPS_NVRAM_COCLOCK_T));
+ if (read_size != sizeof(GPS_NVRAM_COCLOCK_T)) {
+ LOGD("read size is %d, structure size is %lu\n", read_size, sizeof(GPS_NVRAM_COCLOCK_T));
+ }
+ close(fd);
+ fd = -1;
+ }
+ init_cfg.C0 = gps_clock_calidata.C0;
+ init_cfg.C1 = gps_clock_calidata.C1;
+ init_cfg.initU = gps_clock_calidata.initU;
+ init_cfg.lastU = gps_clock_calidata.lastU;
+#endif
+#if MTK_GPS_NVRAM
+ if (gps_nvram_valid == 1) {
+ init_cfg.hw_Clock_Freq = stGPSReadback.gps_tcxo_hz; // 26MHz TCXO,
+ init_cfg.hw_Clock_Drift = stGPSReadback.gps_tcxo_ppb; // 0.5ppm TCXO
+ init_cfg.Int_LNA_Config = stGPSReadback.gps_lna_mode; // 0 -> Mixer in , 1 -> Internal LNA
+ init_cfg.u1ClockType = stGPSReadback.gps_tcxo_type; // clk_type;
+ #ifdef MTK_GPS_CO_CLOCK_DATA_IN_MD
+ if (strcmp(chip_id, "0x6580") == 0 || strcmp(chip_id, "0x6570") == 0) {
+ LOGD("calibration read from AP NVRAM\n");
+ init_cfg.C0 = stGPSReadback.C0;
+ init_cfg.C1 = stGPSReadback.C1;
+ init_cfg.initU = stGPSReadback.initU;
+ init_cfg.lastU = stGPSReadback.lastU;
+ }
+ #else
+ init_cfg.C0 = stGPSReadback.C0;
+ init_cfg.C1 = stGPSReadback.C1;
+ init_cfg.initU = stGPSReadback.initU;
+ init_cfg.lastU = stGPSReadback.lastU;
+ #endif
+ } else {
+#endif
+ init_cfg.hw_Clock_Freq = 26000000; // 26MHz TCXO
+ init_cfg.hw_Clock_Drift = 2000; // 0.5ppm TCXO
+ init_cfg.Int_LNA_Config = 0; // 0 -> Mixer in , 1 -> Internal LNA
+ init_cfg.u1ClockType = 0xFF; // clk_type;
+#if MTK_GPS_NVRAM
+ }
+#endif
+ if (init_cfg.hw_Clock_Drift == 0) {
+ LOGD_ENG("customer didn't set clock drift value, use default value\n");
+ init_cfg.hw_Clock_Drift = 2000;
+ }
+
+ /*setting 1Hz/5Hz */
+#if 0
+ if (g_is_1Hz) {
+ init_cfg.fix_interval = 1000; // 1Hz update rate
+ } else {
+ init_cfg.fix_interval = 200; // 5Hz update rate
+ }
+#endif
+
+ if(mnl_config.fix_interval == 200 || mnl_config.fix_interval == 500 ||
+ mnl_config.fix_interval == 1000 || (mnl_config.fix_interval >= 100 &&
+ mnl_config.GNSSOPMode == MTK_CONFIG_GPS_ONLY)) {
+ init_cfg.fix_interval = mnl_config.fix_interval;
+ }else{
+ init_cfg.fix_interval = 1000;
+ }
+ LOGD("init_cfg.fix_interval = %d \n", init_cfg.fix_interval);
+
+
+ init_cfg.datum = MTK_DATUM_WGS84; // datum
+ init_cfg.dgps_mode = MTK_DGPS_MODE_SBAS; // enable SBAS
+
+MTK_GPS_MNL_CONFIG_XML_PARAM mnl_config_xml;
+#ifdef MTK_GPS_DUAL_FREQ_SUPPORT /*Defined in Android.mk*/
+ char Feature[FEATURE_NAMING_SIZE] = "L1Only";
+ memset(&mnl_config_xml,0,sizeof(mnl_config_xml));
+ MNLD_STRNCPY(mnl_config_xml.xml_feature_name, Feature, sizeof(mnl_config_xml.xml_feature_name));
+ if (mtk_gps_get_MNL_Config_XML_param(MNL_READ_WRITE_PATH, &mnl_config_xml)) {
+ if ((mnl_config_xml.xml_feature_config == 1) && (mnl_config_xml.xml_feature_setting[0][0] == 1)) {
+ MNLD_STRNCPY(driver_cfg.dsp2_port_name,"none",sizeof(driver_cfg.dsp2_port_name));
+ } else {
+ MNLD_STRNCPY(driver_cfg.dsp2_port_name, mnl_config.dev_dsp2 ,sizeof(driver_cfg.dsp2_port_name));
+ }
+ } else if (mtk_gps_get_MNL_Config_XML_param(MNL_CFG_XML_DEFAULT_PATH, &mnl_config_xml)) {
+ if ((mnl_config_xml.xml_feature_config == 1) && (mnl_config_xml.xml_feature_setting[0][0] == 1)) {
+ MNLD_STRNCPY(driver_cfg.dsp2_port_name,"none",sizeof(driver_cfg.dsp2_port_name));
+ } else {
+ MNLD_STRNCPY(driver_cfg.dsp2_port_name, mnl_config.dev_dsp2 ,sizeof(driver_cfg.dsp2_port_name));
+ }
+ } else {
+ MNLD_STRNCPY(driver_cfg.dsp2_port_name, mnl_config.dev_dsp2 ,sizeof(driver_cfg.dsp2_port_name));
+ }
+ LOGD("dsp port2: %s", driver_cfg.dsp2_port_name);
+#endif
+ char Feature2[FEATURE_NAMING_SIZE] = "CLKEXT_NIOnly";
+ memset(&mnl_config_xml,0,sizeof(mnl_config_xml));
+ MNLD_STRNCPY(mnl_config_xml.xml_feature_name, Feature2, sizeof(mnl_config_xml.xml_feature_name));
+ if (mtk_gps_get_MNL_Config_XML_param(MNL_READ_WRITE_PATH, &mnl_config_xml)) {
+ if ((mnl_config_xml.xml_feature_config == 1) && (mnl_config_xml.xml_feature_setting[0][0] == 1)) {
+ set_clk_ext_ni_only(1);
+ } else {
+ set_clk_ext_ni_only(0);
+ }
+ } else if (mtk_gps_get_MNL_Config_XML_param(MNL_CFG_XML_DEFAULT_PATH, &mnl_config_xml)) {
+ if ((mnl_config_xml.xml_feature_config == 1) && (mnl_config_xml.xml_feature_setting[0][0] == 1)) {
+ set_clk_ext_ni_only(1);
+ } else {
+ set_clk_ext_ni_only(0);
+ }
+ } else {
+ set_clk_ext_ni_only(0);
+ }
+ LOGD("CLKEXT_NIOnly: %d", is_clk_ext_ni_only());
+
+
+#if defined(GPS_SUSPEND_SUPPORT)
+ gps_controller_session_id_update();
+ driver_cfg.hw_suspend_enabled = mnld_gps_suspend_is_enabled() || mnld_gps_suspend_ext_is_enabled();
+ driver_cfg.hw_resume_required = 0;
+ if (driver_cfg.hw_suspend_enabled) {
+ if (gps_controller_suspend_done_flag) {
+ if (pthread_rst_listener_rst_detected_flag) {
+ int try_close_okay;
+ try_close_okay = mnld_gps_try_suspend_to_close(); // must be true
+ LOGE("rst happen on starting from suspend, try close, ok = %d", try_close_okay);
+ pthread_rst_listener_rst_detected_flag = 0;
+ //goto _try_open_dsp_fd; - re-open
+ } else {
+ driver_cfg.hw_resume_required = 1;
+ // libmnl may drop the 1st DBTT if it arrives too early
+ // move bellow steps to callback: mtk_gps_sys_do_hw_suspend_resume,
+ // and then libmnl will not drop DBTT at that time.
+ // 1. mnld_do_gps_suspend_resume(0);
+ // 2. gps_controller_suspend_done_flag = 0;
+ goto _after_open_dsp_fd;
+ }
+ }
+ }
+
+//_try_open_dsp_fd:
+#endif
+
+#ifndef __LIBMNL_SIMULATOR__
+ int dsp_open_retry = 0;
+ while (1) {
+ dsp_fd = open(mnl_config.dev_dsp, O_RDWR);
+ if (dsp_fd == -1) {
+ LOGE("open_port: Unable to open - %s, [%s]\n", mnl_config.dev_dsp, strerror(errno));
+ if (dsp_open_retry <= 20) {
+ usleep(1000*1000);
+ dsp_open_retry++;
+ LOGD("open_port: sleep and contine to do %d retry", dsp_open_retry);
+ continue;
+ } else {
+ LOGE("open_port: %d retry still fail, return err", dsp_open_retry);
+ }
+ return MTK_GPS_ERROR;
+ } else {
+ LOGD("open dsp successfully(fd:%d)\n", dsp_fd);
+ }
+ break;
+ }
+#ifdef MTK_GPS_DUAL_FREQ_SUPPORT /*Defined in Android.mk*/
+ if(strlen(driver_cfg.dsp2_port_name) > 4) { //Set dsp2 name as "none" to disable DSP2
+ dsp_open_retry = 0;
+ while (1) {
+ dsp2_fd = open(driver_cfg.dsp2_port_name, O_RDWR);
+ if (dsp2_fd == -1) {
+ LOGD("open_port2: Unable to open - %s, [%s]\n", driver_cfg.dsp2_port_name, strerror(errno));
+ if (dsp_open_retry <= 20) {
+ usleep(1000*1000);
+ dsp_open_retry++;
+ LOGD("open_port2: sleep and contine to do %d retry", dsp_open_retry);
+ continue;
+ } else {
+ LOGE("open_port2: %d retry still fail, return err", dsp_open_retry);
+ }
+ //return MTK_GPS_ERROR;
+ } else {
+ LOGD("open dsp2 successfully(fd: %d)\n", dsp2_fd);
+ }
+ break;
+ }
+ } else {
+ dsp2_fd = -1;
+ mtk_gps_support_l5_set(false);
+ if (property_set(GPS_L5_SUPPORT_P, "0") != 0) {
+ LOGE("set GPS_L5_SUPPORT_P %s\n", strerror(errno));
+ }
+ }
+#endif
+#endif //__LIBMNL_SIMULATOR__
+#if defined(GPS_SUSPEND_SUPPORT)
+_after_open_dsp_fd:
+#endif
+
+#if ANDROID_MNLD_PROP_SUPPORT
+{
+ char result[PROPERTY_VALUE_MAX] = {0};
+ property_get(HIDE_LOG_PROP, result, NULL);
+ if (result[0] == '1') {
+ mtk_gps_log_hide = 1;
+ } else if (result[0] == '2') {
+ mtk_gps_log_hide = 2;
+ gps_dbg_log_state_set_encrypt_enable();
+ } else {
+ mtk_gps_log_hide = 0;
+ }
+}
+#endif
+ mtk_gps_log_set_hide_opt_by_mnl_config();
+
+ if (chip_id[0] == 0) {
+ chip_detector();
+ }
+
+ if (strcmp(chip_id, "0x6592") == 0 || strcmp(chip_id, "0x6571") == 0
+ || strcmp(chip_id, "0x6580") == 0 || strcmp(chip_id, "0x0321") == 0
+ || strcmp(chip_id, "0x0335") == 0 || strcmp(chip_id, "0x0337") == 0
+ || strcmp(chip_id, "0x6735") == 0 || strcmp(chip_id, "0x8163") == 0
+ || strcmp(chip_id, "0x8127") == 0 || strcmp(chip_id, "0x6755") == 0
+ || strcmp(chip_id, "0x6797") == 0 || strcmp(chip_id, "0x6757") == 0
+ || strcmp(chip_id, "0x6759") == 0 || strcmp(chip_id, "0x6763") == 0
+ || strcmp(chip_id, "0x6758") == 0 || strcmp(chip_id, "0x6570") == 0
+ || strcmp(chip_id, "0x6739") == 0 || strcmp(chip_id, "0x6771") == 0
+ || strcmp(chip_id, "0x6775") == 0 || strcmp(chip_id, "0x6765") == 0
+ || strcmp(chip_id, "0x3967") == 0 || strcmp(chip_id, "0x6761") == 0
+ || strcmp(chip_id, "0x6779") == 0 || strcmp(chip_id, "0x6768") == 0
+ || strcmp(chip_id, "0x6885") == 0 || strcmp(chip_id, "0x6873") == 0
+ || strcmp(chip_id, "0x6880") == 0 || strcmp(chip_id, "0x6890") == 0) {
+ clock_type = (UINT32)ioctl(dsp_fd, 11, NULL);
+ clock_type = clock_type & 0x00ff;
+ switch (clock_type) {
+ case 0x00:
+ LOGD("TCXO, buffer 2\n");
+ init_cfg.u1ClockType = 0xFF;
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (property_set(GPS_CLOCK_TYPE_P, "20") != 0)
+ LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+ #endif
+ break;
+ case 0x10:
+ LOGD("TCXO, buffer 1\n");
+ init_cfg.u1ClockType = 0xFF;
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (property_set(GPS_CLOCK_TYPE_P, "10") != 0)
+ LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+ #endif
+ break;
+ case 0x20:
+ LOGD("TCXO, buffer 2\n");
+ init_cfg.u1ClockType = 0xFF;
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (property_set(GPS_CLOCK_TYPE_P, "20") != 0)
+ LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+ #endif
+ break;
+ case 0x30:
+ LOGD("TCXO, buffer 3\n");
+ init_cfg.u1ClockType = 0xFF;
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (property_set(GPS_CLOCK_TYPE_P, "30") != 0)
+ LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+ #endif
+ break;
+ case 0x40:
+ LOGD("TCXO, buffer 4\n");
+ init_cfg.u1ClockType = 0xFF;
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (property_set(GPS_CLOCK_TYPE_P, "40") != 0)
+ LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+ #endif
+ break;
+ case 0x01:
+ LOGD("GPS coclock, buffer 2, coTMS\n");
+ init_cfg.u1ClockType = 0xFE;
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (property_set(GPS_CLOCK_TYPE_P, "21") != 0)
+ LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+ #endif
+ break;
+ case 0x02:
+ case 0x03:
+ LOGD("TCXO, buffer 2, coVCTCXO\n");
+ init_cfg.u1ClockType = 0xFF;
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (property_set(GPS_CLOCK_TYPE_P, "20") != 0)
+ LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+ #endif
+ break;
+ case 0x11:
+ LOGD("GPS coclock, buffer 1\n");
+ init_cfg.u1ClockType = 0xFE;
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (property_set(GPS_CLOCK_TYPE_P, "11") != 0)
+ LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+ #endif
+ break;
+ case 0x21:
+ LOGD("GPS coclock, buffer 2\n");
+ init_cfg.u1ClockType = 0xFE;
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (property_set(GPS_CLOCK_TYPE_P, "21") != 0)
+ LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+ #endif
+ break;
+ case 0x31:
+ LOGD("GPS coclock, buffer 3\n");
+ init_cfg.u1ClockType = 0xFE;
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (property_set(GPS_CLOCK_TYPE_P, "31") != 0)
+ LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+ #endif
+ break;
+ case 0x41:
+ LOGD("GPS coclock, buffer 4\n");
+ init_cfg.u1ClockType = 0xFE;
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (property_set(GPS_CLOCK_TYPE_P, "41") != 0)
+ LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+ #endif
+ break;
+ default:
+ LOGW("unknown clock type(0x%x), set as GPS coclock, buffer 2, coTMS\n", clock_type);
+ init_cfg.u1ClockType = 0xFE;
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (property_set(GPS_CLOCK_TYPE_P, "21") != 0)
+ LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+ #endif
+ break;
+ }
+ } else {
+ if (strcmp(chip_id, "0x6572") == 0 || strcmp(chip_id, "0x6582") == 0
+ || strcmp(chip_id, "0x6630") == 0 || strcmp(chip_id, "0x6752") == 0
+ || strcmp(chip_id, "0x6632") == 0) {
+ if (0xFF == init_cfg.u1ClockType) {
+ LOGD("TCXO\n");
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (property_set(GPS_CLOCK_TYPE_P, "90") != 0) {
+ LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+ }
+ #endif
+ } else if (0xFE == init_cfg.u1ClockType) {
+ LOGD("GPS coclock\n");
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (property_set(GPS_CLOCK_TYPE_P, "91") != 0) {
+ LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+ }
+ #endif
+ } else {
+ LOGD("GPS unknown clock\n");
+ }
+ }
+ /*Add clock type to display on YGPS by mtk06325 2013-12-09 end */
+ }
+
+ if (ioctl(dsp_fd, 10, NULL) == 1) {
+ LOGD("clear RTC\n");
+ delete_aiding_data = GPS_DELETE_TIME;
+ }
+
+ if (strcmp(chip_id, "0x6628") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6628;
+ init_cfg.reservedx = MT6628_E1;
+ } else if (strcmp(chip_id, "0x6630") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6630;
+ if (ioctl(dsp_fd, COMBO_IOC_GPS_IC_HW_VERSION, &hw_ver) < 0) {
+ LOGD("get COMBO_IOC_GPS_IC_HW_VERSION failed\n");
+ return MTK_GPS_ERROR;
+ }
+
+ if (ioctl(dsp_fd, COMBO_IOC_GPS_IC_FW_VERSION, &fw_ver) < 0) {
+ LOGD("get COMBO_IOC_GPS_IC_FW_VERSION failed\n");
+ return MTK_GPS_ERROR;
+ }
+
+ if ((hw_ver == 0x8A00) && (fw_ver == 0x8A00)) {
+ LOGD("MT6630_E1\n");
+ init_cfg.reservedx = MT6630_E1;
+ } else if ((hw_ver == 0x8A10) && (fw_ver == 0x8A10)) {
+ LOGD("MT6630_E2\n");
+ init_cfg.reservedx = MT6630_E2;
+ } else if ((hw_ver >= 0x8A11) && (fw_ver >= 0x8A11)) {
+ LOGD("MT6630 chip dection done,hw_ver = %d and fw_ver = %d\n", hw_ver, fw_ver);
+ init_cfg.reservedx = MT6630_E2; /*mnl match E1 or not E1,so we send MT6630_E2 to mnl */
+ } else {
+ LOGD("hw_ver = %d and fw_ver = %d\n", hw_ver, fw_ver);
+ init_cfg.reservedx = MT6630_E2; /*default value*/
+ }
+ } else if (strcmp(chip_id, "0x6572") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6572;
+ init_cfg.reservedx = MT6572_E1;
+ } else if (strcmp(chip_id, "0x6570") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6570;
+ init_cfg.reservedx = MT6570_E1;
+ } else if (strcmp(chip_id, "0x6571") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6571;
+ init_cfg.reservedx = MT6571_E1;
+ } else if (strcmp(chip_id, "0x8127") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6571;
+ init_cfg.reservedx = MT6571_E1;
+ } else if (strcmp(chip_id, "0x6582") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6582;
+ init_cfg.reservedx = MT6582_E1;
+ } else if (strcmp(chip_id, "0x6592") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6592;
+ init_cfg.reservedx = MT6592_E1;
+ } else if (strcmp(chip_id, "0x3332") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT3332;
+ init_cfg.reservedx = MT3332_E2;
+ } else if (strcmp(chip_id, "0x6752") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6752;
+ init_cfg.reservedx = MT6752_E1;
+ } else if (strcmp(chip_id, "0x8163") == 0) {
+ mnl_config.GNSSOPMode = 3; // gps only
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6735M;
+ init_cfg.reservedx = MT6735M_E1;
+ } else if (strcmp(chip_id, "0x6580") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6580;
+ init_cfg.reservedx = MT6580_E1;
+ } else if (strcmp(chip_id, "0x0321") == 0) { // Denali1
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6735;
+ init_cfg.reservedx = MT6735_E1;
+
+ gnss_mode_flag = ioctl(dsp_fd, 9, NULL); // 32'h10206198 value is 01
+ LOGD("gnss_mode_flag=%d \n", gnss_mode_flag);
+
+ if (((gnss_mode_flag & 0x01000000) != 0) && ((gnss_mode_flag & 0x02000000) == 0)) {
+ mnl_config.GNSSOPMode = 3; // gps only
+ }
+ } else if (strcmp(chip_id, "0x0335") == 0) { // Denali2
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6735M;
+ init_cfg.reservedx = MT6735M_E1;
+ } else if (strcmp(chip_id, "0x0337") == 0) { // Denali3
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6753;
+ init_cfg.reservedx = MT6753_E1;
+ } else if (strcmp(chip_id, "0x6739") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6739;
+ init_cfg.reservedx = MT6739_E1;
+ } else if (strcmp(chip_id, "0x6755") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6755;
+ init_cfg.reservedx = MT6755_E1;
+
+ gnss_mode_flag = ioctl(dsp_fd, 9, NULL); // 32'h10206048 value is 01
+ LOGD("gnss_mode_flag=%d \n", gnss_mode_flag);
+
+ if (((gnss_mode_flag & 0x01000000) != 0) && ((gnss_mode_flag & 0x02000000) == 0)) {
+ mnl_config.GNSSOPMode = 3; // gps only
+ }
+ } else if (strcmp(chip_id, "0x6763") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6763;
+ init_cfg.reservedx = MT6763_E1;
+ } else if (strcmp(chip_id, "0x6797") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6797;
+ init_cfg.reservedx = MT6797_E1;
+ } else if (strcmp(chip_id, "0x6757") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6757;
+ init_cfg.reservedx = MT6757_E1;
+
+ gnss_mode_flag = ioctl(dsp_fd, 9, NULL); // 32'h10206048 value is 01
+ LOGD("gnss_mode_flag=%d \n", gnss_mode_flag);
+
+ if (((gnss_mode_flag & 0x01000000) != 0) && ((gnss_mode_flag & 0x02000000) == 0)) {
+ mnl_config.GNSSOPMode = 3; // gps only
+ }
+ } else if (strcmp(chip_id, "0x6758") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6758;
+ init_cfg.reservedx = MT6758_E1;
+ } else if (strcmp(chip_id, "0x6759") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6759;
+ init_cfg.reservedx = MT6759_E1;
+ } else if (strcmp(chip_id, "0x6771") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6771;
+ init_cfg.reservedx = MT6771_E1;
+ } else if (strcmp(chip_id, "0x6775") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6775;
+ init_cfg.reservedx = MT6775_E1;
+ } else if (strcmp(chip_id, "0x6765") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6765;
+ init_cfg.reservedx = MT6765_E1;
+ } else if (strcmp(chip_id, "0x3967") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT3967;
+ init_cfg.reservedx = MT3967_E1;
+ } else if (strcmp(chip_id, "0x6761") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6761;
+ init_cfg.reservedx = MT6761_E1;
+ } else if (strcmp(chip_id, "0x6779") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6779;
+ init_cfg.reservedx = MT6779_E1;
+ } else if (strcmp(chip_id, "0x6768") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6768;
+ init_cfg.reservedx = MT6768_E1;
+ } else if (strcmp(chip_id, "0x6873") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6873;
+ init_cfg.reservedx = MT6873_E1;
+ } else if (strcmp(chip_id, "0x6885") == 0) {
+ #ifdef MTK_GPS_DUAL_FREQ_SUPPORT
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6885;
+ init_cfg.reservedx = MT6885_E1;
+ init_cfg.reservedy_2 = (void *)MTK_GPS_CHIP_KEY_MT6885;
+ init_cfg.reservedx_2 = MT6885_E1;
+ #else
+ LOGE("!!![ERROR]chip id fail(%s)!!!", chip_id);
+ return MTK_GPS_ERROR;
+ #endif
+ } else if (strcmp(chip_id, "0x6880") == 0) {
+ #ifdef MTK_GPS_DUAL_FREQ_SUPPORT
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6880;
+ init_cfg.reservedx = MT6880_E1;
+ init_cfg.reservedy_2 = (void *)MTK_GPS_CHIP_KEY_MT6880;
+ init_cfg.reservedx_2 = MT6880_E1;
+ #else
+ LOGE("!!![ERROR]chip id fail(%s)!!!", chip_id);
+ return MTK_GPS_ERROR;
+ #endif
+ } else if (strcmp(chip_id, "0x6890") == 0) {
+ #ifdef MTK_GPS_DUAL_FREQ_SUPPORT
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6890;
+ init_cfg.reservedx = MT6890_E1;
+ init_cfg.reservedy_2 = (void *)MTK_GPS_CHIP_KEY_MT6890;
+ init_cfg.reservedx_2 = MT6890_E1;
+ #else
+ LOGE("!!![ERROR]chip id fail(%s)!!!", chip_id);
+ return MTK_GPS_ERROR;
+ #endif
+ } else if (strcmp(chip_id, "0x6632") == 0) {
+ init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6632;
+ if (ioctl(dsp_fd, COMBO_IOC_GPS_IC_HW_VERSION, &hw_ver) < 0) {
+ LOGD("get COMBO_IOC_GPS_IC_HW_VERSION failed\n");
+ return MTK_GPS_ERROR;
+ }
+ if (ioctl(dsp_fd, COMBO_IOC_GPS_IC_FW_VERSION, &fw_ver) < 0) {
+ LOGD("get COMBO_IOC_GPS_IC_FW_VERSION failed\n");
+ return MTK_GPS_ERROR;
+ }
+
+ if ((hw_ver == 0x8A00) && (fw_ver == 0x8A00)) {
+ LOGD("MT6632_E1\n");
+ init_cfg.reservedx = MT6632_E1;
+ } else if ((hw_ver >= 0x8A10) && (fw_ver >= 0x8A10)) {
+ LOGD("MT6632 chip dection done, hw_ver = %d and fw_ver = %d\n", hw_ver, fw_ver);
+ init_cfg.reservedx = MT6632_E3;
+ } else {
+ LOGD("hw_ver = %d and fw_ver = %d\n", hw_ver, fw_ver);
+ init_cfg.reservedx = MT6632_E3; /*default value*/
+ mnl_config.GNSSOPMode = 6;
+ }
+ } else {
+ LOGE("chip is unknown, chip id is %s\n", chip_id);
+ }
+
+ LOGD("Get chip version type (%p) \n", init_cfg.reservedy);
+ LOGD_ENG("Get chip version value (%d) \n", init_cfg.reservedx);
+
+ if (ioctl(dsp_fd, COMBO_IOC_GET_GPS_LNA_PIN, &lna_pin) < 0) {
+ LOGE("get COMBO_IOC_GET_GPS_LNA_PIN failed\n");
+ }
+ init_cfg.eLNA_pin_num = lna_pin;
+
+ if (gps_epo_type == 0) {
+ if (((mnl_config.GNSSOPMode & 0x000f) != 0) && ((mnl_config.GNSSOPMode & 0x000f) != 2)) {
+ //gps_epo_type = 1;
+ }
+ }
+
+ if (mnl_config.ACCURACY_SNR == 1) {
+ init_cfg.reservedx |=(UINT32)0x80000000;
+ } else if (mnl_config.ACCURACY_SNR == 2) {
+ init_cfg.reservedx |=(UINT32)0x40000000;
+ } else if (mnl_config.ACCURACY_SNR == 3) {
+ init_cfg.reservedx |=(UINT32)0xC0000000;
+ }
+ init_cfg.mtk_gps_version_mode = MTK_GPS_AOSP_MODE;
+ //LOGD("mtk_gps_version_mode = %d\n", init_cfg.mtk_gps_version_mode);
+ /*
+ mnl_config.GNSSOPMode |= 0x0300; // default AGps On, AGlonass On, ABeidou Off
+ if ((sv_type_agps_set | 0xef) == 0xef) { // locationEM2 AGlonass button off
+ mnl_config.GNSSOPMode &= ~(0x0200);
+ }
+ if ((sv_type_agps_set & 0x40) == 0x40) { // locationEM2 ABeidou button on
+ mnl_config.GNSSOPMode |= 0x0400;
+ } else {
+ mnl_config.GNSSOPMode &= ~(0x0400);
+ }
+ */
+ init_cfg.GNSSOPMode = mnl_config.GNSSOPMode;
+ //LOGD("GNSSOPMode: 0x%x\n", init_cfg.GNSSOPMode);
+ if (in_meta_factory == 1) {
+ init_cfg.GLP_Enabled = 0;
+ } else {
+ init_cfg.GLP_Enabled = 1;
+ }
+ LOGD_ENG("GLP_Enabled: %d\n", init_cfg.GLP_Enabled);
+
+ MNLD_STRNCPY(driver_cfg.nv_file_name, NV_FILE,sizeof(driver_cfg.nv_file_name));
+ MNLD_STRNCPY(driver_cfg.ofl_nv_file_name, OFL_NV_FILE ,sizeof(driver_cfg.ofl_nv_file_name));
+ // strcpy(driver_cfg.dbg_file_name, LOG_FILE);
+ MNLD_STRNCPY(driver_cfg.nmeain_port_name, mnl_config.dev_dbg ,sizeof(driver_cfg.nmeain_port_name));
+ MNLD_STRNCPY(driver_cfg.nmea_port_name, mnl_config.dev_gps ,sizeof(driver_cfg.nmea_port_name));
+ MNLD_STRNCPY(driver_cfg.dsp_port_name, mnl_config.dev_dsp ,sizeof(driver_cfg.dsp_port_name));
+ MNLD_STRNCPY(driver_cfg.mnl_cfg_xml_default_path_name, mnl_config.mnl_cfg_xml_default_path ,sizeof(driver_cfg.mnl_cfg_xml_default_path_name));
+ MNLD_STRNCPY(driver_cfg.mnl_read_write_path_name, mnl_config.mnl_read_write_path ,sizeof(driver_cfg.mnl_read_write_path_name));
+ MNLD_STRNCPY((char *)driver_cfg.bee_path_name, mnl_config.bee_path ,sizeof(driver_cfg.bee_path_name));
+ driver_cfg.reserved = mnl_config.BEE_enabled;
+ init_cfg.sv_type_agps_set = sv_type_agps_set;
+ gps_dbg_log_state_set_bitmask(mnl_config.dbg2file);
+ // driver_cfg.DebugType: 0x01-> libmnl write file;0x11 -> libmnl write file.
+ driver_cfg.DebugType = gps_debuglog_state;
+ MNLD_STRNCPY(gps_debuglog_file_name, mnl_config.debug_file_name, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ if(gps_dbg_log_output2file() && (mnld_debug_file_check_init(mnl_config.debug_file_name) == MTK_GPS_ERROR)) {
+ gps_dbg_log_output2file_clean();
+ LOGD("mnld write GPS debug log to file(%s), but access fail, cancle it!", mnl_config.debug_file_name);
+ }
+ MNLD_STRNCPY(driver_cfg.dbg_file_name, gps_debuglog_file_name, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+
+ driver_cfg.u1AgpsMachine = mnl_config.u1AgpsMachine;
+ MNLD_STRNCPY((char *)driver_cfg.epo_file_name, mnl_config.epo_file ,sizeof(driver_cfg.epo_file_name));
+ MNLD_STRNCPY((char *)driver_cfg.epo_update_file_name, mnl_config.epo_update_file ,sizeof(driver_cfg.epo_update_file_name));
+ MNLD_STRNCPY((char *)driver_cfg.qepo_file_name, mnl_config.qepo_file ,sizeof(driver_cfg.qepo_file_name));
+ MNLD_STRNCPY((char *)driver_cfg.qepo_update_file_name, mnl_config.qepo_update_file ,sizeof(driver_cfg.qepo_update_file_name));
+ MNLD_STRNCPY((char *)driver_cfg.qepo_bd_file_name, QEPO_BD_FILE,sizeof(driver_cfg.qepo_bd_file_name));
+ MNLD_STRNCPY((char *)driver_cfg.qepo_bd_update_file_name, QEPO_BD_UPDATE_FILE ,sizeof(driver_cfg.qepo_bd_update_file_name));
+ MNLD_STRNCPY((char *)driver_cfg.mtknav_file_name, MTKNAV_DAT_FILE ,sizeof(driver_cfg.mtknav_file_name));
+ MNLD_STRNCPY((char *)driver_cfg.mtknav_update_file_name, MTKNAV_DAT_FILE_HAL ,sizeof(driver_cfg.mtknav_update_file_name));
+ MNLD_STRNCPY((char *)driver_cfg.qepo_ga_file_name, QEPO_GA_FILE ,sizeof(driver_cfg.qepo_ga_file_name));
+ MNLD_STRNCPY((char *)driver_cfg.qepo_ga_update_file_name, QEPO_GA_UPDATE_FILE ,sizeof(driver_cfg.qepo_ga_update_file_name));
+
+ driver_cfg.log_file_max_size = MAX_DBG_LOG_FILE_SIZE;
+ driver_cfg.log_folder_max_size = MAX_DBG_LOG_DIR_SIZE;
+ MNLD_STRNCPY(driver_cfg.mnld_ver, MNLD_VER ,sizeof(driver_cfg.mnld_ver));
+ LOGD("[mnld version] = %s\n", MNLD_VER);
+ driver_cfg.EMI_Start_Address = adc_emi_address;
+ driver_cfg.EMI_End_Address = adc_emi_address + ADC_CAPTURE_MAX_SIZE;
+ LOGD("linux_gps_init:ADC emi address:0x%08x\n",adc_emi_address);
+
+ driver_cfg.u1AgpsMachine = mnl_config.u1AgpsMachine;
+ if (driver_cfg.u1AgpsMachine == 1) {
+ LOGD("use CRTU to test\n");
+ } else {
+ LOGD_ENG("use Spirent to test\n");
+ }
+
+#ifdef MTK_GPS_DRIVER_CFG_EXT_SUPPORT
+ driver_cfg.ext_offset = MTK_GPS_DRIVER_CFG_EXT_OFFSET;
+ driver_cfg.ext_size = MTK_GPS_DRIVER_CFG_EXT_SIZE;
+ driver_cfg.ext_magic = MTK_GPS_DRIVER_CFG_EXT_MAGIC;
+ driver_cfg.ext_ver = MTK_GPS_DRIVER_CFG_EXT_VER;
+ LOGD("driver_cfg.ext offset=%u, size=%u, magic=0x%04x, ver=0x%04x",
+ driver_cfg.ext_offset, driver_cfg.ext_size,
+ driver_cfg.ext_magic, driver_cfg.ext_ver);
+#else
+ LOGD("driver_cfg.ext not support");
+#endif
+
+ if(mnld_is_gps_meas_enabled() && assist_data_bit_map != FLAG_HOT_START) {
+ driver_cfg.raw_meas_enable = 1;
+ } else {
+ driver_cfg.raw_meas_enable = 0;
+ }
+
+ LOGD_ENG("start gps raw meas enable:%d", driver_cfg.raw_meas_enable);
+
+ memcpy(&driver_cfg.blacklist, &svBlacklist, sizeof(driver_cfg.blacklist));
+
+ status = mtk_gps_delete_nv_data(assist_data_bit_map);
+ if (!(assist_data_bit_map&MTK_GPS_DELETE_EPHEMERIS)&&!(assist_data_bit_map&MTK_GPS_DELETE_POSITION)
+ &&!(assist_data_bit_map&MTK_GPS_DELETE_TIME)&&g_is_1Hz&&((mtk_gps_get_gps_user()&GPS_USER_APP)==GPS_USER_APP)) {
+ init_cfg.fast_HTTFF_enabled = mnl_config.fast_HTTFF;
+ } else {
+ init_cfg.fast_HTTFF_enabled = 0;
+ }
+ //LOGD("assist_data_bit_map:%d, g_is_1Hz:%d,mtk_gps_get_gps_user():%d\n", assist_data_bit_map, g_is_1Hz, mtk_gps_get_gps_user());
+ LOGD("u4Bitmap= %d, init_cfg.C0 = %d,init_cfg.C1 = %d,init_cfg.initU = %d,init_cfg.lastU = %d,GNSSOPMode: 0x%x,eLNA_pin:%d, raw meas enable:%d, fast_HTTFF_enabled:%d\n",
+ status, init_cfg.C0, init_cfg.C1, init_cfg.initU, init_cfg.lastU, init_cfg.GNSSOPMode, init_cfg.eLNA_pin_num, driver_cfg.raw_meas_enable, init_cfg.fast_HTTFF_enabled);
+
+#if defined(GPS_SUSPEND_SUPPORT)
+ LOGW("session_id = %lu, suspend_en = %d, need_resume = %d",
+ gps_controller_session_id_get(), driver_cfg.hw_suspend_enabled, driver_cfg.hw_resume_required);
+#endif
+
+ driver_cfg.dsp_fd = dsp_fd;
+#ifdef MTK_GPS_DUAL_FREQ_SUPPORT /*Defined in Android.mk*/
+ driver_cfg.dsp2_fd = dsp2_fd;
+#endif
+ /* Multi log thread may cause mutex destory twice, it will trigger abort on Android P
+ * do not creat log thread when MNLD prepare to exit */
+ if (mnld_exiting == false) {
+ gps_dbg_log_thread_init();
+ }
+
+ if (PDN_test_enable == 1 || PDN_test_enable == 0) {
+ init_cfg.Int_IMAX_Config = PDN_test_enable;
+ LOGD_ENG("init_cfg.Int_IMAX_Config = %d\n", init_cfg.Int_IMAX_Config);
+ } else {
+ LOGD("PDN_test_enable has wrong number\n");
+ init_cfg.Int_IMAX_Config = 0;
+ }
+ driver_cfg.RfPathLossDb_Ap = mnl_config.RfPathLossDb_Ap;
+
+ driver_cfg.socket_port = mnl_config.socket_port;
+
+ LOGD("pps_config mode = %d, delay = %d, polarity = %d, duty = %d elev_mask = %d\n",
+ init_cfg.pps_mode, init_cfg.pps_delay, init_cfg.pps_polarity, init_cfg.pps_duty, init_cfg.elev_mask);
+
+ mnl_status = mtk_gps_mnl_run((const MTK_GPS_INIT_CFG*)&init_cfg , (const MTK_GPS_DRIVER_CFG*)&driver_cfg);
+ LOGD("Status (%d) \n", mnl_status);
+ g_mnl_init = true;
+ if (mnl_status != MNL_INIT_SUCCESS) {
+ status = MTK_GPS_ERROR;
+ return status;
+ }
+#ifdef MTK_MPE_SUPPORT
+ mnl_mpe_thread_init();
+#endif
+ if (access(EPO_UPDATE_HAL, F_OK) == -1) {
+ LOGD_ENG("EPOHAL file does not exist, no EPO yet\n");
+ } else if (mnld_is_epo_download_finished() == false) {
+ LOGD("EPO is still downloading");
+ } else {
+ //LOGD("there is a EPOHAL file, please mnl update EPO.DAT from EPOHAL.DAT\n");
+ if (mtk_agps_agent_epo_file_update() == MTK_GPS_ERROR) {
+ LOGE("EPO file updates fail\n");
+ } else {
+ unlink(EPO_UPDATE_HAL);
+ }
+ }
+ if (access(QEPO_UPDATE_HAL, F_OK) == -1) {
+ LOGD_ENG("QEPOHAL file does not exist, no EPO yet\n");
+ } else {
+ //LOGD("there is a QEPOHAL file, please mnl update QEPO.DAT from QEPOHAL.DAT\n");
+ if (mtk_agps_agent_qepo_file_update() == MTK_GPS_ERROR) {
+ LOGE("QEPO file updates fail\n");
+ }
+ }
+ if (access(MTKNAV_DAT_FILE_HAL, F_OK) == -1) {
+ LOGD_ENG("MTKNAVHAL file does not exist, no MTKNAV yet\n");
+ } else {
+ //LOGD("there is a MTKNAVHAL file, please mnl update MTKNAV.DAT from MTKNAVHAL.DAT\n");
+ if (mtk_agps_agent_mtknav_file_update() == MTK_GPS_ERROR) {
+ LOGE("MTKNAV file updates fail\n");
+ } else {
+ unlink(MTKNAV_DAT_FILE_HAL);
+ }
+ }
+ LOGD("dsp port (%s),nmea port (%s),nmea dbg port (%s),dbg_file_name (%s),DebugType (%d),nv_file_name (%s), mtk_gps_log_hide:%d,RfPathLossDb_Ap:%.2f, socket_port:%d, bitmap_nfw_ctrl:0x%x\n",
+ driver_cfg.dsp_port_name, driver_cfg.nmea_port_name, driver_cfg.nmeain_port_name,
+ driver_cfg.dbg_file_name, driver_cfg.DebugType, driver_cfg.nv_file_name, mtk_gps_log_hide, driver_cfg.RfPathLossDb_Ap, driver_cfg.socket_port, mnld_cfg.bitmap_nfw_ctrl);
+#if ANDROID_MNLD_PROP_SUPPORT
+ if (epo_setconfig == 1) {
+ userprofile.EPO_enabled = mnl_config.EPO_enabled;
+ } else {
+ userprofile.EPO_enabled = get_prop(7);
+ }
+#else
+ userprofile.EPO_enabled = mnl_config.EPO_enabled;
+ LOGD("Prop is not support,EPO_enabled (%d) \n", userprofile.EPO_enabled);
+#endif
+ // userprofile.EPO_enabled = mnl_config.EPO_enabled;
+ userprofile.BEE_enabled = mnl_config.BEE_enabled;
+ userprofile.SUPL_enabled = mnl_config.SUPL_enabled;
+ userprofile.EPO_priority = mnl_config.EPO_priority;
+ userprofile.BEE_priority = mnl_config.BEE_priority;
+ userprofile.SUPL_priority = mnl_config.SUPL_priority;
+ userprofile.fgGpsAosp_Ver = mnl_config.fgGpsAosp_Ver;
+ userprofile.LPPE_enabled = lppe_enable;
+ // mtk_agps_set_param(MTK_MSG_AGPS_MSG_PROFILE, &userprofile, MTK_MOD_DISPATCHER, MTK_MOD_AGENT);
+#if RAW_DATA_SUPPORT
+ gps_raw_data_enable();
+#endif
+
+ unsigned int i = 0;
+ INT32 ret = MTK_GPS_ERROR;
+ mnl_agps_location_sync_data.alt_valid = false;
+ mnl_agps_location_sync_data.alt = 0.0f;
+ mnl_agps_location_sync_data.source_valid = true;
+ mnl_agps_location_sync_data.source_gnss = true;
+ mnl_agps_location_sync_data.source_nlp = false;
+ mnl_agps_location_sync_data.source_sensor = false;
+ mnld_set_sv_inuse_valid(false);
+ mnld_set_sv_inuse_num(0);
+ mnl_agps_location_sync_data.sv_inuse_num_valid = mnld_get_sv_inuse_num_valid();
+ mnl_agps_location_sync_data.sv_inuse_num = mnld_get_sv_inuse_num();
+ // if sending profile msg fail, re-try 2-times, each time sleep 10ms
+ for (i = 0; i < 3; i++) {
+ ret = mtk_agps_set_param(MTK_MSG_AGPS_MSG_PROFILE, &userprofile, MTK_MOD_DISPATCHER, MTK_MOD_AGENT);
+ if (ret != MTK_GPS_SUCCESS) {
+ LOGD("%d st send profile to agent fail. try again \n", i);
+ usleep(10000); // sleep 10ms for init agent message queue
+ } else {
+ LOGD_ENG("%d st send profile to agent OK \n", i);
+ break;
+ }
+ }
+
+ mtk_gps_dump_nfw_visibility();
+ if (mtk_gps_get_position_accuracy(&latitude, &longitude, &accuracy) == MTK_GPS_SUCCESS && accuracy < 100) {
+ LOGDX("mnl init, mtk_gps_get_position_accuracy success");
+ mnl_agps_location_sync_data.lat = latitude;
+ mnl_agps_location_sync_data.lng = longitude;
+ mnl_agps_location_sync_data.acc = accuracy;
+ mnld_nfw_mnl2agps_location_sync(&mnl_agps_location_sync_data);
+ }
+
+ hasAlmanac();
+
+ ret = mtk_gps_set_param(MTK_PARAM_CMD_SIB8_16_ENABLE, &sib8_16_enable);
+ LOGD("sent CMD_SIB8_16_ENABLE to mnl, sib8_16_enable = %d ,ret = %d", sib8_16_enable, ret);
+ ret = mtk_gps_set_param(MTK_PARAM_CMD_DEBUG2APP_CONFIG, &enable_debug2app);
+ LOGD("sent enable_debug2app to mnl, enable_debug2app = %d ,ret = %d", enable_debug2app, ret);
+ if(mtk_gps_mnl_info.support_lppe){
+ ret = mtk_gps_set_param(MTK_PARAM_CMD_LPPE_ENABLE, &lppe_enable);
+ LOGD("sent MTK_PARAM_CMD_LPPE_ENABLE to mnl, lppe_enable = %d ,ret = %d", lppe_enable, ret);
+ }
+ ret = mtk_gps_set_param(MTK_PARAM_CMD_ENABLE_FULL_TRACKING, &g_enable_full_tracking);
+ LOGD("sent enable_full_tracking to mnl, enable_full_tracking = %d ,ret = %d", g_enable_full_tracking, ret);
+ return status;
+}
+
+void mnl_gps_gps_close_fd(void) {
+ if (dsp_fd > 0) {
+ close(dsp_fd);
+ dsp_fd = -1;
+ }
+}
+
+void mnl_gps_gps_close_fd2(void) {
+ if (dsp2_fd > 0) {
+ close(dsp2_fd);
+ dsp2_fd = -1;
+ }
+}
+
+/*****************************************************************************/
+static int mnld_gps_stop_or_suspend_impl(bool is_to_suspend) {
+ int ret = 0;
+ bool need_to_close = true;
+ LOGD("MNL exiting, is_suspend = %d\n", is_to_suspend);
+ if (g_mnl_init == true) {
+ mtk_gps_mnl_stop();
+ g_mnl_init = false;
+ }
+
+ if (is_to_suspend) {
+ LOGD_ENG("mtk_gps_mnl_suspend()\n");
+ } else {
+ LOGD_ENG("mtk_gps_mnl_stop()\n");
+ }
+
+ if (g_gpsdbglogThreadExit == false) {
+ gps_dbg_log_exit_flush(1);
+ }
+ if ((ret = mtk_gps_sys_uninit())) {
+ LOGE("mtk_gps_sys_uninit err = %d=\n", errno);
+ }
+ if (dsp_fd > 0) {
+#if defined(GPS_SUSPEND_SUPPORT)
+ if (is_to_suspend) {
+ //change to gps close if suspend fail,
+ //it might be a normal case if suspend not ready on stpgps/firmware part
+ bool suspend_okay = true;
+ bool suspend_okay_dsp2 = true;
+ suspend_okay = mnld_do_gps_suspend_resume(dsp_fd, MNLD_GPS_DO_HW_SUSPEND);
+ if(dsp2_fd > 0) {
+ suspend_okay_dsp2 = mnld_do_gps_suspend_resume(dsp2_fd, MNLD_GPS_DO_HW_SUSPEND);
+ }
+ if (suspend_okay && suspend_okay_dsp2) {
+ gps_device_rst_listener_thread_init();
+ gps_controller_suspend_done_flag = 1;
+ need_to_close = false;
+ } else {
+ LOGW("do hw suspend fail, change to do close, (%d, %d)", suspend_okay, suspend_okay_dsp2);
+ need_to_close = true;
+ }
+ } else {
+ bool try_okay;
+ try_okay = mnld_gps_try_suspend_to_close();
+ if (try_okay) {
+ need_to_close = false;
+ } else {
+ need_to_close = true;
+ LOGD("not in suspend mode, only do mnl_gps_gps_close_fd");
+ }
+ }
+#endif
+ if (need_to_close) {
+ mnl_gps_gps_close_fd();
+ }
+ }
+#ifdef MTK_GPS_DUAL_FREQ_SUPPORT /*Defined in Android.mk*/
+ if (need_to_close) {
+ mnl_gps_gps_close_fd2();
+ }
+#endif
+ // cancel alarm
+ LOGD_ENG("Cancel alarm");
+ alarm(0);
+ return ret;
+}
+
+static int mnld_gps_stop_impl(void) {
+ return mnld_gps_stop_or_suspend_impl(false);
+}
+
+/*****************************************************************************/
+static time_t last_send_time = 0;
+static time_t current_time = 0;
+
+int send_active_notify() {
+ unsigned int gps_user = mtk_gps_get_gps_user();
+
+ if (!(mnl_config.debug_mnl & MNL_NMEA_DISABLE_NOTIFY)) {
+ char buff[1024] = {0};
+ int offset = 0;
+ LOGD("send clean nmea timer cmd!\n");
+ put_int(buff, &offset, GPS2GPS_NMEA_DATA_TIMEOUT);
+ return safe_sendto(MNLD_GPS_CONTROL_SOCKET, buff, offset);
+ }
+ return -1;
+}
+
+INT32 mtk_gps_sys_gps_mnl_callback(MTK_GPS_NOTIFICATION_TYPE msg) {
+ LOGD_ENG("msg:%d\n", msg);
+ switch (msg) {
+ case MTK_GPS_MSG_FIX_READY:
+ {
+ // For NI open GPS
+ double dfRtcD = 0.0, dfAge = 0.0;
+ if (send_active_notify() == -1) {
+ LOGE("send_active_notify failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ #if defined(__ANDROID_OS__)
+ if (mtk_gps_get_rtc_info(&dfRtcD, &dfAge) == MTK_GPS_SUCCESS) {
+ LOGD("MTK_GPS_MSG_FIX_READY, GET_RTC_OK, %.3lf, %.3lf\n", dfRtcD, dfAge);
+ LOGD("Age = %d, RTCDiff = %d, Time_interval = %d\n", mnl_config.AVAILIABLE_AGE,
+ mnl_config.RTC_DRIFT, mnl_config.TIME_INTERVAL);
+ if ((dfAge <= mnl_config.AVAILIABLE_AGE) && (dfRtcD >= mnl_config.RTC_DRIFT ||
+ dfRtcD <= -mnl_config.RTC_DRIFT) && dfRtcD < 5000) {
+ int fd_fmsta = -1;
+ unsigned char buf[2]= {0};
+ int status = -1;
+ fd_fmsta = open("/proc/fm", O_RDWR);
+ if (fd_fmsta < 0) {
+ LOGD("open /proc/fm error");
+ } else {
+ LOGD("open /proc/fm success!");
+ status = read(fd_fmsta, &buf, sizeof(buf));
+ if (status < 0)
+ LOGD("read fm status fails = %s", strerror(errno));
+ if (close(fd_fmsta) == -1)
+ LOGD("close fails = %s", strerror(errno));
+ }
+
+ if (buf[0] == '2') {
+ INT32 time_diff;
+ if (time(¤t_time)==((time_t)-1)) {
+ LOGE("time() fail(%s)!!\r\n", strerror(errno));
+ }
+ time_diff = current_time - last_send_time;
+ if ((0 == last_send_time) || (time_diff > mnl_config.TIME_INTERVAL)) {
+ int fd_fmdev = -1;
+ int ret = 0;
+ struct fm_gps_rtc_info rtcInfo;
+ fd_fmdev = open("dev/fm", O_RDWR);
+ if (fd_fmdev < 0) {
+ LOGD("open fm dev error\n");
+ }
+ else {
+ rtcInfo.retryCnt = 2;
+ rtcInfo.ageThd = mnl_config.AVAILIABLE_AGE;
+ rtcInfo.driftThd = mnl_config.RTC_DRIFT;
+ rtcInfo.tvThd.tv_sec = mnl_config.TIME_INTERVAL;
+ rtcInfo.age = dfAge;
+ rtcInfo.drift = dfRtcD;
+ rtcInfo.tv.tv_sec = current_time;
+ ret = ioctl(fd_fmdev, FM_IOCTL_GPS_RTC_DRIFT, &rtcInfo);
+ if (ret) {
+ LOGD("send rtc info failed, [ret=%d]\n", ret);
+ }
+ ret = close(fd_fmdev);
+ if (ret) {
+ LOGD("close fm dev error\n");
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ LOGD("MTK_GPS_MSG_FIX_READY,GET_RTC_FAIL\n");
+ }
+ #endif
+ #if RAW_DATA_SUPPORT
+ if (gps_raw_debug_mode && !mtk_msg_raw_meas_flag) {
+ LOGD("raw_debug_mode is open, send MTK_MSG_RAW_MEAS to libmnl\n");
+
+ INT32 ret = MTK_GPS_ERROR;
+ ret = mtk_gps_set_param(MTK_MSG_RAW_MEAS, NULL);
+ LOGD("mtk_gps_set_param,ret = %d\n", ret);
+ if (ret != MTK_GPS_SUCCESS) {
+ LOGE("send MTK_MSG_RAW_MEASto mnl fail,please reopen gps\n");
+ } else {
+ LOGD("send MTK_MSG_RAW_MEAS to mnl OK \n");
+ mtk_msg_raw_meas_flag = 1; // Don't send MTK_MSG_RAW_MEAS when it was sent to mnl successfully
+ }
+ }
+
+ /*get gps measurement and clock data*/
+ if (mnld_is_gps_meas_enabled() && mnld_is_gps_started_done()) {
+ #if 0 //gnss measurement API include gps info
+ get_gps_measurement_clock_data();
+ #endif
+ get_gnss_measurement_clock_data();
+ LOGD("gps_meas_enable");
+ }
+
+ /*get gps navigation event */
+ if (mnld_is_gps_navi_enabled() && mnld_is_gps_started_done()) {
+ LOGD("gps_navi_enable");
+ #if 0 //gnss navigation API include gps info
+ get_gps_navigation_event();
+ #endif
+ get_gnss_navigation_event();
+ }
+ #endif
+ //Calculate Geofence status
+ if (mtk_geofence2mnl_get_valid_fence_num() > 0)
+ {
+ mtk_geofence_position_info pos_data;
+ memset(&pos_data, 0, sizeof(pos_data));
+
+ if (mtk_gps_geofence_get_position(&pos_data) == MTK_GPS_SUCCESS){
+ mtk_geofence_location_expire(pos_data);
+ }
+ }
+ }
+ break;
+ case MTK_GPS_MSG_FIX_PROHIBITED:
+ {
+ if (send_active_notify() == -1) {
+ LOGE("send_active_notify failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ LOGD("MTK_GPS_MSG_FIX_PROHIBITED\n");
+ }
+ break;
+ case MTK_GPS_MSG_TEST_STATUS_READY:
+ {
+ if(gps_emi_fd != -1) {
+ char *buff = NULL;
+ FILE *fp = NULL;
+ int num = 0;
+ buff = malloc(ADC_CAPTURE_MAX_SIZE);
+ if (buff != NULL) {
+ memset(buff, 0, ADC_CAPTURE_MAX_SIZE);
+ num = read(gps_emi_fd, buff, ADC_CAPTURE_MAX_SIZE);
+ LOGD("ADC read length = %d\n", num);
+ if((fp = fopen(MTK_GPS_DATA_PATH"ADC.txt", "w+")) != NULL) {
+ fwrite(buff, ADC_CAPTURE_MAX_SIZE, 1, fp);
+ fclose(fp);
+ }
+ free(buff);
+ } else {
+ LOGD("ADC malloc failed");
+ }
+ }
+ }
+ break;
+ case MTK_GPS_MSG_NEED_RESTART:
+ {
+ LOGW("MTK_GPS_MSG_NEED_RESTART from mnl");
+ gps_mnld_restart_mnl_process();
+ }
+ break;
+ default:
+ break;
+ }
+ return MTK_GPS_SUCCESS;
+}
+
+/*****************************************************************************/
+/*Agps dispatcher state mode*/
+typedef enum {
+ ST_SI,
+ ST_NI,
+ ST_IDLE,
+ ST_UNKNOWN,
+}MTK_AGPS_DISPATCH_STATE;
+
+void gps_controller_rcv_pmtk(const char* pmtk) {
+ // LOGD("rcv_pmtk: %s", pmtk);
+ if (mnld_is_gps_stopped()) {
+ LOGD("rcv_pmtk: MNL stopped, return");
+ return;
+ }
+ int ret = mtk_agps_set_param(MTK_MSG_AGPS_MSG_SUPL_PMTK, pmtk, MTK_MOD_DISPATCHER, MTK_MOD_AGENT);
+ if (ret != 0) {
+ LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_PMTK\n");
+ }
+}
+
+INT32 mtk_gps_sys_agps_disaptcher_callback(UINT16 type, UINT16 length, char *data) {
+ INT32 ret = MTK_GPS_SUCCESS;
+
+ if (type == MTK_AGPS_CB_SUPL_PMTK || type == MTK_AGPS_CB_ASSIST_REQ || \
+ type == MTK_AGPS_CB_START_REQ || type == MTK_AGPS_CB_LPPE_ASSIST_REQ) {
+ if (mnl_config.SUPL_enabled) {
+ if (type == MTK_AGPS_CB_SUPL_PMTK) {
+ if (length != 0)
+ if (mnl2agps_pmtk(data) == -1) {
+ LOGE("mnl2agps_pmtk failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ return 0;
+ } else if (type == MTK_AGPS_CB_ASSIST_REQ) {
+ LOGD("GPS re-aiding\n");
+ if (mnl2agps_reaiding_req() == -1) {
+ LOGE("mnl2agps_reaiding_req failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ return 0;
+ }else if (type == MTK_AGPS_CB_LPPE_ASSIST_REQ) {
+ if (length != 0) {
+ mnl2agps_lppe_assist_data_req(data,length);
+ LOGD("request lppe data\n");
+ }
+ return 0;
+ }
+
+ } else {
+ LOGD("mtk_sys_agps_disaptcher_callback: SUPL disable");
+ ret = MTK_GPS_ERROR;
+ }
+ if ((type == MTK_AGPS_CB_START_REQ) && (data != NULL)) {
+ LOGD("MNL ready and assist req:%d", *data);
+ int assist_req;
+ if (*data == 1) {
+ //LOGD("Agent assist request");
+ assist_req = 1;
+ } else if (*data == 0) {
+ //LOGD("Agent no assist request");
+ assist_req = 0;
+ } else {
+ LOGD("unknown data");
+ assist_req = 0;
+ }
+ if (!mnl_config.SUPL_enabled) {
+ LOGD("SUPL disable,assist_req = 0");
+ assist_req = 0;
+ }
+ // mnl2agps_gps_open(assist_req);
+ if (gps_restart == 1) {
+ release_condition(&lock_for_sync[M_RESTART]);
+ LOGD("release condition for restart");
+ }
+ if (mnld_gps_start_done(assist_req) == -1) {
+ LOGE("mnld_gps_start_done failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ ret = MTK_GPS_SUCCESS;
+ return ret;
+ }
+ } else if ((type == MTK_AGPS_CB_BITMAP_UPDATE) && (data != NULL)) {
+ LOGD("MNL NTP/NLP request:%d", *data);
+ if ((*data & 0x01) == 0x01) {
+ LOGD("Call request utc time request");
+ if (mnl2hal_request_utc_time() == -1) {
+ LOGE("mnl2hal_request_utc_time failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ }
+ if ((*data & 0x02) == 0x02) {
+ LOGD("Call nlp_server request");
+ mnld_gps_request_nlp(NLP_REQUEST_SRC_MNL);
+ }
+ } else if (type == MTK_AGPS_CB_QEPO_DOWNLOAD_REQ) {
+ UINT16 wn;
+ UINT32 tow;
+ UINT32 sys_time;
+ char dl_bitmap = 0;
+
+ #if defined(QEPO_BD) || defined(QEPO_GA)
+ if(data != NULL)
+ {
+ dl_bitmap = *data;
+ ret = mtk_agps_agent_qepo_get_rqst_time(&wn, &tow, &sys_time);
+ LOGD("wn, tow, sys_time = %d, %d, %d,bitmap:0x%x\n", wn, tow, sys_time, *data);
+ gps_mnl_set_gps_time(wn, tow, sys_time);
+ if (( dl_bitmap & (AGT_QEPO_GP_BIT|AGT_QEPO_GL_BIT)) != 0) {
+ if (-1==qepo_downloader_start()) {
+ LOGE("qepo_downloader_start failed reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+
+ if ((dl_bitmap & AGT_QEPO_BD_BIT) == AGT_QEPO_BD_BIT) {
+ if (-1==qepo_bd_downloader_start()) {
+ LOGE("qepo_bd_downloader_start failed reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+
+ if ((dl_bitmap & AGT_QEPO_GA_BIT) == AGT_QEPO_GA_BIT) {
+ if (-1==qepo_ga_downloader_start()) {
+ LOGE("qepo_ga_downloader_start failed reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+
+ }else{
+ LOGE("QEPO dl request , pointer of data is null!!!\n");
+ }
+ #else
+ ret = mtk_agps_agent_qepo_get_rqst_time(&wn, &tow, &sys_time);
+ LOGD("wn, tow, sys_time = %d, %d, %d\n", wn, tow, sys_time);
+ gps_mnl_set_gps_time(wn, tow, sys_time);
+ qepo_downloader_start();
+ #endif
+ } else if (type == MTK_AGPS_CB_MTKNAV_DOWNLOAD_REQ) {
+ if(mtknav_downloader_start() == -1){
+ LOGW("mtknav downloader start fail");
+ }
+ }
+ #ifdef MTK_MD_GNSS_SYNC
+ else if (type == MTK_AGPS_CB_MD_TIME_SYNC_REQ) {
+ mnld_request_MD_time_sync(*(md_time_require_action*)data);
+ } else if (type == MTK_AGPS_CB_MD_TIME_INFO_RSP) {
+ mnld_feadback_time_to_MD((gnss_timeOfDay_with_unc*)data);
+ }
+ #endif
+ return ret;
+}
+
+#if RAW_DATA_SUPPORT
+int get_val(char *pStr, char** ppKey, char** ppVal) {
+ int len = (int)strlen(pStr);
+ char *end = pStr + len;
+ char *key = NULL, *val = NULL;
+
+ LOGD("pStr = %s,len=%d!!\n", pStr, len);
+
+ if (!len) {
+ return -1; // no data
+ } else if (pStr[0] == '#') { /*ignore comment*/
+ *ppKey = *ppVal = NULL;
+ return 0;
+ } else if (pStr[len-1] != '\n') {
+ if (len >= GPS_CONF_FILE_SIZE-1) {
+ LOGD("buffer is not enough!!\n");
+ return -1;
+ } else {
+ pStr[len] = '\n';
+ }
+ }
+ key = pStr;
+
+ LOGD("key = %s!!\n", key);
+ while ((*pStr != '=') && (pStr < end)) pStr++;
+ if (pStr >= end) {
+ LOGW("'=' is not found!!\n");
+ *ppKey = *ppVal = NULL;
+ return 0; // format error
+ }
+
+ *pStr++ = '\0';
+ while (IS_SPACE(*pStr) && (pStr < end)) pStr++; // skip space chars
+ val = pStr;
+ while (!IS_SPACE(*pStr) && (pStr < end)) pStr++;
+ *pStr = '\0';
+ *ppKey = key;
+ *ppVal = val;
+
+ LOGD("val = %s!!\n", val);
+ return 0;
+}
+
+static int gps_raw_data_enable(void) {
+ char result[GPS_CONF_FILE_SIZE] = {0};
+
+ FILE *fp = fopen(RAW_DATA_CONTROL_FILE_PATH, "r");
+ char *key = NULL, *val = NULL;
+ if (!fp) {
+ LOGD_ENG("%s: open %s fail!\n", __FUNCTION__, RAW_DATA_CONTROL_FILE_PATH);
+ return 1;
+ }
+
+ while (fgets(result, sizeof(result), fp)) {
+ if (get_val(result, &key, &val)) {
+ LOGD("%s: Get data fails!!\n", __FUNCTION__);
+ fclose(fp);
+ return 1;
+ }
+ if (!key || !val) {
+ continue;
+ }
+ if (!strcmp(key, "RAW_DEBUG_MODE")) {
+ int len = strlen(val);
+ gps_raw_debug_mode = str2int(val, val+len); // *val-'0';
+ if ((gps_raw_debug_mode != 1) && (gps_raw_debug_mode != 0)) {
+ gps_raw_debug_mode = 0;
+ }
+ LOGD("gps_raw_debug_mode = %d\n", gps_raw_debug_mode);
+ }
+ }
+ fclose(fp);
+ return gps_raw_debug_mode;
+}
+
+void print_gnss_measurement(gnss_measurement *in) {
+ LOGD("===== print_gnss_measurement ====");
+ LOGD("flags=0x%x", in->flags);
+ LOGD("svid=%d", in->svid);
+ LOGD("constellation=0x%x", in->constellation);
+ LOGD("time_offset_ns=%f", in->time_offset_ns);
+ LOGD("state=0x%x", in->state);
+ LOGD("received_gps_tow_ns=%"PRId64, in->received_sv_time_in_ns);
+ LOGD("received_gps_tow_uncertainty_ns=%"PRId64, in->received_sv_time_uncertainty_in_ns);
+ LOGD("c_n0_dbhz=%f", in->c_n0_dbhz);
+ LOGD("pseudorange_rate_mps=%f", in->pseudorange_rate_mps);
+ LOGD("pseudorange_rate_uncertainty_mps=%f", in->pseudorange_rate_uncertainty_mps);
+ LOGD("accumulated_delta_range_state=0x%x", in->accumulated_delta_range_state);
+ LOGD("accumulated_delta_range_m=%f", in->accumulated_delta_range_m);
+ LOGD("accumulated_delta_range_uncertainty_m=%f", in->accumulated_delta_range_uncertainty_m);;
+ LOGD("carrier_frequency_hz=%f", in->carrier_frequency_hz);
+ LOGD("carrier_cycles=%"PRId64, in->carrier_cycles);
+ LOGD("carrier_phase=%f", in->carrier_phase);
+ LOGD("carrier_phase_uncertainty=%f", in->carrier_phase_uncertainty);
+ LOGD("multipath_indicator=%d", in->multipath_indicator);
+ LOGD("snr_db=%f", in->snr_db);
+ LOGD("fullInterSignalBiasNs=%f", in->fullInterSignalBiasNs);
+ LOGD("fullInterSignalBiasUncertaintyNs=%f", in->fullInterSignalBiasUncertaintyNs);
+ LOGD("satelliteInterSignalBiasNs=%f", in->satelliteInterSignalBiasNs);
+ LOGD("satelliteInterSignalBiasUncertaintyNs=%f", in->satelliteInterSignalBiasUncertaintyNs);
+ LOGD("basebandCN0DbHz=%f", in->basebandCN0DbHz);
+ LOGD("agc_level_db=%f", in->agc_level_db);
+}
+
+void print_gnss_clock(gnss_clock *in) {
+ LOGD("===== print_gnss_clock ====");
+ LOGD("flags=0x%x", in->flags);
+ LOGD("leap_second=%d", in->leap_second);
+ LOGD("time_ns=%"PRId64, in->time_ns);
+ LOGD("time_uncertainty_ns=%f", in->time_uncertainty_ns);
+ LOGD("full_bias_ns=%"PRId64, in->full_bias_ns);
+ LOGD("bias_ns=%f", in->bias_ns);
+ LOGD("bias_uncertainty_ns=%f", in->bias_uncertainty_ns);
+ LOGD("drift_nsps=%f", in->drift_nsps);
+ LOGD("drift_uncertainty_nsps=%f", in->drift_uncertainty_nsps);
+ LOGD("hw_clock_discontinuity_count=%d", in->hw_clock_discontinuity_count);
+ LOGD("constellation=%d", in->referenceSignalTypeForIsb.constellation);
+ LOGD("carrierFrequencyHz=%f", in->referenceSignalTypeForIsb.carrierFrequencyHz);
+ LOGD("string=%s", in->referenceSignalTypeForIsb.codeType);
+}
+
+void print_gnss_nav_msg(gnss_nav_msg *in) {
+ LOGD("===== print_gnss_nav_msg ====");
+ LOGD("svid=%d", in->svid);
+ LOGD("type=%d", in->type);
+ LOGD("status=0x%x", in->status);
+ LOGD("message_id=%d", in->message_id);
+ LOGD("submessage_id=%d", in->submessage_id);
+ LOGD("data_length=%zu", in->data_length);
+}
+
+static void update_gnss_measurement(gnss_measurement* dst, Gnssmeasurement* src) {
+ LOGD("update_gnss_measurement begin");
+
+ fieldp_copy(dst, src, flags);
+ fieldp_copy(dst, src, svid);
+ fieldp_copy(dst, src, constellation);
+ fieldp_copy(dst, src, time_offset_ns);
+ fieldp_copy(dst, src, state);
+ fieldp_copy(dst, src, received_sv_time_in_ns);
+ fieldp_copy(dst, src, received_sv_time_uncertainty_in_ns);
+ fieldp_copy(dst, src, c_n0_dbhz);
+ fieldp_copy(dst, src, pseudorange_rate_mps);
+ fieldp_copy(dst, src, pseudorange_rate_uncertainty_mps);
+ fieldp_copy(dst, src, accumulated_delta_range_state);
+ fieldp_copy(dst, src, accumulated_delta_range_m);
+ fieldp_copy(dst, src, accumulated_delta_range_uncertainty_m);
+ fieldp_copy(dst, src, carrier_frequency_hz);
+ fieldp_copy(dst, src, carrier_cycles);
+ fieldp_copy(dst, src, carrier_phase);
+ fieldp_copy(dst, src, carrier_phase_uncertainty);
+ fieldp_copy(dst, src, multipath_indicator);
+ fieldp_copy(dst, src, snr_db);
+ fieldp_copy(dst, src, fullInterSignalBiasNs);
+ fieldp_copy(dst, src, fullInterSignalBiasUncertaintyNs);
+ fieldp_copy(dst, src, satelliteInterSignalBiasNs);
+ fieldp_copy(dst, src, satelliteInterSignalBiasUncertaintyNs);
+ fieldp_copy(dst, src, basebandCN0DbHz);
+ ///TODO FIX IT
+ // fieldp_copy(dst, src, agc_level_db);
+ dst->agc_level_db = g_agc_level;
+ // Check frequency to determin code type
+ if ((src->carrier_frequency_hz > CARRIER_FREQ_GPS_L1_MIN) && (dst->carrier_frequency_hz < CARRIER_FREQ_GPS_L1_MAX)) {
+ MNLD_STRNCPY(dst->codeType, "C", sizeof(dst->codeType));
+ } else if ((src->carrier_frequency_hz > CARRIER_FREQ_GPS_L5_MIN) && (dst->carrier_frequency_hz < CARRIER_FREQ_GPS_L5_MAX)) {
+ MNLD_STRNCPY(dst->codeType, "I", sizeof(dst->codeType));
+ } else if ((src->carrier_frequency_hz > CARRIER_FREQ_GLO_L1_MIN) && (dst->carrier_frequency_hz < CARRIER_FREQ_GLO_L1_MAX)) {
+ MNLD_STRNCPY(dst->codeType, "C", sizeof(dst->codeType));
+ } else if ((src->carrier_frequency_hz > CARRIER_FREQ_GAL_E1_MIN) && (dst->carrier_frequency_hz < CARRIER_FREQ_GAL_E1_MAX)) {
+ MNLD_STRNCPY(dst->codeType, "A", sizeof(dst->codeType));
+ } else if ((src->carrier_frequency_hz > CARRIER_FREQ_GAL_E5A_MIN) && (dst->carrier_frequency_hz < CARRIER_FREQ_GAL_E5A_MAX)) {
+ MNLD_STRNCPY(dst->codeType, "I", sizeof(dst->codeType));
+ } else if ((src->carrier_frequency_hz > CARRIER_FREQ_BD_B1_MIN) && (dst->carrier_frequency_hz < CARRIER_FREQ_BD_B1_MAX)) {
+ MNLD_STRNCPY(dst->codeType, "I", sizeof(dst->codeType));
+ } else if ((src->carrier_frequency_hz > CARRIER_FREQ_BD_B2_MIN) && (dst->carrier_frequency_hz < CARRIER_FREQ_BD_B2_MAX)) {
+ MNLD_STRNCPY(dst->codeType, "I", sizeof(dst->codeType));
+ } else if ((src->carrier_frequency_hz > CARRIER_FREQ_BD_B3_MIN) && (dst->carrier_frequency_hz < CARRIER_FREQ_BD_B3_MAX)) {
+ MNLD_STRNCPY(dst->codeType, "I", sizeof(dst->codeType));
+ } else {
+ MNLD_STRNCPY(dst->codeType, "UNKNOWN", sizeof(dst->codeType));
+ }
+// private static final int HAS_SNR = (1<<0);
+// private static final int HAS_CARRIER_FREQUENCY = (1<<9);
+// private static final int HAS_AUTOMATIC_GAIN_CONTROL = (1<<13);
+// private static final int HAS_FULL_ISB = (1<<16);
+// private static final int HAS_FULL_ISB_UNCERTAINTY = (1<<17);
+// private static final int HAS_SATELLITE_ISB = (1<<18);
+// private static final int HAS_SATELLITE_ISB_UNCERTATINTY = (1<<19);
+
+ dst->flags = (dst->flags | (1<<0)| (1<<9) |(1<<13) |(1<<16) |(1<<17) |(1<<18) |(1<<19));
+
+ if (gps_raw_debug_mode) {
+ print_gnss_measurement(dst);
+ }
+}
+
+static void update_gnss_clock(gnss_clock* dst, Gnssclock* src) {
+ LOGD("update_gnss_clock begin");
+
+ fieldp_copy(dst, src, flags);
+ fieldp_copy(dst, src, leap_second);
+ fieldp_copy(dst, src, time_ns);
+ fieldp_copy(dst, src, time_uncertainty_ns);
+ fieldp_copy(dst, src, full_bias_ns);
+ fieldp_copy(dst, src, bias_ns);
+ fieldp_copy(dst, src, bias_uncertainty_ns);
+ fieldp_copy(dst, src, drift_nsps);
+ fieldp_copy(dst, src, drift_uncertainty_nsps);
+ fieldp_copy(dst, src, hw_clock_discontinuity_count);
+ field_copy(dst->referenceSignalTypeForIsb, src->referenceSignalTypeForIsb, constellation);
+ field_copy(dst->referenceSignalTypeForIsb, src->referenceSignalTypeForIsb, carrierFrequencyHz);
+ MNLD_STRNCPY(dst->referenceSignalTypeForIsb.codeType, src->referenceSignalTypeForIsb.codeType, sizeof(dst->referenceSignalTypeForIsb.codeType));
+
+ if (gps_raw_debug_mode) {
+ print_gnss_clock(dst);
+ }
+}
+
+static void update_gnss_navigation(gnss_nav_msg* dst, GnssNavigationmessage* src) {
+ LOGD("update_gnss_navigation begin");
+
+ fieldp_copy(dst, src, svid);
+ fieldp_copy(dst, src, type);
+ fieldp_copy(dst, src, status);
+ fieldp_copy(dst, src, message_id);
+ fieldp_copy(dst, src, submessage_id);
+ fieldp_copy(dst, src, data_length);
+
+ if (gps_raw_debug_mode) {
+ print_gnss_nav_msg(dst);
+ }
+}
+
+gnss_data gnssdata;
+Gnssmeasurement gpqzmeasurement[MNLD_MGPSID+MNLD_MQZSSID];
+Gnssmeasurement glomeasurement[MNLD_MGLONID];
+Gnssmeasurement bdmeasurement[MNLD_MBD2ID];
+Gnssmeasurement galmeasurement[MNLD_MGLEOID];
+Gnssmeasurement sbasmeasurement[MNLD_SBAS_BUN_PRN];
+Gnssmeasurement navicmeasurement[MNLD_MNAVICID];
+
+static void get_gnss_measurement_clock_data() {
+ int i;
+ unsigned int num = 0;
+ int ret;
+
+ INT8 GpQz_Ch_Proc_Ord_PRN[MNLD_MGPSID+MNLD_MQZSSID] = {0};
+ INT8 Glo_Ch_Proc_Ord_PRN[MNLD_MGLONID] = {0};
+ INT8 BD_Ch_Proc_Ord_PRN[MNLD_MBD2ID] = {0};
+ INT8 Gal_Ch_Proc_Ord_PRN[MNLD_MGLEOID] = {0};
+ INT8 SBAS_Ch_Proc_Ord_PRN[MNLD_SBAS_BUN_PRN] = {0};
+ INT8 NAVIC_Ch_Proc_Ord_PRN[MNLD_MNAVICID] = {0};
+
+ LOGD("get_gnss_measurement_clock_data begin, sizeof(Gnssmeasurement):%lu, sizeof(gnss_data):%lu",sizeof(Gnssmeasurement), sizeof(gnss_data));
+
+ memset(gpqzmeasurement, 0, sizeof(gpqzmeasurement));
+ memset(glomeasurement, 0, sizeof(glomeasurement));
+ memset(bdmeasurement, 0, sizeof(bdmeasurement));
+ memset(galmeasurement, 0, sizeof(galmeasurement));
+ memset(sbasmeasurement, 0, sizeof(sbasmeasurement));
+ memset(navicmeasurement, 0, sizeof(navicmeasurement));
+ mtk_gnss_get_measurement(gpqzmeasurement, glomeasurement, bdmeasurement, galmeasurement, sbasmeasurement,navicmeasurement,
+ GpQz_Ch_Proc_Ord_PRN, Glo_Ch_Proc_Ord_PRN, BD_Ch_Proc_Ord_PRN, Gal_Ch_Proc_Ord_PRN, SBAS_Ch_Proc_Ord_PRN, NAVIC_Ch_Proc_Ord_PRN);
+
+ Gnssclock gnssclock;
+ if (mtk_gnss_get_clock(&gnssclock) == 0) {
+ LOGD("mtk_gnss_get_clock fail\n");
+ memset(&gnssclock, 0, sizeof(Gnssclock));
+ }
+ gnss_clock gnss_clock;
+ memset(&gnss_clock, 0, sizeof(gnss_clock));
+ update_gnss_clock(&gnss_clock, &gnssclock);
+
+ memset(&gnssdata, 0, sizeof(gnssdata));
+ // For GPS & QZSS
+ for (i = 0; i < MNLD_MGPSID+MNLD_MQZSSID; i++) {
+ if (gpqzmeasurement[i].svid != 0) {
+ num = gnssdata.measurement_count;
+ if (num >= MTK_MNLD_GNSS_MAX_MEASUREMENT) {
+ LOGD("measurement_count exceed the upper limit!");
+ break;
+ }
+
+ update_gnss_measurement(&gnssdata.measurements[num], &gpqzmeasurement[i]);
+ if (gnssdata.measurements[num].state == 0) {
+ gnssdata.measurements[num].pseudorange_rate_mps = 1;
+ }
+ gnssdata.measurement_count++;
+ LOGD("GPS/QZSS measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+ num, i, gnssdata.measurements[num].svid);
+ }
+ }
+
+ // For Glonass
+ for (i = 0; i < MNLD_MGLONID; i++) {
+ if (glomeasurement[i].svid != 0) {
+ num = gnssdata.measurement_count;
+ if (num >= MTK_MNLD_GNSS_MAX_MEASUREMENT) {
+ LOGD("measurement_count exceed the upper limit!");
+ break;
+ }
+
+ update_gnss_measurement(&gnssdata.measurements[num], &glomeasurement[i]);
+ if (gnssdata.measurements[num].state == 0) {
+ gnssdata.measurements[num].pseudorange_rate_mps = 1;
+ }
+ gnssdata.measurement_count++;
+ LOGD("Glonass measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+ num, i, gnssdata.measurements[num].svid);
+ }
+ }
+
+ // For Beidou
+ for (i = 0; i < MNLD_MBD2ID; i++) {
+ if (bdmeasurement[i].svid != 0) {
+ num = gnssdata.measurement_count;
+ if (num >= MTK_MNLD_GNSS_MAX_MEASUREMENT) {
+ LOGD("measurement_count exceed the upper limit!");
+ break;
+ }
+
+ update_gnss_measurement(&gnssdata.measurements[num], &bdmeasurement[i]);
+ if (gnssdata.measurements[num].state == 0) {
+ gnssdata.measurements[num].pseudorange_rate_mps = 1;
+ }
+ gnssdata.measurement_count++;
+ LOGD("Beidou measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+ num, i, gnssdata.measurements[num].svid);
+ }
+ }
+
+ // For Galileo
+ for (i = 0; i < MNLD_MGLEOID; i++) {
+ if (galmeasurement[i].svid != 0) {
+ num = gnssdata.measurement_count;
+ if (num >= MTK_MNLD_GNSS_MAX_MEASUREMENT) {
+ LOGD("measurement_count exceed the upper limit!");
+ break;
+ }
+
+ update_gnss_measurement(&gnssdata.measurements[num], &galmeasurement[i]);
+ if (gnssdata.measurements[num].state == 0) {
+ gnssdata.measurements[num].pseudorange_rate_mps = 1;
+ }
+ gnssdata.measurement_count++;
+ LOGD("Galileo measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+ num, i, gnssdata.measurements[num].svid);
+ }
+ }
+
+ // For SBAS
+ for (i = 0; i < MNLD_SBAS_BUN_PRN; i++) {
+ if (sbasmeasurement[i].svid != 0) {
+ num = gnssdata.measurement_count;
+ if (num >= MTK_MNLD_GNSS_MAX_MEASUREMENT) {
+ LOGD("measurement_count exceed the upper limit!");
+ break;
+ }
+
+ update_gnss_measurement(&gnssdata.measurements[num], &sbasmeasurement[i]);
+ if (gnssdata.measurements[num].state == 0) {
+ gnssdata.measurements[num].pseudorange_rate_mps = 1;
+ }
+ gnssdata.measurement_count++;
+ LOGD("SBAS measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+ num, i, gnssdata.measurements[num].svid);
+ }
+ }
+
+ // For NAVIC
+ for (i = 0; i < MNLD_MNAVICID; i++) {
+ if (navicmeasurement[i].svid != 0) {
+ num = gnssdata.measurement_count;
+ if (num >= MTK_MNLD_GNSS_MAX_MEASUREMENT) {
+ LOGD("measurement_count exceed the upper limit!");
+ break;
+ }
+
+ update_gnss_measurement(&gnssdata.measurements[num], &navicmeasurement[i]);
+ if (gnssdata.measurements[num].state == 0) {
+ gnssdata.measurements[num].pseudorange_rate_mps = 1;
+ }
+ gnssdata.measurement_count++;
+ LOGD("NAVIC measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+ num, i, gnssdata.measurements[num].svid);
+ }
+ }
+
+ memcpy(&gnssdata.clock , &gnss_clock, sizeof(gnss_clock));
+ LOGD("gnssdata.measurement_count = %zu, sizeof(gnssdata) = %lu", gnssdata.measurement_count, sizeof(gnssdata));
+ if (gnssdata.measurement_count > 0) {
+ ret = mnl2hal_gnss_measurements(&gnssdata);
+ LOGD("mnl2hal_gnss_measurements done ,ret = %d", ret);
+ }
+}
+
+static void get_gnss_navigation_event() {
+ LOGD("get_gnss_navigation_event begin");
+
+ int svid;
+ int i;
+ int ret;
+ GnssNavigationmessage gnss_navigation_msg;
+ gnss_nav_msg gnssnavigation;
+
+ // GPS
+ for (svid = 1; svid <= GPS_MAX_MEASUREMENT; svid++) {
+ ret = mtk_gnss_get_navigation_event(&gnss_navigation_msg, svid, 1);
+ if (ret == 0) {
+ LOGD("mtk_gnss_get_navigation_event GPS sv fail, svid = %d,[ret=%d]\n", svid, ret);
+ memset(&gnss_navigation_msg, 0, sizeof(GnssNavigationmessage));
+ }
+
+ memset(&gnssnavigation, 0, sizeof(gnss_nav_msg));
+ update_gnss_navigation(&gnssnavigation, &gnss_navigation_msg);
+ if(gnssnavigation.data_length <= sizeof(gnssnavigation.data)) {
+ memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GP_data, gnssnavigation.data_length);
+ } else {
+ memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GP_data, sizeof(gnssnavigation.data));
+ }
+
+ if (gps_raw_debug_mode) {
+ for (i = 0; i < 40; i++) {
+ LOGD("GPS sv gnssnavigation.data[%d] = %x, %p",
+ i, gnssnavigation.data[i], &gnssnavigation.data[i]);
+ }
+ }
+ ret = mnl2hal_gnss_navigation(gnssnavigation);
+ LOGD("GPS sv, mnl2hal_gnss_navigation done ,ret = %d", ret);
+ }
+
+ // glonass
+ for (svid = 1; svid <= 24; svid++) {
+ ret = mtk_gnss_get_navigation_event(&gnss_navigation_msg, svid, 16);
+ if (ret == 0) {
+ LOGD("mtk_gnss_get_navigation_event Glonass sv fail, svid = %d,[ret=%d]\n", svid, ret);
+ memset(&gnss_navigation_msg, 0, sizeof(GnssNavigationmessage));
+ }
+
+ memset(&gnssnavigation, 0, sizeof(gnss_nav_msg));
+ update_gnss_navigation(&gnssnavigation, &gnss_navigation_msg);
+ if(gnssnavigation.data_length <= sizeof(gnssnavigation.data)) {
+ memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GL_data, gnssnavigation.data_length);
+ } else {
+ memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GL_data, sizeof(gnssnavigation.data));
+ }
+ if (gps_raw_debug_mode) {
+ for (i = 0; i < 12; i++) {
+ LOGD("Glonass sv gnssnavigation.data[%d] = %x, %p",
+ i, gnssnavigation.data[i], &gnssnavigation.data[i]);
+ }
+ }
+ ret = mnl2hal_gnss_navigation(gnssnavigation);
+ LOGD("Glonass sv, mnl2hal_gnss_navigation done ,ret = %d", ret);
+ }
+
+ // beidou
+ for (svid = 1; svid <= 37; svid++) {
+ ret = mtk_gnss_get_navigation_event(&gnss_navigation_msg, svid, 32);
+ if (ret == 0) {
+ LOGD("mtk_gnss_get_navigation_event BD sv fail, svid = %d,[ret=%d]\n", svid, ret);
+ memset(&gnss_navigation_msg, 0, sizeof(GnssNavigationmessage));
+ }
+
+ memset(&gnssnavigation, 0, sizeof(gnss_nav_msg));
+ update_gnss_navigation(&gnssnavigation, &gnss_navigation_msg);
+ if(gnssnavigation.data_length <= sizeof(gnssnavigation.data)) {
+ memcpy(gnssnavigation.data, gnss_navigation_msg.uData.BD_data, gnssnavigation.data_length);
+ } else {
+ memcpy(gnssnavigation.data, gnss_navigation_msg.uData.BD_data, sizeof(gnssnavigation.data));
+ }
+ if (gps_raw_debug_mode) {
+ for (i = 0; i < 40; i++) {
+ LOGD("BD sv gnssnavigation.data[%d] = %x, %p",
+ i, gnssnavigation.data[i], &gnssnavigation.data[i]);
+ }
+ }
+ ret = mnl2hal_gnss_navigation(gnssnavigation);
+ LOGD("BD sv, mnl2hal_gnss_navigation done ,ret = %d", ret);
+ }
+
+ // galileo
+ for (svid = 1; svid <= 36; svid++) {
+ ret = mtk_gnss_get_navigation_event(&gnss_navigation_msg, svid, 4);
+ if (ret == 0) {
+ LOGD("mtk_gnss_get_navigation_event Galileo sv fail, svid = %d,[ret=%d]\n", svid, ret);
+ memset(&gnss_navigation_msg, 0, sizeof(GnssNavigationmessage));
+ }
+
+ memset(&gnssnavigation, 0, sizeof(gnss_nav_msg));
+ update_gnss_navigation(&gnssnavigation, &gnss_navigation_msg);
+ if(gnssnavigation.data_length <= sizeof(gnssnavigation.data)) {
+ memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GA_data, gnssnavigation.data_length);
+ } else {
+ memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GA_data, sizeof(gnssnavigation.data));
+ }
+ if (gps_raw_debug_mode) {
+ for (i = 0; i < 40; i++) {
+ LOGD("Galileo sv gnssnavigation.data[%d] = %x, %p",
+ i, gnssnavigation.data[i], &gnssnavigation.data[i]);
+ }
+ }
+ ret = mnl2hal_gnss_navigation(gnssnavigation);
+ LOGD("Galileo sv, mnl2hal_gnss_navigation done ,ret = %d", ret);
+ }
+}
+
+#endif
+
+#if ANDROID_MNLD_PROP_SUPPORT
+/*---------------------------------------------------------------------------*/
+#define MNL_CONFIG_STATUS "persist.vendor.radio.mnl.prop"
+static int get_prop(unsigned int index) {
+ // Read property
+ char result[PROPERTY_VALUE_MAX] = {0};
+ int ret = 0;
+ if (property_get(MNL_CONFIG_STATUS, result, NULL)) {
+ ret = result[index] - '0';
+ LOGD("gps.log: %s, %d\n", &result[index], ret);
+ } else {
+ if (index == 7) {
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+ LOGD_ENG("Config is not set yet, use default value");
+ }
+ return ret;
+}
+
+int get_gps_cmcc_log_enabled() {
+ int is_enabled = get_prop(6);
+ return is_enabled;
+}
+#endif
+static int gps_control_event_hdlr(int fd) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ main2gps_event cmd;
+ int read_len;
+
+ read_len = safe_recvfrom(fd, buff, sizeof(buff));
+ if (read_len <= 0) {
+ LOGE("gps_control_event_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+ return -1;
+ }
+
+ cmd = get_int(buff, &offset, sizeof(buff));
+ switch (cmd) {
+ case MAIN2GPS_EVENT_START: {
+ int delete_aiding_data_flags = get_int(buff, &offset, sizeof(buff));
+ LOGW("mnld version: %s", MNLD_VERSION);
+ // need to call mnld_gps_start_done() when GPS is started
+ mnld_gps_start(delete_aiding_data_flags);
+ break;
+ }
+ case MAIN2GPS_EVENT_STOP: {
+ // need to call mnld_gps_stop_done() when GPS is stopped
+ mnld_gps_stop();
+ break;
+ }
+#if defined(GPS_SUSPEND_SUPPORT)
+ case MAIN2GPS_EVENT_SUSPEND: {
+ mnld_gps_suspend();
+ break;
+ }
+ case MNL2GPS_EVENT_MNL_DO_RESUME_DONE: {
+ gps_device_rst_listener_thread_exit_and_join();
+ break;
+ }
+ case RST2GPS_EVENT_SUSPEND_TO_CLOSE: {
+ unsigned long curr_rst_listener_id = gps_controller_session_id_get();
+ unsigned long from_rst_listener_id =
+ (unsigned long)get_int(buff, &offset, sizeof(buff));
+
+ if (from_rst_listener_id == curr_rst_listener_id) {
+ bool okay;
+ okay = mnld_gps_try_suspend_to_close();
+ LOGD("RST2GPS_EVENT_SUSPEND_TO_CLOSE, from_sid = %lu, curr_sid = %lu, ok = %d",
+ from_rst_listener_id, curr_rst_listener_id, okay);
+ } else {
+ LOGW("RST2GPS_EVENT_SUSPEND_TO_CLOSE, from_sid = %lu, curr_sid = %lu, not match!",
+ from_rst_listener_id, curr_rst_listener_id);
+ }
+ break;
+ }
+ case MAIN2GPS_EVENT_SUSPEND_TO_CLOSE: {
+ bool okay;
+ okay = mnld_gps_try_suspend_to_close();
+ LOGD("MAIN2GPS_EVENT_SUSPEND_TO_CLOSE, curr_sid = %lu, ok = %d",
+ gps_controller_session_id_get(), okay);
+ break;
+ }
+#endif
+ case MAIN2GPS_DELETE_AIDING_DATA: {
+ int delete_aiding_data_flags = get_int(buff, &offset, sizeof(buff));
+ LOGW("mnld_gps_delete_aiding_data() before delete_aiding_data_flags=0x%x",
+ delete_aiding_data_flags);
+ // need to call mnld_gps_reset_done() when GPS is reset
+ mnld_gps_delete_aiding_data(delete_aiding_data_flags);
+ LOGW("mnld_gps_delete_aiding_data() after");
+ break;
+ }
+ case GPS2GPS_NMEA_DATA_TIMEOUT: {
+ // not to start nmea timer if only LINK user
+ // although send_ative_noitfy already add the protection, it's also needed here
+ // to handle race condition:
+ // 1. send_ative_noitfy send a GPS2GPS_NMEA_DATA_TIMEOUT msg
+ // 2. MAIN thread change user to FLP only, and mnld_fsm stop nmea timer
+ // 3. GPS2GPS_NMEA_DATA_TIMEOUT reach here, and restart the timer
+ // then, GPS2MAIN_EVENT_NMEA_TIMEOUT may be caused
+ mnld_gps_controller_mnl_nmea_timeout();
+ break;
+ }
+ default: {
+ LOGE("gps_control_event_hdlr() unknown cmd=%d", cmd);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static void gps_control_thread_timeout() {
+ if (mnld_timeout_ne_enabled() == false) {
+ LOGE("gps_control_thread_timeout() dump and exit.");
+ mnld_exiting = true;
+ gps_dbg_log_exit_flush(0);
+ mnld_block_exit();
+ } else {
+ LOGE("gps_control_thread_timeout() crash here for debugging");
+ CRASH_TO_DEBUG();
+ }
+}
+
+static void* gps_control_thread(void *arg) {
+ #define MAX_EPOLL_EVENT 50
+ timer_t hdlr_timer = init_timer(gps_control_thread_timeout);
+ struct epoll_event events[MAX_EPOLL_EVENT];
+ UNUSED(arg);
+
+ memset(events, 0x00, sizeof(events));
+ int epfd = epoll_create(MAX_EPOLL_EVENT);
+ if (epfd == -1) {
+ LOGE("gps_control_thread() epoll_create failure reason=[%s]%d",
+ strerror(errno), errno);
+ return 0;
+ }
+
+ if (epoll_add_fd(epfd, g_fd_gps) == -1) {
+ LOGE("gps_control_thread() epoll_add_fd() failed for g_fd_gps failed");
+ return 0;
+ }
+
+ while (1) {
+ int i;
+ int n;
+ memset(events, 0x00, sizeof(events));
+ LOGD("gps_control_thread wait");
+ n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+ if (n == -1) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ LOGE("gps_control_thread() epoll_wait failure reason=[%s]%d",
+ strerror(errno), errno);
+ return 0;
+ }
+ }
+ mnld_wake_lock_take();
+ start_timer(hdlr_timer, MNLD_GPS_HANDLER_TIMEOUT);
+ for (i = 0; i < n; i++) {
+ if (events[i].data.fd == g_fd_gps) {
+ if (events[i].events & EPOLLIN) {
+ gps_control_event_hdlr(g_fd_gps);
+ }
+ } else {
+ LOGE("gps_control_thread() unknown fd=%d",
+ events[i].data.fd);
+ }
+ }
+ stop_timer(hdlr_timer);
+ mnld_wake_lock_give();
+ }
+
+ LOGE("gps_control_thread() exit");
+ return 0;
+}
+
+int gps_control_gps_start(int delete_aiding_data_flags) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, MAIN2GPS_EVENT_START);
+ put_int(buff, &offset, delete_aiding_data_flags);
+ return safe_sendto(MNLD_GPS_CONTROL_SOCKET, buff, offset);
+}
+
+int gps_control_gps_stop() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, MAIN2GPS_EVENT_STOP);
+ return safe_sendto(MNLD_GPS_CONTROL_SOCKET, buff, offset);
+}
+
+int gps_control_gps_reset(int delete_aiding_data_flags) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, MAIN2GPS_DELETE_AIDING_DATA);
+ put_int(buff, &offset, delete_aiding_data_flags);
+ return safe_sendto(MNLD_GPS_CONTROL_SOCKET, buff, offset);
+}
+
+#if defined(GPS_SUSPEND_SUPPORT)
+int gps_control_gps_suspend() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, MAIN2GPS_EVENT_SUSPEND);
+ return safe_sendto(MNLD_GPS_CONTROL_SOCKET, buff, offset);
+}
+
+int gps_control_gps_suspend_to_close() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, MAIN2GPS_EVENT_SUSPEND_TO_CLOSE);
+ return safe_sendto(MNLD_GPS_CONTROL_SOCKET, buff, offset);
+}
+
+int gps_control_gps_suspend_to_close_by_rst(unsigned int listener_id) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, RST2GPS_EVENT_SUSPEND_TO_CLOSE);
+ put_int(buff, &offset, (int)listener_id);
+ return safe_sendto(MNLD_GPS_CONTROL_SOCKET, buff, offset);
+}
+
+int gps_control_gps_resume() {
+ char buff[1024] = {0};
+ int offset = 0;
+ LOGD("send MNL2GPS_EVENT_MNL_DO_RESUME_DONE\n");
+ put_int(buff, &offset, MNL2GPS_EVENT_MNL_DO_RESUME_DONE);
+ return safe_sendto(MNLD_GPS_CONTROL_SOCKET, buff, offset);
+}
+#endif
+
+int gps_control_init() {
+ pthread_t pthread_gps;
+
+ hasAlmanac();
+ g_fd_gps = socket_bind_udp_force(MNLD_GPS_CONTROL_SOCKET);
+ if (g_fd_gps < 0) {
+ LOGE("socket_bind_udp(MNLD_GPS_CONTROL_SOCKET) failed");
+ return -1;
+ }
+
+ pthread_create(&pthread_gps, NULL, gps_control_thread, NULL);
+
+ return 0;
+}
+
+// for kernel wakelock control when offload is enabled
+#if 1
+static int gps_kernel_wakelock_fd = C_INVALID_FD;
+static int gps_kernel_wakelock_to_take = 1;
+
+void gps_control_kernel_wakelock_init() {
+ if (gps_kernel_wakelock_fd != dsp_fd && dsp_fd >= 0) {
+ gps_kernel_wakelock_fd = dsp_fd;
+ LOGD("dsp_fd is opened, fellow wakelock to take = %d, dsp_fd = %d",
+ gps_kernel_wakelock_to_take, gps_kernel_wakelock_fd);
+ if (!gps_kernel_wakelock_to_take) {
+ gps_control_kernel_wakelock_give();
+ } else {
+ LOGD("dsp_fd is opened, wakelock is taken defaultly, no need to take again");
+ }
+ }
+}
+
+void gps_control_kernel_wakelock_uninit() {
+ gps_kernel_wakelock_fd = C_INVALID_FD;
+}
+
+void gps_control_kernel_wakelock_take() {
+ int ret, fd;
+ fd = gps_kernel_wakelock_fd;
+ gps_kernel_wakelock_to_take = 1;
+ if (fd >= 0) {
+ ret = ioctl(fd, COMBO_IOC_TAKE_GPS_WAKELOCK, NULL);
+ LOGD("take kernel wakelock, fd = %d, ret = %d", fd, ret);
+ } else {
+ LOGD("dsp_fd not opened, record wakelock to take = %d", gps_kernel_wakelock_to_take);
+ }
+}
+
+void gps_control_kernel_wakelock_give() {
+ int ret, fd;
+ fd = gps_kernel_wakelock_fd;
+ gps_kernel_wakelock_to_take = 0;
+ if (fd >= 0) {
+ ret = ioctl(fd, COMBO_IOC_GIVE_GPS_WAKELOCK, NULL);
+ LOGD("give kernel wakelock, fd = %d, ret = %d", fd, ret);
+ } else {
+ LOGD("dsp_fd not opened, record wakelock to take = %d", gps_kernel_wakelock_to_take);
+ }
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// META mode
+/*****************************************************************************/
+void linux_signal_handler(int signo) {
+ int ret = 0;
+ pthread_t self = pthread_self();
+ if (signo == SIGTERM) {
+ unsigned int gps_user = GPS_USER_UNKNOWN;
+ gps_user = mtk_gps_get_gps_user();
+ if ((gps_user & GPS_USER_APP) != 0) {
+ LOGD("Normal mode,sdcard storage send SIGTERM to mnld");
+ gps_dbg_log_state_set_output_disable();
+ if (mnld_is_gps_started_done()) {
+ ret = mtk_gps_set_debug_type(gps_debuglog_state);
+ if (MTK_GPS_ERROR== ret) {
+ LOGD("sdcard storage send SIGTERM to mnld, stop gpsdebuglog, mtk_gps_set_debug_type fail");
+ }
+ }
+ } else {
+ LOGD("Meta or factory or adb shell mode done");
+ if (gps_user & GPS_USER_META) {
+ mnld_gps_stop();
+ } else if (gps_user & GPS_USER_OFL_TEST) {
+ // flp_test2mnl_gps_start();
+ mnld_gps_start(FLAG_HOT_START);
+ }
+ exit_meta_factory = 1;
+ }
+ }
+#if defined(__ANDROID_OS__)
+ if(signo < 0) {
+ LOGD("Signal handler of %.8x -> error:signo negative signo:%d\n", (unsigned int)self, signo);
+ } else {
+ LOGD("Signal handler of %.8x -> %s\n", (unsigned int)self, sys_siglist[signo]);
+ }
+#endif
+}
+
+int linux_setup_signal_handler(void) {
+ struct sigaction actions;
+ int err;
+ /*the signal handler is MUST, otherwise, the thread will not be killed*/
+ memset(&actions, 0, sizeof(actions));
+ sigemptyset(&actions.sa_mask);
+ actions.sa_flags = 0;
+ actions.sa_handler = linux_signal_handler;
+ if ((err = sigaction(SIGTERM, &actions, NULL))) {
+ LOGD("register signal hanlder for SIGTERM: %s\n", strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+int mnld_factory_test_entry(int argc, char** argv) {
+ int res = 0;
+
+ LOGD("Meta or factory or adb shell mode");
+
+ in_meta_factory = 1;
+ res = unlink(NV_FILE);
+ LOGD("unlink NV_FILE, errno=%d, res=%d\n", errno, res);
+ MNLD_STRNCPY(gps_debuglog_file_name, LOG_FILE, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ gps_debuglog_state = MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD;
+ if (argc >= 4) {
+ if (!strncmp(argv[3], "od", 2)) {
+ LOGD("MNL is non-offload");
+ mnld_cfg.OFFLOAD_enabled = 0;
+ // factory_mnld_gps_start();
+ mnld_gps_start(FLAG_HOT_START);
+ } else if (!strncmp(argv[3], "ot", 2)) {
+ LOGD("MNL is offload, run on test mode");
+ // flp_test2mnl_gps_start();
+ mnld_gps_start(FLAG_HOT_START);
+ } else if (!strncmp(argv[2], "PDNTest", 7)) {
+ PDN_test_enable = atoi(argv[3]);
+ LOGD("PDN test start, option is %d\n",PDN_test_enable);
+ mnld_gps_start(FLAG_HOT_START);
+ } else if (!strncmp(argv[3], "log_ctrl", 8)) {
+ //meta log ctrl must set this argv[3] ,to make sure mnld auto run
+ LOGD("Meta mode for log_ctrl start\n");
+ gps_control_init();
+ mnld_init();
+ block_here();
+ } else {
+ LOGD("MNL is offload, for meta/factory mode");
+ // factory_mnld_gps_start();
+ mnld_gps_start(FLAG_HOT_START);
+ }
+ } else {
+ LOGD("MNL is offload, for meta/factory mode");
+ // factory_mnld_gps_start();
+ mnld_gps_start(FLAG_HOT_START);
+ }
+ while (1) {
+ usleep(100000);
+ if (exit_meta_factory == 1) {
+ LOGD("Meta or factory mode exit");
+ exit_meta_factory = 0;
+ in_meta_factory = 0;
+ exit(1);
+ }
+ LOGD("Meta or factory mode testing...");
+ }
+ in_meta_factory = 0;
+}
+
+#if defined(GPS_SUSPEND_SUPPORT)
+
+void gps_controller_session_id_update(void) {
+ g_gps_controller_session_id++;
+}
+
+unsigned long gps_controller_session_id_get(void) {
+ return g_gps_controller_session_id;
+}
+
+
+void* gps_device_rst_listener_main(void* arg) {
+ long ret = 0;
+ unsigned long session_id = (unsigned long)arg;
+ unsigned long latest_session_id = 0;
+ int exit_flag = pthread_rst_listener_need_exit_flag;
+
+ UNUSED(arg);
+
+ if (exit_flag) {
+ LOGW("start & exit @sid = %lu due to need exit", session_id);
+ } else {
+ LOGD("start @sid = %lu", session_id);
+ ret = ioctl(dsp_fd, COMBO_IOC_GPS_LISTEN_RST_EVT, 0);
+
+ // return 0 stands for WMT EE or GPS closed, otherwise it's signal
+ if (ret == 0) {
+ // Note: rst evt only be listened on SUSPEND or STARTING state
+ //
+ // 1. For STARTING state, we will update the session id, if rst happened
+ // on last session, not send RST2GPS_EVENT_SUSPEND_TO_CLOSE.
+ // If rst happened after RST2GPS_EVENT_SUSPEND_TO_CLOSE is sent,
+ // the handler will ignore it if find it comes from last session.
+ // So if rst happen on STARTING state, the behavious is same as
+ // before: Ther is no 1st DBTT and timeout NE.
+ //
+ // 2. For SUSPEND state, RST2GPS_EVENT_SUSPEND_TO_CLOSE is sent to
+ // make suspend to close. If START request come after this, it will
+ // start from close rather than suspend.
+ //
+ pthread_rst_listener_rst_detected_flag = true;
+ latest_session_id = gps_controller_session_id_get();
+ if (latest_session_id == session_id) {
+ //notify gps controller thread to do close and join me
+ if (-1==gps_control_gps_suspend_to_close_by_rst(session_id)) {
+ LOGE("gps_control_gps_suspend_to_close_by_rst fail");
+ }
+ }
+ }
+
+ LOGD("exit @sid = %lu, latest_id = %lu, ioctl ret = %ld, last_errno = %d, need exit = %d",
+ session_id, latest_session_id, ret, errno, pthread_rst_listener_need_exit_flag);
+ }
+
+ // Has an finite time to finish the join after this
+ pthread_rst_listernr_is_joinable = 1;
+ return NULL;
+}
+
+int gps_device_rst_listener_thread_init() {
+ pthread_rst_listener_need_exit_flag = 0;
+ pthread_rst_listener_rst_detected_flag = 0;
+ pthread_rst_listernr_is_joinable = 0;
+ pthread_create(&pthread_rst_listener, NULL,
+ gps_device_rst_listener_main, (void *)gps_controller_session_id_get());
+ return 0;
+}
+
+// the max total wait time will almost 2^CNT * interval
+#define GPS_DEVICE_RST_LISTENER_TRY_KILL_MAX_CNT (10)
+#define GPS_DEVICE_RST_LISTENER_TRY_KILL_POLL_INTERVAL_MS (1)
+
+int gps_device_rst_listener_thread_exit_and_join() {
+ int ret;
+ void *retval;
+ int try_kill_cnt = 0;
+ int wait_cnt = 0;
+ int wait_max = 0;
+
+ pthread_rst_listener_need_exit_flag = 1;
+ if (pthread_rst_listener != C_INVALID_TID) {
+
+ //Try multiple kill for signal lost or rst_listener not on cancellation point
+ while (!pthread_rst_listernr_is_joinable &&
+ (try_kill_cnt < GPS_DEVICE_RST_LISTENER_TRY_KILL_MAX_CNT)) {
+
+ try_kill_cnt++;
+ ret = pthread_kill(pthread_rst_listener, SIGUSR1);
+
+ //From man, pthread_kill returns 0 on success; returns an error number
+ //and no signal is sent.
+ if (ret != 0) {
+ LOGE("try kill cnt = %d, wait cnt = %d, ret = %d, no signal is sent, errno = %d",
+ try_kill_cnt, wait_cnt, ret, errno);
+ } else if (try_kill_cnt >= (GPS_DEVICE_RST_LISTENER_TRY_KILL_MAX_CNT/2)) {
+ //show log only when try cnt reach threshold
+ LOGD("try kill cnt = %d, wait cnt = %d, ret = %d, signal is sent done",
+ try_kill_cnt, wait_cnt, ret);
+ }
+
+ //To avoid too freqency kill
+ // for 1st kill, wait 1 intervals (total 1) for next kill
+ // for 2nd kill, wait 2 intervals (total 3) for next kill
+ // ...
+ // for Nth kill, wait 2^(N-1) intervals (total 2^N - 1) for join
+ // currently, N is 10, interval is 1ms, so max 10 kill and wait 1.023s
+ //wait_max = (int)pow(2, try_kill_cnt)
+ wait_max = wait_max * 2 + 1;
+ while (wait_cnt + 1 < wait_max) {
+ if (pthread_rst_listernr_is_joinable) {
+ break;
+ } else {
+ // wait some time and check joinable again
+ usleep(1000*GPS_DEVICE_RST_LISTENER_TRY_KILL_POLL_INTERVAL_MS);
+ }
+ wait_cnt++;
+ }
+ }
+
+ if (try_kill_cnt >= GPS_DEVICE_RST_LISTENER_TRY_KILL_MAX_CNT) {
+ LOGW("try kill cnt reach max = %d, wait cnt = %d/%d, join anyway",
+ try_kill_cnt, wait_cnt, wait_max);
+ } else {
+ LOGD("try kill cnt = %d, wait cnt = %d/%d, to be joinable",
+ try_kill_cnt, wait_cnt, wait_max);
+ }
+
+ //Join anyway, if signal doesn't arrive rst_listener,
+ // gps controller thread will block here and
+ // MNLD_GPS_HANDLER_TIMEOUT will assert it.
+ pthread_join(pthread_rst_listener, &retval);
+ LOGD("join done");
+
+ pthread_rst_listener = C_INVALID_TID;
+ }
+
+ return 0;
+}
+
+bool mnld_do_gps_suspend_resume(int fd, mnld_gps_do_hw_ctrl_opcode op) {
+ long ioctl_ret = -1;
+ bool is_okay = false;
+ unsigned long hw_suspend_mode = MNLD_GPS_HW_SUSPEND_MODE_DEEP_STOP;
+
+ if(mnld_gps_suspend_ext_is_enabled()) {
+ hw_suspend_mode = MNLD_GPS_HW_SUSPEND_MODE_CLK_EXT;
+ } else {
+ hw_suspend_mode = MNLD_GPS_HW_SUSPEND_MODE_DEEP_STOP;
+ }
+ if (MNLD_GPS_DO_HW_RESUME == op) {
+ ioctl_ret = ioctl(fd, COMBO_IOC_GPS_HW_RESUME, 0);
+ } else if (MNLD_GPS_DO_HW_SUSPEND == op) {
+ ioctl_ret = ioctl(fd, COMBO_IOC_GPS_HW_SUSPEND, hw_suspend_mode);
+ } else {
+ LOGW("(fd:%d)received unexpected opcode = %d, hw suspend mode: %lu", fd, op, hw_suspend_mode);
+ return false;
+ }
+
+ if (ioctl_ret == 0) {
+ LOGD("(fd:%d)op = %d, ioctl_ret = %ld, hw suspend mode: %lu\n", fd, op, ioctl_ret, hw_suspend_mode);
+ is_okay =true;
+ } else {
+ LOGW("(fd:%d)op = %d, ioctl_ret = %ld, err = %d, hw suspend mode: %lu\n", fd, op, ioctl_ret, errno, hw_suspend_mode);
+ is_okay = false;
+ }
+
+ return is_okay;
+}
+
+/* libmnl callback implementation */
+INT32 mtk_gps_sys_do_hw_suspend_resume(UINT32 bitmask) {
+ bool suspend_okay = true;
+ bool resume_okay = true;
+ bool suspend_okay_dsp2 = true;
+ bool resume_okay_dsp2 = true;
+ bool last_is_suspend_done;
+ bool meta_or_factory;
+
+ last_is_suspend_done = gps_controller_suspend_done_flag;
+ meta_or_factory = in_meta_factory;
+ LOGD("mnld_suspend_flag = %d, meta_or_factory = %d, libmnl_bitmask = 0x%x",
+ last_is_suspend_done, meta_or_factory, bitmask);
+
+ // Currently, no need to check the bitmask in mnld
+ if (last_is_suspend_done) {
+ //bitmask MNL_HW_SUSPEND_MASK_RESUME_FLAG should be set
+ gps_controller_suspend_done_flag = 0;
+ resume_okay = mnld_do_gps_suspend_resume(dsp_fd, MNLD_GPS_DO_HW_RESUME);
+ if((bitmask & MNL_HW_SUSPEND_MASK_L5_FLAG) && (dsp2_fd > 0)) {
+ resume_okay_dsp2 = mnld_do_gps_suspend_resume(dsp2_fd, MNLD_GPS_DO_HW_RESUME);
+ }
+ if (-1==gps_control_gps_resume()) {
+ LOGE("gps_control_gps_resume fail\r\n");
+ }
+ } else {
+ // No using GPS hw suspend/resume under meta or factory test
+ if (meta_or_factory) {
+ return MTK_GPS_ERROR;
+ }
+
+ //PMTK-like restart: bitmask MNL_HW_SUSPEND_MASK_RESTART_FLAG should be set
+ suspend_okay = mnld_do_gps_suspend_resume(dsp_fd, MNLD_GPS_DO_HW_SUSPEND);
+ if((bitmask & MNL_HW_SUSPEND_MASK_L5_FLAG) && (dsp2_fd > 0)) {
+ suspend_okay_dsp2 = mnld_do_gps_suspend_resume(dsp2_fd, MNLD_GPS_DO_HW_SUSPEND);
+ }
+ if (!suspend_okay || !suspend_okay_dsp2) {
+ //return error to notify libmnl to do re-MVCD if suspend fail
+ //it might be a normal case if suspend not ready on stpgps/firmware part
+ LOGW("mnld_suspend_flag = %d, libmnl_bitmask = 0x%x, suspend fail",
+ last_is_suspend_done, bitmask);
+ return MTK_GPS_ERROR;
+ }
+
+ resume_okay = mnld_do_gps_suspend_resume(dsp_fd, MNLD_GPS_DO_HW_RESUME);
+ if((bitmask & MNL_HW_SUSPEND_MASK_L5_FLAG) && (dsp2_fd > 0)) {
+ resume_okay_dsp2 = mnld_do_gps_suspend_resume(dsp2_fd, MNLD_GPS_DO_HW_RESUME);
+ }
+ }
+
+ if (!resume_okay || !resume_okay_dsp2) {
+ //Now resume fail should be impossible case except rst happened,
+ // if this case happened, NEMA timeout / start timeout / libmnl RX
+ // timeout will assert it.
+ LOGE("mnld_suspend_flag = %d, libmnl_bitmask = 0x%x, resume fail",
+ last_is_suspend_done, bitmask);
+ }
+ return MTK_GPS_SUCCESS;
+}
+#endif /* GPS_SUSPEND_SUPPORT */
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/gps_dbg_log.c b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/gps_dbg_log.c
new file mode 100644
index 0000000..7c08955
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/gps_dbg_log.c
@@ -0,0 +1,1699 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <sys/epoll.h>
+#include <pthread.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+#if defined(__ANDROID_OS__)
+#include <cutils/sockets.h>
+#include <cutils/properties.h>
+#endif
+
+#include "mtk_prop_util.h"
+
+#include "mnld_utile.h"
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#include "mnld.h"
+#include "mtk_gps.h"
+#include "mtk_gps_type.h"
+
+#include "gps_dbg_log.h"
+#include "mpe.h"
+#include "LbsLogInterface.h"
+
+#include "mtk_mnld_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "gps_dbg_log"
+
+/*Close the GPS debug log file, and rename to ".nma".
+ *fd: file descriptor, should be a global variable for NULL check;
+ *fn: Current writing file name;
+*/
+
+#define GPSLOG_FCLOSE(fd,fn) do {\
+ if (NULL != fd) {\
+ if (fclose(fd)) {\
+ LOGE("fclose fail(%s)", strerror(errno)); \
+ } \
+ fd = NULL;\
+ gps_log_file_rename(fn);\
+ property_set(GPS_LOG_PERSIST_FLNM, GPS_LOG_PERSIST_VALUE_NONE);\
+ }\
+} while (0)
+
+#ifndef MAX
+#define MAX(A,B) ((A)>(B)?(A):(B))
+#endif
+#ifndef MIN
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#endif
+
+#define GPSLog_TIMESTRING_LEN 25
+#define C_INVALID_TID (pthread_t)(-1) /*invalid thread id*/
+
+unsigned char gps_debuglog_state = MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD;
+
+//bit0: Output gps debug log to file(0:close 1:open)
+//bit1: Output gps debug log to socket(0:close 1:open)
+unsigned int log_mode_bitmap = MNLD_WRITE_LOG_TOFILE | MNLD_WRITE_LOG_SOCKET;
+
+unsigned int meta_logctrl = 0;
+
+char gps_debuglog_file_name[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = GPS_DBGLOG_FILE_NAME;
+char storagePath_mtklogger_set[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = GPS_DBGLOG_PATH;
+char storagePath[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = GPS_DBGLOG_PATH;
+
+static char log_filename_suffix[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = GPS_DBGLOG_FILE_NAME_SUFFIX;
+static char gsGpsLogFileName[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+static char gsGpsLogFileName_full[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+static char gsGpsLogFileName_full_socket[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+static int total_file_count = 0;
+static int Current_FileSize = 0;
+static int Filenum = 0;
+static int DirLogSize = 0;
+UINT32 g_dbglog_file_size_in_config = 0; //Max dbg log file size read from config file
+UINT32 g_dbglog_folder_size_in_config = 0; //Max dbg log folder size read from config file
+static int fg_create_dir_done = 0;
+pthread_mutex_t g_mnldMutex[MNLD_MUTEX_MAX];
+
+FILE* g_hLogFile = NULL;
+bool g_gpsdbglogThreadExit = true;
+bool g_pingpang_init = false;
+pthread_mutex_t FILE_WRITE_MUTEX;
+pthread_t pthread_dbg_log = C_INVALID_TID;
+
+#define PINGPANG_WRITE_LOCK 0
+#define PINGPANG_FLUSH_LOCK 1
+
+static SYNC_LOCK_T lock_for_sync[] = {{PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0},
+ {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 1}};
+
+// data
+#define DATA_MAX_SEND2HIDL (LBS_LOG_INTERFACE_BUFF_SIZE - LBS_LOG_INTERFACE_HEADER_SIZE)
+#define PINGPANG_BUFFER_SIZE (80*1024)
+#define GPSDBGLOG_EXIT_RETRY_SLEEP (20*1000) //20ms
+#define GPSDBGLOG_EXIT_RETRY_CNT (100) //Total retry time is 100*20ms
+#define GPSDBGLOG_EXIT_RETRY_SGL_INTERVAL (25) //send signal every 500ms
+#define GPSDBGLOG_EXIT_SIG (SIGRTMIN+1)
+
+// describle one single buffer
+typedef enum {
+ NOTINIT = 0,
+ WRITABLE, // the state which can swtich to writing state
+ WRITING, // means the buffer is writing
+ READABLE, // means mtklogger thread now can read this buffer and write data to flash
+ READING // means mtklogger thread is writing data to flash
+} buffer_state;
+
+typedef struct {
+ char* volatile next_write;
+ char* start_address_buffer1;
+ char* start_address_buffer2;
+ char* end_address_buffer1;
+ char* end_address_buffer2;
+ // int* p_buffer1_lenth_to_write;
+ // int* p_buffer2_lenth_to_write;
+ // buffer_state* p_buffer1_state;
+ // buffer_state* p_buffer2_state;
+ int volatile buffer1_lenth_to_write;
+ int volatile buffer2_lenth_to_write;
+ buffer_state volatile buffer1_state;
+ buffer_state volatile buffer2_state;
+ int num_loose;
+} ping_pang_buffer;
+// static buffer_state buffer1_state = NOTINIT;
+// static buffer_state buffer2_state = NOTINIT;
+// static int lenth_to_write_buffer1 = 0;
+// static int lenth_to_write_buffer2 = 0;
+
+
+mtk_socket_fd gpslogd_fd;
+
+static ping_pang_buffer ping_pang_buffer_body;
+
+// function related
+// called when mtklogger thread init if debugtype set true
+static INT32 create_debug_log_file();
+static INT32 mtklog_gps_set_debug_file(char* file_name);
+static INT32 gps_dbg_log_pingpang_init();
+// called in function mnl_sys_alps_nmea_output
+static INT32 gps_dbg_log_pingpang_copy(ping_pang_buffer* pingpang, const char* buffer, INT32 len);
+// called in mtklogger thread when it is need to write
+static INT32 gps_dbg_log_pingpang_write(ping_pang_buffer* pingpang, FILE* filp);
+// called when debugtype set 1 to 0 or mtklogger thread exit
+static INT32 gps_dbg_log_pingpang_free();
+// called when debugtype set 1 to 0 or mtklogger thread exit
+static INT32 gps_dbg_log_pingpang_flush(ping_pang_buffer* pingpang, FILE * filp);
+
+void gps_dbg_log_thread_exit(int sig_no);
+
+static void mnld_create_mutex( mnld_mutex_enum mutex_idx);
+
+static void mnld_destroy_mutex(mnld_mutex_enum mutex_idx);
+
+static void mnld_take_mutex(mnld_mutex_enum mutex_idx);
+
+static void mnld_give_mutex(mnld_mutex_enum mutex_idx);
+
+static INT32 gps_dbg_log_get_filename(char * path, char * filename) {
+ int i = 0;
+ if(path == NULL || filename == NULL) {
+ return -1;
+ }
+
+ if(strlen(path) > GPS_DEBUG_LOG_FILE_NAME_MAX_LEN) {
+ return -1;
+ }
+
+ for(i = strlen(path); i >= 0; i--) {
+ if(path[i] == '/') {//Find '/' from tail
+ MNLD_STRNCPY(filename,&path[i+1],GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ LOGD("Find filename %s from %s", filename, path);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+void gps_dbg_log_mode_set(unsigned int bitmap) {
+ log_mode_bitmap = bitmap;
+ LOGD("Set log_mode_bitmap:0x%x", log_mode_bitmap);
+}
+
+unsigned int gps_dbg_log_mode_get() {
+ LOGD("Get log_mode_bitmap:0x%x", log_mode_bitmap);
+ return log_mode_bitmap;
+}
+
+bool gps_dbg_log_output2file() {
+ if(log_mode_bitmap & MNLD_WRITE_LOG_TOFILE) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool gps_dbg_log_output2socket() {
+ if(log_mode_bitmap & MNLD_WRITE_LOG_SOCKET) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void gps_dbg_log_output2file_clean() {
+ log_mode_bitmap &= ~MNLD_WRITE_LOG_TOFILE;
+}
+
+void gps_dbg_log_output2socket_clean() {
+ log_mode_bitmap &= ~MNLD_WRITE_LOG_SOCKET;
+}
+
+// GPS log sender
+bool mnld2logd_open_gpslog(char* file) {
+ return LbsLogInterface_openLog(&gpslogd_fd, LBS_LOG_INTERFACE_LOG_CATEGORY_GPS_LOG, file);
+}
+
+bool mnld2logd_write_gpslog(char * data, int len) {
+ return LbsLogInterface_writeLog(&gpslogd_fd, LBS_LOG_INTERFACE_LOG_CATEGORY_GPS_LOG, data, len);
+}
+
+bool mnld2logd_close_gpslog(void) {
+ return LbsLogInterface_closeLog(&gpslogd_fd, LBS_LOG_INTERFACE_LOG_CATEGORY_GPS_LOG);
+}
+
+bool mnld2logd_write_gpslog_subpackage(char * data, int len) {
+ unsigned int n = 0;
+ unsigned int i = 0;
+ char buff[DATA_MAX_SEND2HIDL+1];
+
+ if ((len>PINGPANG_BUFFER_SIZE-2) || (len<=0)) {
+ LOGE("len = %d, wrong lenth, return", len);
+ return false;
+ }
+
+
+ n = (len + (DATA_MAX_SEND2HIDL-1))/DATA_MAX_SEND2HIDL;
+ for (i=0; i<n; i++) {
+ memset(buff, 0x0, sizeof(buff));
+ memcpy(buff, data+i*DATA_MAX_SEND2HIDL, MIN(DATA_MAX_SEND2HIDL,len-i*DATA_MAX_SEND2HIDL));
+ if (!mnld2logd_write_gpslog(buff, MIN(DATA_MAX_SEND2HIDL,len-i*DATA_MAX_SEND2HIDL))) {
+ LOGE("send gps log to HIDL fail(%s)", strerror(errno));
+ }
+ }
+ LOGD("send total %u bytes of gps log", len);
+ return true;
+}
+
+bool islog_ctrl_by_meta() {
+ if (meta_logctrl == META_LOGCTRL_DISABLE) {
+ return false;
+ }
+ return true;
+}
+
+// MPE log sender
+bool mnld2logd_open_mpelog(char* file) {
+ return LbsLogInterface_openLog(&gpslogd_fd, LBS_LOG_INTERFACE_LOG_CATEGORY_MPE_LOG, file);
+}
+
+bool mnld2logd_write_mpelog(char * data, int len) {
+ return LbsLogInterface_writeLog(&gpslogd_fd, LBS_LOG_INTERFACE_LOG_CATEGORY_MPE_LOG, data, len);
+}
+
+bool mnld2logd_close_mpelog(void) {
+ return LbsLogInterface_closeLog(&gpslogd_fd, LBS_LOG_INTERFACE_LOG_CATEGORY_MPE_LOG);
+}
+
+
+// DUMP log sender
+bool mnld2logd_open_dumplog(char* file) {
+ return LbsLogInterface_openLog(&gpslogd_fd, LBS_LOG_INTERFACE_LOG_CATEGORY_DUMP_LOG, file);
+}
+
+bool mnld2logd_write_dumplog(char * data, int len) {
+ return LbsLogInterface_writeLog(&gpslogd_fd, LBS_LOG_INTERFACE_LOG_CATEGORY_DUMP_LOG, data, len);
+}
+
+bool mnld2logd_close_dumplog(void) {
+ return LbsLogInterface_closeLog(&gpslogd_fd, LBS_LOG_INTERFACE_LOG_CATEGORY_DUMP_LOG);
+}
+
+static void mnld_create_mutex( mnld_mutex_enum mutex_idx){
+ // mutex index is not within the supported range
+ if (mutex_idx >= MNLD_MUTEX_MAX)
+ {
+ LOGD("mnld_create_mutex fail,mutex_idx error\n");
+ return;
+ }
+
+ if (pthread_mutex_init(&g_mnldMutex[mutex_idx], NULL))
+ {
+ LOGD("mnld_create_mutex fail(%s)\n", strerror(errno));
+ }
+}
+
+static void mnld_destroy_mutex(mnld_mutex_enum mutex_idx){
+
+ if (mutex_idx >= MNLD_MUTEX_MAX)
+ {
+ LOGD("mnld_destroy_mutex fail,mutex_idx error\n");
+ return;
+ }
+
+ if (pthread_mutex_destroy(&g_mnldMutex[mutex_idx]))
+ {
+ LOGD("mnld_destroy_mutex fail(%s)\n", strerror(errno));
+ }
+}
+
+static void mnld_take_mutex(mnld_mutex_enum mutex_idx){
+
+ if (mutex_idx >= MNLD_MUTEX_MAX)
+ {
+ LOGD("mnld_take_mutex fail,mutex_idx error\n");
+ return;
+ }
+
+ if (pthread_mutex_lock(&g_mnldMutex[mutex_idx]))
+ {
+ LOGD("mnld_take_mutex fail(%s)\n", strerror(errno));
+ }
+}
+
+static void mnld_give_mutex(mnld_mutex_enum mutex_idx){
+
+ if (mutex_idx >= MNLD_MUTEX_MAX)
+ {
+ LOGD("mnld_give_mutex fail,mutex_idx error\n");
+ return;
+ }
+
+ if (pthread_mutex_unlock(&g_mnldMutex[mutex_idx]))
+ {
+ LOGD("mnld_give_mutex fail(%s)\n", strerror(errno));
+ }
+}
+
+void gps_stop_dbglog_release_condition(void) {
+ g_gpsdbglogThreadExit = true;
+ release_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+ release_condition(&lock_for_sync[PINGPANG_FLUSH_LOCK]);
+ LOGD("exit while, gps_dbg_log thread exit\n");
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * gps_dbg_log_exit_flush
+ * DESCRIPTION
+ * Set exit flag to true and release condition let gps debug log thread exit.
+ * Will do GPS debug log flush and pingpang buffer free when thread exit.
+ * And wait seconds for flush(fwrite) blocking issue.
+ * PARAMETERS
+ * force_exit [IN] force exit mnld process, to avoid resource leakage issue.
+ * RETURNS
+ * None
+ *****************************************************************************/
+void gps_dbg_log_exit_flush(int force_exit) {
+ //int err = 0;
+ int cnt = 0;
+
+ gps_stop_dbglog_release_condition(); //Exit gps debug log thread, will flush gps debug log when exit
+ do {
+ if (pthread_dbg_log == C_INVALID_TID)//The thread has exited, will clear pthread_dbg_log at gps dbg log thread exit time
+ {
+ LOGD("gpsdbglog thread exit OK!");
+ break;
+ } else {//The thread still alive
+ if((cnt % GPSDBGLOG_EXIT_RETRY_SGL_INTERVAL == 0)) {
+ gps_stop_dbglog_release_condition(); //Exit gps debug log thread, will flush gps debug log when exit
+ }
+ usleep(GPSDBGLOG_EXIT_RETRY_SLEEP);
+ //Wait here to flush gps debug log, to avoid blocked in flush(fwrite)
+ cnt++;
+ }
+ } while(cnt < GPSDBGLOG_EXIT_RETRY_CNT);
+
+ if(cnt >= GPSDBGLOG_EXIT_RETRY_CNT) {
+ LOGW("GPS debug log may be not flushed completely!!!");
+ if(force_exit == 1) { //Process exit to avoid resource leakage issue, process will restart
+ LOGE("mnld will exit due to block at flushing GPS debug log!!!");
+ _exit(0);//Exit process directly, and mnld will be restarted. Some GPS debug log will be lost.
+ //Remove process dump due to it will take a long time to dump process backtraces when system loading is heavy, and easy to tigger false NE and EE.
+ }
+ }
+}
+
+void gps_log_file_rename(char *filename_cur) {
+ char tmp_suffix = 'a'-1;
+ char filename1[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+ char filename2[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+ unsigned int indx = 0;
+
+ if (filename_cur == NULL) {
+ LOGE("[gps_log_file_rename]: NULL Pointer!!!");
+ return;
+ }
+
+ MNLD_STRNCPY(filename1, filename_cur, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ indx = strlen(filename1) - strlen(LOG_FILE_WRITING_EXTEN_NAME);
+
+ if(strncmp(&(filename1[indx]), LOG_FILE_WRITING_EXTEN_NAME, strlen(LOG_FILE_WRITING_EXTEN_NAME)) != 0) {
+ LOGE("[gps_log_file_rename]: file extension name not match:%s", filename1);
+ return;
+ }
+
+ filename1[indx] = '\0';//remove ".nmac"
+
+ //Get new file name , storage into filename2
+ do {
+ if(tmp_suffix < 'a') {
+ MNLD_SNPRINTF(filename2, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s"LOG_FILE_EXTEN_NAME, filename1);
+ } else if(tmp_suffix <= 'z') {
+ MNLD_SNPRINTF(filename2, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s_%c"LOG_FILE_EXTEN_NAME, filename1, tmp_suffix);
+ } else {
+ MNLD_SNPRINTF(filename2, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s"LOG_FILE_EXTEN_NAME, filename1);
+ break;
+ }
+ tmp_suffix++;
+ } while (access(filename2, F_OK) == 0); //File has existed
+
+ LOGD("Writing file: %s, rename to:%s", filename_cur, filename2);
+ if(rename(filename_cur, filename2) != 0) {
+ LOGE("[gps_log_file_rename]:rename fail:%s", strerror(errno));
+ }
+ if(chmod(filename2, 0660) != 0) {
+ LOGE("[gps_log_file_chmod]:chmod fail:%s", strerror(errno));
+ }
+}
+
+#define MNLD_PATH_MAX_LENGTH GPS_DEBUG_LOG_FILE_NAME_MAX_LEN
+
+//If path not existed, will create it by folder;
+//Return value: 0 - Success, -1 - Fail
+int mnld_path_init(const char* data_path, const int length) {
+ int index = 0;
+ char dir[MNLD_PATH_MAX_LENGTH] = {0};
+
+ for(index=2;(index<length) && data_path[index]; index++) {
+ if(data_path[index] == '/') {
+ memset(dir, 0, MNLD_PATH_MAX_LENGTH);
+ strncpy(dir, data_path, index+1);
+ if (mkdir(dir, 00744) < 0) {
+ if (errno == EEXIST) {
+ LOGD("directory %s existed.\n", dir);
+ } else {
+ LOGE("mkdir (%s) failed: %s\n", dir, strerror(errno));
+ return -1;
+ }
+ } else {
+ LOGD("mkdir (%s) succeed\n", dir);
+ }
+ }
+ }
+ return 0;
+}
+
+/*************Check the debug file valid or not***************/
+int mnld_debug_file_check_init(char * dbg_file)
+{
+ char dirname[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+ int index = 0;
+
+ if(NULL == dbg_file) {
+ LOGE("[%s] NULL dbg_file\r\n",__func__);
+ return MTK_GPS_ERROR;
+ }
+
+ strncpy(dirname, dbg_file, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ for(index=strlen(dirname)-1;index>1;index--) {
+ if(dirname[index] == '/') {
+ break;
+ }
+ }
+ dirname[index+1] = '\0';
+
+ LOGD("dirname:%s\r\n",dirname);
+ MNLD_STRNCPY(storagePath, dirname, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ MNLD_STRNCPY(storagePath_mtklogger_set, dirname, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ if (0 != access(dirname, F_OK|R_OK)) { // Check if the dir exist, can read,return value 0:success, -1 : fail
+ LOGE("Access gps debug log dir(%s) fail(%s)!\r\n", dirname, strerror(errno));
+ if(ENOENT == errno) {//No such dir
+ LOGD("try to create it");
+ if (mnld_path_init(dirname, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN) == -1) { // mkdir ,if fail print the fail info to main log
+ LOGE("mkdir %s fail(%s)", dirname, strerror(errno));
+ return MTK_GPS_ERROR;
+ }
+ } else {
+ return MTK_GPS_ERROR;
+ }
+ }
+ return MTK_GPS_SUCCESS;
+}
+
+static int get_mtklog_path(char *logpath) {
+ char temp[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+ unsigned int len;
+
+ char* ptr;
+ ptr = strchr(logpath, ',');
+ if (ptr) {
+ MNLD_STRNCPY(temp, ptr + 1, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ LOGD("logpath for mtklogger socket msg: %s", temp);
+ } else {
+ LOGD("logpath for mtklogger socket msg has not ',': %s", temp);
+ MNLD_STRNCPY(logpath, LOG_FILE_PATH, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ return 0;
+ }
+
+ len = strlen(temp);
+ if (len != 0 && temp[len-1] != '/') {
+ temp[len++] = '/';
+ if (len < GPS_DEBUG_LOG_FILE_NAME_MAX_LEN) {
+ temp[len] = '\0';
+ }
+ }
+ if (len <= GPS_DEBUG_LOG_FILE_NAME_MAX_LEN - strlen(PATH_SUFFIX)) {
+ MNLD_SPRINTF(logpath, "%sdebuglogger/connsyslog/gpshost/", temp);
+ LOGD("get_mtklog_path:logpath is %s", logpath);
+ }
+
+ if (gps_dbg_log_output2file()) {
+ char mtklogpath[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+ if (len <= GPS_DEBUG_LOG_FILE_NAME_MAX_LEN-7) {
+ MNLD_SNPRINTF(mtklogpath, sizeof(mtklogpath), "%smtklog/connsyslog/", temp);
+ if (0 != access(mtklogpath, F_OK)) { // if mtklog dir is not exit, mkdir
+ LOGD("access dir error(%s), Try to create dir", mtklogpath);
+ if (mkdir(mtklogpath, 0775) == -1) {
+ MNLD_STRNCPY(logpath, LOG_FILE_PATH, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN); // if mkdir fail, set default path
+ LOGD("mkdir %s fail(%s), set default logpath(%s)", mtklogpath, strerror(errno), logpath);
+ }
+ }
+ }
+ }
+ return 1;
+}
+static int mode = 0;
+
+bool Mnld2Mtklogger_WriteDate(mtk_socket_fd* client_fd, char* msg, int len) {
+ if (msg == NULL || len > MNLD2MTKLOGGER_ANS_BUFF_SIZE) {
+ SOCK_LOGE("Mnld2Mtklogger_WriteDate() input parameter error");
+ return false;
+ }
+ pthread_mutex_lock(&client_fd->mutex);
+ if(!mtk_socket_client_connect(client_fd)) {
+ SOCK_LOGE("Mnld2Mtklogger_WriteDate() mtk_socket_client_connect() failed");
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ int _ret;
+ _ret = mtk_socket_write(client_fd->fd, msg, len);
+ if(_ret == -1) {
+ SOCK_LOGE("Mnld2Mtklogger_WriteDate() mtk_socket_write() failed, fd=%d err=[%s]%d",
+ client_fd->fd, strerror(errno), errno);
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return false;
+ }
+ mtk_socket_client_close(client_fd);
+ pthread_mutex_unlock(&client_fd->mutex);
+ return true;
+}
+
+int mtklogger2mnl_hdlr(int server_fd, mtk_socket_fd* client_fd) {
+ int ret = 0;
+ char ans[MNLD2MTKLOGGER_ANS_BUFF_SIZE] = {0};
+ char buff_msg[MTKLOGGER2MNLD_READ_BUFF_SIZE] = {0};
+
+ if (!islog_ctrl_by_meta()) {
+ LOGD("gps debug log not control by meta.");
+ ret = mtk_socket_read(server_fd, buff_msg, sizeof(buff_msg) - 1);
+ if(ret == -1) {
+ LOGE("mtk_socket_read() failed, server_fd=%d err=[%s]%d",
+ server_fd, strerror(errno), errno);
+ return false;
+ }
+
+ // response "msg,1" to mtklogger
+ MNLD_SNPRINTF(ans, sizeof(ans), "%s,1", buff_msg);
+ LOGD("notify client, recv %s from mtklogger, ans: %s\n", buff_msg, ans);
+ if (strstr(buff_msg, "set_storage_path")) { // buff is "set_storage_path,storagePath"
+ //close mnld log when MTKlogger active
+ gps_dbg_log_output2file_clean();
+ memset(storagePath_mtklogger_set, 0, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ MNLD_STRNCPY(storagePath_mtklogger_set, buff_msg, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ get_mtklog_path(storagePath_mtklogger_set);
+ Mnld2Mtklogger_WriteDate(client_fd, ans, strlen(ans));
+ } else if (!strncmp(buff_msg, "deep_start", 10)) {
+ time_t tm;
+ struct tm *p = NULL;
+ static char GPSLog_timestamp[GPSLog_TIMESTRING_LEN];
+
+ if (time(&tm)==((time_t)-1)) {
+ LOGE("time fail(%s)", strerror(errno));
+ }
+ p = localtime(&tm);
+ if(p == NULL) {
+ LOGE("Get localtime fail:[%s]%d", strerror(errno), errno);
+ return false;
+ }
+
+ // GPS debug log dir is not exit, mkdir, before add time string, return value 0:success, -1 : fail
+ if (gps_dbg_log_output2file()) {
+ if (0 != access(storagePath_mtklogger_set, F_OK)) {
+ LOGE("Create dir %s\r\n", strerror(errno));
+ if (mkdir(storagePath_mtklogger_set, 0775) == -1) {
+ // mkdir before GPSLog_%timestamp%,if fail print the fail info to main log
+ LOGE("mkdir %s fail(%s)", storagePath_mtklogger_set, strerror(errno));
+ }
+ }
+ }
+ memset(GPSLog_timestamp, 0x00, sizeof(GPSLog_timestamp));
+ MNLD_SNPRINTF(GPSLog_timestamp, sizeof(GPSLog_timestamp), "CSLog_%04d_%02d%02d_%02d%02d%02d",
+ 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday,
+ p->tm_hour, p->tm_min, p->tm_sec);
+
+ MNLD_SNPRINTF(storagePath, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s%s/", storagePath_mtklogger_set, GPSLog_timestamp);
+
+ // strncat(storagePath, GPSLog_timestamp, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+
+ LOGD("storagePath:%s\n", storagePath);
+
+ gps_dbg_log_state_set_output_enable();
+ LOGD("gps_debuglog_state:%d", gps_debuglog_state);
+
+ #if ANDROID_MNLD_PROP_SUPPORT
+ property_set(GPS_LOG_PERSIST_STATE, GPS_LOG_PERSIST_VALUE_ENABLE);
+ property_set(GPS_LOG_PERSIST_PATH, storagePath);
+ #endif
+ Mnld2Mtklogger_WriteDate(client_fd, ans, strlen(ans));
+
+ mode = 0;
+ MNLD_STRNCPY(gps_debuglog_file_name, storagePath, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ strncat(gps_debuglog_file_name, log_filename_suffix, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN - strlen(gps_debuglog_file_name));
+
+ LOGD("gps_debuglog_file_name:%s\n", gps_debuglog_file_name);
+
+ if (mnld_is_gps_or_ofl_started_done()) {
+ ret = mtk_gps_set_debug_type(gps_debuglog_state);
+ if (MTK_GPS_ERROR == ret) {
+ LOGE("deep_start,1,mtk_gps_set_debug_type fail");
+ } else {
+ LOGD("start gpsdbglog successfully\n");
+ }
+ fg_create_dir_done = 0;
+ release_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+ }
+ } else if (!strncmp(buff_msg, "deep_start,2", 12)) {
+ gps_dbg_log_state_set_output_enable();
+ LOGD("gps_debuglog_state:%d", gps_debuglog_state);
+
+ #if ANDROID_MNLD_PROP_SUPPORT
+ property_set(GPS_LOG_PERSIST_STATE, GPS_LOG_PERSIST_VALUE_ENABLE);
+ property_set(GPS_LOG_PERSIST_PATH, storagePath);
+ #endif
+ Mnld2Mtklogger_WriteDate(client_fd, ans, strlen(ans));
+
+ MNLD_STRNCPY(gps_debuglog_file_name, LOG_FILE, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ MNLD_STRNCPY(storagePath, LOG_FILE_PATH, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ if (mnld_is_gps_or_ofl_started_done()) {
+ ret = mtk_gps_set_debug_type(gps_debuglog_state);
+ if (MTK_GPS_ERROR == ret) {
+ LOGE("deep_start,2,mtk_gps_set_debug_type fail");
+ } else {
+ LOGD("start gpsdbglog successfully\n");
+ }
+ fg_create_dir_done = 0;
+ release_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+ }
+
+ mode = 1;
+ } else if (!strncmp(buff_msg, "deep_stop", 9)) {
+ gps_dbg_log_state_set_output_disable();
+ LOGD("gps_debuglog_state:%d", gps_debuglog_state);
+
+ #if ANDROID_MNLD_PROP_SUPPORT
+ property_set(GPS_LOG_PERSIST_STATE, GPS_LOG_PERSIST_VALUE_DISABLE);
+ property_set(GPS_LOG_PERSIST_PATH, GPS_LOG_PERSIST_VALUE_NONE);
+ #endif
+ Mnld2Mtklogger_WriteDate(client_fd, ans, strlen(ans));
+
+ if (mnld_is_gps_or_ofl_started_done()) {
+ ret = mtk_gps_set_debug_type(gps_debuglog_state);
+ if (MTK_GPS_ERROR== ret) {
+ LOGE("deep_stop, mtk_gps_set_debug_type fail");
+ } else {
+ LOGD("stop gpsdbglog successfully\n");
+ }
+ release_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+ }
+ #ifdef MTK_MPE_SUPPORT
+ mnl2mpe_set_log_path(storagePath, 0, 0);
+ #endif
+ mode = 0;
+ } else {
+ Mnld2Mtklogger_WriteDate(client_fd, ans, strlen(ans));
+ LOGE("unknown message: %s\n", buff_msg);
+ }
+ } else {
+ LOGD("gps debug log controled by meta.ignor cmd from mtklogger!");
+ }
+ return 0;
+}
+#ifdef MTK_MPE_SUPPORT
+void mtklogger_mped_reboot_message_update(void) {
+ if (gps_dbg_log_state_is_output_disabled()) {
+ mnl2mpe_set_log_path(storagePath, 0, mode);
+ } else if (gps_dbg_log_state_is_output_enabled()) {
+ mnl2mpe_set_log_path(storagePath, 1, mode);
+ }
+}
+#endif
+void* gps_dbg_log_thread(void* arg) {
+ LOGD("create: %p, arg = %p\r\n", (void *)pthread_self(), arg);
+ pthread_detach(pthread_self());
+
+ init_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+ init_condition(&lock_for_sync[PINGPANG_FLUSH_LOCK]);
+ if (gps_dbg_log_output2file()) {
+ GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);
+ }
+
+ if (gps_dbg_log_state_is_output_enabled()) {
+ create_debug_log_file();
+#ifdef MTK_MPE_SUPPORT
+ mnl2mpe_set_log_path(storagePath, 1, 0); //Notify MPE to enable log and pass the log path to MPE, the 3rd param is unused
+#endif
+ }
+
+ if (gps_dbg_log_output2file()) {
+ if ((access(storagePath, F_OK|R_OK|W_OK)) == 0) {
+ DirLogSize = gps_log_dir_check(storagePath);
+ }
+ }
+ while (!g_gpsdbglogThreadExit) {
+ get_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+ //LOGD("get_condition PINGPANG_WRITE_LOCK");
+ if (gps_dbg_log_state_is_output_enabled()) {
+ if ((fg_create_dir_done == 0) && (!g_gpsdbglogThreadExit)) {
+ mtklog_gps_set_debug_file(gps_debuglog_file_name);
+ #ifdef MTK_MPE_SUPPORT
+ mnl2mpe_set_log_path(storagePath, 1, 0);
+ #endif
+ }
+ if (gps_dbg_log_output2file()) {
+ INT32 count = 0;
+ if (0 != access(storagePath, F_OK|R_OK|W_OK)) { // return value 0:success, -1 : fail
+ LOGE("Access gps debug log dir fail(%s)!\r\n", strerror(errno));
+ GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full); // close file before open, if the file has been open.
+
+ if (mnld_is_gps_or_ofl_started_done()) {
+ if (MTK_GPS_ERROR == mtk_gps_set_debug_type(gps_debuglog_state)) {
+ LOGE("GPS_DEBUGLOG_DISABLE, mtk_gps_set_debug_type fail");
+ } else {
+ LOGD("GPS_DEBUGLOG_DISABLE, stop gpsdbglog successfully\n");
+ }
+ }
+ }
+ if (g_hLogFile != NULL) {
+ if (Current_FileSize + PINGPANG_BUFFER_SIZE > MAX_DBG_LOG_FILE_SIZE) {
+ //char tmpfilename[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN]={0};
+ Filenum++;
+ GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full); // close file before open, if the file has been open.
+ DirLogSize = DirLogSize + Current_FileSize;
+ MNLD_SNPRINTF(gsGpsLogFileName_full, sizeof(gsGpsLogFileName_full), "%s-%d", gsGpsLogFileName, Filenum);
+ strncat(gsGpsLogFileName_full, LOG_FILE_WRITING_EXTEN_NAME, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN - strlen(gsGpsLogFileName_full));
+#if ANDROID_MNLD_PROP_SUPPORT
+ char* property_str = strstr(gsGpsLogFileName_full, log_filename_suffix);
+ if (NULL!=property_str) {
+ property_set(GPS_LOG_PERSIST_FLNM, property_str);
+ } else {
+ LOGE("strstr fail\r\n");
+ }
+#endif
+ LOGD("MAX_DBG_LOG_FILE_SIZE:%d, Current_FileSize:%d, create file:%s", MAX_DBG_LOG_FILE_SIZE, Current_FileSize, gsGpsLogFileName_full);
+ g_hLogFile = fopen(gsGpsLogFileName_full, "w");
+ if (NULL == g_hLogFile) {
+ LOGE("open file fail, NULL == g_hLogFile, %s[%d]\r\n", strerror(errno), errno);
+ break;
+ }
+ if (DirLogSize > (int)(MAX_DBG_LOG_DIR_SIZE - MAX_DBG_LOG_FILE_SIZE)
+ || (total_file_count + Filenum) > GPS_DBG_LOG_FILE_NUM_LIMIT) {
+ DirLogSize = gps_log_dir_check(storagePath);
+ }
+
+ Current_FileSize = 0;
+ }
+ }
+ if (g_hLogFile != NULL) {
+ count = gps_dbg_log_pingpang_write(&ping_pang_buffer_body, g_hLogFile);
+ Current_FileSize = count + Current_FileSize;
+ }
+ } else {
+ if (!gps_dbg_log_pingpang_write(&ping_pang_buffer_body, NULL)) {
+ LOGE("send gpslog to gps logd fail");
+ }
+ }
+ } else {
+ if ((ping_pang_buffer_body.start_address_buffer1 != NULL)
+ && (ping_pang_buffer_body.start_address_buffer2 != NULL)) {
+ //LOGD("debuglog switch closed, flush gpsdbglog to flash from pingpang\r\n");
+ if ((gps_dbg_log_output2file() && (g_hLogFile != NULL)) ||gps_dbg_log_output2socket()) {
+ gps_dbg_log_pingpang_flush(&ping_pang_buffer_body, g_hLogFile);
+ }
+
+ gps_dbg_log_pingpang_free();
+ if (gps_dbg_log_output2file()) {
+ GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);
+ }
+
+ if (gps_dbg_log_output2socket()) {
+ if (!mnld2logd_close_gpslog())
+ LOGE("send close gpslog cmd to gps logd fail");
+ }
+ }
+ }
+ }
+
+ //if (g_hLogFile != NULL) {
+ if ((ping_pang_buffer_body.start_address_buffer1 != NULL)
+ && (ping_pang_buffer_body.start_address_buffer2 != NULL)) {
+ // flush
+ LOGD("thread will exit,flush gpsdbglog to flash from pingpang\r\n");
+ if ((gps_dbg_log_output2file() && (g_hLogFile != NULL)) || gps_dbg_log_output2socket()) {
+ gps_dbg_log_pingpang_flush(&ping_pang_buffer_body, g_hLogFile);
+ }
+
+ // free pingpang
+ //LOGD("free pingpang buffer now\r\n");
+ gps_dbg_log_pingpang_free();
+ }
+
+ if (gps_dbg_log_output2file()) {
+ GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);
+ LOGD("close log file\r\n");
+ }
+ if (gps_dbg_log_output2socket()) {
+ LOGD("send close gpslog cmd to gps logd\r\n");
+ if (!mnld2logd_close_gpslog())
+ LOGE("send close gpslog cmd to gps logd fail");
+ }
+ g_hLogFile = NULL;
+ //}
+
+ mnld_destroy_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+ pthread_dbg_log = C_INVALID_TID;
+ return NULL;
+}
+
+int gps_dbg_log_thread_init() {
+ mnld_create_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+ g_gpsdbglogThreadExit = false;
+ if (!g_pingpang_init && gps_dbg_log_state_is_output_enabled()) {
+ if (MTK_GPS_ERROR == gps_dbg_log_pingpang_init()) {
+ g_gpsdbglogThreadExit = true;
+ LOGE("gps dbg log pingpang init fail, thread exit");
+ }
+ }
+ if(gps_dbg_log_get_filename(gps_debuglog_file_name, log_filename_suffix) == -1) {
+ LOGE("Get filename fail: %s, %s", gps_debuglog_file_name, log_filename_suffix);
+ }
+ pthread_create(&pthread_dbg_log, NULL, gps_dbg_log_thread, NULL);
+ return 0;
+}
+
+int create_mtklogger2mnl_fd() {
+ static int socket_fd = 0;
+
+#if defined(__LINUX_OS__)
+ socket_fd = socket_local_server("gpslogd", SOCK_STREAM);
+#elif defined(__ANDROID_OS__)
+ socket_fd = socket_local_server("gpslogd", ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+#endif
+ if (socket_fd < 0) {
+ LOGE("create server fail(%s)", strerror(errno));
+ return -1;
+ }
+ LOGD("socket_fd = %d", socket_fd);
+
+ if (listen(socket_fd, 5) < 0) {
+ LOGE("listen socket fail(%s)", strerror(errno));
+ close(socket_fd);
+ return -1;
+ }
+
+ return socket_fd;
+}
+
+static int FindGPSlogFile(const char* Filename) {
+ int i;
+ int GPSlogNamelen = 0;
+
+ GPSlogNamelen = strlen(log_filename_suffix);
+
+ for (i = 0; i < GPSlogNamelen; i++) {
+ if (Filename[i]!= log_filename_suffix[i]) {
+ return MTK_GPS_ERROR;
+ }
+ }
+ return MTK_GPS_SUCCESS;
+}
+
+static int GetFileSize(const char *filename) {
+ char dir_filename[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+ struct stat statbuff;
+
+ memset(dir_filename, 0x00, sizeof(dir_filename));
+
+ if (NULL == filename) {
+ LOGE("[GetFileSize][error]: File name is NULL!!\r\n");
+ return 0;
+ }
+
+ // LOGD("[GetFileSize]File name:%s!\r\n", filename);
+ MNLD_SNPRINTF(dir_filename, sizeof(dir_filename), "%s%s", storagePath,
+ filename);
+
+ if (stat(dir_filename, &statbuff) < 0) {
+ LOGE("[GetFileSize][error]: open file(%s) state fail(%s)!\r\n", dir_filename, strerror(errno));
+ return 0;
+ } else {
+ return statbuff.st_size; // return the file size
+ }
+}
+
+#if 0
+static int CmpStrFile(char a[], char b[]) { // compare two log files
+ char *pa = a, *pb = b;
+ while (*pa == *pb) {
+ pa++;
+ pb++;
+ }
+ return (*pa - *pb);
+}
+#endif
+static int CmpFileTime(const char *filename1, const char *filename2) {
+ char dir_filename1[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+ char dir_filename2[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+ struct stat statbuff1;
+ struct stat statbuff2;
+
+ memset(dir_filename1, 0x00, sizeof(dir_filename1));
+ memset(dir_filename2, 0x00, sizeof(dir_filename2));
+
+ if (NULL == filename1 || NULL == filename2) {
+ LOGE("[CmpFileTime][error]: File name is NULL!!\r\n");
+ return 0;
+ }
+ // LOGD("[CmpFileTime]File name1:%s, filename2:%s!!\r\n", filename1, filename2);
+
+ MNLD_SNPRINTF(dir_filename1, sizeof(dir_filename1), "%s%s", storagePath, filename1);
+ MNLD_SNPRINTF(dir_filename2, sizeof(dir_filename2), "%s%s", storagePath, filename2);
+
+ if (stat(dir_filename1, &statbuff1) < 0) {
+ LOGD("[CmpFileTime][error]: open file(%s) state fail(%s)!!\r\n", dir_filename1, strerror(errno));
+ return 0;
+ }
+
+ if (stat(dir_filename2, &statbuff2) < 0) {
+ LOGD("[CmpFileTime][error]: open file(%s) state fail(%s)!!\r\n", dir_filename2, strerror(errno));
+ return 0;
+ }
+ return (statbuff1.st_mtime-statbuff2.st_mtime);
+}
+
+static INT32 create_debug_log_file() {
+ time_t tm;
+ struct tm *p = NULL;
+ char *gps_debuglog_file_name_format_str;
+
+ if (time(&tm)==((time_t)-1)) {
+ LOGE("time() fail(%s)!!\r\n", strerror(errno));
+ }
+ p = localtime(&tm);
+
+ if(p == NULL) {
+ LOGE("Get localtime fail:[%s]%d", strerror(errno), errno);
+ }
+ if (strlen((const char*)gps_debuglog_file_name) && (p != NULL)) { // if filename length > 0
+ // initialize debug log (use OPEN_ALWAYS to append debug log)
+ // GPS debug log dir is not exit, mkdir, return value 0:success, -1 : fail
+
+ if (gps_dbg_log_output2file()) {
+ char file_tree[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+ FILE* fd = NULL;
+ if (0 != access(storagePath, F_OK)) {
+ LOGD("Try to create dir(%s)\r\n", storagePath);
+ if (mkdir(storagePath, 0775) == -1) { // mkdir ,if fail print the fail info to main log
+ LOGE("mkdir %s fail(%s)", storagePath, strerror(errno));
+ return MTK_GPS_ERROR;
+ } else { // Create dir successfully
+ MNLD_SNPRINTF(file_tree, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%sfile_tree.txt", storagePath_mtklogger_set);
+ fd = fopen(file_tree, "at"); // Write the latest storage path to the end of file_tree.txt
+ if (NULL != fd) {
+ if(!fwrite(storagePath, 1, strlen(storagePath), fd)) {
+ LOGE("fwrite fail(%s)", strerror(errno));
+ }
+ if (!fwrite("\n", 1, 1, fd)) {
+ LOGE("fwrite fail(%s)", strerror(errno));
+ }
+ if (fclose(fd)) {
+ LOGE("fclose fail(%s)", strerror(errno));
+ }
+ } else {
+ LOGE("write file %s fail(%s)", file_tree, strerror(errno));
+ }
+ }
+ }
+ }
+
+ if (gps_dbg_log_state_is_encrypt_enabled()) {
+ gps_debuglog_file_name_format_str = "%s_%04d_%02d%02d_%02d%02d%02d.enc";
+ } else {
+ gps_debuglog_file_name_format_str = "%s_%04d_%02d%02d_%02d%02d%02d";
+ }
+
+ memset(gsGpsLogFileName, 0x00, sizeof(gsGpsLogFileName));
+ MNLD_SNPRINTF(gsGpsLogFileName, sizeof(gsGpsLogFileName), gps_debuglog_file_name_format_str, gps_debuglog_file_name,
+ 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday,
+ p->tm_hour, p->tm_min, p->tm_sec);
+ Filenum = 0;
+ if (gps_dbg_log_output2file()) {
+ GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full); // close file before open, if the file has been open.
+
+ MNLD_SNPRINTF(gsGpsLogFileName_full, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s"LOG_FILE_WRITING_EXTEN_NAME, gsGpsLogFileName);
+ }
+
+ if (gps_dbg_log_output2socket()) {
+ memset(gsGpsLogFileName_full_socket, 0, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ MNLD_SNPRINTF(gsGpsLogFileName_full_socket, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s", gsGpsLogFileName);
+ }
+#if ANDROID_MNLD_PROP_SUPPORT
+ char* property_str = strstr(gsGpsLogFileName_full, log_filename_suffix);
+ if (NULL!=property_str) {
+ property_set(GPS_LOG_PERSIST_FLNM, property_str);
+ } else {
+ LOGE("strstr fail\r\n");
+ }
+#endif
+
+ if (gps_dbg_log_output2file()) {
+ int LogFile_fd = open(gsGpsLogFileName_full, O_RDWR|O_NONBLOCK|O_CREAT, 0660);
+ if (LogFile_fd < 0) {
+ LOGE("open file fail(%s)", strerror(errno));
+ return MTK_GPS_ERROR;
+ } else {
+ int flags = fcntl(LogFile_fd, F_GETFL, 0);
+ if (fcntl(LogFile_fd, F_SETFL, flags|O_NONBLOCK) < 0) {
+ LOGD("fcntl logFile_fd fail");
+ }
+ if (fchmod(LogFile_fd, 0660) < 0) {
+ LOGD("fchmod logFile_fd fail");
+ }
+ g_hLogFile = fdopen(LogFile_fd, "w");
+ }
+ LOGD("file(%s) created successfully(0x%p)\r\n", gsGpsLogFileName_full, g_hLogFile);
+ }
+
+ if (gps_dbg_log_output2socket()) {
+ if (!mnld2logd_open_gpslog(gsGpsLogFileName_full_socket)) {
+ LOGE("file(%s) created fail\r\n", gsGpsLogFileName_full_socket);
+ } else {
+ LOGD("cmd create file(%s) send to gps debug daemon successfully", gsGpsLogFileName_full_socket);
+ }
+ }
+ Current_FileSize = 0;
+ fg_create_dir_done = 1;
+ return MTK_GPS_SUCCESS;
+ }
+ LOGD("create_debug_log_file fail");
+ return MTK_GPS_ERROR;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * mtklog_gps_set_debug_file
+ * DESCRIPTION
+ * Set the GPS debug file name(include the path name) in running time
+ * PARAMETERS
+ * file_name [IN] the debug file name needs to be changed
+ * RETURNS
+ * success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+static INT32 mtklog_gps_set_debug_file(char* file_name) {
+ if (NULL == file_name) { // Null pointer, return error
+ LOGE("file_name is NULL pointer! \r\n");
+ return MTK_GPS_ERROR;
+ }
+// The length of file_name is too long, return error
+ if (GPS_DEBUG_LOG_FILE_NAME_MAX_LEN <= (strlen(file_name) + 1)) {
+ LOGE("file_name is too long! \r\n");
+ return MTK_GPS_ERROR;
+ }
+
+ if (!g_pingpang_init) {
+ if (MTK_GPS_ERROR == gps_dbg_log_pingpang_init()) {
+ g_gpsdbglogThreadExit = true;
+ LOGE("gps dbg log pingpang init fail, thread exit");
+ }
+ }
+
+ if (MTK_GPS_ERROR == create_debug_log_file()) {
+ LOGD("create debug file(%s) error\r\n", file_name);
+ } else { // Create file success, check dir size
+ DirLogSize = gps_log_dir_check(storagePath);
+ }
+
+ return MTK_GPS_SUCCESS;
+}
+
+INT32 gps_log_dir_check(char * dirname) { // file size check
+ char temp_filename[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+ char OldGpsFile[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+ unsigned int DirLogSize_temp;
+ DIR *p_dir = NULL;
+ char OldFile[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+
+ struct dirent *p_dirent = NULL;
+ do {
+ if (0 != access(dirname, F_OK|R_OK)) { // Check if the dir exist, can read,return value 0:success, -1 : fail
+ LOGE("Access gps debug log dir fail(%s)!\r\n", strerror(errno));
+ return MTK_GPS_ERROR;
+ }
+
+ if ((p_dir = opendir(dirname)) == NULL) {
+ LOGE("open dir error(%s)\r\n", strerror(errno));
+ return MTK_GPS_ERROR;
+ } else {
+ LOGD("open dir sucess\r\n");
+ }
+
+ total_file_count = 0;
+ memset(OldGpsFile, 0x00, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN); // For compare file name,set a max char value
+ DirLogSize_temp = 0;
+
+ while ((p_dirent = readdir(p_dir)) && !g_gpsdbglogThreadExit) {
+ if (NULL == p_dirent || (0 != access(dirname, F_OK))) { // return value 0:success, -1 : fail
+ LOGE("Access gps debug log dir fail(%s)!\r\n", dirname);
+ break;
+ }
+ if (strcmp(p_dirent->d_name, ".") == 0 || strcmp(p_dirent->d_name, "..") == 0) { // Ignore the "." & ".."
+ continue; // while((p_dirent=readdir(p_dir)) && !g_gpsdbglogThreadExit)
+ }
+
+ if (GPS_DEBUG_LOG_FILE_NAME_MAX_LEN > strlen(p_dirent->d_name)) {
+ memset(temp_filename, 0 , GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ MNLD_STRNCPY(temp_filename, (void *)&p_dirent->d_name, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN - 1);
+ } else { // The length of d_name is too long, ignore this file
+ LOGD("d_name is too long!\r\n");
+ continue;
+ }
+
+ if (FindGPSlogFile(temp_filename) == MTK_GPS_SUCCESS) {
+ // LOGD("%s is a GPS debug log file!\r\n", temp_filename);
+
+ DirLogSize_temp = GetFileSize(temp_filename) + DirLogSize_temp;
+ total_file_count++;
+ if (strncmp(OldGpsFile, temp_filename, strlen(log_filename_suffix)) != 0) {
+ MNLD_STRNCPY(OldGpsFile, temp_filename, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN - 1);
+ LOGD("copy file name to OldGpsFile: %s, and continue\r\n", OldGpsFile);
+ continue; // while((p_dirent=readdir(p_dir)) && !g_gpsdbglogThreadExit)
+ }
+
+ if (CmpFileTime(temp_filename, OldGpsFile) < 0) { // Find the latest old file
+ memset(OldGpsFile, '\0', GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ MNLD_STRNCPY(OldGpsFile, temp_filename, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN - 1);
+ }
+ }
+ }
+ LOGD("DirLogSize_temp:%d, the latest OldGpsFile:%s!\r\n", DirLogSize_temp, OldGpsFile);
+ closedir(p_dir);
+ if (DirLogSize_temp >= (MAX_DBG_LOG_DIR_SIZE - MAX_DBG_LOG_FILE_SIZE)
+ || (total_file_count > GPS_DBG_LOG_FILE_NUM_LIMIT)) {
+ // Over size or the number of GPS debug log file over the limitation
+ // when OldGpsFile is small, it will cause many re-calculation in the second loop. need to avoid it.
+ INT32 ret = 0;
+
+ ret = GetFileSize(OldGpsFile);
+ memset(OldFile, 0x00, sizeof(OldFile));
+ MNLD_SNPRINTF(OldFile, sizeof(OldFile), "%s%s", storagePath, OldGpsFile);
+
+ LOGD("need delete OldFile:%s\r\n", OldFile);
+
+ if (remove(OldFile) != 0) { // Error handle
+ LOGW("Remove file %s error(%s)!\r\n", OldFile, strerror(errno));
+ }
+ DirLogSize_temp = DirLogSize_temp - ret;
+ }
+
+ LOGD("After remove file gpsdebug log dir size:%d!\r\n", DirLogSize_temp);
+ }while (((DirLogSize_temp > (MAX_DBG_LOG_DIR_SIZE - MAX_DBG_LOG_FILE_SIZE))
+ || (total_file_count > GPS_DBG_LOG_FILE_NUM_LIMIT)) && !g_gpsdbglogThreadExit);
+
+ if ((DirLogSize_temp <= (MAX_DBG_LOG_DIR_SIZE - MAX_DBG_LOG_FILE_SIZE)) && g_gpsdbglogThreadExit) {
+ LOGD("gps_log_dir_check interrupted size=%d!!\r\n", DirLogSize_temp);
+ }
+ LOGD("dir size:%d\r\n", DirLogSize_temp);
+ return DirLogSize_temp;
+}
+
+INT32 mnl_sys_alps_gps_dbg2file_mnld(const char* buffer, UINT32 length) {
+ //INT32 ret = MTK_GPS_SUCCESS;
+ //UINT32 count = 0;
+
+ if (mtk_gps_log_is_hide()) { //Forbit to print gps debug log
+ return MTK_GPS_SUCCESS;
+ }
+
+ if (gps_dbg_log_state_is_output_enabled() \
+ && (ping_pang_buffer_body.next_write != NULL)) {
+ gps_dbg_log_pingpang_copy(&ping_pang_buffer_body, buffer, length);
+ } else {
+ LOGD("will not copy to pingpang, DebugType:%d, buffer1:%p, buffer2:%p, g_hLogFile:%p\r\n",
+ gps_debuglog_state, ping_pang_buffer_body.start_address_buffer1,
+ ping_pang_buffer_body.start_address_buffer2, g_hLogFile);
+ }
+
+ return MTK_GPS_SUCCESS;
+}
+
+// if return error , gpsdbglog will not be writen
+static INT32 gps_dbg_log_pingpang_init() {
+ LOGD("gps_dbg_log_pingpang_init");
+ mnld_take_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+ memset(&ping_pang_buffer_body, 0x00, sizeof(ping_pang_buffer_body));
+ if (((ping_pang_buffer_body.start_address_buffer1 = calloc(1, PINGPANG_BUFFER_SIZE)) == NULL) || \
+ ((ping_pang_buffer_body.start_address_buffer2 = calloc(1, PINGPANG_BUFFER_SIZE)) == NULL)) {
+ if (ping_pang_buffer_body.start_address_buffer1 != NULL) {
+ free(ping_pang_buffer_body.start_address_buffer1);
+ ping_pang_buffer_body.start_address_buffer1 = NULL;
+ }
+ if (ping_pang_buffer_body.start_address_buffer2 != NULL) {
+ free(ping_pang_buffer_body.start_address_buffer2);
+ ping_pang_buffer_body.start_address_buffer2 = NULL;
+ }
+ mnld_give_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+ return MTK_GPS_ERROR;
+ }
+ // lenth_to_write_buffer1 = 0;
+ // lenth_to_write_buffer2 = 0;
+ ping_pang_buffer_body.buffer1_state = WRITING;
+ ping_pang_buffer_body.buffer2_state = WRITABLE;
+ // buffer1_state = WRITING;
+ // buffer2_state = WRITABLE;
+ // ping_pang_buffer_body.p_buffer1_lenth_to_write = &lenth_to_write_buffer1;
+ // ping_pang_buffer_body.p_buffer2_lenth_to_write = &lenth_to_write_buffer2;
+ ping_pang_buffer_body.end_address_buffer1 = ping_pang_buffer_body.start_address_buffer1 + PINGPANG_BUFFER_SIZE-2;
+ ping_pang_buffer_body.end_address_buffer2 = ping_pang_buffer_body.start_address_buffer2 + PINGPANG_BUFFER_SIZE-2;
+ ping_pang_buffer_body.next_write = ping_pang_buffer_body.start_address_buffer1;
+
+ g_pingpang_init = true;
+ mnld_give_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+ return MTK_GPS_SUCCESS;
+}
+
+static INT32 gps_dbg_log_pingpang_copy(ping_pang_buffer* pingpang, const char* buffer, INT32 len) {
+ if ((len >= PINGPANG_BUFFER_SIZE-1) || (len < 0)) {
+ LOGW("len = %d out of range\n", len);
+ return MTK_GPS_ERROR;
+ }
+ mnld_take_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+ if (pingpang->next_write == NULL) {
+ LOGW("next_write is NULL\n");
+ return MTK_GPS_ERROR;
+ }
+ if ((pingpang->buffer1_state == WRITING) && (pingpang->buffer2_state != WRITING)) {
+ if (pingpang->next_write+len > pingpang->end_address_buffer1) {
+ if (pingpang->buffer2_state == WRITABLE) {
+ pingpang->buffer1_lenth_to_write = pingpang->next_write - pingpang->start_address_buffer1;
+ pingpang->next_write = pingpang->start_address_buffer2;
+ pingpang->buffer2_state = WRITING;
+ pingpang->buffer1_state = READABLE;
+ release_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+ } else {
+ memset(pingpang->start_address_buffer1, 0x0, PINGPANG_BUFFER_SIZE);
+ pingpang->next_write = pingpang->start_address_buffer1;
+ pingpang->num_loose++;
+ LOGD("loose log ,num is %d \r\n", pingpang->num_loose);
+ }
+ }
+ } else if ((pingpang->buffer2_state == WRITING) && (pingpang->buffer1_state != WRITING)) {
+ if (pingpang->next_write+len > pingpang->end_address_buffer2) {
+ if (pingpang->buffer1_state == WRITABLE) {
+ pingpang->buffer2_lenth_to_write = pingpang->next_write - pingpang->start_address_buffer2;
+ pingpang->next_write = pingpang->start_address_buffer1;
+ pingpang->buffer1_state = WRITING;
+ pingpang->buffer2_state = READABLE;
+ release_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+ } else {
+ memset(pingpang->start_address_buffer2, 0x0, PINGPANG_BUFFER_SIZE);
+ pingpang->next_write = pingpang->start_address_buffer2;
+ pingpang->num_loose++;
+ LOGD("loose log ,num is %d \r\n", pingpang->num_loose);
+ }
+ }
+ } else {
+ LOGE("abnormal happens, buffer1_state=%d, buffer2_state=%d\r\n", pingpang->buffer1_state, pingpang->buffer2_state);
+ mnld_give_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+ return MTK_GPS_ERROR;
+ }
+
+ memcpy(pingpang->next_write, buffer, len);
+ pingpang->next_write += len;
+ mnld_give_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+ return MTK_GPS_SUCCESS;
+}
+
+bool gps_dbg_log_print_status(ping_pang_buffer* pingpang) {
+ LOGD("=====================================================\n");
+ LOGD("start_address_buffer1:%p\n", pingpang->start_address_buffer1);
+ LOGD("start_address_buffer2:%p\n", pingpang->start_address_buffer2);
+ LOGD("end_address_buffer1:%p\n", pingpang->end_address_buffer1);
+ LOGD("end_address_buffer2:%p\n", pingpang->end_address_buffer2);
+ LOGD("buffer1_lenth_to_write:%d\n", pingpang->buffer1_lenth_to_write);
+ LOGD("buffer2_lenth_to_write:%d\n", pingpang->buffer2_lenth_to_write);
+ LOGD("buffer1_state:%d\n", pingpang->buffer1_state);
+ LOGD("buffer2_state:%d\n", pingpang->buffer2_state);
+ LOGD("num_loose:%d\n", pingpang->num_loose);
+ return true;
+}
+// the real write to flash
+static INT32 gps_dbg_log_pingpang_write(ping_pang_buffer* pingpang, FILE* filp) {
+ int count = 0;
+ if ((pingpang->buffer1_state == READABLE)\
+ && (pingpang->buffer2_state != READABLE)\
+ && ((pingpang->buffer1_lenth_to_write) != 0)) {
+ pingpang->buffer1_state = READING;
+ if (filp != NULL) {
+ count = fwrite(pingpang->start_address_buffer1, 1, pingpang->buffer1_lenth_to_write, filp);
+ if (count==0) {
+ LOGE("fwrite fail(%s)", strerror(errno));
+ }
+ }
+
+ if (gps_dbg_log_output2socket()) {
+ if (mnld2logd_write_gpslog_subpackage(pingpang->start_address_buffer1, pingpang->buffer1_lenth_to_write)) {
+ if (filp == NULL) {
+ count = pingpang->buffer1_lenth_to_write;
+ }
+ } else {
+ count = 0;
+ }
+ }
+ memset(pingpang->start_address_buffer1, 0x0, PINGPANG_BUFFER_SIZE);
+ pingpang->buffer1_lenth_to_write = 0;
+ pingpang->buffer1_state = WRITABLE;
+ } else if ((pingpang->buffer2_state == READABLE)\
+ && (pingpang->buffer1_state != READABLE)\
+ && ((pingpang->buffer2_lenth_to_write) != 0)) {
+ pingpang->buffer2_state = READING;
+ if (filp != NULL) {
+ count = fwrite(pingpang->start_address_buffer2, 1, pingpang->buffer2_lenth_to_write, filp);
+ if (count == 0) {
+ LOGE("fwrite fail(%s)", strerror(errno));
+ }
+ }
+
+ if (gps_dbg_log_output2socket()) {
+ if (mnld2logd_write_gpslog_subpackage(pingpang->start_address_buffer2, pingpang->buffer2_lenth_to_write)) {
+ if (filp == NULL) {
+ count = pingpang->buffer2_lenth_to_write;
+ }
+ } else {
+ count = 0;
+ }
+ }
+ memset(pingpang->start_address_buffer2, 0x0, PINGPANG_BUFFER_SIZE);
+ pingpang->buffer2_lenth_to_write = 0;
+ pingpang->buffer2_state = WRITABLE;
+ } else {
+ return count;
+ }
+ LOGD("write to flash %d bytes\n", count);
+ return count;
+}
+
+// when mnl exit or mtklogger set 1 to 0, there is a need free pingpang buffer
+static INT32 gps_dbg_log_pingpang_free() {
+ mnld_take_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+ if (ping_pang_buffer_body.start_address_buffer1 != NULL) {
+ free(ping_pang_buffer_body.start_address_buffer1);
+ ping_pang_buffer_body.start_address_buffer1 = NULL;
+ }
+ if (ping_pang_buffer_body.start_address_buffer2 != NULL) {
+ free(ping_pang_buffer_body.start_address_buffer2);
+ ping_pang_buffer_body.start_address_buffer2 = NULL;
+ }
+ memset(&ping_pang_buffer_body, 0x00, sizeof(ping_pang_buffer_body));
+ // lenth_to_write_buffer1 = 0;
+ // lenth_to_write_buffer2 = 0;
+ // buffer1_state = NOTINIT;
+ // buffer2_state = NOTINIT;
+
+ g_pingpang_init = false;
+ LOGD("free pingpang buffer\r\n");
+ mnld_give_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+ return MTK_GPS_SUCCESS;
+}
+
+// when mnl exit or mtklogger set 1 to 0, there is a need to flush the data to flash from buffer
+static INT32 gps_dbg_log_pingpang_flush(ping_pang_buffer * pingpang, FILE* filp) {
+ char* tmp_next_write = NULL;
+ mnld_take_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+ tmp_next_write = pingpang->next_write;
+ if ((pingpang->buffer1_state == WRITING) && (pingpang->buffer2_state != WRITING)) {
+ if (pingpang->buffer2_state == READABLE) {
+ if (filp != NULL) {
+ if(!fwrite(pingpang->start_address_buffer2, 1, pingpang->buffer2_lenth_to_write, filp)) {
+ LOGE("fwrite fail(%s)", strerror(errno));
+ }
+ }
+
+ if (gps_dbg_log_output2socket()) {
+ mnld2logd_write_gpslog_subpackage(pingpang->start_address_buffer2, pingpang->buffer2_lenth_to_write);
+ }
+ }
+ if (filp != NULL) {
+ if (!fwrite(pingpang->start_address_buffer1, 1, tmp_next_write - pingpang->start_address_buffer1, filp)) {
+ LOGE("fwrite fail(%s)", strerror(errno));
+ }
+ }
+
+ if (gps_dbg_log_output2socket()) {
+ mnld2logd_write_gpslog_subpackage(pingpang->start_address_buffer1, tmp_next_write - pingpang->start_address_buffer1);
+ }
+ } else if ((pingpang->buffer2_state == WRITING) && (pingpang->buffer1_state != WRITING)) {
+ if (pingpang->buffer1_state == READABLE) {
+ if (filp != NULL) {
+ if (!fwrite(pingpang->start_address_buffer1, 1, pingpang->buffer1_lenth_to_write, filp)) {
+ LOGE("fwrite fail(%s)", strerror(errno));
+ }
+ }
+
+ if (gps_dbg_log_output2socket()) {
+ mnld2logd_write_gpslog_subpackage(pingpang->start_address_buffer1, pingpang->buffer1_lenth_to_write);
+ }
+ }
+ if (filp != NULL) {
+ if (!fwrite(pingpang->start_address_buffer2, 1, tmp_next_write - pingpang->start_address_buffer2, filp)) {
+ LOGE("fwrite fail(%s)", strerror(errno));
+ }
+ }
+
+ if (gps_dbg_log_output2socket()) {
+ mnld2logd_write_gpslog_subpackage(pingpang->start_address_buffer2, tmp_next_write - pingpang->start_address_buffer2);
+ }
+ } else {
+ LOGE("abnormal happens\r\n");
+ }
+ LOGD("flush gpsdbg to flash done!\r\n");
+ mnld_give_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+ return MTK_GPS_SUCCESS;
+}
+/*****************************************************************************
+ * FUNCTION
+ * gps_dbg_log_property_load
+ * DESCRIPTION
+ * Load properties to set gps_debuglog_state, storagePath, gps_debuglog_file_name and
+ * to rename the legacy gps debug log .nmac to .nma.
+ * The legacy gps debug log file name has been stored in GPS_LOG_PERSIST_PATH & GPS_LOG_PERSIST_FLNM
+ * PARAMETERS
+ * None
+ * RETURNS
+ * None
+ *****************************************************************************/
+void gps_dbg_log_property_load(void) {
+#if ANDROID_MNLD_PROP_SUPPORT
+ char path_result[PROPERTY_VALUE_MAX] = {0};
+ char flnm_result[PROPERTY_VALUE_MAX] = {0};
+ char state_result[PROPERTY_VALUE_MAX] = {0};
+ char filename_full[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+
+ if(property_get(GPS_LOG_PERSIST_STATE, state_result, NULL) != 0) {
+ //close mnld log when MTKlogger active
+ gps_dbg_log_output2file_clean();
+ if(state_result[0] == '1') {
+ gps_dbg_log_state_set_output_enable();
+ } else {
+ gps_dbg_log_state_set_output_disable();
+ }
+ }
+
+ if ((property_get(GPS_LOG_PERSIST_PATH, path_result, NULL) != 0)
+ && (strcmp(path_result, GPS_LOG_PERSIST_VALUE_NONE) != 0)) {
+ MNLD_STRNCPY(storagePath, path_result, PROPERTY_VALUE_MAX);
+ MNLD_SNPRINTF(gps_debuglog_file_name, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s%s", storagePath, log_filename_suffix);
+
+ if((property_get(GPS_LOG_PERSIST_FLNM, flnm_result, NULL) != 0)
+ && (strcmp(flnm_result, GPS_LOG_PERSIST_VALUE_NONE) != 0)
+ && ((strlen(path_result) + strlen(flnm_result)) < GPS_DEBUG_LOG_FILE_NAME_MAX_LEN)) {
+ MNLD_SNPRINTF(filename_full, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s%s", path_result, flnm_result);
+ LOGD("Rename legacy gpsdbgfile:%s", filename_full);
+ gps_log_file_rename(filename_full);
+ } else {
+ LOGE("length fail: %s(len:%d), %s(len:%d)", path_result, strlen(path_result), flnm_result, strlen(flnm_result));
+ }
+ }
+#endif
+}
+
+#define HAS_BITS(x, bits) (!!((x) & (bits)))
+#define SET_BITS(x, bits) ((x) |= (bits))
+#define CLR_BITS(x, bits) ((x) &= (~(bits)))
+
+void gps_dbg_log_state_init() {
+ //default value is: MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD
+ //gps_debuglog_state = MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD;
+
+ //create mutex here
+ mnld_create_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+}
+
+void gps_dbg_log_state_set_bitmask(unsigned int bitmask) {
+ mnld_take_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+ SET_BITS(gps_debuglog_state, bitmask);
+ mnld_give_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+}
+
+void gps_dbg_log_state_set_output_enable() {
+ mnld_take_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+ SET_BITS(gps_debuglog_state, MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD); //set 0x11
+ mnld_give_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+}
+
+void gps_dbg_log_state_set_output_disable() {
+ mnld_take_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+ CLR_BITS(gps_debuglog_state, MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNL); //clear 0x01, keep 0x10
+ mnld_give_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+}
+
+bool gps_dbg_log_state_is_output_enabled() {
+ bool is_enabled = false;
+
+ mnld_take_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+ // Note: currently 0x10 always be true, it equals "just check 0x01 is set"
+ is_enabled = (MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD ==
+ (gps_debuglog_state & MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD));
+ mnld_give_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+
+ return is_enabled;
+}
+
+bool gps_dbg_log_state_is_output_disabled() {
+ bool is_disabled = false;
+
+ mnld_take_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+ // Note: currently 0x10 always be true, it equals "just check 0x01 is clear"
+ is_disabled = (MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD ==
+ (gps_debuglog_state & MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD));
+ mnld_give_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+
+ return is_disabled;
+}
+
+void gps_dbg_log_state_set_encrypt_enable() {
+ mnld_take_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+ SET_BITS(gps_debuglog_state, MTK_GPS_ENCRYPT_DEBUG_MSG_BY_MNL);
+ mnld_give_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+}
+
+void gps_dbg_log_state_set_encrypt_disable() {
+ mnld_take_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+ CLR_BITS(gps_debuglog_state, MTK_GPS_ENCRYPT_DEBUG_MSG_BY_MNL);
+ mnld_give_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+}
+
+bool gps_dbg_log_state_is_encrypt_enabled() {
+ bool is_enabled = false;
+
+ mnld_take_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+ is_enabled = HAS_BITS(gps_debuglog_state, MTK_GPS_ENCRYPT_DEBUG_MSG_BY_MNL);
+ mnld_give_mutex(MNLD_MUTEX_GPS_DBG_LOG_STATE);
+
+ return is_enabled;
+}
+
+#define MNL_LOG_PRINTX_TAG "MNLD"
+void mnld_log_printx(mnld_log_level_t log_lv, int skip_chars, char *fmt, ...) {
+ char out_buf[1024];
+ va_list ap;
+ int log_len;
+ unsigned int enc_len = 0;
+
+ if (mtk_gps_log_is_hide()) {
+ return;
+ }
+
+ va_start(ap, fmt);
+ log_len = vsnprintf(out_buf, sizeof(out_buf)-1, fmt, ap);
+ if (log_len < 0) {
+ LOGE("vsnprintf fail(%s)!!\r\n", strerror(errno));
+ return;
+ }
+ va_end(ap);
+
+ if (mtk_gps_log_get_hide_opt() == 2) {
+
+ if (log_len > skip_chars) {
+ // Not encrypt the lead "skip_chars" of line, typically the 1st "X"
+ enc_len = mtk_gps_log_line_enc_inplace(&out_buf[1], (UINT32)(log_len - skip_chars));
+ }
+
+ if (enc_len == 0) {
+ LOGD("XXLOGX dropped: log_len=%d, skip_len=%d, enc_len=%d", log_len, skip_chars, enc_len);
+ return; //not ouptut due to nothing is encrypt
+ }
+
+ //LOGD("XXLOGX encrypt: log_len=%d, skip_len=%d, enc_len=%d", log_len, skip_chars, enc_len);
+ }
+#if defined(__ANDROID_OS__)
+ switch(log_lv) {
+ case LV_DEBUG:
+ __android_log_write(ANDROID_LOG_DEBUG, MNL_LOG_PRINTX_TAG, out_buf);
+ break;
+ case LV_VERBOSE:
+ __android_log_write(ANDROID_LOG_VERBOSE, MNL_LOG_PRINTX_TAG, out_buf);
+ break;
+ case LV_INFO:
+ __android_log_write(ANDROID_LOG_INFO, MNL_LOG_PRINTX_TAG, out_buf);
+ break;
+ case LV_WARN:
+ __android_log_write(ANDROID_LOG_WARN, MNL_LOG_PRINTX_TAG, out_buf);
+ break;
+ case LV_ERROR:
+ __android_log_write(ANDROID_LOG_ERROR, MNL_LOG_PRINTX_TAG, out_buf);
+ break;
+ default:
+ __android_log_write(ANDROID_LOG_DEBUG, MNL_LOG_PRINTX_TAG, out_buf);
+ }
+#elif defined(__LINUX_OS__)
+ switch(log_lv) {
+ case LV_DEBUG:
+ LOGD("[%s]%s", MNL_LOG_PRINTX_TAG, out_buf);
+ break;
+ case LV_VERBOSE:
+ LOGV("[%s]%s", MNL_LOG_PRINTX_TAG, out_buf);
+ break;
+ case LV_INFO:
+ LOGI("[%s]%s", MNL_LOG_PRINTX_TAG, out_buf);
+ break;
+ case LV_WARN:
+ LOGW("[%s]%s", MNL_LOG_PRINTX_TAG, out_buf);
+ break;
+ case LV_ERROR:
+ LOGE("[%s]%s", MNL_LOG_PRINTX_TAG, out_buf);
+ break;
+ default:
+ LOGD("[%s]%s", MNL_LOG_PRINTX_TAG, out_buf);
+ }
+#endif
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mnl2hal_interface.c b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mnl2hal_interface.c
new file mode 100644
index 0000000..5c2ab6d
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mnl2hal_interface.c
@@ -0,0 +1,926 @@
+#include "mnl2hal_interface.h"
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#include "mpe.h"
+#include "mnld.h"
+#include "errno.h"
+#include <inttypes.h> //PRId64
+
+#include "gps_controller.h"
+#include "mtk_mnld_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "mnl2hal"
+
+extern int mtk_gps_sys_strncmp(const char * str1,const char * str2);
+
+
+char g_mnl_hal_basic_msg_buf[HAL_MNL_BUFF_SIZE*2] = {0};
+cyclical_buffer_t g_mnl_hal_basic_cbuffer; // io - cyclic buffer
+
+char g_mnl_hal_ext_msg_buf[HAL_MNL_BUFF_SIZE*2] = {0};
+cyclical_buffer_t g_mnl_hal_ext_cbuffer; // io - cyclic buffer
+
+client_list g_hal_basic_client_list;
+client_list g_hal_ext_client_list;
+measurement_corrections corrections;
+
+void mnl_hal_basic_client_capability_query(int fd, mnl_hal_basic_client_cap *cap) {
+ if(cap == NULL) {
+ LOGE("NULL cap !!!!fd:%d", fd);
+ return;
+ }
+ client_ctx * pclient;
+ pclient = client_list_get_ctx_by_fd(&g_hal_basic_client_list, fd);
+ if(pclient == NULL) {
+ LOGE("Get basic context faild!!!!fd:%d", fd);
+ return;
+ }
+ memcpy(cap, &(pclient->client_cap.basic_client_cap), sizeof(mnl_hal_basic_client_cap));
+ DUMP_BASIC_CLIENT_CAP(cap);
+}
+
+void mnl_hal_basic_server_capability_query(int fd, mnl_hal_basic_server_cap *cap) {
+ if(cap == NULL) {
+ LOGE("NULL cap !!!!fd:%d", fd);
+ return;
+ }
+ client_ctx * pclient;
+ pclient = client_list_get_ctx_by_fd(&g_hal_basic_client_list, fd);
+ if(pclient == NULL) {
+ LOGE("Get basic context faild!!!!fd:%d", fd);
+ return;
+ }
+
+ memcpy(cap, &(pclient->server_cap.basic_server_cap), sizeof(mnl_hal_basic_server_cap));
+ DUMP_BASIC_SERVER_CAP(cap);
+}
+
+void mnl_hal_ext_client_capability_query(int fd, mnl_hal_ext_client_cap *cap) {
+ if(cap == NULL) {
+ LOGE("NULL cap !!!!fd:%d", fd);
+ return;
+ }
+ client_ctx * pclient;
+ pclient = client_list_get_ctx_by_fd(&g_hal_ext_client_list, fd);
+ if(pclient == NULL) {
+ LOGE("Get extension context faild!!!!fd:%d", fd);
+ return;
+ }
+ memcpy(cap, &(pclient->client_cap.ext_client_cap), sizeof(mnl_hal_ext_client_cap));
+ DUMP_EXT_CLIENT_CAP(cap);
+}
+
+void mnl_hal_ext_server_capability_query(int fd, mnl_hal_ext_server_cap *cap) {
+ if(cap == NULL) {
+ LOGE("NULL cap !!!!fd:%d", fd);
+ return;
+ }
+ client_ctx * pclient;
+ pclient = client_list_get_ctx_by_fd(&g_hal_ext_client_list, fd);
+ if(pclient == NULL) {
+ LOGE("Get extension context faild!!!!fd:%d", fd);
+ return;
+ }
+
+ memcpy(cap, &(pclient->server_cap.ext_server_cap), sizeof(mnl_hal_ext_server_cap));
+ DUMP_EXT_SERVER_CAP(cap);
+}
+
+//Tell client the support capability of mnld basic server interface
+int mnl2hal_basic_server_capability_update(int fd) {
+ LOGI("mnl2hal_basic_server_capability_update, fd:%d", fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ client_ctx * pclient = client_list_get_ctx_by_fd(&g_hal_basic_client_list, fd);
+ if(pclient == NULL) {
+ LOGE("Get client context faild!!!!");
+ return -1;
+ }
+ memset(&pclient->server_cap.basic_server_cap, 0, sizeof(mnl_hal_basic_server_cap));
+ pclient->server_cap.basic_server_cap.support_gnss = 1;
+
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+ put_int(buff, &offset, MNL2HAL_BASIC_CAP_SYNC);
+ put_binary(buff, &offset, (char *)&pclient->server_cap.basic_server_cap, (int)sizeof(mnl_hal_basic_server_cap));
+ return mnl2hal_basic_all(buff, offset);
+}
+
+//Tell client the support capability of mnld extension server interface
+int mnl2hal_ext_server_capability_update(int fd) {
+ LOGI("mnl2hal_ext_server_capability_update, fd:%d", fd);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ client_ctx * pclient;
+ pclient = client_list_get_ctx_by_fd(&g_hal_ext_client_list, fd);
+ if(pclient == NULL) {
+ LOGE("Get client context faild!!!!fd:%d", fd);
+ return -1;
+ }
+
+ memset(&(pclient->server_cap.ext_server_cap), 0, sizeof(mnl_hal_ext_server_cap));
+ pclient->server_cap.ext_server_cap.support_gnss = 1;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_EXT_CAP_SYNC);
+ put_binary(buff, &offset, (char *)&(pclient->server_cap.ext_server_cap), (int)sizeof(mnl_hal_ext_server_cap));
+
+ return mnl2hal_ext(buff, offset);
+}
+
+int mnl2hal_mnld_reboot() {
+ LOGD("mnl2hal_mnld_reboot");
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_MNLD_REBOOT);
+
+ return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_location(gps_location location) {
+ //LOGD("mnl2hal_location");
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_LOCATION);
+ put_binary(buff, &offset, (const char*)&location, sizeof(location));
+
+ return mnl2hal_basic(buff, offset);
+}
+
+int mnl2hal_gnss_status(gps_status status) {
+ LOGD("mnl2hal_gnss_status status=%d", status);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_GPS_STATUS);
+ put_binary(buff, &offset, (const char*)&status, sizeof(status));
+
+ return mnl2hal_basic(buff, offset);
+}
+
+int mnl2hal_gnss_status_one_client(gps_status status, int fd) {
+ LOGD("mnl2hal_gnss_status status=%d", status);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_GPS_STATUS);
+ put_binary(buff, &offset, (const char*)&status, sizeof(status));
+
+ return socket_tcp_send(fd, buff, offset);
+}
+
+int mnl2hal_gnss_sv(gnss_sv_info *sv) {
+ //LOGD("mnl2hal_gnss_sv num=%d", sv->num_svs);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_GPS_SV);
+ put_binary(buff, &offset, (const char*)sv, sizeof(gnss_sv_info));
+
+ return mnl2hal_basic(buff, offset);
+}
+
+int mnl2hal_nmea(int64_t timestamp, const char* nmea, int length) {
+ #ifdef CONFIG_GPS_ENG_LOAD
+ if ('$' == nmea[0] && (mtk_gps_sys_strncmp(&nmea[3],"RMC")==0)) {
+ LOGD("timestamp=%"PRId64", len=%d, nmea=%s",timestamp, length, nmea);
+ }
+ #endif
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_NMEA);
+ put_long(buff, &offset, timestamp);
+ put_string(buff, &offset, nmea, sizeof(buff));
+ put_int(buff, &offset, length);
+ return mnl2hal_basic(buff, offset);
+}
+
+int mnl2hal_nmea_done(void) {
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_NMEA_DONE);
+ LOGD("NMEA report done!");
+ return mnl2hal_basic(buff, offset);
+}
+
+int mnl2hal_gnss_measurements(gnss_data *data) {
+ LOGD_ENG("mnl2hal_gnss_measurements");
+ char buff[HAL_MNL_BUFF_SIZE_SND] = {0};
+ int offset = 0;
+
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_GNSS_MEASUREMENTS);
+ put_binary(buff, &offset, (const char*)&data, sizeof(data));
+
+ return mnl2hal_basic( buff, offset);
+}
+
+int mnl2hal_gnss_navigation(gnss_nav_msg msg) {
+ LOGD_ENG("mnl2hal_gnss_navigation");
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_GNSS_NAVIGATION);
+ put_binary(buff, &offset, (const char*)&msg, sizeof(msg));
+
+ return mnl2hal_ext( buff, offset);
+}
+
+
+int mnl2hal_request_wakelock(int fd) {
+ LOGD_ENG("mnl2hal_request_wakelock");
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_REQUEST_WAKELOCK);
+
+ return mnl2hal_ext( buff, offset);
+}
+
+int mnl2hal_release_wakelock(int fd) {
+ LOGD_ENG("mnl2hal_release_wakelock");
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_RELEASE_WAKELOCK);
+
+ return mnl2hal_ext( buff, offset);
+}
+
+int mnl2hal_request_utc_time(int fd) {
+ LOGD("mnl2hal_request_utc_time");
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_REQUEST_UTC_TIME);
+
+ return mnl2hal_ext( buff, offset);
+}
+
+int mnl2hal_request_data_conn(struct sockaddr_storage addr, agps_type type) {
+ LOGD("mnl2hal_request_data_conn");
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_REQUEST_DATA_CONN);
+ put_binary(buff, &offset, (const char*)&addr, sizeof(addr));
+ put_int(buff, &offset, type);
+
+ return mnl2hal_ext( buff, offset);
+}
+
+int mnl2hal_release_data_conn(agps_type type) {
+ LOGD("mnl2hal_release_data_conn");
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_RELEASE_DATA_CONN);
+ put_int(buff, &offset, type);
+
+ return mnl2hal_ext( buff, offset);
+}
+
+int mnl2hal_request_ni_notify(int session_id, agps_ni_type ni_type,
+ agps_notify_type type, const char* requestor_id,
+ const char* client_name, ni_encoding_type requestor_id_encoding,
+ ni_encoding_type client_name_encoding) {
+ LOGD("mnl2hal_request_ni_notify");
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_REQUEST_NI_NOTIFY);
+ put_int(buff, &offset, session_id);
+ put_int(buff, &offset, type);
+ put_string(buff, &offset, requestor_id, sizeof(buff));
+ put_string(buff, &offset, client_name, sizeof(buff));
+ put_int(buff, &offset, requestor_id_encoding);
+ put_int(buff, &offset, client_name_encoding);
+ put_int(buff, &offset, ni_type);
+
+ return mnl2hal_ext( buff, offset);
+}
+
+int mnl2hal_request_set_id(request_setid flags) {
+ LOGD("mnl2hal_request_set_id flag=0x%x", flags);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_REQUEST_SET_ID);
+ put_int(buff, &offset, flags);
+
+ return mnl2hal_ext( buff, offset);
+}
+
+int mnl2hal_request_ref_loc(request_refloc flags) {
+ LOGD("mnl2hal_request_ref_loc flag=0x%x", flags);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_REQUEST_REF_LOC);
+ put_int(buff, &offset, flags);
+
+ return mnl2hal_ext( buff, offset);
+}
+
+int mnl2hal_vzw_debug_screen_output(const char* str) {
+ LOGD("mnl2hal_vzw_debug_screen_output, str=%s", str);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_VZW_DEBUG_OUTPUT);
+ put_string(buff, &offset, str, sizeof(buff));
+
+ return mnl2hal_ext( buff, offset);
+}
+
+int mnl2hal_update_gnss_name(const char* str, int len) {
+ LOGD("mnl2hal_update_gnss_name, str=%s, len=%d", str, len);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_UPDATE_GNSS_NAME);
+ put_int(buff, &offset, len);
+ put_string(buff, &offset, str, sizeof(buff));
+
+ return mnl2hal_ext( buff, offset);
+}
+
+int mnl2hal_request_nlp(bool type, bool fgemergency) {
+ LOGD("mnl2hal_request_nlp, type=%d, flag=%d", type, fgemergency);
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_REQUEST_NLP);
+ put_byte(buff, &offset, type);
+ put_byte(buff, &offset, fgemergency);
+
+ return mnl2hal_ext( buff, offset);
+}
+
+int mnl2hal_nfw_notify(nfw_notification *nfw_notify) {
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ if(mnld_show_icon_get() == 0) {
+ LOGW("Stop to notify, AGPS forbit to show icon");
+ return 0;
+ }
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_NFW_NOTIFY);
+ put_binary(buff, &offset, (const char*)nfw_notify, sizeof(nfw_notification));
+
+ return mnl2hal_ext( buff, offset);
+}
+
+int mnl2hal_agps_location(mnl_hal_agps_location *location) {
+ //LOGD("mnl2hal_agps_location");
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+ put_int(buff, &offset, MNL2HAL_AGPS_LOCATION);
+ put_binary(buff, &offset, (const char*)location, sizeof(mnl_hal_agps_location));
+
+ return mnl2hal_ext(buff, offset);
+}
+
+// -1 means failure
+int create_hal2mnl_basic_fd() {
+ int fd = socket_tcp_server_bind_local_force(true, MTK_HAL2MNL_BASIC_SERVER);
+ if(fd != -1) {
+ socket_set_blocking(fd, 0); //Set as non-blocking
+ }
+ mnld_buffer_initialize(&g_mnl_hal_basic_cbuffer, g_mnl_hal_basic_msg_buf, sizeof(g_mnl_hal_basic_msg_buf));
+ memset(&g_hal_basic_client_list, 0, sizeof(g_hal_basic_client_list));
+ return fd;
+}
+
+// -1 means failure
+int create_hal2mnl_ext_fd() {
+ int fd = socket_tcp_server_bind_local_force(true, MTK_HAL2MNL_EXT_SERVER);
+ if(fd != -1) {
+ socket_set_blocking(fd, 0); //Set as non-blocking
+ }
+ mnld_buffer_initialize(&g_mnl_hal_ext_cbuffer, g_mnl_hal_ext_msg_buf, sizeof(g_mnl_hal_ext_msg_buf));
+ memset(&g_hal_ext_client_list, 0, sizeof(g_hal_ext_client_list));
+ return fd;
+}
+
+void hal2mnl_basic_server_hdlr(int fd, int epfd) {
+ int new_fd = socket_tcp_server_new_connect(fd);
+ if(new_fd == -1) {
+ LOGE("socket basic new client connection failure");
+ } else {
+ socket_set_blocking(new_fd, 0); //Set as non-blocking
+ if(client_list_add(&g_hal_basic_client_list, new_fd)) {
+ epoll_add_fd(epfd, new_fd);
+ if(mnl2hal_basic_server_capability_update(new_fd) == -1) { //Sync mnld basic interface's capability to server
+ LOGE("mnl2hal_basic_server_capability_update fail!!!");
+ }
+ LOGW("socket new client connected fd=[%d] list num=[%d]", new_fd, g_hal_basic_client_list.num);
+ } else {
+ LOGE("gnssadp_epoll_at_server_hdlr() client num is reached to max");
+ close(new_fd);
+ }
+ }
+}
+
+void hal2mnl_ext_server_hdlr(int fd, int epfd) {
+ int new_fd = socket_tcp_server_new_connect(fd);
+ if(new_fd == -1) {
+ LOGE("socket ext new client connection failure");
+ } else {
+ socket_set_blocking(new_fd, 0); //Set as non-blocking
+ if(g_hal_basic_client_list.num > 0) { //Connect to extension interface, only when have basic client connection
+ if(client_list_add(&g_hal_ext_client_list, new_fd)) {
+ epoll_add_fd(epfd, new_fd);
+ mnld_gps_update_name();
+ if(mnl2hal_ext_server_capability_update(new_fd) == -1) { //Sync mnld extension interface's capability to server
+ LOGW("mnl_hal_ext_cap_sync fail!!!");
+ }
+ LOGD("new externsion client connected, fd=[%d] ext num=[%d], basic num=[%d]"
+ , new_fd, g_hal_ext_client_list.num, g_hal_basic_client_list.num);
+ return; //Return directly, when add client successfully
+ }
+ }
+ LOGE("Can't connect to externsion client, fd=[%d] ext num=[%d], basic num=[%d]"
+ , new_fd, g_hal_ext_client_list.num, g_hal_basic_client_list.num);
+ close(new_fd);
+ }
+ return;
+}
+
+void hal2mnl_basic_client_hdlr(int fd, hal2mnl_basic_interface* hdlr) {
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ char buff_read[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ int ver;
+ hal2mnl_cmd cmd;
+ int read_len = 0;
+ int ret = 0;
+ int msg_len = 0;
+ int ret_len = 0;
+
+ read_len = read(fd, buff_read, sizeof(buff));
+ if (read_len <= 0) { //Client Closed
+ hal_gnss_stop(fd);
+ hal_gnss_cleanup(fd);
+ hal_raw_meas_gps_stop(fd);
+ client_list_remove(&g_hal_basic_client_list, fd);
+ close(fd);
+ LOGE("hal2mnl_basic_client_hdlr() safe_recvfrom() failed read_len=%d, client num:%d, %s", read_len, g_hal_basic_client_list.num, strerror(errno));
+ return;
+ }
+
+ mnld_put_msg_to_cycle(&g_mnl_hal_basic_cbuffer, buff_read, read_len);
+
+ while((ret_len = mnld_get_one_msg(&g_mnl_hal_basic_cbuffer, buff)) > 0) {
+ offset = 0;
+ msg_len = get_int(buff, &offset, sizeof(buff)); //Get message length
+ LOGD("msg len:%d, get len:%d, fd:%d", msg_len, ret_len, fd);
+ for(int i=0;i<ret_len;i++) {
+ LOGD(" 0x%x", buff[i]);
+ }
+ LOGD("=========================");
+ ver = get_int(buff, &offset, sizeof(buff));
+ UNUSED(ver);
+ cmd = get_int(buff, &offset, sizeof(buff));
+
+ switch (cmd) {
+
+ case HAL2MNL_GPS_INIT: {
+ if (hdlr->gnss_init) {
+ hdlr->gnss_init(fd);
+ } else {
+ LOGE("hal2mnl_basic_hdlr() gnss_init is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_GPS_START: {
+ if (hdlr->gnss_start) {
+ hdlr->gnss_start(fd);
+ } else {
+ LOGE("hal2mnl_basic_hdlr() gnss_start is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_GPS_STOP: {
+ if (hdlr->gnss_stop) {
+ hdlr->gnss_stop(fd);
+ } else {
+ LOGE("hal2mnl_basic_hdlr() gnss_stop is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_GPS_CLEANUP: {
+ if (hdlr->gnss_cleanup) {
+ hdlr->gnss_cleanup(fd);
+ } else {
+ LOGE("hal2mnl_basic_hdlr() gnss_cleanup is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_GPS_MEASUREMENT: {
+ if (hdlr->set_measurement_enable) {
+ bool enabled = get_int(buff, &offset, sizeof(buff));
+ hdlr->set_measurement_enable(enabled, fd);
+ } else {
+ LOGE("hal2mnl_basic_hdlr() set_measurement_enable is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_BASIC_CAP_SYNC: {
+ if(hdlr->client_capability_update) {
+ mnl_hal_basic_client_cap cap;
+ memset(&cap, 0, sizeof(cap));
+ get_binary(buff, &offset, (char *)&cap, sizeof(buff), sizeof(cap));
+ hdlr->client_capability_update(fd, &cap);
+ } else {
+ LOGE("hal2mnl_basic_hdlr() client_capability_update is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ default: {
+ LOGE("hal2mnl_basic_hdlr() unknown cmd=%d", cmd);
+ ret = -1;
+ break;
+ }
+ }
+ }
+ UNUSED(ret);
+}
+
+void hal2mnl_ext_client_hdlr(int fd, hal2mnl_ext_interface* hdlr) {
+ char buff[HAL_MNL_BUFF_SIZE] = {0};
+ char buff_read[HAL_MNL_BUFF_SIZE] = {0};
+ int offset = 0;
+ int ver;
+ hal2mnl_cmd cmd;
+ int read_len;
+ int ret = 0;
+ int ret_len = 0;
+ int msg_len = 0;
+
+ read_len = safe_recvfrom(fd, buff_read, sizeof(buff));
+ if (read_len <= 0) {
+ close(fd);
+ client_list_remove(&g_hal_ext_client_list, fd);
+ LOGE("hal2mnl_ext_client_hdlr() safe_recvfrom() failed read_len=%d, %s", read_len, strerror(errno));
+ return;
+ }
+
+ mnld_put_msg_to_cycle(&g_mnl_hal_ext_cbuffer, buff_read, read_len);
+
+ while((ret_len = mnld_get_one_msg(&g_mnl_hal_ext_cbuffer, buff)) > 0) {
+ offset = 0;
+ msg_len = get_int(buff, &offset, sizeof(buff)); //Get message length
+ UNUSED(msg_len);
+ ver = get_int(buff, &offset, sizeof(buff));
+ UNUSED(ver);
+ cmd = get_int(buff, &offset, sizeof(buff));
+ LOGD("msg len:%d, get len:%d, fd:%d", msg_len, ret_len, fd);
+ for(int i=0;i<ret_len;i++) {
+ LOGD(" 0x%x", buff[i]);
+ }
+ LOGD("=========================");
+ switch (cmd) {
+ case HAL2MNL_GPS_INJECT_TIME: {
+ if (hdlr->gnss_inject_time) {
+ int64_t time = get_long(buff, &offset, sizeof(buff));
+ int64_t time_reference = get_long(buff, &offset, sizeof(buff));
+ int uncertainty = get_int(buff, &offset, sizeof(buff));
+ hdlr->gnss_inject_time(time, time_reference, uncertainty);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() gnss_inject_time is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_GPS_INJECT_LOCATION: {
+ if (hdlr->gnss_inject_location) {
+ double lat = get_double(buff, &offset, sizeof(buff));
+ double lng = get_double(buff, &offset, sizeof(buff));
+ float acc = get_float(buff, &offset, sizeof(buff));
+ hdlr->gnss_inject_location(lat, lng, acc);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() gnss_inject_location is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_GPS_DELETE_AIDING_DATA: {
+ if (hdlr->gnss_delete_aiding_data) {
+ int flags = get_int(buff, &offset, sizeof(buff));
+ hdlr->gnss_delete_aiding_data(flags);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() gnss_delete_aiding_data is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_GPS_SET_POSITION_MODE: {
+ if (hdlr->gnss_set_position_mode) {
+ gps_pos_mode mode = get_int(buff, &offset, sizeof(buff));
+ gps_pos_recurrence recurrence = get_int(buff, &offset, sizeof(buff));
+ int min_interval = get_int(buff, &offset, sizeof(buff));
+ int preferred_acc = get_int(buff, &offset, sizeof(buff));
+ int preferred_time = get_int(buff, &offset, sizeof(buff));
+ bool lowPowerMode = get_byte(buff, &offset, sizeof(buff));
+ hdlr->gnss_set_position_mode(mode, recurrence, min_interval,
+ preferred_acc, preferred_time, lowPowerMode);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() gnss_set_position_mode is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_DATA_CONN_OPEN: {
+ if (hdlr->data_conn_open) {
+ char* apn = get_string(buff, &offset, sizeof(buff));
+ hdlr->data_conn_open(apn);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() data_conn_open is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_DATA_CONN_OPEN_WITH_APN_IP_TYPE: {
+ if (hdlr->data_conn_open_with_apn_ip_type) {
+ uint64_t network_handle = get_long(buff, &offset, sizeof(buff));
+ char* apn = get_string(buff, &offset, sizeof(buff));
+ apn_ip_type ip_type = get_int(buff, &offset, sizeof(buff));
+ hdlr->data_conn_open_with_apn_ip_type(network_handle, apn, ip_type);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() data_conn_open_with_apn_ip_type is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_DATA_CONN_CLOSED: {
+ if (hdlr->data_conn_closed) {
+ hdlr->data_conn_closed();
+ } else {
+ LOGE("hal2mnl_ext_hdlr() data_conn_closed is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_DATA_CONN_FAILED: {
+ if (hdlr->data_conn_failed) {
+ hdlr->data_conn_failed();
+ } else {
+ LOGE("hal2mnl_ext_hdlr() data_conn_failed is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_SET_SERVER: {
+ if (hdlr->set_server) {
+ agps_type type = get_int(buff, &offset, sizeof(buff));
+ char* hostname = get_string(buff, &offset, sizeof(buff));
+ int port = get_int(buff, &offset, sizeof(buff));
+ hdlr->set_server(type, hostname, port);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() set_server is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_SET_REF_LOCATION: {
+ if (hdlr->set_ref_location) {
+ cell_type type = get_int(buff, &offset, sizeof(buff));
+ int mcc = get_int(buff, &offset, sizeof(buff));
+ int mnc = get_int(buff, &offset, sizeof(buff));
+ int lac = get_int(buff, &offset, sizeof(buff));
+ int cid = get_int(buff, &offset, sizeof(buff));
+ hdlr->set_ref_location(type, mcc, mnc, lac, cid);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() set_ref_location is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_SET_ID: {
+ if (hdlr->set_id) {
+ agps_id_type type = get_int(buff, &offset, sizeof(buff));
+ char* setid = get_string(buff, &offset, sizeof(buff));
+ hdlr->set_id(type, setid);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() set_id is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_NI_MESSAGE: {
+ if (hdlr->ni_message) {
+ char msg[1024] = {0};
+ int len = get_binary(buff, &offset, msg, sizeof(buff), sizeof(msg));
+ hdlr->ni_message(msg, len);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() ni_message is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_NI_RESPOND: {
+ if (hdlr->ni_respond) {
+ int notif_id = get_int(buff, &offset, sizeof(buff));
+ ni_user_response_type user_response = get_int(buff, &offset, sizeof(buff));
+ hdlr->ni_respond(notif_id, user_response);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() ni_respond is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_UPDATE_NETWORK_STATE: {
+ if (hdlr->update_network_state) {
+ uint64_t network_handle = get_long(buff, &offset, sizeof(buff));
+ bool is_connected = get_byte(buff, &offset, sizeof(buff));
+ unsigned short capabilities = get_short(buff, &offset, sizeof(buff));
+ char* apn = get_string(buff, &offset, sizeof(buff));
+ //hdlr->update_network_state(connected, type, roaming, extra_info); //Before HIDL 2.0
+ LOGD("hal2mnl_ext_hdlr() network_state network_handle=%"PRId64" is_connected=%d capabilities=%d apn=%s",
+ network_handle, is_connected, capabilities, apn);
+ hdlr->update_network_state(network_handle, is_connected, capabilities, apn);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() update_network_state is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_UPDATE_NETWORK_AVAILABILITY: {
+ if (hdlr->update_network_availability) {
+ int available = get_int(buff, &offset, sizeof(buff));
+ char* apn = get_string(buff, &offset, sizeof(buff));
+ hdlr->update_network_availability(available, apn);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() update_network_availability is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_FULL_TRACKING: {
+ if (hdlr->set_gnss_full_tracking_enable) {
+ bool enabled = get_int(buff, &offset, sizeof(buff));
+ hdlr->set_gnss_full_tracking_enable(enabled);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() set_gnss_full_tracking_enable is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_GPS_NAVIGATION: {
+ if (hdlr->set_gnss_navigation_enable) {
+ bool enabled = get_int(buff, &offset, sizeof(buff));
+ hdlr->set_gnss_navigation_enable(enabled);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() set_gnss_navigation_enable is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_VZW_DEBUG: {
+ if (hdlr->set_vzw_debug) {
+ bool enabled = get_int(buff, &offset, sizeof(buff));
+ hdlr->set_vzw_debug(enabled);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() set_vzw_debug is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_GNSS_CONFIG: {
+ if (hdlr->update_gnss_config) {
+ int length = get_int(buff, &offset, sizeof(buff));
+ char* config_data = get_string(buff, &offset, sizeof(buff));
+ hdlr->update_gnss_config(config_data, length);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() update_gnss_config is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_SV_BLACKLIST: {
+ if (hdlr->set_sv_blacklist) {
+ long long blacklist[7];
+ memset(blacklist, 0x00, sizeof(long long));
+ int size = get_int(buff, &offset, sizeof(buff));
+ size = size < 7 ? size : 7;
+ get_binary(buff, &offset, (char*)blacklist, sizeof(buff),
+ sizeof(long long) * size);
+ hdlr->set_sv_blacklist(blacklist, size);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() set_sv_blacklist is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_CORRECTION: {
+ if (hdlr->set_correction) {
+ memset(&corrections, 0x00, sizeof(corrections));
+ get_binary(buff, &offset, (char*)&corrections, sizeof(buff), sizeof(measurement_corrections));
+ hdlr->set_correction(&corrections);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() set_correction is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_NFW_ACCESS: {
+ if (hdlr->set_nfw_access) {
+ int length = get_int(buff, &offset, sizeof(buff));
+ char* proxyApps = get_string(buff, &offset, sizeof(buff));
+ hdlr->set_nfw_access(proxyApps, length);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() nfw_access is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_SEND_PMTK: {
+ if (hdlr->send_pmtk) {
+ char pmtk[256];
+ get_binary(buff, &offset, pmtk, sizeof(buff), sizeof(pmtk));
+ hdlr->send_pmtk(pmtk, offset);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() send_pmtk is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_EPO_ENABLE: {
+ if (hdlr->set_epo_enable) {
+ epo_bitmap epo_cfg = get_int(buff, &offset, sizeof(buff));
+ hdlr->set_epo_enable(epo_cfg);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() set_epo_enable is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_SET_TTFF_ACC: {
+ if (hdlr->set_ttff_acc) {
+ ttff_acc acc_mode = get_int(buff, &offset, sizeof(buff));
+ hdlr->set_ttff_acc(acc_mode);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() set_ttff_acc is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ case HAL2MNL_EXT_CAP_SYNC: {
+ if(hdlr->client_capability_update) {
+ mnl_hal_ext_client_cap cap;
+ memset(&cap, 0, sizeof(cap));
+ get_binary(buff, &offset, (char *)&cap, sizeof(buff), sizeof(cap));
+ hdlr->client_capability_update(fd, &cap);
+ } else {
+ LOGE("hal2mnl_ext_hdlr() client_capability_update is NULL");
+ ret = -1;
+ }
+ break;
+ }
+ default: {
+ LOGE("hal2mnl_ext_hdlr() unknown cmd=%d", cmd);
+ ret = -1;
+ break;
+ }
+ }
+ }
+ UNUSED(ret);
+}
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mnl_common.c b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mnl_common.c
new file mode 100644
index 0000000..953edb8
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mnl_common.c
@@ -0,0 +1,456 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#define _MNL_COMMON_C_
+/*******************************************************************************
+* Dependency
+*******************************************************************************/
+#include <stdio.h> /* Standard input/output definitions */
+#include <string.h> /* String function definitions */
+#include <stdlib.h>
+#include <sys/time.h>
+#include <errno.h>
+
+#if defined(__ANDROID_OS__)
+#include <cutils/properties.h>
+#endif
+
+#include "mtk_prop_util.h"
+#include "mnl_common.h"
+#include "mtk_lbs_utility.h"
+
+#include "mtk_mnld_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "mnl_common"
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#define MNL_CONFIG_STATUS "persist.vendor.radio.mnl.prop"
+#endif
+/*******************************************************************************
+* structure & enumeration
+*******************************************************************************/
+
+/******************************************************************************
+ * Functions
+******************************************************************************/
+#if defined(READ_PROPERTY_FROM_FILE)
+/******************************************************************************
+Sample for mnl.prop: (for emulator)
+-------------------------------------------------------------------------------
+init.speed=38400
+link.speed=38400
+dev.dsp=/dev/ttyS3
+dev.gps=/dev/gps
+bee.path=/bee
+pmtk.conn=socket
+pmtk.socket.port=7000
+#pmtk.conn=serial
+#pmtk.serial.dev=/dev/ttygserial
+debug.nema=1 (0:none; 1:normal; 2:full)
+debug.mnl=1
+******************************************************************************/
+const char *mnl_prop_path[] = {
+ MTK_GPS_DATA_PATH"mnl.prop", /*mainly for target*/
+ "/sbin/mnl.prop", /*mainly for emulator*/
+};
+#define PROPBUF_SIZE 512
+static char propbuf[512];
+extern int epo_setconfig;
+extern void set_mnl_prop_config_socket_port();
+#define IS_SPACE(ch) ((ch == ' ') || (ch == '\t') || (ch == '\n'))
+/******************************************************************************
+* Read property from file and overwritting the existing property
+******************************************************************************/
+int get_prop(char *pStr, char** ppKey, char** ppVal) {
+ int len = (int)strlen(pStr);
+ char *end = pStr + len;
+ char *key = NULL, *val = NULL;
+
+ if (!len) {
+ return -1; // no data
+ }
+ else if (pStr[0] == '#') { /*ignore comment*/
+ *ppKey = *ppVal = NULL;
+ return 0;
+ } else if (pStr[len-1] != '\n') {
+ if (len >= PROPBUF_SIZE-1) {
+ LOGE("%s: buffer is not enough!!\n", __FUNCTION__);
+ return -1;
+ } else {
+ pStr[len] = '\n';
+ }
+ }
+ key = pStr;
+ while ((*pStr != '=') && (pStr < end)) pStr++;
+ if (pStr >= end) {
+ LOGW("%s: '=' is not found!!\n", __FUNCTION__);
+ *ppKey = *ppVal = NULL;
+ return 0; // format error
+ }
+
+ *pStr++ = '\0';
+ while (IS_SPACE(*pStr) && (pStr < end)) pStr++; // skip space chars
+ val = pStr;
+ while (!IS_SPACE(*pStr) && (pStr < end)) pStr++;
+ *pStr = '\0';
+ *ppKey = key;
+ *ppVal = val;
+ return 0;
+}
+/*****************************************************************************/
+int set_prop(MNL_CONFIG_T* prConfig, const char* key, const char* val) {
+ if (!strcmp(key, "init.speed")) {
+ prConfig->init_speed = atoi(val);
+ } else if (!strcmp(key, "link.speed")) {
+ prConfig->link_speed = atoi(val);
+ } else if (!strcmp(key, "dev.dsp")) {
+ if (strlen(val) < sizeof(prConfig->dev_dsp))
+ MNLD_STRNCPY(prConfig->dev_dsp, val, sizeof(prConfig->dev_dsp));
+ } else if (!strcmp(key, "dev.dsp2")) {
+ if (strlen(val) < sizeof(prConfig->dev_dsp2))
+ MNLD_STRNCPY(prConfig->dev_dsp2, val, sizeof(prConfig->dev_dsp2));
+ } else if (!strcmp(key, "dev.gps")) {
+ if (strlen(val) < sizeof(prConfig->dev_gps))
+ MNLD_STRNCPY(prConfig->dev_gps, val,sizeof(prConfig->dev_gps));
+ } else if (!strcmp(key, "bee.path")) {
+ if (strlen(val) < sizeof(prConfig->bee_path))
+ MNLD_STRNCPY(prConfig->bee_path, val, sizeof(prConfig->bee_path));
+ } else if (!strcmp(key, "pmtk.serial.dev")) {
+ if (strlen(val) < sizeof(prConfig->dev_dbg))
+ MNLD_STRNCPY(prConfig->dev_dbg, val,sizeof(prConfig->dev_dbg));
+ } else if (!strcmp(key, "pmtk.conn")) {
+ if (!strcmp(val, "serial"))
+ prConfig->pmtk_conn = PMTK_CONNECTION_SERIAL;
+ else if (!strcmp(val, "socket"))
+ prConfig->pmtk_conn = PMTK_CONNECTION_SOCKET;
+ }
+ else if (!strcmp(key, "pmtk.serial.port")) {
+ prConfig->socket_port = atoi(val);
+ set_mnl_prop_config_socket_port();
+ }
+ else if (!strcmp(key, "debug.debug_nmea")) {
+ /* it will be set to enable_dbg_log */
+ prConfig->debug_nmea = (atoi(val) > 0) ? (1) : (0);
+ } else if (!strcmp(key, "debug.mnl")) {
+ prConfig->debug_mnl = strtol(val, NULL, 16);
+ } else if (!strcmp(key, "debug.dbg2file")) {
+ prConfig->dbg2file = atoi(val);
+ } else if (!strcmp(key, "debug.filename")) {
+ MNLD_STRNCPY(prConfig->debug_file_name, val, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ } else if (!strcmp(key, "debug.mode")) {
+ //bit0: Output gps debug log to file(0:close 1:open)
+ //bit1: Output gps debug log to socket(0:close 1:open)
+ gps_dbg_log_mode_set(atoi(val));
+ } else if (!strcmp(key, "timeout.monitor")) {
+ prConfig->timeout_monitor = atoi(val);
+ } else if (!strcmp(key, "timeout.init")) {
+ prConfig->timeout_init = atoi(val);
+ } else if (!strcmp(key, "timeout.sleep")) {
+ prConfig->timeout_sleep = atoi(val);
+ } else if (!strcmp(key, "timeout.pwroff")) {
+ prConfig->timeout_pwroff = atoi(val);
+ } else if (!strcmp(key, "timeout.wakeup")) {
+ prConfig->timeout_wakeup = atoi(val);
+ } else if (!strcmp(key, "timeout.ttff")) {
+ prConfig->timeout_ttff = atoi(val);
+ } else if (!strcmp(key, "delay.reset_dsp")) {
+ prConfig->delay_reset_dsp = atoi(val);
+ } else if (!strcmp(key, "EPO_enabled")) {
+ prConfig->EPO_enabled = atoi(val);
+ epo_setconfig = 1;
+ } else if (!strcmp(key, "BEE_enabled")) {
+ prConfig->BEE_enabled = atoi(val);
+ } else if (!strcmp(key, "SUPL_enabled")) {
+ prConfig->SUPL_enabled = atoi(val);
+ } else if (!strcmp(key, "SUPLSI_enabled")) {
+ prConfig->SUPLSI_enabled = atoi(val);
+ } else if (!strcmp(key, "EPO_priority")) {
+ prConfig->EPO_priority = atoi(val);
+ } else if (!strcmp(key, "BEE_priority")) {
+ prConfig->BEE_priority = atoi(val);
+ } else if (!strcmp(key, "SUPL_priority")) {
+ prConfig->SUPL_priority = atoi(val);
+ } else if (!strcmp(key, "AVAILIABLE_AGE")) {
+ prConfig->AVAILIABLE_AGE = atoi(val);
+ } else if (!strcmp(key, "RTC_DRIFT")) {
+ prConfig->RTC_DRIFT = atoi(val);
+ } else if (!strcmp(key, "TIME_INTERVAL")) {
+ prConfig->TIME_INTERVAL = atoi(val);
+ } else if (!strcmp(key, "TEST_MACHINE")) {
+ prConfig->u1AgpsMachine = atoi(val);
+ } else if (!strcmp(key, "ACC_SNR")) {
+ prConfig->ACCURACY_SNR = atoi(val);
+ } else if (!strcmp(key, "GNSS_MODE")) {
+ prConfig->GNSSOPMode = atoi(val);
+ } else if (!strcmp(key, "DBGLOG_FILE_MAX")) {
+ prConfig->dbglog_file_max_size = atoi(val);
+ } else if (!strcmp(key, "DBGLOG_FOLDER_MAX")) {
+ prConfig->dbglog_folder_max_size = atoi(val);
+ } else if ((!strcmp(key, "OFFLOAD_enabled"))) {
+ prConfig->OFFLOAD_enabled = atoi(val);
+ } else if ((!strcmp(key, "OFFLOAD_testMode"))) {
+ prConfig->OFFLOAD_testMode = atoi(val);
+ } else if ((!strcmp(key, "OFFLOAD_switchMode"))) {
+ prConfig->OFFLOAD_switchMode = atoi(val);
+ } else if ((!strcmp(key, "debug.log_hide"))) {
+ prConfig->log_hide = atoi(val);
+ } else if ((!strcmp(key, "ADC_CAPTURE_enabled"))) {
+ prConfig->adc_capture_enabled = atoi(val);
+ } else if ((!strcmp(key, "FAST_HTTFF_enabled"))) {
+ prConfig->fast_HTTFF = atoi(val);
+ #if defined(GPS_SUSPEND_SUPPORT)
+ } else if ((!strcmp(key, "SUSPEND_enabled"))) {
+ prConfig->SUSPEND_enabled = atoi(val);
+ } else if ((!strcmp(key, "SUSPEND_timeout"))) {
+ prConfig->SUSPEND_timeout = atoi(val);
+ } else if ((!strcmp(key, "SUSPEND_ext_enabled"))) {
+ prConfig->SUSPEND_ext_enabled = atoi(val);
+ } else if ((!strcmp(key, "SUSPEND_ext_timeout"))) {
+ prConfig->SUSPEND_ext_timeout = atoi(val);
+ } else if ((!strcmp(key, "SUSPEND_ext_available"))) {
+ prConfig->SUSPEND_ext_available = atoi(val);
+ #endif
+ } else if ((!strcmp(key, "NFW_CTRL"))) {
+ prConfig->bitmap_nfw_ctrl = atoi(val);
+ } else if ((!strcmp(key, "RfPathLossDb_Ap"))) {
+ prConfig->RfPathLossDb_Ap = atof(val);
+ } else if ((!strcmp(key, "fix_interval"))) {
+ prConfig->fix_interval = atoi(val);
+ } else if ((!strcmp(key, "pps_mode"))) {
+ prConfig->pps_mode = atoi(val);
+ } else if ((!strcmp(key, "pps_delay"))) {
+ prConfig->pps_delay = atoi(val);
+ } else if ((!strcmp(key, "pps_polarity"))) {
+ prConfig->pps_polarity = atoi(val);
+ } else if ((!strcmp(key, "pps_duty"))) {
+ prConfig->pps_duty = atoi(val);
+ }
+ return 0;
+}
+/*****************************************************************************/
+int read_prop(MNL_CONFIG_T* prConfig, const char* name) {
+ FILE *fp = fopen(name, "rb");
+ char *key, *val;
+ if (!fp) {
+ LOGD_ENG("%s: open %s fail!\n", __FUNCTION__, name);
+ return -1;
+ }
+ while (fgets(propbuf, sizeof(propbuf), fp)) {
+ if (get_prop(propbuf, &key, &val)) {
+ LOGD("%s: Get Property fails!!\n", __FUNCTION__);
+ fclose(fp);
+ return -1;
+ }
+ if (!key || !val)
+ continue;
+ // LOGD("%s: Get Property: '%s' => '%s'\n", __FUNCTION__, key, val);
+ if (set_prop(prConfig, key, val)) {
+ LOGE("%s: Set Property fails!!\n", __FUNCTION__);
+ fclose(fp);
+ return -1;
+ }
+ }
+ fclose(fp);
+ return 0;
+}
+/*****************************************************************************/
+int mnl_utl_load_property(MNL_CONFIG_T* prConfig) {
+ int idx;
+ int cnt = sizeof(mnl_prop_path)/sizeof(mnl_prop_path[0]);
+ int res = 0;
+ epo_setconfig = 0;
+ for (idx = 0; idx < cnt; idx++) {
+ if (!read_prop(prConfig, mnl_prop_path[idx]))
+ break;
+ }
+#if ANDROID_MNLD_PROP_SUPPORT
+ // Add for reading property set by YGPS
+ char result[PROPERTY_VALUE_MAX] = {0};
+ if (property_get(MNL_CONFIG_STATUS, result, NULL)) {
+ prConfig->dbg2file = result[2] - '0';
+ LOGD_ENG("dbg2file: %d\n", prConfig->dbg2file);
+ prConfig->debug_nmea = result[3] - '0';
+ LOGD_ENG("debug_nmea:%d \n", prConfig->debug_nmea);
+ prConfig->BEE_enabled = result[4] - '0';
+ LOGD_ENG("BEE_enabled: %d", prConfig->BEE_enabled);
+ // prConfig->test_mode = result[5] - '0';
+ // LOGD("test_mode: %d", prConfig->test_mode);
+ } else {
+ LOGD_ENG("Config is not set yet, ignore");
+ }
+#endif
+ if (idx < cnt) /* successfully read property from file */ {
+ LOGD_ENG("[setting] reading from %s\n", mnl_prop_path[idx]);
+ res = 0;
+ } else {
+ LOGD_ENG("[setting] load default value\n");
+ res = -1;
+ }
+ LOGD("dev_dsp/dev_dsp2/dev_gps : %s %s %s,init_speed/link_speed: %d %d\n",
+ prConfig->dev_dsp, prConfig->dev_dsp2, prConfig->dev_gps,
+ prConfig->init_speed, prConfig->link_speed);
+ LOGD_ENG("pmtk_conn/socket_port/dev_dbg : %d %d %s\n",
+ prConfig->pmtk_conn, prConfig->socket_port, prConfig->dev_dbg);
+ LOGD_ENG("debug_nmea/debug_mnl: %d 0x%04X,nmea2file/dbg2file: %d/%d\n",
+ prConfig->debug_nmea, prConfig->debug_mnl, prConfig->nmea2file, prConfig->dbg2file);
+ LOGD_ENG("time-out: %d %d %d %d %d %d\n", prConfig->timeout_init,
+ prConfig->timeout_monitor, prConfig->timeout_wakeup, prConfig->timeout_ttff,
+ prConfig->timeout_sleep, prConfig->timeout_pwroff);
+ LOGD_ENG("EPO_Enabled: %d,BEE_Enabled: %d,SUPL_Enabled: %d,SUPLSI_Enabled: %d\n",
+ prConfig->EPO_enabled, prConfig->BEE_enabled, prConfig->SUPL_enabled, prConfig->SUPLSI_enabled);
+ LOGD_ENG("EPO_priority: %d,BEE_priority: %d, SUPL_priority: %d\n",
+ prConfig->EPO_priority, prConfig->BEE_priority, prConfig->SUPL_priority);
+ LOGD_ENG("AVAILIABLE_AGE: %d,RTC_DRIFT: %d,TIME_INTERVAL: %d\n",
+ prConfig->AVAILIABLE_AGE, prConfig->RTC_DRIFT, prConfig->TIME_INTERVAL);
+ #if defined(GPS_SUSPEND_SUPPORT)
+ LOGD("SUSPEND_enabled: %d, SUSPEND_timeout:%d,SUSPEND_ext_enabled:%d,SUSPEND_ext_timeout:%d,SUSPEND_ext_available:%d\n",
+ prConfig->SUSPEND_enabled, prConfig->SUSPEND_timeout, prConfig->SUSPEND_ext_enabled, prConfig->SUSPEND_ext_timeout, prConfig->SUSPEND_ext_available);
+ #endif
+ return res;
+}
+
+int write_prop(const char *file_name, char* key, char* val) {
+ char linebuffer[PROPBUF_SIZE] = {0};
+ char buffer1[PROPBUF_SIZE] = {0};
+ char buffer2[PROPBUF_SIZE] = {0};
+
+ int line_len = 0;
+ int len = 0;
+ int res;
+ bool changed = 0;
+ FILE *fp = NULL;
+
+ if (0 != access(file_name, F_OK)) { // if file is not exit, create file
+ LOGD("access file error(%s), Try to create file", file_name);
+
+ fp = fopen(file_name, "w"); //Create file
+ if (fp == NULL) {
+ LOGD("create file %s fail(%s)", file_name, strerror(errno));
+ return -1;
+ }
+ } else {
+ fp = fopen(file_name, "r+"); //Read and write
+ if(fp == NULL)
+ {
+ LOGE("open error, %s", strerror(errno));
+ return -1;
+ }
+ }
+
+ while(fgets(linebuffer, PROPBUF_SIZE, fp)) {
+ line_len = strlen(linebuffer);
+ len += line_len;
+ sscanf(linebuffer, "%[^=]=%[^=]", buffer1,buffer2);
+ LOGD("buffer1:%s, buffer2:%s", buffer1, buffer2);
+ if(!strcmp(key, buffer1)) {
+ len -= strlen(linebuffer);
+ res = fseek(fp, len, SEEK_SET);
+ if(res < 0) {
+ LOGE("fseek fail, %s", strerror(errno));
+ fclose(fp);
+ return -1;
+ }
+ LOGD("Before modify [%s=%s] in file [%s]", buffer1, buffer2, file_name);
+ memset(buffer2, 0, PROPBUF_SIZE);
+ MNLD_STRNCPY(buffer2, val, PROPBUF_SIZE);
+ strncat(buffer1, "=", PROPBUF_SIZE - strlen(buffer1) - 1);
+ strncat(buffer1, buffer2, PROPBUF_SIZE - strlen(buffer1) - 1);
+ LOGD("After modify [%s] in file [%s]", buffer1, file_name);
+ changed = 1;
+ fprintf(fp, "%s", buffer1);
+ fclose(fp);
+ return 0;
+ }
+ }
+ if(changed == 0) { //Not find key
+ memset(linebuffer, 0, PROPBUF_SIZE);
+ strncat(linebuffer, "\n", PROPBUF_SIZE - strlen(linebuffer) - 1);
+ strncat(linebuffer, key, PROPBUF_SIZE - strlen(linebuffer) - 1);
+ strncat(linebuffer, "=", PROPBUF_SIZE - strlen(linebuffer) - 1);
+ strncat(linebuffer, val, PROPBUF_SIZE - strlen(linebuffer) - 1);
+ LOGD("Add config [%s] to file [%s]", linebuffer, file_name);
+ res = fseek(fp, 0, SEEK_END);
+ if(res < 0) {
+ LOGE("fseek fail, %s", strerror(errno));
+ fclose(fp);
+ return -1;
+ }
+ fprintf(fp, "%s", linebuffer);
+
+ fclose(fp);
+ }
+ return 0;
+}
+
+void mnld_write_cfg(char* key, char* val) {
+ int idx;
+ int cnt = sizeof(mnl_prop_path)/sizeof(mnl_prop_path[0]);
+
+ for (idx = 0; idx < cnt; idx++) {
+ if (!write_prop(mnl_prop_path[idx], key, val))
+ break;
+ }
+}
+#endif
+
+/*****************************************************************************/
+int str2int(const char* p, const char* end) {
+ int result = 0;
+ int len = end - p;
+ int sign = 1;
+
+ if (*p == '-') {
+ sign = -1;
+ p++;
+ len = end - p;
+ }
+
+ for (; len > 0; len--, p++) {
+ int c;
+
+ if (p >= end)
+ return -1;
+
+ c = *p - '0';
+ if ((unsigned)c >= 10)
+ return -1;
+
+ result = result*10 + c;
+ }
+ return sign*result;
+}
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mnld.c b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mnld.c
new file mode 100755
index 0000000..ded6721
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mnld.c
@@ -0,0 +1,3577 @@
+#include <pthread.h>
+#include <sys/epoll.h>
+#include <errno.h>
+#include <string.h>
+#include <netinet/in.h> // struct sockaddr_in
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <signal.h>
+#if defined(__ANDROID_OS__)
+#include <cutils/properties.h>
+#endif
+
+#include "mtk_prop_util.h"
+
+#include "mnld.h"
+#include "mnld_utile.h"
+#include "mnl_common.h"
+#include "mtk_gps.h"
+#include "agps_agent.h"
+#include "mtk_lbs_utility.h"
+#include "mnl2hal_interface.h"
+#include "mnl2agps_interface.h"
+#include "data_coder.h"
+#include "gps_controller.h"
+#include "epo.h"
+#include "qepo.h"
+#include "mtknav.h"
+#include "op01_log.h"
+#include "mtk_geofence_main.h"
+#include "gps_dbg_log.h"
+#include "mpe.h"
+#include "mnl_at_interface.h"
+#include "Mnld2NlpUtilsInterface.h"
+#include "Meta2MnldInterface.h"
+#include "Meta2Mnld_logctrl_Interface.h"
+#include "Mnld2DebugInterface.h"
+#include "Debug2MnldInterface.h"
+#include "mtk_geofence_controller.h"
+
+#include <unistd.h>
+
+#include "mtk_mnld_log.h"
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "MNLD"
+
+#define CLK_EXT_AVAILABLE_DISABLE 0
+#define CLK_EXT_AVAILABLE_ENABLE 1
+static void mnld_fsm(mnld_gps_event event, int data1, int data2, void* data3);
+
+int clk_extension_ni_only = 0;
+bool agps_open_gps_flag = false;
+bool sv_inuse_num_valid = 0;
+int sv_inuse_number = 0;
+static mnld_context g_mnld_ctx;
+static md_ts_context g_md_time_ctx;
+UINT8 sv_type_agps_set = 0;
+UINT8 sib8_16_enable = 0;
+UINT8 lppe_enable = 0;// if mnl support lppe, use this variable to determin on or off, else, it is invalid
+mnl_agps_agps_settings g_settings_from_agps;
+MTK_GPS_MNL_INFO mtk_gps_mnl_info;// include lib information:vertion and if support lppe
+mnl_agps_gnss_settings g_settings_to_agps = {
+ .gps_satellite_support = 1,
+ .glonass_satellite_support = 0,
+ .beidou_satellite_support = 0,
+ .galileo_satellite_support = 0,
+};
+extern int gps_epo_type;
+extern mtk_socket_fd gpslogd_fd;
+extern bool mnld_exiting;
+
+#if ANDROID_MNLD_PROP_SUPPORT
+extern char chip_id[PROPERTY_VALUE_MAX];
+#define MNL_CONFIG_STATUS "persist.vendor.radio.mnl.prop"
+#else
+extern char chip_id[100];
+#endif
+
+int log_dbg_level = L_DEBUG;
+
+extern client_list g_hal_basic_client_list;
+extern client_list g_hal_ext_client_list;
+extern client_list g_geofence_client_list;
+extern client_list g_geofence_client_control_list;
+
+extern int in_meta_factory;
+extern MTK_GPS_SV_BLACKLIST svBlacklist;
+extern bool g_enable_full_tracking;
+volatile UINT8 enable_debug2app = DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_STOP_DEBUG;
+
+extern char gps_debuglog_file_name[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+extern char storagePath_mtklogger_set[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+extern char storagePath[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+/******************************************************************************************************************************
+Steps to add NFW(None Framework) user visibility control:
+Step 1. Add NFW user app name in nfw_app_name_list;
+Step 2. Add NFW user ID to enum MNLD_NFW_USER;
+Step 3. Complete the API to update to new NFW user allowed to access location or not, and call the API in hal_set_nfw_access();
+Step 4. Call mtk_gps_get_nfw_visibility(nfw_user) API to check whether nfw_user in visibility check list
+Step 5. Fill nfw_notification structure and call mnl2hal_nfw_notify() API in correct time.
+*******************************************************************************************************************************/
+char nfw_app_name_list[MNLD_NFW_USER_NUM][MNLD_NFW_USER_NAME_LEN] = {MNLD_NFW_PROXY_NAME};
+nfw_notification nfw_user_notify[MNLD_NFW_USER_NUM];
+bool g_mnld_nfw_notified[MNLD_NFW_USER_NUM] = {0};
+nfw_notification nfw_user_notify_default[MNLD_NFW_USER_NUM] = {
+ {//NFW AGPS
+ .proxy_app_package_name = MNLD_NFW_PROXY_NAME,
+ .protocol_stack = NFW_PS_OTHER,
+ .other_protocol_stack_name = "MODEM",
+ .requestor = NFW_REQUESTOR_MODEM_CHIPSET_VENDOR,
+ .requestor_id = "MTK",
+ .in_emergency_mode = 0,
+ .is_cached_location = 0
+ }
+};
+/*****************************************
+MNLD get sv valid/num
+*****************************************/
+
+void mnld_set_sv_inuse_valid(bool valid)
+{
+ sv_inuse_num_valid = valid;
+}
+void mnld_set_sv_inuse_num(int num)
+{
+ sv_inuse_number = num;
+}
+bool mnld_get_sv_inuse_num_valid()
+{
+ return sv_inuse_num_valid;
+}
+int mnld_get_sv_inuse_num()
+{
+ return sv_inuse_number;
+}
+
+/*****************************************
+MNLD FSM
+*****************************************/
+static const char* get_mnld_gps_state_str(mnld_gps_state input) {
+ switch (input) {
+ case MNLD_GPS_STATE_IDLE:
+ return "IDLE";
+ case MNLD_GPS_STATE_STARTING:
+ return "STARTING";
+ case MNLD_GPS_STATE_STARTED:
+ return "STARTED";
+ case MNLD_GPS_STATE_STOPPING:
+ return "STOPPING";
+ case MNLD_GPS_STATE_SUSPEND:
+ return "SUSPEND";
+ default:
+ break;
+ }
+ return "UNKNOWN";
+}
+
+static const char* get_mnld_gps_event_str(mnld_gps_event input) {
+ switch (input) {
+ case GPS_EVENT_START:
+ return "START";
+ case GPS_EVENT_STOP:
+ return "STOP";
+ case GPS_EVENT_RESET:
+ return "RESET";
+ case GPS_EVENT_START_DONE:
+ return "START_DONE";
+ case GPS_EVENT_STOP_DONE:
+ return "STOP_DONE";
+ case GPS_EVENT_SUSPEND:
+ return "SUSPEND";
+ case GPS_EVENT_SUSPEND_DONE:
+ return "SUSPEND_DONE";
+ case GPS_EVENT_SUSPEND_CLOSE:
+ return "SUSPEND_CLOSE";
+ default:
+ break;
+ }
+ return "UNKNOWN";
+}
+
+static void do_gps_reset_hdlr() {
+ mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+ if (agps->need_reset_ack) {
+ agps->need_reset_ack = false;
+ if (mnl2agps_reset_gps_done() == -1) {
+ LOGE("mnl2agps_reset_gps_done failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ }
+}
+
+static void do_gps_started_hdlr(int si_assist_req) {
+ mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+ mnld_gps_client* raw_meas = &g_mnld_ctx.gps_status.clients.raw_meas;
+ mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+ mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+ mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+ mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+ if (hal->need_open_ack) {
+ hal->need_open_ack = false;
+ if (mnl2hal_gnss_status(MTK_GPS_STATUS_SESSION_ENGINE_ON) == -1) {
+ LOGE("mnl2hal_gps_status failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ if (mnl2hal_gnss_status(MTK_GPS_STATUS_SESSION_BEGIN) == -1) {
+ LOGE("mnl2hal_gps_status failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ mnl2agps_gps_open(si_assist_req);
+ }
+
+ if (agps->need_open_ack) {
+ agps->need_open_ack = false;
+ mnl2agps_open_gps_done();
+ }
+
+ if (geofence->need_open_ack) {
+ geofence->need_open_ack = false;
+ mnl2agps_gps_open(si_assist_req);
+ }
+
+ if (at_cmd_test->need_open_ack) {
+ at_cmd_test->need_open_ack = false;
+ /*add open ack message to at_cmd_test*/
+ }
+
+ if (factory->need_open_ack) {
+ factory->need_open_ack = false;
+ /*add open ack message to factory*/
+ mtk_gps_mnl_create_dbg_port(PMTK_CONNECTION_SOCKET_PORT); //Create debug socket in running time
+ }
+
+ if (raw_meas->need_open_ack) {
+ raw_meas->need_open_ack = false;
+ int ret = mtk_gps_set_param(MTK_PARAM_CMD_ENABLE_FULL_TRACKING, &g_enable_full_tracking);
+ if (ret < 0) {
+ LOGW("set measurement parameter fail");
+ }
+ }
+
+ if (enable_debug2app == DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_START_DEBUG) {
+ Mnld2DebugInterface_mnldUpdateGpsStatus(&g_mnld_ctx.fds.fd_debug_client,
+ MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STARTED);
+ }
+
+ do_gps_reset_hdlr();
+
+ if (g_mnld_ctx.gps_status.delete_aiding_flag) {
+ start_timer(g_mnld_ctx.gps_status.timer_reset, MNLD_GPS_RESET_TIMEOUT);
+ if (gps_control_gps_reset((int)g_mnld_ctx.gps_status.delete_aiding_flag) == -1) {
+ LOGE("gps_control_gps_reset failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+ }
+}
+
+static void do_gps_stopped_hdlr() {
+ mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+ if (hal->need_close_ack) {
+ hal->need_close_ack = false;
+ if (mnl2hal_gnss_status(MTK_GPS_STATUS_SESSION_END) == -1) {
+ LOGE("mnl2hal_gps_status failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ if (mnl2hal_gnss_status(MTK_GPS_STATUS_SESSION_ENGINE_OFF) == -1) {
+ LOGE("mnl2hal_gps_status failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ mnl2agps_gps_close();
+ }
+
+ mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+ if (agps->need_close_ack) {
+ agps->need_close_ack = false;
+ mnl2agps_close_gps_done();
+ }
+
+ mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+ if (geofence->need_close_ack) {
+ geofence->need_close_ack = false;
+ }
+
+ mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+ if (at_cmd_test->need_close_ack) {
+ at_cmd_test->need_close_ack = false;
+ /* add close ack message to at_cmd_test*/
+ }
+
+ mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+ if (factory->need_close_ack) {
+ factory->need_close_ack = false;
+ /* add close ack message to factory*/
+ }
+
+ mnld_gps_client* raw_meas = &g_mnld_ctx.gps_status.clients.raw_meas;
+ if (raw_meas->need_close_ack) {
+ raw_meas->need_close_ack = false;
+ /* add close ack message to raw_meas*/
+ }
+
+ if (enable_debug2app == DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_START_DEBUG) {
+ Mnld2DebugInterface_mnldUpdateGpsStatus(&g_mnld_ctx.fds.fd_debug_client,
+ MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STOPPED);
+ }
+ //Mnld2NlpUtilsInterface_cancelNlpLocation(&g_mnld_ctx.fds.fd_nlp_utils, NLP_REQUEST_SRC_MNL);
+
+ do_gps_reset_hdlr();
+}
+
+static bool is_all_gps_client_exit() {
+ mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+ mnld_gps_client* raw_meas = &g_mnld_ctx.gps_status.clients.raw_meas;
+ mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+ mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+ mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+ mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+ if (hal->gps_used == false && agps->gps_used == false
+ && at_cmd_test->gps_used == false && factory->gps_used == false
+ && geofence->gps_used == false && raw_meas->gps_used == false) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static bool is_a_gps_client_exist() {
+ mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+ mnld_gps_client* raw_meas = &g_mnld_ctx.gps_status.clients.raw_meas;
+ mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+ mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+ mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+ mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+ if (hal->gps_used == true || agps->gps_used == true
+ || at_cmd_test->gps_used == true || factory->gps_used == true || geofence->gps_used == true || raw_meas->gps_used == true) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void mtk_gps_clear_gps_user() {
+ mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+ mnld_gps_client* raw_meas = &g_mnld_ctx.gps_status.clients.raw_meas;
+ mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+ mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+ mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+ mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+
+ if (hal->gps_used)
+ hal->gps_used = false;
+ if (agps->gps_used)
+ agps->gps_used = false;
+ if (geofence->gps_used)
+ geofence->gps_used = false;
+ if (at_cmd_test->gps_used)
+ at_cmd_test->gps_used = false;
+ if (factory->gps_used)
+ factory->gps_used = false;
+ if (raw_meas->gps_used)
+ raw_meas->gps_used = false;
+}
+unsigned int mtk_gps_get_gps_user() {
+ mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+ mnld_gps_client* raw_meas = &g_mnld_ctx.gps_status.clients.raw_meas;
+ mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+ mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+ mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+ mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+ unsigned int gps_user = GPS_USER_UNKNOWN;
+
+ if (hal->gps_used)
+ gps_user |= GPS_USER_APP;
+ if (agps->gps_used)
+ gps_user |= GPS_USER_AGPS;
+ if (geofence->gps_used)
+ gps_user |= GPS_USER_GEOFENCE;
+ if (at_cmd_test->gps_used)
+ gps_user |= GPS_USER_AT_CMD;
+ if (factory->gps_used)
+ gps_user |= GPS_USER_META;
+ if (raw_meas->gps_used)
+ gps_user |= GPS_USER_RAW_MEAS;
+ return gps_user;
+}
+
+bool mtk_gps_get_nfw_visibility(MNLD_NFW_USER nfw_user) {
+ return g_mnld_ctx.nfw_user_visibility[nfw_user];
+}
+
+void mtk_gps_set_nfw_visibility(int usr, bool set_value) {
+ g_mnld_ctx.nfw_user_visibility[usr] = set_value;
+}
+
+void mtk_gps_set_nfw_visibility_all(bool set_value) {
+ int idx = 0;
+
+ for(idx = 0; idx < MNLD_NFW_USER_NUM; idx++) {
+ mtk_gps_set_nfw_visibility(idx, set_value);
+ }
+}
+
+void mtk_gps_dump_nfw_visibility(void) {
+ int idx = 0;
+
+ for(idx = 0; idx < MNLD_NFW_USER_NUM; idx++) {
+ LOGD("nfw_user_visibility[%d]:%d", idx, g_mnld_ctx.nfw_user_visibility[idx]);
+ }
+}
+
+int is_geofence_user_exist() {
+ mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+ return geofence->gps_used;
+}
+
+static bool is_all_hbd_gps_client_exit() {
+ mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+ mnld_gps_client* raw_meas = &g_mnld_ctx.gps_status.clients.raw_meas;
+ mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+ mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+ mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+ if (hal->gps_used == false && agps->gps_used == false && at_cmd_test->gps_used == false
+ && factory->gps_used == false && raw_meas->gps_used == false) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static bool is_a_hbd_gps_client_exist() {
+ mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+ mnld_gps_client* raw_meas = &g_mnld_ctx.gps_status.clients.raw_meas;
+ mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+ mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+ mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+ if (hal->gps_used == true || agps->gps_used == true || at_cmd_test->gps_used == true
+ || factory->gps_used == true || raw_meas->gps_used == true) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+extern int start_time_out;
+extern int nmea_data_time_out;
+static void fsm_gps_state_idle(mnld_gps_event event, int data1, int data2, void* data3) {
+ LOGD_ENG("fsm_gps_state_idle() data1=%d,data2=%d,data3=%p\n", data1, data2, data3);
+ switch (event) {
+ case GPS_EVENT_START: {
+ if (mnl2hal_request_wakelock() == -1) {
+ LOGE("mnl2hal_request_wakelock failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (get_gps_cmcc_log_enabled()) {
+ op01_log_gps_start();
+ }
+ #else
+ op01_log_gps_start();
+ #endif
+ g_mnld_ctx.gps_status.gps_start_time = get_tick();
+ g_mnld_ctx.gps_status.wait_first_location = true;
+ g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STARTING;
+ start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+ if(gps_control_gps_start((int)g_mnld_ctx.gps_status.delete_aiding_flag) == -1) {
+ LOGE("gps_control_gps_start fail because safe_sendto fail!!!");
+ }
+ g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+ break;
+ }
+ case GPS_EVENT_STOP: {
+ do_gps_stopped_hdlr();
+ break;
+ }
+ case GPS_EVENT_RESET: {
+ do_gps_reset_hdlr();
+ break;
+ }
+ case GPS_EVENT_START_DONE:
+ // Need fix by MNL,it will send MTK_AGPS_CB_START_REQ to mnld when stopping or started.
+ // LOGE("fsm_gps_state_stopping() unexpected event=%d", event);
+ // break;
+ case GPS_EVENT_STOP_DONE:
+ default: {
+ LOGE("fsm_gps_state_idle() unexpected gps_event=%d", event);
+ CRASH_TO_DEBUG();
+ break;
+ }
+ }
+}
+
+static void fsm_gps_state_starting(mnld_gps_event event, int data1, int data2, void* data3) {
+ LOGD_ENG("fsm_gps_state_starting() data2=%d,data3=%p\n", data2, data3);
+ switch (event) {
+ case GPS_EVENT_STOP:
+ case GPS_EVENT_START:
+ case GPS_EVENT_RESET: {
+ // do nothing
+ break;
+ }
+ case GPS_EVENT_START_DONE: {
+ stop_timer(g_mnld_ctx.gps_status.timer_start);
+ do_gps_started_hdlr(data1);
+ if (is_all_gps_client_exit()) {
+ g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STOPPING;
+ start_timer(g_mnld_ctx.gps_status.timer_stop, MNLD_GPS_STOP_TIMEOUT);
+#if defined(GPS_SUSPEND_SUPPORT)
+ if (mnld_gps_suspend_mode_entry_check()) {
+ if (gps_control_gps_suspend() == -1) {
+ LOGE("gps_control_gps_suspend failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ break; //skip stop flow
+ }
+#endif
+ if(gps_control_gps_stop() == -1) {
+ LOGE("gps_control_gps_stop fail because safe_sendto fail!!!");
+ }
+ } else {
+ g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STARTED;
+ //Update mtknav and qepo if download finish before start done.
+ if (mtknav_update_flag == true) {
+ mtknav_update_mtknav_file(mtknav_res);
+ mtknav_update_flag = false;
+ }
+ if (qepo_update_flag == true) {
+ qepo_update_quarter_epo_file(qepo_dl_res);
+ qepo_update_flag = false;
+ }
+ if (qepo_BD_update_flag == true) {
+ qepo_update_quarter_epo_bd_file(qepo_bd_dl_res);
+ qepo_BD_update_flag = false;
+ }
+ if (qepo_GA_update_flag == true) {
+ qepo_update_quarter_epo_ga_file(qepo_ga_dl_res);
+ qepo_GA_update_flag = false;
+ }
+ }
+ break;
+ }
+ case GPS_EVENT_STOP_DONE:
+ default: {
+ LOGE("fsm_gps_state_starting() unexpected gps_event=%d", event);
+ CRASH_TO_DEBUG();
+ break;
+ }
+ }
+}
+
+static void fsm_gps_state_started(mnld_gps_event event, int data1, int data2, void* data3) {
+ LOGD_ENG("fsm_gps_state_started() data1=%d,data2=%d,data3=%p\n", data1, data2, data3);
+ switch (event) {
+ case GPS_EVENT_START: {
+ do_gps_started_hdlr(0);
+ break;
+ }
+ case GPS_EVENT_STOP: {
+ if (is_all_gps_client_exit()) {
+ g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STOPPING;
+ start_timer(g_mnld_ctx.gps_status.timer_stop, MNLD_GPS_STOP_TIMEOUT);
+
+#if defined(GPS_SUSPEND_SUPPORT)
+ if (mnld_gps_suspend_mode_entry_check()) {
+ if (gps_control_gps_suspend() == -1) {
+ LOGE("gps_control_gps_suspend failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ break; //skip stop flow
+ }
+#endif
+ if(gps_control_gps_stop() == -1) {
+ LOGE("gps_control_gps_stop fail because safe_sendto fail!!!");
+ }
+ } else {
+ do_gps_stopped_hdlr();
+ }
+ break;
+ }
+ case GPS_EVENT_RESET: {
+ if (g_mnld_ctx.gps_status.delete_aiding_flag) {
+ start_timer(g_mnld_ctx.gps_status.timer_reset, MNLD_GPS_RESET_TIMEOUT);
+ if (gps_control_gps_reset((int)g_mnld_ctx.gps_status.delete_aiding_flag) == -1) {
+ LOGE("gps_control_gps_reset failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+ }
+ break;
+ }
+ case GPS_EVENT_START_DONE:
+ // MNL restart.
+ if (GPS_USER_APP & mtk_gps_get_gps_user()) {
+ if (mnl2agps_reaiding_req() == -1) {
+ LOGE("mnl2agps_reaiding_req failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ }
+ LOGE("fsm_gps_state_started() unexpected event=%d", event);
+ break;
+ case GPS_EVENT_STOP_DONE:
+ default: {
+ LOGE("fsm_gps_state_started() unexpected gps_event=%d", event);
+ CRASH_TO_DEBUG();
+ break;
+ }
+ }
+}
+
+static void fsm_gps_state_stopping(mnld_gps_event event, int data1, int data2, void* data3) {
+ LOGD_ENG("fsm_gps_state_stopping() data1=%d,data2=%d,data3=%p\n", data1, data2, data3);
+ switch (event) {
+ case GPS_EVENT_START:
+ case GPS_EVENT_STOP: {
+ // do nothing
+ break;
+ }
+ case GPS_EVENT_RESET: {
+ do_gps_reset_hdlr();
+ break;
+ }
+ case GPS_EVENT_STOP_DONE: {
+ stop_timer(g_mnld_ctx.gps_status.timer_stop);
+ do_gps_stopped_hdlr();
+ if (is_a_gps_client_exist()) {
+ g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STARTING;
+ start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+
+ if(gps_control_gps_start((int)g_mnld_ctx.gps_status.delete_aiding_flag) == -1) {
+ LOGE("gps_control_gps_start fail because safe_sendto fail!!!");
+ }
+ g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+ } else {
+ if(mnl2hal_release_wakelock() == -1) {
+ LOGE("mnl2hal_release_wakelock fail because safe_sendto fail!!!");
+ }
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (get_gps_cmcc_log_enabled()) {
+ op01_log_gps_stop();
+ }
+ #else
+ op01_log_gps_stop();
+ #endif
+ g_mnld_ctx.gps_status.gps_stop_time = get_tick();
+ g_mnld_ctx.gps_status.wait_first_location = false;
+ g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_IDLE;
+ }
+ break;
+ }
+#if defined(GPS_SUSPEND_SUPPORT)
+ case GPS_EVENT_SUSPEND_DONE: {
+ stop_timer(g_mnld_ctx.gps_status.timer_stop);
+ do_gps_stopped_hdlr();
+ if (is_a_gps_client_exist()) {
+ g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STARTING;
+ start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+ if(gps_control_gps_start((int)g_mnld_ctx.gps_status.delete_aiding_flag) == -1) {
+ LOGE("gps_control_gps_start fail because safe_sendto fail!!!");
+ }
+ g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+ } else {
+ if(mnl2hal_release_wakelock() == -1) {
+ LOGE("mnl2hal_release_wakelock fail because safe_sendto fail!!!");
+ }
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (get_gps_cmcc_log_enabled()) {
+ op01_log_gps_stop();
+ }
+ #else
+ op01_log_gps_stop();
+ #endif
+ g_mnld_ctx.gps_status.gps_stop_time = get_tick();
+ g_mnld_ctx.gps_status.wait_first_location = false;
+ g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_SUSPEND;
+
+ if ((mnld_gps_suspend_ext_is_enabled() &&
+ mnld_gps_suspend_ext_get_timeout_sec() > 0)) {
+ LOGD("Change from clock ext suspend mode to close after %d ms", mnld_gps_suspend_ext_get_timeout_sec());
+ // Need to change suspend to close after timeout
+ g_mnld_ctx.gps_status.is_suspend_timer_running = true;
+ start_timer_alarm(g_mnld_ctx.fds.fd_suspend_timer,
+ mnld_gps_suspend_ext_get_timeout_sec());
+ } else if ((g_mnld_ctx.screen_status == SCREEN_STATUS_OFF) &&
+ mnld_gps_suspend_is_enabled() &&
+ mnld_gps_suspend_get_timeout_sec() > 0) {
+ LOGD("Change from suspend mode to close after %d ms", mnld_gps_suspend_get_timeout_sec());
+ // Need to change suspend to close after timeout
+ g_mnld_ctx.gps_status.is_suspend_timer_running = true;
+ start_timer_alarm(g_mnld_ctx.fds.fd_suspend_timer,
+ mnld_gps_suspend_get_timeout_sec());
+ }
+ }
+ break;
+ }
+#endif /* GPS_SUSPEND_SUPPORT */
+ case GPS_EVENT_START_DONE:
+ // MNL restart.
+ LOGE("fsm_gps_state_stopping() unexpected event=%d", event);
+ break;
+ default: {
+ LOGE("fsm_gps_state_stopping() unexpected gps_event=%d", event);
+ CRASH_TO_DEBUG();
+ break;
+ }
+ }
+}
+
+#if defined(GPS_SUSPEND_SUPPORT)
+static void fsm_gps_state_suspend(mnld_gps_event event, int data1, int data2, void* data3) {
+ LOGD("fsm_gps_state_suspend() data1=%d,data2=%d,data3=%p\n", data1, data2, data3);
+ switch (event) {
+ case GPS_EVENT_START: {
+ if (mnl2hal_request_wakelock() == -1) {
+ LOGE("mnl2hal_request_wakelock failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (get_gps_cmcc_log_enabled()) {
+ op01_log_gps_start();
+ }
+ #else
+ op01_log_gps_start();
+ #endif
+ g_mnld_ctx.gps_status.gps_start_time = get_tick();
+ g_mnld_ctx.gps_status.wait_first_location = true;
+ g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STARTING;
+ start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+
+ // stop suspend timer
+ if (g_mnld_ctx.gps_status.is_suspend_timer_running) {
+ stop_timer_alarm(g_mnld_ctx.fds.fd_suspend_timer);
+ g_mnld_ctx.gps_status.is_suspend_timer_running = false;
+ }
+
+ if(gps_control_gps_start((int)g_mnld_ctx.gps_status.delete_aiding_flag) == -1) {
+ LOGE("gps_control_gps_start fail because safe_sendto fail!!!");
+ }
+ g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+ break;
+ }
+ case GPS_EVENT_STOP: {
+ do_gps_stopped_hdlr();
+ break;
+ }
+ case GPS_EVENT_RESET: {
+ do_gps_reset_hdlr();
+ break;
+ }
+ case GPS_EVENT_SUSPEND_CLOSE: {
+ if (g_mnld_ctx.gps_status.is_suspend_timer_running) {
+ stop_timer_alarm(g_mnld_ctx.fds.fd_suspend_timer);
+ g_mnld_ctx.gps_status.is_suspend_timer_running = false;
+ }
+ if (gps_control_gps_suspend_to_close() == -1) {
+ LOGE("gps_control_gps_suspend_to_close failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_IDLE;
+ break;
+ }
+ case GPS_EVENT_START_DONE:
+ // Need fix by MNL,it will send MTK_AGPS_CB_START_REQ to mnld when stopping or started.
+ // LOGE("fsm_gps_state_stopping() unexpected event=%d", event);
+ // break;
+ case GPS_EVENT_STOP_DONE:
+ default: {
+ LOGE("fsm_gps_state_idle() unexpected gps_event=%d", event);
+ CRASH_TO_DEBUG();
+ break;
+ }
+ }
+}
+#endif
+
+int mnld_gps_controller_mnl_nmea_timeout(void) {
+ if(mnld_is_gps_or_ofl_started_done()) {
+ if (g_mnld_ctx.gps_status.timer_nmea_monitor != 0) {
+ // stop_timer(g_mnld_ctx.gps_status.timer_nmea_monitor);
+ LOGD("Start NMEA timer");
+ start_timer(g_mnld_ctx.gps_status.timer_nmea_monitor, nmea_data_time_out);
+ }
+ } else {
+ LOGD("GPS not in started done state, ignore timer for NMEA monitor!!!");
+ }
+ return 0;
+}
+
+int mnld_gps_start_nmea_monitor() {
+ if(mnld_is_gps_or_ofl_started_done()) {
+ if (g_mnld_ctx.gps_status.timer_nmea_monitor != 0) {
+ start_timer(g_mnld_ctx.gps_status.timer_nmea_monitor, nmea_data_time_out);
+ }
+ } else {
+ LOGD("GPS not in started done state, ignore timer for NMEA monitor!!!");
+ }
+ return 0;
+}
+
+int mnld_gps_stop_nmea_monitor() {
+ if (g_mnld_ctx.gps_status.timer_nmea_monitor != 0) {
+ stop_timer(g_mnld_ctx.gps_status.timer_nmea_monitor);
+ }
+ return 0;
+}
+
+static void mnld_fsm(mnld_gps_event event, int data1, int data2, void* data3) {
+ mnld_gps_state gps_state = g_mnld_ctx.gps_status.gps_state;
+
+ unsigned int user_bitmap;
+ user_bitmap = mtk_gps_get_gps_user();
+ LOGW("mnld_fsm() state=[%s] event=[%s], user=0x%08x",
+ get_mnld_gps_state_str(gps_state), get_mnld_gps_event_str(event),
+ user_bitmap);
+
+ switch (gps_state) {
+ case MNLD_GPS_STATE_IDLE: {
+ fsm_gps_state_idle(event, data1, data2, data3);
+ break;
+ }
+ case MNLD_GPS_STATE_STARTING: {
+ fsm_gps_state_starting(event, data1, data2, data3);
+ break;
+ }
+ case MNLD_GPS_STATE_STARTED: {
+ fsm_gps_state_started(event, data1, data2, data3);
+ break;
+ }
+ case MNLD_GPS_STATE_STOPPING: {
+ fsm_gps_state_stopping(event, data1, data2, data3);
+ break;
+ }
+#if defined(GPS_SUSPEND_SUPPORT)
+ case MNLD_GPS_STATE_SUSPEND: {
+ fsm_gps_state_suspend(event, data1, data2, data3);
+ break;
+ }
+#endif
+ default: {
+ LOGE("mnld_fsm() unexpected gps_state=%d", gps_state);
+ CRASH_TO_DEBUG();
+ break;
+ }
+ }
+}
+
+/*****************************************
+HAL -> MNL
+*****************************************/
+static void hal_gnss_init(int fd) {
+ client_ctx* ctx = client_list_get_ctx_by_fd(&g_hal_basic_client_list, fd);
+
+ ctx->gnss_inited = true;
+
+ LOGW("hal_gnss_init, fd:[%d], init:%d", fd, g_mnld_ctx.gps_status.is_gps_init);
+ if(g_mnld_ctx.gps_status.is_gps_init != true) {
+ g_mnld_ctx.gps_status.is_gps_init = true;
+ if(-1 == mnl2agps_gps_init()) {
+ LOGW("mnl2agps_gps_init fail.");
+ }
+ }
+}
+
+static void hal_gnss_start(int fd) {
+ client_ctx* ctx = client_list_get_ctx_by_fd(&g_hal_basic_client_list, fd);
+ mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+
+ ctx->gnss_started = true;
+
+ LOGD("hal_gnss_start, fd=[%d], used:%d", fd, hal->gps_used);
+ if(hal->gps_used != true) {
+ hal->gps_used = true;
+ hal->need_open_ack = true;
+ hal->need_close_ack = false;
+ hal_start_gps_trigger_epo_download();
+ mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+ } else { //If GPS in use, report to HAL directely
+ mnl2hal_gnss_status_one_client(MTK_GPS_STATUS_SESSION_ENGINE_ON, fd);
+ mnl2hal_gnss_status_one_client(MTK_GPS_STATUS_SESSION_BEGIN, fd);
+ }
+}
+
+void hal_gnss_stop(int fd) {
+ client_ctx* ctx = client_list_get_ctx_by_fd(&g_hal_basic_client_list, fd);
+ mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+
+ ctx->gnss_started = false;
+
+ LOGW("hal_gnss_stop, fd:[%d], used:%d", fd, hal->gps_used);
+
+ if((hal->gps_used == true) && client_list_is_all_gnss_stop(&g_hal_basic_client_list)) {
+ hal->gps_used = false;
+ hal->need_open_ack = false;
+ hal->need_close_ack = true;
+ mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+ } else { //No need stop, report to HAL directely
+ LOGW("GPS HAL not active...");
+ }
+}
+
+void hal_gnss_cleanup(int fd) {
+ client_ctx* ctx = client_list_get_ctx_by_fd(&g_hal_basic_client_list, fd);
+
+ ctx->gnss_inited = false;
+
+ LOGW("hal_gnss_cleanup, fd:[%d], init:%d", fd, g_mnld_ctx.gps_status.is_gps_init);
+ if((g_mnld_ctx.gps_status.is_gps_init == true) && client_list_is_all_gnss_cleanup(&g_hal_basic_client_list)) {
+ g_mnld_ctx.gps_status.is_gps_init = false;
+ mnl2agps_gps_cleanup();
+ }
+}
+
+static void hal_raw_meas_gps_start(int fd) {
+ client_ctx* ctx = client_list_get_ctx_by_fd(&g_hal_basic_client_list, fd);
+ mnld_gps_client* raw_meas = &g_mnld_ctx.gps_status.clients.raw_meas;
+
+ ctx->meas_started = true;
+
+ LOGW("hal_raw_meas_gps_start, fd:[%d], meas_open:%d", fd, raw_meas->gps_used);
+ if(raw_meas->gps_used != true) {
+ raw_meas->gps_used = true;
+ raw_meas->need_open_ack = true;
+ raw_meas->need_close_ack = false;
+ mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+ }
+}
+
+void hal_raw_meas_gps_stop(int fd) {
+ client_ctx* ctx = client_list_get_ctx_by_fd(&g_hal_basic_client_list, fd);
+ mnld_gps_client* raw_meas = &g_mnld_ctx.gps_status.clients.raw_meas;
+ ctx->meas_started = false;
+
+ LOGW("hal_raw_meas_gps_stop, fd:[%d], meas_open:%d", fd, raw_meas->gps_used);
+ if((raw_meas->gps_used == true) && client_list_is_all_meas_stop(&g_hal_basic_client_list)) {
+ raw_meas->gps_used = false;
+ raw_meas->need_open_ack = false;
+ raw_meas->need_close_ack = true;
+ mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+ }
+}
+
+static void hal_set_measurement_enable(bool enabled, int fd) {
+ LOGD("hal_set_measurement_enable enabled=%d", enabled);
+
+ g_mnld_ctx.gps_status.is_gps_meas_enabled = enabled;
+
+ if(enabled) {
+ hal_raw_meas_gps_start(fd);
+ } else {
+ hal_raw_meas_gps_stop(fd);
+ }
+}
+
+static void hal_gps_inject_time(int64_t time, int64_t time_reference, int uncertainty) {
+ LOGD("hal_gps_inject_time time=%lu time_reference=%lu uncertainty=%d",
+ time, time_reference, uncertainty);
+ // TODO libmnl.so
+ ntp_context ntp_inject;
+
+ memset(&ntp_inject, 0, sizeof(ntp_context));
+ ntp_inject.time = time;
+ ntp_inject.timeReference = time_reference;
+ ntp_inject.uncertainty = uncertainty;
+ if (mnld_is_gps_started_done()) {
+ mtk_gps_inject_ntp_time((MTK_GPS_NTP_T*)&ntp_inject);
+ }
+}
+
+static void hal_gps_inject_location(double lat, double lng, float acc) {
+ MTK_GPS_NLP_T nlp_inject;
+ nlp_context context;
+ mnl_agps_location_time mnl_agps_location_sync_data;
+ memset(&mnl_agps_location_sync_data, 0, sizeof(mnl_agps_location_time));
+ mnl_agps_location_sync_data.alt_valid = false;
+ float altitude = 0.0f;
+ mnl_agps_location_sync_data.alt = 0.0f;
+ mnl_agps_location_sync_data.source_valid = true;
+ mnl_agps_location_sync_data.source_gnss = false;
+ mnl_agps_location_sync_data.source_nlp = true;
+ mnl_agps_location_sync_data.source_sensor = false;
+
+ // LOGW("lat=%f lng=%f acc=%f", lat, lng, acc);
+ memset(&nlp_inject, 0, sizeof(MTK_GPS_NLP_T));
+ memset(&context, 0, sizeof(nlp_context));
+ if (clock_gettime(CLOCK_MONOTONIC , &context.ts) == -1) {
+ LOGE("clock_gettime failed reason=[%s]\n", strerror(errno));
+ return;
+ }
+ nlp_inject.accuracy = acc;
+ nlp_inject.lattidude = lat;
+ nlp_inject.longitude = lng;
+ nlp_inject.timeReference[0] = (UINT32)context.ts.tv_sec;
+ nlp_inject.timeReference[1] = (UINT32)context.ts.tv_nsec;
+ nlp_inject.started = (UINT8)mnld_is_gps_started_done();
+ nlp_inject.type = 0;
+ if (mnld_is_gps_started_done()) {
+ mtk_gps_inject_nlp_location(&nlp_inject);
+ }
+ mnl_agps_location_sync_data.lat = lat;
+ mnl_agps_location_sync_data.lng = lng;
+ mnl_agps_location_sync_data.acc = acc;
+ mnl_agps_location_sync_data.sv_inuse_num_valid = mnld_get_sv_inuse_num_valid();
+ mnl_agps_location_sync_data.sv_inuse_num = mnld_get_sv_inuse_num();
+
+ mnld_nfw_mnl2agps_location_sync(&mnl_agps_location_sync_data);
+}
+
+static void hal_gps_delete_aiding_data(int flags) {
+ LOGW("hal_gps_delete_aiding_data flags=0x%x", flags);
+ if (mnl2agps_delete_aiding_data(flags) == -1) {
+ LOGE("mnl2agps_delete_aiding_data failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+ hal->need_reset_ack = false; // HAL no need the ACK
+ g_mnld_ctx.gps_status.delete_aiding_flag |= (unsigned int)flags;
+ mnld_fsm(GPS_EVENT_RESET, 0, 0, NULL);
+}
+
+static void hal_gps_set_position_mode(gps_pos_mode mode, gps_pos_recurrence recurrence,
+ int min_interval, int preferred_acc, int preferred_time, bool lowPowerMode) {
+ LOGD("hal_gps_set_position_mode mode=%d recurrence=%d min_interval=%d preferred_acc=%d preferred_time=%d lowPowerMode=%d",
+ mode, recurrence, min_interval, preferred_acc, preferred_time, lowPowerMode);
+ if (mnl2agps_set_position_mode(mode) == -1) {
+ LOGE("mnl2agps_set_position_mode failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void hal_data_conn_open(const char* apn) {
+ LOGD("hal_data_conn_open");
+ if (mnl2agps_data_conn_open(apn) == -1) {
+ LOGE("mnl2agps_data_conn_open failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void hal_data_conn_open_with_apn_ip_type(uint64_t network_handle,
+ const char* apn, apn_ip_type ip_type) {
+ LOGD("hal_data_conn_open_with_apn_ip_type network_handle=%lu apn=%s ip_type=%d",
+ network_handle, apn, ip_type);
+ if (mnl2agps_data_conn_open_ip_type(apn, ip_type, true, network_handle) == -1) {
+ LOGE("mnl2agps_data_conn_open_ip_type failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void hal_data_conn_closed() {
+ LOGD("hal_data_conn_closed");
+ if (mnl2agps_data_conn_closed() == -1) {
+ LOGE("mnl2agps_data_conn_closed failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void hal_data_conn_failed() {
+ LOGD("hal_data_conn_failed");
+ if (mnl2agps_data_conn_failed() == -1) {
+ LOGE("mnl2agps_data_conn_failed failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void hal_set_server(agps_type type, const char* hostname, int port) {
+ LOGD("hal_set_server");
+ if (mnl2agps_set_server(type, hostname, port) == -1) {
+ LOGE("mnl2agps_set_server failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void hal_set_ref_location(cell_type type, int mcc, int mnc, int lac, int cid) {
+ LOGD("hal_set_ref_location");
+ if (mnl2agps_set_ref_loc(type, mcc, mnc, lac, cid) == -1) {
+ LOGE("mnl2agps_set_ref_loc failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void hal_set_id(agps_id_type type, const char* setid) {
+ LOGD("hal_set_id");
+ if (mnl2agps_set_set_id(type, setid) == -1) {
+ LOGE("mnl2agps_set_set_id failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void hal_ni_message(const char* msg, int len) {
+ LOGD("hal_ni_message, len=%d", len);
+ if (mnl2agps_ni_message(msg, len) == -1) {
+ LOGE("mnl2agps_ni_message failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void hal_ni_respond(int notif_id, ni_user_response_type user_response) {
+ LOGD("hal_ni_respond notif_id=%d user_response=%d", notif_id, user_response);
+ if (mnl2agps_ni_respond(notif_id, user_response) == -1) {
+ LOGE("mnl2agps_ni_respond failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void hal_update_network_state(uint64_t network_handle, bool is_connected,
+ unsigned short capabilities, const char* apn) {
+ LOGD("hal_update_network_state networkHandle=%lu isConnected=%d capabilities=%d apn=[%s]",
+ network_handle, is_connected, capabilities, apn);
+ /***Remove network state update to AGPSD, due to this msg type never used in AGPSD***/
+ //mnl2agps_update_network_state(connected, type, roaming, extra_info);
+ if (mnl2agps_update_network_state_with_handle(network_handle, is_connected, capabilities, apn) == -1) {
+ LOGE("mnl2agps_update_network_state_with_handle failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ mnl_epo_status* epo_status = &g_mnld_ctx.epo_status;
+ if(is_connected) {
+ qepo_invalid_dl_cnt_clear();
+ }
+ epo_status->is_network_connected = is_connected;
+ if ((capabilities & NOT_METERED) == NOT_METERED) {
+ epo_status->is_wifi_connected = is_connected;
+ } else {
+ epo_status->is_wifi_connected = false;
+ }
+
+ if (mnld_is_gps_or_ofl_started()) {
+ epo_read_cust_config();
+ if (is_connected && epo_status->is_epo_downloading == false &&
+ epo_downloader_is_file_invalid() && epo_is_epo_download_enabled()) {
+ epo_status->is_epo_downloading = true;
+ if (epo_downloader_start() == -1) {
+ LOGE("epo_downloader_start failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ }
+ } else if ((capabilities & NOT_METERED) == NOT_METERED) {
+ epo_read_cust_config();
+ if (is_connected && epo_status->is_epo_downloading == false && epo_is_wifi_trigger_enabled() &&
+ epo_downloader_is_file_invalid() && epo_is_epo_download_enabled()) {
+ epo_status->is_epo_downloading = true;
+ if (epo_downloader_start() == -1) {
+ LOGE("epo_downloader_start failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ }
+ }
+}
+
+void hal_start_gps_trigger_epo_download() {
+ mnl_epo_status* epo_status = &g_mnld_ctx.epo_status;
+ LOGD_ENG("is_network_connected=%d,is_epo_downloading=%d",
+ epo_status->is_network_connected, epo_status->is_epo_downloading);
+ epo_read_cust_config();
+ if (epo_status->is_epo_downloading == false
+ && epo_downloader_is_file_invalid() && epo_is_epo_download_enabled()) {
+ epo_status->is_epo_downloading = true;
+ epo_downloader_start();
+ }
+}
+
+bool is_network_connected() {
+ mnl_epo_status* epo_status = &g_mnld_ctx.epo_status;
+ return epo_status->is_network_connected;
+}
+
+bool is_wifi_network_connected() {
+ mnl_epo_status* epo_status = &g_mnld_ctx.epo_status;
+ return epo_status->is_wifi_connected;
+}
+
+static void hal_update_network_availability(int available, const char* apn) {
+ LOGD("hal_update_network_availability available=%d apn=[%s]", available, apn);
+ if (mnl2agps_update_network_availability(available, apn) == -1) {
+ LOGE("mnl2agps_update_network_availability failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void hal_set_gps_full_tracking(bool enabled) {
+ LOGD("hal_set_gps_full_tracking enabled=%d", enabled);
+
+ g_enable_full_tracking = enabled;
+ if (mnld_is_gps_or_ofl_started_done()) {
+ int ret = mtk_gps_set_param(MTK_PARAM_CMD_ENABLE_FULL_TRACKING, &g_enable_full_tracking);
+ if (ret < 0) {
+ LOGW("set full tracking parameter fail");
+ }
+ }
+}
+
+static void hal_set_gps_navigation(bool enabled) {
+ LOGD("hal_set_gps_navigation enabled=%d", enabled);
+ g_mnld_ctx.gps_status.is_gps_navi_enabled = enabled;
+}
+
+static void hal_set_vzw_debug(bool enabled) {
+ LOGD("hal_set_vzw_debug enabled=%d", enabled);
+ if (mnl2agps_vzw_debug_screen_enable(enabled) == -1) {
+ LOGE("mnl2agps_vzw_debug_screen_enable failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void hal_update_gnss_config(const char* config_data, int length) {
+ int ret = mnl2agps_update_configuration(config_data, length);
+ LOGD("hal_update_gnss_config length=%d, ret=%d", length, ret);
+}
+
+static void hal_set_sv_blacklist(long long* blacklist, int size) {
+ int i = 0;
+ memset(svBlacklist.sv_list, 0, sizeof(svBlacklist.sv_list));
+ memcpy(svBlacklist.sv_list, blacklist, sizeof(svBlacklist.sv_list));
+
+ if(mnld_is_gps_or_ofl_started_done()) {
+ LOGD("hal_set_sv_blacklist to mnl");
+ int ret = mtk_gps_set_param(MTK_PARAM_CMD_SET_SV_BLACKLIST, &svBlacklist); //set to libmnl in run time
+ if (ret < 0) {
+ LOGW("set SV blacklist parameter fail");
+ }
+ } else {
+ LOGD("hal_set_sv_blacklist gps not start");
+ }
+ for(i = 0; i < size; i++) {
+ LOGD("hal_set_sv_blacklist constellation:%d, svidlist:0x%llx", i, blacklist[i]);
+ }
+}
+
+MTK_GPS_PARAM_MEAS_CORR meas_correction;
+static void hal_set_correction(measurement_corrections* corrections) {
+ int idx = 0;
+
+ memset(&meas_correction, 0, sizeof(MTK_GPS_PARAM_MEAS_CORR));
+ memcpy(&meas_correction, corrections, sizeof(MTK_GPS_PARAM_MEAS_CORR));
+
+ LOGD("CORRECTIONS: lat(%f), lon(%f), alt(%f), hUnc(%f), vUncs(%f), toa(%lld), svcnt(%lld)",
+ meas_correction.latitudeDegrees, meas_correction.longitudeDegrees, meas_correction.altitudeMeters, meas_correction.horizontalPositionUncertaintyMeters, meas_correction.verticalPositionUncertaintyMeters, meas_correction.toaGpsNanosecondsOfWeek, meas_correction.num_satCorrection);
+ if(meas_correction.num_satCorrection > MTK_MNLD_GNSS_MAX_SVS) {
+ meas_correction.num_satCorrection = MTK_MNLD_GNSS_MAX_SVS;
+ }
+ for(idx = 0; idx < meas_correction.num_satCorrection; idx++) {
+ LOGD_ENG("SV CORRETION[%d]:Flags(0x%x), constellation(%d), svid(%d), cFHz(%f), probLos(%f), ePL(%f), ePLUnc(%f)",
+ idx, meas_correction.satCorrections[idx].singleSatCorrectionFlags, meas_correction.satCorrections[idx].constellation, meas_correction.satCorrections[idx].svid, meas_correction.satCorrections[idx].carrierFrequencyHz,
+ meas_correction.satCorrections[idx].probSatIsLos, meas_correction.satCorrections[idx].excessPathLengthMeters, meas_correction.satCorrections[idx].excessPathLengthUncertaintyMeters);
+ LOGD_ENG("SV CORRETION[%d] Reflecting Plane:lat(%f), lgt(%f), alt(%f), azim(%f)",
+ idx, meas_correction.satCorrections[idx].reflectingPlane.latitudeDegrees, meas_correction.satCorrections[idx].reflectingPlane.longitudeDegrees, meas_correction.satCorrections[idx].reflectingPlane.altitudeMeters, meas_correction.satCorrections[idx].reflectingPlane.azimuthDegrees);
+ }
+ if (mnld_is_gps_or_ofl_started_done()) {
+ INT32 ret = 0;
+ ret = mtk_gps_set_param(MTK_PARAM_CMD_CONFIG_BLUE_MEAS_CORR, &meas_correction);
+ if (ret < 0) {
+ LOGW("set correction fail");
+ }
+ }
+}
+
+/*Update location visibility of nfw user(s) to bool arry g_mnld_ctx.nfw_user_visibility*/
+static void mnld_nfw_visiblity_update(char* proxyApps, int length) {
+ char *app_name_start = proxyApps;
+ unsigned int app_name_len = 0;
+ int idx = 0;
+ unsigned int set_app_idx = 0;
+
+ memset(g_mnld_ctx.nfw_user_visibility, 0, sizeof(g_mnld_ctx.nfw_user_visibility)); //All NFW app users are not allowed to get GPS location as default.
+ if(proxyApps == NULL) {
+ LOGD("proxyApps NULL, Set all NFW user denied!!!");
+ } else if((length == 0) || (strlen(proxyApps) == 0)) {
+ LOGD("Set all NFW user denied!!!");
+ } else {
+ if(length > MNLD_NFW_USER_NAME_LEN*MNLD_NFW_USER_NUM_MAX) {
+ length = MNLD_NFW_USER_NAME_LEN*MNLD_NFW_USER_NUM_MAX;
+ }
+ app_name_start = proxyApps;
+ for(idx = 0; idx <= length; idx++) {
+ if(proxyApps[idx] == ' ' || proxyApps[idx] == '\0') { //APP name divided by ' '
+ //int app_idx = 0;
+ app_name_len = &proxyApps[idx] - app_name_start; //calculate app name length by poiter shift.
+ if(app_name_len >= MNLD_NFW_USER_NAME_LEN) {
+ app_name_len = MNLD_NFW_USER_NAME_LEN - 1;
+ }
+
+#if 0
+ for(app_idx = 0; app_idx < MNLD_NFW_USER_NUM; app_idx++) {
+ if((app_name_len == strlen(nfw_app_name_list[app_idx]))
+ && (!strncmp(app_name_start, nfw_app_name_list[app_idx], strlen(nfw_app_name_list[app_idx])))) { //APP name matched
+ LOGD("Set visibility for NFW User[%d]: %s, len:%d", app_idx, nfw_app_name_list[app_idx], app_name_len);
+ g_mnld_ctx.nfw_user_visibility[app_idx] = true; //Set visibility
+ }
+ }
+#else
+ //Ignore proxy package name comparing, use visibility update package name as notify name
+ MNLD_STRNCPY(nfw_app_name_list[set_app_idx], app_name_start, app_name_len+1);
+ MNLD_STRNCPY(nfw_user_notify[set_app_idx].proxy_app_package_name, app_name_start, app_name_len+1);
+ MNLD_STRNCPY(nfw_user_notify_default[set_app_idx].proxy_app_package_name, app_name_start, app_name_len+1);
+ g_mnld_ctx.nfw_user_visibility[set_app_idx] = true; //Set visibility
+ LOGD("Set NFW user[%d] allowed:%s", set_app_idx, nfw_app_name_list[set_app_idx]);
+#endif
+
+ if(proxyApps[idx] == ' ') {
+ set_app_idx++;
+ app_name_start = &proxyApps[idx+1]; //Point to the next APP name
+ }
+ }
+ }
+ }
+}
+
+static void hal_set_nfw_access(char* proxyApps, int length) {
+ if(proxyApps != NULL) {
+ LOGD("hal_set_nfw_access length=%d, proxyApps:%s, nlp visibility ctrl:%d, gnss visibility ctrl:%d ", length, proxyApps, mnld_nfw_ctrl_nlp_enabled(), mnld_nfw_ctrl_gnss_enabled());
+ } else {
+ LOGD("hal_set_nfw_access length=%d, proxyApps:NULL, nlp visibility ctrl:%d, gnss visibility ctrl:%d ", length, mnld_nfw_ctrl_nlp_enabled(), mnld_nfw_ctrl_gnss_enabled());
+ }
+
+ if(mnld_nfw_ctrl_nlp_enabled() || mnld_nfw_ctrl_gnss_enabled()) {
+ mnld_nfw_visiblity_update(proxyApps, length);
+ } else {
+ mtk_gps_set_nfw_visibility_all(true);
+ }
+ if (mnl2agps_update_gnss_access_control(g_mnld_ctx.nfw_user_visibility[MNLD_NFW_USER_AGPS]) == -1) {
+ LOGE("mnl2agps_update_gnss_access_control failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void hal_send_pmtk(char* msg, int len) {
+ if(msg != NULL) {
+ LOGD("hal_send_pmtk[%s] length=%d", msg, len);
+ }
+
+ gps_controller_rcv_pmtk(msg);
+}
+
+static void hal_set_epo_enable(epo_bitmap epo_cfg) {
+ LOGD("hal_set_epo_enable:0x%x", epo_cfg);
+ switch (epo_cfg & 0x03) {
+ case 0x00: //Disable EPO & QEPO
+ mnld_write_cfg("EPO_enabled", "0");
+ epo_write_cfg("EPO_ENABLE", "0"); //Disable EPO download
+ break;
+ case 0x01: //Enable EPO, Disable QEPO
+ mnld_write_cfg("EPO_enabled", "2");
+ epo_write_cfg("EPO_ENABLE", "1"); //Enable EPO download
+ break;
+ case 0x02: //Disable EPO, Enable QEPO
+ mnld_write_cfg("EPO_enabled", "3");
+ epo_write_cfg("EPO_ENABLE", "0"); //Disable EPO download
+ break;
+ case 0x03: //Enable EPO & QEPO
+ mnld_write_cfg("EPO_enabled", "1");
+ epo_write_cfg("EPO_ENABLE", "1"); //Enable EPO download
+ break;
+ default:
+ LOGW("invalid epo_cfg:0x%x", epo_cfg);
+ break;
+ }
+}
+
+static void hal_set_ttff_acc(ttff_acc acc_mode) {
+ MTK_GPS_MNL_CONFIG_XML_PARAM mnl_config_xml;
+ memset(&mnl_config_xml, 0, sizeof(mnl_config_xml));
+ sprintf(mnl_config_xml.xml_feature_name, "TTFFAcc");
+ mnl_config_xml.xml_feature_setting_number = 1;
+ mnl_config_xml.xml_feature_setting[0][0] = (double)acc_mode;
+ mnl_config_xml.xml_feature_config = 1;
+ LOGD("acc_mode:%d", acc_mode);
+ mtk_gps_set_MNL_Config_XML_param(MNL_READ_WRITE_PATH, &mnl_config_xml);
+}
+
+//Sync mnld server support capability
+static void hal_basic_client_capability_update(int fd, mnl_hal_basic_client_cap *cap) {
+ client_ctx * pclient;
+ pclient = client_list_get_ctx_by_fd(&g_hal_basic_client_list, fd);
+ DUMP_BASIC_CLIENT_CAP(cap);
+ if(pclient == NULL) {
+ LOGE("Get client context faild!!!!fd:%d", fd);
+ return;
+ }
+
+ memcpy(&(pclient->client_cap.basic_client_cap), cap, sizeof(mnl_hal_basic_client_cap));
+}
+
+//Sync mnld server support capability
+static void hal_ext_client_capability_update(int fd, mnl_hal_ext_client_cap *cap) {
+ client_ctx * pclient;
+ pclient = client_list_get_ctx_by_fd(&g_hal_ext_client_list, fd);
+ DUMP_EXT_CLIENT_CAP(cap);
+ if(pclient == NULL) {
+ LOGE("Get client context faild!!!!fd:%d", fd);
+ return;
+ }
+
+ memcpy(&(pclient->client_cap.ext_client_cap), cap, sizeof(mnl_hal_ext_client_cap));
+}
+
+static hal2mnl_basic_interface g_hal2mnl_basic_interface = {
+ hal_gnss_init,
+ hal_gnss_start,
+ hal_gnss_stop,
+ hal_gnss_cleanup,
+ hal_set_measurement_enable,
+ hal_basic_client_capability_update,
+};
+
+static hal2mnl_ext_interface g_hal2mnl_ext_interface = {
+ hal_gps_inject_time,
+ hal_gps_inject_location,
+ hal_gps_delete_aiding_data,
+ hal_gps_set_position_mode,
+ hal_data_conn_open,
+ hal_data_conn_open_with_apn_ip_type,
+ hal_data_conn_closed,
+ hal_data_conn_failed,
+ hal_set_server,
+ hal_set_ref_location,
+ hal_set_id,
+ hal_ni_message,
+ hal_ni_respond,
+ hal_update_network_state,
+ hal_update_network_availability,
+ hal_set_gps_full_tracking,
+ hal_set_gps_navigation,
+ hal_set_vzw_debug,
+ hal_update_gnss_config,
+ hal_set_sv_blacklist,
+ hal_set_correction,
+ hal_set_nfw_access,
+ hal_send_pmtk,
+ hal_set_epo_enable,
+ hal_set_ttff_acc,
+ hal_ext_client_capability_update,
+};
+
+
+/*****************************************
+AGPSD -> MNL
+*****************************************/
+
+static void agps_reboot() {
+ LOGW("agps_reboot");
+ mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+ agps->gps_used = false;
+ agps->need_open_ack = false;
+ agps->need_close_ack = false;
+ agps->need_reset_ack = false;
+ if (mnl2agps_update_gnss_access_control(g_mnld_ctx.nfw_user_visibility[MNLD_NFW_USER_AGPS]) == -1) {
+ LOGE("mnl2agps_update_gnss_access_control failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static nfw_protocal_stack mnld_nfw_agps_protocal_stack(mnl_agps_open_type open_type) {
+ switch(open_type) {
+ case MNL_AGPS_OPEN_TYPE_SUPL:
+ return NFW_PS_SUPL;
+
+ case MNL_AGPS_OPEN_TYPE_CP_NILR:
+ case MNL_AGPS_OPEN_TYPE_CP_MTLR:
+ case MNL_AGPS_OPEN_TYPE_CP_MOLR:
+ case MNL_AGPS_OPEN_TYPE_CP_QUERY:
+ case MNL_AGPS_OPEN_TYPE_CP_MLR:
+ return NFW_PS_CTRL_PLANE;
+
+ case MNL_AGPS_OPEN_TYPE_UNKNOWN:
+ case MNL_AGPS_OPEN_TYPE_C2K:
+ default :
+ return NFW_PS_OTHER;
+ }
+}
+
+void mnld_nfw_set_default_notification(MNLD_NFW_USER usr) {
+ if(usr < MNLD_NFW_USER_NUM) {
+ memset(&nfw_user_notify[usr], 0, sizeof(nfw_notification));
+ memcpy(&nfw_user_notify[usr], &nfw_user_notify_default[usr], sizeof(nfw_notification));
+ } else {
+ LOGW("[NFW]set default wrong user:%d", usr);
+ }
+}
+
+void mnld_nfw_notify2hal_default(MNLD_NFW_USER usr, nfw_response_type response_type) {
+ if(usr < 0) {
+ LOGE("mnld_nfw_notify2hal_default fail user negative!!!");
+ return;
+ }
+ nfw_user_notify_default[usr].response_type = response_type;
+ LOGD("user[%d]:%s, ps:%d, otherPSName:%s, requestor:%d, requestorID:%s, responseType:%d, inEmergencyMode:%d, cashed:%d",
+ usr, nfw_user_notify_default[usr].proxy_app_package_name,
+ nfw_user_notify_default[usr].protocol_stack, nfw_user_notify_default[usr].other_protocol_stack_name,
+ nfw_user_notify_default[usr].requestor, nfw_user_notify_default[usr].requestor_id,
+ nfw_user_notify_default[usr].response_type, nfw_user_notify_default[usr].in_emergency_mode, nfw_user_notify_default[usr].is_cached_location);
+ if(mnl2hal_nfw_notify(&nfw_user_notify_default[usr]) == -1) {
+ LOGW("nfw(%d) notify to hal fail!!!", usr);
+ }
+ g_mnld_nfw_notified[usr] = true;
+}
+
+static void mnld_nfw_update_notification(MNLD_NFW_USER usr, mnl_agps_open_type open_type,
+ mnl_agps_open_requestor requestor_type, const char* requestor_id,
+ bool emergency_call){
+ if(usr < MNLD_NFW_USER_NUM) {
+ memset(&nfw_user_notify[usr], 0, sizeof(nfw_user_notify[usr]));
+ MNLD_STRNCPY(nfw_user_notify[usr].proxy_app_package_name, nfw_app_name_list[usr], MNLD_NFW_USER_NAME_LEN);
+ nfw_user_notify[usr].protocol_stack = mnld_nfw_agps_protocal_stack(open_type);
+ if(open_type == MNL_AGPS_OPEN_TYPE_C2K) {
+ MNLD_STRNCPY(nfw_user_notify[usr].other_protocol_stack_name, "C2K", MTK_MNLD_STRING_MAXLEN);
+ }
+ nfw_user_notify[usr].requestor = requestor_type;
+ MNLD_STRNCPY(nfw_user_notify[usr].requestor_id, requestor_id, MTK_MNLD_STRING_MAXLEN);
+ nfw_user_notify[usr].in_emergency_mode = emergency_call;
+ nfw_user_notify[usr].is_cached_location = 0;
+ } else {
+ LOGW("[NFW]update wrong user:%d", usr);
+ }
+}
+
+void mnld_nfw_notify2hal(MNLD_NFW_USER usr, nfw_response_type response_type) {
+ if(usr < 0) {
+ LOGE("mnld_nfw_notify2hal fail user negative!!!");
+ return;
+ }
+ nfw_user_notify[usr].response_type = response_type;
+ LOGD_ENG("user[%d]:%s, ps:%d, otherPSName:%s, requestor:%d, requestorID:%s, responseType:%d, inEmergencyMode:%d, cashed:%d",
+ usr, nfw_user_notify[usr].proxy_app_package_name,
+ nfw_user_notify[usr].protocol_stack, nfw_user_notify[usr].other_protocol_stack_name,
+ nfw_user_notify[usr].requestor, nfw_user_notify[usr].requestor_id,
+ nfw_user_notify[usr].response_type, nfw_user_notify[usr].in_emergency_mode, nfw_user_notify[usr].is_cached_location);
+ if(mnl2hal_nfw_notify(&nfw_user_notify[usr]) == -1) {
+ LOGW("nfw(%d) notify to hal fail!!!", usr);
+ }
+ g_mnld_nfw_notified[usr] = true;
+}
+
+void mnld_nfw_mnl2agps_location_sync(mnl_agps_location_time* location_sync_data)
+{
+ int ret = 0;
+
+ if((location_sync_data->source_nlp && mnld_nfw_ctrl_nlp_enabled()) || (location_sync_data->source_gnss && mnld_nfw_ctrl_gnss_enabled())) {
+ if (mtk_gps_get_nfw_visibility(MNLD_NFW_USER_AGPS)) {
+ ret = mnl2agps_location_sync(location_sync_data);
+ LOGD("nfw have white list ret = %d\n", ret);
+ if (-1 != ret) {
+ LOGD("mnl2agps_location_sync success\n");
+ }
+ if(mtk_gps_get_gps_user() & GPS_USER_AGPS) { //AGPS in GPS user list
+ //Notify HAL allowed AGPS open GPS
+ mnld_nfw_notify2hal(MNLD_NFW_USER_AGPS, NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED);
+ } else {
+ mnld_nfw_notify2hal_default(MNLD_NFW_USER_AGPS, NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED);
+ }
+ } else {
+ if(location_sync_data->utc_time_sync.utc_time_valid) {
+ ret = mnl2agps_gnss_time_sync(location_sync_data->utc_time_sync.utc_time);
+ LOGD("nfw dont have white list ret = %d\n", ret);
+ if (-1 != ret) {
+ LOGD("mnl2agps_gnss_time_sync success\n");
+ }
+ }
+ }
+ } else {
+ ret = mnl2agps_location_sync(location_sync_data);
+ LOGD("ret = %d\n", ret);
+ if (-1 != ret) {
+ LOGD("mnl2agps_location_sync success\n");
+ }
+ }
+}
+
+
+int g_mnld_show_icon = 1; //Default show GPS icon(notify to framework), unless AGPS notify fobid to show.
+int mnld_show_icon_get(void) {
+ return g_mnld_show_icon;
+}
+
+void mnld_show_icon_set(int show_gps_icon) {
+ g_mnld_show_icon = show_gps_icon;
+}
+
+static void agps_open_gps_req(int show_gps_icon, mnl_agps_open_type open_type,
+ mnl_agps_open_requestor requestor_type, const char* requestor_id,
+ bool emergency_call) {
+ LOGW("agps_open_gps_req show_gps_icon=%d open_type=%d requestor_type=%d requestor_id=%s emergency_call=%d, allowed:%d\n",
+ show_gps_icon, open_type, requestor_type, requestor_id, emergency_call, mtk_gps_get_nfw_visibility(MNLD_NFW_USER_AGPS));
+ mnld_show_icon_set(show_gps_icon);
+ if(MNL_AGPS_OPEN_REQUESTOR_UNKNOWN == requestor_type) {//i.e. old AGPSD
+ LOGW("May be using an old AGPSD!!!");
+ mnld_nfw_set_default_notification(MNLD_NFW_USER_AGPS);
+ } else {
+ mnld_nfw_update_notification(MNLD_NFW_USER_AGPS, open_type, requestor_type, requestor_id, emergency_call);
+ }
+ mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+ agps->gps_used = true;
+ agps->need_open_ack = true;
+ agps->need_close_ack = false;
+ agps_open_gps_flag = true;
+ mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+ g_mnld_nfw_notified[MNLD_NFW_USER_AGPS] = false;
+}
+
+static void agps_close_gps_req() {
+ LOGW("agps_close_gps_req, notified:%d", g_mnld_nfw_notified[MNLD_NFW_USER_AGPS]);
+ mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+ agps->gps_used = false;
+ agps->need_open_ack = false;
+ agps->need_close_ack = true;
+ mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+ if(g_mnld_nfw_notified[MNLD_NFW_USER_AGPS] == false) { //Never notified to HAL in one session
+ mnld_nfw_notify2hal(MNLD_NFW_USER_AGPS, NFW_RESPONSE_TYPE_ACCEPTED_NO_LOCATION_PROVIDED);
+ }
+ mnld_nfw_set_default_notification(MNLD_NFW_USER_AGPS);
+ mnld_show_icon_set(1);
+}
+
+static void agps_reset_gps_req(int flags) {
+ LOGW("agps_reset_gps_req flags=0x%x", flags);
+ if (flags == 0) {
+ if (mnl2agps_reset_gps_done() == -1) {
+ LOGE("mnl2agps_reset_gps_done failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ return;
+ }
+ g_mnld_ctx.gps_status.delete_aiding_flag |= (unsigned int)flags;
+ mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+ agps->need_reset_ack = true;
+ mnld_fsm(GPS_EVENT_RESET, 0, 0, NULL);
+}
+
+static void agps_open_gps_rejected(mnl_agps_open_type open_type,
+ mnl_agps_open_requestor requestor_type, const char* requestor_id,
+ bool emergency_call) {
+ LOGW("agps_open_gps_rejected open_type=%d requestor_type=%d requestor_id=%s emergency_call=%d allowed=%d\n",
+ open_type, requestor_type, requestor_id, emergency_call, mtk_gps_get_nfw_visibility(MNLD_NFW_USER_AGPS));
+
+ mnld_nfw_update_notification(MNLD_NFW_USER_AGPS, open_type, requestor_type, requestor_id, emergency_call);
+ mnld_nfw_notify2hal(MNLD_NFW_USER_AGPS, NFW_RESPONSE_TYPE_REJECTED);
+}
+
+static void agps_session_done() {
+ LOGW("agps_session_done call back function is empty!");
+}
+
+static void agps_ni_notify(int session_id, mnl_agps_ni_type ni_type,
+ mnl_agps_notify_type type, const char* requestor_id, const char* client_name) {
+ LOGD("agps_ni_notify session_id=%d type=%d requestor_id=[%s] client_name=[%s]",
+ session_id, type, requestor_id, client_name);
+ int usc2_len;
+ char ucs2_buff[1024];
+ char requestor_id_str[1024] = {0};
+ char clientName[1024] = {0};
+
+ memset(ucs2_buff, 0, sizeof(ucs2_buff));
+ usc2_len = asc_str_to_usc2_str(ucs2_buff, requestor_id);
+ raw_data_to_hex_string(requestor_id_str, ucs2_buff, usc2_len);
+
+ memset(ucs2_buff, 0, sizeof(ucs2_buff));
+ usc2_len = asc_str_to_usc2_str(ucs2_buff, client_name);
+ raw_data_to_hex_string(clientName, ucs2_buff, usc2_len);
+
+ if (mnl2hal_request_ni_notify(session_id, ni_type, type, requestor_id_str, clientName,
+ NI_ENCODING_TYPE_UCS2, NI_ENCODING_TYPE_UCS2) == -1) {
+ LOGE("mnl2hal_request_ni_notify failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void agps_data_conn_req(int ipaddr, int is_emergency) {
+ LOGD("agps_data_conn_req ipaddr=0x%x is_emergency=%d", ipaddr, is_emergency);
+ UNUSED(is_emergency);
+ struct sockaddr_storage addr;
+ memset(&addr, 0, sizeof(addr));
+ struct sockaddr_in *in = (struct sockaddr_in*)&addr;
+ addr.ss_family = AF_INET;
+ in->sin_addr.s_addr = ipaddr;
+ if (mnl2hal_request_data_conn(addr, MTK_AGPS_TYPE_SUPL) == -1) {
+ LOGE("mnl2hal_request_data_conn failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void agps_data_conn_release(mnl_agps_data_connection_type agps_type) {
+ LOGD("agps_data_conn_release agnss_type=%d", agps_type);
+ if (mnl2hal_release_data_conn(agps_type) == -1) {
+ LOGE("mnl2hal_release_data_conn failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void agps_set_id_req(int flags) {
+ LOGD("agps_set_id_req flags=%d", flags);
+ if (mnl2hal_request_set_id(flags) == -1) {
+ LOGE("mnl2hal_request_set_id failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void agps_ref_loc_req(int flags) {
+ LOGD("agps_ref_loc_req flags=%d", flags);
+ if (mnl2hal_request_ref_loc(flags) == -1) {
+ LOGE("mnl2hal_request_ref_loc failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void agps_rcv_pmtk(const char* pmtk) {
+ // LOGD("agps_rcv_pmtk pmtk=%s", pmtk);
+ // TODO libmnl.so
+ gps_controller_rcv_pmtk(pmtk);
+}
+
+static void agps_gpevt(gpevt_type type) {
+ LOGD("agps_gpevt type=%d", type);
+ UNUSED(type);
+}
+static void agps_rcv_lppe_common_iono(const char* data, int len)
+{
+ LOGD("rcv_lppe_data\n");
+ if (mnld_is_gps_and_ofl_stopped()) {
+ LOGD("rcv_lppe_data: MNL stopped, return");
+ return;
+ }
+ int ret = mtk_agps_set_param_with_payload_len(MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_IONO, data, MTK_MOD_DISPATCHER, MTK_MOD_AGENT,len);
+
+ if (ret != 0) {
+ LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_LPPE\n");
+ }else{
+ gnss_ha_assist_ack_struct ack;
+ memset((char*)(&ack),0x0,sizeof(gnss_ha_assist_ack_struct));
+ ack.type=AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_IONO;
+ if (mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct)) == -1) {
+ LOGE("mnl2agps_gps_cleanup failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ }
+}
+static void agps_rcv_lppe_common_trop(const char* data, int len)
+{
+ LOGD("rcv_lppe_data\n");
+ if (mnld_is_gps_and_ofl_stopped()) {
+ LOGD("rcv_lppe_data: MNL stopped, return");
+ return;
+ }
+ int ret = mtk_agps_set_param_with_payload_len(MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_TROP, data, MTK_MOD_DISPATCHER, MTK_MOD_AGENT,len);
+ if (ret != 0) {
+ LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_LPPE\n");
+ }else{
+ gnss_ha_assist_ack_struct ack;
+ memset((char*)(&ack),0x0,sizeof(gnss_ha_assist_ack_struct));
+ ack.type=AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_TROP;
+ if (mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct)) == -1) {
+ LOGE("mnl2agps_gps_cleanup failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ }
+
+}
+static void agps_rcv_lppe_common_alt(const char* data, int len)
+{
+ LOGD("rcv_lppe_data\n");
+ if (mnld_is_gps_and_ofl_stopped()) {
+ LOGD("rcv_lppe_data: MNL stopped, return");
+ return;
+ }
+ int ret = mtk_agps_set_param_with_payload_len(MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_ALT, data, MTK_MOD_DISPATCHER, MTK_MOD_AGENT,len);
+ if (ret != 0) {
+ LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_LPPE\n");
+ }else{
+ gnss_ha_assist_ack_struct ack;
+ memset((char*)(&ack),0x0,sizeof(gnss_ha_assist_ack_struct));
+ ack.type=AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_ALT;
+ if (mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct)) == -1) {
+ LOGE("mnl2agps_gps_cleanup failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ }
+
+}
+static void agps_rcv_lppe_common_solar(const char* data, int len)
+{
+ LOGD("rcv_lppe_data\n");
+ if (mnld_is_gps_and_ofl_stopped()) {
+ LOGD("rcv_lppe_data: MNL stopped, return");
+ return;
+ }
+ int ret = mtk_agps_set_param_with_payload_len(MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_SOLAR, data, MTK_MOD_DISPATCHER, MTK_MOD_AGENT,len);
+ if (ret != 0) {
+ LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_LPPE\n");
+ }else{
+ gnss_ha_assist_ack_struct ack;
+ memset((char*)(&ack),0x0,sizeof(gnss_ha_assist_ack_struct));
+ ack.type=AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_SOLAR;
+ if (mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct)) == -1) {
+ LOGE("mnl2agps_gps_cleanup failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ }
+
+}
+static void agps_rcv_lppe_common_ccp(const char* data, int len)
+{
+ LOGD("rcv_lppe_data\n");
+ if (mnld_is_gps_and_ofl_stopped()) {
+ LOGD("rcv_lppe_data: MNL stopped, return");
+ return;
+ }
+ int ret = mtk_agps_set_param_with_payload_len(MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_CCP, data, MTK_MOD_DISPATCHER, MTK_MOD_AGENT,len);
+ if (ret != 0) {
+ LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_LPPE\n");
+ }else{
+ gnss_ha_assist_ack_struct ack;
+ memset((char*)(&ack),0x0,sizeof(gnss_ha_assist_ack_struct));
+ ack.type=AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_CCP;
+ if (mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct)) == -1) {
+ LOGE("mnl2agps_gps_cleanup failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ }
+
+}
+static void agps_rcv_lppe_generic_ccp(const char* data, int len)
+{
+ LOGD("rcv_lppe_data\n");
+ if (mnld_is_gps_and_ofl_stopped()) {
+ LOGD("rcv_lppe_data: MNL stopped, return");
+ return;
+ }
+ int ret = mtk_agps_set_param_with_payload_len(MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_GENERIC_CCP, data, MTK_MOD_DISPATCHER, MTK_MOD_AGENT,len);
+ if (ret != 0) {
+ LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_LPPE\n");
+ }else{
+ gnss_ha_assist_ack_struct ack;
+ memset((char*)(&ack),0x0,sizeof(gnss_ha_assist_ack_struct));
+ ack.type=AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_GENERIC_CCP;
+ if (mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct)) == -1) {
+ LOGE("mnl2agps_gps_cleanup failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ }
+
+}
+static void agps_rcv_lppe_generic_dm(const char* data, int len)
+{
+ LOGD("rcv_lppe_data\n");
+ if (mnld_is_gps_and_ofl_stopped()) {
+ LOGD("rcv_lppe_data: MNL stopped, return");
+ return;
+ }
+ int ret = mtk_agps_set_param_with_payload_len(MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_GENERIC_DM, data, MTK_MOD_DISPATCHER, MTK_MOD_AGENT,len);
+ if (ret != 0) {
+ LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_LPPE\n");
+ }else{
+ gnss_ha_assist_ack_struct ack;
+ memset((char*)(&ack),0x0,sizeof(gnss_ha_assist_ack_struct));
+ ack.type=AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_GENERIC_DM;
+ if (mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct)) == -1) {
+ LOGE("mnl2agps_gps_cleanup failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ }
+
+}
+
+/**
+* @description : init a g_md_time_ctx
+* @note: should be called before mnld_main_thread main loop.
+*/
+void mnld_init_time_aiding_ctx(void) {
+
+ LOGD("%s\n",__func__);
+ if (pthread_mutex_init(&g_md_time_ctx.lock, NULL)) {
+ LOGE("pthread_mutex_init Failed reason=[%s]",strerror(errno));
+ return;
+ } else {
+ pthread_mutex_lock(&g_md_time_ctx.lock);
+ g_md_time_ctx.status = MD_TIME_SYNC_IDLE;
+ g_md_time_ctx.transactionID = 0;
+ g_md_time_ctx.inited = 1;
+ pthread_mutex_unlock(&g_md_time_ctx.lock);
+ }
+}
+
+/**
+* @description : send a time back MD.
+* @note, only support TOD type, and only be sent in condition below:
+* 1. MNL has required aiding time and get the valid aiding time from MD
+* 2. MNL has 3D fixed.
+*/
+void mnld_feadback_time_to_MD(gnss_timeOfDay_with_unc* tod) {
+
+ LOGD("%s\n",__func__);
+ mnl_md_time_info_rsp_struct time;
+ unsigned short transactionID;
+ unsigned short transactionIDTime;
+ md_time_sync_status status;
+
+ memset(&time, 0x0, sizeof(time));
+
+ pthread_mutex_lock(&g_md_time_ctx.lock);
+ transactionID = g_md_time_ctx.transactionID;
+ status = g_md_time_ctx.status;
+ transactionIDTime = g_md_time_ctx.time.transactionID;
+
+ if ((status == MD_TIME_SYNC_TIME_INJECTED) && (transactionIDTime == transactionID)) {
+ g_md_time_ctx.status = MD_TIME_SYNC_IDLE;
+ memcpy(&time, &g_md_time_ctx.time, sizeof(time));
+ }
+ pthread_mutex_unlock(&g_md_time_ctx.lock);
+
+ if ((status == MD_TIME_SYNC_TIME_INJECTED) && (transactionIDTime == transactionID)) {
+
+ time.gnss_timeInfo.gnss_timeInfo_valid = 1;
+ //time.gnss_timeInfo.time_info_source = 0;//need double checked by Linda.
+ time.gnss_timeInfo.time_infoType = 1;
+ time.gnss_timeInfo.gnss_timeUncertainty = tod->uncertainty;
+ memcpy(&time.gnss_timeInfo.gnss_tod, &tod->tod, sizeof(gnss_timeOfDay_struct));
+ if (mnl2agps_md_time_info_rsp((char*)&time, sizeof(time))==-1) {
+ LOGE("mnl2agps_md_time_info_rsp send fail, reason=[%s]\n", strerror(errno));
+ }
+ } else
+ LOGW("mnld_feadback_time_to_MD no need to send, status =%d, transactionIDTime =%d, transactionID = %d\n", status, transactionIDTime, transactionID);
+}
+
+
+/**
+* @description : send a time aiding request to MD.
+* @note:
+* 1. State will be changed to MD_TIME_SYNC_REQUESTING when received a new request, no matter what the state is before.
+* 2. however, we only consider MD_TIME_SYNC_IDLE or MD_TIME_SYNC_TIME_INJECTED as a normal case
+*/
+void mnld_request_MD_time_sync(md_time_require_action action) {
+
+ LOGD("%s\n",__func__);
+ mnl_md_time_sync_req_struct req;
+ //unsigned short old_transactionID;
+ unsigned short new_transactionID;
+ md_time_sync_status old_status;
+ //md_time_sync_status new_status;
+
+ memset(&req, 0x0, sizeof(req));
+
+ if (action == MD_TIME_REQUIRE_START) {
+ LOGD("mnld request MD aiding start\n");
+ } else if (action == MD_TIME_REQUIRE_TESTMODE) {
+ LOGD("mnld request MD aiding test mode");
+ /*pulsePeriod 100...300000 msec*/
+ req.pulsePeriod = 100;
+ /*pulseNumber, 0: Periodic mod, 1-7200: None-Periodic Number of Pulse*/
+ req.pulseNumber = 0;
+ } else if (action == MD_TIME_REQUIRE_STOP) {
+ LOGD("mnld request MD aiding stop");
+ } else {
+ LOGE("mnld request MD aiding, action:%d over flow\n", action);
+ return;
+ }
+
+ pthread_mutex_lock(&g_md_time_ctx.lock);
+ //old_transactionID = g_md_time_ctx.transactionID;
+ old_status = g_md_time_ctx.status;
+
+ g_md_time_ctx.transactionID += 1;
+ new_transactionID = g_md_time_ctx.transactionID;
+
+ g_md_time_ctx.status = MD_TIME_SYNC_REQUESTING;
+ //new_status = g_md_time_ctx.status;
+ pthread_mutex_unlock(&g_md_time_ctx.lock);
+
+ req.transactionID = new_transactionID;
+ req.ctrlFlag = action;
+
+ if (mnl2agps_md_time_sync_req((char*)&req, sizeof(req))==-1) {
+ LOGE("mnl2agps_md_time_sync_req send fail, reason=[%s]\n", strerror(errno));
+ }
+ if (old_status==MD_TIME_SYNC_REQUESTING) {
+ LOGW("repeat request MD time, and no ack from MD\n");
+ } else if (old_status==MD_TIME_SYNC_REQUESTED) {
+ LOGW("repeat request MD time, alread receive ack from MD\n");
+ }
+}
+
+
+/**
+* @description : send a ack to MD accoriding to the transaction ID from MD aiding time
+* @para transactionID : this must be align with transatction ID from MD, only do this, MD can make sure GPS have received the right aiding data.
+*/
+void mnld_ACK_to_MD_time(unsigned short transactionID) {
+
+ LOGD("%s\n",__func__);
+ mnl_md_time_sync_rsp_struct ack;
+ ack.transactionID = transactionID;
+ if (mnl2agps_md_time_sync_rsp((char*)&ack, sizeof(ack))==-1) {
+ LOGE("mnl2agps_md_time_sync_rsp send fail, reason=[%s]\n", strerror(errno));
+ }
+}
+
+
+/**
+* @description : receive MD time aiding and inject to mnl
+* @note:
+* 1. alway reply ack to MD regardless if inject successfully.
+* 2. only when the state machine matched, we will inject aiding time to MNL.
+* 3. if all the things go well, the status of state machine will be MD_TIME_SYNC_TIME_INJECTED
+*/
+void md_time_sync_ind (const char* data, int len) { // refer to mnl_md_time_sync_ind_struct
+
+ LOGD("%s\n",__func__);
+ mnl_md_time_sync_ind_struct* time = NULL;
+ bool check_status = 0;
+ unsigned short transactionID;
+ md_time_sync_status status;
+ unsigned short transactionIDMD;
+
+ LOGD("md_time_sync_ind\n");
+ time = (mnl_md_time_sync_ind_struct*)data;
+ transactionIDMD = time->transactionID;
+ if (mnld_is_gps_and_ofl_stopped()) {
+ LOGW("md_time_sync_ind: MNL stopped, return");
+ goto ack;
+ }
+
+ if (len != sizeof(mnl_md_time_sync_ind_struct)) {
+ LOGE("md_time_sync_ind: size error, len=%d, structure size=%lu\n", len, sizeof(mnl_md_time_sync_ind_struct));
+ goto ack;
+ }
+
+ //g_md_time_ctx.inited no need lock, it only be inited when MNLD start, here is to check wether structure be destroied by other function or lock has been inited.
+ if (g_md_time_ctx.inited) {
+
+ pthread_mutex_lock(&g_md_time_ctx.lock);
+ transactionID = g_md_time_ctx.transactionID;
+ status = g_md_time_ctx.status;
+ if ((status==MD_TIME_SYNC_REQUESTED) && (transactionID==transactionIDMD)) {
+ g_md_time_ctx.status = MD_TIME_SYNC_TIME_INJECTED;
+ check_status = 1;
+ memcpy(&g_md_time_ctx.time, time, sizeof(g_md_time_ctx.time));
+ }
+ pthread_mutex_unlock(&g_md_time_ctx.lock);
+
+ /* begin inject to mnl*/
+ if (check_status == 1) {
+ if (mtk_gps_set_param(MTK_PARAM_CMD_MD_TIME_SYNC_IND, data)) {
+ LOGE("mtk_agps_set_param fail, MTK_PARAM_CMD_MD_TIME_SYNC_IND\n");
+ }
+ } else {
+ LOGE("md_time_sync_ind status error, transactionID:%d, time.transactionID:%d, contex status:%d\n",
+ transactionID, transactionIDMD, status);
+ }
+
+ } else {
+ LOGE("g_md_time_ctx not inited, init:%d\n", g_md_time_ctx.inited);
+ }
+
+ ack:
+ mnld_ACK_to_MD_time(transactionIDMD);
+}
+
+
+/**
+* @description : receive MD ack for request MD time aiding
+* @note:
+* 1. if we did not get MD's ack, it means MD have some problem and can not reply to mnld.
+* 2. we change status machine from MD_TIME_SYNC_REQUESTING to MD_TIME_SYNC_REQUESTED if all things go well.
+*/
+void md_time_sync_cnf (const char* data, int len) { // refer to mnl_md_time_sync_cnf_struct
+
+ LOGD("%s\n",__func__);
+ mnl_md_time_sync_cnf_struct* ack_from_MD = NULL;
+ bool check_status = 0;
+ unsigned short transactionID;
+ md_time_sync_status status;
+
+ //LOGD("md_time_sync_cnf, rec MD ack for request time\n");
+
+ if (mnld_is_gps_and_ofl_stopped()) {
+ LOGW("md_time_sync_cnf: MNL stopped, return");
+ return;
+ }
+
+ if (len != sizeof(mnl_md_time_sync_cnf_struct)) {
+ LOGE("md_time_sync_cnf: size error, len=%d, structure size=%lu\n", len, sizeof(mnl_md_time_sync_cnf_struct));
+ return;
+ }
+ if (g_md_time_ctx.inited) {
+
+ ack_from_MD = (mnl_md_time_sync_cnf_struct*)data;
+ pthread_mutex_lock(&g_md_time_ctx.lock);
+ transactionID = g_md_time_ctx.transactionID;
+ status = g_md_time_ctx.status;
+ if ((status==MD_TIME_SYNC_REQUESTING) && (transactionID==ack_from_MD->transactionID)) {
+ g_md_time_ctx.status = MD_TIME_SYNC_REQUESTED;
+ check_status = 1;
+ }
+ pthread_mutex_unlock(&g_md_time_ctx.lock);
+ if (check_status != 1) {
+ LOGE("md_time_sync_cnf status error, transactionID:%d, ack_from_MD.transactionID:%d, contex status:%d\n",
+ transactionID, ack_from_MD->transactionID, status);
+ }
+ } else {
+ LOGE("g_md_time_ctx not inited, init:%d\n", g_md_time_ctx.inited);
+ }
+
+}
+
+
+
+static void agps_location(mnl_agps_agps_location2* location_input) {
+ mnl_agps_agps_location * location = &(location_input->loc);
+ mnl_hal_agps_location agps_loc;
+ LOGDX("agps_location lat,lng %f,%f acc=%f used=%d",
+ location->latitude, location->longitude, location->accuracy, location->accuracy_used);
+
+ MTK_GPS_NLP_T c2k_cell_location;
+ nlp_context context;
+ memset(&c2k_cell_location, 0, sizeof(MTK_GPS_NLP_T));
+ memset(&context, 0, sizeof(nlp_context));
+ if (clock_gettime(CLOCK_MONOTONIC , &context.ts) == -1) {
+ LOGE("clock_gettime failed reason=[%s]\n", strerror(errno));
+ return;
+ }
+ LOGD("ts.tv_sec = %ld, ts.tv_nsec = %ld\n",
+ context.ts.tv_sec, context.ts.tv_nsec);
+
+ c2k_cell_location.lattidude = location->latitude;
+ c2k_cell_location.longitude = location->longitude;
+ c2k_cell_location.accuracy = location->accuracy;
+ c2k_cell_location.timeReference[0] = (UINT32)context.ts.tv_sec;
+ c2k_cell_location.timeReference[1] = (UINT32)context.ts.tv_nsec;
+ c2k_cell_location.type = NLP_FRAMEWORK;
+ c2k_cell_location.started = 1;
+ LOGDX("inject cell location lati= %f, longi = %f, accuracy = %f\n",
+ c2k_cell_location.lattidude, c2k_cell_location.longitude, c2k_cell_location.accuracy);
+
+ if (mnld_is_gps_started_done()) {
+ mtk_gps_inject_nlp_location(&c2k_cell_location);
+ }
+
+ memset(&agps_loc, 0, sizeof(agps_loc));
+ memcpy(&agps_loc, location, sizeof(mnl_agps_agps_location));
+ agps_loc.type_used = location_input->source_used;
+ agps_loc.type = location_input->source;
+ mnl2hal_agps_location(&agps_loc);
+}
+
+static void agps_cell_location(mnl_agps_agps_location2* location_input) {
+ mnl_agps_agps_location * location = &(location_input->loc);
+ LOGD("agps_cell_location");
+
+ if(location_input->source_used &&
+ location_input->source == MNL_AGPS_AGPS_LOC_TYPE_CDMA_CELL) {
+ MTK_GPS_NLP_T c2k_cell_location;
+ nlp_context context;
+
+ memset(&context, 0, sizeof(nlp_context));
+ memset(&c2k_cell_location, 0, sizeof(MTK_GPS_NLP_T));
+ if (clock_gettime(CLOCK_MONOTONIC , &context.ts) == -1) {
+ LOGE("clock_gettime failed reason=[%s]\n", strerror(errno));
+ return;
+ }
+ LOGD("ts.tv_sec = %lld, ts.tv_nsec = %lld\n",
+ (long long)context.ts.tv_sec, (long long)context.ts.tv_nsec);
+ c2k_cell_location.lattidude = location->latitude;
+ c2k_cell_location.longitude = location->longitude;
+ c2k_cell_location.accuracy = location->accuracy;
+ c2k_cell_location.timeReference[0] = (UINT32)context.ts.tv_sec;
+ c2k_cell_location.timeReference[1] = (UINT32)context.ts.tv_nsec;
+ c2k_cell_location.type = NLP_C2K_CELL;
+ c2k_cell_location.started = 1;
+ LOGD("inject cell location lati= %f, longi = %f, accuracy = %f, type:%d\n",
+ c2k_cell_location.lattidude, c2k_cell_location.longitude, c2k_cell_location.accuracy, c2k_cell_location.type);
+ if (mnld_is_gps_started_done()) {
+ mtk_gps_inject_nlp_location(&c2k_cell_location);
+ }
+ }
+
+ mnl_hal_agps_location agps_loc;
+ memset(&agps_loc, 0, sizeof(agps_loc));
+ memcpy(&agps_loc, location, sizeof(mnl_agps_agps_location));
+ agps_loc.type_used = location_input->source_used;
+ agps_loc.type = location_input->source;
+ mnl2hal_agps_location(&agps_loc);
+}
+
+#if defined(__LIBMNL_SIMULATOR__)
+void mnl2hal_c2k_cell_send(gps_location location_in) {
+ mnl_agps_agps_location2 location_ref;
+
+ location_ref.loc.latitude = location_in.lat;
+ location_ref.loc.longitude = location_in.lng;
+ location_ref.loc.altitude_used = 1;
+ location_ref.loc.altitude = location_in.alt;
+ location_ref.loc.accuracy_used = 1;
+ location_ref.loc.accuracy = location_in.h_accuracy;
+ location_ref.loc.bearing_used = 1;
+ location_ref.loc.bearing = location_in.bearing;
+ location_ref.loc.speed_used = 1;
+ location_ref.loc.speed = location_in.speed;
+ location_ref.loc.timestamp_used = 1;
+ location_ref.loc.timestamp = location_in.timestamp;
+
+ location_ref.source_used = 0;
+ location_ref.source = 1;
+
+ agps_cell_location(&location_ref);
+}
+#endif
+static void agps_ni_notify2(int session_id, mnl_agps_ni_type ni_type,
+ mnl_agps_notify_type type, const char* requestor_id, const char* client_name,
+ mnl_agps_ni_encoding_type requestor_id_encoding,
+ mnl_agps_ni_encoding_type client_name_encoding) {
+ LOGD("agps_ni_notify2 session_id=%d type=%d requestor_id_encoding=%d client_name_encoding=%d",
+ session_id, type, requestor_id_encoding, client_name_encoding);
+ if (mnl2hal_request_ni_notify(session_id, ni_type, type, requestor_id,
+ client_name, requestor_id_encoding, client_name_encoding) == -1) {
+ LOGE("mnl2hal_request_ni_notify failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void agps_data_conn_req2(struct sockaddr_storage* addr, int is_emergency,
+ mnl_agps_data_connection_type agps_type) {
+ LOGD("agps_data_conn_req2 is_emergency=%d agnss_type=%d", is_emergency, agps_type);
+ UNUSED(is_emergency);
+ if (mnl2hal_request_data_conn(*addr, agps_type) == -1) {
+ LOGE("mnl2hal_request_data_conn failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static int get_agnss_capability(const UINT8 sv_type_agps_set, const UINT8 sv_type, char *pmtk_str) {
+ char tmp[64]={0};
+ int agps_cap = 0;
+ int aglonass_cap = 0;
+ int abeidou_cap = 0;
+ int agalileo_cap = 0;
+ int gnss_num = 0;
+ MTK_GPS_MNL_CONFIG_XML_PARAM mnl_config_xml;
+ int is_l5_enable_by_xml = 1;
+ int is_l5_enable = 0;
+
+ MNLD_STRNCPY(mnl_config_xml.xml_feature_name, "L1Only", sizeof(mnl_config_xml.xml_feature_name));
+
+ if (mtk_gps_get_MNL_Config_XML_param(MNL_READ_WRITE_PATH, &mnl_config_xml)) {
+ if ((mnl_config_xml.xml_feature_config == 1) && ((int)mnl_config_xml.xml_feature_setting[0][0] == 1)) {
+ is_l5_enable_by_xml = 0;
+ }
+ } else if (mtk_gps_get_MNL_Config_XML_param(MNL_CFG_XML_DEFAULT_PATH, &mnl_config_xml)) {
+ if ((mnl_config_xml.xml_feature_config == 1) && ((int)mnl_config_xml.xml_feature_setting[0][0] == 1)) {
+ is_l5_enable_by_xml = 0;
+ }
+ }
+
+ is_l5_enable = is_l5_enable_by_xml;//for android, we known the Adchip id, but for cogin, we have not this API yet
+
+ // Axxx Enable. with HW support condition
+ if (((sv_type_agps_set & 0x21) == 0x21) && ((sv_type & 0x01) == 0x01)) {
+ agps_cap = 1;
+ }
+ if (((sv_type_agps_set & 0x12) == 0x12) && ((sv_type & 0x02) == 0x02)) {
+ aglonass_cap = 1;
+ }
+ if (((sv_type_agps_set & 0x44) == 0x44) && ((sv_type & 0x04) == 0x04)) {
+ abeidou_cap = 1;
+ }
+ if (((sv_type_agps_set & 0x88) == 0x88) && ((sv_type & 0x08) == 0x08)) {
+ agalileo_cap = 1;
+ }
+ gnss_num = agps_cap + aglonass_cap + abeidou_cap + agalileo_cap;
+
+ MNLD_SPRINTF(pmtk_str, "$PMTK764,0,0,0");
+ MNLD_SPRINTF(tmp, ",%d", gnss_num);
+ strncat(pmtk_str, tmp, PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+
+ if (agps_cap) {
+ if (is_l5_enable) {
+ strncat(pmtk_str, ",0,144", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+ } else {
+ strncat(pmtk_str, ",0,128", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+ }
+ }
+
+ if (agalileo_cap) {
+ if (is_l5_enable) {
+ strncat(pmtk_str, ",3,192", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+ } else {
+ strncat(pmtk_str, ",3,128", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+ }
+ }
+
+ if (aglonass_cap) {
+ strncat(pmtk_str, ",4,128", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+ }
+ if (abeidou_cap) {
+ strncat(pmtk_str, ",5,128", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+ }
+ if (lppe_enable){
+ strncat(pmtk_str, ",1", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+ }else{
+ strncat(pmtk_str, ",0", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+ }
+ add_chksum(pmtk_str);
+ LOGD("MNLD_PMTK764: %s, agps_cap:%d, aglonass_cap:%d, abeidou_cap:%d, agalileo_cap:%d, lppe_support:%d\n",
+ pmtk_str, agps_cap, aglonass_cap, abeidou_cap, agalileo_cap, lppe_enable);
+ return 0;
+}
+
+void agps_settings_sync(mnl_agps_agps_settings* s) {
+ UINT8 sv_type;
+ int ret;
+
+ char pmtk_str[PMTK_MAX_PKT_LENGTH];
+ memset(pmtk_str, 0, sizeof(pmtk_str));
+
+ LOGD("agps setting, sib8_16_enable = %d, gps_sat_en = %d, glonass_sat_en = %d, \
+ beidou_sat_en = %d, galileo_sat_en = %d, a_glonass_sat_en = %d, \
+ a_gps_satellite_enable = %d, a_beidou_satellite_enable = %d, a_galileo_satellite_enable = %d, lppe_enable=%d\n",
+ s->sib8_16_enable,
+ s->gps_satellite_enable, s->glonass_satellite_enable,
+ s->beidou_satellite_enable, s->galileo_satellite_enable,
+ s->a_glonass_satellite_enable, s->a_gps_satellite_enable,
+ s->a_beidou_satellite_enable, s->a_galileo_satellite_enable,
+ s->lppe_enable);
+ g_settings_from_agps = *s;
+
+ sv_type_agps_set = 0;
+ sv_type_agps_set |= (g_settings_from_agps.a_galileo_satellite_enable & 0x01) << 7;
+ sv_type_agps_set |= (g_settings_from_agps.a_beidou_satellite_enable & 0x01) << 6;
+ sv_type_agps_set |= (g_settings_from_agps.a_gps_satellite_enable & 0x01) << 5;
+ sv_type_agps_set |= (g_settings_from_agps.a_glonass_satellite_enable & 0x01) << 4;
+ sv_type_agps_set |= (g_settings_from_agps.galileo_satellite_enable & 0x01) << 3;
+ sv_type_agps_set |= (g_settings_from_agps.beidou_satellite_enable & 0x01) << 2;
+ sv_type_agps_set |= (g_settings_from_agps.glonass_satellite_enable & 0x01) << 1;
+ sv_type_agps_set |= (g_settings_from_agps.gps_satellite_enable & 0x01);
+ sib8_16_enable = g_settings_from_agps.sib8_16_enable;
+ lppe_enable = g_settings_from_agps.lppe_enable && mtk_gps_mnl_info.support_lppe;
+ get_chip_sv_support_capability(&sv_type);
+ //LOGD("get_chip_sv_support_capability, sv_type = %d", sv_type);
+ g_settings_to_agps.gps_satellite_support = (sv_type) & (0x01);
+ g_settings_to_agps.glonass_satellite_support = ((sv_type) & (0x02)) >> 1;
+ g_settings_to_agps.beidou_satellite_support = ((sv_type) & (0x04)) >> 2;
+ g_settings_to_agps.galileo_satellite_support = ((sv_type) & (0x08)) >> 3;
+
+ ret = mnl2agps_agps_settings_ack(&g_settings_to_agps);
+ //LOGD("mnl2agps_agps_settings_ack done, ret = %d", ret);
+
+ if (mnld_is_gps_started_done()) {
+ ret = mtk_gps_set_param(MTK_PARAM_CMD_SWITCH_CONSTELLATION, &sv_type_agps_set);
+ LOGD("sent CMD_SWITCH_CONSTELLATION to mnl, sv_type_agps_set = 0x%x ,ret = %d", sv_type_agps_set, ret);
+
+ ret = mtk_gps_set_param(MTK_PARAM_CMD_SIB8_16_ENABLE, &sib8_16_enable);
+ LOGD("sent CMD_SIB8_16_ENABLE to mnl, sib8_16_enable = %d ,ret = %d", sib8_16_enable, ret);
+ if(mtk_gps_mnl_info.support_lppe){
+ ret = mtk_gps_set_param(MTK_PARAM_CMD_LPPE_ENABLE, &lppe_enable);
+ LOGD("sent MTK_PARAM_CMD_LPPE_ENABLE to mnl, lppe_enable = %d ,ret = %d", lppe_enable, ret);
+ }
+ } else {
+ LOGD("mnl stop, mnld send pmtk764 to agpsd\n");
+
+ // Generate PMTK764 and send to AGPSD
+ get_agnss_capability(sv_type_agps_set, sv_type, pmtk_str);
+ if (mnl2agps_pmtk(pmtk_str) == -1) {
+ LOGE("mnl2agps_pmtk failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ }
+}
+static void vzw_debug_screen_output(const char* str) {
+ LOGD("vzw_debug_screen_output str=%s", str);
+ if (mnl2hal_vzw_debug_screen_output(str) == -1) {
+ LOGE("mnl2hal_vzw_debug_screen_output failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+#ifdef MTK_AGPS_SUPPORT
+static agps2mnl_interface g_agps2mnl_interface = {
+ agps_reboot,
+ agps_open_gps_req,
+ agps_close_gps_req,
+ agps_reset_gps_req,
+ agps_open_gps_rejected,
+ agps_session_done,
+ agps_ni_notify,
+ agps_data_conn_req,
+ agps_data_conn_release,
+ agps_set_id_req,
+ agps_ref_loc_req,
+ agps_rcv_pmtk,
+ agps_gpevt,
+ agps_location,
+ agps_cell_location,
+ agps_ni_notify2,
+ agps_data_conn_req2,
+ agps_settings_sync,
+ vzw_debug_screen_output,
+ agps_rcv_lppe_common_iono,
+ agps_rcv_lppe_common_trop,
+ agps_rcv_lppe_common_alt,
+ agps_rcv_lppe_common_solar,
+ agps_rcv_lppe_common_ccp,
+ agps_rcv_lppe_generic_ccp,
+ agps_rcv_lppe_generic_dm,
+
+ md_time_sync_ind,//time aiding from MD
+ md_time_sync_cnf,//time request conf from MD
+};
+#endif
+/*****************************************
+META -> MNL
+*****************************************/
+static void meta_req_gnss_location(int source) {
+ LOGW("meta_req_gnss_location source: %d", source);
+ in_meta_factory = 1;
+ factory_mnld_gps_start();
+}
+
+static void meta_cancel_gnss_location(int source) {
+ LOGW("meta_cancel_gnss_location source: %d", source);
+ in_meta_factory = 0;
+ factory_mnld_gps_stop();
+}
+
+static Meta2MnldInterface_callbacks g_meta2mnl_callbacks = {
+ meta_req_gnss_location,
+ meta_cancel_gnss_location
+};
+
+/////// end of meta
+
+/*****************************************
+DEBUG -> MNL
+*****************************************/
+void mnld_gps_output_data_handle(char* buff, int off_set) {
+ char data[MNLD_TO_APP_BUFF_SIZE] = {0};
+ int offset = off_set;
+ main_out_put_data_type cmd;
+ int lenth = 0;
+
+ cmd = get_int(buff, &offset, MNLD_INTERNAL_BUFF_SIZE);
+
+ switch(cmd) {
+ case DATA_DEBUG2APP: {
+ lenth = get_binary(buff, &offset, data, MNLD_INTERNAL_BUFF_SIZE, sizeof(data));
+ LOGW("mnld send debug msg to app:%s, len:%d", data, lenth);
+ Mnld2DebugInterface_mnldUpdateMessageInfo(&g_mnld_ctx.fds.fd_debug_client, data);
+ break;
+ }
+ default: {
+ LOGW("unkown main_out_put_data_type cmd:%d", cmd);
+ return;
+ }
+ }
+}
+
+int sys_gps_mnl_data2mnld_callback(const char *data, unsigned int length) {
+ char buff[MNLD_TO_APP_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, GPS2MAIN_EVENT_OUTPUT_DATA);
+ put_int(buff, &offset, DATA_DEBUG2APP);
+ put_binary(buff, &offset, data, length);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+static void debug_req_mnld_message(Debug2MnldInterface_DebugReqStatusCategory status) {
+ Mnld2DebugInterface_MnldGpsStatusCategory gps_status;
+ gps_status = (Mnld2DebugInterface_MnldGpsStatusCategory)(mnld_is_gps_started());
+ switch(status) {
+ case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_START_DEBUG:
+ case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_STOP_DEBUG:
+ enable_debug2app = status;
+ LOGW("receive debug request msg:%d", status);
+ if (MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STARTED==gps_status) {
+ if(mtk_gps_set_param(MTK_PARAM_CMD_DEBUG2APP_CONFIG, (const UINT8 *)&enable_debug2app)) {
+ LOGW("send APP Debug msg to mnl fail");
+ }
+ }
+ break;
+ default:
+ LOGW("receive wrong debug msg:%d, do nothing", status);
+ break;
+ }
+ Mnld2DebugInterface_mnldAckDebugReq(&g_mnld_ctx.fds.fd_debug_client);
+ Mnld2DebugInterface_mnldUpdateGpsStatus(&g_mnld_ctx.fds.fd_debug_client,gps_status);
+}
+
+static void debug_mnld_ne_property(bool enabled) {
+ if (enabled == true) {
+ property_set("vendor.debug.gps.mnld.ne", "1"); //Enable mnld NE
+ LOGD("Set MNLD NE property to enable");
+ } else {
+ property_set("vendor.debug.gps.mnld.ne", "0"); //Disable mnld NE
+ LOGD("Set MNLD NE property to disable");
+ }
+}
+
+static void debug_mnld_radio_property(char* value) {
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (strlen(value) <= 10) { //Max length of value received from HIDL is 10 bytes(char value[10])
+ property_set(MNL_CONFIG_STATUS, value);
+ LOGD("gps radio property set success, value=%s", value);
+ } else {
+ LOGW("radio property value incorrect");
+ }
+ #else
+ LOGW("ANDROID_MNLD_PROP_SUPPORT not set");
+ #endif
+}
+
+static Debug2MnldInterface_callbacks g_debug2mnl_callbacks = {
+ debug_req_mnld_message,
+ debug_mnld_ne_property,
+ debug_mnld_radio_property
+};
+
+static void mnld_gfc_hbd_gps_open() {
+ LOGD("mnld_gfc_hbd_gps_open\n");
+ mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+ geofence->gps_used = true;
+ geofence->need_open_ack = true;
+ geofence->need_close_ack = false;
+ mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+}
+
+static void mnld_gfc_hbd_gps_close() {
+ LOGD("mnld_gfc_hbd_gps_close");
+ mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+ geofence->gps_used = false;
+ geofence->need_open_ack = false;
+ geofence->need_close_ack = true;
+ mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static gfc2mnl_interface g_gfc2mnl_interface = {
+ mnld_gfc_hbd_gps_open,
+ mnld_gfc_hbd_gps_close
+};
+
+void factory_mnld_gps_start() {
+ LOGD("factory_mnld_gps_start\n");
+ mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+ factory->gps_used = true;
+ factory->need_open_ack = true; // need to confirm flp deamon
+ factory->need_close_ack = false;
+ mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+}
+
+void factory_mnld_gps_stop() {
+ LOGD("factory_mnld_gps_stop");
+ mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+ factory->gps_used = false;
+ factory->need_open_ack = false;
+ factory->need_close_ack = false;
+ mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+// for AT cmd
+int at_test2mnl_gps_start(void) {
+ LOGD("at_test2mnl_gps_start\n");
+ mnld_gps_client* at_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+ at_test->gps_used = true;
+ at_test->need_open_ack = false; // need to confirm flp deamon
+ at_test->need_close_ack = false;
+ mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+ return 0;
+}
+
+int at_test2mnl_gps_stop(void) {
+ LOGD("at_test2mnl_gps_stop");
+ mnld_gps_client* at_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+ at_test->gps_used = false;
+ at_test->need_open_ack = false;
+ at_test->need_close_ack = false;
+ mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+ return 0;
+}
+
+/*****************************************
+ALL -> MAIN
+*****************************************/
+int mnld_gps_start_done(bool is_assist_req) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, GPS2MAIN_EVENT_START_DONE);
+ put_int(buff, &offset, is_assist_req);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_gps_start_nmea_timeout() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, GPS2MAIN_EVENT_NMEA_TIMEOUT);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_gps_stop_done() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, GPS2MAIN_EVENT_STOP_DONE);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+#if defined(GPS_SUSPEND_SUPPORT)
+int mnld_gps_suspend_done() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, GPS2MAIN_EVENT_SUSPEND_DONE);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_gps_suspend_timeout() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, GPS2MAIN_EVENT_SUSPEND_TIMEOUT);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+#endif
+
+int mnld_gps_reset_done() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, GPS2MAIN_EVENT_RESET_DONE);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_gps_update_location(gps_location location, int fix_mod) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, GPS2MAIN_EVENT_UPDATE_LOCATION);
+ put_binary(buff, &offset, (const char*)&location, sizeof(location));
+ put_int(buff, &offset, fix_mod);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_gps_update_sv(gnss_sv_info *sv_status) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, GPS2MAIN_EVENT_UPDATE_SV);
+ put_binary(buff, &offset, (const char*)sv_status, sizeof(gnss_sv_info));
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_gnss_nmea_done(void) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, GPS2MAIN_EVENT_NMEA_DONE);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_epo_download_done(epo_download_result result) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, EPO2MAIN_EVENT_EPO_DONE);
+ put_int(buff, &offset, result);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_qepo_download_done(epo_download_result result) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, QEPO2MAIN_EVENT_QEPO_DONE);
+ put_int(buff, &offset, result);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_qepo_bd_download_done(epo_download_result result) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, QEPO2MAIN_EVENT_QEPO_BD_DONE);
+ put_int(buff, &offset, result);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_qepo_ga_download_done(epo_download_result result) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, QEPO2MAIN_EVENT_QEPO_GA_DONE);
+ put_int(buff, &offset, result);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_mtknav_download_done(epo_download_result result) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, MTKNAV2MAIN_EVENT_MTKNAV_DONE);
+ put_int(buff, &offset, result);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_screen_on_notify() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, SCREEN2MAIN_EVENT_SCREEN_ON);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_screen_off_notify() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, SCREEN2MAIN_EVENT_SCREEN_OFF);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_screen_unknown_notify() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, SCREEN2MAIN_EVENT_SCREEN_UNKNOWN);
+ return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+void mnld_dump_gnss_sv_info(gnss_sv_info sv) {
+ unsigned int i = 0;
+ LOGD("[dump_gnss_sv_info], sv_num:%d", sv.num_svs);
+ for(i = 0; i < sv.num_svs; i++) {
+ LOGD("[%d]SV:%d, cons:%d, Cn0dBHz:%f, elev:%f, azim:%f, flags:%d, cf:%f"
+ ,i, sv.sv_list[i].svid, sv.sv_list[i].constellation, sv.sv_list[i].c_n0_dbhz, sv.sv_list[i].elevation
+ , sv.sv_list[i].azimuth, sv.sv_list[i].flags, sv.sv_list[i].carrier_frequency);
+ }
+}
+
+static int main_event_hdlr(int fd) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ main_internal_event cmd;
+ int read_len;
+
+ read_len = safe_recvfrom(fd, buff, sizeof(buff));
+ if (read_len <= 0) {
+ LOGE("main_event_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+ return -1;
+ }
+
+ cmd = get_int(buff, &offset, sizeof(buff));
+ LOGD("cmd:%d", cmd);
+ switch (cmd) {
+ case GPS2MAIN_EVENT_START_DONE: {
+ int is_assist_req = get_int(buff, &offset, sizeof(buff));
+ LOGW("GPS2MAIN_EVENT_START_DONE is_assist_req=%d", is_assist_req);
+ mnld_fsm(GPS_EVENT_START_DONE, is_assist_req, 0, NULL);
+ break;
+ }
+ case GPS2MAIN_EVENT_STOP_DONE: {
+ LOGW("GPS2MAIN_EVENT_STOP_DONE");
+ mnld_fsm(GPS_EVENT_STOP_DONE, 0, 0, NULL);
+ break;
+ }
+#if defined(GPS_SUSPEND_SUPPORT)
+ case GPS2MAIN_EVENT_SUSPEND_DONE: {
+ LOGW("GPS2MAIN_EVENT_SUSPEND_DONE");
+ mnld_fsm(GPS_EVENT_SUSPEND_DONE, 0, 0, NULL);
+ break;
+ }
+
+ case GPS2MAIN_EVENT_SUSPEND_TIMEOUT: {
+ if (mnld_is_gps_suspend()) {
+ LOGW("GPS2MAIN_EVENT_SUSPEND_TIMEOUT");
+ mnld_fsm(GPS_EVENT_SUSPEND_CLOSE, 0, 0, NULL);
+ } else {
+ LOGW("GPS2MAIN_EVENT_SUSPEND_TIMEOUT ignored");
+ }
+ break;
+ }
+#endif
+ case GPS2MAIN_EVENT_RESET_DONE: {
+ LOGW("GPS2MAIN_EVENT_RESET_DONE");
+ stop_timer(g_mnld_ctx.gps_status.timer_reset);
+ do_gps_reset_hdlr();
+ break;
+ }
+ case GPS2MAIN_EVENT_NMEA_TIMEOUT: {
+ LOGD("GPS2MAIN_EVENT_NMEA_TIMEOUT");
+ g_mnld_ctx.gps_status.is_in_nmea_timeout_handler = true;
+ if (mnld_is_gps_started_done()) {
+ mtk_gps_clear_gps_user();
+ LOGD("set nmea timeout event to main thread\n");
+ mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+ // send the reboot message to the related modules
+ if (mnl2hal_mnld_reboot() == -1) {
+ LOGE("mnl2hal_mnld_reboot failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ if (mnl2agps_mnl_reboot() == -1) {
+ LOGE("mnl2agps_mnl_reboot failed because of send2agps fail ,strerror:%s \n", strerror(errno));
+ }
+ }
+ g_mnld_ctx.gps_status.is_in_nmea_timeout_handler = false;
+ break;
+ }
+ case GPS2MAIN_EVENT_UPDATE_LOCATION: {
+ gps_location location;
+ memset(&location, 0, sizeof(location));
+ mnl_agps_location_time mnl_agps_location_sync_data;
+ memset(&mnl_agps_location_sync_data, 0, sizeof(mnl_agps_location_time));
+ int fix_mod;
+ get_binary(buff, &offset, (char*)&location, sizeof(buff), sizeof(gps_location));
+ fix_mod = get_int(buff, &offset, sizeof(buff));
+ mnl_agps_location_sync_data.alt_valid = (location.flags & MTK_GPS_LOCATION_HAS_ALT)? true : false;
+ mnl_agps_location_sync_data.source_valid = true;
+ mnl_agps_location_sync_data.source_gnss = true;
+ mnl_agps_location_sync_data.source_nlp = false;
+ mnl_agps_location_sync_data.source_sensor = false;
+ mnl_agps_location_sync_data.acc = (location.flags & MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY)? location.h_accuracy : 2000;
+ mnl_agps_location_sync_data.utc_time_sync.utc_time = location.timestamp;
+ if(fix_mod == 2 || fix_mod == 3)
+ mnl_agps_location_sync_data.utc_time_sync.utc_time_valid = 1;
+ LOGWX("GPS2MAIN_EVENT_UPDATE_LOCATION");
+ LOGD_ENG("wait_first_location=%d\n", g_mnld_ctx.gps_status.wait_first_location);
+
+#if defined(__LIBMNL_SIMULATOR__)
+ mnl2hal_c2k_cell_send(location);
+#endif
+ if(mnld_nfw_ctrl_gnss_enabled() && mtk_gps_get_nfw_visibility(MNLD_NFW_USER_AGPS)) {
+ if (g_mnld_ctx.gps_status.wait_first_location) {
+ g_mnld_ctx.gps_status.wait_first_location = false;
+ g_mnld_ctx.gps_status.gps_ttff = get_tick() - g_mnld_ctx.gps_status.gps_start_time;
+ #if ANDROID_MNLD_PROP_SUPPORT
+ if (get_gps_cmcc_log_enabled()) {
+ op01_log_gps_location(location.lat, location.lng, g_mnld_ctx.gps_status.gps_ttff);
+ }
+ #else
+ op01_log_gps_location(location.lat, location.lng, g_mnld_ctx.gps_status.gps_ttff);
+ #endif
+ }
+ }
+ mnl_agps_location_sync_data.lat = location.lat;
+ mnl_agps_location_sync_data.lng = location.lng;
+ mnl_agps_location_sync_data.alt = (float)location.alt;
+ mnl_agps_location_sync_data.sv_inuse_num_valid = mnld_get_sv_inuse_num_valid();
+ mnl_agps_location_sync_data.sv_inuse_num = mnld_get_sv_inuse_num();
+ mnld_nfw_mnl2agps_location_sync(&mnl_agps_location_sync_data);
+
+ LOGD_ENG("location_sync done\n");
+ break;
+ }
+ case GPS2MAIN_EVENT_UPDATE_SV: {
+ gnss_sv_info sv;
+ memset(&sv, 0, sizeof(sv));
+ get_binary(buff, &offset, (char*)&sv, sizeof(buff), sizeof(gnss_sv_info));
+ mnl2hal_gnss_sv(&sv);
+ //mnld_dump_gnss_sv_info(sv);
+ LOGD_ENG("sv_sync done\n");
+ break;
+ }
+ case EPO2MAIN_EVENT_EPO_DONE: {
+ epo_download_result result = get_int(buff, &offset, sizeof(buff));
+ LOGD("EPO2MAIN_EVENT_EPO_DONE result=%d", result);
+ g_mnld_ctx.epo_status.is_epo_downloading = false;
+ // TODO libmnl.so to inject the EPO
+ bool started = mnld_is_gps_or_ofl_started_done();
+ if (result == EPO_DOWNLOAD_RESULT_SUCCESS) {
+ if (started) {
+ epo_update_epo_file();
+ }
+ } else {
+ unlink(EPO_UPDATE_HAL);
+ }
+ break;
+ }
+ case QEPO2MAIN_EVENT_QEPO_DONE: {
+ epo_download_result result = get_int(buff, &offset, sizeof(buff));
+ bool started = mnld_is_gps_or_ofl_started_done();
+ LOGD("QEPO2MAIN_EVENT_QEPO_DONE result=%d started=%d\n", result, started);
+ if (started) {
+ qepo_update_quarter_epo_file(result);
+ } else {
+ LOGW("qepo download finsh before GPS start done");
+ qepo_update_flag = true;
+ }
+ break;
+ }
+ case QEPO2MAIN_EVENT_QEPO_BD_DONE: {
+ epo_download_result result = get_int(buff, &offset, sizeof(buff));
+ bool started = mnld_is_gps_or_ofl_started_done();
+ LOGD("QEPO2MAIN_EVENT_QEPO_BD_DONE result=%d started=%d\n", result, started);
+ if (started) {
+ qepo_update_quarter_epo_bd_file(result);
+ } else {
+ LOGW("qepo BD download finsh before GPS start done");
+ qepo_BD_update_flag = true;
+ }
+ break;
+ }
+ case QEPO2MAIN_EVENT_QEPO_GA_DONE: {
+ epo_download_result result = get_int(buff, &offset, sizeof(buff));
+ bool started = mnld_is_gps_or_ofl_started_done();
+ LOGD("QEPO2MAIN_EVENT_QEPO_GA_DONE result=%d started=%d\n", result, started);
+ if (started) {
+ qepo_update_quarter_epo_ga_file(result);
+ } else {
+ LOGW("qepo GA download finsh before GPS start done");
+ qepo_GA_update_flag = true;
+ }
+ break;
+ }
+ case MTKNAV2MAIN_EVENT_MTKNAV_DONE: {
+ epo_download_result result = get_int(buff, &offset, sizeof(buff));
+ bool started = mnld_is_gps_or_ofl_started_done();
+ LOGD("MTKNAV2MAIN_EVENT_MTKNAV_DONE result=%d started=%d\n", result, started);
+ if (started) {
+ mtknav_update_mtknav_file(result);
+ } else {
+ LOGW("mtknav download finsh before GPS start done");
+ mtknav_update_flag = true;
+ }
+ break;
+ }
+ case GPS2MAIN_EVENT_OUTPUT_DATA: {
+ mnld_gps_output_data_handle(buff, offset);
+ break;
+ }
+ case SCREEN2MAIN_EVENT_SCREEN_UNKNOWN:
+ case SCREEN2MAIN_EVENT_SCREEN_OFF: {
+ if (cmd == SCREEN2MAIN_EVENT_SCREEN_OFF) {
+ g_mnld_ctx.screen_status = SCREEN_STATUS_OFF;
+ } else {
+ g_mnld_ctx.screen_status = SCREEN_STATUS_UNKNOWN;
+ }
+ LOGD("SCREEN2MAIN_EVENT_SCREEN = %d", g_mnld_ctx.screen_status);
+#if defined(GPS_SUSPEND_SUPPORT)
+ if (mnld_is_gps_suspend()) {
+ mnld_fsm(GPS_EVENT_SUSPEND_CLOSE, 0, 0, NULL);
+ }
+#endif
+ break;
+ }
+ case SCREEN2MAIN_EVENT_SCREEN_ON: {
+ g_mnld_ctx.screen_status = SCREEN_STATUS_ON;
+ LOGD("SCREEN2MAIN_EVENT_SCREEN = %d", g_mnld_ctx.screen_status);
+#if defined(GPS_SUSPEND_SUPPORT)
+ if (mnld_gps_suspend_get_timeout_sec() &&
+ g_mnld_ctx.gps_status.is_suspend_timer_running) {
+ // It's possible timer_suspend is running, we can cancel it
+ // if screen change to be on.
+ // And it should be no harm to cancel it even when it's not running.
+ stop_timer_alarm(g_mnld_ctx.fds.fd_suspend_timer);
+ g_mnld_ctx.gps_status.is_suspend_timer_running = false;
+ }
+#endif
+ break;
+ }
+ case GPS2MAIN_EVENT_NMEA_DONE: {
+ LOGD("GPS2MAIN_EVENT_NMEA_DONE");
+ if(mnl2hal_nmea_done() == -1) {
+ LOGD("Report GPS2MAIN_EVENT_NMEA_DONE fail");
+ }
+ break;
+ }
+ default: {
+ LOGW("event = %d is unhandled", cmd);
+ }
+ }
+ return 0;
+}
+
+/*****************************************
+Threads
+*****************************************/
+static void mnld_main_thread_timeout() {
+ if (mnld_timeout_ne_enabled() == false) {
+ LOGE("mnld_main_thread_timeout() dump and exit.");
+ mnld_exiting = true;
+ gps_dbg_log_exit_flush(0);
+ mnld_block_exit();
+ } else {
+ LOGE("mnld_main_thread_timeout() crash here for debugging");
+ CRASH_TO_DEBUG();
+ }
+}
+
+static void mnld_gps_start_timeout() {
+ if (mnld_timeout_ne_enabled() == false) {
+ LOGE("mnld_gps_start_timeout() dump and exit.");
+ mnld_exiting = true;
+ gps_dbg_log_exit_flush(0);
+ mnld_block_exit();
+ } else {
+ LOGE("mnld_gps_start_timeout() crash here for debugging");
+ CRASH_TO_DEBUG();
+ }
+}
+
+static void mnld_gps_stop_timeout() {
+ if (mnld_timeout_ne_enabled() == false) {
+ LOGE("mnld_gps_stop_timeout() dump and exit.");
+ mnld_exiting = true;
+ gps_dbg_log_exit_flush(0);
+ mnld_block_exit();
+ } else {
+ LOGE("mnld_gps_stop_timeout() crash here for debugging");
+ CRASH_TO_DEBUG();
+ }
+}
+
+static void mnld_gps_reset_timeout() {
+ if (mnld_timeout_ne_enabled() == false) {
+ LOGE("mnld_gps_reset_timeout() dump and exit.");
+ mnld_exiting = true;
+ gps_dbg_log_exit_flush(0);
+ mnld_block_exit();
+ } else {
+ LOGE("mnld_gps_reset_timeout() crash here for debugging");
+ CRASH_TO_DEBUG();
+ }
+}
+
+#if defined(GPS_SUSPEND_SUPPORT)
+static void mnld_gps_suspend_timeout_callback() {
+ if (mnld_is_gps_suspend()) {
+ LOGD("Suspend mode timer timeout, leave suspend state and stop gps");
+ if (mnld_gps_suspend_timeout() == -1) {
+ LOGE("mnld_gps_suspend_timeout failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ } else {
+ LOGD("No need to handle for GPS has leaved suspend state");
+ }
+}
+
+void set_clk_ext_ni_only(int flag) {
+ clk_extension_ni_only = flag;
+}
+
+bool is_clk_ext_ni_only() {
+ if(clk_extension_ni_only == 0) {
+ return false;
+ }
+ return true;
+}
+
+bool mnld_gps_suspend_mode_entry_check(void) {
+ bool to_go = false;
+ bool meta_or_factory = in_meta_factory;
+ int timeout_sec = 0;
+
+ if (g_mnld_ctx.gps_status.is_in_nmea_timeout_handler || meta_or_factory) {
+ // For nmea timeout case, need to do close rather than suspend
+ // and meta_or_factory not utilize suspend mode
+ to_go = false;
+ } else if (mnld_gps_suspend_ext_is_enabled()) {
+ timeout_sec = mnld_gps_suspend_ext_get_timeout_sec();
+ // The strategy is using suspend to replace close, whatever screen on or off,
+ if (agps_open_gps_flag || !is_clk_ext_ni_only()) {
+ to_go = true;
+ } else {
+ to_go = false;
+ }
+ } else if (mnld_gps_suspend_is_enabled()) {
+ timeout_sec = mnld_gps_suspend_get_timeout_sec();
+ if (g_mnld_ctx.screen_status == SCREEN_STATUS_ON) {
+ // The strategy is using suspend to replace close when screen on,
+ // so timeout_sec is ignored and to_go is set true.
+ to_go = true;
+ } else if (g_mnld_ctx.screen_status == SCREEN_STATUS_OFF &&
+ timeout_sec > 0) {
+ // timeout_sec > 0 stands for it needs to keep in suspend for
+ // some time (timeout_sec) when user stop gps under screen off condition.
+ // So, to_go still true;
+ // Otherwise, we need not to go in suspend status, so to_go is false
+ to_go = true;
+ }
+ } else {
+ to_go = false;
+ }
+
+ LOGW("suspend check: to_go = %d, scr = %d, timeout_sec = %d, nmea_timeout = %d, meta_or_factory = %d, agps_open_gps_flag= %d, suspend_ext:EN:%d, AV:%d, suspend EN:%d",
+ to_go, g_mnld_ctx.screen_status, timeout_sec,
+ g_mnld_ctx.gps_status.is_in_nmea_timeout_handler, meta_or_factory, agps_open_gps_flag,
+ mnld_gps_suspend_ext_is_enabled(), mnld_gps_suspend_ext_is_available(), mnld_gps_suspend_is_enabled());
+ agps_open_gps_flag = false;
+ return to_go;
+}
+#endif
+
+void gps_mnld_restart_mnl_process(void) {
+ LOGD("gps_mnld_restart_mnl_process\n");
+ //mnld_gps_start_nmea_timeout();
+ if (mnld_timeout_ne_enabled() == false) {
+ LOGE("gps_mnld_restart_mnl_process() dump and exit.");
+ mnld_exiting = true;
+ gps_dbg_log_exit_flush(0);
+ mnld_block_exit();
+ } else {
+ LOGE("gps_mnld_restart_mnl_process() crash here for debugging");
+ CRASH_TO_DEBUG();
+ }
+}
+
+void mnld_gps_request_nlp(int src) {
+ LOGD("mnld_gps_request_nlp src: %d", src);
+ //Mnld2NlpUtilsInterface_reqNlpLocation(&g_mnld_ctx.fds.fd_nlp_utils, src);
+ bool fgemergency = true; //Emergency flag always set to true, because framework will double check it by itself
+ if (mnl2hal_request_nlp((bool)src, fgemergency) == -1) {
+ LOGE("mnl2hal_request_nlp failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+}
+
+static void* mnld_main_thread(void *arg) {
+ #define MAX_EPOLL_EVENT 50
+ timer_t hdlr_timer = init_timer(mnld_main_thread_timeout);
+ struct epoll_event events[MAX_EPOLL_EVENT];
+ UNUSED(arg);
+
+ memset(events, 0, sizeof(events));
+ int epfd = epoll_create(MAX_EPOLL_EVENT);
+ if (epfd == -1) {
+ LOGE("mnld_main_thread() epoll_create failure reason=[%s]%d",
+ strerror(errno), errno);
+ return 0;
+ }
+ mnld_init_time_aiding_ctx();
+#ifdef MTK_AGPS_SUPPORT
+ int fd_agps = g_mnld_ctx.fds.fd_agps;
+#endif
+ int fd_hal_basic_server = g_mnld_ctx.fds.fd_hal_basic_server;
+ int fd_hal_ext_server = g_mnld_ctx.fds.fd_hal_ext_server;
+ int fd_geofence = g_mnld_ctx.fds.fd_geofence;
+ int fd_geofence_control = g_mnld_ctx.fds.fd_geofence_control;
+ int fd_at_cmd = g_mnld_ctx.fds.fd_at_cmd;
+ int fd_int = g_mnld_ctx.fds.fd_int;
+ int fd_mtklogger = g_mnld_ctx.fds.fd_mtklogger;
+ int fd_meta = g_mnld_ctx.fds.fd_meta;
+ int fd_debug = g_mnld_ctx.fds.fd_debug;
+ int fd_suspend_timer = g_mnld_ctx.fds.fd_suspend_timer;
+#ifdef MTK_AGPS_SUPPORT
+ if ((fd_agps > 0) && epoll_add_fd(epfd, fd_agps) == -1) {
+ LOGE("mnld_main_thread() epoll_add_fd() failed for fd_agps failed");
+ //return 0;
+ }
+#endif
+
+ if ((fd_hal_basic_server > 0) && epoll_add_fd(epfd, fd_hal_basic_server) == -1) {
+ LOGE("mnld_main_thread() epoll_add_fd() failed for fd_hal_basic_server failed");
+ //return 0;
+ }
+
+ if ((fd_hal_ext_server > 0) && epoll_add_fd(epfd, fd_hal_ext_server) == -1) {
+ LOGE("mnld_main_thread() epoll_add_fd() failed for fd_hal_ext_server failed");
+ //return 0;
+ }
+
+ if ((fd_geofence > 0) && epoll_add_fd(epfd, fd_geofence) == -1) {
+ LOGE("mnld_main_thread() epoll_add_fd() failed for fd_geofence failed");
+ //return 0;
+ }
+
+ if (epoll_add_fd(epfd, fd_geofence_control) == -1) {
+ LOGE("mnld_main_thread() epoll_add_fd() failed for fd_geofence_control failed");
+ //return 0;
+ }
+
+ if ((fd_at_cmd > 0) && epoll_add_fd(epfd, fd_at_cmd) == -1) {
+ LOGE("mnld_main_thread() epoll_add_fd() failed for fd_at_cmd failed");
+ //return 0;
+ }
+ if ((fd_int > 0) && epoll_add_fd(epfd, fd_int) == -1) {
+ LOGE("mnld_main_thread() epoll_add_fd() failed for fd_int failed");
+ //return 0;
+ }
+ if ((fd_mtklogger > 0) && epoll_add_fd(epfd, fd_mtklogger) == -1) {
+ LOGE("mnld_main_thread() epoll_add_fd() failed for fd_mtklogger failed");
+ //return 0;
+ }
+
+ if ((fd_meta > 0) && epoll_add_fd(epfd, fd_meta) == -1) {
+ LOGE("mnld_main_thread() epoll_add_fd() failed for fd_meta failed");
+ //return 0;
+ }
+
+ if ((fd_debug > 0) && epoll_add_fd(epfd, fd_debug) == -1) {
+ LOGE("mnld_main_thread() epoll_add_fd() failed for fd_debug failed");
+ //return 0;
+ }
+
+ if(mnld_gps_suspend_ext_is_available() ||
+ (mnld_gps_suspend_is_enabled() && (mnld_gps_suspend_get_timeout_sec() > 0))) {
+ if (epoll_add_fd2(epfd, fd_suspend_timer, (EPOLLIN | EPOLLWAKEUP)) == -1) {
+ LOGE("mnld_main_thread() epoll_add_fd() failed for fd_suspend_timer failed");
+ //return 0;
+ }
+ }
+ while (1) {
+ int i;
+ int n = 0;
+ memset(events, 0, sizeof(events));
+ #ifdef CONFIG_GPS_ENG_LOAD
+ LOGD("mnld_main_thread() enter wait\n");
+ #endif
+ n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+ if (n > 1) {
+ LOGD("n=%d\n", n);
+ } else if (n == -1) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ LOGE("mnld_main_thread() epoll_wait failure reason=[%s]%d",
+ strerror(errno), errno);
+ return 0;
+ }
+ }
+ mnld_wake_lock_take();
+ start_timer(hdlr_timer, MNLD_MAIN_HANDLER_TIMEOUT);
+ for (i = 0; i < n; i++) {
+ #ifdef MTK_AGPS_SUPPORT
+ if (events[i].data.fd == fd_agps) {
+ if (events[i].events & EPOLLIN) {
+ //LOGD("agps2mnl_hdlr msg");
+ agps2mnl_hdlr(fd_agps, &g_agps2mnl_interface);
+ }
+ } else
+ #endif
+ if (events[i].data.fd == fd_hal_basic_server) {
+ if (events[i].events & EPOLLIN) {
+ LOGD_ENG("hal2mnl_basic_server_hdlr msg");
+ hal2mnl_basic_server_hdlr(fd_hal_basic_server, epfd);
+ }
+ } else if (events[i].data.fd == fd_hal_ext_server) {
+ if (events[i].events & EPOLLIN) {
+ LOGD_ENG("hal2mnl_ext_server_hdlr msg");
+ hal2mnl_ext_server_hdlr(fd_hal_ext_server, epfd);
+ }
+ } else if (events[i].data.fd == fd_geofence) {
+ if (events[i].events & EPOLLIN) {
+ mtk_geofence_epoll_server_hdlr(fd_geofence, epfd);
+ }
+ } else if(client_list_contains(&g_geofence_client_list, events[i].data.fd)) {
+ if(events[i].events & EPOLLIN) {
+ mtk_geofence_epoll_client_hdlr(events[i].data.fd, &g_gfc2mnl_interface);
+ }
+ } else if (events[i].data.fd == fd_geofence_control) {
+ if (events[i].events & EPOLLIN) {
+ mtk_geofence_epoll_control_server_hdlr(fd_geofence_control, epfd);
+ }
+ } else if(client_list_contains(&g_geofence_client_control_list, events[i].data.fd)) {
+ if(events[i].events & EPOLLIN) {
+ mtk_geofence_epoll_client_control_hdlr(events[i].data.fd, &g_gfc2mnl_interface);
+ }
+ } else if (events[i].data.fd == fd_at_cmd) {
+ if (events[i].events & EPOLLIN) {
+ LOGD("at_cmd2mnl_hdlr msg");
+ at_cmd2mnl_hdlr(fd_at_cmd);
+ }
+ } else if (events[i].data.fd == fd_int) {
+ if (events[i].events & EPOLLIN) {
+ LOGD_ENG("main_event_hdlr msg");
+ main_event_hdlr(fd_int);
+ }
+ } else if (events[i].data.fd == fd_mtklogger) {
+ if ((events[i].events & EPOLLIN) != 0) {
+ LOGD("mtklogger2mnl_hdlr msg");
+ start_timer(hdlr_timer, MNLD_GPS_LOG_HANDLER_TIMEOUT); // mkdir in external sdcard so slowly
+ mtklogger2mnl_hdlr(fd_mtklogger, &g_mnld_ctx.fds.fd_mtklogger_client);
+ }
+ } else if (events[i].data.fd == fd_meta) {
+ if (events[i].events & EPOLLIN) {
+ LOGD("meta2mnl_event_hdlr msg");
+ Meta2MnldInterface_receiver_read_and_decode(fd_meta, &g_meta2mnl_callbacks);
+ }
+ } else if (events[i].data.fd == fd_debug) {
+ if (events[i].events & EPOLLIN) {
+ LOGD_ENG("debug2mnl_event_hdlr msg");
+ Debug2MnldInterface_receiver_read_and_decode(fd_debug, &g_debug2mnl_callbacks);
+ }
+ } else if(client_list_contains(&g_hal_basic_client_list, events[i].data.fd)) {
+ if(events[i].events & EPOLLIN) {
+ hal2mnl_basic_client_hdlr(events[i].data.fd, &g_hal2mnl_basic_interface);
+ }
+ } else if(client_list_contains(&g_hal_ext_client_list, events[i].data.fd)) {
+ if(events[i].events & EPOLLIN) {
+ hal2mnl_ext_client_hdlr(events[i].data.fd, &g_hal2mnl_ext_interface);
+ }
+ } else {
+ LOGE("mnld_main_thread() unknown fd=%d",
+ events[i].data.fd);
+ }
+ }
+ stop_timer(hdlr_timer);
+ mnld_wake_lock_give();
+ }
+ LOGE("mnld_main_thread() exit");
+ return 0;
+}
+
+int mnld_init() {
+ pthread_t pthread_main;
+
+ // init fds
+#ifdef MTK_AGPS_SUPPORT
+ g_mnld_ctx.fds.fd_agps = create_agps2mnl_fd();
+ if (g_mnld_ctx.fds.fd_agps < 0) {
+ LOGE("create_agps2mnl_fd() failed");
+ //return -1;
+ }
+#else
+ g_mnld_ctx.fds.fd_agps = 0;
+#endif
+
+ g_mnld_ctx.fds.fd_hal_basic_server = create_hal2mnl_basic_fd();
+ if (g_mnld_ctx.fds.fd_hal_basic_server < 0) {
+ LOGE("create_hal2mnl_basic_fd() failed");
+ //return -1;
+ }
+
+ g_mnld_ctx.fds.fd_hal_ext_server = create_hal2mnl_ext_fd();
+ if (g_mnld_ctx.fds.fd_hal_ext_server < 0) {
+ LOGE("create_hal2mnl_ext_fd() failed");
+ //return -1;
+ }
+
+ g_mnld_ctx.fds.fd_geofence= create_geofence2mnl_data_fd();
+ if (g_mnld_ctx.fds.fd_geofence < 0) {
+ LOGE("create_gfchal2mnl_fd() failed");
+ //return -1;
+ }
+
+ g_mnld_ctx.fds.fd_geofence_control= create_geofence2mnl_control_fd();
+ if (g_mnld_ctx.fds.fd_geofence_control < 0) {
+ LOGE("create_geofence2mnl_control_fd() failed");
+ //return -1;
+ }
+
+ g_mnld_ctx.fds.fd_at_cmd = create_at2mnl_fd();
+ if (g_mnld_ctx.fds.fd_at_cmd < 0) {
+ LOGE("create_at2mnl_fd() failed");
+ //return -1;
+ }
+ g_mnld_ctx.fds.fd_int = socket_bind_udp_force(MNLD_MAIN_SOCKET);
+ if (g_mnld_ctx.fds.fd_int < 0) {
+ LOGE("socket_bind_udp(MNLD_MAIN_SOCKET) failed");
+ //return -1;
+ }
+ //g_mnld_ctx.fds.fd_meta = mtk_socket_server_bind_local(META_TO_MNLD_SOCKET, SOCK_NS_ABSTRACT);
+ g_mnld_ctx.fds.fd_meta = socket_bind_udp(META_TO_MNLD_SOCKET);
+ if (g_mnld_ctx.fds.fd_meta < 0) {
+ LOGE("create meta fd failed");
+ //return -1;
+ }
+
+ g_mnld_ctx.fds.fd_debug = mtk_socket_server_bind_local(DEBUG_TO_MNLD_SOCKET, SOCK_NS_ABSTRACT);
+ if (g_mnld_ctx.fds.fd_debug < 0) {
+ LOGE("create debug fd failed");
+ //return -1;
+ }
+
+ g_mnld_ctx.fds.fd_mtklogger = mtk_socket_server_bind_local(MTKLOGGER_TO_MNLD_SOCKET, SOCK_NS_ABSTRACT);
+ if (g_mnld_ctx.fds.fd_mtklogger < 0) {
+ LOGE("create_mtklogger2mnl_fd() failed");
+ //return -1;
+ }
+
+ mtk_socket_client_init_local(&g_mnld_ctx.fds.fd_debug_client,
+ MNLD_TO_DEBUG_SOCKET, SOCK_NS_ABSTRACT);
+
+ mtk_socket_client_init_local(&g_mnld_ctx.fds.fd_nlp_utils,
+ MNLD_TO_NLP_UTILS_SOCKET, SOCK_NS_ABSTRACT);
+
+ mtk_socket_client_init_local(&g_mnld_ctx.fds.fd_mtklogger_client,
+ MNLD_TO_MTKLOGGER_SOCKET, SOCK_NS_ABSTRACT);
+ mtk_socket_client_init_local(&gpslogd_fd, LOG_HIDL_INTERFACE, SOCK_NS_ABSTRACT);
+ // init timers
+ g_mnld_ctx.gps_status.timer_start = init_timer(mnld_gps_start_timeout);
+ if (g_mnld_ctx.gps_status.timer_start == INVALID_TIMERID) {
+ LOGE("init_timer(mnld_gps_start_timeout) failed");
+ return -1;
+ }
+
+ g_mnld_ctx.gps_status.timer_stop = init_timer(mnld_gps_stop_timeout);
+ if (g_mnld_ctx.gps_status.timer_stop == INVALID_TIMERID) {
+ LOGE("init_timer(mnld_gps_stop_timeout) failed");
+ return -1;
+ }
+
+ g_mnld_ctx.gps_status.timer_reset = init_timer(mnld_gps_reset_timeout);
+ if (g_mnld_ctx.gps_status.timer_reset == INVALID_TIMERID) {
+ LOGE("init_timer(mnld_gps_reset_timeout) failed");
+ return -1;
+ }
+
+ g_mnld_ctx.gps_status.timer_nmea_monitor = init_timer(gps_mnld_restart_mnl_process);
+ if (g_mnld_ctx.gps_status.timer_nmea_monitor == INVALID_TIMERID) {
+ LOGE("init_timer(gps_mnld_restart_mnl_process) failed");
+ return -1;
+ }
+
+#if defined(GPS_SUSPEND_SUPPORT)
+// need clk_ext enable or suspend available
+ if(mnld_gps_suspend_ext_is_available() ||
+ (mnld_gps_suspend_is_enabled() && (mnld_gps_suspend_get_timeout_sec() > 0))) {
+ g_mnld_ctx.gps_status.is_suspend_timer_running = false;
+ g_mnld_ctx.fds.fd_suspend_timer = init_timer_alarm();
+ if (g_mnld_ctx.fds.fd_suspend_timer == -1) {
+ mtk_gps_suspend_extention_available_set(CLK_EXT_AVAILABLE_DISABLE);
+ LOGE("init_timer(mnld_gps_suspend_timeout) failed");
+ }
+ }
+#endif
+ // set screen status to unknown until screen monitor thread notify the real status
+ g_mnld_ctx.screen_status = SCREEN_STATUS_UNKNOWN;
+
+ // init threads
+ pthread_create(&pthread_main, NULL, mnld_main_thread, NULL);
+
+ // send the reboot message to the related modules
+ if (mnl2hal_release_wakelock() == -1) {
+ LOGE("mnl2hal_release_wakelock failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ if (mnl2hal_mnld_reboot() == -1) {
+ LOGE("mnl2hal_mnld_reboot failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ mnl2agps_mnl_reboot();
+ Mnld2DebugInterface_mnldUpdateReboot(&g_mnld_ctx.fds.fd_debug_client);
+ mnld2logd_close_gpslog();
+ mnld2logd_close_mpelog();
+ mnld2logd_close_dumplog();
+ mnld_gps_update_name();
+ mtk_geofence_init();
+ return 0;
+}
+
+bool mnld_is_gps_started() {
+ if (g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_STARTING ||
+ g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_STARTED) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool mnld_is_gps_or_ofl_started() {
+ return mnld_is_gps_started();
+}
+
+bool mnld_is_gps_started_done() {
+ if (g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_STARTED) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool mnld_is_gps_or_ofl_started_done() {
+ if (mnld_is_gps_started_done() ||
+ g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_OFL_STARTED) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool mnld_is_gps_meas_enabled() {
+ return g_mnld_ctx.gps_status.is_gps_meas_enabled;
+}
+
+bool mnld_is_gps_navi_enabled() {
+ return g_mnld_ctx.gps_status.is_gps_navi_enabled;
+}
+
+// Due to gps_state extends from 4 states to 7 states (3 more for GPS offload),
+// mnld_is_gps_stopped might be overdue. Considering to deprecate this API,
+// and use mnld_is_gps_and_ofl_stopped as replace or change it.
+bool mnld_is_gps_stopped() {
+ if (g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_IDLE ||
+ g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_STOPPING) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool mnld_is_gps_and_ofl_stopped() {
+ if (g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_IDLE ||
+ g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_STOPPING ||
+ g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_OFL_STOPPING) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+#if defined(GPS_SUSPEND_SUPPORT)
+bool mnld_is_gps_suspend() {
+ if (g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_SUSPEND) {
+ return true;
+ } else {
+ return false;
+ }
+}
+#endif
+
+bool mnld_is_epo_download_finished() {
+ if (g_mnld_ctx.epo_status.is_epo_downloading == false) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool mnld_check_log_enable() {
+ char result[PROPERTY_VALUE_MAX] = {0};
+ bool ret = false;
+ if(property_get("ro.logsystem.usertype", result, NULL) != 0) {
+ if (result[0] != '3' && result[0] != '5') {
+ LOGD("user version:%d\n", result[0]);
+ ret = false;
+ } else {
+ LOGD("beta version:%d\n", result[0]);
+ ret = true;
+ }
+ }
+ return ret;
+}
+
+void daemon_parse_commandline(int argc, char *argv[])
+{
+ int i = 0;
+ for (i = 1; i < argc; i++)
+ {
+ if (strcmp("-d", argv[i]) == 0)
+ {
+ set_log_level(&log_dbg_level, atoi(argv[++i]));
+ }
+ }
+}
+
+int main(int argc, char** argv) {
+ mnld_wake_lock_init();
+ mnld_wake_lock_take();
+ LOGD("mnld version=%s\n", MNLD_VERSION);
+ daemon_parse_commandline(argc, argv);
+
+ set_signal_ignore(SIGPIPE);
+ set_signal_ignore(SIGBUS);
+
+ memset(&g_mnld_ctx, 0, sizeof(g_mnld_ctx));
+#ifdef MTK_GPS_DUAL_FREQ_SUPPORT /*Defined in Android.mk*/
+ mtk_gps_support_l5_set(true);
+ if (property_set(GPS_L5_SUPPORT_P, "1") != 0) {
+ LOGE("set GPS_L5_SUPPORT_P %s\n", strerror(errno));
+ }
+#endif
+ if ((argc >= 3) //Parameter count check
+ && (!strncmp(argv[2], "meta", 4) || !strncmp(argv[2], "factory", 7)
+ || !strncmp(argv[2], "test", 4) || !strncmp(argv[2], "PDNTest", 7))) {
+ in_meta_factory = 1;
+ }
+ chip_detector();
+ /*get gps_epo_type begin*/
+ if (strcmp(chip_id, "0x6572") == 0 || strcmp(chip_id, "0x6582") == 0 || strcmp(chip_id, "0x6570") == 0 ||
+ strcmp(chip_id, "0x6580") == 0 || strcmp(chip_id, "0x6592") == 0 || strcmp(chip_id, "0x6571") == 0 ||
+ strcmp(chip_id, "0x8127") == 0 || strcmp(chip_id, "0x0335") == 0 ||strcmp(chip_id, "0x8163") == 0) {
+ gps_epo_type = 1; // GPS only
+ } else if (strcmp(chip_id, "0x6630") == 0 || strcmp(chip_id, "0x6752") == 0 || strcmp(chip_id, "0x6755") == 0
+ || strcmp(chip_id, "0x6797") == 0 || strcmp(chip_id, "0x6632") == 0 || strcmp(chip_id, "0x6759") == 0
+ || strcmp(chip_id, "0x6763") == 0 || strcmp(chip_id, "0x6758") == 0 || strcmp(chip_id, "0x6739") == 0
+ || strcmp(chip_id, "0x6771") == 0 || strcmp(chip_id, "0x6775") == 0 || strcmp(chip_id, "0x6765") == 0
+ || strcmp(chip_id, "0x3967") == 0 || strcmp(chip_id, "0x6761") == 0 || strcmp(chip_id, "0x6779") == 0
+ || strcmp(chip_id, "0x6768") == 0 || strcmp(chip_id, "0x6885") == 0 || strcmp(chip_id, "0x6873") == 0
+ || strcmp(chip_id, "0x6880") == 0 || strcmp(chip_id, "0x6890") == 0 ) {
+ gps_epo_type = 0; // G+G
+ } else {
+ gps_epo_type = 0; // Default is G+G
+ }
+
+ /*get initial GNSS OP Mode*/
+ get_chip_gnss_op_mode();
+
+#if defined(GPS_SUSPEND_SUPPORT)
+ mnld_gps_suspend_check_capability();
+#endif
+
+ if (mnld_check_log_enable()) {
+ gps_dbg_log_mode_set(gps_dbg_log_mode_get() |MNLD_WRITE_LOG_TOFILE);
+ MNLD_STRNCPY(gps_debuglog_file_name, "/data/vendor/log/gps/GPS_HOST" ,GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ MNLD_STRNCPY(storagePath, "/data/vendor/log/gps/" ,GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ MNLD_STRNCPY(storagePath_mtklogger_set, "/data/vendor/log/gps/" ,GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+ LOGD("default enable GPS debug log\n");
+ gps_dbg_log_state_set_output_enable();
+ }
+ if (mnl_init()) {
+ LOGE("mnl_init: %d (%s)\n", errno, strerror(errno));
+ }
+ #ifdef ADC_CAPTURE_DEFINE
+ if (mnld_adc_capture_is_enabled() == 1) {
+ mnld_gps_emi_init(1);
+ }
+ #endif
+ if (mtk_socket_tcp_startListening(META_TO_MNLD_LOGCTRL_SOCKET, SOCK_NS_ABSTRACT) < 0) {
+ LOGE("create meta logctrl fd failed");
+ }
+ if ((argc >= 3) //Parameter count check
+ && (!strncmp(argv[2], "meta", 4) || !strncmp(argv[2], "factory", 7)
+ || !strncmp(argv[2], "test", 4) || !strncmp(argv[2], "PDNTest", 7))) {
+ mnld_factory_test_entry(argc, argv);
+ mnld_wake_lock_give();
+ } else {
+ gps_control_init();
+ epo_downloader_init();
+ qepo_downloader_init();
+ mtknav_downloader_init();
+ op01_log_init();
+ #if defined(MTK_MPE_SUPPORT)
+ mpe_function_init();
+ #endif
+ mnld_init();
+ // For MNL5.9 and later version, we move flp_monitor_init after mnld_init,
+ // creating that the monitor thread after mnld msg socket initialized,
+ // then the screen status can be send to mnld main thread without concern
+ // of msg dropping because socket not ready.
+#ifdef __TEST__
+ mnld_test_start();
+#else
+ mnld_wake_lock_give();
+ block_here();
+ mnld_wake_lock_deinit();
+ //Will go here after calling mnld_block_exit
+ #if defined(__ANDROID_OS__)
+ mnld_dump_exit();
+ #endif
+#endif
+ }
+/*
+ LOGD("sizeof(mnld_context)=%d", sizeof(mnld_context)); // 48
+ LOGD("sizeof(gps_location)=%d", sizeof(gps_location)); // 56
+ LOGD("sizeof(gnss_sv)=%d", sizeof(gnss_sv )); // 20
+ LOGD("sizeof(gnss_sv_info)=%d", sizeof(gnss_sv_info)); // 5124
+ LOGD("sizeof(gps_data)=%d", sizeof(gps_data )); // 7752
+ LOGD("sizeof(gps_nav_msg)=%d", sizeof(gps_nav_msg)); // 80
+*/
+ return 0;
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mnld_uti.c b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mnld_uti.c
new file mode 100644
index 0000000..c601ed0
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mnld_uti.c
@@ -0,0 +1,327 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+/*******************************************************************************
+* Dependency
+*******************************************************************************/
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+
+#if defined(__ANDROID_OS__)
+#include <cutils/properties.h>
+#include <android/log.h>
+#include <cutils/android_filesystem_config.h>
+#endif
+
+#include "mtk_prop_util.h"
+#include <stdio.h> /* Standard input/output definitions */
+#include <string.h> /* String function definitions */
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h> // For 'O_RDWR' & 'O_EXCL'
+#include <poll.h>
+#include "mnld_utile.h"
+#include <termios.h>
+#if MTK_GPS_NVRAM
+#include "CFG_GPS_File.h"
+#endif
+#include "mnl_agps_interface.h"
+
+#include "mtk_lbs_utility.h"
+
+#include "mtk_mnld_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "mnld_uti"
+
+extern int mtk_gps_sys_init();
+#if MTK_GPS_NVRAM
+extern ap_nvram_gps_config_struct stGPSReadback;
+#endif
+extern int in_meta_factory;
+
+/*****************************************************************************/
+int read_NVRAM() {
+ int ret = 0;
+ ret = mtk_gps_sys_init();
+ #if MTK_GPS_NVRAM
+ if (strcmp(stGPSReadback.dsp_dev, DSP_DEV) == 0) {
+ LOGE("not 3332 UART port\n");
+ return 1;
+ }
+ #endif
+ return ret;
+}
+
+int init_3332_interface(const int fd) {
+ struct termios termOptions;
+ // fcntl(fd, F_SETFL, 0);
+
+ // Get the current options:
+ tcgetattr(fd, &termOptions);
+
+ // Set 8bit data, No parity, stop 1 bit (8N1):
+ termOptions.c_cflag &= ~PARENB;
+ termOptions.c_cflag &= ~CSTOPB;
+ termOptions.c_cflag &= ~CSIZE;
+ termOptions.c_cflag |= CS8 | CLOCAL | CREAD;
+
+ LOGD("GPS_Open: c_lflag=%x,c_iflag=%x,c_oflag=%x\n", termOptions.c_lflag, termOptions.c_iflag,
+ termOptions.c_oflag);
+ // termOptions.c_lflag
+
+ // Raw mode
+ termOptions.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF | IXANY);
+ termOptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*raw input*/
+ termOptions.c_oflag &= ~OPOST; /*raw output*/
+
+ tcflush(fd, TCIFLUSH); // clear input buffer
+ termOptions.c_cc[VTIME] = 10; /* inter-character timer unused, wait 1s, if no data, return */
+ termOptions.c_cc[VMIN] = 0; /* blocking read until 0 character arrives */
+
+ // Set baudrate to 38400 bps
+ cfsetispeed(&termOptions, B115200); /*set baudrate to 115200, which is 3332 default bd*/
+ cfsetospeed(&termOptions, B115200);
+
+ tcsetattr(fd, TCSANOW, &termOptions);
+
+ return 0;
+}
+
+int hw_test_3332(const int fd) {
+ ssize_t bytewrite, byteread;
+ char buf[6] = {0};
+ char cmd[] = {0xAA, 0xF0, 0x6E, 0x00, 0x08, 0xFE, 0x1A, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xC3, 0x01, 0xA5, 0x02, 0x00, 0x00, 0x00, 0x00, 0x5A, 0x45, 0x00,
+ 0x80, 0x04, 0x80, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x96, 0x00, 0x6F, 0x3C, 0xDE, 0xDF, 0x8B, 0x6D, 0x04, 0x04, 0x00, 0xD2, 0x00,
+ 0xB7, 0x00, 0x28, 0x00, 0x5D, 0x4A, 0x1E, 0x00, 0xC6, 0x37, 0x28, 0x00, 0x5D,
+ 0x4A, 0x8E, 0x65, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0xFF, 0x00, 0x80, 0x00,
+ 0x47, 0x00, 0x64, 0x00, 0x50, 0x00, 0xD8, 0x00, 0x50, 0x00, 0xBB, 0x00, 0x03,
+ 0x00, 0x3C, 0x00, 0x6F, 0x00, 0x89, 0x00, 0x88, 0x00, 0x02, 0x00, 0xFB, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x7A, 0x16, 0xAA, 0x0F};
+ char ack[] = {0xaa, 0xf0, 0x0e, 0x00, 0x31, 0xfe};
+
+ bytewrite = write(fd, cmd, sizeof(cmd));
+ if (bytewrite == sizeof(cmd)) {
+ usleep(500*000);
+ byteread = read(fd, buf, sizeof(buf));
+ LOGD("ack:%02x %02x %02x %02x %02x %02x\n",
+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+ if ((byteread == sizeof(ack)) && (memcmp(buf, ack, sizeof(ack)) == 0)) {
+ LOGD("it's 3332\n");
+ return 0; /*0 means 3332, 1 means other GPS chips*/
+ }
+ return 1;
+ } else {
+ LOGE("write error, write API return is %zu, error message is %s\n", bytewrite, strerror(errno));
+ return 1;
+ }
+}
+
+int hand_shake() {
+#if MTK_GPS_NVRAM
+ int fd = -1;
+#endif
+ int ret = -1;
+ int nv;
+ nv = read_NVRAM();
+
+ if (nv == 1)
+ return 1;
+ else if (nv == -1)
+ return -1;
+ else
+ LOGD("read NVRAM ok\n");
+#if MTK_GPS_NVRAM
+ fd = open(stGPSReadback.dsp_dev, O_RDWR | O_NOCTTY);
+ if (fd == -1) {
+ LOGE("GPS_Open: Unable to open - %s, %s\n", stGPSReadback.dsp_dev, strerror(errno));
+ return -1;
+ }
+ init_3332_interface(fd); /*set UART parameter*/
+
+ ret = hw_test_3332(fd); /*is 3332? 0:yes 1:no*/
+ close(fd);
+#endif
+ return ret;
+}
+
+int confirm_if_3332() {
+ int ret;
+ // power_on_3332();
+ ret = hand_shake();
+ // power_off_3332();
+ return ret;
+}
+#if ANDROID_MNLD_PROP_SUPPORT
+extern char chip_id[PROPERTY_VALUE_MAX];
+#else
+extern char chip_id[100];
+#endif
+void chip_detector() {
+#ifdef __ANDROID_OS__
+ int res;
+ int get_time = 20;
+ while ((get_time-- != 0) && ((res = property_get("persist.vendor.connsys.chipid", chip_id, NULL)) < 6)) {
+ LOGE("get chip id fail, retry");
+ usleep(200000);
+ }
+
+ // chip id is like "0xXXXX"
+ if (res < 6) {
+ LOGE("combo_chip_id error: %s\n", chip_id);
+ return;
+ }
+#else
+ memset(chip_id, 0, sizeof(chip_id));
+ strncpy(chip_id, "0x6880", sizeof(chip_id)-1);
+#endif
+ LOGD("combo_chip_id is %s\n", chip_id);
+
+ return;
+}
+
+int buff_get_int(const char* buff, int* offset) {
+ int ret = *((int*)&buff[*offset]);
+ *offset += 4;
+ return ret;
+}
+
+int buff_get_string(char* str, const char* buff, int* offset) {
+ int len = *((int*)&buff[*offset]);
+ *offset += 4;
+
+ memcpy(str, &buff[*offset], len);
+ *offset += len;
+ return len;
+}
+
+void buff_put_int(int input, char* buff, int* offset) {
+ *((int*)&buff[*offset]) = input;
+ *offset += 4;
+}
+
+void buff_put_string(const char* str, char* buff, int* offset) {
+ int len = strlen(str) + 1;
+
+ *((int*)&buff[*offset]) = len;
+ *offset += 4;
+
+ memcpy(&buff[*offset], str, len);
+ *offset += len;
+}
+
+void buff_put_struct(const void* input, int size, char* buff, int* offset) {
+ memcpy(&buff[*offset], input, size);
+ *offset += size;
+}
+
+void buff_get_struct(char* output, int size, const char* buff, int* offset) {
+ memcpy(output, &buff[*offset], size);
+ *offset += size;
+}
+
+int buff_get_binary(void* output, const char* buff, int* offset) {
+ int len = *((int*)&buff[*offset]);
+ *offset += 4;
+
+ memcpy(output, &buff[*offset], len);
+ *offset += len;
+ return len;
+}
+
+int add_chksum(char *pBuf) {
+ int i;
+ unsigned char chksum;
+ char ch;
+ unsigned short Size;
+
+ Size = strlen(pBuf);
+
+ if (Size == 0) {
+ return 0;
+ }
+
+ // will add six characters: '*', CHK1, CHK2, <CR>, <LF>, <ZERO>
+ if (Size > (PMTK_MAX_PKT_LENGTH - 6)) {
+ Size = PMTK_MAX_PKT_LENGTH - 6;
+ }
+
+ chksum = 0;
+ for (i = 1; i < Size; i++) {
+ if (pBuf[i] != '*') {
+ chksum ^= pBuf[i];
+ } else {
+ Size = i;
+ break;
+ }
+ }
+
+ // Add symbol '*'
+ pBuf[Size] = '*';
+
+ // Add CHK1
+ ch = (chksum & 0xF0) >> 4;
+ if (ch >= 10) {
+ ch = 'A' + ch - 10;
+ } else {
+ ch = '0' + ch;
+ }
+ pBuf[Size + 1] = ch;
+
+ // Add CHK2
+ ch = chksum & 0x0F;
+ if (ch >= 10) {
+ ch = 'A' + ch - 10;
+ } else {
+ ch = '0' + ch;
+ }
+ pBuf[Size + 2] = ch;
+
+ pBuf[Size + 3] = '\r';
+ pBuf[Size + 4] = '\n';
+ pBuf[Size + 5] = '\0';
+
+ return 1;
+}
+
+
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mpe.c b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mpe.c
new file mode 100644
index 0000000..ff1b346
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mpe.c
@@ -0,0 +1,264 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#include <pthread.h>
+#include <errno.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/epoll.h>
+
+#include "mtk_lbs_utility.h"
+#include "mnld.h"
+#include "mtk_gps.h"
+#include "mpe.h"
+#include "gps_dbg_log.h"
+#include "mpe_common.h"
+#include "data_coder.h"
+#include "gps_controller.h"
+
+#include "mtk_mnld_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "mpe"
+
+MPECallBack gMpeCallBackFunc = NULL;
+static int g_fd_mpe;
+extern unsigned char gMpeThreadExist;
+
+int mnl2mpe_set_log_path(const char* path, int status_flag, int mode_flag) {
+ char mnl2mpe_buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+ int offset = 0;
+
+ put_int(mnl2mpe_buff, &offset, CMD_SEND_FROM_MNLD);
+ put_int(mnl2mpe_buff, &offset, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN + 2*sizeof(INT32));
+ put_int(mnl2mpe_buff, &offset, status_flag);
+ put_int(mnl2mpe_buff, &offset, mode_flag);
+ put_binary(mnl2mpe_buff, &offset, (const char*)path, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+
+ if (!(mpe_sys_get_mpe_conf_flag() & MPE_CONF_MPE_ENABLE)) {
+ LOGD("MPE not enable\n");
+ return MTK_GPS_ERROR;
+ }
+ if(safe_sendto(MNLD_MPE_SOCKET, mnl2mpe_buff, MNL_MPE_MAX_BUFF_SIZE) == -1) {
+ LOGE("safe_sendto fail:[%s]%d", strerror(errno), errno);
+ return MTK_GPS_ERROR;
+ }
+ return 0;
+}
+
+int mpe2mnl_hdlr(char *buff) {
+ int type, length;
+ int offset = 0;
+
+ type = get_int(buff, &offset, MNL_MPE_MAX_BUFF_SIZE);
+ length = get_int(buff, &offset, MNL_MPE_MAX_BUFF_SIZE);
+
+ LOGD("type=%d length=%d\n", type, length);
+
+ switch (type) {
+ case CMD_MPED_REBOOT_DONE: {
+ mtklogger_mped_reboot_message_update();
+ break;
+ }
+ case CMD_START_MPE_RES:
+ case CMD_STOP_MPE_RES:
+ case CMD_SEND_SENSOR_RAW_RES:
+ case CMD_SEND_SENSOR_CALIBRATION_RES:
+ case CMD_SEND_SENSOR_FUSION_RES:
+ case CMD_SEND_GPS_AIDING_RES:
+ case CMD_SEND_ADR_STATUS_RES:
+ case CMD_SEND_GPS_TIME_REQ: {
+ if (mnld_is_gps_started_done()) {
+ mtk_gps_mnl_get_sensor_info((UINT8 *)buff, length + sizeof(MPE_MSG));
+ }
+ break;
+ }
+ default: {
+ LOGE("unknown cmd=%d\n", type);
+ break;
+ }
+ }
+ return 0;
+}
+
+int mtk_gps_mnl_trigger_mpe(void) {
+ UINT16 mpe_len;
+ char mnl2mpe_buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+ int ret = MTK_GPS_ERROR;
+
+ mpe_len = mtk_gps_set_mpe_info((UINT8 *)mnl2mpe_buff);
+ LOGD_ENG("mpemsg len=%d\n", mpe_len);
+
+ if (mpe_len > 0) {
+ if (!(mpe_sys_get_mpe_conf_flag() & MPE_CONF_MPE_ENABLE)) {
+ LOGD("MPE not enable\n");
+ return MTK_GPS_ERROR;
+ }
+ if (safe_sendto(MNLD_MPE_SOCKET, mnl2mpe_buff, MNL_MPE_MAX_BUFF_SIZE) == -1) {
+ LOGE("safe_sendto fail:[%s]%d", strerror(errno), errno);
+ return MTK_GPS_ERROR;
+ }
+ ret = MTK_GPS_SUCCESS;
+ }
+ return ret;
+}
+#if 0
+static void mpe_thread_timeout() {
+ if (mnld_timeout_ne_enabled() == false) {
+ LOGE("mpe_thread_timeout() dump and exit.");
+ gps_dbg_log_exit_flush(0);
+ mnld_block_exit();
+ } else {
+ LOGE("mpe_thread_timeout() crash here for debugging");
+ CRASH_TO_DEBUG();
+ }
+}
+#endif
+int mnl_mpe_thread_init() {
+ int ret;
+ LOGD("mpe enabled");
+
+ gMpeCallBackFunc = mtk_gps_mnl_trigger_mpe;
+ ret = mtk_gps_mnl_mpe_callback_reg((MPECallBack *)gMpeCallBackFunc);
+ LOGD("register mpe cb %d,gMpeCallBackFunc= %p,mtk_gps_mnl_trigger_mpe=%p\n",
+ ret, gMpeCallBackFunc, mtk_gps_mnl_trigger_mpe);
+ return 0;
+}
+
+unsigned char mpe_sys_sensor_threads_create(void)
+{
+ pthread_t sensor_thread_handle;
+
+ if (gMpeThreadExist == 0) {
+ gMpeThreadExist = 1;
+ if(pthread_create(&sensor_thread_handle, NULL, mpe_sensor_thread, NULL)) {
+ gMpeThreadExist = 0;
+ LOGD("MPE sensor thread init failed - pthread_create");
+ return FALSE;
+ }
+ } else {
+ LOGD("MPE sensor thread init failed - Thread exist");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void* mpe_main_thread(void *arg) {
+ #define MAX_EPOLL_EVENT 50
+ struct epoll_event events[MAX_EPOLL_EVENT];
+ UNUSED(arg);
+ pthread_detach(pthread_self());
+
+ mnl2mpe_hdlr_init();
+ int epfd = epoll_create(MAX_EPOLL_EVENT);
+ if (epfd == -1) {
+ LOGE("epoll_create failure reason=[%s]%d\n",
+ strerror(errno), errno);
+ return 0;
+ }
+
+ if (epoll_add_fd(epfd, g_fd_mpe) == -1) {
+ LOGE("epoll_add_fd() failed for g_fd_epo failed");
+ return 0;
+ }
+ while (1) {
+ int i;
+ int n;
+ LOGD("wait");
+ memset(events, 0, sizeof(events));
+ n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+ if (n == -1) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ LOGE("epoll_wait failure reason=[%s]%d",
+ strerror(errno), errno);
+ return 0;
+ }
+ }
+ mnld_wake_lock_take();
+ for (i = 0; i < n; i++) {
+ if (events[i].data.fd == g_fd_mpe) {
+ if (events[i].events & EPOLLIN) {
+ mnl2mpe_hdlr(g_fd_mpe);
+ }
+ } else {
+ LOGE("unknown fd=%d",
+ events[i].data.fd);
+ }
+ }
+ mnld_wake_lock_give();
+ }
+
+ LOGE("exit");
+ pthread_exit(NULL);
+ return 0;
+}
+
+int mpe_function_init(void) {
+ pthread_t calib_thread_handle;
+ pthread_t main_thread_handle;
+
+ mpe_sys_read_mpe_conf_flag();
+ if (!(mpe_sys_get_mpe_conf_flag() & MPE_CONF_MPE_ENABLE)) {
+ LOGD("MPE not enable\n");
+ return MTK_GPS_SUCCESS;
+ }
+
+ if (mpe_sys_get_mpe_conf_flag() & MPE_CONF_AUTO_CALIB) {
+ if(pthread_create(&calib_thread_handle, NULL, mpe_calib_thread, NULL)) {
+ LOGE("MPE calib thread init failed");
+ }
+ }
+
+ g_fd_mpe = socket_bind_udp(MNLD_MPE_SOCKET);
+
+ if(pthread_create(&main_thread_handle, NULL, mpe_main_thread, NULL)) {
+ LOGE("MPE main thread init failed");
+ }
+
+ return MTK_GPS_SUCCESS;
+}
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mtknav.c b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mtknav.c
new file mode 100644
index 0000000..a335bf8
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/mtknav.c
@@ -0,0 +1,443 @@
+#include <errno.h> /* Error number definitions */
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "mtk_gps_agps.h"
+#include "agps_agent.h"
+#include "data_coder.h"
+#include "mnl_common.h"
+#include "mnld.h"
+#include "mtk_lbs_utility.h"
+#include "epo.h"
+#include "mtknav.h"
+#include "curl.h"
+#include "easy.h"
+#include "mtk_gps.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "mtknav"
+
+static char mtknav_file_name[GPS_EPO_FILE_LEN] = {0};
+static char mtknav_md5_file_name[GPS_EPO_FILE_LEN] = {0};
+
+bool mtknav_update_flag = false;
+int mtknav_res = EPO_DOWNLOAD_RESULT_FAIL;
+
+static int mtknav_file_update_impl();
+typedef enum {
+ MAIN2MTKNAV_EVENT_START = 0,
+} main2mtknav_event;
+
+typedef struct mtknav_dl_state {
+ bool MD5_DL_Today;
+ bool DAT_DL_Today;
+ int last_DL_Date;
+ unsigned int retry_time;
+}MTKNAV_STATE_T;
+
+static int g_fd_mtknav;
+static int mtknav_downloading = 0;
+static MTKNAV_STATE_T dl_state = {
+ .MD5_DL_Today = false,
+ .DAT_DL_Today = false,
+ .last_DL_Date = -1,
+ .retry_time = 0,
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+// static functions
+
+static int counter = 1;
+static void getMtkNavUrl(const char* filename, char* url) {
+ char count_str[15] = {0};
+
+ if (counter <= 1) {
+ strncat(url, EPO_URL_HOME_G, GPS_EPO_URL_LEN - strlen(url));
+ } else {
+ strncat(url, EPO_URL_HOME_C, GPS_EPO_URL_LEN -strlen(url));
+ }
+
+ strncat(url, filename, GPS_EPO_URL_LEN - strlen(url));
+ strncat(url, "?retryCount=", GPS_EPO_URL_LEN - strlen(url));
+ MNLD_SPRINTF(count_str, "%d", counter-1);
+ strncat(url, count_str, GPS_EPO_URL_LEN - strlen(url));
+ LOGD("url = %s\n", url);
+}
+
+static void check_mtknav_file_exist(void) {
+ if ( (access(MTKNAV_MD5_FILE, F_OK) == -1) ||
+ (access(MTKNAV_DAT_FILE, F_OK) == -1) ) {
+ LOGD_ENG("mtknav file does not exist, need download\n");
+ dl_state.MD5_DL_Today = false;
+ dl_state.DAT_DL_Today = false;
+ dl_state.retry_time = 0;
+ }
+}
+
+static CURLcode curl_easy_download_mtknav_DAT(void) {
+ int res_val;
+ CURLcode res;
+ char url[GPS_EPO_URL_LEN]={0};
+
+ LOGD("curl_easy_download_mtknav_DAT");
+ getMtkNavUrl(mtknav_file_name, url);
+ res = curl_easy_download(url, MTKNAV_DAT_FILE_HAL);
+
+ LOGD("mtknav DAT file curl_easy_download res = %d\n", res);
+ if (res == 0) {
+ counter = 1;
+ res_val = chmod(MTKNAV_DAT_FILE_HAL, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+ } else {
+ counter++;
+ }
+ return res;
+}
+
+static CURLcode curl_easy_download_mtknav_MD5(void) {
+ int res_val;
+ CURLcode res;
+ char url[GPS_EPO_URL_LEN]={0};
+
+ LOGD_ENG("curl_easy_download_mtknav_MD5");
+ getMtkNavUrl(mtknav_md5_file_name, url);
+ res = curl_easy_download(url, MTKNAV_MD5_FILE_HAL);
+
+ LOGD("mtknav MD5 file curl_easy_download res = %d\n", res);
+ if (res == 0) {
+ counter = 1;
+ res_val = chmod(MTKNAV_MD5_FILE_HAL, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ LOGD("chmod MD5 res_val = %d, %s\n", res_val, strerror(errno));
+ } else {
+ counter++;
+ }
+ return res;
+}
+
+static int mtknav_MD5_file_check(void) {
+ int ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+ FILE *fp_old = NULL;
+ FILE *fp_new = NULL;
+ int new_file_size = 0;
+ char old_md5[40]; // length = 40 because current our md5 file size is 37bytes, but only first 32 bytes are useful.
+ char new_md5[40];
+
+ memset(old_md5, 0x00, sizeof(old_md5));
+ memset(new_md5, 0x00, sizeof(new_md5));
+
+ if (is_file_exist(MTKNAV_MD5_FILE_HAL) == 0) {
+ LOGE("new mtknav MD5 file doesn't exist, download failed!");
+ return EPO_MD5_DOWNLOAD_RESULT_FAIL;
+ }
+
+ if (is_file_exist(MTKNAV_MD5_FILE) == 0) {
+ LOGW("old mtknav MD5 file doesn't exist");
+ new_file_size = get_file_size(MTKNAV_MD5_FILE_HAL);
+ if (new_file_size < 32) {
+ ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+ if (delete_file(MTKNAV_MD5_FILE_HAL) == -1) {
+ LOGW("delete %s file error",MTKNAV_MD5_FILE_HAL);
+ }
+ } else {
+ ret = EPO_MD5_FILE_UPDATED;
+ if (rename(MTKNAV_MD5_FILE_HAL, MTKNAV_MD5_FILE) == -1) { //update MTKNAV.MD5 on local
+ LOGW("MD5 rename error");
+ }
+ }
+ } else {
+ new_file_size = get_file_size(MTKNAV_MD5_FILE_HAL);
+ if (new_file_size < 32) {
+ ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+ if (delete_file(MTKNAV_MD5_FILE_HAL) == -1) {
+ LOGW("delete %s file error",MTKNAV_MD5_FILE_HAL);
+ }
+ } else {
+ fp_old = fopen(MTKNAV_MD5_FILE, "r");
+ if (fp_old != NULL) {
+ if (fread(old_md5, 32, 1, fp_old) != 32) { //only first 32 bytes are useful.
+ LOGW("read old MD5 file error");
+ }
+ fclose(fp_old);
+ }
+ fp_new = fopen(MTKNAV_MD5_FILE_HAL, "r");
+ if (fp_new != NULL) {
+ if (fread(new_md5, 32, 1, fp_new) != 32) {
+ LOGW("read new MD5 file error");
+ }
+ fclose(fp_new);
+ }
+ if (strncmp(old_md5,new_md5,32) != 0) {
+ if (rename(MTKNAV_MD5_FILE_HAL, MTKNAV_MD5_FILE) == -1) { //update MTKNAV.MD5 on local only when file content update
+ LOGW("MD5 rename error");
+ }
+ ret = EPO_MD5_FILE_UPDATED;
+ } else {
+ ret = EPO_MD5_FILE_NO_UPDATE;
+ if (delete_file(MTKNAV_MD5_FILE_HAL) == -1) {
+ LOGW("delete %s file error",MTKNAV_MD5_FILE_HAL);
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+static int is_mtknav_file_valid(void) {
+ int fd = 0;
+ int ret = EPO_DOWNLOAD_RESULT_FAIL;
+
+ fd = open(MTKNAV_DAT_FILE_HAL, O_RDONLY);
+ if (fd < 0) {
+ LOGE("Open mtknav fail(%s), return\n",strerror(errno));
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ } else {
+ ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+ close(fd);
+ }
+ return ret;
+}
+
+static int mtknav_DAT_download_process(void) {
+ int ret = EPO_DOWNLOAD_RESULT_FAIL;
+ LOGD("mtknav_DAT_download_process begin");
+
+ MNLD_STRNCPY(mtknav_file_name, "MTKNAV.DAT", sizeof(mtknav_file_name));
+ if (curl_easy_download_mtknav_DAT() == CURLE_OK) {
+ LOGD("download mtknav DAT file success,CURLE_OK");
+ if (is_mtknav_file_valid() == EPO_DOWNLOAD_RESULT_SUCCESS) {
+ LOGD("Check mtknav DAT file ok");
+ ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+ } else {
+ dl_state.retry_time++;
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ LOGW("check mtknav DAT file error, retry:%d",dl_state.retry_time);
+ }
+ } else {
+ LOGW("download mtknav MD5 file failed");
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ }
+ return ret;
+}
+
+static int mtknav_MD5_download_process(void) {
+ LOGD_ENG("mtknav_MD5_download_process begin");
+ int ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+ MNLD_STRNCPY(mtknav_md5_file_name, "MTKNAV.MD5", sizeof(mtknav_md5_file_name));
+ if (curl_easy_download_mtknav_MD5() == CURLE_OK) {
+ LOGD("mtknav MD5 download success, start to check");
+ ret = mtknav_MD5_file_check();
+ } else {
+ LOGD_ENG("download mtknav MD5 file failed");
+ ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+ }
+ return ret;
+}
+
+static int mtknav_file_update_impl() {
+ int ret_MD5 = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+ int ret_DAT = EPO_DOWNLOAD_RESULT_FAIL;
+
+ ret_MD5 = mtknav_MD5_download_process();
+ if (ret_MD5 != EPO_MD5_DOWNLOAD_RESULT_FAIL) {
+ LOGD("MD5 download success, no need download any more today");
+ dl_state.MD5_DL_Today = true;
+ }
+
+ if (ret_MD5 == EPO_MD5_FILE_NO_UPDATE) {
+ dl_state.DAT_DL_Today = true; // new MD5 match old MD5, no need download DAT any more
+ return EPO_DOWNLOAD_RESULT_NO_UPDATE;
+ }
+
+ if (ret_MD5 == EPO_MD5_FILE_UPDATED) {
+ ret_DAT = mtknav_DAT_download_process();
+ }
+
+ if (ret_DAT == EPO_DOWNLOAD_RESULT_SUCCESS) {
+ LOGD("DAT download success, no need download any more today");
+ dl_state.DAT_DL_Today = true;
+ }
+ return ret_DAT;
+}
+
+void mtknav_update_mtknav_file(int mtknav_valid) {
+ int xdownload_status = MTK_MTKNAV_RSP_DOWNLOAD_FAIL;
+
+ if (mtknav_valid == EPO_DOWNLOAD_RESULT_SUCCESS) {
+ if (mtk_agps_agent_mtknav_file_update() == MTK_GPS_ERROR) {
+ xdownload_status = MTK_MTKNAV_RSP_UPDATE_FAIL;
+ } else {
+ LOGD("Update mtknav file successfully");
+ xdownload_status = MTK_MTKNAV_RSP_UPDATE_SUCCESS;
+ unlink(MTKNAV_DAT_FILE_HAL);
+ }
+ } else if (mtknav_valid == EPO_DOWNLOAD_RESULT_NO_UPDATE) {
+ xdownload_status = MTK_MTKNAV_RSP_NO_UPDATE;
+ } else if (mtknav_valid == EPO_DOWNLOAD_RESULT_RETRY_TOO_MUCH) {
+ xdownload_status = MTK_MTKNAV_RSP_DOWNLOAD_FAIL;
+ } else {
+ xdownload_status = MTK_MTKNAV_RSP_DOWNLOAD_FAIL;
+ }
+
+ LOGD("xdownload_status = 0x%x\n", xdownload_status);
+ if (MTK_GPS_ERROR == (mtk_agps_set_param (MTK_PARAM_MTKNAV_DOWNLOAD_RESPONSE,
+ &xdownload_status, MTK_MOD_DISPATCHER, MTK_MOD_AGENT))) {
+ LOGE("GPS MTKNAV update fail\n");
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////
+// MAIN -> MTKNAV Download (handlers)
+static int mnld_mtknav_download() {
+ int ret;
+ struct tm tm;
+ time_t now = time(NULL);
+ gmtime_r(&now, &tm);
+
+ check_mtknav_file_exist();
+
+ LOGD_ENG("dl_state_date:%d, system_date:%d, MD5_flag:%d, DAT_flag:%d, retry:%d",
+ dl_state.last_DL_Date,tm.tm_mday, dl_state.MD5_DL_Today, dl_state.DAT_DL_Today,dl_state.retry_time);
+
+ if (dl_state.last_DL_Date != tm.tm_mday) {
+ dl_state.MD5_DL_Today = false;
+ dl_state.DAT_DL_Today = false;
+ dl_state.retry_time = 0;
+ dl_state.last_DL_Date = tm.tm_mday;
+ LOGD_ENG("First mtknav request today, day is %d", dl_state.last_DL_Date);
+ }
+
+ if ((dl_state.DAT_DL_Today == false) && (dl_state.retry_time <= MTKNAV_DL_RETRY_TIME)) {
+ mtknav_downloading = 1;
+ ret = mtknav_file_update_impl();
+ mtknav_downloading = 0;
+ } else if (dl_state.DAT_DL_Today == true) {
+ LOGW("mtknav has been downloaded today");
+ ret = EPO_DOWNLOAD_RESULT_NO_UPDATE;
+ } else {
+ LOGW("mtknav has been retry too much, retry time=%d",dl_state.retry_time);
+ ret = EPO_DOWNLOAD_RESULT_RETRY_TOO_MUCH;
+ }
+ mtknav_res = ret;
+ if(mnld_mtknav_download_done(ret) == -1){
+ LOGD_ENG("mtknav has not download done");
+ }
+ return ret;
+}
+
+static int mtknav_event_hdlr(int fd) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ main2mtknav_event cmd;
+ int read_len;
+
+ read_len = safe_recvfrom(fd, buff, sizeof(buff));
+ if (read_len <= 0) {
+ LOGE("mtknav_event_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+ return -1;
+ }
+
+ cmd = get_int(buff, &offset, sizeof(buff));
+ switch (cmd) {
+ case MAIN2MTKNAV_EVENT_START: {
+ LOGD_ENG("mnld_mtknav_download() before");
+ mnld_mtknav_download();
+ LOGD_ENG("mnld_mtknav_download() after");
+ break;
+ }
+ default: {
+ LOGE("mtknav_event_hdlr() unknown cmd=%d", cmd);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static void* mtknav_downloader_thread(void *arg) {
+ #define MAX_EPOLL_EVENT 50
+ //timer_t hdlr_timer = init_timer(qepo_downloader_thread_timeout);
+ struct epoll_event events[MAX_EPOLL_EVENT];
+ UNUSED(arg);
+
+ int epfd = epoll_create(MAX_EPOLL_EVENT);
+ if (epfd == -1) {
+ LOGE("mtknav_downloader_thread() epoll_create failure reason=[%s]%d",
+ strerror(errno), errno);
+ return 0;
+ }
+
+ if (epoll_add_fd(epfd, g_fd_mtknav) == -1) {
+ LOGE("mtknav_downloader_thread() epoll_add_fd() failed for g_fd_mtknav failed");
+ return 0;
+ }
+
+ while (1) {
+ int i;
+ int n;
+ LOGD_ENG("mtknav_downloader_thread wait");
+ memset(events, 0, sizeof(events));
+ n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+ if (n == -1) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ LOGE("mtknav_downloader_thread() epoll_wait failure reason=[%s]%d",
+ strerror(errno), errno);
+ return 0;
+ }
+ }
+ mnld_wake_lock_take();
+ //start_timer(hdlr_timer, MNLD_QEPO_HANDLER_TIMEOUT);
+ for (i = 0; i < n; i++) {
+ if (events[i].data.fd == g_fd_mtknav) {
+ if (events[i].events & EPOLLIN) {
+ mtknav_event_hdlr(g_fd_mtknav);
+ }
+ } else {
+ LOGE("mtknav_downloader_thread() unknown fd=%d",
+ events[i].data.fd);
+ }
+ }
+ //stop_timer(hdlr_timer);
+ mnld_wake_lock_give();
+ }
+
+ LOGE("mtknav_downloader_thread() exit");
+ return 0;
+}
+
+int mtknav_downloader_start() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ if (mtknav_downloading == 1) {
+ LOGW("mtknav downloading... abort requst msg!");
+ return 0;
+ }
+ put_int(buff, &offset, MAIN2MTKNAV_EVENT_START);
+ return safe_sendto(MNLD_MTKNAV_DOWNLOAD_SOCKET, buff, offset);
+}
+
+int mtknav_downloader_init() {
+ pthread_t pthread_mtknav;
+
+ g_fd_mtknav = socket_bind_udp(MNLD_MTKNAV_DOWNLOAD_SOCKET);
+ if (g_fd_mtknav < 0) {
+ LOGE("socket_bind_udp(%s) failed",MNLD_MTKNAV_DOWNLOAD_SOCKET);
+ return -1;
+ }
+
+ pthread_create(&pthread_mtknav, NULL, mtknav_downloader_thread, NULL);
+ return 0;
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/nmea_parser.c b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/nmea_parser.c
new file mode 100755
index 0000000..c389e1a
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/nmea_parser.c
@@ -0,0 +1,1144 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#define _NMEA_PARSER_C_
+/*******************************************************************************
+* Dependency
+*******************************************************************************/
+#include <errno.h>
+#include <stdio.h> /* Standard input/output definitions */
+#include <string.h> /* String function definitions */
+#include <stdlib.h>
+#include <sys/time.h>
+#include <math.h>
+#include "mnld.h"
+#include "mtk_gps.h"
+#include "mnl2hal_interface.h"
+#include "nmea_parser.h"
+#include "mtk_lbs_utility.h"
+#include "mnl_at_interface.h"
+
+#include "mtk_mnld_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "NMEA_PARSER"
+
+/*******************************************************************************
+* structure & enumeration
+*******************************************************************************/
+static int gps_nmea_end_tag = 0;
+static NmeaCash nmea_cash[550];
+static bool sv_status_changed = false;
+int sv_inuse_num = 0;
+
+extern int prn[32];
+extern int snr[32];
+extern int MNL_AT_TEST_FLAG;
+extern int MNL_AT_SIGNAL_MODE;
+extern int MNL_AT_CW_MODE;
+extern int MNL_AT_FM_MODE;
+extern int g_agc_level;
+
+#define CARRIER_FREQ_GPS_L1 (1575.42*1000000)
+#define CARRIER_FREQ_GPS_L2 (1227.60*1000000)
+#define CARRIER_FREQ_GPS_L5 (1176.45*1000000)
+#define CARRIER_FREQ_GLO_L1 (1602*1000000)
+#define CARRIER_FREQ_GAL_E1 (1575.42*1000000)
+#define CARRIER_FREQ_GAL_E5A (1176.45*1000000)
+#define CARRIER_FREQ_BD_B1 (1561.098*1000000)
+#define CARRIER_FREQ_BD_B2 (1207.14*1000000)
+#define CARRIER_FREQ_BD_B3 (1268.52*1000000)
+#define CARRIER_FREQ_IRN_L5 (1176.45*1000000)
+
+#define POS_AGC_LEVEL_IN_PMTKAGC 9
+
+#define MNLD_BDS_OFFSET 200
+#define MNLD_GALILEO_OFFSET 400
+#define MNLD_IRNSS_OFFSET 500
+#define MNLD_QZSS_OFFSET 192
+
+extern MNL_CONFIG_T mnld_cfg;
+/******************************************************************************
+ * Functions
+******************************************************************************/
+static void nmea_reader_update_utc_diff(NmeaReader* const r) {
+ time_t now = time(NULL);
+ struct tm tm_local;
+ struct tm tm_utc;
+ unsigned long time_local, time_utc;
+
+ if ((time_t)-1==now) {
+ LOGE("time() error: %d %s\n", errno, strerror(errno));
+ }
+ if (!gmtime_r(&now, &tm_utc)) {
+ LOGE("gmtime_r error: %d %s\n", errno, strerror(errno));
+ }
+ if (!localtime_r(&now, &tm_local)) {
+ LOGE("localtime_r error: %d %s\n", errno, strerror(errno));
+ }
+ tm_local.tm_isdst = -1;
+ tm_utc.tm_isdst = -1;
+ if (!(time_local = mktime(&tm_local))) {
+ LOGE("mktime error: %d %s\n", errno, strerror(errno));
+ }
+ if (!(time_utc = mktime(&tm_utc))) {
+ LOGE("mktime error: %d %s\n", errno, strerror(errno));
+ }
+
+ r->utc_diff = time_utc - time_local;
+}
+
+static void nmea_reader_init(NmeaReader* const r) {
+ memset( r, 0, sizeof(*r) );
+
+ r->pos = 0;
+ r->overflow = 0;
+ r->utc_year = -1;
+ r->utc_mon = -1;
+ r->utc_day = -1;
+ r->utc_diff = 0;
+ r->sv_count = 0;
+ r->fix_mode = 0; /*no fix*/
+ r->cb_status_changed = 0;
+ memset((void*)&r->sv_status, 0x00, sizeof(r->sv_status));
+ memset((void*)r->in, 0x00, sizeof(r->in));
+
+ nmea_reader_update_utc_diff(r);
+}
+
+static int nmea_tokenizer_init(NmeaTokenizer* t, const char* p, const char* end) {
+ int count = 0;
+
+ // the initial '$' is optional
+ if (p < end && p[0] == '$')
+ p += 1;
+
+ // remove trailing newline
+ if (end > p && end[-1] == '\n') {
+ end -= 1;
+ if (end > p && end[-1] == '\r')
+ end -= 1;
+ }
+
+ // get rid of checksum at the end of the sentecne
+ if (end >= p+3 && end[-3] == '*') {
+ end -= 3;
+ }
+
+ while (p < end) {
+ const char* q = p;
+
+ q = memchr(p, ',', end-p);
+ if (q == NULL)
+ q = end;
+
+ if (q >= p) {
+ if (count < MAX_NMEA_TOKENS) {
+ t->tokens[count].p = p;
+ t->tokens[count].end = q;
+ count += 1;
+ }
+ }
+ if (q < end)
+ q += 1;
+
+ p = q;
+ }
+
+ t->count = count;
+ return count;
+}
+
+static Token nmea_tokenizer_get(NmeaTokenizer* t, int index) {
+ Token tok;
+ static const char* dummy = "";
+
+ if (index < 0 || index >= t->count) {
+ tok.p = tok.end = dummy;
+ } else
+ tok = t->tokens[index];
+
+ return tok;
+}
+
+static double str2float(const char* p, const char* end) {
+ int len = end - p;
+ char temp[16];
+
+ if (len >= (int)sizeof(temp))
+ return 0.;
+
+ memcpy(temp, p, len);
+ temp[len] = 0;
+ return strtod( temp, NULL );
+}
+
+static bool nmea_reader_sv_status_changed(void) {
+ return sv_status_changed;
+}
+
+void nmea_reader_sv_update_set(bool sv_update) {
+ sv_status_changed = sv_update;
+}
+
+static int nmea_reader_update_altitude(NmeaReader* const r,
+ Token altitude,
+ Token units) {
+ Token tok = altitude;
+ UNUSED(units);
+
+ if (tok.p >= tok.end)
+ return -1;
+
+ r->fix.flags |= MTK_GPS_LOCATION_HAS_ALT;
+ r->fix.alt = str2float(tok.p, tok.end);
+ return 0;
+}
+
+static int nmea_reader_update_dop(NmeaReader* const r,
+ Token pdop,
+ Token hdop,
+ Token vdop) {
+ Token ptok = pdop;
+ Token htok = hdop;
+ Token vtok = vdop;
+
+ if (ptok.p >= ptok.end || htok.p >= htok.end ||vtok.p >= vtok.end) {
+ LOGE("tok fail!!!ptok.p:%p, ptok.end:%p, htok.p:%p, htok.end:%p, vtok.p:%p, vtok.end:%p",
+ ptok.p, ptok.end, htok.p, htok.end, vtok.p, vtok.end);
+ return -1;
+ }
+ r->fix.flags |= MTK_GPS_LOCATION_HAS_PDOP;
+ r->fix.pdop = str2float(ptok.p, ptok.end);
+ r->fix.flags |= MTK_GPS_LOCATION_HAS_HDOP;
+ r->fix.hdop = str2float(htok.p, htok.end);
+ r->fix.flags |= MTK_GPS_LOCATION_HAS_VDOP;
+ r->fix.vdop = str2float(vtok.p, vtok.end);
+ return 0;
+}
+
+static int nmea_reader_update_time(NmeaReader* const r, Token tok) {
+ int hour, minute;
+ double seconds;
+ struct tm tm;
+ time_t fix_time;
+
+ if (tok.p + 6 > tok.end)
+ return -1;
+
+ memset((void*)&tm, 0x00, sizeof(tm));
+ if (r->utc_year < 0) {
+ // no date yet, get current one
+ time_t now = time(NULL);
+ gmtime_r(&now, &tm);
+ r->utc_year = tm.tm_year + 1900;
+ r->utc_mon = tm.tm_mon + 1;
+ r->utc_day = tm.tm_mday;
+ }
+
+ hour = str2int(tok.p, tok.p+2);
+ minute = str2int(tok.p+2, tok.p+4);
+ seconds = str2float(tok.p+4, tok.end);
+
+ tm.tm_hour = hour;
+ tm.tm_min = minute;
+ tm.tm_sec = (int) seconds;
+ tm.tm_year = r->utc_year - 1900;
+ tm.tm_mon = r->utc_mon - 1;
+ tm.tm_mday = r->utc_day;
+ tm.tm_isdst = -1;
+
+ if (mktime(&tm) == (time_t)-1)
+ LOGE("mktime error: %d %s\n", errno, strerror(errno));
+
+ // Add by ZQH to recalculate the utc_diff when the time zone is reset
+ nmea_reader_update_utc_diff(r);
+ fix_time = mktime(&tm) - r->utc_diff;
+ r->fix.timestamp = (long long)fix_time * 1000;
+ return 0;
+}
+
+static int nmea_reader_update_date(NmeaReader* const r, Token date, Token time) {
+ Token tok = date;
+ int day, mon, year;
+
+ if (tok.p + 6 != tok.end) {
+ LOGE("date not properly formatted: '%.*s'", (int)(tok.end-tok.p), tok.p);
+ return -1;
+ }
+ day = str2int(tok.p, tok.p+2);
+ mon = str2int(tok.p+2, tok.p+4);
+ year = str2int(tok.p+4, tok.p+6) + 2000;
+
+ if ((day|mon|year) < 0) {
+ LOGE("date not properly formatted: '%.*s'", (int)(tok.end-tok.p), tok.p);
+ return -1;
+ }
+
+ r->utc_year = year;
+ r->utc_mon = mon;
+ r->utc_day = day;
+
+ return nmea_reader_update_time( r, time );
+}
+
+static double convert_from_hhmm(Token tok) {
+ double val = str2float(tok.p, tok.end);
+ int degrees = (int)(floor(val) / 100);
+ double minutes = val - degrees*100.;
+ double dcoord = degrees + minutes / 60.0;
+ return dcoord;
+}
+
+static int nmea_reader_update_latlong(NmeaReader* const r,
+ Token latitude,
+ char latitudeHemi,
+ Token longitude,
+ char longitudeHemi) {
+ double lat, lon;
+ Token tok;
+
+ tok = latitude;
+ if (tok.p + 6 > tok.end) {
+ LOGE("latitude is too short: '%.*s'", (int)(tok.end-tok.p), tok.p);
+ return -1;
+ }
+ lat = convert_from_hhmm(tok);
+ if (latitudeHemi == 'S')
+ lat = -lat;
+
+ tok = longitude;
+ if (tok.p + 6 > tok.end) {
+ LOGE("longitude is too short: '%.*s'", (int)(tok.end-tok.p), tok.p);
+ return -1;
+ }
+ lon = convert_from_hhmm(tok);
+ if (longitudeHemi == 'W')
+ lon = -lon;
+
+ r->fix.flags |= MTK_GPS_LOCATION_HAS_LAT_LONG;
+ r->fix.lat = lat;
+ r->fix.lng = lon;
+ r->fix.type = MTK_LOC_TYPE_GNSS_STANDALONE;
+ return 0;
+}
+
+static int nmea_reader_update_bearing(NmeaReader* const r,
+ Token bearing) {
+ Token tok = bearing;
+
+ if (tok.p >= tok.end)
+ return -1;
+
+ r->fix.flags |= MTK_GPS_LOCATION_HAS_BEARING;
+ r->fix.bearing = str2float(tok.p, tok.end);
+ return 0;
+}
+
+static int nmea_reader_update_speed(NmeaReader* const r,
+ Token speed) {
+ Token tok = speed;
+
+ if (tok.p >= tok.end)
+ return -1;
+
+ r->fix.flags |= MTK_GPS_LOCATION_HAS_SPEED;
+
+ // Modify by ZQH to convert the speed unit from knot to m/s
+ // r->fix.speed = str2float(tok.p, tok.end);
+ r->fix.speed = str2float(tok.p, tok.end) / 1.942795467;
+ return 0;
+}
+
+// Add by LCH for accuracy
+static int nmea_reader_update_accuracy(NmeaReader* const r,
+ Token haccuracy, Token baccuracy, Token saccuracy, Token vaccuracy) {
+ Token htok = haccuracy;
+ Token btok = baccuracy;
+ Token stok = saccuracy;
+ Token vtok = vaccuracy;
+
+ if (htok.p >= htok.end || btok.p >= btok.end || stok.p >= stok.end || vtok.p >= vtok.end)
+ return -1;
+
+ r->fix.flags |= MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY;
+ r->fix.flags |= MTK_GPS_LOCATION_HAS_VERTICAL_ACCURACY;
+ r->fix.flags |= MTK_GPS_LOCATION_HAS_SPEED_ACCURACY;
+ r->fix.flags |= MTK_GPS_LOCATION_HAS_BEARING_ACCURACY;
+ r->fix.h_accuracy = str2float(htok.p, htok.end);
+ r->fix.b_accuracy = str2float(btok.p, btok.end);
+ r->fix.s_accuracy = str2float(stok.p, stok.end);
+ r->fix.v_accuracy = str2float(vtok.p, vtok.end);
+ LOGD("update accuracy: h=%f, b= %f, s=%f, v=%f", r->fix.h_accuracy, r->fix.b_accuracy,
+ r->fix.s_accuracy, r->fix.v_accuracy);
+ return 0;
+}
+
+static float nmea_signal_id_to_freq_gps(SIGNAL_ID_GP sgl_id) {
+ switch(sgl_id) {
+ case SIGNAL_ID_GP_L1_CA:
+ case SIGNAL_ID_GP_L1_P:
+ case SIGNAL_ID_GP_L1_M:
+ return CARRIER_FREQ_GPS_L1;
+ case SIGNAL_ID_GP_L2_P:
+ case SIGNAL_ID_GP_L2C_M:
+ case SIGNAL_ID_GP_L2C_L:
+ return CARRIER_FREQ_GPS_L2;
+ case SIGNAL_ID_GP_L5_I:
+ case SIGNAL_ID_GP_L5_Q:
+ return CARRIER_FREQ_GPS_L5;
+ default:
+ return CARRIER_FREQ_GPS_L1;
+ }
+}
+
+static float nmea_signal_id_to_freq_ga(SIGNAL_ID_GA sgl_id) {
+ switch(sgl_id) {
+ case SIGNAL_ID_GA_L1_A:
+ return CARRIER_FREQ_GAL_E1;
+ case SIGNAL_ID_GA_E5A:
+ return CARRIER_FREQ_GAL_E5A;
+ default:
+ return CARRIER_FREQ_GAL_E1;
+ }
+}
+
+static float nmea_signal_id_to_freq_bd(SIGNAL_ID_BD sgl_id) {
+ switch(sgl_id) {
+ case SIGNAL_ID_BD_B1_I:
+ return CARRIER_FREQ_BD_B1;
+ case SIGNAL_ID_BD_B2_b:
+ return CARRIER_FREQ_BD_B2;
+ default:
+ return CARRIER_FREQ_BD_B1;
+ }
+}
+
+static float nmea_signal_id_to_freq_qzss(SIGNAL_ID_QZ sgl_id) {
+ switch(sgl_id) {
+ case SIGNAL_ID_QZ_L1_CA:
+ case SIGNAL_ID_QZ_L1_CD:
+ case SIGNAL_ID_QZ_L1_CP:
+ return CARRIER_FREQ_GPS_L1;
+ case SIGNAL_ID_QZ_L2_CM:
+ case SIGNAL_ID_QZ_L2_CL:
+ return CARRIER_FREQ_GPS_L2;
+ case SIGNAL_ID_QZ_L5_I:
+ case SIGNAL_ID_QZ_L5_Q:
+ return CARRIER_FREQ_GPS_L5;
+ default:
+ return CARRIER_FREQ_GPS_L1;
+ }
+}
+#define EPSILON 1000.0
+bool nmea_freq_l1_signal(float freq) {
+ LOGD("nmea_freq_l1_signal:%f-%f=%f", freq, CARRIER_FREQ_GPS_L1, (freq - CARRIER_FREQ_GPS_L1));
+ if( fabs(freq - CARRIER_FREQ_GPS_L1) <= EPSILON ||
+ fabs(freq - CARRIER_FREQ_GLO_L1) <= EPSILON ||
+ fabs(freq - CARRIER_FREQ_GAL_E1) <= EPSILON ||
+ fabs(freq - CARRIER_FREQ_BD_B1) <= EPSILON
+ ) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool nmea_freq_l5_signal(float freq) {
+ LOGD("nmea_freq_l5_signal:%f", (freq - CARRIER_FREQ_GPS_L1));
+ if( fabs(freq - CARRIER_FREQ_GPS_L5) <= EPSILON ||
+ fabs(freq - CARRIER_FREQ_GAL_E5A) <= EPSILON ||
+ fabs(freq - CARRIER_FREQ_BD_B2) <= EPSILON || fabs(freq - CARRIER_FREQ_BD_B3) <= EPSILON ||
+ fabs(freq - CARRIER_FREQ_IRN_L5) <= EPSILON
+ ) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+char *nmea_sv_system_to_string(SV_SYSTEM sv_sys) {
+ char *svs_str[SV_SYSTEM_NUMBER] = {
+ "GPS L1",
+ "GPS L5",
+ "SBAS",
+ "Glonass",
+ "QZSS L1",
+ "QZSS L5",
+ "Beidou B1",
+ "Beidou B2a",
+ "Galileo E1",
+ "Galileo E5a",
+ "IRNSS"
+ };
+ return svs_str[sv_sys];
+}
+
+SV_SYSTEM nmea_constellation_to_system_index(SV_TYPE constellation, float freq) {
+ LOGD("constellation:%d, freq:%f", constellation, freq);
+ switch(constellation) {
+ case GPS_SV:
+ if(nmea_freq_l5_signal(freq)) {
+ return SV_SYSTEM_GPS_L5;
+ } else {
+ return SV_SYSTEM_GPS_L1;
+ }
+ case SBAS_SV:
+ return SV_SYSTEM_SBAS;
+ case GLONASS_SV:
+ return SV_SYSTEM_GLONASS;
+ case QZSS_SV:
+ if(nmea_freq_l5_signal(freq)) {
+ return SV_SYSTEM_QZSS_L5;
+ } else {
+ return SV_SYSTEM_QZSS_L1;
+ }
+ case BDS_SV:
+ if(nmea_freq_l5_signal(freq)) {
+ return SV_SYSTEM_BEIDOU_B2A;
+ } else {
+ return SV_SYSTEM_BEIDOU_B1;
+ }
+ case GALILEO_SV:
+ if(nmea_freq_l5_signal(freq)) {
+ return SV_SYSTEM_GALILEO_E5A;
+ } else {
+ return SV_SYSTEM_GALILEO_E1;
+ }
+ case IRNSS_SV:
+ return SV_SYSTEM_IRNSS;
+ default:
+ return SV_SYSTEM_UNKNOWN;
+ }
+}
+
+char *nmea_constellation_to_string(SV_TYPE constellation, float freq) {
+ SV_SYSTEM sv_system = SV_SYSTEM_UNKNOWN;
+
+ sv_system = nmea_constellation_to_system_index(constellation, freq);
+ if(sv_system < SV_SYSTEM_NUMBER) {
+ return nmea_sv_system_to_string(sv_system);
+ } else {
+ return "Unkown";
+ }
+}
+
+bool nmea_sv_searched_l1(NmeaReader* const r) {
+ int index = 0;
+ gnss_sv *sv_list = r->sv_status.sv_list;
+
+ for(index = 0; index < r->sv_count; index++) {
+ if(nmea_freq_l1_signal(sv_list[index].carrier_frequency)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool nmea_sv_searched_l5(NmeaReader* const r) {
+ int index = 0;
+ gnss_sv *sv_list = r->sv_status.sv_list;
+
+ for(index = 0; index < r->sv_count; index++) {
+ if(nmea_freq_l5_signal(sv_list[index].carrier_frequency)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool nmea_sv_searched_l1_and_l5(NmeaReader* const r) {
+ int index = 0;
+ bool searched_l1 = false;
+ bool searched_l5 = false;
+ gnss_sv *sv_list = r->sv_status.sv_list;
+
+ for(index = 0; index < r->sv_count; index++) {
+ if(nmea_freq_l1_signal(sv_list[index].carrier_frequency)) {
+ searched_l1 = true;
+ }
+ if(nmea_freq_l5_signal(sv_list[index].carrier_frequency)) {
+ searched_l5 = true;
+ }
+ if(searched_l1 && searched_l5) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static int nmea_reader_update_sv_status(NmeaReader* r, unsigned int sv_index,
+ int id, Token elevation,
+ Token azimuth, Token snr, int sgl_id) {
+ // int prn = str2int(id.p, id.end);
+ int prn = id;
+ sv_index = r->sv_count+r->sv_status.num_svs;
+ if (MTK_MNLD_GNSS_MAX_SVS <= sv_index) {
+ LOGE("ERR: sv_index=[%d] is larger than MTK_MNLD_GNSS_MAX_SVS.\n", sv_index);
+ return 0;
+ }
+
+ if ((prn > 0) && (prn <= 32)) {
+ r->sv_status.sv_list[sv_index].svid = prn;
+ r->sv_status.sv_list[sv_index].constellation = GPS_SV;
+ r->sv_status.sv_list[sv_index].carrier_frequency = nmea_signal_id_to_freq_gps(sgl_id); //(float)CARRIER_FREQ_GPS_L1;
+ r->sv_status.sv_list[sv_index].flags |= 0x08;
+ } else if ((prn >= 65) && (prn <= 96)) {
+ r->sv_status.sv_list[sv_index].svid = prn-64;
+ r->sv_status.sv_list[sv_index].constellation = GLONASS_SV;
+ r->sv_status.sv_list[sv_index].carrier_frequency = (float)CARRIER_FREQ_GLO_L1;
+ r->sv_status.sv_list[sv_index].flags |= 0x08;
+ } else if ((prn >= 201) && (prn <= 263)) {
+ r->sv_status.sv_list[sv_index].svid = prn-MNLD_BDS_OFFSET;
+ r->sv_status.sv_list[sv_index].constellation = BDS_SV;
+ r->sv_status.sv_list[sv_index].carrier_frequency = nmea_signal_id_to_freq_bd(sgl_id); //(float)CARRIER_FREQ_BD_B1;
+ r->sv_status.sv_list[sv_index].flags |= 0x08;
+ } else if ((prn >= 401) && (prn <= 436)) {
+ r->sv_status.sv_list[sv_index].svid = prn-MNLD_GALILEO_OFFSET;
+ r->sv_status.sv_list[sv_index].constellation = GALILEO_SV;
+ r->sv_status.sv_list[sv_index].carrier_frequency = nmea_signal_id_to_freq_ga(sgl_id); //(float)CARRIER_FREQ_GAL_E1;
+ r->sv_status.sv_list[sv_index].flags |= 0x08;
+ } else if ((prn >= 193) && (prn <= 200)) {
+ r->sv_status.sv_list[sv_index].svid = prn-MNLD_QZSS_OFFSET;
+ r->sv_status.sv_list[sv_index].constellation = QZSS_SV;
+ r->sv_status.sv_list[sv_index].carrier_frequency = nmea_signal_id_to_freq_qzss(sgl_id); //(float)CARRIER_FREQ_GPS_L1;
+ r->sv_status.sv_list[sv_index].flags |= 0x08;
+ } else if ((prn >= 33) && (prn <= 64)) {
+ r->sv_status.sv_list[sv_index].svid = prn+87;
+ r->sv_status.sv_list[sv_index].constellation = SBAS_SV;
+ r->sv_status.sv_list[sv_index].carrier_frequency = (float)CARRIER_FREQ_GPS_L1;
+ r->sv_status.sv_list[sv_index].flags |= 0x08;
+ } else if ((prn >= 501) && (prn <= 514)) {
+ r->sv_status.sv_list[sv_index].svid = prn-MNLD_IRNSS_OFFSET;
+ r->sv_status.sv_list[sv_index].constellation = IRNSS_SV;
+ r->sv_status.sv_list[sv_index].carrier_frequency = (float)CARRIER_FREQ_IRN_L5;
+ r->sv_status.sv_list[sv_index].flags |= 0x08;
+ } else {
+ LOGW("sv_status: ignore (%d)", prn);
+ return 0;
+ }
+
+ r->sv_status.sv_list[sv_index].basebandCN0DbHz = str2float(snr.p, snr.end);
+ r->sv_status.sv_list[sv_index].c_n0_dbhz = r->sv_status.sv_list[sv_index].basebandCN0DbHz + mnld_cfg.RfPathLossDb_Ap;
+ r->sv_status.sv_list[sv_index].elevation = str2int(elevation.p, elevation.end);
+ r->sv_status.sv_list[sv_index].azimuth = str2int(azimuth.p, azimuth.end);
+ if (1 == nmea_cash[prn].used_in_fix) {
+ r->sv_status.sv_list[sv_index].flags |= 0x04;
+ } else {
+ r->sv_status.sv_list[sv_index].flags &= ~(0x04);
+ }
+ if (1 == nmea_cash[prn].has_almanac_data) {
+ r->sv_status.sv_list[sv_index].flags |= 0x02;
+ } else {
+ r->sv_status.sv_list[sv_index].flags &= ~(0x02);
+ }
+ if (1 == nmea_cash[prn].has_ephemeris_data) {
+ r->sv_status.sv_list[sv_index].flags |= 0x01;
+ } else {
+ r->sv_status.sv_list[sv_index].flags &= ~(0x01);
+ }
+
+ r->sv_count++;
+ /*
+ #ifdef CONFIG_GPS_ENG_LOAD
+ LOGD("sv_status(%2d): %2d, %d, %2f, %3f, %2f, %d",
+ sv_index, r->sv_status.sv_list[sv_index].svid, r->sv_status.sv_list[sv_index].constellation,
+ r->sv_status.sv_list[sv_index].elevation, r->sv_status.sv_list[sv_index].azimuth,
+ r->sv_status.sv_list[sv_index].c_n0_dbhz, r->sv_status.sv_list[sv_index].flags);
+ #endif
+ */
+ return 0;
+}
+
+static SV_TYPE nmea_sysid_to_svtype(GNSS_SYSTEM_ID sys_id) {
+ switch(sys_id) {
+ case GNSS_SYSTEM_ID_GP:
+ return GPS_SV;
+ case GNSS_SYSTEM_ID_GL:
+ return GLONASS_SV;
+ case GNSS_SYSTEM_ID_GA:
+ return GALILEO_SV;
+ case GNSS_SYSTEM_ID_BD:
+ return BDS_SV;
+ case GNSS_SYSTEM_ID_QZ:
+ return QZSS_SV;
+ case GNSS_SYSTEM_ID_IR:
+ return IRNSS_SV;
+ case GNSS_SYSTEM_ID_SBAS:
+ return SBAS_SV;
+ default:
+ LOGW("Invalid system id:%d, set to GPS type", sys_id);
+ return GPS_SV;
+ }
+}
+
+static void nmea_reader_parse(NmeaReader* const r) {
+/* we received a complete sentence, now parse it to generate
+* a new GPS fix...
+*/
+ nmea_parser_at_cmd_pre(); // for AT cmd test check
+
+ NmeaTokenizer tzer[1];
+ Token tok;
+ Token mtok;
+ SV_TYPE sv_type = GPS_SV;
+
+ #if NEMA_DEBUG
+ LOGD("Received: '%.*s'", r->pos, r->in);
+ #endif
+ if (r->pos < 9) {
+ LOGE("Too short. discarded. '%.*s'", r->pos, r->in);
+ return;
+ }
+
+ nmea_tokenizer_init(tzer, r->in, r->in + r->pos);
+ #if NEMA_DEBUG
+ {
+ int n;
+ LOGD("Found %d tokens", tzer->count);
+ for (n = 0; n < tzer->count; n++) {
+ Token tok = nmea_tokenizer_get(tzer, n);
+ LOGD("%2d: '%.*s'", n, tok.end-tok.p, tok.p);
+ }
+ }
+ #endif
+
+ tok = nmea_tokenizer_get(tzer, 0);
+ if (tok.p + 5 > tok.end) {
+ LOGE("sentence id '%.*s' too short, ignored.", (int)(tok.end-tok.p), tok.p);
+ return;
+ }
+ /*Will not go here if NMEA4.10, because all GSA are GNGSA in NMEA4.10
+ sv_type will be determined by system ID in GSA sentence for NMEA4.10*/
+ // ignore first two characters.
+ mtok.p = tok.p; // Mark the first two char for GPS,GLONASS,BDS , GALILEO SV parse.
+ if (!memcmp(mtok.p, "GB", 2)) {
+ sv_type = BDS_SV;
+ } else if (!memcmp(mtok.p, "BD", 2)) {
+ sv_type = BDS_SV;
+ } else if (!memcmp(mtok.p, "GP", 2)) {
+ sv_type = GPS_SV;
+ } else if (!memcmp(mtok.p, "GL", 2)) {
+ sv_type = GLONASS_SV;
+ } else if (!memcmp(mtok.p, "GA", 2)) {
+ sv_type = GALILEO_SV;
+ } else if (!memcmp(mtok.p, "GI", 2)) {
+ sv_type = IRNSS_SV;
+ } else if (!memcmp(mtok.p, "GQ", 2)) {
+ sv_type = QZSS_SV;
+ }
+ #if NEMA_DEBUG
+ LOGD("SV type: %d", sv_type);
+ #endif
+ tok.p += 2;
+ if ( !memcmp(tok.p, "GGA", 3) ) {
+ sv_inuse_num = 0;
+ // GPS fix
+ Token tok_time = nmea_tokenizer_get(tzer, 1);
+ Token tok_latitude = nmea_tokenizer_get(tzer, 2);
+ Token tok_latitudeHemi = nmea_tokenizer_get(tzer, 3);
+ Token tok_longitude = nmea_tokenizer_get(tzer, 4);
+ Token tok_longitudeHemi = nmea_tokenizer_get(tzer, 5);
+ Token tok_altitude = nmea_tokenizer_get(tzer, 9);
+ Token tok_altitudeUnits = nmea_tokenizer_get(tzer, 10);
+
+ nmea_reader_update_time(r, tok_time);
+ nmea_reader_update_latlong(r, tok_latitude,
+ tok_latitudeHemi.p[0],
+ tok_longitude,
+ tok_longitudeHemi.p[0]);
+ nmea_reader_update_altitude(r, tok_altitude, tok_altitudeUnits);
+ nmea_reader_sv_update_set(true);
+ } else if ( !memcmp(tok.p, "GSA", 3) ) {
+ Token tok_fix = nmea_tokenizer_get(tzer, 2);
+ Token tok_pdop = nmea_tokenizer_get(tzer, 15);
+ Token tok_hdop = nmea_tokenizer_get(tzer, 16);
+ Token tok_vdop = nmea_tokenizer_get(tzer, 17);
+ int idx, max = 12; /*the number of satellites in GPGSA*/
+ r->fix_mode = str2int(tok_fix.p, tok_fix.end);
+ if(tzer->count == 19) { //Get GNSS system id, and transfer to sv_type, for NMEA4.10
+ Token tok_sysid = nmea_tokenizer_get(tzer, tzer->count-1); //Get system ID
+ int sv_sysid = str2int(tok_sysid.p, tok_sysid.end);
+ sv_type = nmea_sysid_to_svtype(sv_sysid);
+ }
+
+ if (LOC_FIXED(r)) { /* 1: No fix; 2: 2D; 3: 3D*/
+ for (idx = 0; idx < max; idx++) {
+ Token tok_satellite = nmea_tokenizer_get(tzer, idx+3);
+ if (tok_satellite.p == tok_satellite.end) {
+ #if NEMA_DEBUG
+ LOGD("GSA: found %d active satellites\n", idx);
+ #endif
+ break;
+ }
+ unsigned int sate_id = (unsigned)str2int(tok_satellite.p, tok_satellite.end);
+ if (sv_type == BDS_SV) {
+ sate_id += MNLD_BDS_OFFSET;
+ #if NEMA_DEBUG
+ LOGD("It is BDS SV: %d", sate_id);
+ #endif
+ } else if (sv_type == GALILEO_SV) {
+ sate_id += MNLD_GALILEO_OFFSET;
+ #if NEMA_DEBUG
+ LOGD("It is GALILEO SV: %d", sate_id);
+ #endif
+ } else if (sv_type == IRNSS_SV) {
+ sate_id += MNLD_IRNSS_OFFSET;
+ #if NEMA_DEBUG
+ LOGD("It is IRNSS SV: %d", sate_id);
+ #endif
+ } else if (sv_type == QZSS_SV) {
+ sate_id += MNLD_QZSS_OFFSET;
+ #if NEMA_DEBUG
+ LOGD("It is QZSS SV: %d, signal ID:%d", sv_id, sglid);
+ #endif
+ }
+ if (sate_id < 550) {
+ nmea_cash[sate_id].prn = sate_id;
+ nmea_cash[sate_id].used_in_fix = 1;
+ }
+ sv_inuse_num ++;
+ }
+ nmea_reader_update_dop(r, tok_pdop, tok_hdop, tok_vdop);
+ }
+ }
+ // VER("GPGSA: mask 0x%x", r->sv_status.used_in_fix_mask);
+ else if (!memcmp(tok.p, "RMC", 3)) {
+ Token tok_time = nmea_tokenizer_get(tzer, 1);
+ Token tok_fixStatus = nmea_tokenizer_get(tzer, 2);
+ Token tok_latitude = nmea_tokenizer_get(tzer, 3);
+ Token tok_latitudeHemi = nmea_tokenizer_get(tzer, 4);
+ Token tok_longitude = nmea_tokenizer_get(tzer, 5);
+ Token tok_longitudeHemi = nmea_tokenizer_get(tzer, 6);
+ Token tok_speed = nmea_tokenizer_get(tzer, 7);
+ Token tok_bearing = nmea_tokenizer_get(tzer, 8);
+ Token tok_date = nmea_tokenizer_get(tzer, 9);
+
+ #if NEMA_DEBUG
+ LOGW("in RMC, fixStatus=%c", tok_fixStatus.p[0]);
+ #endif
+ if (tok_fixStatus.p[0] == 'A') {
+ nmea_reader_update_date(r, tok_date, tok_time);
+ nmea_reader_update_latlong(r, tok_latitude,
+ tok_latitudeHemi.p[0],
+ tok_longitude,
+ tok_longitudeHemi.p[0]);
+ nmea_reader_update_bearing(r, tok_bearing);
+ nmea_reader_update_speed(r, tok_speed);
+ }
+ } else if (!memcmp(tok.p+3, "EPH", 3)) {
+ #if NEMA_DEBUG
+ Token tok_num = nmea_tokenizer_get(tzer, 1); // number of EPH
+ int num = str2int(tok_num.p, tok_num.end);
+ #endif
+ int idx, eph = 0;
+ for (idx = 0; idx < GPS_MAX_SVS; idx++) {
+ Token tok_satellite = nmea_tokenizer_get(tzer, idx+2);
+ eph = str2int(tok_satellite.p, tok_satellite.end);
+ if (eph > 0) {
+ nmea_cash[idx+1].has_ephemeris_data = 1;
+ #if NEMA_DEBUG
+ LOGD("eph: %d, sate_id: %d, num: %d\n", eph, idx+1, num);
+ #endif
+ }
+ }
+ } else if (!memcmp(tok.p+3, "ALM", 3)) {
+ #if NEMA_DEBUG
+ Token tok_num = nmea_tokenizer_get(tzer, 1); // number of ALM
+ int num = str2int(tok_num.p, tok_num.end);
+ #endif
+ int idx, alm = 0;
+ for (idx = 0; idx < GPS_MAX_SVS; idx++) {
+ Token tok_satellite = nmea_tokenizer_get(tzer, idx+2);
+ alm = str2int(tok_satellite.p, tok_satellite.end);
+ if (alm > 0) {
+ nmea_cash[idx+1].has_almanac_data = 1;
+ #if NEMA_DEBUG
+ LOGD("alm: %d, sate_id: %d, num: %d\n", alm, idx+1, num);
+ #endif
+ }
+ }
+ } else if (!memcmp(tok.p, "GSV", 3)) {
+ Token tok_num = nmea_tokenizer_get(tzer, 1); // number of messages
+ Token tok_seq = nmea_tokenizer_get(tzer, 2); // sequence number
+ Token tok_cnt = nmea_tokenizer_get(tzer, 3); // Satellites in view
+ int num = str2int(tok_num.p, tok_num.end);
+ int seq = str2int(tok_seq.p, tok_seq.end);
+ int cnt = str2int(tok_cnt.p, tok_cnt.end);
+ int sglid = 0; //Re-use signal ID as int for different constellations' signal id enum, SIGNAL_ID_XX
+ int sv_base = (seq - 1)*NMEA_MAX_SV_INFO;
+ int sv_num = cnt - sv_base;
+ int idx, base = 4, base_idx;
+ if (sv_num > NMEA_MAX_SV_INFO)
+ sv_num = NMEA_MAX_SV_INFO;
+ if (seq == 1) /*if sequence number is 1, a new set of GSV will be parsed*/
+ r->sv_count = 0;
+ if(tzer->count%base == 1) { //Get signal ID, for NMEA4.10
+ Token tok_sglid = nmea_tokenizer_get(tzer, tzer->count-1); //Signal ID
+ sglid = str2int(tok_sglid.p, tok_sglid.end);
+ }
+ for (idx = 0; idx < sv_num; idx++) {
+ base_idx = base*(idx+1);
+ Token tok_id = nmea_tokenizer_get(tzer, base_idx+0);
+ int sv_id = str2int(tok_id.p, tok_id.end);
+
+ if (sv_type == BDS_SV) {
+ sv_id += MNLD_BDS_OFFSET;
+ #if NEMA_DEBUG
+ LOGD("It is BDS SV: %d, signal ID:%d", sv_id, sglid);
+ #endif
+ } else if (sv_type == GALILEO_SV) {
+ sv_id += MNLD_GALILEO_OFFSET;
+ #if NEMA_DEBUG
+ LOGD("It is GALILEO SV: %d, signal ID:%d", sv_id, sglid);
+ #endif
+ } else if (sv_type == IRNSS_SV) {
+ sv_id += MNLD_IRNSS_OFFSET;
+ #if NEMA_DEBUG
+ LOGD("It is IRNSS SV: %d, signal ID:%d", sv_id, sglid);
+ #endif
+ } else if (sv_type == QZSS_SV) {
+ sv_id += MNLD_QZSS_OFFSET;
+ #if NEMA_DEBUG
+ LOGD("It is QZSS SV: %d, signal ID:%d", sv_id, sglid);
+ #endif
+ }
+ Token tok_ele = nmea_tokenizer_get(tzer, base_idx+1);
+ Token tok_azi = nmea_tokenizer_get(tzer, base_idx+2);
+ Token tok_snr = nmea_tokenizer_get(tzer, base_idx+3);
+ if (r->sv_count < MTK_SV_NUMBER) {
+ prn[r->sv_count] = str2int(tok_id.p, tok_id.end);
+ snr[r->sv_count] = (int)str2float(tok_snr.p, tok_snr.end);
+ }
+
+ nmea_reader_update_sv_status(r, sv_base+idx, sv_id, tok_ele, tok_azi, tok_snr, sglid);
+ }
+ if (seq == num) {
+ if (r->sv_count <= cnt) {
+ r->sv_status.num_svs += r->sv_count;
+ if ((1 == MNL_AT_TEST_FLAG) || (1 == MNL_AT_SIGNAL_MODE) || (1 == MNL_AT_FM_MODE)) {
+ gps_at_command_test_proc(r);
+ }
+ } else {
+ LOGE("GPGSV incomplete (%d/%d), ignored!", r->sv_count, cnt);
+ r->sv_count = r->sv_status.num_svs = 0;
+ }
+ }
+ }
+ // Add for Accuracy
+ else if (!memcmp(tok.p, "ACCURACY", 8)) {
+ if ((r->fix_mode == 3) || (r->fix_mode == 2)) {
+ // if(LOC_FIXED(r)) {
+ Token tok_haccuracy = nmea_tokenizer_get(tzer, 1);
+ Token tok_baccuracy = nmea_tokenizer_get(tzer, 2);
+ Token tok_saccuracy = nmea_tokenizer_get(tzer, 3);
+ Token tok_vaccuracy = nmea_tokenizer_get(tzer, 4);
+ nmea_reader_update_accuracy(r, tok_haccuracy, tok_baccuracy, tok_saccuracy, tok_vaccuracy);
+ //LOGD("GPS get accuracy from driver:%f\n", r->fix.accuracy);
+ }
+ } else if (!memcmp(mtok.p, "PMTK817", 7)) {
+ int snr = 0;
+ float clkdrift = 0.0f;
+
+ Token tok_snr = nmea_tokenizer_get(tzer, 2);
+ Token clk_drift = nmea_tokenizer_get(tzer, 3);
+
+ snr = str2int(tok_snr.p, tok_snr.end);
+ clkdrift = str2float(clk_drift.p, clk_drift.end);
+
+ LOGD("receive PMTK817 command, snr: %d clkdrfit: %.2f\n", snr, clkdrift);
+
+ if (MNL_AT_CW_MODE == 1){
+ at_cw_test_command_test_result(snr, clkdrift);
+ }
+ } else if (!memcmp(mtok.p, "PMTKAG2", 7)) {
+ Token tok_agc = nmea_tokenizer_get(tzer, 2);
+ g_agc_level = str2int(tok_agc.p, tok_agc.end);
+ LOGD("receive PMTKAG2 command, agc: %d\n", g_agc_level);
+ } else if (!memcmp(mtok.p, "PMTKAGC", 7) && ((tzer->count) > POS_AGC_LEVEL_IN_PMTKAGC)) {
+ Token tok_agc = nmea_tokenizer_get(tzer, POS_AGC_LEVEL_IN_PMTKAGC);
+ g_agc_level = str2int(tok_agc.p, tok_agc.end);
+ LOGD("receive PMTKAGC command, agc: %d\n", g_agc_level);
+ } else {
+ tok.p -= 2;
+ LOGW("unknown sentence '%.*s", (int)(tok.end-tok.p), tok.p);
+ }
+ #if NEMA_DEBUG
+ LOGD("r->sv_status.num_svs = %d, gps_nmea_end_tag = %d", r->sv_status.num_svs, gps_nmea_end_tag);
+ #endif
+ if (gps_nmea_end_tag && nmea_reader_sv_status_changed()) {
+ if(mnld_gps_update_sv(&(r->sv_status)) == -1) {
+ LOGW("mnld_gps_update_sv fail");
+ }
+ r->sv_count = r->sv_status.num_svs = 0;
+ memset((void*)nmea_cash, 0x00, sizeof(nmea_cash));
+ nmea_reader_sv_update_set(false);
+ }
+ if (!LOC_FIXED(r)) {
+ mnld_set_sv_inuse_valid(false);
+ mnld_set_sv_inuse_num(0);
+ #if NEMA_DEBUG
+ LOGW("Location is not fixed, ignored callback\n");
+ #endif
+ } else if (r->fix.flags != 0 && gps_nmea_end_tag) {
+ #if NEMA_DEBUG
+ char temp[256];
+ char* p = temp;
+ char* end = p + sizeof(temp);
+ struct tm utc;
+
+ p += snprintf(p, end-p, "sending fix");
+ if (r->fix.flags & MTK_GPS_LOCATION_HAS_LAT_LONG) {
+ p += snprintf(p, end-p, " lat=%g lon=%g", r->fix.lat, r->fix.lng);
+ }
+ if (r->fix.flags & MTK_GPS_LOCATION_HAS_ALT) {
+ p += snprintf(p, end-p, " altitude=%g", r->fix.alt);
+ }
+ if (r->fix.flags & MTK_GPS_LOCATION_HAS_SPEED) {
+ p += snprintf(p, end-p, " speed=%g", r->fix.speed);
+ }
+ if (r->fix.flags & MTK_GPS_LOCATION_HAS_BEARING) {
+ p += snprintf(p, end-p, " bearing=%g", r->fix.bearing);
+ }
+ if (r->fix.flags & MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY) {
+ p += snprintf(p, end-p, " accuracy=%g", r->fix.h_accuracy);
+ LOGD("GPS accuracy=%g\n", r->fix.h_accuracy);
+ }
+ gmtime_r((time_t*) &r->fix.timestamp, &utc);
+ p += snprintf(p, end-p, " time=%s", asctime(&utc));
+ LOGW("%s", temp);
+ #endif
+ LOGD("fix_mode:%d, fix_flag:0x%x", r->fix_mode, r->fix.flags);
+ mnld_set_sv_inuse_valid(true);
+ mnld_set_sv_inuse_num(sv_inuse_num);
+ LOGD("mnld_set_sv_inuse_valid:%d, mnld_set_sv_inuse_num:%d", mnld_get_sv_inuse_num_valid(), mnld_get_sv_inuse_num());
+ if (mnl2hal_location(r->fix) == -1) {
+ LOGE("mnl2hal_location failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ if (mnld_gps_update_location(r->fix, r->fix_mode) == -1) {
+ LOGE("mnld_gps_update_location failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ r->fix.flags = 0;
+ }
+}
+
+static void nmea_reader_addc(NmeaReader* const r, int c) {
+ if (r->overflow) {
+ r->overflow = (c != '\n');
+ return;
+ }
+
+ if (r->pos >= NMEA_MAX_SIZE) {
+ r->overflow = 1;
+ r->pos = 0;
+ return;
+ }
+
+ r->in[r->pos] = (char)c;
+ r->pos += 1;
+
+ if (c == '\n') {
+ nmea_reader_parse(r);
+ // LOGD("the structure include nmea_cb address is %p\n", r);
+ if (mnl2hal_nmea(r->fix.timestamp, r->in, r->pos) == -1) {
+ LOGE("mnl2hal_nmea failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+
+ if(gps_nmea_end_tag) {
+ if(mnld_gnss_nmea_done() == -1) {
+ LOGW("mnld_gnss_nmea_done fail");
+ }
+ }
+ // LOGD("length: %d, nmea sentence: %s\n", r->pos, r->in);
+ r->pos = 0;
+ memset(r->in, 0x00, NMEA_MAX_SIZE+1);
+ }
+}
+
+void mtk_mnl_nmea_parser_process(const char * buffer, UINT32 length) {
+ UINT32 nn;
+ NmeaReader reader[1];
+
+ nmea_reader_init(reader);
+ gps_nmea_end_tag = 0;
+ for (nn = 0; nn < length; nn++) {
+ if (nn == (length-1)) {
+ gps_nmea_end_tag = 1;
+ }
+ nmea_reader_addc(reader, buffer[nn]);
+ }
+}
+
+int get_gps_nmea_parser_end_status() {
+ int ret = 0;
+
+ ret = gps_nmea_end_tag;
+ return ret;
+}
+
+void mnld_get_mnl_version(char *mnl_ver) {
+ char mnl_ver_pmtk[NMEA_MAX_SIZE] = {0};
+ NmeaTokenizer tzer[1];
+ Token tok_mnlver;
+ int len_mnlver = 0;
+
+ mtk_gps_get_param(MTK_PARAM_LIB_VERSION, mnl_ver_pmtk);
+ if(strlen(mnl_ver_pmtk) > NMEA_MAX_SIZE) {
+ mnl_ver_pmtk[NMEA_MAX_SIZE-1] = '\0';
+ }
+ nmea_tokenizer_init(tzer, mnl_ver_pmtk, mnl_ver_pmtk+strlen(mnl_ver_pmtk)-1);
+#if NEMA_DEBUG
+ {
+ int n;
+ LOGD("Found %d tokens", tzer->count);
+ for (n = 0; n < tzer->count; n++) {
+ Token tok = nmea_tokenizer_get(tzer, n);
+ LOGD("%2d: '%.*s'", n, tok.end-tok.p, tok.p);
+ }
+ }
+#endif
+ tok_mnlver = nmea_tokenizer_get(tzer, 3);
+ len_mnlver = tok_mnlver.end - tok_mnlver.p;
+ if(len_mnlver > NMEA_MAX_SIZE) {
+ len_mnlver = NMEA_MAX_SIZE;
+ }
+ MNLD_STRNCPY(mnl_ver, tok_mnlver.p, NMEA_MAX_SIZE);
+}
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/op01_log.c b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/op01_log.c
new file mode 100644
index 0000000..bfbcb6c
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/op01_log.c
@@ -0,0 +1,213 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#include "op01_log.h"
+#include "mnld.h"
+#include "gps_controller.h"
+
+#include "mtk_mnld_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "OP01_LOG"
+
+typedef enum {
+ MAIN2OP01_EVENT_LOG_WRITE = 0,
+} main2op01_event;
+
+#ifdef MTK_GNSS_OP01_LOG_SUPPORT
+static int g_fd_op01;
+extern bool mnld_exiting;
+static int send_op01_log_msg(const char *fmt, ...) {
+ char buf[1024] = {0};
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ put_int(buff, &offset, MAIN2OP01_EVENT_LOG_WRITE);
+ put_string(buff, &offset, buf, sizeof(buff));
+ return safe_sendto(MNLD_OP01_LOG_WRITER_SOCKET, buff, offset);
+}
+
+static void get_time_stamp(char* time_str1, char* time_str2) {
+ struct tm *tm_pt = NULL;
+ time_t time_st;
+ struct timeval tv;
+
+ time(&time_st);
+ gettimeofday(&tv, NULL);
+ tm_pt = gmtime(&time_st);
+ tm_pt = localtime(&tv.tv_sec);
+ memset(time_str1, 0, sizeof(char)*30);
+ memset(time_str2, 0, sizeof(char)*30);
+ if (tm_pt) {
+ sprintf(time_str1, "%d%02d%02d%02d%02d%02d.%1ld",
+ tm_pt->tm_year+1900, tm_pt->tm_mon+1, tm_pt->tm_mday,
+ tm_pt->tm_hour, tm_pt->tm_min, tm_pt->tm_sec, tv.tv_usec/100000);
+ sprintf(time_str2, "%d%02d%02d%02d%02d%02d.%03ld",
+ tm_pt->tm_year+1900, tm_pt->tm_mon+1, tm_pt->tm_mday,
+ tm_pt->tm_hour, tm_pt->tm_min, tm_pt->tm_sec, tv.tv_usec/1000);
+ }
+ LOGE("time_str1=%s,time_str2=%s\n", time_str1, time_str2);
+}
+int op01_log_write_internal(const char* log) {
+ // TODO add a configuration to enable/disable the op01 log
+ if (get_file_size(MNLD_OP01_LOG_PATH) > 65535) {
+ LOGD("delete_op01_file=[%s]", MNLD_OP01_LOG_PATH);
+ delete_file(MNLD_OP01_LOG_PATH);
+ }
+ write_msg2file(MNLD_OP01_LOG_PATH, "%s", log);
+ return 0;
+}
+static int op01_event_hdlr(int fd) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ main2op01_event cmd;
+ int read_len;
+
+ read_len = safe_recvfrom(fd, buff, sizeof(buff));
+ if (read_len <= 0) {
+ LOGE("op01_event_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+ return -1;
+ }
+
+ cmd = get_int(buff, &offset, sizeof(buff));
+ switch (cmd) {
+ case MAIN2OP01_EVENT_LOG_WRITE: {
+ char* log = get_string(buff, &offset, sizeof(buff));
+ LOGD("op01_log_write_internal() log=[%s]", log);
+ op01_log_write_internal(log);
+ break;
+ }
+ default: {
+ LOGE("epo_event_hdlr() unknown cmd=%d", cmd);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static void op01_log_thread_timeout() {
+ if (mnld_timeout_ne_enabled() == false) {
+ LOGE("op01_log_thread_timeout() dump and exit.");
+ mnld_exiting = true;
+ gps_dbg_log_exit_flush(0);
+ mnld_block_exit();
+ } else {
+ LOGE("op01_log_thread_timeout() crash here for debugging");
+ CRASH_TO_DEBUG();
+ }
+}
+static void* op01_log_thread(void *arg) {
+ #define MAX_EPOLL_EVENT 50
+ timer_t hdlr_timer = init_timer(op01_log_thread_timeout);
+ struct epoll_event events[MAX_EPOLL_EVENT];
+ UNUSED(arg);
+
+ int epfd = epoll_create(MAX_EPOLL_EVENT);
+ if (epfd == -1) {
+ LOGE("op01_log_thread() epoll_create failure reason=[%s]%d",
+ strerror(errno), errno);
+ return 0;
+ }
+
+ if (epoll_add_fd(epfd, g_fd_op01) == -1) {
+ LOGE("op01_log_thread() epoll_add_fd() failed for g_fd_op01 failed");
+ return 0;
+ }
+
+ while (1) {
+ int i;
+ int n;
+ LOGD("op01_log_thread wait");
+ n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+ if (n == -1) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ LOGE("op01_log_thread() epoll_wait failure reason=[%s]%d",
+ strerror(errno), errno);
+ return 0;
+ }
+ }
+ start_timer(hdlr_timer, MNLD_OP01_HANDLER_TIMEOUT);
+ for (i = 0; i < n; i++) {
+ if (events[i].data.fd == g_fd_op01) {
+ if (events[i].events & EPOLLIN) {
+ op01_event_hdlr(g_fd_op01);
+ }
+ } else {
+ LOGE("op01_log_thread() unknown fd=%d",
+ events[i].data.fd);
+ }
+ }
+ stop_timer(hdlr_timer);
+ }
+ LOGE("op01_log_thread() exit");
+ return 0;
+}
+#endif
+int op01_log_gps_start() {
+#ifdef MTK_GNSS_OP01_LOG_SUPPORT
+ char time_str1[30] = {0};
+ char time_str2[30] = {0};
+ get_time_stamp(time_str1, time_str2);
+ return send_op01_log_msg("[%s]0x00000000: %s #gps start\r\n", time_str2, time_str2);
+#else
+ return 0;
+#endif
+}
+
+int op01_log_gps_stop() {
+#ifdef MTK_GNSS_OP01_LOG_SUPPORT
+ char time_str1[30] = {0};
+ char time_str2[30] = {0};
+ get_time_stamp(time_str1, time_str2);
+ return send_op01_log_msg("[%s]0x00000001: %s #gps stop\r\n", time_str2, time_str2);
+#else
+ return 0;
+#endif
+}
+
+int op01_log_gps_location(double lat, double lng, int ttff) {
+#ifdef MTK_GNSS_OP01_LOG_SUPPORT
+ char time_str1[30] = {0};
+ char time_str2[30] = {0};
+ get_time_stamp(time_str1, time_str2);
+ return send_op01_log_msg("[%s]0x00000002: %s, %f, %f, %d #position(time_stamp, lat, lon, ttff)\r\n",
+ time_str2, time_str2, lat, lng, ttff);
+#else
+ UNUSED(lat);
+ UNUSED(lng);
+ UNUSED(ttff);
+ return 0;
+#endif
+}
+
+int op01_log_init() {
+#ifdef MTK_GNSS_OP01_LOG_SUPPORT
+ pthread_t pthread_op01;
+
+ g_fd_op01 = socket_bind_udp(MNLD_OP01_LOG_WRITER_SOCKET);
+ if (g_fd_op01 < 0) {
+ LOGE("socket_bind_udp(MNLD_OP01_LOG_WRITER_SOCKET) failed");
+ return -1;
+ }
+
+ pthread_create(&pthread_op01, NULL, op01_log_thread, NULL);
+#endif
+ return 0;
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/qepo.c b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/qepo.c
new file mode 100644
index 0000000..f1dc363
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/mnld_entity/src/qepo.c
@@ -0,0 +1,1337 @@
+#include <errno.h> /* Error number definitions */
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "mtk_gps_agps.h"
+#include "agps_agent.h"
+#include "data_coder.h"
+#include "mnl_common.h"
+#include "mnld.h"
+#include "mtk_lbs_utility.h"
+#include "epo.h"
+#include "qepo.h"
+#include "curl.h"
+#include "easy.h"
+#include "gps_controller.h"
+
+#include "mtk_mnld_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "qepo"
+
+#define QUARTER_FILE_HAL MTK_GPS_DATA_PATH"QEPOHAL.DAT"
+#define QEPO_BD_INVALID_SLEEP (100*1000) //Delay 100ms before fail response, when the BD QEPO data on server is invalid
+#define QEPO_GA_INVALID_SLEEP (100*1000) //Delay 100ms before fail response, when the GA QEPO data on server is invalid
+
+static char quarter_epo_file_name[GPS_EPO_FILE_LEN] = {0};
+static char quarter_epo_bd_file_name[GPS_EPO_FILE_LEN] = {0};
+static char quarter_epo_bd_md_file_name[GPS_EPO_FILE_LEN] = {0};
+static char quarter_epo_ga_file_name[GPS_EPO_FILE_LEN] = {0};
+
+static int qepo_file_update_impl();
+typedef enum {
+ MAIN2QEPO_EVENT_START = 0,
+ MAIN2QEPO_BD_EVENT_START = 1,
+ MAIN2QEPO_GA_EVENT_START = 2,
+} main2qepo_event;
+
+typedef struct qepo_gps_time {
+ int wn;
+ int tow;
+ int sys_time;
+}QEPO_GPS_TIME_T;
+
+static QEPO_GPS_TIME_T gps_time;
+static int g_fd_qepo;
+static int qepo_download_finished = 1;
+static int qepo_bd_download_finished = 1;
+static int qepo_ga_download_finished = 1;
+extern int gps_epo_type;
+static time_t g_qbd_latest_dl_time_utc_s = 0; //Record the latest time of downloading BD QEPO file from server
+static time_t g_qbd_first_invalid_dl_time_utc_s = 0; //Record the latest time of downloading BD QEPO file from server, and the file is valid
+static int g_qepo_bd_has_epo = MTK_GPS_TRUE; //This flag to indentify the QBD.DAT file on server is valid or not, valid when init
+static int g_qepo_bd_file_size_correct = MTK_GPS_TRUE; //The file size is correct or not, correct in init
+static int g_qepo_bd_file_time_correct = MTK_GPS_TRUE; //The BD QEPO file time is correct or not, correct in init
+int g_qepo_bd_invalid_dl_cnt = 0;
+static time_t g_qga_latest_dl_time_utc_s = 0; //Record the latest time of downloading BD QEPO file from server
+static time_t g_qga_first_invalid_dl_time_utc_s = 0; //Record the latest time of downloading BD QEPO file from server, and the file is valid
+static int g_qepo_ga_has_epo = MTK_GPS_TRUE; //This flag to indentify the QBD.DAT file on server is valid or not, valid when init
+static int g_qepo_ga_file_size_correct = MTK_GPS_TRUE; //The file size is correct or not, correct in init
+static int g_qepo_ga_file_time_correct = MTK_GPS_TRUE; //The BD QEPO file time is correct or not, correct in init
+int g_qepo_ga_invalid_dl_cnt = 0;
+bool qepo_update_flag = false;
+int qepo_dl_res = EPO_DOWNLOAD_RESULT_FAIL;
+bool qepo_BD_update_flag = false;
+int qepo_bd_dl_res = EPO_DOWNLOAD_RESULT_FAIL;
+bool qepo_GA_update_flag = false;
+int qepo_ga_dl_res = EPO_DOWNLOAD_RESULT_FAIL;
+
+/////////////////////////////////////////////////////////////////////////////////
+// static functions
+
+static int pre_day = 0;
+static int server_not_updated = 0;
+static int Qepo_res = 0;
+static int Qepo_bd_res = 0;
+static int Qepo_ga_res = 0;
+static int counter_GR = 1;
+static int counter_BD = 1;
+static int counter_GA = 1;
+
+static void getQepoUrl(const char* filename, char* url, int count) {
+ char count_str[15] = {0};
+
+ if (count > 1 || (access(EPO_FILE, F_OK) < 0) || epo_downloader_is_file_invalid()) {
+ strncat(url, EPO_URL_HOME_C, GPS_EPO_URL_LEN - strlen(url));
+ } else {
+ strncat(url, EPO_URL_HOME_G, GPS_EPO_URL_LEN -strlen(url));
+ }
+
+ strncat(url, filename, GPS_EPO_URL_LEN - strlen(url));
+ strncat(url, "?retryCount=", GPS_EPO_URL_LEN - strlen(url));
+ MNLD_SPRINTF(count_str, "%d", count-1);
+ strncat(url, count_str, GPS_EPO_URL_LEN - strlen(url));
+ LOGD_ENG("url = %s\n", url);
+}
+
+static CURLcode curl_easy_download_quarter_epo(void) {
+ int res_val;
+ CURLcode res;
+ char url[GPS_EPO_URL_LEN]={0};
+
+ LOGD_ENG("curl_easy_download_quarter_epo");
+ getQepoUrl(quarter_epo_file_name, url, counter_GR);
+
+ res = curl_easy_download(url, QUARTER_FILE_HAL);
+ LOGD("qepo file curl_easy_download res = %d\n", res);
+ Qepo_res = res;
+ if (res == 0) {
+ counter_GR = 1;
+ res_val = chmod(QUARTER_FILE_HAL, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ if (res_val < 0) {
+ LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+ }
+ } else {
+ counter_GR++;
+ }
+ return res;
+}
+
+static CURLcode curl_easy_download_quarter_epo_bd(void) {
+ int res_val;
+ CURLcode res;
+ char url[GPS_EPO_URL_LEN]={0};
+
+ LOGD_ENG("curl_easy_download_quarter_bdepo");
+ getQepoUrl(quarter_epo_bd_file_name, url, counter_BD);
+
+ res = curl_easy_download(url, QEPO_BD_UPDATE_FILE);
+
+ LOGD("qbdepo file curl_easy_download res = %d\n", res);
+ Qepo_bd_res = res;
+ if (res == 0) {
+ counter_BD = 1;
+ res_val = chmod(QEPO_BD_UPDATE_FILE, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+ } else {
+ counter_BD++;
+ }
+ return res;
+}
+
+static CURLcode curl_easy_download_quarter_epo_ga(void) {
+ int res_val;
+ CURLcode res;
+ char url[GPS_EPO_URL_LEN]={0};
+
+ LOGD_ENG("curl_easy_download_quarter_gaepo");
+ getQepoUrl(quarter_epo_ga_file_name, url, counter_GA);
+
+ res = curl_easy_download(url, QEPO_GA_UPDATE_FILE);
+
+ LOGD("qgaepo file curl_easy_download res = %d\n", res);
+ Qepo_ga_res = res;
+ if (res == 0) {
+ counter_GA = 1;
+ res_val = chmod(QEPO_GA_UPDATE_FILE, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+ } else {
+ counter_GA++;
+ }
+ return res;
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_qepo_bd_period_start
+ * DESCRIPTION
+ * Get the start time of Beidou QEPO file
+ * PARAMETERS
+ * [IN] fd: The file description of Beidou QEPO file
+ * [OUT] u4GpsSecs: The start time of Beidou QEPO file in second of GSP time
+ * [OUT] uSecond: The start time of Beidou QEPO file in second of UTC time
+ * RETURNS
+ * success(0); failure(-1)
+ *****************************************************************************/
+int mtk_gps_sys_qepo_bd_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond) { // no file lock
+ char szBuf[MTK_EPO_ONE_SV_SIZE];
+ int pi2WeekNo;
+ unsigned int pu4Tow;
+
+ if (-1 == lseek(fd, MTK_QEPO_BD_HEADER_SIZE, SEEK_SET)) { //Skip the header of BD QEPO file
+ LOGE("lseek error\n");
+ return -1;
+ }
+
+ if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+ LOGE("read error\n");
+ return -1;
+ }
+
+ *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+ pi2WeekNo = (*u4GpsSecs) / 604800;
+ pu4Tow = (*u4GpsSecs) % 604800;
+
+ // TRC();
+ GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond); // to get UTC second
+ return 0;
+}
+
+int mtk_gps_sys_qepo_ga_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond) { // no file lock
+ char szBuf[MTK_EPO_ONE_SV_SIZE];
+ int pi2WeekNo;
+ unsigned int pu4Tow;
+
+ if (-1 == lseek(fd, MTK_QEPO_GA_HEADER_SIZE, SEEK_SET)) { //Skip the header of GA QEPO file
+ LOGE("lseek error\n");
+ return -1;
+ }
+
+ if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+ LOGE("read error\n");
+ return -1;
+ }
+
+ *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+ pi2WeekNo = (*u4GpsSecs) / 604800;
+ pu4Tow = (*u4GpsSecs) % 604800;
+
+ // TRC();
+ GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond); // to get UTC second
+ return 0;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_qepo_bd_has_epo
+ * DESCRIPTION
+ * Get the HAS_EPO flag of Beidou QEPO file
+ * PARAMETERS
+ * [IN] header: The first word value of header in Beidou QEPO file
+ * [OUT] has_epo: The value of HAS_EPO flag
+ * RETURNS
+ * success(0); failure(-1)
+ *****************************************************************************/
+int mtk_gps_sys_qepo_bd_has_epo(UINT32 header, int* has_epo) {
+ if (NULL == has_epo) { //Read from the beginning of BD QEPO file
+ LOGE("has_epo pointer check error\n");
+ return -1;
+ }
+
+ if((header&QEPO_BD_HAS_EPO_BIT_MASK) == QEPO_BD_HAS_EPO_BIT_MASK)
+ {
+ *has_epo = MTK_GPS_TRUE;
+ LOGD("BD QEPO has epo(0x%x)!!!\n", header);
+ }else{
+ *has_epo = MTK_GPS_FALSE;
+ LOGE("BD QEPO file error(0x%x), doesn't have epo!!!\n",header);
+ }
+
+ return 0;
+}
+
+int mtk_gps_sys_qepo_ga_has_epo(UINT32 header, int* has_epo) {
+ if (NULL == has_epo) { //Read from the beginning of GA QEPO file
+ LOGE("has_epo pointer check error\n");
+ return -1;
+ }
+
+ if((header&QEPO_GA_HAS_EPO_BIT_MASK) == QEPO_GA_HAS_EPO_BIT_MASK)
+ {
+ *has_epo = MTK_GPS_TRUE;
+ LOGD("GA QEPO has epo(0x%x)!!!\n", header);
+ }else{
+ *has_epo = MTK_GPS_FALSE;
+ LOGE("GA QEPO file error(0x%x), doesn't have epo!!!\n",header);
+ }
+
+ return 0;
+}
+
+/* count the number of 1 in a 32-bit word */
+static UINT32
+gps_mnl_epo_bit_cnt (UINT32 u4BitMask)
+{
+ UINT32 i, u4Cnt = 0;
+
+ for (i = 0; i < 32; i++)
+ {
+ if (1 == ((u4BitMask >> i) & 1))
+ {
+ u4Cnt++;
+ }
+ }
+
+ return u4Cnt;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_qepo_bd_get_sv_cnt
+ * DESCRIPTION
+ * Get the SV cnt of Beidou QEPO file
+ * PARAMETERS
+ * [IN] header: The second word value of header in Beidou QEPO file
+ * [OUT] sv_cnt: The value of SV count
+ * RETURNS
+ * success(0); failure(-1)
+ *****************************************************************************/
+int mtk_gps_sys_qepo_bd_get_sv_cnt(UINT32 header, int* sv_cnt) {
+ if (NULL == sv_cnt) { //Read from the beginning of BD QEPO file
+ LOGE("sv_cnt pointer check error\n");
+ return -1;
+ }
+
+ *sv_cnt = gps_mnl_epo_bit_cnt(header);
+ LOGD("sv cnt(0x%x):%d",header,*sv_cnt);
+
+ return 0;
+}
+
+int mtk_gps_sys_qepo_ga_get_sv_cnt(UINT32 header, int* sv_cnt) {
+ if (NULL == sv_cnt) { //Read from the beginning of GA QEPO file
+ LOGE("sv_cnt pointer check error\n");
+ return -1;
+ }
+
+ *sv_cnt = gps_mnl_epo_bit_cnt(header);
+ LOGD("sv cnt(0x%x):%d",header,*sv_cnt);
+
+ return 0;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * mtk_gps_sys_qepo_bd_get_header
+ * DESCRIPTION
+ * Get the header of Beidou QEPO file(72byte)
+ * PARAMETERS
+ * [IN] fd: The file description of Beidou QEPO file
+ * [OUT] bd_header: The pointer of HAS_EPO flag
+ * RETURNS
+ * success(0); failure(-1)
+ *****************************************************************************/
+int mtk_gps_sys_qepo_bd_get_header(int fd, UINT32 bd_header[MTK_EPO_ONE_SV_SIZE/4]) { // no file lock
+ if(NULL == bd_header )
+ {
+ LOGE("bd_header pointer check error\n");
+ return -1;
+ }
+
+ if (-1 == lseek(fd, 0, SEEK_SET)) { //Read from the beginning of BD QEPO file
+ LOGE("lseek error(%s)\n",strerror(errno));
+ return -1;
+ }
+
+ memset(bd_header,0,MTK_EPO_ONE_SV_SIZE);
+ if (read(fd, bd_header, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+ LOGD_ENG("read error(%s)\n",strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+int mtk_gps_sys_qepo_ga_get_header(int fd, UINT32 ga_header[MTK_EPO_ONE_SV_SIZE/4]) { // no file lock
+ if(NULL == ga_header )
+ {
+ LOGE("ga_header pointer check error\n");
+ return -1;
+ }
+
+ if (-1 == lseek(fd, 0, SEEK_SET)) { //Read from the beginning of BD QEPO file
+ LOGE("lseek error(%s)\n",strerror(errno));
+ return -1;
+ }
+
+ memset(ga_header,0,MTK_EPO_ONE_SV_SIZE);
+ if (read(fd, ga_header, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+ LOGE("read error(%s)\n",strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+static int is_quarter_epo_valid(void) {
+ unsigned int u4GpsSecs_start; // GPS seconds
+ time_t uSecond_start; // UTC seconds
+ time_t mnl_time;
+ time_t *mnl_gps_time = NULL;
+ int fd = 0;
+ int ret = EPO_DOWNLOAD_RESULT_FAIL;
+
+ fd = open(QUARTER_FILE_HAL, O_RDONLY);
+ if (fd < 0) {
+ LOGE("Open QEPO fail, return\n");
+ return ret;
+ } else {
+ if (mtk_gps_sys_epo_period_start(fd, &u4GpsSecs_start, &uSecond_start)) {
+ LOGE("Read QEPO file failed\n");
+ close(fd);
+ return ret;
+ } else {
+ mnl_gps_time = &mnl_time;
+ //LOGD("gps_time.wn, tow %d, %d\n", gps_time.wn, gps_time.tow);
+ GpsToUtcTime(gps_time.wn, gps_time.tow, mnl_gps_time);
+ //LOGD("The Start time of QEPO file is %lld\n", (long long)uSecond_start);
+ LOGD("The start time of QEPO file is %s", ctime(&uSecond_start));
+ LOGD("GPS time: %s", ctime(mnl_gps_time));
+
+ if ((mnl_time >= uSecond_start) && (mnl_time < ((6*60*60) + uSecond_start))) {
+ ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+ } else {
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ if (uSecond_start >= ((18*60*60) + mnl_time)) {
+ // download time 23:55, server has updated
+ pre_day = 1;
+ } else {
+ pre_day = 0;
+ }
+ if (mnl_time >= ((24*60*60) + uSecond_start)) {
+ // download time 00:04,server has not updated
+ server_not_updated = 1;
+ } else {
+ server_not_updated = 0;
+ }
+ }
+ }
+ close(fd);
+ }
+ return ret;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * gps_mnl_set_qbd_latest_dl_time
+ * DESCRIPTION
+ * Set the latest Beidou QEPO download time in second of UTC time
+ * PARAMETERS
+ * [IN] dl_time: The UTC time to be set
+ * RETURNS
+ * All ways 0
+ *****************************************************************************/
+static int gps_mnl_set_qbd_latest_dl_time(time_t dl_time)
+{
+ g_qbd_latest_dl_time_utc_s = dl_time;
+
+ return 0;
+}
+
+static int gps_mnl_set_qga_latest_dl_time(time_t dl_time)
+{
+ g_qga_latest_dl_time_utc_s = dl_time;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * gps_mnl_get_qbd_latest_dl_time
+ * DESCRIPTION
+ * Get the latest Beidou QEPO download time in second of UTC time
+ * PARAMETERS
+ * None
+ * RETURNS
+ * The value of g_qbd_latest_dl_time_utc_s
+ *****************************************************************************/
+time_t gps_mnl_get_qbd_latest_dl_time(void)
+{
+ return g_qbd_latest_dl_time_utc_s;
+}
+
+time_t gps_mnl_get_qga_latest_dl_time(void)
+{
+ return g_qga_latest_dl_time_utc_s;
+}
+
+ /*****************************************************************************
+ * FUNCTION
+ * gps_mnl_set_qbd_first_invalid_dl_time
+ * DESCRIPTION
+ * Set the latest Beidou QEPO invalid download time in second of UTC time
+ * invalid download: The file has been downloaded to local, but is invalid(size or start time is incorrect)
+ * PARAMETERS
+ * [IN] dl_time: The UTC time to be set
+ * RETURNS
+ * All ways 0
+ *****************************************************************************/
+ int gps_mnl_set_qbd_first_invalid_dl_time(time_t dl_time)
+ {
+ g_qbd_first_invalid_dl_time_utc_s = dl_time;
+ return 0;
+ }
+
+ int gps_mnl_set_qga_first_invalid_dl_time(time_t dl_time)
+ {
+ g_qga_first_invalid_dl_time_utc_s = dl_time;
+ return 0;
+ }
+
+ /*****************************************************************************
+ * FUNCTION
+ * gps_mnl_get_qbd_first_invalid_dl_time
+ * DESCRIPTION
+ * Get the latest Beidou QEPO invalid download time in second of UTC time
+ * invalid download: The file has been downloaded to local, but is invalid(size or start time is incorrect)
+ * PARAMETERS
+ * None
+ * RETURNS
+ * The value of g_qbd_first_invalid_dl_time_utc_s
+ *****************************************************************************/
+ time_t gps_mnl_get_qbd_first_invalid_dl_time(void)
+ {
+ return g_qbd_first_invalid_dl_time_utc_s;
+ }
+
+ time_t gps_mnl_get_qga_first_invalid_dl_time(void)
+ {
+ return g_qga_first_invalid_dl_time_utc_s;
+ }
+
+ /*****************************************************************************
+ * FUNCTION
+ * gps_mnl_qbd_has_epo
+ * DESCRIPTION
+ * Get the value of g_qepo_bd_has_epo
+ * PARAMETERS
+ * None
+ * RETURNS
+ * The value of g_qepo_bd_has_epo
+ *****************************************************************************/
+int gps_mnl_qbd_has_epo(void)
+{
+ return g_qepo_bd_has_epo;
+}
+
+int gps_mnl_qga_has_epo(void)
+{
+ return g_qepo_ga_has_epo;
+}
+
+ /*****************************************************************************
+ * FUNCTION
+ * gps_mnl_epo_get_file_size
+ * DESCRIPTION
+ * Get the file size
+ * PARAMETERS
+ * [IN] fd: The file description
+ * RETURNS
+ * File size
+ *****************************************************************************/
+int gps_mnl_epo_get_file_size(int fd)
+{
+ int u4FileSize;
+
+ if (fd == 0)
+ {
+ return -1;
+ }
+
+ u4FileSize = lseek(fd, 0, SEEK_END);
+
+ if (-1 == u4FileSize) { //lseek fail
+ LOGE("lseek end error(%s)\n",strerror(errno));
+ return -1;
+ }
+
+ if (-1 == lseek(fd, 0, SEEK_SET)) { //Back to the start of file
+ LOGE("lseek set error(%s)\n",strerror(errno));
+ return -1;
+ }
+
+ return u4FileSize;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * gps_mnl_bd_qepo_init
+ * DESCRIPTION
+ * Reset the init condition of BD QEPO
+ * PARAMETERS
+ * None
+ * RETURNS
+ * None
+ *****************************************************************************/
+void gps_mnl_bd_qepo_init(void)
+{
+ g_qepo_bd_has_epo = MTK_GPS_TRUE; //This flag to indentify the QBD.DAT file on server is valid or not, valid when init
+ g_qepo_bd_file_size_correct = MTK_GPS_TRUE; //The file size is correct or not, correct in init
+ g_qepo_bd_file_time_correct = MTK_GPS_TRUE; //The BD QEPO file time is correct or not, correct in init
+}
+
+void gps_mnl_ga_qepo_init(void)
+{
+ g_qepo_ga_has_epo = MTK_GPS_TRUE; //This flag to indentify the QGA.DAT file on server is valid or not, valid when init
+ g_qepo_ga_file_size_correct = MTK_GPS_TRUE; //The file size is correct or not, correct in init
+ g_qepo_ga_file_time_correct = MTK_GPS_TRUE; //The GA QEPO file time is correct or not, correct in init
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * is_quarter_epo_bd_on_server_valid
+ * DESCRIPTION
+ * Judge the Beidou QEPO file on server is valid or not
+ * if invalid, will retry downloading.
+ * Valid: HAS_EPO flag is true && the time is correct
+ * PARAMETERS
+ * None
+ * RETURNS
+ * MTK_GPS_TRUE; MTK_GPS_FALSE
+ *****************************************************************************/
+static int is_quarter_epo_bd_on_server_valid(void) {
+ if(g_qepo_bd_file_time_correct == MTK_GPS_TRUE &&
+ g_qepo_bd_has_epo == MTK_GPS_TRUE){
+ return MTK_GPS_TRUE;
+ }else{
+ return MTK_GPS_FALSE;
+ }
+}
+
+static int is_quarter_epo_ga_on_server_valid(void) {
+ if(g_qepo_ga_file_time_correct == MTK_GPS_TRUE &&
+ g_qepo_ga_has_epo == MTK_GPS_TRUE){
+ return MTK_GPS_TRUE;
+ }else{
+ return MTK_GPS_FALSE;
+ }
+}
+
+ /*****************************************************************************
+ * FUNCTION
+ * is_quarter_epo_bd_valid
+ * DESCRIPTION
+ * Judge the Beidou QEPO file of current download is valid or not
+ * if invalid, will retry downloading.
+ * Valid: file open successfully && get HAS_EPO flag successfully && get start time successfully
+ * && request time is in the valid durration of current Beidou QEPO file (start time+6H).
+ * PARAMETERS
+ * None
+ * RETURNS
+ * EPO_DOWNLOAD_RESULT_FAIL; EPO_DOWNLOAD_RESULT_SUCCESS
+ *****************************************************************************/
+static int is_quarter_epo_bd_valid(void) {
+ unsigned int u4GpsSecs_start; // GPS seconds
+ time_t current_qbd_start_time_utc_s; // UTC seconds
+ time_t current_rqst_time_utc_s;
+ time_t current_dl_time_utc_s;
+ UINT32 bd_header_data[MTK_EPO_ONE_SV_SIZE/4] = {0};
+ int file_size = 0;
+ int sv_cnt = 0;
+ int sv_cnt_ext = 0;
+
+ int fd = 0;
+ int ret = EPO_DOWNLOAD_RESULT_FAIL;
+
+ fd = open(QEPO_BD_UPDATE_FILE, O_RDONLY);
+ if (fd < 0) {
+ /*Something goes wrong, set HAS_EPO & time correct flag to true for next downloading*/
+ g_qepo_bd_has_epo = MTK_GPS_TRUE; //This flag to indentify the QBD.DAT file on server is valid or not
+ g_qepo_bd_file_size_correct = MTK_GPS_FALSE;
+ g_qepo_bd_file_time_correct = MTK_GPS_TRUE;
+
+ LOGE("Open QEPO_BD fail(%s), return\n",strerror(errno));
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ goto func_exit;
+ } else {
+ LOGD_ENG("gps_time.wn, tow %d, %d\n", gps_time.wn, gps_time.tow);
+ GpsToUtcTime(gps_time.wn, gps_time.tow, ¤t_rqst_time_utc_s);
+ LOGD("Request GPS time: %s", ctime(¤t_rqst_time_utc_s));
+
+ gps_mnl_set_qbd_latest_dl_time(current_rqst_time_utc_s);
+
+ if(mtk_gps_sys_qepo_bd_get_header(fd, bd_header_data)){
+ /*Something goes wrong, set HAS_EPO & time correct flag to true for next downloading*/
+ g_qepo_bd_has_epo = MTK_GPS_TRUE; //This flag to indentify the QBD.DAT file on server is valid or not
+ g_qepo_bd_file_size_correct = MTK_GPS_FALSE;
+ g_qepo_bd_file_time_correct = MTK_GPS_TRUE;
+
+ LOGD_ENG("qepo bd get header fail, return\n");
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ goto func_exit;
+ }
+
+ //Check HAS_EPO flag
+ mtk_gps_sys_qepo_bd_has_epo(bd_header_data[QEPO_HEADER_HAS_EPO_FLAG_INDX], &g_qepo_bd_has_epo);
+ mtk_gps_sys_qepo_bd_get_sv_cnt(bd_header_data[QEPO_HEADER_SV_CNT_INDX], &sv_cnt);
+ mtk_gps_sys_qepo_bd_get_sv_cnt(bd_header_data[QEPO_HEADER_SV_CNT_EXT_INDX], &sv_cnt_ext);
+ sv_cnt += sv_cnt_ext;
+
+ //Check file size
+ file_size = gps_mnl_epo_get_file_size(fd);
+ LOGD_ENG("qepo bd file size:%d, sv cnt:%d\n",file_size, sv_cnt);
+ if((file_size==0) || ((file_size%MTK_EPO_ONE_SV_SIZE != 0)||
+ (sv_cnt != (file_size/MTK_EPO_ONE_SV_SIZE-1)))){ //The BD QEPO file size and sv cnt not match, something goes wrong
+ LOGE("qepo bd file size check error\n");
+ g_qepo_bd_file_size_correct = MTK_GPS_FALSE;
+ }else{
+ g_qepo_bd_file_size_correct = MTK_GPS_TRUE;
+ }
+
+ //Check time
+ if (mtk_gps_sys_epo_bd_period_start(fd, &u4GpsSecs_start, ¤t_qbd_start_time_utc_s)) {
+ /*Something goes wrong, set time correct flag to true for next downloading*/
+ g_qepo_bd_file_time_correct = MTK_GPS_TRUE;
+
+ LOGE("Read QEPO file failed\n");
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ goto func_exit;
+ } else {
+ LOGD_ENG("The Start time of QEPO file is %lld\n", (long long)current_qbd_start_time_utc_s);
+ LOGD("The start time of QEPO file is %s\n", ctime(¤t_qbd_start_time_utc_s));
+ current_dl_time_utc_s = current_rqst_time_utc_s+(time((time_t *)NULL)-gps_time.sys_time);
+ LOGD_ENG("Time after download: %s\n", ctime(¤t_dl_time_utc_s));
+ if ((current_dl_time_utc_s >= current_qbd_start_time_utc_s) && (current_dl_time_utc_s < ((6*60*60) + current_qbd_start_time_utc_s))) {
+ g_qepo_bd_file_time_correct = MTK_GPS_TRUE;
+ }else{
+ LOGE("qepo bd file time check error\n");
+ g_qepo_bd_file_time_correct = MTK_GPS_FALSE;
+ }
+ }
+ }
+
+ if(g_qepo_bd_has_epo == MTK_GPS_TRUE
+ && g_qepo_bd_file_size_correct == MTK_GPS_TRUE
+ && g_qepo_bd_file_time_correct == MTK_GPS_TRUE)
+ {
+ ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+ }else{
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ }
+
+func_exit:
+ if(fd >= 0){
+ close(fd);
+ }
+
+ return ret;
+}
+
+static int is_quarter_epo_ga_valid(void) {
+ unsigned int u4GpsSecs_start; // GPS seconds
+ time_t current_qga_start_time_utc_s; // UTC seconds
+ time_t current_rqst_time_utc_s;
+ time_t current_dl_time_utc_s;
+ UINT32 ga_header_data[MTK_EPO_ONE_SV_SIZE/4] = {0};
+ int file_size = 0;
+ int sv_cnt = 0;
+ int sv_cnt_ext = 0;
+
+ int fd = 0;
+ int ret = EPO_DOWNLOAD_RESULT_FAIL;
+
+ fd = open(QEPO_GA_UPDATE_FILE, O_RDONLY);
+ if (fd < 0) {
+ /*Something goes wrong, set HAS_EPO & time correct flag to true for next downloading*/
+ g_qepo_ga_has_epo = MTK_GPS_TRUE; //This flag to indentify the QGA.DAT file on server is valid or not
+ g_qepo_ga_file_size_correct = MTK_GPS_FALSE;
+ g_qepo_ga_file_time_correct = MTK_GPS_TRUE;
+
+ LOGE("Open QEPO_GA fail(%s), return\n",strerror(errno));
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ goto func_exit;
+ } else {
+ LOGD_ENG("gps_time.wn, tow %d, %d\n", gps_time.wn, gps_time.tow);
+ GpsToUtcTime(gps_time.wn, gps_time.tow, ¤t_rqst_time_utc_s);
+ LOGD("Request GPS time: %s", ctime(¤t_rqst_time_utc_s));
+
+ gps_mnl_set_qga_latest_dl_time(current_rqst_time_utc_s);
+
+ if(mtk_gps_sys_qepo_ga_get_header(fd, ga_header_data)){
+ /*Something goes wrong, set HAS_EPO & time correct flag to true for next downloading*/
+ g_qepo_ga_has_epo = MTK_GPS_TRUE; //This flag to indentify the QGA.DAT file on server is valid or not
+ g_qepo_ga_file_size_correct = MTK_GPS_FALSE;
+ g_qepo_ga_file_time_correct = MTK_GPS_TRUE;
+
+ LOGD_ENG("qepo ga get header fail, return\n");
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ goto func_exit;
+ }
+
+ //Check HAS_EPO flag
+ mtk_gps_sys_qepo_ga_has_epo(ga_header_data[QEPO_HEADER_HAS_EPO_FLAG_INDX], &g_qepo_ga_has_epo);
+ mtk_gps_sys_qepo_ga_get_sv_cnt(ga_header_data[QEPO_HEADER_SV_CNT_INDX], &sv_cnt);
+ mtk_gps_sys_qepo_ga_get_sv_cnt(ga_header_data[QEPO_HEADER_SV_CNT_EXT_INDX], &sv_cnt_ext);
+ sv_cnt += sv_cnt_ext;
+
+ //Check file size
+ file_size = gps_mnl_epo_get_file_size(fd);
+ LOGD_ENG("qepo ga file size:%d, sv cnt:%d\n",file_size, sv_cnt);
+ if((file_size==0) || ((file_size%MTK_EPO_ONE_SV_SIZE != 0)||
+ (sv_cnt != (file_size/MTK_EPO_ONE_SV_SIZE-1)))){ //The GA QEPO file size and sv cnt not match, something goes wrong
+ LOGE("qepo ga file size check error\n");
+ g_qepo_ga_file_size_correct = MTK_GPS_FALSE;
+ }else{
+ g_qepo_ga_file_size_correct = MTK_GPS_TRUE;
+ }
+
+ //Check time
+ if (mtk_gps_sys_epo_ga_period_start(fd, &u4GpsSecs_start, ¤t_qga_start_time_utc_s)) {
+ /*Something goes wrong, set time correct flag to true for next downloading*/
+ g_qepo_ga_file_time_correct = MTK_GPS_TRUE;
+
+ LOGE("Read QEPO file failed\n");
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ goto func_exit;
+ } else {
+ LOGD_ENG("The Start time of QEPO file is %lld\n", (long long)current_qga_start_time_utc_s);
+ LOGD("The start time of QEPO file is %s\n", ctime(¤t_qga_start_time_utc_s));
+ current_dl_time_utc_s = current_rqst_time_utc_s+(time((time_t *)NULL)-gps_time.sys_time);
+ LOGD_ENG("Time after download: %s\n", ctime(¤t_dl_time_utc_s));
+ if ((current_dl_time_utc_s >= current_qga_start_time_utc_s) && (current_dl_time_utc_s < ((6*60*60) + current_qga_start_time_utc_s))) {
+ g_qepo_ga_file_time_correct = MTK_GPS_TRUE;
+ }else{
+ LOGE("qepo ga file time check error\n");
+ g_qepo_ga_file_time_correct = MTK_GPS_FALSE;
+ }
+ }
+ }
+
+ if(g_qepo_ga_has_epo == MTK_GPS_TRUE
+ && g_qepo_ga_file_size_correct == MTK_GPS_TRUE
+ && g_qepo_ga_file_time_correct == MTK_GPS_TRUE)
+ {
+ ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+ }else{
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ }
+
+func_exit:
+ if(fd >= 0){
+ close(fd);
+ }
+
+ return ret;
+}
+#if 0
+static void
+gps_download_quarter_epo_file_name(int count) {
+ if (gps_epo_type == 1) {
+ if (count == 1) {
+ strncpy(quarter_epo_file_name, "QG_R_1.DAT", GPS_EPO_FILE_LEN);
+ } else if (count == 2) {
+ strncpy(quarter_epo_file_name, "QG_R_2.DAT", GPS_EPO_FILE_LEN);
+ } else if (count == 3) {
+ strncpy(quarter_epo_file_name, "QG_R_3.DAT", GPS_EPO_FILE_LEN);
+ } else if (count == 4) {
+ strncpy(quarter_epo_file_name, "QG_R_4.DAT", GPS_EPO_FILE_LEN);
+ } else if (count == 5) {
+ strncpy(quarter_epo_file_name, "QG_R_5.DAT", GPS_EPO_FILE_LEN);
+ }
+ LOGD("quarter_epo_file_name=%s\n", quarter_epo_file_name);
+ } else if (gps_epo_type == 0) {
+ if (count == 1) {
+ strncpy(quarter_epo_file_name, "QG_R_1.DAT", GPS_EPO_FILE_LEN);
+ } else if (count == 2) {
+ strncpy(quarter_epo_file_name, "QG_R_2.DAT", GPS_EPO_FILE_LEN);
+ } else if (count == 3) {
+ strncpy(quarter_epo_file_name, "QG_R_3.DAT", GPS_EPO_FILE_LEN);
+ } else if (count == 4) {
+ strncpy(quarter_epo_file_name, "QG_R_4.DAT", GPS_EPO_FILE_LEN);
+ } else if (count == 5) {
+ strncpy(quarter_epo_file_name, "QG_R_5.DAT", GPS_EPO_FILE_LEN);
+ }
+ LOGD("quarter_epo_file_name=%s\n", quarter_epo_file_name);
+ }
+}
+#endif
+void gps_mnl_set_gps_time(int wn, int tow, int sys_time) {
+ gps_time.wn = wn;
+ gps_time.tow = tow;
+ gps_time.sys_time = sys_time;
+}
+static void quarter_epo_download_process(void) {
+ // LOGD("quarter_epo_download_process begin");
+/* int index = 1;
+ INT32 SecofDay = gps_time.tow % 86400;
+
+ if ((SecofDay > 300) && (SecofDay <= 21900)) {
+ index = 1;
+ } else if ((SecofDay > 21900) && (SecofDay <= 43500)) {
+ index = 2;
+ } else if ((SecofDay > 43500) && (SecofDay <= 65100)) {
+ index = 3;
+ } else if ((SecofDay > 65100) && (SecofDay <= 85500)) {
+ index = 4;
+ } else if ((SecofDay <= 300) || (SecofDay > 85500)) {
+ if (server_not_updated) {
+ index = 4;
+ } else {
+ index = 5;
+ }
+ }
+
+ if (pre_day) {
+ index = 5;
+ }
+ LOGD("SecofDay = %d , index = %d\n", SecofDay, index);
+ gps_download_quarter_epo_file_name(index);*/
+ strncpy(quarter_epo_file_name, "QG_R.DAT", sizeof(quarter_epo_file_name));
+ curl_easy_download_quarter_epo();
+}
+
+static void quarter_epo_bd_download_process(void) {
+ strncpy(quarter_epo_bd_file_name, "QBD2.DAT",sizeof(quarter_epo_bd_file_name));
+ strncpy(quarter_epo_bd_md_file_name, "QBD2.MD5",sizeof(quarter_epo_bd_md_file_name));
+ curl_easy_download_quarter_epo_bd();
+}
+
+static void quarter_epo_ga_download_process(void) {
+ strncpy(quarter_epo_ga_file_name, "QGA.DAT",sizeof(quarter_epo_ga_file_name));
+ curl_easy_download_quarter_epo_ga();
+}
+
+static int qepo_file_update_impl() {
+ int try_time = QEPO_GR_DL_RETRY_TIME; // for network issue download failed retry.
+ int qepo_valid = EPO_DOWNLOAD_RESULT_FAIL;
+
+ //LOGD("qepo_download_finished = 0\n");
+ quarter_epo_download_process();
+ while (((qepo_valid = is_quarter_epo_valid()) == EPO_DOWNLOAD_RESULT_FAIL)
+ && (try_time > 0) && is_network_connected()) {
+ try_time--;
+
+ LOGD("qepo download failed try again, try_time = %d\n", try_time);
+ quarter_epo_download_process();
+ }
+ LOGD_ENG("try time is %d, qepo_valid is %d\n", try_time, qepo_valid);
+ if (try_time < QEPO_GR_DL_RETRY_TIME) {
+ try_time = QEPO_GR_DL_RETRY_TIME;
+ }
+ if (server_not_updated) {
+ Qepo_res = CURLE_RECV_ERROR; // server has not updated
+ }
+ return qepo_valid; // success
+}
+
+static int qepo_bd_file_update_impl() {
+ int qepo_bd_valid = EPO_DOWNLOAD_RESULT_FAIL;
+
+ /*Download directly.
+ *If the notwork is unavailable, will download fail, is_quarter_epo_bd_valid() will return FAIL.
+ *If the network is available and download successfully, is_quarter_epo_bd_valid will return TRUE*/
+ LOGD_ENG("qepo download start, network conncet:%d...\n",is_network_connected());
+ quarter_epo_bd_download_process();
+
+ qepo_bd_valid = is_quarter_epo_bd_valid();
+ LOGD("qepo_bd_valid is %d, has epo:%d, file time correct:%d, file size correct:%d, invalid download cnt:%d\n",
+ qepo_bd_valid,g_qepo_bd_has_epo,g_qepo_bd_file_time_correct,g_qepo_bd_file_size_correct, g_qepo_bd_invalid_dl_cnt);
+ if((is_quarter_epo_bd_on_server_valid() == MTK_GPS_FALSE) ||
+ (g_qepo_bd_file_size_correct == MTK_GPS_FALSE))
+ {
+ if(g_qepo_bd_invalid_dl_cnt == 0)
+ {
+ gps_mnl_set_qbd_first_invalid_dl_time(gps_mnl_get_qbd_latest_dl_time());//record the firest invalid download times
+ }
+ g_qepo_bd_invalid_dl_cnt++;
+ }
+
+ return qepo_bd_valid;
+}
+
+static int qepo_ga_file_update_impl() {
+ int qepo_ga_valid = EPO_DOWNLOAD_RESULT_FAIL;
+
+ /*Download directly.
+ *If the notwork is unavailable, will download fail, is_quarter_epo_ga_valid() will return FAIL.
+ *If the network is available and download successfully, is_quarter_epo_ga_valid will return TRUE*/
+ LOGD_ENG("qepo download start, network conncet:%d...\n",is_network_connected());
+ quarter_epo_ga_download_process();
+
+ qepo_ga_valid = is_quarter_epo_ga_valid();
+ LOGD("qepo_ga_valid is %d, has epo:%d, file time correct:%d, file size correct:%d, invalid downlaod cnt:%d\n",
+ qepo_ga_valid,g_qepo_ga_has_epo,g_qepo_ga_file_time_correct,g_qepo_ga_file_size_correct, g_qepo_ga_invalid_dl_cnt);
+ if((is_quarter_epo_ga_on_server_valid() == MTK_GPS_FALSE) ||
+ (g_qepo_ga_file_size_correct == MTK_GPS_FALSE))
+ {
+ if(g_qepo_ga_invalid_dl_cnt == 0)
+ {
+ gps_mnl_set_qga_first_invalid_dl_time(gps_mnl_get_qga_latest_dl_time());//record the firest invalid download times
+ }
+ g_qepo_ga_invalid_dl_cnt++;
+ }
+
+ return qepo_ga_valid;
+}
+
+void qepo_update_quarter_epo_file(int qepo_valid) {
+ unsigned int qdownload_status = MTK_QEPO_RSP_DOWNLOAD_FAIL;
+
+ if (qepo_valid == EPO_DOWNLOAD_RESULT_SUCCESS) {
+ if (mtk_agps_agent_qepo_file_update() == MTK_GPS_ERROR) {
+ qdownload_status = MTK_QEPO_RSP_UPDATE_FAIL;
+ } else {
+ qdownload_status = MTK_QEPO_RSP_UPDATE_SUCCESS;
+ unlink(QEPO_UPDATE_HAL);
+ }
+ } else {
+ qdownload_status = Qepo_res;
+ if (qdownload_status > 0) {
+ qdownload_status = MTK_QEPO_RSP_DOWNLOAD_FAIL;
+ }
+ }
+
+ qdownload_status |= ((AGT_QEPO_GP_BIT|AGT_QEPO_GL_BIT)<< MTK_QEPO_RSP_BIT_NUM);
+ LOGD("qdownload_status = 0x%x\n", qdownload_status);
+ if (MTK_GPS_ERROR == (mtk_agps_set_param (MTK_PARAM_QEPO_DOWNLOAD_RESPONSE,
+ &qdownload_status, MTK_MOD_DISPATCHER, MTK_MOD_AGENT))) {
+ LOGE("GPS QEPO update fail\n");
+ }
+}
+
+void qepo_update_quarter_epo_bd_file(int qepo_bd_valid) {
+ unsigned int qdownload_bd_status = MTK_QEPO_RSP_DOWNLOAD_FAIL;
+
+ if (qepo_bd_valid == EPO_DOWNLOAD_RESULT_SUCCESS) {
+ if (MTK_GPS_ERROR == mtk_agps_agent_qepo_bd_file_update()) {
+ qdownload_bd_status = MTK_QEPO_RSP_UPDATE_FAIL;
+ LOGE("qdownload_bd_status = %d, download fail\n", qdownload_bd_status);
+ } else {
+ qdownload_bd_status = MTK_QEPO_RSP_UPDATE_SUCCESS;
+ unlink(QEPO_BD_UPDATE_FILE);
+ }
+ } else {
+ if((is_quarter_epo_bd_on_server_valid() == MTK_GPS_TRUE) && (g_qepo_bd_file_size_correct == MTK_GPS_FALSE))
+ {
+ if (MTK_GPS_ERROR == mtk_agps_agent_qepo_bd_file_update()) {
+ qdownload_bd_status = MTK_QEPO_RSP_UPDATE_FAIL;
+ LOGE("qdownload_bd_status = %d, download fail\n", qdownload_bd_status);
+ } else {
+ qdownload_bd_status = MTK_QEPO_RSP_SIZE_FAIL;
+ unlink(QEPO_BD_UPDATE_FILE);
+ }
+ }
+ else
+ {
+ qdownload_bd_status = MTK_QEPO_RSP_DOWNLOAD_FAIL;
+ }
+ }
+
+ qdownload_bd_status = qdownload_bd_status |(AGT_QEPO_BD_BIT<< MTK_QEPO_RSP_BIT_NUM); // high 4 bit
+ if (MTK_GPS_ERROR == (mtk_agps_set_param (MTK_PARAM_QEPO_DOWNLOAD_RESPONSE,
+ &qdownload_bd_status, MTK_MOD_DISPATCHER, MTK_MOD_AGENT)) ) {
+ LOGE("GPS QEPO_BD update fail\n");
+ }
+}
+
+void qepo_update_quarter_epo_ga_file(int qepo_ga_valid) {
+ unsigned int qdownload_ga_status = MTK_QEPO_RSP_DOWNLOAD_FAIL;
+
+ if (qepo_ga_valid == EPO_DOWNLOAD_RESULT_SUCCESS) {
+ if (MTK_GPS_ERROR == mtk_agps_agent_qepo_ga_file_update()) {
+ qdownload_ga_status = MTK_QEPO_RSP_UPDATE_FAIL;
+ LOGE("qdownload_ga_status = %d, download fail\n", qdownload_ga_status);
+ } else {
+ qdownload_ga_status = MTK_QEPO_RSP_UPDATE_SUCCESS;
+ unlink(QEPO_GA_UPDATE_FILE);
+ }
+ } else {
+ if((is_quarter_epo_ga_on_server_valid() == MTK_GPS_TRUE) && (g_qepo_ga_file_size_correct == MTK_GPS_FALSE))
+ {
+ if (MTK_GPS_ERROR == mtk_agps_agent_qepo_ga_file_update()) {
+ qdownload_ga_status = MTK_QEPO_RSP_UPDATE_FAIL;
+ LOGE("qdownload_ga_status = %d, download fail\n", qdownload_ga_status);
+ } else {
+ qdownload_ga_status = MTK_QEPO_RSP_SIZE_FAIL;
+ unlink(QEPO_GA_UPDATE_FILE);
+ }
+ } else {
+ qdownload_ga_status = MTK_QEPO_RSP_DOWNLOAD_FAIL;
+ }
+ }
+
+ qdownload_ga_status = qdownload_ga_status |(AGT_QEPO_GA_BIT<< MTK_QEPO_RSP_BIT_NUM); // high 4 bit
+ if (MTK_GPS_ERROR == (mtk_agps_set_param (MTK_PARAM_QEPO_DOWNLOAD_RESPONSE,
+ &qdownload_ga_status, MTK_MOD_DISPATCHER, MTK_MOD_AGENT)) ) {
+ LOGE("GPS QEPO_GA update fail\n");
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// MAIN -> EPO Download (handlers)
+static int mnld_qepo_download() {
+ //LOGD("mnld_qepo_download");
+
+ qepo_download_finished = 0;
+ int ret = qepo_file_update_impl();
+ qepo_download_finished = 1;
+ qepo_dl_res = ret;
+ if (mnld_qepo_download_done(ret) == -1) {
+ LOGE("mnld_qepo_download_done failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ return ret;
+}
+
+static int mnld_qepo_bd_download() {
+ time_t current_rqst_time_utc_s = 0;
+ time_t qbd_rqst_time_diff = 0;
+ int ret = EPO_DOWNLOAD_RESULT_FAIL;
+
+ GpsToUtcTime(gps_time.wn, gps_time.tow, ¤t_rqst_time_utc_s);
+
+ qbd_rqst_time_diff = current_rqst_time_utc_s/SECONDS_PER_HOUR - gps_mnl_get_qbd_first_invalid_dl_time()/SECONDS_PER_HOUR;
+ LOGD_ENG("QBD current request time: %ld, latest invalid dl time:%ld, time_diff:%ld,\n", current_rqst_time_utc_s,gps_mnl_get_qbd_first_invalid_dl_time(),qbd_rqst_time_diff);
+ if(qbd_rqst_time_diff != 0){ //Rest the count value hourly
+ g_qepo_bd_invalid_dl_cnt = 0;
+ LOGD_ENG("reset invalid download cnt\n");
+ }
+
+ //qbd_rqst_time_diff = current_rqst_time_utc_s/SECONDS_PER_HOUR - gps_mnl_get_qbd_latest_dl_time()/SECONDS_PER_HOUR;
+ if(g_qepo_bd_invalid_dl_cnt < QEPO_BD_DL_RETRY_TIME)//The invalid download count of one hour
+ {
+
+ qepo_bd_download_finished = 0;
+ ret = qepo_bd_file_update_impl();
+ qepo_bd_download_finished = 1;
+ }else{
+ usleep(QEPO_BD_INVALID_SLEEP);
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ LOGW("Download BD QEPO fail, download in next hour!(has epo:%d, time correct:%d, size correct:%d, invalid download cnt:%d)\n", g_qepo_bd_has_epo,g_qepo_bd_file_time_correct,g_qepo_bd_file_size_correct,g_qepo_bd_invalid_dl_cnt);
+ }
+
+ qepo_bd_dl_res = ret;
+
+ if (mnld_qepo_bd_download_done(ret) == -1) {
+ LOGE("mnld_qepo_bd_download_done failed because of safe_sendto fail ,strerror:%s \n", strerror(errno));
+ }
+ return ret;
+}
+
+static int mnld_qepo_ga_download() {
+ time_t current_rqst_time_utc_s = 0;
+ time_t qga_rqst_time_diff = 0;
+ int ret = EPO_DOWNLOAD_RESULT_FAIL;
+
+ GpsToUtcTime(gps_time.wn, gps_time.tow, ¤t_rqst_time_utc_s);
+
+ qga_rqst_time_diff = current_rqst_time_utc_s/SECONDS_PER_HOUR - gps_mnl_get_qga_first_invalid_dl_time()/SECONDS_PER_HOUR;
+ LOGD_ENG("QGA current request time: %ld, latest invalid dl time:%ld, time_diff:%ld,\n", current_rqst_time_utc_s,gps_mnl_get_qga_first_invalid_dl_time(),qga_rqst_time_diff);
+ if(qga_rqst_time_diff != 0){ //Rest the count value hourly
+ g_qepo_ga_invalid_dl_cnt = 0;
+ LOGD_ENG("reset invalid download cnt\n");
+ }
+
+ //qbd_rqst_time_diff = current_rqst_time_utc_s/SECONDS_PER_HOUR - gps_mnl_get_qbd_latest_dl_time()/SECONDS_PER_HOUR;
+ if(g_qepo_ga_invalid_dl_cnt < QEPO_GA_DL_RETRY_TIME)//The invalid download count of one hour
+ {
+
+ qepo_ga_download_finished = 0;
+ ret = qepo_ga_file_update_impl();
+ qepo_ga_download_finished = 1;
+ }else{
+ usleep(QEPO_GA_INVALID_SLEEP);
+ ret = EPO_DOWNLOAD_RESULT_FAIL;
+ LOGW("Download GA QEPO fail, download in next hour!(has epo:%d, time correct:%d, size correct:%d, invalid download cnt:%d)\n", g_qepo_ga_has_epo,g_qepo_ga_file_time_correct,g_qepo_ga_file_size_correct,g_qepo_ga_invalid_dl_cnt);
+ }
+
+ qepo_ga_dl_res = ret;
+
+ if(-1 == mnld_qepo_ga_download_done(ret)) {
+ LOGW("mnld_qepo_ga_download_done fail!");
+ }
+ return ret;
+}
+
+int is_qepo_download_finished() {
+ return qepo_download_finished;
+}
+
+int is_qepo_bd_download_finished() {
+ return qepo_bd_download_finished;
+}
+
+int is_qepo_ga_download_finished() {
+ return qepo_ga_download_finished;
+}
+
+static int qepo_event_hdlr(int fd) {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ main2qepo_event cmd;
+ int read_len;
+
+ read_len = safe_recvfrom(fd, buff, sizeof(buff));
+ if (read_len <= 0) {
+ LOGE("qepo_event_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+ return -1;
+ }
+
+ cmd = get_int(buff, &offset, sizeof(buff));
+ switch (cmd) {
+ case MAIN2QEPO_EVENT_START: {
+ LOGD_ENG("mnld_qepo_download() before");
+ // need to call mnld_qepo_download_done() when QEPO download is done
+ mnld_qepo_download();
+ LOGD_ENG("mnld_qepo_download() after");
+ break;
+ }
+ case MAIN2QEPO_BD_EVENT_START: {
+ LOGD_ENG("mnld_qepo_bd_download() before");
+ mnld_qepo_bd_download();
+ LOGD_ENG("mnld_qepo_bd_download() after");
+ break;
+ }
+ case MAIN2QEPO_GA_EVENT_START: {
+ LOGD_ENG("mnld_qepo_ga_download() before");
+ mnld_qepo_ga_download();
+ LOGD_ENG("mnld_qepo_ga_download() after");
+ break;
+ }
+
+ default: {
+ LOGE("qepo_event_hdlr() unknown cmd=%d", cmd);
+ return -1;
+ }
+ }
+ return 0;
+}
+#if 0
+static void qepo_downloader_thread_timeout() {
+ if (mnld_timeout_ne_enabled() == false) {
+ LOGE("qepo_downloader_thread_timeout() dump and exit.");
+ gps_dbg_log_exit_flush(0);
+ mnld_block_exit();
+ } else {
+ LOGE("qepo_downloader_thread_timeout() crash here for debugging");
+ CRASH_TO_DEBUG();
+ }
+}
+#endif
+static void* qepo_downloader_thread(void *arg) {
+ #define MAX_EPOLL_EVENT 50
+ //timer_t hdlr_timer = init_timer(qepo_downloader_thread_timeout);
+ struct epoll_event events[MAX_EPOLL_EVENT];
+ UNUSED(arg);
+
+ int epfd = epoll_create(MAX_EPOLL_EVENT);
+ if (epfd == -1) {
+ LOGE("qepo_downloader_thread() epoll_create failure reason=[%s]%d",
+ strerror(errno), errno);
+ return 0;
+ }
+
+ if (epoll_add_fd(epfd, g_fd_qepo) == -1) {
+ LOGE("qepo_downloader_thread() epoll_add_fd() failed for g_fd_qepo failed");
+ return 0;
+ }
+
+ while (1) {
+ int i;
+ int n;
+ LOGD_ENG("qepo_downloader_thread wait");
+ memset(events, 0, sizeof(events));
+ n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+ if (n == -1) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ LOGE("qepo_downloader_thread() epoll_wait failure reason=[%s]%d",
+ strerror(errno), errno);
+ return 0;
+ }
+ }
+ mnld_wake_lock_take();
+ //start_timer(hdlr_timer, MNLD_QEPO_HANDLER_TIMEOUT);
+ for (i = 0; i < n; i++) {
+ if (events[i].data.fd == g_fd_qepo) {
+ if (events[i].events & EPOLLIN) {
+ qepo_event_hdlr(g_fd_qepo);
+ }
+ } else {
+ LOGE("qepo_downloader_thread() unknown fd=%d",
+ events[i].data.fd);
+ }
+ }
+ //stop_timer(hdlr_timer);
+ mnld_wake_lock_give();
+ }
+
+ LOGE("qepo_downloader_thread() exit");
+ return 0;
+}
+
+int qepo_downloader_start() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ if (qepo_download_finished == 0) {
+ LOGW("qepo downloading... abort requst msg!");
+ return 0;
+ }
+ put_int(buff, &offset, MAIN2QEPO_EVENT_START);
+ return safe_sendto(MNLD_QEPO_DOWNLOAD_SOCKET, buff, offset);
+}
+
+
+int qepo_bd_downloader_start() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ if (qepo_bd_download_finished == 0) {
+ LOGW("qepo bd downloading... abort requst msg!");
+ return 0;
+ }
+ put_int(buff, &offset, MAIN2QEPO_BD_EVENT_START);
+ return safe_sendto(MNLD_QEPO_DOWNLOAD_SOCKET, buff, offset);
+}
+
+int qepo_ga_downloader_start() {
+ char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+ int offset = 0;
+ if (qepo_ga_download_finished == 0) {
+ LOGW("qepo ga downloading... abort requst msg!");
+ return 0;
+ }
+ put_int(buff, &offset, MAIN2QEPO_GA_EVENT_START);
+ return safe_sendto(MNLD_QEPO_DOWNLOAD_SOCKET, buff, offset);
+}
+
+int qepo_downloader_init() {
+ pthread_t pthread_qepo;
+
+ g_fd_qepo = socket_bind_udp(MNLD_QEPO_DOWNLOAD_SOCKET);
+ if (g_fd_qepo < 0) {
+ LOGE("socket_bind_udp(MNLD_QEPO_DOWNLOAD_SOCKET) failed");
+ return -1;
+ }
+
+ pthread_create(&pthread_qepo, NULL, qepo_downloader_thread, NULL);
+ gps_mnl_bd_qepo_init();
+ return 0;
+}
+
+void qepo_invalid_dl_cnt_clear(void) {
+ g_qepo_bd_invalid_dl_cnt = 0;
+ g_qepo_ga_invalid_dl_cnt = 0;
+}
diff --git a/src/connectivity/gps/2.0/mtk_mnld/utility/inc/data_coder.h b/src/connectivity/gps/2.0/mtk_mnld/utility/inc/data_coder.h
new file mode 100644
index 0000000..29a6cf2
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/utility/inc/data_coder.h
@@ -0,0 +1,32 @@
+#ifndef __DATA_CODER_H__
+#define __DATA_CODER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char get_byte(char* buff, int* offset, int src_len);
+short get_short(char* buff, int* offset, int src_len);
+int get_int(char* buff, int* offset, int src_len);
+long long get_long(char* buff, int* offset, int src_len);
+float get_float(char* buff, int* offset, int src_len);
+double get_double(char* buff, int* offset, int src_len);
+char* get_string(char* buff, int* offset, int src_len);
+char* get_string2(char* buff, int* offset, int src_len);
+int get_binary(char* buff, int* offset, char* output, int src_len, int des_len);
+
+void put_byte(char* buff, int* offset, const char input);
+void put_short(char* buff, int* offset, const short input);
+void put_int(char* buff, int* offset, const int input);
+void put_long(char* buff, int* offset, const long long input);
+void put_float(char* buff, int* offset, const float input);
+void put_double(char* buff, int* offset, const double input);
+void put_string(char* buff, int* offset, const char* input, int max_size);
+void put_binary(char* buff, int* offset, const char* input, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_lbs_utility.h b/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_lbs_utility.h
new file mode 100644
index 0000000..441af7b
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_lbs_utility.h
@@ -0,0 +1,335 @@
+#ifndef __MTK_LBS_UTILITY_H__
+#define __MTK_LBS_UTILITY_H__
+
+#include <time.h>
+#include <sys/time.h>
+#include <stdint.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include "gps_dbg_log.h"
+
+#include "mtk_mnld_log.h"
+
+#include "hal_mnl_interface_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************
+* Basic Utilities
+**************************************************/
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+#define CRASH_TO_DEBUG() \
+{\
+ int* crash = 0;\
+ gps_dbg_log_exit_flush(0);\
+ *crash = 100;\
+}
+
+#define DUMP_BYTES_PER_LINE 16
+#define DUMP_MAX_PRINT_LINE 10
+
+#define INVALID_TIMERID ((timer_t)-1)
+
+#define MNLD_DUMP_MEM(addr, len) do{\
+ int i = 0, j = 0;\
+ char print_buf[DUMP_BYTES_PER_LINE*5+1] = {0};\
+ unsigned int print_len = len;\
+ if(len > DUMP_MAX_PRINT_LINE*DUMP_BYTES_PER_LINE) {\
+ print_len = DUMP_MAX_PRINT_LINE*DUMP_BYTES_PER_LINE;\
+ }\
+ LOGD(">>>>>DUMP_START(addr:%p, len:%d, print_len:%ud)<<<<<", addr, len,print_len);\
+ for(i = 0; i < print_len; i+=DUMP_BYTES_PER_LINE) {\
+ memset(print_buf, 0, sizeof(print_buf));\
+ for(j=0;j<DUMP_BYTES_PER_LINE;j++) {\
+ sprintf(&print_buf[j*5], "0x%02x ", ((char *)addr)[i*DUMP_BYTES_PER_LINE+j]);\
+ print_buf[DUMP_BYTES_PER_LINE*5] = '\0';\
+ }\
+ LOGD("[%3d]:%s", i/DUMP_BYTES_PER_LINE, print_buf);\
+ }\
+ LOGD("<<<<<DUMP_STOP>>>>>");\
+}while(0)
+
+#if defined(__ANDROID_OS__)
+#define ANDROID_MNLD_PROP_SUPPORT 1
+#define MTK_GPS_NVRAM 1
+#elif defined(__LINUX_OS__)
+#define ANDROID_MNLD_PROP_SUPPORT 0
+#define MTK_GPS_NVRAM 0
+
+/**
+ * connect to peer named "name"
+ * returns fd or -1 on error
+ */
+int socket_local_client(const char *name, int type);
+/** Open a server-side UNIX domain datagram socket in the Linux non-filesystem
+ * namespace
+ *
+ * Returns fd on success, -1 on fail
+ */
+int socket_local_server(const char *name, int type);
+#endif
+
+
+#define MNLD_STRNCPY(dst,src,size) do{\
+ strncpy((char *)(dst), (char *)(src), (size - 1));\
+ (dst)[size - 1] = '\0';\
+ }while(0)
+
+#define MNLD_SPRINTF(buf,fmt,...) do{\
+ if(sprintf((char *)(buf), fmt,##__VA_ARGS__) < 0){\
+ LOGE("sprintf error occurred");\
+ }\
+ }while(0)
+
+#define MNLD_SNPRINTF(buf,len,fmt,...) do{\
+ if(snprintf((char *)(buf), len, fmt,##__VA_ARGS__) < 0){\
+ LOGE("snprintf error occurred");\
+ }\
+ }while(0)
+
+#define MNLD_VSNPRINTF(buf,len,fmt,...) do{\
+ if(vsnprintf((char *)(buf), len, fmt,##__VA_ARGS__) < 0){\
+ LOGE("vsnprintf error occurred");\
+ }\
+ }while(0)
+
+#define MNLD_FRINTF(buf,fmt,...) do{\
+ if(fprintf(buf, fmt,##__VA_ARGS__) < 0){\
+ LOGE("fprintf error occurred");\
+ }\
+ }while(0)
+
+#define MNLD_FCLOSE(fd) do{ \
+ if(fclose(fd) != 0) { \
+ LOGE("FUNC[%s], Line[%d], fclose fail, %s(%d)", __func__, __LINE__, strerror(errno), errno); \
+ } \
+}while(0)
+
+typedef struct sync_lock {
+ pthread_mutex_t mutx;
+ pthread_cond_t con;
+ int condtion;
+ int index;
+}SYNC_LOCK_T;
+
+void msleep(int interval);
+
+// in millisecond
+time_t get_tick();
+
+// in millisecond
+UINT64 get_time_in_millisecond();
+
+// -1 means failure
+int block_here();
+
+//exit block_here() and process will exit and restart
+void mnld_block_exit(void);
+
+/*************************************************
+* Timer
+**************************************************/
+typedef void (* timer_callback)();
+
+// -1 means failure
+timer_t init_timer_id(timer_callback cb, int id);
+
+// -1 means failure
+timer_t init_timer(timer_callback cb);
+
+// -1 means failure
+int start_timer(timer_t timerid, int milliseconds);
+
+// -1 means failure
+int stop_timer(timer_t timerid);
+
+// -1 means failure
+int deinit_timer(timer_t timerid);
+/*************************************************
+* Timer Alarm
+**************************************************/
+// -1 means failure
+int init_timer_alarm();
+
+// -1 means failure
+int init_timer_id_alarm(int id);
+
+// -1 means failure
+int stop_timer_alarm(int timerid);
+
+// -1 means failure
+int start_timer_alarm(int timerfd, int milliseconds);
+
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int epoll_add_fd(int epfd, int fd);
+
+// -1 failed
+int epoll_add_fd2(int epfd, int fd, uint32_t events);
+
+// -1 failed
+int epoll_del_fd(int epfd, int fd);
+
+int epoll_mod_fd(int epfd, int fd, uint32_t events);
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int socket_bind_udp(const char* path);
+
+int mnld_flp_to_mnld_fd_init(const char* path);
+
+int mnld_sendto_flp(const void* dest, const char* buf, int size);
+
+// -1 means failure
+int socket_set_blocking(int fd, int blocking);
+
+// -1 means failure
+int safe_sendto(const char* path, const char* buff, int len);
+
+// -1 means failure
+int safe_recvfrom(int fd, char* buff, int len);
+
+int socket_tcp_server_bind_local(bool abstract, const char* name);
+
+int socket_tcp_server_new_connect(int serverfd);
+
+int socket_tcp_client_connect_local(bool abstract, const char* name);
+
+
+
+/*************************************************
+* File
+**************************************************/
+// 0 not exist, 1 exist
+int is_file_exist(const char* path);
+
+// -1 means failure
+int get_file_size(const char* path);
+
+// -1 failure
+int delete_file(const char* file_path);
+
+// -1 means failure
+int write_msg2file(const char* dest, const char* msg, ...);
+
+int asc_str_to_usc2_str(char* output, const char* input);
+
+void raw_data_to_hex_string(char* output, const char* input, int input_len);
+
+void init_condition(SYNC_LOCK_T *lock);
+
+void get_condition(SYNC_LOCK_T *lock);
+
+void release_condition(SYNC_LOCK_T *lock);
+
+void mnld_dump_exit(void);
+
+//--------------------------------------------------------------------------------------------------------
+#define MAX_CLIENT_NUM 10
+
+typedef struct {
+ int fd;
+
+ //state
+ bool gnss_started;
+ bool gnss_inited;
+ bool meas_started;
+ union {
+ mnl_hal_basic_client_cap basic_client_cap;
+ mnl_hal_ext_client_cap ext_client_cap;
+ } client_cap;
+ union {
+ mnl_hal_basic_server_cap basic_server_cap;
+ mnl_hal_ext_server_cap ext_server_cap;
+ } server_cap;
+} client_ctx;
+
+typedef struct {
+ int num;
+ client_ctx clients[MAX_CLIENT_NUM];
+} client_list;
+
+void client_list_dump(client_list* list);
+
+bool client_list_add(client_list* list, int fd);
+
+bool client_list_remove(client_list* list, int fd);
+
+bool client_list_contains(client_list* list, int fd);
+
+client_ctx* client_list_get_ctx_by_fd(client_list* list, int fd);
+
+bool client_list_is_all_gnss_stop(client_list* list);
+
+bool client_list_is_all_gnss_cleanup(client_list* list);
+
+bool client_list_is_all_meas_stop(client_list* list);
+
+bool client_list_is_geofence_ongoing(client_list* list, int fd);
+
+int socket_tcp_send(int fd, const char* buff, int len);
+
+int client_send_to_all(client_list* list, const char* buff, int len);
+
+int mnl2hal_basic(const char* buff, int len);
+
+int mnl2hal_ext(const char* buff, int len);
+
+int mnl2hal_basic_all(const char* buff, int len);
+
+//Cycle buffer
+typedef struct cyclical_buffer // Cyclical buffer
+{
+ char *next_write; // next position to write to
+ char *next_read; // next position to read from
+ char *start_buffer; // start of buffer
+ char *end_buffer; // end of buffer + 1
+ int buffer_size;
+} cyclical_buffer_t;
+
+int mnld_get_one_msg(cyclical_buffer_t *cyc_buffer, char *buff);
+int mnld_put_msg_to_cycle(cyclical_buffer_t *cyc_buffer, char *buff, int len);
+void mnld_buffer_initialize(cyclical_buffer_t *buffer, char *buffer_body, unsigned int buffer_size);
+
+//------------------------------------------------------
+//Linux wake lock
+
+#define MNLD_WAKE_LOCK_ID "mnld_wakelock"
+//delay to do wake_unlock to ensure the msg can be deliveried to other process
+#define MNLD_WAKE_LOCK_TIMEOUT (5 * 1000)
+//Timer refresh latency, to protect timer update too often in short time
+#define MNLD_WAKE_LOCK_LATENCY (1 * 1000)
+
+typedef struct {
+ bool wake_lock_acquired;
+ timer_t unlock_timer;
+ pthread_mutex_t mutex;
+ UINT64 time_last_refresh;
+} wake_lock_ctx;
+
+void mnld_wake_lock_init();
+void mnld_wake_lock_deinit();
+void mnld_wake_lock_take();
+void mnld_wake_lock_give();
+
+void set_signal_ignore(int signo);
+
+int socket_bind_udp_force(const char* path);
+
+int socket_tcp_server_bind_local_force(bool abstract, const char* name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_mnld_log.h b/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_mnld_log.h
new file mode 100644
index 0000000..c6c6a6e
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_mnld_log.h
@@ -0,0 +1,201 @@
+/*
+* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2017. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*/
+#ifndef MTK_MNLD_LOG_H
+#define MTK_MNLD_LOG_H
+
+/**
+ * @enum LOG_LEVEL
+ * @brief Define Log Level
+ */
+typedef enum {
+ L_VERBOSE = 0, L_DEBUG, L_INFO, L_WARN, L_ERROR, L_ASSERT, L_SUPPRESS
+} LOG_LEVEL;
+
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+#ifdef LOGD
+#undef LOGD
+#endif
+#ifdef LOGW
+#undef LOGW
+#endif
+#ifdef LOGE
+#undef LOGE
+#endif
+
+#ifndef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnld"
+#endif
+
+#include <string.h>
+
+int set_log_level(int *dst_level, int src_level);
+
+extern int log_dbg_level;
+#define LOG_IS_ENABLED(level) (log_dbg_level <= level)
+
+#define FILE_NAME(x) strrchr(x, '/')?strrchr(x, '/') + 1 : x
+
+#if defined(__ANDROID_OS__)
+
+#include <cutils/sockets.h>
+#include <log/log.h> /*logging in logcat*/
+#include <cutils/android_filesystem_config.h>
+#include <cutils/properties.h>
+
+#define PRINT_LOG(loglevel, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ switch (loglevel){\
+ case L_ASSERT:\
+ {\
+ ALOG_ASSERT("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_ERROR:\
+ {\
+ ALOGE("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_WARN:\
+ {\
+ ALOGW("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_INFO:\
+ {\
+ ALOGI("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_DEBUG:\
+ {\
+ ALOGD("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ case L_VERBOSE:\
+ {\
+ ALOGV("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ break;\
+ }\
+ }\
+ }\
+ } while (0)
+
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, fmt, ##args)
+
+#define TRC(f) ALOGD("%s", __func__)
+
+#elif defined(__LINUX_OS__)
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+char time_buff[64];
+int get_time_str(char* buf, int len);
+
+#ifndef gettid
+#define _GNU_SOURCE
+#define gettid() syscall(__NR_gettid)
+#define getpid() syscall(__NR_getpid)
+#endif
+
+#define PRINT_LOG_SAMPLE
+#ifndef PRINT_LOG_SAMPLE
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ get_time_str(time_buff, sizeof(time_buff));\
+ printf("%ld %ld [%s]" LOG_TAG tag "%s %s %d " fmt "\n",\
+ (long)getpid(), (long)gettid(),time_buff, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ fflush(stdout);\
+ }\
+ } while (0)
+#else
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ printf("%ld %ld " LOG_TAG tag "%s %s %d " fmt "\n",\
+ (long)getpid(), (long)gettid(), FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+ fflush(stdout);\
+ }\
+ } while (0)
+#endif
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, "[ASSERT]: ", fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, "[ERROR]: ", fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, "[WARNING]: ", fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, "[INFO]: ", fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, "[DEBUG]: ", fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, "[VERBOSE]: ", fmt, ##args)
+
+#define TRC(f) ((void)0)
+
+#elif defined(__TIZEN_OS__)
+
+#include <dlog/dlog.h>
+
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+ do {\
+ if (LOG_IS_ENABLED(loglevel)) {\
+ dlog_print(DLOG_DEBUG, fmt "\n", ##args);\
+ printf(fmt "\n", ##args);
+ fflush(stdout);\
+ }\
+ } while (0)
+
+#define LOGA(fmt, args...) PRINT_LOG(L_ASSERT, "[ASSERT]: ", fmt, ##args)
+#define LOGE(fmt, args...) PRINT_LOG(L_ERROR, "[ERROR]: ", fmt, ##args)
+#define LOGW(fmt, args...) PRINT_LOG(L_WARN, "[WARNING]: ", fmt, ##args)
+#define LOGI(fmt, args...) PRINT_LOG(L_INFO, "[INFO]: ", fmt, ##args)
+#define LOGD(fmt, args...) PRINT_LOG(L_DEBUG, "[DEBUG]: ", fmt, ##args)
+#define LOGV(fmt, args...) PRINT_LOG(L_VERBOSE, "[VERBOSE]: ", fmt, ##args)
+
+#endif
+#define CONFIG_GPS_ENG_LOAD
+#ifdef CONFIG_GPS_ENG_LOAD
+#define LOGD_ENG(fmt, arg ...) LOGD( fmt, ##arg)
+#else
+#define LOGD_ENG(fmt, arg ...) NULL
+#endif
+
+#endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_prop_util.h b/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_prop_util.h
new file mode 100644
index 0000000..133250b
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_prop_util.h
@@ -0,0 +1,11 @@
+#ifndef __MTK_PROP_UTIL_H__
+#define __MTK_PROP_UTIL_H__
+#if defined(__LINUX_OS__)
+
+#define PROPERTY_VALUE_MAX 256
+
+int property_set(char *prop, char *value);
+int property_get(char *prop, char *value, char *default_value);
+
+#endif
+#endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_socket_data_coder.h b/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_socket_data_coder.h
new file mode 100644
index 0000000..c40a11b
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_socket_data_coder.h
@@ -0,0 +1,50 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __DATA_CODER_H__
+#define __DATA_CODER_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool mtk_socket_get_bool(char* buff, int* offset);
+char mtk_socket_get_char(char* buff, int* offset);
+short mtk_socket_get_short(char* buff, int* offset);
+int mtk_socket_get_int(char* buff, int* offset);
+int64_t mtk_socket_get_int64_t(char* buff, int* offset);
+float mtk_socket_get_float(char* buff, int* offset);
+double mtk_socket_get_double(char* buff, int* offset);
+int mtk_socket_get_string(char* buff, int* offset, char* output, int max_size);
+int mtk_socket_get_bool_array(char* buff, int* offset, bool output[], int max_size);
+int mtk_socket_get_char_array(char* buff, int* offset, char output[], int max_size);
+int mtk_socket_get_short_array(char* buff, int* offset, short output[], int max_size);
+int mtk_socket_get_int_array(char* buff, int* offset, int output[], int max_size);
+int mtk_socket_get_int64_t_array(char* buff, int* offset, int64_t output[], int max_size);
+int mtk_socket_get_float_array(char* buff, int* offset, float output[], int max_size);
+int mtk_socket_get_double_array(char* buff, int* offset, double output[], int max_size);
+int mtk_socket_get_string_array(char* buff, int* offset, void* output, int max_size1, int max_size2);
+
+void mtk_socket_put_bool(char* buff, int* offset, bool input);
+void mtk_socket_put_char(char* buff, int* offset, char input);
+void mtk_socket_put_short(char* buff, int* offset, short input);
+void mtk_socket_put_int(char* buff, int* offset, int input);
+void mtk_socket_put_int64_t(char* buff, int* offset, int64_t input);
+void mtk_socket_put_float(char* buff, int* offset, float input);
+void mtk_socket_put_double(char* buff, int* offset, double input);
+void mtk_socket_put_string(char* buff, int* offset, const char* input);
+void mtk_socket_put_bool_array(char* buff, int* offset, bool input[], int size);
+void mtk_socket_put_char_array(char* buff, int* offset, const char input[], int size);
+void mtk_socket_put_short_array(char* buff, int* offset, const short input[], int size);
+void mtk_socket_put_int_array(char* buff, int* offset, const int input[], int size);
+void mtk_socket_put_int64_t_array(char* buff, int* offset, int64_t input[], int size);
+void mtk_socket_put_float_array(char* buff, int* offset, float input[], int size);
+void mtk_socket_put_double_array(char* buff, int* offset, double input[], int size);
+void mtk_socket_put_string_array(char* buff, int* offset, void* input, int size1, int size2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_socket_utils.h b/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_socket_utils.h
new file mode 100644
index 0000000..d3ce000
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/utility/inc/mtk_socket_utils.h
@@ -0,0 +1,258 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __MTK_SOCKET_UTILS_H__
+#define __MTK_SOCKET_UTILS_H__
+
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <pthread.h>
+
+#include "mtk_mnld_log.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#define strings void*
+
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+typedef enum {
+ SOCK_NS_ABSTRACT = 0,
+ SOCK_NS_FILESYSTEM = 1,
+} mtk_socket_namespace;
+
+typedef struct {
+ int fd;
+ bool is_local;
+ pthread_mutex_t mutex;
+
+ // Network
+ char* host;
+ int port;
+
+ // Local
+ char* path;
+ mtk_socket_namespace namesapce;
+} mtk_socket_fd;
+void _mtk_socket_log(int type, const char *fmt, ...);
+
+#define SOCK_LOGD(fmt, arg ...) LOGD(fmt, ##arg)
+#define SOCK_LOGW(fmt, arg ...) LOGW( fmt, ##arg)
+#define SOCK_LOGE(fmt, arg ...) LOGE(fmt, ##arg)
+
+//#define SOCK_LOGD(...) _mtk_socket_log(0, __VA_ARGS__);
+//#define SOCK_LOGE(...) _mtk_socket_log(1, __VA_ARGS__);
+
+//-1 means failure
+int mtk_socket_server_bind_network(int port);
+//-1 means failure
+int mtk_socket_server_bind_network_ipv6(int port);
+//-1 means failure
+int mtk_socket_server_bind_local(const char* path, mtk_socket_namespace sock_namespace);
+
+void mtk_socket_client_init_network(mtk_socket_fd* sock_fd, const char* host, int port);
+void mtk_socket_client_init_local(mtk_socket_fd* sock_fd, const char* path, mtk_socket_namespace sock_namespace);
+
+void mtk_socket_client_cleanup(mtk_socket_fd* sock_fd);
+
+bool mtk_socket_client_connect(mtk_socket_fd* sock_fd);
+void mtk_socket_client_close(mtk_socket_fd* sock_fd);
+
+//-1 means failure
+int mtk_socket_read(int fd, char* buff, int len);
+
+//-1 means failure
+int mtk_socket_write(int fd, void* buff, int len);
+
+// <= 0 means no data received
+int mtk_socket_poll(int fd, int timeout);
+
+
+void mtk_socket_buff_dump(const char* buff, int len);
+
+bool mtk_socket_string_is_equal(char* data1, char* data2);
+bool mtk_socket_string_array_is_equal(void* data1, int data1_size, void* data2, int data2_size, int string_size);
+void mtk_socket_string_array_dump(void* input, int size1, int size2);
+
+bool mtk_socket_bool_array_is_equal(bool data1[], int data1_size, bool data2[], int data2_size);
+void mtk_socket_bool_array_dump(bool input[], int size);
+
+bool mtk_socket_char_array_is_equal(char data1[], int data1_size, char data2[], int data2_size);
+void mtk_socket_char_array_dump(char input[], int size);
+
+bool mtk_socket_short_array_is_equal(short data1[], int data1_size, short data2[], int data2_size);
+void mtk_socket_short_array_dump(short input[], int size);
+
+bool mtk_socket_int_array_is_equal(int data1[], int data1_size, int data2[], int data2_size);
+void mtk_socket_int_array_dump(int input[], int size);
+
+bool mtk_socket_int64_t_array_is_equal(int64_t data1[], int data1_size, int64_t data2[], int data2_size);
+void mtk_socket_int64_t_array_dump(int64_t input[], int size);
+
+bool mtk_socket_float_array_is_equal(float data1[], int data1_size, float data2[], int data2_size);
+void mtk_socket_float_array_dump(float input[], int size);
+
+bool mtk_socket_double_array_is_equal(double data1[], int data1_size, double data2[], int data2_size);
+void mtk_socket_double_array_dump(double input[], int size);
+
+bool mtk_socket_expected_bool(char* buff, int* offset, bool expected_value, const char* func, int line);
+bool mtk_socket_expected_char(char* buff, int* offset, char expected_value, const char* func, int line);
+bool mtk_socket_expected_short(char* buff, int* offset, short expected_value, const char* func, int line);
+bool mtk_socket_expected_int(char* buff, int* offset, int expected_value, const char* func, int line);
+bool mtk_socket_expected_int64_t(char* buff, int* offset, int64_t expected_value, const char* func, int line);
+bool mtk_socket_expected_float(char* buff, int* offset, float expected_value, const char* func, int line);
+bool mtk_socket_expected_double(char* buff, int* offset, double expected_value, const char* func, int line);
+bool mtk_socket_expected_string(char* buff, int* offset, const char* expected_value, int max_size, const char* func, int line);
+
+char *safe_strncpy(char *dest, const char *src, size_t n);
+
+#define ASSERT_EQUAL_INT(d1, d2) \
+{\
+ int _d1 = d1;\
+ int _d2 = d2;\
+ if(_d1 != _d2) {\
+ SOCK_LOGE("%s():%d ASSERT_EQUAL_INT() failed, d1=[%d], d2=[%d]",\
+ __func__, __LINE__, _d1, _d2);\
+ return false;\
+ }\
+}
+
+#define EXPECTED_BOOL(buff, offset, expected_value) \
+{\
+ if(!mtk_socket_expected_bool(buff, offset, expected_value, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_CHAR(buff, offset, expected_value) \
+{\
+ if(!mtk_socket_expected_char(buff, offset, expected_value, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_SHORT(buff, offset, expected_value) \
+{\
+ if(!mtk_socket_expected_short(buff, offset, expected_value, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_INT(buff, offset, expected_value) \
+{\
+ if(!mtk_socket_expected_int(buff, offset, expected_value, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_INT64_T(buff, offset, expected_value) \
+{\
+ if(!mtk_socket_expected_int64_t(buff, offset, expected_value, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_FLOAT(buff, offset, expected_value) \
+{\
+ if(!mtk_socket_expected_float(buff, offset, expected_value, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_DOUBLE(buff, offset, expected_value) \
+{\
+ if(!mtk_socket_expected_double(buff, offset, expected_value, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_STRING(buff, offset, expected_value, max_size) \
+{\
+ if(!mtk_socket_expected_string(buff, offset, expected_value, max_size, __func__, __LINE__)) {\
+ return false;\
+ }\
+}
+
+#define EXPECTED_STRUCT(buff, offset, expected_value, struct_name) \
+{\
+ struct_name _tmp;\
+ struct_name##_decode(buff, offset, &_tmp);\
+ if(!struct_name##_is_equal(&_tmp, expected_value)) {\
+ SOCK_LOGE("%s():%d EXPECTED_STRUCT() %s_is_equal() fail", __func__, __LINE__, #struct_name);\
+ SOCK_LOGE(" ============= read ===============");\
+ struct_name##_dump(&_tmp);\
+ SOCK_LOGE(" ============= expected ===============");\
+ struct_name##_dump(expected_value);\
+ return false;\
+ }\
+}
+
+#define EXPECTED_ARRAY(buff, offset, expected_num, expected_value, type, max_size) \
+{\
+ type _tmp[max_size] = {0};\
+ int _tmp_num = mtk_socket_get_##type##_array(buff, offset, _tmp, max_size);\
+ if(!mtk_socket_##type##_array_is_equal(expected_value, expected_num, _tmp, _tmp_num)) {\
+ SOCK_LOGE("%s():%d expected_%s_array() fail", __func__, __LINE__, #type);\
+ SOCK_LOGE(" ============= read ===============");\
+ mtk_socket_##type##_array_dump(_tmp, _tmp_num);\
+ SOCK_LOGE(" ============= expected ===============");\
+ mtk_socket_##type##_array_dump(expected_value, expected_num);\
+ return false;\
+ }\
+}
+
+#define EXPECTED_STRING_ARRAY(buff, offset, expected_num, expected_value, max_size1, max_size2) \
+{\
+ char _tmp[max_size1][max_size2];\
+ int _tmp_num = mtk_socket_get_string_array(buff, offset, _tmp, max_size1, max_size2);\
+ if(!mtk_socket_string_array_is_equal(expected_value, expected_num, _tmp, _tmp_num, max_size2)) {\
+ SOCK_LOGE("%s():%d expected_string_array() fail", __func__, __LINE__);\
+ SOCK_LOGE(" ============= read ===============");\
+ mtk_socket_string_array_dump(_tmp, _tmp_num, max_size2);\
+ SOCK_LOGE(" ============= expected ===============");\
+ mtk_socket_string_array_dump(expected_value, expected_num, max_size2);\
+ return false;\
+ }\
+}
+
+#define EXPECTED_STRUCT_ARRAY(buff, offset, expected_num, expected_value, type, max_size) \
+{\
+ type _tmp[max_size];\
+ int _tmp_num = type##_array_decode(buff, offset, _tmp, max_size);\
+ if(!type##_array_is_equal(expected_value, expected_num, _tmp, _tmp_num)) {\
+ SOCK_LOGE("%s():%d expected_%s_array() fail", __func__, __LINE__, #type);\
+ SOCK_LOGE(" ============= read ===============");\
+ type##_array_dump(_tmp, _tmp_num);\
+ SOCK_LOGE(" ============= expected ===============");\
+ type##_array_dump(expected_value, expected_num);\
+ return false;\
+ }\
+}
+
+#define ASSERT_LESS_EQUAL_THAN(d1, d2) \
+{\
+ if(d1 > d2) {\
+ SOCK_LOGE("%s():%d ASSERT_LESS_EQUAL_THAN() fail, %s=[%d] > [%d]", __func__, __LINE__, #d1, d1, d2);\
+ return false;\
+ }\
+}
+
+#define ASSERT_LESS_EQUAL_THAN_FOR_MSG(d1, d2) \
+{\
+ if(d1 > d2) {\
+ SOCK_LOGE("%s():%d ASSERT_LESS_EQUAL_THAN_FOR_MSG() fail, %s=[%d] > [%d]", __func__, __LINE__, #d1, d1, d2);\
+ mtk_socket_client_close(client_fd);\
+ pthread_mutex_unlock(&client_fd->mutex);\
+ return false;\
+ }\
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/utility/src/data_coder.c b/src/connectivity/gps/2.0/mtk_mnld/utility/src/data_coder.c
new file mode 100644
index 0000000..36a89ef
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/utility/src/data_coder.c
@@ -0,0 +1,158 @@
+#include <string.h>
+
+#ifndef MAX
+#define MAX(A,B) ((A)>(B)?(A):(B))
+#endif
+#ifndef MIN
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#endif
+
+//===============================================================
+// get
+char get_byte(char* buff, int* offset, int src_len) {
+ char ret = 0;
+ if (*offset >= 0 && *offset < src_len) {
+ ret = buff[*offset];
+ *offset += 1;
+ }
+ return ret;
+}
+
+short get_short(char* buff, int* offset, int src_len) {
+ unsigned short ret = 0;
+ ret |= ((unsigned short)get_byte(buff, offset, src_len) & 0xff);
+ ret |= ((unsigned short)get_byte(buff, offset, src_len) << 8);
+ return (short)ret;
+}
+
+int get_int(char* buff, int* offset, int src_len) {
+ unsigned int ret = 0;
+ ret |= ((unsigned int)get_short(buff, offset, src_len) & 0xffff);
+ ret |= ((unsigned int)get_short(buff, offset, src_len) << 16);
+ return (int)ret;
+}
+
+long long get_long(char* buff, int* offset, int src_len) {
+ unsigned long long ret = 0;
+ ret |= ((unsigned long long)get_int(buff, offset, src_len) & 0xffffffffL);
+ ret |= ((unsigned long long)get_int(buff, offset, src_len) << 32);
+ return (long long)ret;
+}
+
+float get_float(char* buff, int* offset, int src_len) {
+ float ret;
+ int tmp = get_int(buff, offset, src_len);
+ ret = *((float*)&tmp);
+ return ret;
+}
+
+double get_double(char* buff, int* offset, int src_len) {
+ double ret;
+ long long tmp = get_long(buff, offset, src_len);
+ ret = *((double*)&tmp);
+ return ret;
+}
+
+char* get_string(char* buff, int* offset, int src_len) {
+ char ret = get_byte(buff, offset, src_len);
+ if (ret == 0) {
+ return NULL;
+ } else {
+ char* p = NULL;
+ int len = get_int(buff, offset, src_len);
+ if (*offset < 0 || *offset >= src_len) {
+ *offset = 0;
+ }
+ if ((len > src_len - *offset) || len < 0) {
+ len = src_len - *offset;
+ }
+ if (len <= 0) {
+ return NULL;
+ }
+ p = &buff[*offset];
+ p[len-1] = 0;
+ *offset += len;
+ return p;
+ }
+}
+
+char* get_string2(char* buff, int* offset, int src_len) {
+ char* output = get_string(buff, offset, src_len);
+ if (output == NULL) {
+ return "";
+ } else {
+ return output;
+ }
+}
+
+int get_binary(char* buff, int* offset, char* output, int src_len, int des_len) {
+ int len = 0;
+ if (*offset >= 0 && *offset <= src_len) {
+ len = get_int(buff, offset, src_len);
+ if (len > MIN((src_len-(*offset)), des_len)) {
+ len = MIN((src_len-(*offset)), des_len);
+ }
+ if (len > 0) {
+ memcpy(output, &buff[*offset], len);
+ *offset += len;
+ }
+ }
+ return len;
+}
+
+//===============================================================
+// put
+void put_byte(char* buff, int* offset, const char input) {
+ *((char*)&buff[*offset]) = input;
+ *offset += 1;
+}
+
+void put_short(char* buff, int* offset, const short input) {
+ put_byte(buff, offset, (char)((unsigned short)input & 0xff));
+ put_byte(buff, offset, (char)(((unsigned short)input >> 8) & 0xff));
+}
+
+void put_int(char* buff, int* offset, const int input) {
+ put_short(buff, offset, (short)((unsigned int)input & 0xffff));
+ put_short(buff, offset, (short)(((unsigned int)input >> 16) & 0xffff));
+}
+
+void put_long(char* buff, int* offset, const long long input) {
+ put_int(buff, offset, (int)((unsigned long long)input & 0xffffffffL));
+ put_int(buff, offset, (int)(((unsigned long long)input >> 32L) & 0xffffffffL));
+}
+
+void put_float(char* buff, int* offset, const float input) {
+ int* data = (int*)&input;
+ put_int(buff, offset, *data);
+}
+
+void put_double(char* buff, int* offset, const double input) {
+ long long* data = (long long*)&input;
+ put_long(buff, offset, *data);
+}
+
+void put_string(char* buff, int* offset, const char* input, int max_size) {
+ if (input == NULL) {
+ put_byte(buff, offset, 0);
+ } else {
+ int len = strlen(input) + 1;
+ put_byte(buff, offset, 1);
+ put_int(buff, offset, len);
+ if (len >= (max_size - *offset)) {
+ len = (max_size - *offset) - 1;
+ }
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+ buff[max_size - 1] = 0;
+ }
+}
+
+void put_binary(char* buff, int* offset, const char* input, const int len) {
+ put_int(buff, offset, len);
+ if (len > 0) {
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+ }
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_lbs_utility.c b/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_lbs_utility.c
new file mode 100644
index 0000000..6490cb6
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_lbs_utility.c
@@ -0,0 +1,1360 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h> // usleep
+#include <sys/socket.h>
+#include <string.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 <sys/syscall.h>
+
+#if defined(__ANDROID_OS__)
+#include <cutils/log.h> // Android log
+#endif
+#include "mtk_mnld_log.h"
+
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "mtk_lbs_utility"
+
+int asc_str_to_usc2_str(char* output, const char* input) {
+ int len = 2;
+
+ output[0] = 0xfe;
+ output[1] = 0xff;
+
+ while (*input != 0) {
+ output[len++] = 0;
+ output[len++] = *input;
+ input++;
+ }
+
+ output[len] = 0;
+ output[len+1] = 0;
+ return len;
+}
+
+void raw_data_to_hex_string(char* output, const char* input, int input_len) {
+ int i = 0;
+ for (i = 0; i < input_len; i++) {
+ int tmp = (input[i] >> 4) & 0xf;
+
+ if (tmp >= 0 && tmp <= 9) {
+ output[i*2] = tmp + '0';
+ } else {
+ output[i*2] = (tmp - 10) + 'A';
+ }
+
+ tmp = input[i] & 0xf;
+ if (tmp >= 0 && tmp <= 9) {
+ output[(i*2)+1] = tmp + '0';
+ } else {
+ output[(i*2)+1] = (tmp - 10) + 'A';
+ }
+ }
+ output[i*2] = 0;
+}
+
+void msleep(int interval) {
+ usleep(interval * 1000);
+}
+
+// in millisecond
+time_t get_tick() {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
+ LOGE("clock_gettime failed reason=[%s]", strerror(errno));
+ return -1;
+ }
+ return (ts.tv_sec*1000) + (ts.tv_nsec/1000000);
+}
+
+// in millisecond
+UINT64 get_time_in_millisecond() {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_BOOTTIME, &ts) == -1) {
+ LOGE("get_time_in_millisecond failed reason=[%s]", strerror(errno));
+ return 0;
+ }
+ return (UINT64)((UINT64)(ts.tv_sec*1000) + (UINT64)(ts.tv_nsec/1000000));
+}
+
+sem_t g_mnld_exit_sem;
+extern bool mnld_exiting;
+
+// -1 means failure
+int block_here() {
+ if (sem_init(&g_mnld_exit_sem, 0, 0) == -1) {
+ LOGE("block_here() sem_init failure reason=%s\n", strerror(errno));
+ return -1;
+ }
+ sem_wait(&g_mnld_exit_sem);
+ if (sem_destroy(&g_mnld_exit_sem) == -1) {
+ LOGE("block_here() sem_destroy reason=%s\n", strerror(errno));
+ }
+ return 0;
+}
+
+void mnld_block_exit(void) {
+ mnld_exiting = true;
+ LOGW("mnld exiting....");
+ if(sem_post(&g_mnld_exit_sem) == -1) {
+ LOGE("sem_post failed");
+ _exit(0);
+ }
+}
+
+/*************************************************
+* Timer
+**************************************************/
+// -1 means failure
+timer_t init_timer_id(timer_callback cb, int id) {
+ struct sigevent sevp;
+ timer_t timerid;
+
+ memset(&sevp, 0, sizeof(sevp));
+ sevp.sigev_value.sival_int = id;
+ sevp.sigev_notify = SIGEV_THREAD;
+ sevp.sigev_notify_function = cb;
+
+ if (timer_create(CLOCK_MONOTONIC, &sevp, &timerid) == -1) {
+ LOGE("timer_create failed reason=[%s]", strerror(errno));
+ return INVALID_TIMERID;
+ }
+ LOGD("timerid init:%lu", (unsigned long)timerid);
+ return timerid;
+}
+
+// -1 means failure
+timer_t init_timer(timer_callback cb) {
+ return init_timer_id(cb, 0);
+}
+
+// -1 means failure
+int start_timer(timer_t timerid, int milliseconds) {
+ if(timerid != INVALID_TIMERID) {
+ struct itimerspec expire;
+ expire.it_interval.tv_sec = 0;
+ expire.it_interval.tv_nsec = 0;
+ expire.it_value.tv_sec = milliseconds/1000;
+ expire.it_value.tv_nsec = (milliseconds%1000)*1000000;
+ return timer_settime(timerid, 0, &expire, NULL);
+ } else {
+ LOGE("invalid timerid:%p", timerid);
+ return -1;
+ }
+}
+
+// -1 means failure
+int stop_timer(timer_t timerid) {
+ return start_timer(timerid, 0);
+}
+
+// -1 means failure
+int deinit_timer(timer_t timerid) {
+ LOGD("timerid deinit:%lu", (unsigned long)timerid);
+
+ if(timerid != INVALID_TIMERID) {
+ if (timer_delete(timerid) == -1) {
+ LOGE("timer_delete error:%s", strerror(errno));
+ return -1;
+ }
+ } else {
+ LOGE("invalid timerid:%p", timerid);
+ return -1;
+ }
+
+ return 0;
+}
+/*************************************************
+* Timer Alarm
+**************************************************/
+// -1 means failure
+int init_timer_id_alarm(int id) {
+ int wakealarm_fd;
+
+ LOGE("timerfd_create CLOCK_BOOTTIME_ALARM \n");
+ //CLOCK_BOOTTIME_ALARM can work when AP sleep
+ wakealarm_fd = timerfd_create(CLOCK_BOOTTIME_ALARM, id);
+ if (wakealarm_fd == -1) {
+ LOGE("timerfd_create CLOCK_BOOTTIME_ALARM failed reason=[%s]\n", strerror(errno));
+ return -1;
+ }
+ return wakealarm_fd;
+}
+
+// -1 means failure
+int init_timer_alarm() {
+ return init_timer_id_alarm(0);
+}
+
+// -1 means failure
+int start_timer_alarm(int timerfd, int milliseconds) {
+ struct itimerspec expire;
+ expire.it_interval.tv_sec = 0;
+ expire.it_interval.tv_nsec = 0;
+ expire.it_value.tv_sec = milliseconds/1000;
+ expire.it_value.tv_nsec = (milliseconds%1000)*1000000;
+ return timerfd_settime(timerfd, 0, &expire, NULL);
+}
+
+// -1 means failure
+int stop_timer_alarm(int timerid) {
+ return start_timer_alarm(timerid, 0);
+}
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int epoll_add_fd(int epfd, int fd) {
+ struct epoll_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.data.fd = fd;
+ ev.events = EPOLLIN;
+ // 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_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+ strerror(errno), errno, epfd, fd);
+ return -1;
+ }
+ return 0;
+}
+
+// -1 failed
+int 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 epoll_del_fd(int epfd, int fd) {
+ struct epoll_event ev;
+ int ret;
+
+ if (epfd == -1)
+ return -1;
+
+ ev.events = EPOLLIN;
+ ev.data.fd = fd;
+ do {
+ ret = epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev);
+ } while (ret < 0 && errno == EINTR);
+ return ret;
+}
+
+// -1 failed
+int epoll_mod_fd(int epfd, int fd, uint32_t events) {
+ struct epoll_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.data.fd = fd;
+ ev.events = events;
+ if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1) {
+ LOGE("epoll_mod_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+ strerror(errno), errno, epfd, fd);
+ return -1;
+ }
+ return 0;
+}
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int socket_set_reuse_addr(int fd, bool reuse) {
+ int val = (int)reuse;
+ int newval;
+ socklen_t intlen = sizeof(newval);
+
+ if (0 != setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) {
+ LOGE("setsockopt(SO_REUSEADDR) fail %s(%d)", strerror(errno), errno);
+ return -1;
+ }
+
+ if (0 != getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &newval, &intlen)) {
+ LOGE("getsockopt(SO_REUSEADDR) fail %s(%d)", strerror(errno), errno);
+ return -1;
+ }
+
+ if (newval != val) {
+ LOGE("Failed to set SO_REUSEADDR");
+ return -1;
+ }
+
+ return 0;
+}
+
+// -1 means failure
+int 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\n", 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(socket_set_reuse_addr(fd, true) == -1) {
+ LOGE("socket_bind_udp() socket_set_reuse_addr() failed path=[%s] reason=[%s]%d",
+ path, strerror(errno), errno);
+ }
+ 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;
+ }
+
+ LOGD("path=%s\n", path);
+
+ return fd;
+}
+
+// -1 means failure
+int socket_bind_udp_force(const char* path) {
+ int ret = 0;
+ int retry_cnt = 0;
+
+ do {
+ ret = socket_bind_udp(path);
+ if(ret < 0) {
+ retry_cnt++;
+ LOGE("socket_bind_udp_force() bind() failed path=[%s] reason=[%s]%d, retry_cnt:%d",
+ path, strerror(errno), errno, retry_cnt);
+ msleep(1000);
+ if(retry_cnt > 10) {
+ LOGE("socket bind fail, mnld exit...");
+ _exit(-1);
+ }
+ }
+ } while(ret < 0);
+
+ LOGD("path=%s\n", path);
+
+ return ret;
+}
+
+int mnld_flp_to_mnld_fd_init(const char* path) {
+ int flp_fd = -1;
+ struct sockaddr_un cmd_local;
+
+ if ((flp_fd = socket(AF_LOCAL, SOCK_DGRAM, 0)) == -1) {
+ LOGE("flp2mnl socket create failed\n");
+ return flp_fd;
+ }
+
+ unlink(path);
+ memset(&cmd_local, 0, sizeof(cmd_local));
+ cmd_local.sun_family = AF_LOCAL;
+ MNLD_STRNCPY(cmd_local.sun_path, path,sizeof(cmd_local.sun_path));
+
+ if (bind(flp_fd, (struct sockaddr *)&cmd_local, sizeof(cmd_local)) < 0) {
+ LOGE("flp2mnl socket bind failed\n");
+ close(flp_fd);
+ flp_fd = -1;
+ return flp_fd;
+ }
+
+ int res = chmod(path, 0660); // (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ LOGD("chmod res = %d, %s\n", res, strerror(errno));
+ return flp_fd;
+}
+
+// -1 means failure
+int socket_set_blocking(int fd, int blocking) {
+ if (fd < 0) {
+ LOGE("socket_set_blocking() invalid fd=%d", fd);
+ return -1;
+ }
+
+ int flags = fcntl(fd, F_GETFL, 0);
+ if (flags == -1) {
+ LOGE("socket_set_blocking() fcntl() failed invalid flags=%d reason=[%s]%d",
+ flags, strerror(errno), errno);
+ return -1;
+ }
+
+ flags = blocking ? ((unsigned int)flags&~O_NONBLOCK) : ((unsigned int)flags|O_NONBLOCK);
+ return (fcntl(fd, F_SETFL, flags) == 0) ? 0 : -1;
+}
+
+// -1 means failure
+int 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;
+}
+
+int mnld_sendto_flp(const void* dest, const char* buf, int size) {
+ // dest: MTK_MNLD2HAL
+ int ret = 0;
+ int len = 0;
+ struct sockaddr_un soc_addr;
+ socklen_t addr_len;
+ 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;
+ }
+
+ MNLD_STRNCPY(soc_addr.sun_path, dest,sizeof(soc_addr.sun_path));
+ soc_addr.sun_family = AF_UNIX;
+ addr_len = (offsetof(struct sockaddr_un, sun_path) + strlen(soc_addr.sun_path) + 1);
+
+ //LOGD("mnld2flp fd: %d\n", fd);
+ while ((len = sendto(fd, buf, size, 0,
+ (const struct sockaddr *)&soc_addr, (socklen_t)addr_len)) == -1) {
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("[mnld2hal] ERR: sendto dest=[%s] len=%d reason =[%s]\n",
+ (const char*)dest, size, strerror(errno));
+ ret = -1;
+ break;
+ }
+ close(fd);
+ return ret;
+}
+
+// -1 means failure
+int safe_recvfrom(int fd, char* buff, int len) {
+ int ret = 0;
+ int retry = 10;
+
+ 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);
+ }
+
+ while ((ret = recvfrom(fd, buff, len, 0,
+ NULL, NULL)) == -1) {
+ LOGW("safe_recvfrom() ret=%d len=%d", ret, len);
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("safe_recvfrom() recvfrom() failed reason=[%s]%d",
+ strerror(errno), errno);
+ break;
+ }
+ return ret;
+}
+
+/*************************************************
+* File
+**************************************************/
+// 0 not exist, 1 exist
+int is_file_exist(const char* path) {
+ FILE* fp = NULL;
+ fp = fopen(path, "r");
+ if (fp == NULL) {
+ return 0;
+ } else {
+ fclose(fp);
+ return 1;
+ }
+ return 0;
+}
+
+// -1 means failure
+int get_file_size(const char* path) {
+ struct stat s;
+ if (stat(path, &s) == -1) {
+ LOGD("get_file_size() stat() fail for [%s] reason=[%s]",
+ path, strerror(errno));
+ return -1;
+ }
+ return s.st_size;
+}
+
+// -1 failure
+int delete_file(const char* file_path) {
+ return remove(file_path);
+}
+
+// -1 means failure
+int write_msg2file(const char* dest, const char* msg, ...) {
+ FILE* fp = NULL;
+ char buf[1024] = {0};
+ va_list ap;
+
+ if (dest == NULL || msg == NULL) {
+ return -1;
+ }
+
+ va_start(ap, msg);
+ if (vsnprintf(buf, sizeof(buf), msg, ap) < 0){
+ LOGE("write_msg2file vsnprintf error occurred");\
+ }
+ va_end(ap);
+
+ fp = fopen(dest, "a");
+ if (fp == NULL) {
+ LOGE("write_msg2file() fopen() fail reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ MNLD_FRINTF(fp, "%s", buf);
+ MNLD_FCLOSE(fp);
+ return 0;
+}
+
+void init_condition(SYNC_LOCK_T *lock) {
+ int ret = 0;
+
+ pthread_mutex_lock(&(lock->mutx));
+ lock->condtion = 0;
+ ret = pthread_mutex_unlock(&(lock->mutx));
+ LOGD_ENG("ret mutex unlock = %d\n", ret);
+
+ return;
+}
+
+void get_condition(SYNC_LOCK_T *lock) {
+ int ret = 0;
+
+ ret = pthread_mutex_lock(&(lock->mutx));
+ //LOGD("ret mutex lock = %d\n", ret);
+
+ while (!lock->condtion) {
+ ret = pthread_cond_wait(&(lock->con), &(lock->mutx));
+ //LOGD("ret cond wait = %d\n" , ret);
+ }
+
+ lock->condtion = 0;
+ ret = pthread_mutex_unlock(&(lock->mutx));
+ LOGD_ENG("ret mutex unlock = %d\n", ret);
+
+ return;
+}
+
+void release_condition(SYNC_LOCK_T *lock) {
+ int ret = 0;
+
+ ret = pthread_mutex_lock(&(lock->mutx));
+ //LOGD("ret mutex lock = %d\n", ret);
+
+ lock->condtion = 1;
+ ret = pthread_cond_signal(&(lock->con));
+ //LOGD("ret cond_signal = %d\n", ret);
+
+ ret = pthread_mutex_unlock(&(lock->mutx));
+ LOGD_ENG("ret unlock= %d\n", ret);
+
+ return;
+}
+
+#ifdef __LINUX_OS__
+
+#define LISTEN_BACKLOG 4
+/* Only the bottom bits are really the socket type; there are flags too. */
+#define SOCK_TYPE_MASK 0xf
+/* Documented in header file. */
+int socket_make_sockaddr_un(const char *name, struct sockaddr_un *p_addr, socklen_t *alen)
+{
+ memset (p_addr, 0, sizeof (*p_addr));
+ size_t namelen;
+
+ namelen = strlen(name);
+
+ // Test with length +1 for the *initial* '\0'.
+ if ((namelen + 1) > sizeof(p_addr->sun_path)) {
+ goto error;
+ }
+
+ /*
+ * Note: The path in this case is *not* supposed to be
+ * '\0'-terminated. ("man 7 unix" for the gory details.)
+ */
+
+ p_addr->sun_path[0] = 0;
+ memcpy(p_addr->sun_path + 1, name, namelen);
+
+ p_addr->sun_family = AF_LOCAL;
+ *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
+ return 0;
+error:
+ return -1;
+}
+
+/**
+ * connect to peer named "name" on fd
+ * returns same fd or -1 on error.
+ * fd is not closed on error. that's your job.
+ *
+ * Used by AndroidSocketImpl
+ */
+int socket_local_client_connect(int fd, const char *name)
+{
+ struct sockaddr_un addr;
+ socklen_t alen;
+ int err;
+
+ err = socket_make_sockaddr_un(name, &addr, &alen);
+
+ if (err < 0) {
+ goto error;
+ }
+
+ if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
+ goto error;
+ }
+
+ return fd;
+
+error:
+ return -1;
+}
+
+/**
+ * connect to peer named "name"
+ * returns fd or -1 on error
+ */
+int socket_local_client(const char *name, int type)
+{
+ int s;
+
+ s = socket(AF_LOCAL, type, 0);
+ if(s < 0) return -1;
+
+ if ( 0 > socket_local_client_connect(s, name)) {
+ close(s);
+ return -1;
+ }
+
+ return s;
+}
+
+
+
+/**
+ * Binds a pre-created socket(AF_LOCAL) 's' to 'name'
+ * returns 's' on success, -1 on fail
+ *
+ * Does not call listen()
+ */
+int socket_local_server_bind(int s, const char *name)
+{
+ struct sockaddr_un addr;
+ socklen_t alen;
+ int n;
+ int err;
+
+ err = socket_make_sockaddr_un(name, &addr, &alen);
+
+ if (err < 0) {
+ return -1;
+ }
+
+ /* basically: if this is a filesystem path, unlink first */
+ /*ignore ENOENT*/
+ unlink(addr.sun_path);
+
+ n = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
+
+ if(bind(s, (struct sockaddr *) &addr, alen) < 0) {
+ return -1;
+ }
+
+ return s;
+
+}
+
+
+/** Open a server-side UNIX domain datagram socket in the Linux non-filesystem
+ * namespace
+ *
+ * Returns fd on success, -1 on fail
+ */
+
+int socket_local_server(const char *name, int type)
+{
+ int err;
+ int s;
+
+ s = socket(AF_LOCAL, type, 0);
+ if (s < 0) return -1;
+
+ err = socket_local_server_bind(s, name);
+
+ if (err < 0) {
+ close(s);
+ return -1;
+ }
+
+ if ((type & SOCK_TYPE_MASK) == SOCK_STREAM) {
+ int ret;
+
+ ret = listen(s, LISTEN_BACKLOG);
+
+ if (ret < 0) {
+ close(s);
+ return -1;
+ }
+ }
+
+ return s;
+}
+/*
+------------------------
+| Length | Message Body |
+------------------------
+*/
+
+#define MNLD_WAKELOCK_BUFF_SIZE (10 * 1000)
+#define HAL_MNL_BUFF_SIZE_SND (32 * 1000)
+
+int socket_tcp_send(int fd, const char* buff, int len) {
+ char buff_send[HAL_MNL_BUFF_SIZE_SND] = {0};
+ int offset = 0;
+ int retry = 10;
+
+ if(fd < 0) {
+ LOGE("socket_tcp_send() invalid fd:%d", fd);
+ return -1;
+ }
+ put_binary(buff_send, &offset, buff, len); //Put length to the head
+
+ int ret = -1;
+ while((ret = write(fd, buff_send, offset)) == -1) {
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ LOGE("socket_tcp_send() write() failed fd=[%d] ret=%d reason=[%s]%d",
+ fd, ret, strerror(errno), errno);
+ break;
+ }
+#ifdef MNLD_DUMP_CMD_RAW
+ LOGD("send %d, ret %d, fd:%d", len, ret, fd);
+ for(int i=0;i<len+4;i++) {
+ LOGD("0x%x", buff_send[i]);
+ }
+#endif
+ return ret;
+}
+
+/******************************************************************************
+* Socket
+******************************************************************************/
+
+//-1 means fail or serverfd is returned
+int socket_tcp_server_bind_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 {
+ MNLD_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ if(unlink(addr.sun_path) == -1) {
+ LOGW("socket_tcp_server_bind_local() unlink() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(fd == -1) {
+ LOGE("socket_tcp_server_bind_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(socket_set_reuse_addr(fd, true) == -1) {
+ LOGE("socket_tcp_server_bind_local() socket_set_reuse_addr() failed path=[%s] reason=[%s]%d",
+ name, strerror(errno), errno);
+ }
+ if(bind(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("socket_tcp_server_bind_local() bind() failed, abstruct=%d name=[%s] reason=[%s]%d",
+ abstract, name, strerror(errno), errno);
+ close(fd);
+ return -1;
+ }
+ if(listen(fd, 5) == -1) {
+ LOGW("socket_tcp_server_bind_local() listen() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ return fd;
+}
+
+// -1 means failure
+int socket_tcp_server_bind_local_force(bool abstract, const char* name) {
+ int ret = 0;
+ int retry_cnt = 0;
+
+ do {
+ ret = socket_tcp_server_bind_local(abstract, name);
+ if(ret < 0) {
+ retry_cnt++;
+ LOGE("socket_tcp_server_bind_local_force() bind() failed path=[%s] reason=[%s]%d, retry_cnt:%d",
+ name, strerror(errno), errno, retry_cnt);
+ msleep(1000);
+ if(retry_cnt > 10) {
+ LOGE("socket bind fail, mnld exit...");
+ _exit(-1);
+ }
+ }
+ } while(ret < 0);
+
+ LOGD("name=%s\n", name);
+
+ return ret;
+}
+
+//-1 means fail or new clientfd is returned
+int socket_tcp_server_new_connect(int serverfd) {
+ int newfd;
+ struct sockaddr_in addr;
+ socklen_t len = sizeof(addr);
+
+ newfd = accept(serverfd, (struct sockaddr*)&addr, &len);
+ if(newfd == -1) {
+ LOGE("socket_tcp_server_new_connect() accept() failed, serverfd=%d reason=[%s]%d",
+ serverfd, strerror(errno), errno);
+ return -1;
+ }
+ return newfd;
+}
+
+//-1 means fail or serverfd is returned
+int 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 {
+ MNLD_STRNCPY(addr.sun_path, name, sizeof(addr.sun_path));
+ if(unlink(addr.sun_path) == -1) {
+ LOGW("socket_tcp_client_connect_local() unlink() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ }
+ }
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(fd == -1) {
+ LOGE("socket_tcp_client_connect_local() socket() failed, reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ if(connect(fd, (struct sockaddr*)&addr, size) == -1) {
+ LOGE("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 mnld_buffer_initialize(cyclical_buffer_t *buffer, char *buffer_body, unsigned int buffer_size) {
+ // Set up buffer manipulation pointers
+ // end_buffer points to the next byte after the buffer
+ buffer->start_buffer = buffer_body;
+ 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;
+}
+#if 0
+void mnld_dump_cycle(cyclical_buffer_t *cyc_buffer, char *buff, int len) {
+ char* print_buf[HAL_MNL_BUFF_SIZE_SND] = {0};
+ LOGD("=====Cycle Dump, len:%d=======", len);
+ for(int i=0;i<len;i++) {
+ char ch = 0;
+ ch = *(cyc_buffer->next_read++);
+ if(cyc_buffer->next_read == cyc_buffer->end_buffer) {
+ cyc_buffer->next_read = cyc_buffer->start_bufferr;
+ }
+ sprintf(print_buf, " 0x%x", ch);
+ LOGD("0x%x 0x%x 0x%x 0x%x", );
+ }
+}
+#endif
+
+int mnld_put_msg_to_cycle(cyclical_buffer_t *cyc_buffer, char *buff, int len) {
+ int i;
+
+#ifdef MNLD_DUMP_CMD_RAW
+ LOGD("mnld_inf_put_msg_to_cycle:%d", len);
+#endif
+ for (i = 0; i < len; i++)
+ {
+ *(cyc_buffer->next_write++) = buff[i];
+#ifdef MNLD_DUMP_CMD_RAW
+ LOGD("0x%x", *(cyc_buffer->next_write-1));
+#endif
+ if (cyc_buffer->next_write == cyc_buffer->end_buffer){
+ cyc_buffer->next_write = cyc_buffer->start_buffer;
+ }
+
+ if (cyc_buffer->next_write == cyc_buffer->next_read){
+ LOGE("mnld_inf_put_msg_to_cycle buffer full!\r\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+/******************************************
+Get one message from cycle buffer
+******************************************/
+int mnld_get_one_msg(cyclical_buffer_t *cyc_buffer, char *buff) {
+ char *next_write, *next_read;
+ int data_size, i, header_len;
+ char buffer[HAL_MNL_BUFF_SIZE_SND] = {0};
+ int data_len = 0;
+ int return_len = 0;
+
+ next_write = cyc_buffer->next_write;
+ next_read = cyc_buffer->next_read;
+
+ if (cyc_buffer->next_read == next_write)
+ {
+ //buffer empty
+ return -1;
+ }
+
+ header_len = sizeof(int);
+ /*Compute data length*/
+ if (cyc_buffer->next_read < next_write)
+ {
+ data_size = (unsigned long)next_write - (unsigned long)cyc_buffer->next_read;
+ }
+ else
+ {
+ data_size = (unsigned long)cyc_buffer->end_buffer - (unsigned long)cyc_buffer->next_read +
+ (unsigned long)next_write - (unsigned long)cyc_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 == cyc_buffer->end_buffer){
+ next_read = cyc_buffer->start_buffer;
+ }
+ }
+
+ memcpy(&data_len, buffer, sizeof(int));
+ if (data_len <= data_size) {
+ #ifdef MNLD_DUMP_CMD_RAW
+ LOGD("data len:%d, header len:%d", data_len, header_len);
+ #endif
+ for (i = 0; i < (data_len + header_len); i++)
+ {
+ buff[i] = *(cyc_buffer->next_read++);
+ #ifdef MNLD_DUMP_CMD_RAW
+ LOGD("0x%x", buff[i]);
+ #endif
+ return_len++;
+ if (cyc_buffer->next_read == cyc_buffer->end_buffer){
+ cyc_buffer->next_read = cyc_buffer->start_buffer;
+ }
+ }
+ }
+ else {
+ //no enough data
+ return -2;
+ }
+
+ }
+ else
+ {
+ //no enough data
+ return -2;
+ }
+
+ return return_len;
+}
+
+void client_list_dump(client_list* list) {
+ LOGD("client_list_dump() num=[%d]", list->num);
+ int i = 0;
+ for(i = 0; i < list->num; i++) {
+ LOGD(" i=[%d] fd=[%d]", i, list->clients[i].fd);
+ }
+}
+
+bool client_list_add(client_list* list, int fd) {
+ if(list->num >= MAX_CLIENT_NUM) {
+ LOGE("client_list_add() fail due to MAX_CLIENT_NUM=%d", MAX_CLIENT_NUM);
+ return false;
+ }
+
+ list->clients[list->num].fd = fd;
+ list->num++;
+ return true;
+}
+
+bool client_list_remove(client_list* list, int fd) {
+ int i = 0;
+ for(i = 0; i < list->num; i++) {
+ if(list->clients[i].fd == fd) {
+ for(; i < list->num - 1; i++) {
+ list->clients[i] = list->clients[i + 1];
+ }
+ memset(&list->clients[i], 0, sizeof(client_ctx));
+ list->num--;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool client_list_contains(client_list* list, int fd) {
+ int i = 0;
+ LOGD("to find fd:%d", fd);
+ for(i = 0; i < list->num; i++) {
+ if(list->clients[i].fd == fd) {
+ return true;
+ }
+ }
+ return false;
+}
+
+client_ctx* client_list_get_ctx_by_fd(client_list* list, int fd) {
+ unsigned int i = 0;
+ for(i = 0; i < list->num; i++) {
+ if(list->clients[i].fd == fd) {
+ return &list->clients[i];
+ }
+ }
+ return NULL;
+}
+
+bool client_list_is_all_gnss_stop(client_list* list) {
+ int i = 0;
+ for(i = 0; i < list->num; i++) {
+ if(list->clients[i].gnss_started) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool client_list_is_all_gnss_cleanup(client_list* list) {
+ int i = 0;
+ for(i = 0; i < list->num; i++) {
+ if(list->clients[i].gnss_inited) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool client_list_is_all_meas_stop(client_list* list) {
+ int i = 0;
+ for(i = 0; i < list->num; i++) {
+ if(list->clients[i].meas_started) {
+ return false;
+ }
+ }
+ return true;
+}
+
+int client_send_to_all(client_list* list, const char* buff, int len) {
+ int i = 0;
+ int ret = -1;
+
+ for(i = 0; i < list->num; i++) {
+ int fd = list->clients[i].fd;
+ ret = socket_tcp_send(fd, buff, len);
+ }
+ return ret;
+}
+
+extern client_list g_hal_basic_client_list;
+extern client_list g_hal_ext_client_list;
+
+int mnl2hal_basic(const char* buff, int len) {
+ int i = 0;
+ int ret = -1;
+
+ for(i = 0; i < g_hal_basic_client_list.num; i++) {
+ if(g_hal_basic_client_list.clients[i].gnss_started) {
+ int fd = g_hal_basic_client_list.clients[i].fd;
+ ret = socket_tcp_send(fd, buff, len);
+ }
+ }
+ return ret;
+}
+
+int mnl2hal_basic_all(const char* buff, int len) {
+ int i = 0;
+ int ret = -1;
+
+ for(i = 0; i < g_hal_basic_client_list.num; i++) {
+ int fd = g_hal_basic_client_list.clients[i].fd;
+ ret = socket_tcp_send(fd, buff, len);
+ }
+ return ret;
+}
+
+int mnl2hal_ext(const char* buff, int len) {
+ return client_send_to_all(&g_hal_ext_client_list, buff, len);
+}
+
+wake_lock_ctx wlock_ctx;
+
+void mnld_wake_lock() {
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+ int fd = open("/sys/power/wake_lock", O_RDWR | O_NONBLOCK);
+ if(fd == -1) {
+ LOGE("open() failed, reason=[%s]%d", strerror(errno), errno);
+ return;
+ }
+
+ int ret = write(fd, MNLD_WAKE_LOCK_ID, strlen(MNLD_WAKE_LOCK_ID));
+ if(ret == -1) {
+ LOGE("write() failed id=[%s], reason=[%s]%d", MNLD_WAKE_LOCK_ID, strerror(errno), errno);
+ close(fd);
+ return;
+ }
+
+ close(fd);
+#endif
+ return;
+}
+
+void mnld_wake_unlock() {
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_unlock on Linux
+ int fd = open("/sys/power/wake_unlock", O_RDWR | O_NONBLOCK);
+ if(fd == -1) {
+ LOGE("open() failed, reason=[%s]%d", strerror(errno), errno);
+ return;
+ }
+
+ int ret = write(fd, MNLD_WAKE_LOCK_ID, strlen(MNLD_WAKE_LOCK_ID));
+ if(ret == -1) {
+ LOGE("write() failed id=[%s], reason=[%s]%d", MNLD_WAKE_LOCK_ID, strerror(errno), errno);
+ close(fd);
+ return;
+ }
+
+ close(fd);
+#endif
+ return;
+}
+
+int mnld_wakeup_mutex_lock() {
+ int ret = pthread_mutex_lock(&wlock_ctx.mutex);
+ if(ret != 0) {
+ LOGE("pthread_mutex_lock() failed, reason=[%s]%d", strerror(ret), ret);
+ }
+ return ret;
+}
+
+int mnld_wakeup_mutex_unlock() {
+ int ret = pthread_mutex_unlock(&wlock_ctx.mutex);
+ if(ret != 0) {
+ LOGE("pthread_mutex_unlock() failed, reason=[%s]%d", strerror(ret), ret);
+ }
+
+ return ret;
+}
+
+void mnld_wake_lock_take() {
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+ UINT64 time_cur = 0;
+ time_cur = get_time_in_millisecond();
+
+ if(time_cur > (wlock_ctx.time_last_refresh + MNLD_WAKE_LOCK_LATENCY)) {
+ int mutex_ret = 0;
+ stop_timer(wlock_ctx.unlock_timer);
+ mutex_ret = mnld_wakeup_mutex_lock();
+ if(wlock_ctx.wake_lock_acquired == false) {
+ wlock_ctx.wake_lock_acquired = true;
+ mnld_wake_lock();
+ }
+ if(mutex_ret == 0) {
+ mnld_wakeup_mutex_unlock();
+ }
+ }
+#endif
+}
+
+void mnld_wake_lock_give() {
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+ UINT64 time_cur = 0;
+ //delay to do wake_unlock to ensure the msg can be deliveried to other process
+ time_cur = get_time_in_millisecond();
+ if(time_cur > (wlock_ctx.time_last_refresh + MNLD_WAKE_LOCK_LATENCY)) { //Only refresh timer when over latency time
+ start_timer(wlock_ctx.unlock_timer, MNLD_WAKE_LOCK_TIMEOUT);
+ wlock_ctx.time_last_refresh = get_time_in_millisecond();
+ }
+#endif
+}
+
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+static void mnld_timer_wake_unlock_routine(int id) {
+ int mutex_ret = 0;
+ //do not use the internal msg or it will cause infinite loop in epoll_wait
+ mutex_ret = mnld_wakeup_mutex_lock();
+ if(wlock_ctx.wake_lock_acquired == true) {
+ wlock_ctx.wake_lock_acquired = false;
+ mnld_wake_unlock();
+ }
+ if(mutex_ret == 0) {
+ mnld_wakeup_mutex_unlock();
+ }
+}
+#endif
+
+void mnld_wake_lock_init() {
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+ int ret = 0;
+ int read_len = 0;
+ char buff_read[MNLD_WAKELOCK_BUFF_SIZE] = {0};
+
+ int fd = open("/sys/power/wake_lock", O_RDWR | O_NONBLOCK);
+ if(fd == -1) {
+ LOGE("open() failed, reason=[%s]%d", strerror(errno), errno);
+ return;
+ }
+
+ read_len = read(fd, buff_read, sizeof(buff_read)-1);
+ buff_read[MNLD_WAKELOCK_BUFF_SIZE -1] = 0;
+ if(read_len >= strlen(MNLD_WAKE_LOCK_ID) && strstr(buff_read, MNLD_WAKE_LOCK_ID) != NULL) {
+ mnld_wake_unlock();
+ }
+ LOGD("wake_lock:[%s]", buff_read);
+ close(fd);
+
+ memset(&wlock_ctx, 0, sizeof(wlock_ctx));
+ wlock_ctx.wake_lock_acquired = false;
+ wlock_ctx.unlock_timer = init_timer(mnld_timer_wake_unlock_routine);
+ if(wlock_ctx.unlock_timer == INVALID_TIMERID) {
+ LOGE("init_timer(mnld_timer_wake_unlock_routine, 0) failed");
+ exit(1);
+ }
+
+ ret = pthread_mutex_init(&wlock_ctx.mutex, NULL);
+ if(ret != 0) {
+ LOGE("pthread_mutex_init() failed, reason=[%s]%d", strerror(errno), errno);
+ exit(1);
+ }
+#endif
+}
+
+void mnld_wake_lock_deinit() {
+#if !defined(__LIBMNL_SIMULATOR__) //no permission to open wake_lock on Linux
+ deinit_timer(wlock_ctx.unlock_timer);
+ wlock_ctx.unlock_timer = INVALID_TIMERID;
+ pthread_mutex_destroy(&wlock_ctx.mutex);
+#endif
+}
+
+#endif //__LINUX_OS__
+
+void set_signal_ignore(int signo) {
+ sigset_t signal_mask;
+
+ LOGD("set_signal_ignore, signo:%d", signo);
+ if(sigemptyset(&signal_mask) < 0) {
+ LOGW("sigemptyset fail, %s(%d)", strerror(errno), errno);
+ }
+ if(sigaddset(&signal_mask, signo) < 0) {
+ LOGW("sigaddset fail, %s(%d)", strerror(errno), errno);
+ }
+ if(sigprocmask(SIG_BLOCK, &signal_mask, NULL) < 0) {
+ LOGW("sigprocmask fail, %s(%d)", strerror(errno), errno);
+ }
+}
diff --git a/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_mnld_dump.cpp b/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_mnld_dump.cpp
new file mode 100644
index 0000000..9708f84
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_mnld_dump.cpp
@@ -0,0 +1,201 @@
+#include <fcntl.h> /* File control definitions */
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string>
+
+#include "gps_dbg_log.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_gps_type.h"
+#if defined(__ANDROID_OS__)
+#include "libladder.h"
+#include "LbsLogInterface.h"
+#include <cutils/properties.h>
+#endif
+#include "mtk_prop_util.h"
+#include "mtk_mnld_log.h"
+
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "MNLD_DUMP"
+
+#define MNLD_DUMP_FILE_LEN 128
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern bool mnld2logd_open_dumplog(char* file);
+extern bool mnld2logd_write_dumplog(char * data, int len);
+extern bool mnld2logd_close_dumplog(void);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+/**Disable mnld process dump, due to have never used mnld dump infor, and often blocked in unwind backtrace**/
+//#define MNLD_PROCESS_DUMP
+
+#ifdef MNLD_PROCESS_DUMP
+char mnld_dump_file[] = "mnld";
+/*****************************************************************************
+ * FUNCTION
+ * mnld_dump_get_filename
+ * DESCRIPTION
+ * To generate the full name of dump file
+ * PARAMETERS
+ * dump_filename [OUT] the string to store the full name of dump file
+ * length [IN] the max length of dump_filename
+ * RETURNS
+ * None
+ *****************************************************************************/
+void mnld_dump_get_filename(char *dump_filename, size_t length)
+{
+ char path[MNLD_DUMP_FILE_LEN] = {0};
+
+ do {
+#if ANDROID_MNLD_PROP_SUPPORT
+ char path_result[PROPERTY_VALUE_MAX] = {0};
+
+ if (property_get(GPS_LOG_PERSIST_PATH, path_result, NULL) //Store the dump file under GPS debug log folder
+ && (strcmp(path_result, GPS_LOG_PERSIST_VALUE_NONE) != 0)) {
+ MNLD_STRNCPY(path, path_result, length);
+ } else {
+ LOGW("log path not set!");
+ break;
+ }
+#endif
+ if(dump_filename == NULL)
+ {
+ LOGW("input NULL pointer!!!");
+ break;
+ }
+
+ memset(dump_filename, 0x00, length);
+
+ snprintf(dump_filename, length, "%s%s_%d.dumpc",
+ path, mnld_dump_file, getpid());
+ LOGD("dump file:%s", dump_filename);
+ } while(0);
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * mnld_dump_process
+ * DESCRIPTION
+ * Dump all threads of current process.
+ * PARAMETERS
+ * dump_fd [IN] the file descripter to dump in to, -1: dump to mainlog
+ *
+ * RETURNS
+ * None
+ *****************************************************************************/
+void mnld_dump_process(int dump_fd) {
+ std::string dump;
+ if (dump_fd == NULL) {
+ char data[LBS_LOG_INTERFACE_BUFF_SIZE] = {0};
+ unsigned int len = 0;
+ unsigned int i = 0;
+ unsigned int n = 0;
+ unsigned int data_max = 0;
+ if (LBS_LOG_INTERFACE_BUFF_SIZE > 4*sizeof(int)) {
+ data_max = LBS_LOG_INTERFACE_BUFF_SIZE - 4*sizeof(int);
+ } else {
+ LOGE("LBS_LOG_INTERFACE_BUFF_SIZE too log (%u)", LBS_LOG_INTERFACE_BUFF_SIZE);
+ return;
+ }
+ UnwindCurProcessBT(&dump);
+ len = dump.length();
+ n = (len + (data_max-1))/data_max;
+ for (i=0; i<n; i++) {
+ memset(data, 0x0, LBS_LOG_INTERFACE_BUFF_SIZE);
+ strncpy(data, dump.c_str()+i*data_max, data_max);
+ data[data_max] = '\0';
+ if (!mnld2logd_write_dumplog(data, strlen(data))) {
+ LOGE("send write dump file cmd faile(%s)", strerror(errno));
+ }
+ }
+ //write(dump_fd, dump.c_str(), dump.length()); //Dump to file
+ } else {
+ UnwindCurProcessBT(&dump);
+ if(dump_fd != -1) {
+ write(dump_fd, dump.c_str(), dump.length()); //Dump to file
+ }
+ }
+}
+#if 0
+/*****************************************************************************
+ * FUNCTION
+ * mnld_dump_thread
+ * DESCRIPTION
+ * To dump specified thread's backtrace.
+ * [Not used until now, keep here for demo code]
+ * PARAMETERS
+ * dump_fd [IN] the file descripter to dump in to, -1: dump to mainlog
+ * tid [IN] the thread id(tid) need to be dumped
+ *
+ * RETURNS
+ * None
+ *****************************************************************************/
+void mnld_dump_thread(int dump_fd, pid_t tid) { //Dump specific thread backtrace
+ std::string dump;
+ UnwindCurThreadBT(&dump);
+ if(dump_fd != -1) {
+ write(dump_fd, dump.c_str(), dump.length()); //Dump to file
+ LOGD("mnld_dump_thread tid:(%d)", tid);
+ }
+}
+#endif
+#endif
+/*****************************************************************************
+ * FUNCTION
+ * mnld_dump_exit
+ * DESCRIPTION
+ * To dump specified thread's backtrace and exit current process.
+ * If the tid equal to current process id(pid), will dump all threads of current process.
+ * PARAMETERS
+ * tid [IN] the thread id(tid) need to be dumped
+ *
+ * RETURNS
+ * None
+ *****************************************************************************/
+extern "C" void mnld_dump_exit(void)
+{
+#ifdef MNLD_PROCESS_DUMP
+ if (gps_dbg_log_output2file()) {
+ int dump_fd = 0;
+ char dump_file_full[MNLD_DUMP_FILE_LEN] = {0};
+ char dump_file_full2[MNLD_DUMP_FILE_LEN] = {0};
+
+ mnld_dump_get_filename(dump_file_full, MNLD_DUMP_FILE_LEN);
+ dump_fd = open(dump_file_full, O_RDWR|O_NONBLOCK|O_CREAT, 0660);
+ mnld_dump_process(dump_fd);
+ if(dump_fd != -1) {
+ MNLD_STRNCPY(dump_file_full2, dump_file_full, MNLD_DUMP_FILE_LEN);
+ dump_file_full2[strlen(dump_file_full2)-1] = '\0';
+ if(rename(dump_file_full, dump_file_full2) != 0) {
+ LOGW("rename faile(%s)", strerror(errno));
+ }
+ close(dump_fd);
+ }
+ }
+
+ if (gps_dbg_log_output2socket()) {
+ char dump_file_full[MNLD_DUMP_FILE_LEN] = {0};
+ mnld_dump_get_filename(dump_file_full, MNLD_DUMP_FILE_LEN);
+ //dump_fd = open(dump_file_full, O_RDWR|O_NONBLOCK|O_CREAT, 0660);
+ if(!mnld2logd_open_dumplog(dump_file_full)) {
+ LOGE("send create dump file cmd faile(%s)", strerror(errno));
+ } else {
+ mnld_dump_process(NULL);
+ mnld2logd_close_dumplog();
+ }
+ }
+#endif
+ if (gps_dbg_log_output2file())
+ gps_dbg_log_exit_flush(0);
+ _exit(0);
+}
diff --git a/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_mnld_log.c b/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_mnld_log.c
new file mode 100644
index 0000000..09cb857
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_mnld_log.c
@@ -0,0 +1,125 @@
+/*
+* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2017. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*/
+#include <sys/time.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+#include <memory.h>
+
+#include "mtk_mnld_log.h"
+
+#if defined(__LINUX_OS__)
+// -1 means failure
+int get_time_str(char* buf, int len) {
+#if 0 //Fix build error
+ struct timeval tv;
+ struct timezone tz;
+ struct tm *tm;
+
+ gettimeofday(&tv, &tz);
+ tm = localtime(&tv.tv_sec);
+
+ memset(buf, 0, len);
+ sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d.%03d",
+ tm->tm_year + 1900, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min,
+ tm->tm_sec, (int)(tv.tv_usec / 1000));
+
+ return 0;
+#else
+ time_t now = time(NULL);
+ struct tm tm_utc;
+ time_t time_utc;
+
+ gmtime_r(&now, &tm_utc);
+ time_utc = mktime(&tm_utc);
+
+ memset(buf, 0, len);
+ sprintf(buf, "%s", ctime(&time_utc));
+
+ buf[strlen(buf)-1] = '\0'; //Remove '\n'
+
+ return 0;
+#endif
+}
+#endif
+
+int set_log_level(int *dst_level, int src_level)
+{
+#if defined(__ANDROID_OS__)
+
+ ALOGI("Current debug level=%d", *dst_level);
+
+ if (src_level < L_VERBOSE || src_level > L_SUPPRESS)
+ {
+ ALOGE("Invalid debug level, level=%d", src_level);
+ ALOGE(" [level] -");
+ ALOGE(" QUIET = 6");
+ ALOGE(" ASSERT = 5");
+ ALOGE(" ERROR = 4");
+ ALOGE(" WARNING = 3");
+ ALOGE(" INFO = 2");
+ ALOGE(" DEBUG = 1");
+ ALOGE(" LOGALL = 0");
+ return -1;
+ }
+
+ *dst_level = src_level;
+
+ ALOGI("New debug level=%d", *dst_level);
+
+#elif defined(__LINUX_OS__)
+
+ printf("Current debug level=%d\n", *dst_level);
+
+ if (src_level < L_VERBOSE || src_level > L_SUPPRESS)
+ {
+ printf("Invalid debug level, level=%d", src_level);
+ printf(" [level] -");
+ printf(" QUIET = 6");
+ printf(" ASSERT = 5");
+ printf(" ERROR = 4");
+ printf(" WARNING = 3");
+ printf(" INFO = 2");
+ printf(" DEBUG = 1");
+ printf(" LOGALL = 0");
+ return -1;
+ }
+
+ *dst_level = src_level;
+
+ printf("New debug level=%d\n", *dst_level);
+
+#endif
+ return 0;
+}
diff --git a/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_prop_util.c b/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_prop_util.c
new file mode 100644
index 0000000..5d3a563
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_prop_util.c
@@ -0,0 +1,17 @@
+#if defined(__LINUX_OS__)
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "mtk_prop_util.h"
+
+int property_set(char *prop, char *value)
+{
+ //To-do
+ return 0;
+}
+int property_get(char *prop, char *value, char *default_value)
+{
+ //To-do
+ return 0;
+}
+#endif
diff --git a/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_socket_data_coder.c b/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_socket_data_coder.c
new file mode 100644
index 0000000..455593d
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_socket_data_coder.c
@@ -0,0 +1,256 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include "mtk_socket_data_coder.h"
+
+bool mtk_socket_get_bool(char* buff, int* offset) {
+ bool ret = (mtk_socket_get_char(buff, offset) == 0)? false : true;
+ return ret;
+}
+
+char mtk_socket_get_char(char* buff, int* offset) {
+ char ret = buff[*offset];
+ *offset += 1;
+ return ret;
+}
+
+short mtk_socket_get_short(char* buff, int* offset) {
+ short ret = 0;
+ ret |= mtk_socket_get_char(buff, offset) & 0xff;
+ ret |= (mtk_socket_get_char(buff, offset) << 8);
+ return ret;
+}
+
+int mtk_socket_get_int(char* buff, int* offset) {
+ int ret = 0;
+ ret |= mtk_socket_get_short(buff, offset) & 0xffff;
+ ret |= (mtk_socket_get_short(buff, offset) << 16);
+ return ret;
+}
+
+int64_t mtk_socket_get_int64_t(char* buff, int* offset) {
+ int64_t ret = 0;
+ ret |= mtk_socket_get_int(buff, offset) & 0xffffffffL;
+ ret |= ((int64_t)mtk_socket_get_int(buff, offset) << 32);
+ return ret;
+}
+
+float mtk_socket_get_float(char* buff, int* offset) {
+ float ret;
+ int tmp = mtk_socket_get_int(buff, offset);
+ ret = *((float*)&tmp);
+ return ret;
+}
+
+double mtk_socket_get_double(char* buff, int* offset) {
+ double ret;
+ int64_t tmp = mtk_socket_get_int64_t(buff, offset);
+ ret = *((double*)&tmp);
+ return ret;
+}
+
+int mtk_socket_get_string(char* buff, int* offset, char* output, int max_size) {
+ int size = mtk_socket_get_int(buff, offset);
+ memset(output, 0, max_size);
+ memcpy(output, &buff[*offset], (size > max_size)? max_size : size);
+ output[max_size - 1] = 0;
+ *offset += size;
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_bool_array(char* buff, int* offset, bool output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ bool data = mtk_socket_get_bool(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_char_array(char* buff, int* offset, char output[], int max_size) {
+ int size = mtk_socket_get_int(buff, offset);
+ memcpy(output, &buff[*offset], (size > max_size)? max_size : size);
+ *offset += size;
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_short_array(char* buff, int* offset, short output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ short data = mtk_socket_get_short(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_int_array(char* buff, int* offset, int output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ int data = mtk_socket_get_int(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_int64_t_array(char* buff, int* offset, int64_t output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ int64_t data = mtk_socket_get_int64_t(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_float_array(char* buff, int* offset, float output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ float data = mtk_socket_get_float(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_double_array(char* buff, int* offset, double output[], int max_size) {
+ int i = 0;
+ int size = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size; i++) {
+ double data = mtk_socket_get_double(buff, offset);
+ if(i < max_size) {
+ output[i] = data;
+ }
+ }
+ return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_string_array(char* buff, int* offset, void* output, int max_size1, int max_size2) {
+ int i = 0;
+ int size1 = mtk_socket_get_int(buff, offset);
+ for(i = 0; i < size1; i++) {
+ if(i < max_size1) {
+ mtk_socket_get_string(buff, offset, output, max_size2);
+ output = (char*)output + max_size2;
+ } else {
+ char tmp[max_size2];
+ mtk_socket_get_string(buff, offset, tmp, max_size2);
+ }
+ }
+ return (size1 > max_size1)? max_size1 : size1;
+}
+
+void mtk_socket_put_bool(char* buff, int* offset, bool input) {
+ mtk_socket_put_char(buff, offset, input);
+}
+
+void mtk_socket_put_char(char* buff, int* offset, char input) {
+ *((char*)&buff[*offset]) = input;
+ *offset += 1;
+}
+
+void mtk_socket_put_short(char* buff, int* offset, short input) {
+ mtk_socket_put_char(buff, offset, input & 0xff);
+ mtk_socket_put_char(buff, offset, (input >> 8) & 0xff);
+}
+
+void mtk_socket_put_int(char* buff, int* offset, int input) {
+ mtk_socket_put_short(buff, offset, input & 0xffff);
+ mtk_socket_put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void mtk_socket_put_int64_t(char* buff, int* offset, int64_t input) {
+ mtk_socket_put_int(buff, offset, input & 0xffffffffL);
+ mtk_socket_put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void mtk_socket_put_float(char* buff, int* offset, float input) {
+ int* data = (int*)&input;
+ mtk_socket_put_int(buff, offset, *data);
+}
+
+void mtk_socket_put_double(char* buff, int* offset, double input) {
+ int64_t* data = (int64_t*)&input;
+ mtk_socket_put_int64_t(buff, offset, *data);
+}
+
+void mtk_socket_put_string(char* buff, int* offset, const char* input) {
+ int len = strlen(input);
+ mtk_socket_put_int(buff, offset, len);
+ memcpy(&buff[*offset], input, len);
+ *offset += len;
+}
+
+void mtk_socket_put_bool_array(char* buff, int* offset, bool input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_bool(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_char_array(char* buff, int* offset, const char input[], int size) {
+ mtk_socket_put_int(buff, offset, size);
+ memcpy(&buff[*offset], input, size);
+ *offset += size;
+}
+
+void mtk_socket_put_short_array(char* buff, int* offset, const short input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_short(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_int_array(char* buff, int* offset, const int input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_int(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_int64_t_array(char* buff, int* offset, int64_t input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_int64_t(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_float_array(char* buff, int* offset, float input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_float(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_double_array(char* buff, int* offset, double input[], int size) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size);
+ for(i = 0; i < size; i++) {
+ mtk_socket_put_double(buff, offset, input[i]);
+ }
+}
+
+void mtk_socket_put_string_array(char* buff, int* offset, void* input, int size1, int size2) {
+ int i = 0;
+ mtk_socket_put_int(buff, offset, size1);
+ for(i = 0; i < size1; i++) {
+ mtk_socket_put_string(buff, offset, (char*)input);
+ input = (char*)input + size2;
+ }
+}
+
diff --git a/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_socket_utils.c b/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_socket_utils.c
new file mode 100644
index 0000000..162c560
--- /dev/null
+++ b/src/connectivity/gps/2.0/mtk_mnld/utility/src/mtk_socket_utils.c
@@ -0,0 +1,728 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include "mtk_socket_utils.h"
+#include "mtk_socket_data_coder.h"
+#include "mtk_lbs_utility.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h> //usleep
+#include <sys/socket.h>
+#include <string.h>
+#include <fcntl.h>
+#include <arpa/inet.h> //inet_addr
+#include <sys/un.h> //struct sockaddr_un
+#include <sys/epoll.h>
+#include <poll.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <inttypes.h> //PRId64
+#include <unistd.h> //usleep
+
+#if defined(__ANDROID_OS__)
+#include <cutils/log.h> // Android log
+
+#define ANDROID_LOG_TAG "mtk_socket"
+#endif
+
+# define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose
+
+/* Structure to contain information about address of a service provider. */
+struct addrinfo
+{
+ int ai_flags; /* Input flags. */
+ int ai_family; /* Protocol family for socket. */
+ int ai_socktype; /* Socket type. */
+ int ai_protocol; /* Protocol for socket. */
+ socklen_t ai_addrlen; /* Length of socket address. */
+ struct sockaddr *ai_addr; /* Socket address for socket. */
+ char *ai_canonname; /* Canonical name for service location. */
+ struct addrinfo *ai_next; /* Pointer to next in list. */
+};
+
+
+// -1 means failure
+static int mtk_socket_set_reuse_addr(int fd, bool reuse) {
+ int val = (int)reuse;
+ int newval;
+ socklen_t intlen = sizeof(newval);
+
+ if (0 != setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) {
+ SOCK_LOGE("setsockopt(SO_REUSEADDR) fail %s(%d)", strerror(errno), errno);
+ return -1;
+ }
+
+ if (0 != getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &newval, &intlen)) {
+ SOCK_LOGE("getsockopt(SO_REUSEADDR) fail %s(%d)", strerror(errno), errno);
+ return -1;
+ }
+
+ if (newval != val) {
+ SOCK_LOGE("Failed to set SO_REUSEADDR");
+ return -1;
+ }
+
+ return 0;
+}
+
+#if 0
+//-1 means failure
+static int get_time_str(char* buff, int len) {
+ struct timeval tv;
+ struct timezone tz;
+ struct tm *tm;
+
+ gettimeofday(&tv, &tz);
+ tm = localtime(&tv.tv_sec);
+
+ memset(buff, 0, len);
+ if(tm != NULL) {
+ MNLD_SPRINTF(buff, "%04d/%02d/%02d %02d:%02d:%02d.%03d",
+ tm->tm_year + 1900, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min,
+ tm->tm_sec, (int)(tv.tv_usec / 1000));
+ }
+ return 0;
+}
+#endif
+
+void _mtk_socket_log(int type, const char *fmt, ...) {
+ char buff[1024] = {0};
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (vsnprintf(buff, sizeof(buff), fmt, ap) < 0){
+ SOCK_LOGE("_mtk_socket_log vsnprintf error occurred");
+ }
+ va_end(ap);
+
+#if defined(__ANDROID_OS__)
+ if(type == 0) {
+ __android_log_print(ANDROID_LOG_DEBUG, ANDROID_LOG_TAG, "%s", buff);
+ } else {
+ __android_log_print(ANDROID_LOG_ERROR, ANDROID_LOG_TAG, "ERR: %s", buff);
+ }
+#else
+ char time_buff[64] = {0};
+ get_time_str(time_buff, sizeof(time_buff));
+ if(type == 0) {
+ printf("%s %s\n", time_buff, buff);
+ } else {
+ printf("%s ERR: %s\n", time_buff, buff);
+ }
+#endif
+}
+
+//-1 means failure
+int mtk_socket_server_bind_network(int port) {
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0) {
+ SOCK_LOGE("mtk_socket_server_bind_network() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+ SOCK_LOGE("mtk_socket_server_bind_network() bind() failed reason=[%s]%d for port=[%d]",
+ strerror(errno), errno, port);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+//-1 means failure
+int mtk_socket_server_bind_network_ipv6(int port) {
+ struct sockaddr_in6 addr;
+ memset(&addr, 0, sizeof(addr));
+ int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0) {
+ SOCK_LOGE("mtk_socket_server_bind_network_ipv6() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ addr.sin6_family = AF_INET6;
+ addr.sin6_port = htons(port);
+ addr.sin6_addr = in6addr_any;
+ if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+ SOCK_LOGE("mtk_socket_server_bind_network_ipv6() bind() failed reason=[%s]%d for port=[%d]",
+ strerror(errno), errno, port);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+//-1 means failure
+int mtk_socket_server_bind_local(const char* path, mtk_socket_namespace sock_namespace) {
+ int size;
+ struct sockaddr_un addr;
+ int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ SOCK_LOGE("mtk_socket_server_bind_local() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ size = strlen(path) + offsetof(struct sockaddr_un, sun_path) + 1;
+ if(sock_namespace == SOCK_NS_ABSTRACT) {
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, path, strlen(path));
+ } else if(sock_namespace == SOCK_NS_FILESYSTEM) {
+ safe_strncpy(addr.sun_path, path, sizeof(addr.sun_path));
+ unlink(addr.sun_path);
+ } else {
+ SOCK_LOGE("mtk_socket_server_bind_local() unknown namespace=[%d]", sock_namespace);
+ close(fd);
+ return -1;
+ }
+
+ if(mtk_socket_set_reuse_addr(fd, true) == -1) {
+ SOCK_LOGE("mtk_socket_server_bind_local() mtk_socket_set_reuse_addr() failed path=[%s] reason=[%s]%d",
+ path, strerror(errno), errno);
+ }
+
+ if (bind(fd, (struct sockaddr *)&addr, size) == -1) {
+ SOCK_LOGE("mtk_socket_server_bind_local() bind() failed reason=[%s]%d for path=[%s]",
+ strerror(errno), errno, path);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+
+void mtk_socket_client_init_network(mtk_socket_fd* sock_fd, const char* host, int port) {
+ int len = strlen(host);
+ memset(sock_fd, 0, sizeof(*sock_fd));
+ sock_fd->fd = -1;
+ sock_fd->is_local = false;
+ pthread_mutex_init(&sock_fd->mutex, NULL);
+ sock_fd->host = malloc(len + 1);
+ if (sock_fd->host != NULL){
+ safe_strncpy(sock_fd->host, host, len + 1);
+ }
+ sock_fd->port = port;
+}
+
+void mtk_socket_client_init_local(mtk_socket_fd* sock_fd, const char* path, mtk_socket_namespace sock_namespace) {
+ int len = strlen(path);
+ memset(sock_fd, 0, sizeof(*sock_fd));
+ sock_fd->fd = -1;
+ sock_fd->is_local = true;
+ pthread_mutex_init(&sock_fd->mutex, NULL);
+ sock_fd->path = malloc(len + 1);
+ if (sock_fd->path != NULL){
+ safe_strncpy(sock_fd->path, path, len + 1);
+ }
+ sock_fd->namesapce = sock_namespace;
+}
+
+void mtk_socket_client_cleanup(mtk_socket_fd* sock_fd) {
+ mtk_socket_client_close(sock_fd);
+ if(sock_fd->host) {
+ free(sock_fd->host);
+ sock_fd->host = NULL;
+ }
+ if(sock_fd->path) {
+ free(sock_fd->path);
+ sock_fd->path = NULL;
+ }
+}
+
+static bool mtk_socket_connect_local(mtk_socket_fd* sock_fd) {
+ int size;
+ struct sockaddr_un addr;
+ int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ SOCK_LOGE("mtk_socket_connect_local() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return false;
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_LOCAL;
+ size = strlen(sock_fd->path) + offsetof(struct sockaddr_un, sun_path) + 1;
+ if(sock_fd->namesapce == SOCK_NS_ABSTRACT) {
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, sock_fd->path, strlen(sock_fd->path));
+ } else if(sock_fd->namesapce == SOCK_NS_FILESYSTEM) {
+ safe_strncpy(addr.sun_path, sock_fd->path, sizeof(addr.sun_path));
+ } else {
+ SOCK_LOGE("mtk_socket_connect_local() unknown namespace=[%d]", sock_fd->namesapce);
+ close(fd);
+ return false;
+ }
+ if (connect(fd, (struct sockaddr *)&addr, size) < 0) {
+ SOCK_LOGE("mtk_socket_connect_local() connect() failed reason=[%s]%d for path=[%s]",
+ strerror(errno), errno, sock_fd->path);
+ close(fd);
+ return false;
+ }
+ sock_fd->fd = fd;
+ return true;
+}
+
+static int mtk_socket_connect_network_ipv4(struct sockaddr_in* addr) {
+ int port = ntohs(addr->sin_port);
+ char ip_str[64] = {0};
+ inet_ntop(AF_INET, &(addr->sin_addr), ip_str, sizeof(ip_str));
+ int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0) {
+ SOCK_LOGE("mtk_socket_connect_network_ipv4() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ //SOCK_LOGD("mtk_socket_connect_network_ipv4() IPv4=[%s] port=[%d]", ip_str, port);
+ if (connect(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
+ SOCK_LOGE("mtk_socket_connect_network_ipv4() connect() failed reason=[%s]%d for host=[%s] port=[%d]",
+ strerror(errno), errno, ip_str, port);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+//-1 means failure
+static int mtk_socket_connect_network_ipv6(struct sockaddr_in6* addr) {
+ int port = ntohs(addr->sin6_port);
+ int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0) {
+ SOCK_LOGE("mtk_socket_connect_network_ipv6() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+ //unsigned char* ipv6_addr = addr->sin6_addr.s6_addr;
+ //SOCK_LOGD("mtk_socket_connect_network_ipv6() IPv6=[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x] port=[%d]",
+ // ipv6_addr[0], ipv6_addr[1], ipv6_addr[2], ipv6_addr[3], ipv6_addr[4], ipv6_addr[5], ipv6_addr[6], ipv6_addr[7],
+ // ipv6_addr[8], ipv6_addr[9], ipv6_addr[10], ipv6_addr[11], ipv6_addr[12], ipv6_addr[13], ipv6_addr[14], ipv6_addr[15],
+ // port);
+ if (connect(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
+ SOCK_LOGE("mtk_socket_connect_network_ipv6() connect() failed reason=[%s]%d for port=[%d]",
+ strerror(errno), errno, port);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+static bool mtk_socket_connect_network(mtk_socket_fd* sock_fd) {
+ struct addrinfo hints;
+ struct addrinfo *result;
+ struct addrinfo *rp;
+ int ret;
+ char port_str[11] = {0};
+ MNLD_SPRINTF(port_str, "%u", sock_fd->port);
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6, AF_UNSPEC, AF_INET, AF_INET6
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_ADDRCONFIG; // check local system
+ hints.ai_protocol = IPPROTO_UDP;
+ ret = getaddrinfo(sock_fd->host, port_str, &hints, &result);
+ if(ret != 0) {
+ SOCK_LOGE("mtk_socket_connect_network() getaddrinfo() failure reason=[%s] %d\n",
+ gai_strerror(ret), ret);
+ return false;
+ }
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+ if(rp->ai_family == AF_INET) {
+ ret = mtk_socket_connect_network_ipv4((struct sockaddr_in*)rp->ai_addr);
+ if(ret >= 0) {
+ sock_fd->fd = ret;
+ break;
+ }
+ }
+ if(rp->ai_family == AF_INET6) {
+ ret = mtk_socket_connect_network_ipv6((struct sockaddr_in6*)rp->ai_addr);
+ if(ret >= 0) {
+ sock_fd->fd = ret;
+ break;
+ }
+ }
+ }
+ freeaddrinfo(result);
+ if(ret >= 0) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool mtk_socket_client_connect(mtk_socket_fd* sock_fd) {
+ if(sock_fd->is_local) {
+ return mtk_socket_connect_local(sock_fd);
+ } else {
+ return mtk_socket_connect_network(sock_fd);
+ }
+}
+
+void mtk_socket_client_close(mtk_socket_fd* sock_fd) {
+ if(sock_fd->fd >= 0) {
+ close(sock_fd->fd);
+ sock_fd->fd = -1;
+ }
+}
+
+//-1 means failure
+int mtk_socket_read(int fd, char* buff, int len) {
+ int n, retry = 10;
+ unsigned int len_max;
+ if(fd < 0 || buff == NULL || len < 0) {
+ SOCK_LOGE("mtk_socket_read() invalid params fd=[%d] buff=[%p] len=[%d]", fd, buff, len);
+ return -1;
+ }
+ if(len <= 1) {
+ return 0;
+ } else {
+ len_max = len-1;
+ }
+ while((n = read(fd, buff, (len-1))) < 0) {
+ if(errno == EINTR) continue;
+ if(errno == EAGAIN) {
+ if(retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ goto exit;
+ }
+ goto exit;
+ }
+ buff[len_max] = 0;
+ return n;
+exit:
+ SOCK_LOGE("mtk_socket_read() read() failed, fd=[%d] len=[%d] errno=[%s]%d",
+ fd, len, strerror(errno), errno);
+ return -1;
+}
+
+//-1 means failure
+int mtk_socket_write(int fd, void* buff, int len) {
+ int n, retry = 10;
+ if(fd < 0 || buff == NULL || len < 0) {
+ SOCK_LOGE("mtk_socket_write() invalid params fd=[%d] buff=[%p] len=[%d]", fd, buff, len);
+ return -1;
+ }
+ while((n = write(fd, buff, len)) != len) {
+ if(errno == EINTR) continue;
+ if(errno == EAGAIN) {
+ if(retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ goto exit;
+ }
+ goto exit;
+ }
+ return n;
+exit:
+ SOCK_LOGE("mtk_socket_write() write() failed, fd=[%d] len=[%d] errno=[%s]%d\n",
+ fd, len, strerror(errno), errno);
+ return -1;
+}
+
+// <= 0 means no data received
+int mtk_socket_poll(int fd, int timeout) {
+ struct pollfd poll_fd[1];
+ int ret = 0;
+ memset(poll_fd, 0, sizeof(poll_fd));
+ poll_fd[0].fd = fd;
+ poll_fd[0].events = POLLIN;
+ poll_fd[0].revents = 0;
+
+ ret = poll(poll_fd, 1, timeout);
+ if(ret > 0) {
+ if(poll_fd[0].revents & POLLIN ||
+ poll_fd[0].revents & POLLERR) {
+ ret = 1 << 0;
+ }
+ }
+ return ret;
+}
+
+void mtk_socket_buff_dump(const char* buff, int len) {
+ int i = 0;
+ char tmp[512] = {0};
+ SOCK_LOGD("mtk_socket_buff_dump len=%d", len);
+ for(i = 0; i < len; i++) {
+ if((i % 16 == 0) && (i != 0)) {
+ SOCK_LOGD(" %s", tmp);
+ memset(tmp, 0, sizeof(tmp));
+ }
+ sprintf(tmp + ((i % 16) * 3), "%02x ", buff[i] & 0xff);
+ }
+ if(i > 0) {
+ SOCK_LOGD(" %s", tmp);
+ }
+}
+
+bool mtk_socket_string_is_equal(char* data1, char* data2) {
+ return (strcmp(data1, data2) == 0)? true : false;
+}
+
+bool mtk_socket_bool_array_is_equal(bool data1[], int data1_size, bool data2[], int data2_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(data1[i] != data2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool mtk_socket_char_array_is_equal(char data1[], int data1_size, char data2[], int data2_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(data1[i] != data2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool mtk_socket_short_array_is_equal(short data1[], int data1_size, short data2[], int data2_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(data1[i] != data2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool mtk_socket_int_array_is_equal(int data1[], int data1_size, int data2[], int data2_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(data1[i] != data2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool mtk_socket_int64_t_array_is_equal(int64_t data1[], int data1_size, int64_t data2[], int data2_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(data1[i] != data2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool mtk_socket_float_array_is_equal(float data1[], int data1_size, float data2[], int data2_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(data1[i] != data2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool mtk_socket_double_array_is_equal(double data1[], int data1_size, double data2[], int data2_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(data1[i] != data2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool mtk_socket_string_array_is_equal(void* data1, int data1_size, void* data2, int data2_size, int string_size) {
+ int i = 0;
+ if(data1_size != data2_size) {
+ return false;
+ }
+ for(i = 0; i < data1_size; i++) {
+ if(!mtk_socket_string_is_equal(data1, data2)) {
+ return false;
+ }
+ data1 = (char*)data1 + string_size;
+ data2 = (char*)data2 + string_size;
+ }
+ return true;
+}
+
+void mtk_socket_bool_array_dump(bool input[], int size) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_bool_array_dump size=%d", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%d]", i, input[i]);
+ }
+}
+
+void mtk_socket_char_array_dump(char input[], int size) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_char_array_dump size=%d", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%d]", i, input[i] & 0xff);
+ }
+}
+
+void mtk_socket_short_array_dump(short input[], int size) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_short_array_dump size=%d", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%d]", i, input[i] & 0xffff);
+ }
+}
+
+void mtk_socket_int_array_dump(int input[], int size) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_int_array_dump size=%d", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%d]", i, input[i]);
+ }
+}
+
+void mtk_socket_int64_t_array_dump(int64_t input[], int size) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_int64_t_array_dump size=%d", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%lld]", i, (long long)input[i]);
+ }
+}
+
+void mtk_socket_float_array_dump(float input[], int size) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_float_array_dump size=%d", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%f]", i, input[i]);
+ }
+}
+
+void mtk_socket_double_array_dump(double input[], int size) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_double_array_dump size=%d", size);
+ for(i = 0; i < size; i++) {
+ SOCK_LOGD(" i=[%d] data=[%f]", i, input[i]);
+ }
+}
+
+void mtk_socket_string_array_dump(void* input, int size1, int size2) {
+ int i = 0;
+ SOCK_LOGD("mtk_socket_string_array_dump size1=%d size2=%d", size1, size2);
+ for(i = 0; i < size1; i++) {
+ SOCK_LOGD(" i=[%d] data=[%s]", i, (char*)input);
+ input = (char*)input + size2;
+ }
+}
+
+bool mtk_socket_expected_bool(char* buff, int* offset, bool expected_value, const char* func, int line) {
+ bool value = mtk_socket_get_bool(buff, offset);
+ if(value != expected_value) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_bool() failed, read=[%d], expected=[%d]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_socket_expected_char(char* buff, int* offset, char expected_value, const char* func, int line) {
+ char value = mtk_socket_get_char(buff, offset);
+ if(value != expected_value) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_char() failed, read=[%d], expected=[%d]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_socket_expected_short(char* buff, int* offset, short expected_value, const char* func, int line) {
+ short value = mtk_socket_get_short(buff, offset);
+ if(value != expected_value) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_short() failed, read=[%d], expected=[%d]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_socket_expected_int(char* buff, int* offset, int expected_value, const char* func, int line) {
+ int value = mtk_socket_get_int(buff, offset);
+ if(value != expected_value) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_int() failed, read=[%d], expected=[%d]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_socket_expected_int64_t(char* buff, int* offset, int64_t expected_value, const char* func, int line) {
+ int64_t value = mtk_socket_get_int64_t(buff, offset);
+ if(value != expected_value) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_int64_t() failed, read=[%"PRId64"], expected=[%"PRId64"]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_socket_expected_float(char* buff, int* offset, float expected_value, const char* func, int line) {
+ float value = mtk_socket_get_float(buff, offset);
+ if(value != expected_value) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_float() failed, read=[%f], expected=[%f]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_socket_expected_double(char* buff, int* offset, double expected_value, const char* func, int line) {
+ double value = mtk_socket_get_double(buff, offset);
+ if(value != expected_value) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_double() failed, read=[%f], expected=[%f]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+bool mtk_socket_expected_string(char* buff, int* offset, const char* expected_value, int max_size, const char* func, int line) {
+ char value[max_size];
+ mtk_socket_get_string(buff, offset, value, sizeof(value));
+ if(strcmp(value, expected_value) != 0) {
+ SOCK_LOGE("%s():%d mtk_socket_expected_string() failed, read=[%s], expected=[%s]",
+ func, line, value, expected_value);
+ return false;
+ }
+ return true;
+}
+
+char *safe_strncpy(char *dest, const char *src, size_t n) {
+ if (dest && n > 0) {
+ // Use strncat for performance because strncpy will always fill n bytes in dest
+ dest[0] = '\0'; // Let dest be an empty string
+ strncat(dest, src, --n); // n-1 because strncat may fill n+1 bytes
+ }
+ return dest;
+}
diff --git a/src/connectivity/libipsecims/Makefile b/src/connectivity/libipsecims/Makefile
new file mode 100644
index 0000000..4e7063a
--- /dev/null
+++ b/src/connectivity/libipsecims/Makefile
@@ -0,0 +1,39 @@
+CANLIB=libipsec_ims
+VERSION=1
+TARGET= $(CANLIB).so
+
+
+SO_CFLAGS= -shared
+CFLAGS?= -O2
+H_FILE = ${wildcard *.h}
+CUR_SOURCE=${wildcard *.c}
+CUR_OBJS=${patsubst %.c, %.o, $(CUR_SOURCE)}
+
+
+all: $(TARGET)
+
+
+install: install_headers
+ @mkdir -p $(DEST_DIR)/usr/lib
+ install -m 0644 $(CANLIB).so $(DEST_DIR)/usr/lib
+ install -m 0644 $(CANLIB).so.$(VERSION) $(DEST_DIR)/usr/lib
+
+install_headers:
+ @mkdir -p $(DEST_DIR)/usr/include
+ install -m 0644 *.h $(DEST_DIR)/usr/include
+
+
+%.o: %.c
+ $(CC) -Wall -fPIC $(CFLAGS) -c $^ -o $@
+$(TARGET).$(VERSION) : $(CUR_OBJS)
+ $(CC) -shared -nostartfiles -Wl,-soname,$@ $^ -o $@ $(LDFLAGS) -lpthread -lsncfg -llog
+
+
+
+$(TARGET): $(CANLIB).so.$(VERSION)
+ ln -s $< $@
+
+
+.PHONY: clean
+clean:
+ rm -f $(CANLIB).* $(CUR_OBJS)
\ No newline at end of file
diff --git a/src/connectivity/libipsecims/MediatekProprietary b/src/connectivity/libipsecims/MediatekProprietary
new file mode 100644
index 0000000..e6e7948
--- /dev/null
+++ b/src/connectivity/libipsecims/MediatekProprietary
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
\ No newline at end of file
diff --git a/src/connectivity/libipsecims/rtnl_socket.c b/src/connectivity/libipsecims/rtnl_socket.c
new file mode 100644
index 0000000..538066d
--- /dev/null
+++ b/src/connectivity/libipsecims/rtnl_socket.c
@@ -0,0 +1,152 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+#include "utils_xfrm.h"
+#include "setkey_xfrm_parse.h"
+#define LOG_TAG "setkey"
+#include <log/log.h>
+#include <cutils/log.h>
+
+
+void rtnl_close_xfrm(struct rtnl_handle_xfrm *rth_xfrm)
+{
+ if (rth_xfrm->fd >= 0) {
+ close(rth_xfrm->fd);
+ rth_xfrm->fd = -1;
+ }
+}
+
+int rtnl_open_byproto_xfrm(struct rtnl_handle_xfrm *rth_xfrm, unsigned subscriptions,
+ int protocol)
+{
+ //socklen_t addr_len;
+ //int sndbuf = 32768;
+
+ memset(rth_xfrm, 0, sizeof(*rth_xfrm));
+
+ rth_xfrm->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
+ if (rth_xfrm->fd < 0) {
+ ALOGD("Cannot open netlink socket,errno:%d\n",errno);
+ return -1;
+ }
+
+
+ memset(&rth_xfrm->local, 0, sizeof(rth_xfrm->local));
+ rth_xfrm->local.nl_family = AF_NETLINK;
+ rth_xfrm->local.nl_groups = subscriptions;
+
+ if (bind(rth_xfrm->fd, (struct sockaddr*)&rth_xfrm->local, sizeof(rth_xfrm->local)) < 0) {
+ ALOGD("Cannot bind netlink socket\n");
+ return -1;
+ }
+ return 0;
+}
+
+int rtnl_listen_xfrm(struct rtnl_handle_xfrm *rtnl_xfrm, rtnl_filter_t_xfrm handler)
+{
+ int status;
+ struct nlmsghdr *h_xfrm;
+ struct sockaddr_nl nladdr_xfrm;
+ struct iovec iov;
+ struct msghdr msg_xfrm = {
+ .msg_name = &nladdr_xfrm,
+ .msg_namelen = sizeof(nladdr_xfrm),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+ char buf[16384];
+
+ memset(&nladdr_xfrm, 0, sizeof(nladdr_xfrm));
+ nladdr_xfrm.nl_family = AF_NETLINK;
+ nladdr_xfrm.nl_pid = 0;
+ nladdr_xfrm.nl_groups = 0;
+ iov.iov_base = buf;
+
+ iov.iov_len = sizeof(buf);
+ status = recvmsg(rtnl_xfrm->fd, &msg_xfrm, 0);
+ ALOGD("netlink receive msg status:%d\n",status);
+ if (status < 0) {
+ if (errno == EINTR || errno == EAGAIN || errno == ENOBUFS)
+ return -1;
+ }
+ if (status == 0) {
+ ALOGE("EOF on netlink\n");
+ return -1;
+ }
+ if (msg_xfrm.msg_namelen != sizeof(nladdr_xfrm)) {
+ ALOGE("Sender address length == %d\n", msg_xfrm.msg_namelen);
+ return -1;
+ }
+ for (h_xfrm = (struct nlmsghdr*)buf; status >= sizeof(*h_xfrm); ) {
+ int err;
+ int len = h_xfrm->nlmsg_len;
+ int l = len - sizeof(*h_xfrm);
+
+ if (l<0 || len>status) {
+ if (msg_xfrm.msg_flags & MSG_TRUNC) {
+ ALOGE("Truncated message\n");
+ return -1;
+ }
+ ALOGE("!!!malformed message: len=%d\n", len);
+ return -1;
+ }
+ err = handler(rtnl_xfrm,h_xfrm);
+ if (err == -2) /*no sa & sp entries*/
+ {
+ return err;
+ }
+
+ status -= NLMSG_ALIGN(len);
+ h_xfrm = (struct nlmsghdr*)((char*)h_xfrm + NLMSG_ALIGN(len));
+ }
+
+ return 0;
+}
+
+/*
+ -2: no previous volte_stack policy&& state is set;
+ -1: unknown message type && delete policy or state failed
+ 0: everything is good
+*/
+int rtnl_accept_msg_xfrm(struct rtnl_handle_xfrm * rth ,struct nlmsghdr *n)
+{
+ char pid[128] = {0};
+ property_get("net.ims.volte.pid",pid,"-1");
+ pid_t volte_pid =atoi(pid);
+ /*no previous volte_stack policy&& state is set*/
+ switch (n->nlmsg_type) {
+ case XFRM_MSG_NEWSA:
+ case XFRM_MSG_UPDSA:
+ return xfrm_state_process_delete_exist( rth,n, volte_pid);
+ case XFRM_MSG_NEWPOLICY:
+ case XFRM_MSG_UPDPOLICY:
+ return xfrm_policy_process_delete_exist( rth,n, volte_pid);
+ case XFRM_MSG_EXPIRE:
+ case XFRM_MSG_DELSA:
+ case XFRM_MSG_FLUSHSA:
+ case XFRM_MSG_GETPOLICY:
+ case XFRM_MSG_FLUSHPOLICY:
+ case XFRM_MSG_ACQUIRE:
+ case XFRM_MSG_DELPOLICY:
+ case XFRM_MSG_POLEXPIRE:
+ default:
+ ALOGD("receive netlink message: %08d 0x%08x 0x%08x\n",
+ n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
+ break;
+ }
+
+ if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP &&
+ n->nlmsg_type != NLMSG_DONE) {
+ ALOGE("Unknown message: %08d 0x%08x 0x%08x\n",
+ n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
+ }
+ return -2;
+}
+
diff --git a/src/connectivity/libipsecims/setkey_fileio.c b/src/connectivity/libipsecims/setkey_fileio.c
new file mode 100644
index 0000000..5bc8d14
--- /dev/null
+++ b/src/connectivity/libipsecims/setkey_fileio.c
@@ -0,0 +1,1112 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+#include <linux/capability.h>
+#include <sys/capability.h>
+#include <cutils/properties.h>
+#include "setkey_fileio.h"
+#if 0
+#include "../setkey/log_setky.h"
+#endif
+#define LOG_TAG "setkey"
+#include <log/log.h>
+#include <cutils/log.h>
+
+#if 0
+extern void plog_android(int level, char *format, ...);
+extern int setkey_main(int argc, char ** argv);
+
+#define POLICY_LEN 640
+#define POLICY_MODE 320
+#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
+#define BUFF_SIZE 128
+#define RM_FILE_LEN 64
+
+char setkey_conf[]="/data/misc/setkey/setkey.conf";
+char setkey_conf_bak[]="/data/misc/setkey/setkey_bak.conf";
+char setkey_conf_latest[]="/data/misc/setkey/setkey_latest.conf";
+
+
+static int RemoveString(char * src,char * dst,char * ipsec_type,char * spi_src)
+{
+ FILE *fpSrc = NULL;
+ FILE *fpDst = NULL;
+
+ char achBuf[POLICY_LEN] = {0};
+ fpSrc = fopen(setkey_conf, "rt");
+ if (NULL == fpSrc)
+ {
+ plog_android(LLV_WARNING, "RemoveString:can't open %s,errno:%d",setkey_conf,errno);
+ return -1;
+ }
+ chown(setkey_conf,0,1000);
+ fpDst = fopen(setkey_conf_bak, "wt");
+ if (NULL== fpDst)
+ {
+ plog_android(LLV_WARNING,"RemoveString:Create source file: %s failed,errno:%d\n", setkey_conf_bak,errno);
+ fclose(fpSrc);
+ return -1;
+ }
+ chown(setkey_conf_bak,0,1000);
+ while (!feof(fpSrc))
+ {
+ memset(achBuf, 0, sizeof(achBuf));
+ fgets(achBuf, sizeof(achBuf), fpSrc);
+ /* include below parameter is right*/
+ if ((strstr(achBuf, "add")!=NULL)&&(strstr(achBuf, "spdadd")==NULL)&&(strstr(achBuf, dst)!=NULL)&&(strstr(achBuf,ipsec_type)!=NULL)&&(strstr(achBuf, spi_src)!=NULL))
+ {
+ /*to make sure sequence,first src,then dst*/
+ if(strstr(achBuf, src)<strstr(achBuf, dst))
+ plog_android(LLV_WARNING,"Has found SA,%s,remove it\n",achBuf);
+ else
+ fputs(achBuf, fpDst);
+ } else {
+ fputs(achBuf, fpDst);
+ }
+
+ }
+ fclose(fpSrc);
+ fclose(fpDst);
+
+ return 0;
+}
+
+
+static int RemoveString_SP(char * src,char * dst,int protocol,char * src_port,char * dst_port,char * direction)
+{
+ FILE *fpSrc = NULL;
+ FILE *fpDst = NULL;
+
+ char protocol_str[16]={0};
+ char achBuf[POLICY_LEN] = {0};
+ sprintf(protocol_str,"%d",protocol);
+
+ fpSrc = fopen(setkey_conf, "rt");
+ if (NULL == fpSrc)
+ {
+ plog_android(LLV_WARNING, "RemoveString_SP:can't open %s,errno:%d",setkey_conf,errno);
+ return -1;
+ }
+ chown(setkey_conf,0,1000);
+ fpDst = fopen(setkey_conf_bak, "wt");
+ if (NULL== fpDst)
+ {
+ plog_android(LLV_WARNING,"RemoveString_SP:Create source file: %s failed,errno:%d\n", setkey_conf_bak,errno);
+ fclose(fpSrc);
+ return -1;
+ }
+ chown(setkey_conf_bak,0,1000);
+ while (!feof(fpSrc))
+ {
+ memset(achBuf, 0, sizeof(achBuf));
+ fgets(achBuf, sizeof(achBuf), fpSrc);
+ if ((strstr(achBuf, "spdadd")!=NULL)&&(strstr(achBuf, dst)!=NULL)&&(strstr(achBuf, src)!=NULL)&&(strstr(achBuf, src_port)!=NULL)
+ &&(strstr(achBuf, dst_port)!=NULL)&&(strstr(achBuf, protocol_str)!=NULL)&&(strstr(achBuf, direction)!=NULL))
+ {
+ if((strstr(achBuf, src)<strstr(achBuf, dst))&&(strstr(achBuf, src_port)<strstr(achBuf, dst_port)))
+ plog_android(LLV_WARNING,"Has found SP policy,%s,remove it\n",achBuf);
+ else
+ fputs(achBuf, fpDst);
+ }
+ else
+ {
+ fputs(achBuf, fpDst);
+ }
+ }
+ fclose(fpSrc);
+ fclose(fpDst);
+
+ return 0;
+}
+
+
+/* 1: some error; 0: process successfully */
+int shell(char * cmd)
+{
+ FILE * fp = NULL,* fp_exit_code =NULL;
+ int bufflen;
+ char * buffer = (char *)malloc((BUFF_SIZE));
+ if(buffer == NULL)
+ {
+ plog_android(LLV_WARNING, "run shell command buffer is null");
+ return -1;
+ }
+ char * buffer_retcode = NULL;
+ char * cmd_exit_code = (char *)malloc((BUFF_SIZE));
+ int ret_code = 0;
+ if(cmd_exit_code == NULL)
+ {
+ plog_android(LLV_WARNING, "alloc cmd_exit_code failed ");
+ goto ret_sec;
+ }
+ if(cmd == NULL)
+ {
+ plog_android(LLV_WARNING, "run shell command is null");
+ goto ret_fir;
+ }
+ buffer[0] = 0;
+ strcpy(cmd_exit_code,cmd);
+ strcat(cmd_exit_code,";echo ret_code:$?");
+ fp = popen(cmd_exit_code,"r");
+ if(fp == NULL)
+ {
+ plog_android(LLV_WARNING, "can't run shell command");
+ goto ret_fir;
+ }
+ //plog_android(LLV_WARNING, "run shell command:%s ...",cmd);
+ while(fgets(buffer,BUFF_SIZE,fp)!=NULL)
+ {
+ plog_android(LLV_WARNING, "%s",buffer);
+ }
+ buffer_retcode = strstr(buffer,"ret_code:");
+ if(buffer_retcode)
+ {
+ ret_code = atoi(buffer_retcode+strlen("ret_code:"));
+ plog_android(LLV_WARNING, "processing cmd:%s return code:%d",cmd,ret_code);
+ }
+ pclose(fp);
+
+
+ret_fir:
+ if(cmd_exit_code)
+ free(cmd_exit_code);
+ret_sec:
+ if(buffer)
+ free(buffer);
+ return ret_code;
+}
+
+/*rm setkey.conf file*/
+int shell_rm(void)
+{
+ char rm_file[RM_FILE_LEN];
+ int ret = 1;
+ memset(rm_file,0,RM_FILE_LEN);
+ snprintf(rm_file,sizeof(rm_file),"rm %s",setkey_conf);
+ if(access(setkey_conf,0) == 0)
+ {
+ ret = shell(rm_file);
+ if(ret != 0)
+ {
+ plog_android(LLV_WARNING,"shell %s failed,errno:%d",rm_file,errno);
+ return -1;
+ }
+ }
+ return 0;
+
+}
+
+/*setkey -f setkey.conf */
+int function_setkey(char * file_conf)
+{
+ char * argv[4];
+
+ argv[0] = "setkey";
+ argv[1] = "-f";
+ argv[2] = file_conf;
+ argv[3] = NULL;
+ int ret = setkey_main(3,(char **)argv);
+ if(ret != 0)
+ {
+ plog_android(LLV_WARNING," setkey -f %s failed,errno:%d",file_conf,errno);
+ return ret;
+ }
+ return 0;
+
+}
+#endif
+/*flush all SA*/
+int setkey_flushSAD(void)
+{
+#if 0
+ char * argv[3];
+
+ argv[0] = "setkey";
+ argv[1] = "-F";
+ argv[2] = NULL;
+ if(shell_rm() == -1)
+ {
+ return -1;
+ }
+
+ int ret = setkey_main(2,(char **)argv);
+ if(ret != 0)
+ {
+ plog_android(LLV_WARNING,"setkey -F failed,errno:%d",errno);
+ return ret;
+ }
+ return 0;
+#endif
+ int ret = setkey_flushSAD_xfrm("esp");
+ return ret;
+}
+
+/*flush all SP*/
+int setkey_flushSPD(void)
+{
+#if 0
+ char * argv[4];
+
+ argv[0] = "setkey";
+ argv[1] = "-F";
+ argv[2] = "-P";
+ argv[3] = NULL;
+ if(shell_rm() == -1)
+ {
+ return -1;
+ }
+ int ret = setkey_main(3,(char **)argv);
+ if(ret != 0)
+ {
+ plog_android(LLV_WARNING,"setkey -FP failed,errno:%d",errno);
+ return ret;
+ }
+ return 0;
+#endif
+ int ret = setkey_flushSPD_xfrm();
+ return ret;
+}
+
+/*delete one SA entry*/
+int setkey_deleteSA(char * src,char * dst,char * ipsec_type,char * spi_src)
+{
+#if 0
+ char delSA[POLICY_LEN];
+ FILE * fd_config = NULL;
+
+
+
+ memset(delSA,0,sizeof(delSA));
+
+ snprintf(delSA,sizeof(delSA),"delete %s %s %s %s;\n",src,dst,ipsec_type,spi_src);
+ fd_config = fopen(setkey_conf_latest, "w+");
+ if(fd_config == NULL)
+ {
+ plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+ return -1;
+
+ }
+ chown(setkey_conf_latest,0,1000);
+ fwrite( delSA, strlen(delSA),1,fd_config);
+ plog_android(LLV_WARNING,"setkey_deleteSA:%s",delSA);
+ fclose(fd_config);
+ if(function_setkey(setkey_conf_latest)== -1)
+ return -1;
+ else
+ {
+ /*update setkey.conf to record how many pairs of SA have been established*/
+
+ if(RemoveString(src,dst,ipsec_type,spi_src) == 0)
+ {
+ if(shell_rm() == -1)
+ {
+ return -1;
+ }
+ if(rename(setkey_conf_bak,setkey_conf)<0)
+ {
+ plog_android(LLV_WARNING,"rename setkey.conf failed,errno:%d",errno);
+ return -1;
+ }
+ }
+ else
+ {
+ plog_android(LLV_WARNING,"RemoveString failed");
+ return -1;
+ }
+ }
+ return 0;
+#endif
+ int ret = setkey_deleteSA_xfrm(src,dst,ipsec_type,spi_src);
+ return ret;
+}
+
+/*delete one SP entry*/
+int setkey_deleteSP(char * src,char * dst,enum PROTOCOL_TYPE protocol,char * src_port,char * dst_port,char * direction)
+{
+#if 0
+ char delSP[POLICY_LEN];
+
+ FILE * fd_config = NULL;
+
+
+
+ memset(delSP,0,sizeof(delSP));
+
+ snprintf(delSP,sizeof(delSP),"spddelete %s[%s] %s[%s] %d -P %s;\n",src,src_port,dst,dst_port,protocol,direction);
+ fd_config = fopen(setkey_conf_latest, "w+");
+ if(fd_config == NULL)
+ {
+ plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+ return -1;
+
+ }
+ chown(setkey_conf_latest,0,1000);
+ fwrite( delSP, strlen(delSP),1,fd_config);
+ plog_android(LLV_WARNING,"setkey_deleteSP:%s",delSP);
+ fclose(fd_config);
+ if(function_setkey(setkey_conf_latest)==-1)
+ return -1;
+ else
+ {
+ /*update setkey.conf to record how many pairs of SP policy have been established*/
+
+ if(RemoveString_SP( src, dst, protocol, src_port, dst_port, direction) == 0)
+ {
+ if(shell_rm() == -1)
+ {
+ return -1;
+ }
+ if(rename(setkey_conf_bak,setkey_conf)<0)
+ {
+ plog_android(LLV_WARNING,"rename setkey.conf failed,errno:%d",errno);
+ return -1;
+ }
+ }
+ else
+ {
+ plog_android(LLV_WARNING,"RemoveString---%s failed",delSP);
+ return -1;
+ }
+ }
+ return 0;
+#endif
+ int ret = setkey_deleteSP_xfrm(src,dst,protocol,src_port,dst_port,direction);
+ return ret;
+}
+
+/*dump SA */
+int dump_setkeySA(void)
+{
+/*To do*/
+#if 0
+ char * argv[3];
+
+ argv[0] = "setkey";
+ argv[1] = "-D";
+ argv[2] = NULL;
+ int ret = setkey_main(2,(char **)argv);
+ if(ret != 0)
+ {
+ plog_android(LLV_WARNING," setkey -D failed,errno:%d",errno);
+ return -1;
+ }
+#endif
+ return 0;
+
+}
+
+/*dump SP */
+int dump_setkeySP(void)
+{
+/*To do*/
+#if 0
+ char * argv[4];
+
+ argv[0] = "setkey";
+ argv[1] = "-D";
+ argv[2] = "-P";
+ argv[3] = NULL;
+ int ret = setkey_main(3,(char **)argv);
+ if(ret != 0)
+ {
+ plog_android(LLV_WARNING,"setkey -DP failed,errno:%d",errno);
+ return ret;
+ }
+#endif
+ return 0;
+
+}
+#if 0
+void setkey_get_aid_and_cap() {
+
+ plog_android(LLV_WARNING,"Warning: gid:%d,uid:%d,pid:%d !\n",getgid(),getuid(),getpid());
+ struct __user_cap_header_struct header;
+ struct __user_cap_data_struct cap;
+ header.version = _LINUX_CAPABILITY_VERSION;
+ header.pid = getpid();
+ capget(&header, &cap);
+ plog_android(LLV_WARNING, "Warning: permitted:%x,cap.effective:%x !\n",cap.permitted,cap.effective);
+}
+#endif
+/*set one SA*/
+/*ipsec_type:ah esp
+ mode:transport tunnel
+ encrp_algo_src:encryption algorithm,des-cbc,3des-cbc...
+ encrp_algo_src:key of encryption algorithm
+ intergrity_algo_src:authentication algorithm ,hmac-md5,hmac-sha1
+ intergrity_key_src:key of authentication algorithm
+*/
+int setkey_setSA(char * ip_src,char * ip_dst,char * ipsec_type,char * spi_src,char * mode,
+ char * encrp_algo_src,char * encrp_key_src,char * intergrity_algo_src,char * intergrity_key_src,int u_id)
+{
+#if 0
+ char sad_policy[POLICY_LEN];
+
+ FILE * fd_config = NULL;
+ FILE * fd_config_tmp = NULL;
+
+ memset(sad_policy,0,sizeof(sad_policy));
+
+ setkey_get_aid_and_cap();
+
+ fd_config_tmp = fopen(setkey_conf_latest, "w+" );
+ if(fd_config_tmp == NULL)
+ {
+ plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf_latest,errno);
+ return -1;
+ }
+ chown(setkey_conf_latest,0,1000);
+ if(strcmp(encrp_algo_src,"null")==0)
+ {
+ if(u_id ==0 )
+ snprintf(sad_policy,sizeof(sad_policy),"add %s %s %s %s -m %s -E null -A %s %s;\n",ip_src,ip_dst,ipsec_type,spi_src,mode,
+ intergrity_algo_src,intergrity_key_src);
+ else
+ snprintf(sad_policy,sizeof(sad_policy),"add %s %s %s %s -u %d -m %s -E null -A %s %s;\n",ip_src,ip_dst,ipsec_type,spi_src,u_id,mode,
+ intergrity_algo_src,intergrity_key_src);
+ }
+ else
+ {
+ if(u_id ==0 )
+ snprintf(sad_policy,sizeof(sad_policy),"add %s %s %s %s -m %s -E %s %s -A %s %s;\n",ip_src,ip_dst,ipsec_type,spi_src,mode,
+ encrp_algo_src,encrp_key_src,intergrity_algo_src,intergrity_key_src);
+ else
+ snprintf(sad_policy,sizeof(sad_policy),"add %s %s %s %s -u %d -m %s -E %s %s -A %s %s;\n",ip_src,ip_dst,ipsec_type,spi_src,u_id,mode,
+ encrp_algo_src,encrp_key_src,intergrity_algo_src,intergrity_key_src);
+ }
+ fwrite( sad_policy, strlen(sad_policy),1,fd_config_tmp );
+ plog_android(LLV_WARNING,"setkey_SA:%s",sad_policy);
+ fclose(fd_config_tmp);
+
+ if(function_setkey(setkey_conf_latest)==0)
+ {
+ fd_config = fopen(setkey_conf, "a+" );
+ if(fd_config == NULL)
+ {
+ plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+ return -1;
+ }
+ chown(setkey_conf,0,1000);
+ fwrite( sad_policy, strlen(sad_policy),1,fd_config );
+ fclose(fd_config);
+ }
+ else
+ return -1;
+
+ return 0;
+#endif
+ int ret = setkey_setSA_xfrm(XFRM_MSG_NEWSA,ip_src,ip_dst,ipsec_type,spi_src,mode,
+ encrp_algo_src,encrp_key_src,intergrity_algo_src,intergrity_key_src,u_id);
+ return ret;
+}
+int setkey_setSA_update(char * ip_src,char * ip_dst,char * ipsec_type,char * spi_src,char * mode,
+ char * encrp_algo_src,char * encrp_key_src,char * intergrity_algo_src,char * intergrity_key_src,int u_id)
+{
+ int ret = setkey_setSA_xfrm(XFRM_MSG_UPDSA,ip_src,ip_dst,ipsec_type,spi_src,mode,
+ encrp_algo_src,encrp_key_src,intergrity_algo_src,intergrity_key_src,u_id);
+ return ret;
+}
+/*set one SP of one direction, just for transport mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+ direction:src->dst */
+int setkey_SP(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * ipsec_type,char * mode, char * direction,int u_id)
+{
+#if 0
+ char spd_policy[POLICY_LEN];
+ FILE * fd_config = NULL;
+ FILE * fd_config_tmp = NULL;
+ memset(spd_policy,0,sizeof(spd_policy));
+
+
+ fd_config_tmp = fopen(setkey_conf_latest, "w+" );
+ if(fd_config_tmp == NULL)
+ {
+ plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf_latest,errno);
+ return -1;
+ }
+ chown(setkey_conf_latest,0,1000);
+ if(u_id ==0)
+ snprintf(spd_policy,sizeof(spd_policy),"spdadd %s[%s] %s[%s] %d -P %s ipsec %s/%s//require;\n",src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type,mode);
+ else
+ snprintf(spd_policy,sizeof(spd_policy),"spdadd %s[%s] %s[%s] %d -P %s ipsec %s/%s//unique:%d;\n",src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type,mode,u_id);
+ fwrite( spd_policy, strlen(spd_policy),1,fd_config_tmp );
+ plog_android(LLV_WARNING,"setkey_SP:%s",spd_policy);
+ fclose(fd_config_tmp);
+
+ if(function_setkey(setkey_conf_latest) == 0)
+ {
+ fd_config = fopen(setkey_conf, "a+" );
+ if(fd_config == NULL)
+ {
+ plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+ return -1;
+ }
+ chown(setkey_conf,0,1000);
+ fwrite( spd_policy, strlen(spd_policy),1,fd_config );
+ fclose(fd_config);
+ }
+ else
+ return -1;
+ return 0;
+#endif
+ mode = "transport";
+ int ret = setkey_SP_xfrm(XFRM_MSG_NEWPOLICY,src_range,dst_range,protocol,port_src,port_dst,NULL,NULL,ipsec_type,mode,direction,u_id);
+ return ret;
+}
+
+/*set one SP of one direction, just for tunnel mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+ direction:src->dst
+src_tunnel,dst_tunnel: tunnel src ip tunnel dst ip */
+int setkey_SP_tunnel(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type,char * mode, char * direction,int u_id)
+{
+#if 0
+ char spd_policy[POLICY_LEN];
+ FILE * fd_config = NULL;
+ FILE * fd_config_tmp = NULL;
+ memset(spd_policy,0,sizeof(spd_policy));
+
+
+ fd_config_tmp = fopen(setkey_conf_latest, "w+" );
+ if(fd_config_tmp == NULL)
+ {
+ plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf_latest,errno);
+ return -1;
+ }
+ chown(setkey_conf_latest,0,1000);
+ if(u_id ==0)
+ snprintf(spd_policy,sizeof(spd_policy),"spdadd %s[%s] %s[%s] %d -P %s ipsec %s/%s/%s-%s/require;\n",src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type,mode,src_tunnel, dst_tunnel);
+ else
+ snprintf(spd_policy,sizeof(spd_policy),"spdadd %s[%s] %s[%s] %d -P %s ipsec %s/%s/%s-%s/unique:%d;\n",src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type,mode,src_tunnel, dst_tunnel,u_id);
+ fwrite( spd_policy, strlen(spd_policy),1,fd_config_tmp );
+ plog_android(LLV_WARNING,"setkey_SP_tunnel:%s",spd_policy);
+ fclose(fd_config_tmp);
+
+ if(function_setkey(setkey_conf_latest) == 0)
+ {
+ fd_config = fopen(setkey_conf, "a+" );
+ if(fd_config == NULL)
+ {
+ plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+ return -1;
+ }
+ chown(setkey_conf,0,1000);
+ fwrite( spd_policy, strlen(spd_policy),1,fd_config );
+ fclose(fd_config);
+ }
+ else
+ return -1;
+ return 0;
+#endif
+ mode = "tunnel";
+ int ret = setkey_SP_xfrm(XFRM_MSG_NEWPOLICY,src_range,dst_range,protocol,port_src,port_dst,src_tunnel,dst_tunnel,ipsec_type,mode,direction,u_id);
+ return ret;
+}
+
+/*set one SP of one direction, for 2 layers' ipsec--tunnel mode+transport mode or transport mode+tunnel mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+ direction:src->dst
+src_tunnel,dst_tunnel: tunnel src ip tunnel dst ip */
+int setkey_SP_tunnel_transport(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type1,char * mode1, char * ipsec_type2,char * mode2,char * direction,int u_id1,int u_id2)
+{
+
+ char version[128] = {0};
+ int ret_mapping = 0;
+ property_get("net.ims.ipsec.version",version,"");
+ //plog_android(LLV_WARNING,"getproperty-- net.ims.ipsec.version :%s\n",version);
+ if(strcmp(version,"2.0")==0)
+ {
+ ret_mapping = setkey_SP(src_range,dst_range,protocol,port_src,port_dst,ipsec_type1,mode1, direction,u_id1);
+ return ret_mapping;
+ }
+
+#if 0
+ char spd_policy[POLICY_LEN]={0};
+ char * spd_policy_mode1= (char *)malloc(POLICY_MODE);
+
+ FILE * fd_config = NULL;
+ FILE * fd_config_tmp = NULL;
+
+
+ if(spd_policy_mode1==NULL)
+ {
+ plog_android(LLV_WARNING,"malloc spd_policy_mode1 failed,errno:%d",errno);
+ return -1;
+ }
+ memset(spd_policy_mode1,0,POLICY_MODE);
+
+ char * spd_policy_mode2= (char *)malloc(POLICY_MODE);
+ if(spd_policy_mode2==NULL)
+ {
+ plog_android(LLV_WARNING,"malloc spd_policy_mode2 failed,errno:%d",errno);
+ if(spd_policy_mode1)
+ free(spd_policy_mode1);
+ return -1;
+ }
+ memset(spd_policy_mode2,0,POLICY_MODE);
+
+ fd_config_tmp = fopen(setkey_conf_latest, "w+" );
+ if(fd_config_tmp == NULL)
+ {
+ plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf_latest,errno);
+ if(spd_policy_mode1)
+ free(spd_policy_mode1);
+ if(spd_policy_mode2)
+ free(spd_policy_mode2);
+ return -1;
+ }
+ chown(setkey_conf_latest,0,1000);
+ if(u_id1 ==0)
+ if(strcmp(mode1,"transport")==0)
+ snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s//require",ipsec_type1,mode1);
+ else
+ snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s/%s-%s/require",ipsec_type1,mode1,src_tunnel,dst_tunnel);
+ else
+ if(strcmp(mode1,"transport")==0)
+ snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s//unique:%d",ipsec_type1,mode1,u_id1);
+ else
+ snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s/%s-%s/unique:%d",ipsec_type1,mode1,src_tunnel,dst_tunnel,u_id1);
+ if(u_id2 ==0)
+ if(strcmp(mode2,"transport")==0)
+ snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s//require;\n",ipsec_type2,mode2);
+ else
+ snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s/%s-%s/require;\n",ipsec_type2,mode2,src_tunnel,dst_tunnel);
+ else
+ if(strcmp(mode2,"transport")==0)
+ snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s//unique:%d;\n",ipsec_type2,mode2,u_id2);
+ else
+ snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s/%s-%s/unique:%d;\n",ipsec_type2,mode2,src_tunnel,dst_tunnel,u_id2);
+
+ snprintf(spd_policy,sizeof(spd_policy),"spdadd %s[%s] %s[%s] %d -P %s prio 2147482648 ipsec %s %s",src_range,port_src,dst_range,port_dst,protocol,direction,spd_policy_mode1,spd_policy_mode2);
+ fwrite( spd_policy, strlen(spd_policy),1,fd_config_tmp );
+ plog_android(LLV_WARNING,"setkey_SP_tunnel_transport:%s",spd_policy);
+ fclose(fd_config_tmp);
+ if(spd_policy_mode1)
+ free(spd_policy_mode1);
+ if(spd_policy_mode2)
+ free(spd_policy_mode2);
+ if(function_setkey(setkey_conf_latest) == 0)
+ {
+ fd_config = fopen(setkey_conf, "a+" );
+ if(fd_config == NULL)
+ {
+ plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+ return -1;
+ }
+ chown(setkey_conf,0,1000);
+ fwrite( spd_policy, strlen(spd_policy),1,fd_config );
+ fclose(fd_config);
+ }
+ else
+ return -1;
+ return 0;
+#endif
+ int ret = setkey_SP_2layer_xfrm(XFRM_MSG_UPDPOLICY,src_range,dst_range,protocol,port_src,port_dst,src_tunnel,dst_tunnel,ipsec_type1,mode1,ipsec_type2,mode2,direction,u_id1,u_id2);
+ return ret;
+}
+
+
+/*update one SP of one direction, just for transport mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+ direction:src->dst*/
+int setkey_SP_update_transport(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * ipsec_type, char * direction,int u_id)
+{
+#if 0
+ char spd_policy[POLICY_LEN];
+ FILE * fd_config = NULL;
+ FILE * fd_config_tmp = NULL;
+ memset(spd_policy,0,sizeof(spd_policy));
+
+
+ fd_config_tmp = fopen(setkey_conf_latest, "w+" );
+ if(fd_config_tmp == NULL)
+ {
+ plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf_latest,errno);
+ return -1;
+ }
+ chown(setkey_conf_latest,0,1000);
+ if(u_id ==0)
+ snprintf(spd_policy,sizeof(spd_policy),"spdupdate %s[%s] %s[%s] %d -P %s ipsec %s/transport//require;\n",src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type);
+ else
+ snprintf(spd_policy,sizeof(spd_policy),"spdupdate %s[%s] %s[%s] %d -P %s ipsec %s/transport//unique:%d;\n",src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type,u_id);
+ fwrite( spd_policy, strlen(spd_policy),1,fd_config_tmp );
+ plog_android(LLV_WARNING,"setkey_SP_update_transport:%s",spd_policy);
+ fclose(fd_config_tmp);
+
+ if(function_setkey(setkey_conf_latest) == 0)
+ {
+ fd_config = fopen(setkey_conf, "a+" );
+ if(fd_config == NULL)
+ {
+ plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+ return -1;
+ }
+ chown(setkey_conf,0,1000);
+ fwrite( spd_policy, strlen(spd_policy),1,fd_config );
+ fclose(fd_config);
+ }
+ else
+ return -1;
+ return 0;
+#endif
+ int ret = setkey_SP_xfrm(XFRM_MSG_UPDPOLICY,src_range,dst_range,protocol,port_src,port_dst,NULL,NULL,ipsec_type,"transport",direction,u_id);
+ return ret;
+}
+
+/*update one SP of one direction, for 2 layers' ipsec--tunnel mode+transport mode or transport mode+tunnel mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+ direction:src->dst
+src_tunnel,dst_tunnel: tunnel src ip tunnel dst ip */
+int setkey_SP_update_tunnel_transport(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type1,char * mode1, char * ipsec_type2,char * mode2,char * direction,int u_id1,int u_id2)
+{
+#if 0
+ char spd_policy[POLICY_LEN]={0};
+ char * spd_policy_mode1= (char *)malloc(POLICY_MODE);
+ FILE * fd_config = NULL;
+ FILE * fd_config_tmp = NULL;
+
+
+ if(spd_policy_mode1==NULL)
+ {
+ plog_android(LLV_WARNING,"malloc spd_policy_mode1 failed,errno:%d",errno);
+ return -1;
+ }
+ memset(spd_policy_mode1,0,POLICY_MODE);
+ char * spd_policy_mode2= (char *)malloc(POLICY_MODE);
+ if(spd_policy_mode2==NULL)
+ {
+ plog_android(LLV_WARNING,"malloc spd_policy_mode2 failed,errno:%d",errno);
+ if(spd_policy_mode1)
+ free(spd_policy_mode1);
+ return -1;
+ }
+ memset(spd_policy_mode2,0,POLICY_MODE);
+
+ fd_config_tmp = fopen(setkey_conf_latest, "w+" );
+ if(fd_config_tmp == NULL)
+ {
+ plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf_latest,errno);
+ if(spd_policy_mode1)
+ free(spd_policy_mode1);
+ if(spd_policy_mode2)
+ free(spd_policy_mode2);
+ return -1;
+ }
+ chown(setkey_conf_latest,0,1000);
+ if(u_id1 ==0)
+ if(strcmp(mode1,"transport")==0)
+ snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s//require",ipsec_type1,mode1);
+ else
+ snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s/%s-%s/require",ipsec_type1,mode1,src_tunnel,dst_tunnel);
+ else
+ if(strcmp(mode1,"transport")==0)
+ snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s//unique:%d",ipsec_type1,mode1,u_id1);
+ else
+ snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s/%s-%s/unique:%d",ipsec_type1,mode1,src_tunnel,dst_tunnel,u_id1);
+ if(u_id2 ==0)
+ if(strcmp(mode2,"transport")==0)
+ snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s//require;\n",ipsec_type2,mode2);
+ else
+ snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s/%s-%s/require;\n",ipsec_type2,mode2,src_tunnel,dst_tunnel);
+ else
+ if(strcmp(mode2,"transport")==0)
+ snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s//unique:%d;\n",ipsec_type2,mode2,u_id2);
+ else
+ snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s/%s-%s/unique:%d;\n",ipsec_type2,mode2,src_tunnel,dst_tunnel,u_id2);
+
+ snprintf(spd_policy,sizeof(spd_policy),"spdupdate %s[%s] %s[%s] %d -P %s prio 2147482648 ipsec %s %s",src_range,port_src,dst_range,port_dst,protocol,direction,spd_policy_mode1,spd_policy_mode2);
+ fwrite( spd_policy, strlen(spd_policy),1,fd_config_tmp );
+ plog_android(LLV_WARNING,"setkey_SP_update_tunnel_transport:%s",spd_policy);
+ fclose(fd_config_tmp);
+ if(spd_policy_mode1)
+ free(spd_policy_mode1);
+ if(spd_policy_mode2)
+ free(spd_policy_mode2);
+ if(function_setkey(setkey_conf_latest) == 0)
+ {
+ fd_config = fopen(setkey_conf, "a+" );
+ if(fd_config == NULL)
+ {
+ plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+ return -1;
+ }
+ chown(setkey_conf,0,1000);
+ fwrite( spd_policy, strlen(spd_policy),1,fd_config );
+ fclose(fd_config);
+ }
+ else
+ return -1;
+ return 0;
+#endif
+ int ret = setkey_SP_2layer_xfrm(XFRM_MSG_UPDPOLICY,src_range,dst_range,protocol,port_src,port_dst,src_tunnel,dst_tunnel,ipsec_type1,mode1,ipsec_type2,mode2,direction,u_id1,u_id2);
+ return ret;
+}
+
+
+/*flush SA\SP from setkey.conf*/
+int flush_SA_SP_exist()
+{
+#if 0
+ FILE *fpSrc = NULL;
+ FILE *fpDst = NULL;
+ char * p_add = NULL;
+ char * p_spdadd = NULL;
+ char * p = NULL;
+ char * sp = NULL;
+ char * sp_ipsec = NULL;
+ char * sp_prio = NULL;
+#if 0
+ char * sp_tmp = NULL;
+ char * sp_src_tmp = NULL;
+ char * sp_dst_tmp = NULL;
+ char * sp_dst = NULL;
+#endif
+ if(access(setkey_conf,0) != 0)
+ {
+ plog_android(LLV_WARNING,"There is no SA before\n");
+ return 0;
+ }
+
+
+ char * achBuf = (char *)malloc(POLICY_LEN);
+ if(achBuf == NULL)
+ {
+ plog_android(LLV_WARNING,"malloc achBuf failed\n");
+ return -1;
+ }
+ char * achBuf_deletmp = (char *)malloc(POLICY_LEN);
+ if(achBuf_deletmp == NULL)
+ {
+ plog_android(LLV_WARNING,"malloc achBuf_deletmp failed\n");
+ if(achBuf)
+ free(achBuf);
+
+ return -1;
+ }
+ char * achBuf_delet = (char *)malloc(POLICY_LEN);
+ if(achBuf_delet == NULL)
+ {
+ plog_android(LLV_WARNING,"malloc achBuf_delet failed\n");
+ if(achBuf)
+ free(achBuf);
+ if(achBuf_deletmp)
+ free(achBuf_deletmp);
+ return -1;
+ }
+
+
+ fpSrc = fopen(setkey_conf, "rt");
+ if (NULL == fpSrc)
+ {
+ plog_android(LLV_WARNING, "can't open %s,errno:%d",setkey_conf,errno);
+ if(achBuf)
+ free(achBuf);
+ if(achBuf_deletmp)
+ free(achBuf_deletmp);
+ if(achBuf_delet)
+ free(achBuf_delet);
+ return -1;
+ }
+ chown(setkey_conf,0,1000);
+ fpDst = fopen(setkey_conf_latest, "w+");
+ if (NULL== fpDst)
+ {
+ if(achBuf)
+ free(achBuf);
+ if(achBuf_deletmp)
+ free(achBuf_deletmp);
+ if(achBuf_delet)
+ free(achBuf_delet);
+ plog_android(LLV_WARNING,"Create source file: %s failed,errno:%d\n", setkey_conf_bak,errno);
+ if(fpSrc)
+ fclose(fpSrc);
+ return -1;
+ }
+ chown(setkey_conf_latest,0,1000);
+ fseek(fpSrc,0L,SEEK_SET);
+ while (!feof(fpSrc))
+ {
+ memset(achBuf, 0, POLICY_LEN);
+ memset(achBuf_deletmp, 0, POLICY_LEN);
+ memset(achBuf_delet, 0, POLICY_LEN);
+ fgets(achBuf, POLICY_LEN, fpSrc);
+
+ if (((p_add = strstr(achBuf, "add")) != NULL)&&(strstr(achBuf, "spdadd") == NULL) )
+ {
+
+ p = strstr(p_add,"-m");
+ if(p!= NULL)
+ {
+ memcpy(achBuf_deletmp,p_add + strlen("add"),p-p_add-strlen("add"));
+ snprintf(achBuf_delet,POLICY_LEN-1,"delete %s;\n",achBuf_deletmp) ;
+ plog_android(LLV_WARNING,"delete SA:%s\n", achBuf_delet);
+ fputs(achBuf_delet, fpDst);
+ }
+ else
+ {
+ plog_android(LLV_WARNING,"There are some cmd error in %s,then flush all SAs and SPs\n", setkey_conf);
+ setkey_flushSAD();
+ setkey_flushSPD();
+ if(achBuf)
+ free(achBuf);
+ if(achBuf_deletmp)
+ free(achBuf_deletmp);
+ if(achBuf_delet)
+ free(achBuf_delet);
+ if(fpSrc)
+ fclose(fpSrc);
+ if(fpDst)
+ fclose(fpDst);
+ return -1;
+ }
+ }
+
+ if((p_spdadd = strstr(achBuf, "spdadd")) != NULL)
+ {
+ sp = p_spdadd+strlen("spdadd");
+ if((sp_prio =strstr(sp,"prio"))!=NULL)
+ {
+ memset(achBuf_deletmp, 0, POLICY_LEN);
+ memset(achBuf_delet, 0, POLICY_LEN);
+ strncpy(achBuf_deletmp,sp,sp_prio-sp);
+ snprintf(achBuf_delet,POLICY_LEN-1,"spddelete %s",achBuf_deletmp);
+ strcat(achBuf_delet,";\n");
+ fputs(achBuf_delet, fpDst);
+ plog_android(LLV_WARNING,"delete policy: %s\n", achBuf_delet);
+ }
+ else if((sp_ipsec =strstr(sp,"ipsec"))!=NULL)
+ {
+ memset(achBuf_deletmp, 0, POLICY_LEN);
+ memset(achBuf_delet, 0, POLICY_LEN);
+ strncpy(achBuf_deletmp,sp,sp_ipsec-sp);
+ snprintf(achBuf_delet,POLICY_LEN-1,"spddelete %s",achBuf_deletmp);
+ strcat(achBuf_delet,";\n");
+ fputs(achBuf_delet, fpDst);
+ plog_android(LLV_WARNING,"delete policy: %s\n", achBuf_delet);
+ }
+ else
+ {
+ plog_android(LLV_WARNING,"There are some cmd error in %s,no ,then flush all SAs and SPs\n", setkey_conf);
+ setkey_flushSAD();
+ setkey_flushSPD();
+ if(achBuf)
+ free(achBuf);
+ if(achBuf_deletmp)
+ free(achBuf_deletmp);
+ if(achBuf_delet)
+ free(achBuf_delet);
+ if(fpSrc)
+ fclose(fpSrc);
+ if(fpDst)
+ fclose(fpDst);
+ return -1;
+ }
+#if 0
+ if((sp_tmp =strchr(sp,'['))!=NULL)
+ {
+ memset(achBuf_deletmp, 0, POLICY_LEN);
+ memset(achBuf_delet, 0, POLICY_LEN);
+ strncpy(achBuf_deletmp,sp,sp_tmp-sp);
+ snprintf(achBuf_delet,POLICY_LEN-1,"spddelete %s",achBuf_deletmp);
+ plog_android(LLV_WARNING,"src[ achBuf_delet: %s,sp_tmp:%s\n", achBuf_deletmp,sp_tmp);
+ if((sp_src_tmp =strchr(sp_tmp,']'))!=NULL)
+ {
+
+ if((sp_dst_tmp =strchr(sp_src_tmp,'['))!=NULL)
+ {
+ memset(achBuf_deletmp, 0, POLICY_LEN);
+ strncpy(achBuf_deletmp,sp_src_tmp+strlen("]"),sp_dst_tmp-sp_src_tmp-strlen("]"));
+ strcat(achBuf_delet,achBuf_deletmp);
+ plog_android(LLV_WARNING,"src]_achBuf_delet: %s,achBuf:%s,sp_dst_tmp:%s\n", achBuf_deletmp,achBuf,sp_dst_tmp);
+ if((sp_dst =strchr(sp_dst_tmp,']'))!=NULL)
+ {
+ if((sp_ipsec =strstr(sp_dst,"ipsec"))!=NULL)
+ {
+ memset(achBuf_deletmp, 0, POLICY_LEN);
+ strncpy(achBuf_deletmp,sp_dst+strlen("]"),sp_ipsec-sp_dst-strlen("]"));
+ strcat(achBuf_delet,achBuf_deletmp);
+ strcat(achBuf_delet,";\n");
+ fputs(achBuf_delet, fpDst);
+ plog_android(LLV_WARNING,"spdadd :%s\n",achBuf_delet);
+ }
+ else
+ {
+ plog_android(LLV_WARNING,"There are some cmd error in %s,before ipsec,then flush all SAs and SPs\n", setkey_conf);
+ setkey_flushSAD();
+ setkey_flushSPD();
+ return -1;
+ }
+ }
+ else
+ {
+ plog_android(LLV_WARNING,"There are some cmd error in %s,no dst],then flush all SAs and SPs\n", setkey_conf);
+ setkey_flushSAD();
+ setkey_flushSPD();
+ return -1;
+ }
+ }
+ else
+ {
+ plog_android(LLV_WARNING,"There are some cmd error in %s,no dst[,then flush all SAs and SPs\n", setkey_conf);
+ setkey_flushSAD();
+ setkey_flushSPD();
+ return -1;
+ }
+ }
+ else
+ {
+ plog_android(LLV_WARNING,"There are some cmd error in %s,no ],then flush all SAs and SPs\n", setkey_conf);
+ setkey_flushSAD();
+ setkey_flushSPD();
+ return -1;
+ }
+
+ }
+ else
+ {
+ plog_android(LLV_WARNING,"There are some cmd error in %s,no [,then flush all SAs and SPs\n", setkey_conf);
+ setkey_flushSAD();
+ setkey_flushSPD();
+ return -1;
+ }
+#endif
+ }
+
+
+ }
+ fclose(fpSrc);
+ fclose(fpDst);
+ if(achBuf)
+ free(achBuf);
+ if(achBuf_deletmp)
+ free(achBuf_deletmp);
+ if(achBuf_delet)
+ free(achBuf_delet);
+ if(function_setkey(setkey_conf_latest) == -1)
+ {
+ return -1;
+ }
+ else
+ {
+ if(shell_rm() == -1)
+ {
+ return -1;
+ }
+ }
+ return 0;
+#endif
+ int ret = flush_SA_SP_exist_xfrm();
+ return ret;
+}
+
+
+
+
diff --git a/src/connectivity/libipsecims/setkey_fileio.h b/src/connectivity/libipsecims/setkey_fileio.h
new file mode 100644
index 0000000..141ecb3
--- /dev/null
+++ b/src/connectivity/libipsecims/setkey_fileio.h
@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+#include "utils_xfrm.h"
+
+
+/*flush all SA*/
+extern int setkey_flushSAD(void);
+extern int setkey_flushSAD_xfrm(char * ipsec_type);
+/*flush all SP*/
+extern int setkey_flushSPD(void);
+extern int setkey_flushSPD_xfrm(void);
+/*delete one SA entry*/
+extern int setkey_deleteSA(char * src,char * dst,char * ipsec_type,char * spi_src);
+extern int setkey_deleteSA_xfrm(char * src,char * dst,char * ipsec_type,char * spi_src);
+
+/*delete one SP entry*/
+int setkey_deleteSP(char * src,char * dst,enum PROTOCOL_TYPE protocol,char * src_port,char * dst_port,char * direction);
+int setkey_deleteSP_xfrm(char * src,char * dst,enum PROTOCOL_TYPE protocol,char * src_port,char * dst_port,char * direction);
+
+/*dump all SA */
+extern int dump_setkeySA(void);
+
+/*dump all SP */
+extern int dump_setkeySP(void);
+
+/*set one SA*/
+/*ipsec_type:ah esp
+ mode:transport tunnel
+ encrp_algo_src:encryption algorithm,des-cbc,3des-cbc...
+ encrp_algo_src:key of encryption algorithm
+ intergrity_algo_src:authentication algorithm ,hmac-md5,hmac-sha1
+ intergrity_key_src:key of authentication algorithm
+*/
+extern int setkey_setSA(char * ip_src,char * ip_dst,char * ipsec_type,char * spi_src,char * mode, char * encrp_algo_src,char * encrp_key_src,char * intergrity_algo_src,char * intergrity_key_src,int u_id);
+extern int setkey_setSA_xfrm(int cmd,char * ip_src,char * ip_dst,char * ipsec_type,char * spi_src,char * mode, char * encrp_algo_src,char * encrp_key_src,char * intergrity_algo_src,char * intergrity_key_src,int u_id);
+
+extern int setkey_setSA_update(char * ip_src,char * ip_dst,char * ipsec_type,char * spi_src,char * mode,
+ char * encrp_algo_src,char * encrp_key_src,char * intergrity_algo_src,char * intergrity_key_src,int u_id);
+
+/*set one SP of one direction just for transport mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+ direction:src->dst */
+extern int setkey_SP(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * ipsec_type,char * mode, char * direction,int u_id);
+extern int setkey_SP_xfrm(int cmd,char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type,char * mode, char * direction,int u_id);
+
+/*set one SP of one direction, just for tunnel mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+ direction:src->dst
+src_tunnel,dst_tunnel: tunnel src ip tunnel dst ip */
+extern int setkey_SP_tunnel(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type,char * mode, char * direction,int u_id);
+
+
+/*set one SP of one direction, for 2 layers' ipsec--tunnel mode+transport mode or transport mode+tunnel mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+ direction:src->dst
+src_tunnel,dst_tunnel: tunnel src ip tunnel dst ip */
+extern int setkey_SP_tunnel_transport(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type1,char * mode1, char * ipsec_type2,char * mode2,char * direction,int u_id1,int u_id2);
+
+/*update one SP of one direction, just for transport mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+ direction:src->dst*/
+int setkey_SP_update_transport(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * ipsec_type, char * direction,int u_id);
+
+
+/*update one SP of one direction, for 2 layers' ipsec--tunnel mode+transport mode or transport mode+tunnel mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+ direction:src->dst
+src_tunnel,dst_tunnel: tunnel src ip tunnel dst ip */
+int setkey_SP_update_tunnel_transport(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type1,char * mode1, char * ipsec_type2,char * mode2,char * direction,int u_id1,int u_id2);
+int setkey_SP_2layer_xfrm(int cmd,char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type1,char * mode1, char * ipsec_type2,char * mode2,char * direction,int u_id1,int u_id2);
+
+/*flush SA\SP from setkey.conf*/
+extern int flush_SA_SP_exist();
+extern int flush_SA_SP_exist_xfrm();
+
diff --git a/src/connectivity/libipsecims/setkey_xfrm.c b/src/connectivity/libipsecims/setkey_xfrm.c
new file mode 100644
index 0000000..c2cffba
--- /dev/null
+++ b/src/connectivity/libipsecims/setkey_xfrm.c
@@ -0,0 +1,833 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+#include <linux/capability.h>
+#include <sys/capability.h>
+#include <cutils/properties.h>
+#include "setkey_fileio.h"
+#include "setkey_xfrm_parse.h"
+#include "utils_xfrm.h"
+#define LOG_TAG "setkey"
+#include <log/log.h>
+#include <cutils/log.h>
+
+int volte_pid = -1;
+extern program_invocation_name;
+/*only record volte_stack's pid for flush_SA_SP_exist's use*/
+void set_property_volte()
+{
+ char pid[8] ={0};
+ if(program_invocation_name!=NULL)
+ {
+ ALOGE("program_invocation_name:%s\n",program_invocation_name);
+ }
+ if(strstr(program_invocation_name,"volte")!= NULL)
+ if(volte_pid ==-1)
+ {
+ sprintf(pid,"%d",getpid());
+ int ret = property_set("net.ims.volte.pid",pid);
+ if(ret != 0)
+ {
+ ALOGE("set property failed,errno:%d\n",errno);
+ return;
+ }
+ volte_pid =getpid();
+ }
+}
+
+static int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
+ int alen)
+{
+ int len = RTA_LENGTH(alen);
+ struct rtattr *rta = NULL;
+
+ if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
+ ALOGD( "addattr_l ERROR: message exceeded bound of %d\n",maxlen);
+ return -1;
+ }
+
+ rta = NLMSG_TAIL(n);
+ rta->rta_type = type;
+ rta->rta_len = len;
+ memcpy(RTA_DATA(rta), data, alen);
+ n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
+ return 0;
+}
+
+int setkey_deleteSP_xfrm(char * src,char * dst,enum PROTOCOL_TYPE protocol,char * src_port,char * dst_port,char * direction)
+{
+
+ char src_arr[128] = {0};
+ char dst_arr[128] = {0};
+ unsigned groups = ~((unsigned)0); /* XXX */
+ struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+
+ memcpy(src_arr,src,strlen(src));
+ memcpy(dst_arr,dst,strlen(dst));
+
+
+/*fragment delete policy netlink msg*/
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_userpolicy_id xpid;
+ char buf[RTA_BUF_SIZE];
+ } req;
+
+ memset(&req, 0, sizeof(req));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpid));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = XFRM_MSG_DELPOLICY;
+
+ req.xpid.dir = xfrm_dir_parse(direction);
+ if(req.xpid.dir == XFRM_POLICY_ERROR)
+ {
+ ALOGD("setkey_deleteSP_xfrm dir:%s is wrong\n",direction);
+ return -1;
+ }
+ xfrm_selector_parse(&req.xpid.sel, src_arr,dst_arr,protocol,src_port,dst_port);
+
+ groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+ if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+ return -1;
+
+ if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+ {
+ ALOGD("set2layeripsecrules_xfrm send failed,errno:%d\n",errno);
+ rtnl_close_xfrm(&rth);
+ return -1;
+ }
+ if(req.xpid.dir ==XFRM_POLICY_IN)
+ {
+ req.xpid.dir = XFRM_POLICY_FWD;
+ if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+ {
+ ALOGD("setkey_deleteSP_xfrm send POLICY_FWD failed,errno:%d",errno);
+ rtnl_close_xfrm(&rth);
+ return -1;
+ }
+ }
+#ifdef INIT_ENG_BUILD
+ ALOGD("setkey_deleteSP_xfrm successed fd:%d --spddelete %s[%s] %s[%s] %d -P %s;\n",rth.fd,src,src_port,dst,dst_port,protocol,direction);
+#endif
+ rtnl_close_xfrm(&rth);
+ return 0;
+}
+
+int setkey_deleteSA_xfrm(char * src,char * dst,char * ipsec_type,char * spi_src)
+{
+
+ char src_arr[128] = {0};
+ char dst_arr[128] = {0};
+ unsigned groups = ~((unsigned)0); /* XXX */
+ struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+ memcpy(src_arr,src,strlen(src));
+ memcpy(dst_arr,dst,strlen(dst));
+
+ /*fragment delete state netlink msg*/
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_usersa_id xsid;
+ char buf[RTA_BUF_SIZE];
+ } req;
+
+ memset(&req, 0, sizeof(req));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsid));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = XFRM_MSG_DELSA;
+ req.xsid.family = AF_UNSPEC;
+
+ /* ID */
+ struct xfrm_id id ;
+ xfrm_address_t saddr_xfrm;
+ memset(&id, 0, sizeof(id));
+ memset(&saddr_xfrm, 0, sizeof(saddr_xfrm));
+ xfrm_id_parse(&saddr_xfrm, &id, &req.xsid.family,src_arr,dst_arr,ipsec_type);
+ __u32 spi;
+ if (get_u32(&spi, spi_src, 0))
+ {
+ ALOGD("xfrm_id_parse spi:%s is wrong\n",spi_src);
+ return -1;
+ }
+
+ spi = htonl(spi);
+ id.spi = spi;
+ memcpy(&req.xsid.daddr, &id.daddr, sizeof(req.xsid.daddr));
+ req.xsid.spi = id.spi;
+ req.xsid.proto = id.proto;
+
+ addattr_l(&req.n, sizeof(req.buf), XFRMA_SRCADDR,
+ (void *)&saddr_xfrm, sizeof(saddr_xfrm));
+
+ groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+
+ if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+ return -1;
+ if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+ {
+ ALOGD("set2layeripsecrules_xfrm send failed,errno:%d\n",errno);
+ rtnl_close_xfrm(&rth);
+ return -1;
+ }
+#ifdef INIT_ENG_BUILD
+ ALOGD("setkey_deleteSA_xfrm successed fd:%d --delete %s %s %s %s;\n",rth.fd,src,dst,ipsec_type,spi_src);
+#endif
+ rtnl_close_xfrm(&rth);
+ return 0;
+}
+
+int setkey_setSA_xfrm(int cmd,char * ip_src,char * ip_dst,char * ipsec_type,char * spi_src,char * mode,
+ char * encrp_algo_src,char * encrp_key_src,char * intergrity_algo_src,char * intergrity_key_src,int u_id)
+{
+
+ char encrp_algo_arr[128] = {0};
+ char intergrity_algo_arr[128] = {0};
+ char srcport_arr[64] = {0};
+ char dstport_arr[64] = {0};
+ char * port_head = NULL;
+ char * port_tail = NULL;
+ char src_arr[128] = {0};
+ char dst_arr[128] = {0};
+ unsigned groups = ~((unsigned)0); /* XXX */
+ struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+ set_property_volte();
+
+ /*sepearte src addr and src port\dst addr and dst port, state's format often is add xx[xx] xx[xx] esp xx ....*/
+ port_head = strchr(ip_src,'[');
+ if(port_head == NULL)
+ {
+ memcpy(src_arr,ip_src,strlen(ip_src));
+ memcpy(srcport_arr,"0",1);
+ }
+ else
+ {
+ port_tail = strchr(ip_src,']');
+ if (port_tail == NULL)
+ {
+#ifdef INIT_ENG_BUILD
+ ALOGD("setkey_SA_xfrm wrong src ip:%s \n",ip_src);
+#endif
+ return -1;
+ }
+ else
+ {
+ memcpy(srcport_arr,port_head+1,port_tail-port_head-1);
+ memcpy(src_arr,ip_src,port_head-ip_src);
+ }
+ }
+ port_head = strchr(ip_dst,'[');
+ if(port_head==NULL)
+ {
+ memcpy(dst_arr,ip_dst,strlen(ip_dst));
+ memcpy(dstport_arr,"0",1);
+ }
+ else
+ {
+ port_tail = strchr(ip_dst,']');
+ if (port_tail == NULL)
+ {
+#ifdef INIT_ENG_BUILD
+ ALOGD("setkey_SA_xfrm wrong dst ip:%s \n",ip_dst);
+#endif
+ return -1;
+ }
+ else
+ {
+ memcpy(dstport_arr,port_head+1,port_tail-port_head-1);
+ memcpy(dst_arr,ip_dst,port_head-ip_dst);
+ }
+ }
+
+ /*fragment add/modify state netlink msg*/
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_usersa_info xsinfo;
+ char buf[RTA_BUF_SIZE];
+ } req;
+
+ memset(&req, 0, sizeof(req));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsinfo));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = cmd;
+
+
+ req.xsinfo.family = AF_UNSPEC;
+ req.xsinfo.lft.soft_byte_limit = XFRM_INF;
+ req.xsinfo.lft.hard_byte_limit = XFRM_INF;
+ req.xsinfo.lft.soft_packet_limit = XFRM_INF;
+ req.xsinfo.lft.hard_packet_limit = XFRM_INF;
+ req.xsinfo.reqid = u_id;
+ /* ID */
+ if(xfrm_mode_parse(&req.xsinfo.mode, mode) ==-1)
+ {
+ ALOGD("setkey_SA_xfrm mode:%s is wrong\n",mode);
+ return -1;
+ }
+ __u32 spi;
+ if (get_u32(&spi, spi_src, 0))
+ {
+ ALOGD("xfrm_id_parse spi:%s is wrong\n",spi_src);
+ return -1;
+ }
+
+ spi = htonl(spi);
+ req.xsinfo.id.spi = spi;
+ if(xfrm_id_parse(&req.xsinfo.saddr, &req.xsinfo.id,&req.xsinfo.family,
+ src_arr,dst_arr,ipsec_type)<0)
+ {
+#ifdef INIT_ENG_BUILD
+ ALOGD("setkey_SA_xfrm->xfrm_id_parse failed ip_src:%s,ip_dst:%s,ipsec_type:%s",ip_src,ip_dst,ipsec_type);
+#endif
+ return -1;
+ }
+ xfrm_selector_parse(&req.xsinfo.sel, src_arr,dst_arr,0,srcport_arr,dstport_arr);
+ /* ALGO */
+ struct {
+ union {
+ struct xfrm_algo alg;
+ struct xfrm_algo_aead aead;
+ struct xfrm_algo_auth auth;
+ } u;
+ char buf[XFRM_ALGO_KEY_BUF_SIZE];
+ } alg;
+ int len;
+ char *buf = NULL;
+ memset(&alg, 0, sizeof(alg));
+ buf = alg.u.alg.alg_key;
+ len = sizeof(alg.u.alg);
+
+ xfrm_encry_algo_parse(encrp_algo_src, encrp_algo_arr);
+ if(strcmp(encrp_algo_arr,"not-supported") == 0)
+ return -1;
+
+ if((encrp_algo_src == NULL)||(strcmp(encrp_algo_src,"null")==0))
+ {
+ alg.u.alg.alg_key_len = 0;
+ memcpy(alg.u.alg.alg_name, "ecb(cipher_null)", strlen("ecb(cipher_null)"));
+ }
+ else
+ if(xfrm_algo_parse((void *)&alg, encrp_algo_arr, encrp_key_src,
+ buf, sizeof(alg.buf))==-1)
+ {
+#ifdef INIT_ENG_BUILD
+ ALOGD("setkey_SA_xfrm->xfrm_algo_parse failed encrp_algo:%s,encrp_key:%s,",encrp_algo_src, encrp_key_src);
+#endif
+ return -1;
+ }
+ len += alg.u.alg.alg_key_len;
+ addattr_l(&req.n, sizeof(req.buf), XFRMA_ALG_CRYPT,(void *)&alg, len);
+
+ memset((void *)&alg, 0,sizeof(alg));
+ buf = alg.u.alg.alg_key;
+ len = sizeof(alg.u.alg);
+ xfrm_interg_algo_parse(intergrity_algo_src, intergrity_algo_arr);
+ if(strcmp(intergrity_algo_arr ,"not-supported") == 0)
+ return -1;
+ if((intergrity_algo_src == NULL)||(strcmp(intergrity_algo_src,"null")==0))
+ {
+ alg.u.alg.alg_key_len = 0;
+ memcpy(alg.u.alg.alg_name, "digest_null", strlen("digest_null"));
+ }
+ else
+ if(xfrm_algo_parse((void *)&alg, intergrity_algo_arr, intergrity_key_src,
+ buf, sizeof(alg.buf))<-1)
+ {
+#ifdef INIT_ENG_BUILD
+ ALOGD("setkey_SA_xfrm->xfrm_algo_parse failed intergrity crp_algo:%s,intergrity _key:%s,",intergrity_algo_src, intergrity_key_src);
+#endif
+ return -1;
+ }
+ len += alg.u.alg.alg_key_len;
+ addattr_l(&req.n, sizeof(req.buf), XFRMA_ALG_AUTH,(void *)&alg, len);
+
+ groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+
+ if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+ return -1;
+
+ if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+ {
+ ALOGD("set2layeripsecrules_xfrm send failed,errno:%d",errno);
+ rtnl_close_xfrm(&rth);
+ return -1;
+ }
+#ifdef INIT_ENG_BUILD
+ ALOGD("setkey_SA_xfrm successed fd:%d ---add %s %s %s %s -m %s -E %s %s -A %s %s -u %d; spi:%d\n",rth.fd,ip_src,ip_dst,ipsec_type,spi_src,mode,
+ encrp_algo_src,encrp_key_src,intergrity_algo_src,intergrity_key_src,u_id,req.xsinfo.id.spi);
+#endif
+ rtnl_close_xfrm(&rth);
+ return 0;
+}
+
+
+int setkey_SP_xfrm(int cmd,char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type,char * mode, char * direction,int u_id)
+{
+ char src_arr[128] = {0};
+ char dst_arr[128] = {0};
+ char src_tunnel_arr[128] = {0};
+ char dst_tunnel_arr[128] = {0};
+ unsigned groups = ~((unsigned)0); /* XXX */
+ struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+ memcpy(src_arr,src_range,strlen(src_range));
+ memcpy(dst_arr,dst_range,strlen(dst_range));
+ if(src_tunnel)
+ memcpy(src_tunnel_arr,src_tunnel,strlen(src_tunnel));
+ if(dst_tunnel)
+ memcpy(dst_tunnel_arr,dst_tunnel,strlen(dst_tunnel));
+
+ set_property_volte();
+
+
+
+ struct req_handle_xfrm req;
+ char tmpls_buf[XFRM_TMPLS_BUF_SIZE];
+ struct xfrm_user_tmpl *tmpl = NULL;
+ int tmpls_len = 0;
+
+
+ memset(&req, 0, sizeof(req));
+ memset(&tmpls_buf, 0, sizeof(tmpls_buf));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpinfo));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = cmd;
+
+ req.xpinfo.lft.soft_byte_limit = XFRM_INF;
+ req.xpinfo.lft.hard_byte_limit = XFRM_INF;
+ req.xpinfo.lft.soft_packet_limit = XFRM_INF;
+ req.xpinfo.lft.hard_packet_limit = XFRM_INF;
+ req.xpinfo.dir = xfrm_dir_parse(direction);
+ req.xpinfo.priority = 1000;
+ xfrm_selector_parse(&req.xpinfo.sel, src_arr,dst_arr,protocol,port_src,port_dst);
+
+ if(req.xpinfo.dir == XFRM_POLICY_ERROR)
+ {
+ ALOGD("setkey_SP_xfrm dir:%s is wrong",direction);
+ return -1;
+ }
+ tmpl = (struct xfrm_user_tmpl *)((char *)tmpls_buf + tmpls_len);
+
+ if(xfrm_mode_parse(&tmpl->mode, mode) ==-1)
+ {
+ ALOGD("setkey_SP_xfrm mode:%s is wrong",mode);
+ return -1;
+ }
+ tmpl->family = req.xpinfo.sel.family;
+ if(tmpl->mode == XFRM_MODE_TUNNEL)
+ {
+ xfrm_id_parse(&tmpl->saddr, &tmpl->id, &tmpl->family,
+ src_tunnel_arr,dst_tunnel_arr,ipsec_type);
+ }
+
+ tmpl->aalgos = (~(__u32)0);
+ tmpl->ealgos = (~(__u32)0);
+ tmpl->calgos = (~(__u32)0);
+ tmpl->reqid = u_id;
+ tmpl->id.proto = xfrm_xfrmproto_getbyname(ipsec_type);
+ if(tmpl->id.proto <0)
+ {
+ ALOGD("setkey_SP_xfrm ipsec_type:%s is wrong",ipsec_type);
+ return -1;
+ }
+ tmpls_len += sizeof(*tmpl);
+ if (tmpls_len > 0) {
+ addattr_l(&req.n, sizeof(req), XFRMA_TMPL,
+ (void *)tmpls_buf, tmpls_len);
+ }
+
+ groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+
+ if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+ return -1;
+
+ if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+ {
+ ALOGD("set2layeripsecrules_xfrm send failed,errno:%d",errno);
+ rtnl_close_xfrm(&rth);
+ return -1;
+ }
+ if(req.xpinfo.dir ==XFRM_POLICY_IN)
+ {
+ req.xpinfo.dir = XFRM_POLICY_FWD;
+ if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+ {
+ ALOGD("set2layeripsecrules_xfrm send POLICY_FWD failed,errno:%d",errno);
+ rtnl_close_xfrm(&rth);
+ return -1;
+ }
+ }
+#ifdef INIT_ENG_BUILD
+ ALOGD("setkey_SP_xfrm successed fd:%d --spdadd %s[%s] %s[%s] %d -P %s ipsec %s/%s//unique:%d;\n",rth.fd,src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type,mode,u_id);
+#endif
+ rtnl_close_xfrm(&rth);
+ return 0;
+}
+
+int setkey_SP_2layer_xfrm(int cmd,char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type1,char * mode1, char * ipsec_type2,char * mode2,char * direction,int u_id1,int u_id2)
+{
+ char src_arr[128] = {0};
+ char dst_arr[128] = {0};
+ char src_tunnel_arr[128] = {0};
+ char dst_tunnel_arr[128] = {0};
+ unsigned groups = ~((unsigned)0); /* XXX */
+ struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+ memcpy(src_arr,src_range,strlen(src_range));
+ memcpy(dst_arr,dst_range,strlen(dst_range));
+ if(src_tunnel)
+ memcpy(src_tunnel_arr,src_tunnel,strlen(src_tunnel));
+ if(dst_tunnel)
+ memcpy(dst_tunnel_arr,dst_tunnel,strlen(dst_tunnel));
+
+
+ struct req_handle_xfrm req;
+ char tmpls_buf[XFRM_TMPLS_BUF_SIZE];
+ struct xfrm_user_tmpl *tmpl = NULL;
+ int tmpls_len = 0;
+
+ set_property_volte();
+
+ memset(&req, 0, sizeof(req));
+ memset(&tmpls_buf, 0, sizeof(tmpls_buf));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpinfo));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = cmd;
+
+ req.xpinfo.lft.soft_byte_limit = XFRM_INF;
+ req.xpinfo.lft.hard_byte_limit = XFRM_INF;
+ req.xpinfo.lft.soft_packet_limit = XFRM_INF;
+ req.xpinfo.lft.hard_packet_limit = XFRM_INF;
+ req.xpinfo.dir = xfrm_dir_parse(direction);
+ req.xpinfo.priority = 1000;
+ xfrm_selector_parse(&req.xpinfo.sel, src_arr,dst_arr,protocol,port_src,port_dst);
+
+ if(req.xpinfo.dir == XFRM_POLICY_ERROR)
+ {
+ ALOGD("setkey_SP_xfrm dir:%s is wrong",direction);
+ return -1;
+ }
+ tmpl = (struct xfrm_user_tmpl *)((char *)tmpls_buf + tmpls_len);
+
+ if(xfrm_mode_parse(&tmpl->mode, mode1) ==-1)
+ {
+ ALOGD("setkey_SP_xfrm mode:%s is wrong",mode1);
+ return -1;
+ }
+ tmpl->family = req.xpinfo.sel.family;
+ if(tmpl->mode == XFRM_MODE_TUNNEL)
+ {
+ xfrm_id_parse(&tmpl->saddr, &tmpl->id, &tmpl->family,
+ src_tunnel_arr,dst_tunnel_arr,ipsec_type1);
+ }
+
+ tmpl->aalgos = (~(__u32)0);
+ tmpl->ealgos = (~(__u32)0);
+ tmpl->calgos = (~(__u32)0);
+ tmpl->reqid = u_id1;
+ tmpl->id.proto = xfrm_xfrmproto_getbyname(ipsec_type1);
+ if(tmpl->id.proto <0)
+ {
+ ALOGD("setkey_SP_xfrm ipsec_type:%s is wrong",ipsec_type1);
+ return -1;
+ }
+ tmpls_len += sizeof(*tmpl);
+ tmpl = (struct xfrm_user_tmpl *)((char *)tmpls_buf + tmpls_len);
+
+ if(xfrm_mode_parse(&tmpl->mode, mode2) ==-1)
+ {
+ ALOGD("setkey_SP_xfrm mode:%s is wrong",mode1);
+ return -1;
+ }
+ tmpl->family = req.xpinfo.sel.family;
+ if(tmpl->mode == XFRM_MODE_TUNNEL)
+ {
+ xfrm_id_parse(&tmpl->saddr, &tmpl->id, &tmpl->family,
+ src_tunnel_arr,dst_tunnel_arr,ipsec_type2);
+ }
+ tmpl->aalgos = (~(__u32)0);
+ tmpl->ealgos = (~(__u32)0);
+ tmpl->calgos = (~(__u32)0);
+ tmpl->reqid = u_id2;
+ tmpl->id.proto = xfrm_xfrmproto_getbyname(ipsec_type2);
+ if(tmpl->id.proto <0)
+ {
+ ALOGD("setkey_SP_xfrm ipsec_type:%s is wrong",ipsec_type2);
+ return -1;
+ }
+ tmpls_len += sizeof(*tmpl);
+ if (tmpls_len > 0) {
+ addattr_l(&req.n, sizeof(req), XFRMA_TMPL,
+ (void *)tmpls_buf, tmpls_len);
+ }
+
+ groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+
+ if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+ return -1;
+
+ if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+ {
+ ALOGD("set2layeripsecrules_xfrm send failed,errno:%d",errno);
+ rtnl_close_xfrm(&rth);
+ return -1;
+ }
+ if(req.xpinfo.dir ==XFRM_POLICY_IN)
+ {
+ req.xpinfo.dir = XFRM_POLICY_FWD;
+ if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+ {
+ ALOGD("set2layeripsecrules_xfrm send POLICY_FWD failed,errno:%d",errno);
+ rtnl_close_xfrm(&rth);
+ return -1;
+ }
+ }
+#ifdef INIT_ENG_BUILD
+ ALOGD("setkey_SP_2layer_xfrm successed fd:%d --spdupdate %s[%s] %s[%s] %d -P %s prio 1000 ipsec %s/%s//unique:%d %s/%s/%s-%s/unique:%d;\n",rth.fd,src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type1,mode1,u_id1,ipsec_type2,mode2,src_tunnel,dst_tunnel,u_id2);
+#endif
+ rtnl_close_xfrm(&rth);
+ return 0;
+}
+int setkey_flushSAD_xfrm(char * ipsec_type)
+{
+ unsigned groups = ~((unsigned)0); /* XXX */
+ struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_usersa_flush xsf;
+ } req;
+
+
+ memset(&req, 0, sizeof(req));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsf));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = XFRM_MSG_FLUSHSA;
+ req.xsf.proto = 0;
+
+ req.xsf.proto = (__u8)xfrm_xfrmproto_getbyname(ipsec_type);
+ if (req.xsf.proto < 0)
+ {
+ ALOGD("setkey_flushSAD_xfrm :%s is wrong",ipsec_type);
+ return -1;
+ }
+
+ groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+
+ if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+ return -1;
+
+ if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+ {
+ ALOGD("set2layeripsecrules_xfrm send POLICY_FWD failed,errno:%d",errno);
+ rtnl_close_xfrm(&rth);
+ return -1;
+ }
+ ALOGD("setkey_flushSAD_xfrm successed fd:%d --flush ;\n",rth.fd);
+ rtnl_close_xfrm(&rth);
+
+ return 0;
+}
+int setkey_flushSPD_xfrm(void)
+{
+ unsigned groups = ~((unsigned)0); /* XXX */
+ struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+
+ struct {
+ struct nlmsghdr n;
+ char buf[RTA_BUF_SIZE];
+ } req;
+
+ memset(&req, 0, sizeof(req));
+
+
+ req.n.nlmsg_len = NLMSG_LENGTH(0); /* nlmsg data is nothing */
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = XFRM_MSG_FLUSHPOLICY;
+
+ groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+
+ if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+ return -1;
+ if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+ {
+ ALOGD("set2layeripsecrules_xfrm send POLICY_FWD failed,errno:%d",errno);
+ rtnl_close_xfrm(&rth);
+ return -1;
+ }
+ ALOGD("setkey_flushSPD_xfrm successed fd:%d --flush ;\n",rth.fd);
+
+ rtnl_close_xfrm(&rth);
+
+ return 0;
+}
+int flush_SA_SP_exist_xfrm()
+{
+ unsigned groups = ~((unsigned)0); /* XXX */
+ struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+ struct {
+ struct nlmsghdr nlh;
+ struct rtgenmsg g;
+ __u16 align_rta; /* attribute has to be 32bit aligned */
+ struct rtattr ext_req;
+ __u32 ext_filter_mask;
+ } req;
+
+ memset(&req, 0, sizeof(req));
+ req.nlh.nlmsg_len = sizeof(req);
+ req.nlh.nlmsg_type = XFRM_MSG_GETPOLICY;
+ req.nlh.nlmsg_flags = NLM_F_DUMP|NLM_F_REQUEST;
+ req.nlh.nlmsg_seq = rth.dump = ++rth.seq;
+ req.g.rtgen_family = AF_UNSPEC;
+
+ req.ext_req.rta_type = IFLA_EXT_MASK;
+ req.ext_req.rta_len = RTA_LENGTH(sizeof(__u32));
+ req.ext_filter_mask = RTEXT_FILTER_VF;
+
+ groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+
+ if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+ return -1;
+ if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+ {
+ ALOGD("flush_SA_SP_exist_xfrm send msg failed,errno:%d",errno);
+ rtnl_close_xfrm(&rth);
+ return -1;
+ }
+ if (rtnl_listen_xfrm(&rth, rtnl_accept_msg_xfrm) < 0)
+ {
+ rtnl_close_xfrm(&rth);
+ ALOGD("flush_SA_SP_exist_xfrm <0 done");
+ return -2;
+ }
+ ALOGD("flush_SA_SP_exist_xfrm done");
+ rtnl_close_xfrm(&rth);
+
+ return 0;
+}
+
+int xfrm_policy_process_delete_exist( struct rtnl_handle_xfrm * rth,struct nlmsghdr *n,pid_t volte_pid)
+{
+
+ struct xfrm_userpolicy_info *xpinfo = NULL;
+ int len = n->nlmsg_len;
+
+
+ xpinfo = NLMSG_DATA(n);
+ len -= NLMSG_SPACE(sizeof(*xpinfo));
+ if (len < 0) {
+ ALOGE( "BUG: wrong nlmsg len %d\n", len);
+ return -1;
+ }
+ if(xpinfo->sel.user != volte_pid)
+ {
+ ALOGE( "we donot need to process:%d's policy\n", xpinfo->sel.user);
+ return 0;
+ }
+
+/*fragment delete policy*/
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_userpolicy_id xpid;
+ char buf[RTA_BUF_SIZE];
+ } req;
+
+ memset(&req, 0, sizeof(req));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpid));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = XFRM_MSG_DELPOLICY;
+
+ req.xpid.dir = xpinfo->dir;
+
+ memcpy(&req.xpid.sel,&xpinfo->sel,sizeof(req.xpid.sel));
+
+
+ if(send(rth->fd, (void*)&req, sizeof(req), 0)<0)
+ {
+ ALOGD("xfrm_policy_process_delete_exist send failed,errno:%d",errno);
+ return -1;
+ }
+#ifdef INIT_ENG_BUILD
+ if(req.xpid.sel.family == AF_INET)
+ ALOGD("xfrm_policy_process_delete_exist successed fd:%d --spddelete 0x%x[%d] 0x%x[%d] %d -P %d;\n",rth->fd,req.xpid.sel.saddr.a4,req.xpid.sel.sport,req.xpid.sel.daddr.a4,req.xpid.sel.dport,req.xpid.sel.proto,req.xpid.dir);
+ else
+ ALOGD("xfrm_policy_process_delete_exist successed fd:%d --spddelete 0x%x %x %x %x[%d] 0x%x %x %x %x[%d] %d -P %d;\n",rth->fd,
+ req.xpid.sel.saddr.a6[0],req.xpid.sel.saddr.a6[1],req.xpid.sel.saddr.a6[2],req.xpid.sel.saddr.a6[3],req.xpid.sel.sport,
+ req.xpid.sel.daddr.a6[0],req.xpid.sel.daddr.a6[1],req.xpid.sel.daddr.a6[2],req.xpid.sel.daddr.a6[3],req.xpid.sel.dport,
+ req.xpid.sel.proto,req.xpid.dir);
+#endif
+ return 0;
+}
+
+int xfrm_state_process_delete_exist( struct rtnl_handle_xfrm * rth,struct nlmsghdr *n,pid_t volte_pid)
+{
+
+ struct xfrm_usersa_info * xsinfo = NULL;
+ int len = n->nlmsg_len;
+ xfrm_address_t saddr;
+
+ xsinfo = NLMSG_DATA(n);
+ len -= NLMSG_SPACE(sizeof(*xsinfo));
+ if (len < 0) {
+ ALOGE( "BUG: wrong nlmsg len %d\n", len);
+ return -1;
+ }
+
+ if(xsinfo->sel.user != volte_pid)
+ {
+ ALOGE( "we donot need to process:%d's policy\n", xsinfo->sel.user);
+ return 0;
+ }
+
+/*fragment delete state*/
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_usersa_id xsid;
+ char buf[RTA_BUF_SIZE];
+ } req;
+
+ memset(&req, 0, sizeof(req));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsid));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = XFRM_MSG_DELSA;
+
+ req.xsid.family = xsinfo->family;
+ memcpy(&req.xsid.daddr,&xsinfo->sel.daddr,sizeof(xsinfo->sel.daddr));
+ memcpy(&saddr,&xsinfo->saddr,sizeof(xsinfo->saddr));
+ addattr_l(&req.n, sizeof(req.buf), XFRMA_SRCADDR,
+ (void *)&saddr, sizeof(saddr));
+ if(send(rth->fd, (void*)&req, sizeof(req), 0)<0)
+ {
+ ALOGD("xfrm_state_process_delete_exist send failed,errno:%d",errno);
+ return -1;
+ }
+#ifdef INIT_ENG_BUILD
+ if(xsinfo->sel.family == AF_INET)
+ ALOGD("xfrm_state_process_delete_exist successed fd:%d --delete 0x%x 0x%x %d;\n",rth->fd,xsinfo->sel.saddr.a4,xsinfo->sel.daddr.a4,xsinfo->id.spi);
+ else
+ ALOGD("xfrm_state_process_delete_exist successed fd:%d --delete 0x%x %x %x %x 0x%x %x %x %x %d ;\n",rth->fd,
+ xsinfo->sel.saddr.a6[0],xsinfo->sel.saddr.a6[1],xsinfo->sel.saddr.a6[2],xsinfo->sel.saddr.a6[3],
+ xsinfo->sel.daddr.a6[0],xsinfo->sel.daddr.a6[1],xsinfo->sel.daddr.a6[2],xsinfo->sel.daddr.a6[3],
+ xsinfo->id.spi);
+#endif
+ return 0;
+}
+
diff --git a/src/connectivity/libipsecims/setkey_xfrm_parse.c b/src/connectivity/libipsecims/setkey_xfrm_parse.c
new file mode 100644
index 0000000..44e1aeb
--- /dev/null
+++ b/src/connectivity/libipsecims/setkey_xfrm_parse.c
@@ -0,0 +1,272 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+#include <linux/capability.h>
+#include <sys/capability.h>
+#include <cutils/properties.h>
+#include "setkey_fileio.h"
+#include "utils_xfrm.h"
+#include "setkey_xfrm_parse.h"
+#define LOG_TAG "setkey"
+#include <log/log.h>
+#include <cutils/log.h>
+
+
+const struct typeent xfrmproto_types[]= {
+ { "esp", IPPROTO_ESP }, { "ah", IPPROTO_AH }, { "comp", IPPROTO_COMP },
+ { "route2", IPPROTO_ROUTING }, { "hao", IPPROTO_DSTOPTS },
+ { "ipsec-any", IPSEC_PROTO_ANY },
+ { NULL, -1 }
+};
+
+
+int xfrm_xfrmproto_getbyname(char *name)
+{
+ int i;
+
+ for (i = 0; ; i++) {
+ const struct typeent *t = &xfrmproto_types[i];
+ if (!t->t_name || t->t_type == -1)
+ break;
+
+ if (strcmp(t->t_name, name) == 0)
+ return t->t_type;
+ }
+
+ return -1;
+}
+
+
+int xfrm_id_parse(xfrm_address_t *saddr_xfrm, struct xfrm_id *id, __u16 *family,
+ char * src,char * dst,char * ipsec_type)
+{
+
+ inet_prefix dst_prefix;
+ inet_prefix src_prefix;
+
+ memset(&dst_prefix, 0, sizeof(dst_prefix));
+ memset(&src_prefix, 0, sizeof(src_prefix));
+
+ get_prefix(&src_prefix, src, AF_UNSPEC);
+ if (family)
+ *family = src_prefix.family;
+ memcpy(saddr_xfrm, &src_prefix.data, sizeof(*saddr_xfrm));
+ get_prefix(&dst_prefix, dst, AF_UNSPEC);
+ memcpy(&id->daddr, &dst_prefix.data, sizeof(id->daddr));
+
+ int ret = xfrm_xfrmproto_getbyname(ipsec_type);
+ if(ret<0)
+ {
+ ALOGD("xfrm_id_parse %s is wrong\n",ipsec_type);
+ return -1;
+ }
+ id->proto = (__u8)ret;
+
+
+ return 0;
+}
+
+void xfrm_encry_algo_parse(char * encry_src, char *name)
+{
+ if(encry_src == NULL)
+ memcpy(name,"ecb(cipher_null)",strlen("ecb(cipher_null)"));
+ else if(strcmp(encry_src,"des-cbc")==0)
+ memcpy(name,"cbc(des)",strlen("cbc(des)"));
+ else if(strcmp(encry_src,"des-ede3-cbc")==0)
+ memcpy(name,"cbc(des3_ede)",strlen("cbc(des3_ede)"));
+ else if(strcmp(encry_src,"3des-cbc")==0)
+ memcpy(name,"cbc(des3_ede)",strlen("cbc(des3_ede)"));
+ else if(strcmp(encry_src,"cast5-cbc")==0)
+ memcpy(name,"cbc(cast5)",strlen("cbc(cast5)"));
+ else if(strcmp(encry_src,"blowfish-cbc")==0)
+ memcpy(name,"cbc(blowfish)",strlen("cbc(blowfish)"));
+ else if(strcmp(encry_src,"aes-cbc")==0)
+ memcpy(name,"cbc(aes)",strlen("cbc(aes)"));
+ else if(strcmp(encry_src,"serpent-cbc")==0)
+ memcpy(name,"cbc(serpent)",strlen("cbc(serpent)"));
+ else if(strcmp(encry_src,"camellia-cbc")==0)
+ memcpy(name,"cbc(camellia)",strlen("cbc(camellia)"));
+ else if(strcmp(encry_src,"twofish-cbc")==0)
+ memcpy(name,"cbc(twofish)",strlen("cbc(twofish)"));
+ else if(strcmp(encry_src,"aes-ctr-rfc3686")==0)
+ memcpy(name,"rfc3686(ctr(aes))",strlen("rfc3686(ctr(aes))"));
+ else if(strcmp(encry_src,"null")==0)
+ memcpy(name,"ecb(cipher_null)",strlen("ecb(cipher_null)"));
+ else
+ {
+ memcpy(name,"not-supported",strlen("not-supported"));
+ ALOGD("xfrm_encry_algo_parse not supported algorithm--%s\n",encry_src);
+ }
+}
+
+void xfrm_interg_algo_parse(char * interg_src, char *name)
+{
+ if(interg_src == NULL)
+ memcpy(name,"digest_null",strlen("digest_null"));
+ else if(strcmp(interg_src,"hmac-md5")==0)
+ memcpy(name,"hmac(md5)",strlen("hmac(md5)"));
+ else if(strcmp(interg_src,"hmac-sha1")==0)
+ memcpy(name,"hmac(sha1)",strlen("hmac(sha1)"));
+ else if(strcmp(interg_src,"hmac-sha256")==0)
+ memcpy(name,"hmac(sha256)",strlen("hmac(sha256)"));
+ else if(strcmp(interg_src,"hmac-sha384)")==0)
+ memcpy(name,"hmac(sha384)",strlen("hmac(sha384)"));
+ else if(strcmp(interg_src,"hmac-sha512")==0)
+ memcpy(name,"hmac(sha512)",strlen("hmac(sha512)"));
+ else if(strcmp(interg_src,"hmac-rmd160")==0)
+ memcpy(name,"hmac(rmd160)",strlen("hmac(rmd160)"));
+ else if(strcmp(interg_src,"aes-xcbc")==0)
+ memcpy(name,"xcbc(aes)",strlen("xcbc(aes)"));
+ else if(strcmp(interg_src,"cmac(aes)")==0)
+ memcpy(name,"aes-cmac",strlen("aes-cmac"));
+ else if(strcmp(interg_src,"null")==0)
+ memcpy(name,"digest_null",strlen("digest_null"));
+ else
+ {
+ memcpy(name,"not-supported",strlen("not-supported"));
+ ALOGD("xfrm_interg_algo_parse not supported algorithm--%s\n",interg_src);
+ }
+}
+
+
+int xfrm_algo_parse(struct xfrm_algo *alg, char *name, char *key, char *buf, int max)
+{
+ int len;
+ int slen = strlen(key);
+
+ strncpy(alg->alg_name, name, sizeof(alg->alg_name));
+
+ if (slen > 2 && strncmp(key, "0x", 2) == 0) {
+ /* split two chars "0x" from the top */
+ char *p = key + 2;
+ int plen = slen - 2;
+ int i;
+ int j;
+
+ /* Converting hexadecimal numbered string into real key;
+ * Convert each two chars into one char(value). If number
+ * of the length is odd, add zero on the top for rounding.
+ */
+
+ /* calculate length of the converted values(real key) */
+ len = (plen + 1) / 2;
+ if (len > max)
+ {
+ ALOGD("xfrm_algo_parse key(len:%d) makes buffer overflow\n",len);
+ return -1;
+ }
+
+ for (i = - (plen % 2), j = 0; j < len; i += 2, j++) {
+ char vbuf[3];
+ __u8 val;
+
+ vbuf[0] = i >= 0 ? p[i] : '0';
+ vbuf[1] = p[i + 1];
+ vbuf[2] = '\0';
+
+ if (get_u8(&val, vbuf, 16))
+ {
+ ALOGD("xfrm_algo_parse key(len:%s) is invalid\n",key);
+ return -1;
+ }
+ buf[j] = val;
+ }
+ } else {
+ len = slen;
+ if (len > 0) {
+ if (len > max)
+ {
+ ALOGD("xfrm_algo_parse key(len:%d) makes buffer overflow\n",len);
+ return -1;
+ }
+
+ strncpy(buf, key, len);
+ }
+ }
+
+ alg->alg_key_len = len * 8;
+
+ return 0;
+}
+
+__u8 xfrm_dir_parse(char * dir_str)
+{
+ __u8 dir;
+ if(strcmp(dir_str,"out")==0)
+ dir = XFRM_POLICY_OUT;
+ else if(strcmp(dir_str,"in")==0)
+ dir = XFRM_POLICY_IN;
+ else if(strcmp(dir_str,"fwd")==0)
+ dir = XFRM_POLICY_FWD;
+ else
+ dir = XFRM_POLICY_ERROR;
+ return dir;
+}
+
+int xfrm_mode_parse(__u8 *mode, char * mode_str)
+{
+
+
+ if (strcmp(mode_str, "transport") == 0)
+ *mode = XFRM_MODE_TRANSPORT;
+ else if (strcmp(mode_str, "tunnel") == 0)
+ *mode = XFRM_MODE_TUNNEL;
+ else if (strcmp(mode_str, "ro") == 0)
+ *mode = XFRM_MODE_ROUTEOPTIMIZATION;
+ else if (strcmp(mode_str, "in_trigger") == 0)
+ *mode = XFRM_MODE_IN_TRIGGER;
+ else if (strcmp(mode_str, "beet") == 0)
+ *mode = XFRM_MODE_BEET;
+ else
+ return -1;
+
+
+ return 0;
+}
+
+void xfrm_selector_parse(struct xfrm_selector *sel, char * src,char * dst,enum PROTOCOL_TYPE protocol,char * src_port,char * dst_port)
+{
+
+ inet_prefix dst_prefix;
+ inet_prefix src_prefix;
+
+ memset(&dst_prefix, 0, sizeof(dst_prefix));
+ memset(&src_prefix, 0, sizeof(src_prefix));
+
+
+ get_prefix(&src_prefix, src, AF_UNSPEC);
+ memcpy(&sel->saddr, &src_prefix.data, sizeof(sel->saddr));
+ sel->prefixlen_s = src_prefix.bitlen;
+
+ get_prefix(&dst_prefix, dst, AF_UNSPEC);
+ memcpy(&sel->daddr, &dst_prefix.data, sizeof(sel->daddr));
+ sel->prefixlen_d = dst_prefix.bitlen;
+
+ sel->family = dst_prefix.family;
+
+ sel->sport = htons(atoi(src_port));
+ sel->dport = htons(atoi(dst_port));
+ sel->dport_mask = ~((__u16)0);
+ sel->sport_mask = ~((__u16)0);
+
+ sel->user = getpid();
+
+ sel->proto = protocol;
+#ifdef INIT_ENG_BUILD
+ if(sel->family == AF_INET)
+ ALOGD("xfrm_selector_parse family:%u,prefix_d:%u,prefix_s:%u,daddr:0x%x,saddr:0x%x,sel->sport:%d,sel->dport:%d,proto:%u,user:%u\n",sel->family,sel->prefixlen_d,sel->prefixlen_s,sel->daddr.a4,sel->daddr.a4,sel->sport,sel->dport,sel->proto,sel->user);
+ else
+ ALOGD("xfrm_selector_parse family:%u,prefix_d:%u,prefix_s:%u,daddr:0x%x %x %x %x,saddr:0x%x %x %x %x ,sel->sport:%d,sel->dport:%d,proto:%u,user:%u\n",sel->family,sel->prefixlen_d,sel->prefixlen_s,sel->daddr.a6[0],sel->daddr.a6[1],sel->daddr.a6[2],sel->daddr.a6[3],sel->saddr.a6[0],sel->saddr.a6[1],sel->saddr.a6[2],sel->saddr.a6[3],sel->sport,sel->dport,sel->proto,sel->user);
+#endif
+}
+
+
+
diff --git a/src/connectivity/libipsecims/setkey_xfrm_parse.h b/src/connectivity/libipsecims/setkey_xfrm_parse.h
new file mode 100644
index 0000000..0ce4635
--- /dev/null
+++ b/src/connectivity/libipsecims/setkey_xfrm_parse.h
@@ -0,0 +1,32 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+#include <linux/capability.h>
+#include <linux/ipsec.h>
+#include <sys/capability.h>
+#include <cutils/properties.h>
+#include "utils_xfrm.h"
+
+struct typeent {
+ const char *t_name;
+ int t_type;
+};
+
+
+
+extern int xfrm_xfrmproto_getbyname(char *name);
+extern int xfrm_id_parse(xfrm_address_t *saddr_xfrm, struct xfrm_id *id, __u16 *family,
+ char * src,char * dst,char * ipsec_type);
+extern int xfrm_algo_parse(struct xfrm_algo *alg, char *name, char *key, char *buf, int max);
+extern __u8 xfrm_dir_parse(char * dir_str);
+extern int xfrm_mode_parse(__u8 *mode, char * mode_str);
+extern void xfrm_selector_parse(struct xfrm_selector *sel, char * src,char * dst,enum PROTOCOL_TYPE protocol,char * src_port,char * dst_port);
+extern void xfrm_encry_algo_parse(char * encry_src, char *name);
+extern void xfrm_interg_algo_parse(char * interg_src, char *name);
diff --git a/src/connectivity/libipsecims/utils_xfrm.c b/src/connectivity/libipsecims/utils_xfrm.c
new file mode 100644
index 0000000..178a19b
--- /dev/null
+++ b/src/connectivity/libipsecims/utils_xfrm.c
@@ -0,0 +1,230 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <resolv.h>
+#include <asm/types.h>
+#include <linux/pkt_sched.h>
+#include <time.h>
+#include <sys/time.h>
+#include <errno.h>
+#include "utils_xfrm.h"
+#define LOG_TAG "setkey"
+#include <log/log.h>
+#include <cutils/log.h>
+
+
+int mask2bits(__u32 netmask_xfrm)
+{
+ unsigned bits_xfrm = 0;
+ __u32 mask_xfrm = ntohl(netmask_xfrm);
+ __u32 host_xfrm = ~mask_xfrm;
+
+ /* a valid netmask must be 2^n - 1 */
+ if ((host_xfrm & (host_xfrm + 1)) != 0)
+ return -1;
+
+ for (; mask_xfrm; mask_xfrm <<= 1)
+ ++bits_xfrm;
+ return bits_xfrm;
+}
+
+int get_netmask(unsigned *val_xfrm, const char *arg_xfrm, int base_xfrm)
+{
+ inet_prefix addr_xfrm;
+
+ if (!get_unsigned(val_xfrm, arg_xfrm, base_xfrm))
+ return 0;
+
+ /* try coverting dotted quad to CIDR */
+ if (!get_addr_1(&addr_xfrm, arg_xfrm, AF_INET) && addr_xfrm.family == AF_INET) {
+ int b_xfrm = mask2bits(addr_xfrm.data[0]);
+
+ if (b_xfrm >= 0) {
+ *val_xfrm = b_xfrm;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+int get_unsigned(unsigned *val_xfrm, const char *arg_xfrm, int base_xfrm)
+{
+ unsigned long res_xfrm = 0;
+ char *ptr_xfrm = NULL;
+
+ if (!arg_xfrm || !*arg_xfrm)
+ return -1;
+ res_xfrm = strtoul(arg_xfrm, &ptr_xfrm, base_xfrm);
+ if (!ptr_xfrm || ptr_xfrm == arg_xfrm || *ptr_xfrm || res_xfrm > UINT_MAX)
+ return -1;
+ *val_xfrm = res_xfrm;
+ return 0;
+}
+
+
+int get_u32(__u32 *val_xfrm, const char *arg_xfrm, int base_xfrm)
+{
+ unsigned long res_xfrm = 0;
+ char *ptr_xfrm = NULL;
+
+ if (!arg_xfrm || !*arg_xfrm)
+ return -1;
+ res_xfrm = strtoul(arg_xfrm, &ptr_xfrm, base_xfrm);
+ if (!ptr_xfrm || ptr_xfrm == arg_xfrm || *ptr_xfrm || res_xfrm > 0xFFFFFFFFUL)
+ return -1;
+ *val_xfrm = res_xfrm;
+ return 0;
+}
+
+
+int get_u8(__u8 *val_xfrm, const char *arg_xfrm, int base_xfrm)
+{
+ unsigned long res_xfrm = 0;
+ char *ptr_xfrm = NULL;
+
+ if (!arg_xfrm || !*arg_xfrm)
+ return -1;
+ res_xfrm = strtoul(arg_xfrm, &ptr_xfrm, base_xfrm);
+ if (!ptr_xfrm || ptr_xfrm == arg_xfrm || *ptr_xfrm || res_xfrm > 0xFF)
+ return -1;
+ *val_xfrm = res_xfrm;
+ return 0;
+}
+
+
+
+/* This uses a non-standard parsing (ie not inet_aton, or inet_pton)
+ * because of legacy choice to parse 10.8 as 10.8.0.0 not 10.0.0.8
+ */
+int get_addr_ipv4(__u8 *ap_xfrm, const char *cp_xfrm)
+{
+ int i_xfrm = 0;
+
+ for (i_xfrm = 0; i_xfrm < 4; i_xfrm++) {
+ unsigned long n_xfrm = 0;
+ char *endp_xfrm = NULL;
+
+ n_xfrm = strtoul(cp_xfrm, &endp_xfrm, 0);
+ if (n_xfrm > 255)
+ return -1; /* bogus network value */
+
+ if (endp_xfrm == cp_xfrm) /* no digits */
+ return -1;
+
+ ap_xfrm[i_xfrm] = n_xfrm;
+
+ if (*endp_xfrm == '\0')
+ break;
+
+ if (i_xfrm == 3 || *endp_xfrm != '.')
+ return -1; /* extra characters */
+ cp_xfrm = endp_xfrm + 1;
+ }
+
+ return 1;
+}
+
+int get_addr_1(inet_prefix *addr_xfrm, const char *name_xfrm, int family)
+{
+ memset(addr_xfrm, 0, sizeof(*addr_xfrm));
+
+ if (strcmp(name_xfrm, "default") == 0 ||
+ strcmp(name_xfrm, "all") == 0 ||
+ strcmp(name_xfrm, "any") == 0) {
+ if (family == AF_DECnet)
+ return -1;
+ addr_xfrm->family = family;
+ addr_xfrm->bytelen = (family == AF_INET6 ? 16 : 4);
+ addr_xfrm->bitlen = -1;
+ return 0;
+ }
+
+ if (strchr(name_xfrm, ':')) {
+ addr_xfrm->family = AF_INET6;
+ if (family != AF_UNSPEC && family != AF_INET6)
+ return -1;
+ if (inet_pton(AF_INET6, name_xfrm, addr_xfrm->data) <= 0)
+ return -1;
+ addr_xfrm->bytelen = 16;
+ addr_xfrm->bitlen = -1;
+ return 0;
+ }
+
+
+ addr_xfrm->family = AF_INET;
+ if (family != AF_UNSPEC && family != AF_INET)
+ return -1;
+
+ if (get_addr_ipv4((__u8 *)addr_xfrm->data, name_xfrm) <= 0)
+ return -1;
+
+ addr_xfrm->bytelen = 4;
+ addr_xfrm->bitlen = -1;
+ return 0;
+}
+
+int get_prefix(inet_prefix *dst_xfrm, char *arg_xfrm, int family)
+{
+ int err = 0 ;
+ unsigned plen = 0;
+ char *slash = NULL;
+
+ memset(dst_xfrm, 0, sizeof(*dst_xfrm));
+
+ if (strcmp(arg_xfrm, "default") == 0 ||
+ strcmp(arg_xfrm, "any") == 0 ||
+ strcmp(arg_xfrm, "all") == 0) {
+ if (family == AF_DECnet)
+ return -1;
+ dst_xfrm->family = family;
+ dst_xfrm->bytelen = 0;
+ dst_xfrm->bitlen = 0;
+ return 0;
+ }
+
+ slash = strchr(arg_xfrm, '/');
+ if (slash)
+ *slash = 0;
+
+ err = get_addr_1(dst_xfrm, arg_xfrm, family);
+ if (err == 0) {
+ switch(dst_xfrm->family) {
+ case AF_INET6:
+ dst_xfrm->bitlen = 128;
+ break;
+ case AF_DECnet:
+ dst_xfrm->bitlen = 16;
+ break;
+ default:
+ case AF_INET:
+ dst_xfrm->bitlen = 32;
+ }
+ if (slash) {
+ if (get_netmask(&plen, slash+1, 0)
+ || plen > dst_xfrm->bitlen) {
+ err = -1;
+ goto done;
+ }
+ dst_xfrm->flags |= PREFIXLEN_SPECIFIED;
+ dst_xfrm->bitlen = plen;
+ }
+ }
+done:
+ if (slash)
+ *slash = '/';
+ return err;
+}
+
+
+
+
+
diff --git a/src/connectivity/libipsecims/utils_xfrm.h b/src/connectivity/libipsecims/utils_xfrm.h
new file mode 100644
index 0000000..60d519a
--- /dev/null
+++ b/src/connectivity/libipsecims/utils_xfrm.h
@@ -0,0 +1,109 @@
+#ifndef __UTILS_XFRM_H__
+#define __UTILS_XFRM_H__ 1
+#include <string.h>
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_link.h>
+#include <linux/if_addr.h>
+#include <linux/neighbour.h>
+#include <cutils/properties.h>
+#include <asm/types.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <linux/xfrm.h>
+
+
+//#define NLMSG_DELETEALL_BUF_SIZE (4096-512)
+#define NLMSG_DELETEALL_BUF_SIZE 8192
+
+/*
+ * Receiving buffer defines:
+ * nlmsg
+ * data = struct xfrm_userpolicy_info
+ * rtattr
+ * data = struct xfrm_user_tmpl[]
+ */
+#define NLMSG_BUF_SIZE 4096
+#define RTA_BUF_SIZE 2048
+#define XFRM_TMPLS_BUF_SIZE 1024
+#define CTX_BUF_SIZE 256
+#define XFRM_ALGO_KEY_BUF_SIZE 512
+
+#undef NLMSG_TAIL
+#define NLMSG_TAIL(nmsg) \
+ ((struct rtattr *) (((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
+
+#define XFRM_POLICY_ERROR 255
+enum PROTOCOL_TYPE{
+ PROTOCOL_ICMP=1,
+ PROTOCOL_IPV4=4,
+ PROTOCOL_TCP=6,
+ PROTOCOL_UDP=17,
+ PROTOCOL_IPV6=41,
+ PROTOCOL_GRE=47,
+ PROTOCOL_ESP=50,
+ PROTOCOL_AH=51,
+ PROTOCOL_ICMPV6=58,
+ PROTOCOL_IPCOMP=108,
+ PROTOCOL_L2TP=115
+};
+
+struct rtnl_handle_xfrm
+{
+ int fd;
+ struct sockaddr_nl local;
+ struct sockaddr_nl peer;
+ __u32 seq;
+ __u32 dump;
+};
+
+struct req_handle_xfrm {
+ struct nlmsghdr n;
+ struct xfrm_userpolicy_info xpinfo;
+ char buf[RTA_BUF_SIZE];
+ } ;
+
+typedef struct
+{
+ __u8 family;
+ __u8 bytelen;
+ __s16 bitlen;
+ __u32 flags;
+ __u32 data[8];
+} inet_prefix;
+
+#define PREFIXLEN_SPECIFIED 1
+
+static inline __u32 nl_mgrp_xfrm(__u32 group)
+{
+ if (group > 31 ) {
+ //ALOGD("Use setsockopt for this group %d\n", group);
+ return -1;
+ }
+ return group ? (1 << (group - 1)) : 0;
+}
+
+
+extern int mask2bits(__u32 netmask_xfrm);
+extern int get_netmask(unsigned *val_xfrm, const char *arg_xfrm, int base_xfrm);
+extern int get_unsigned(unsigned *val_xfrm, const char *arg_xfrm, int base_xfrm);
+extern int get_u32(__u32 *val_xfrm, const char *arg_xfrm, int base_xfrm);
+extern int get_u8(__u8 *val_xfrm, const char *arg_xfrm, int base_xfrm);
+extern int get_addr_ipv4(__u8 *ap_xfrm, const char *cp_xfrm);
+extern int get_addr_1(inet_prefix *addr_xfrm, const char *name_xfrm, int family);
+extern int get_prefix(inet_prefix *dst_xfrm, char *arg_xfrm, int family);
+
+
+
+typedef int (*rtnl_filter_t_xfrm)(struct rtnl_handle_xfrm * rth,struct nlmsghdr *n);
+
+extern int xfrm_policy_process_delete_exist( struct rtnl_handle_xfrm * rth,struct nlmsghdr *n, pid_t volte_pid);
+extern int xfrm_state_process_delete_exist( struct rtnl_handle_xfrm * rth,struct nlmsghdr *n, pid_t volte_pid);
+
+extern void rtnl_close_xfrm(struct rtnl_handle_xfrm *rth);
+extern int rtnl_open_byproto_xfrm(struct rtnl_handle_xfrm *rth, unsigned subscriptions,
+ int protocol);
+extern int rtnl_listen_xfrm(struct rtnl_handle_xfrm *rtnl, rtnl_filter_t_xfrm handler);
+extern int rtnl_accept_msg_xfrm(struct rtnl_handle_xfrm * rth,struct nlmsghdr *n);
+#endif /* __UTILS_XFRM_H__ */