[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/connectivity/gps/mtk_mnld/Android.mk b/src/connectivity/gps/mtk_mnld/Android.mk
new file mode 100644
index 0000000..8aea104
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/Android.mk
@@ -0,0 +1,170 @@
+# 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
+
+ifeq ($(MTK_GPS_SUPPORT), true)
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+MY_LOCAL_PATH := $(LOCAL_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_geofence_interface/inc \
+  $(LOCAL_PATH)/mnld_entity/inc \
+  $(LOCAL_PATH)/mnl/inc \
+  $(LOCAL_PATH)/curl/inc \
+  $(TOP)/external/libxml2/include \
+  $(TOP)/system/core/libcutils/include_vndk \
+  $(TOP)/system/core/include \
+  $(TOP)/hardware/libhardware/include \
+  $(TOP)/system/core/libcutils/include \
+  $(LOCAL_PATH)/mnl_mpe_interface/inc \
+
+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_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 \
+	utility/src/mtk_auto_log.c \
+	mnld_entity/src/mpe.c \
+	mnl_mpe_interface/src/mpe_main.c \
+	mnl_mpe_interface/src/mpe_logger.c \
+
+ifeq ($(MTK_GPS_CHIP), MT3303)
+LOCAL_C_INCLUDES += \
+    $(LOCAL_PATH)/mnld_entity/src/flashdownload \
+
+LOCAL_SRC_FILES += \
+	mnld_entity/src/mt3333_controller.c \
+	mnld_entity/src/flashdownload/flashtool.c \
+	mnld_entity/src/flashdownload/brom_base.c \
+	mnld_entity/src/flashdownload/brom_mt3301.c \
+	mnld_entity/src/flashdownload/da_cmd.c \
+	mnld_entity/src/flashdownload/gps_uart.c \
+
+LOCAL_CFLAGS += -DCONFIG_GPS_MT3303
+LOCAL_CFLAGS += -DCONFIG_GPS_MT3303_WITHOUT_POWER_CONTROL
+endif
+
+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
+ifeq ($(MTK_ADR_SUPPORT), true)
+LOCAL_CFLAGS += -DMTK_ADR_SUPPORT
+endif
+LOCAL_CFLAGS += -D__ANDROID_OS__
+
+ifeq ($(PLATFORM_VERSION), 10)
+LOCAL_CFLAGS += -DMTK_GPS_DATA_PATH="\"/data/vendor/gps/\""
+LOCAL_CFLAGS += -DMTK_GPS_FW_PATH="\"/vendor/firmware/\""
+LOCAL_CFLAGS += -D__ANDROID_OS_P__
+LOCAL_CFLAGS += -D__ANDROID_OS_10__
+else ifeq ($(PLATFORM_VERSION), 9)
+LOCAL_CFLAGS += -DMTK_GPS_DATA_PATH="\"/data/vendor/gps/\""
+LOCAL_CFLAGS += -D__ANDROID_OS_P__
+else
+LOCAL_CFLAGS += -DMTK_GPS_DATA_PATH="\"/data/misc/gps/\""
+LOCAL_CFLAGS += -D__ANDROID_OS_O__
+endif
+
+LOCAL_STATIC_LIBRARIES +=  libsupl
+LOCAL_SHARED_LIBRARIES +=  libmnl libgeofence libcurl libcutils libc libm libcrypto libssl libz liblog libhardware libutils libhardware
+LOCAL_HEADER_LIBRARIES +=  libcutils_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
+
+include $(BUILD_EXECUTABLE)
+include $(MY_LOCAL_PATH)/mnl/libs/android/Android.mk
+include $(MY_LOCAL_PATH)/curl/libs/Android.mk
+
+endif
+###############################################################################
diff --git a/src/connectivity/gps/mtk_mnld/LICENSE b/src/connectivity/gps/mtk_mnld/LICENSE
new file mode 100644
index 0000000..77f59ed
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/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/mtk_mnld/Makefile.am b/src/connectivity/gps/mtk_mnld/Makefile.am
new file mode 100644
index 0000000..4569718
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/Makefile.am
@@ -0,0 +1,73 @@
+AUTOMAKE_OPTIONS=foreign subdir-objects
+bin_PROGRAMS = mnld0
+
+mnld0_SOURCES = \
+        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_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 \
+        utility/src/mtk_auto_log.c \
+        mnld_entity/src/mpe.c \
+        mnl_mpe_interface/src/mpe_main.c \
+        mnl_mpe_interface/src/mpe_logger.c \
+        mnld_entity/src/mt3333_controller.c \
+        mnld_entity/src/flashdownload/flashtool.c \
+	 mnld_entity/src/flashdownload/brom_base.c \
+	 mnld_entity/src/flashdownload/brom_mt3301.c \
+	 mnld_entity/src/flashdownload/da_cmd.c \
+ 	 mnld_entity/src/flashdownload/gps_uart.c
+
+AM_CFLAGS = \
+        -Iutility/inc \
+        -Imnl_agps_interface/inc \
+        -Imnl_at_cmd_interface/inc \
+        -Imnl_flp_interface/inc \
+        -Imnl_mpe_interface/inc \
+        -Imnl_nlp_interface/inc \
+        -Imnl_meta_interface/inc \
+        -Imnl_debug_interface/inc \
+        -Imnl_geofence_interface/inc \
+        -Imnld_entity/inc \
+        -Imnld_entity/hardware \
+        -Imnld_entity/src/flashdownload \
+        -Imnl/inc \
+        -Icurl/inc \
+        -Imnl_mpe_interface/inc \
+        -D__LINUX_OS__ \
+        -DMTK_GPS_DATA_PATH="\"/usr/share/gps/\""
+
+AM_CFLAGS+=$(DNS_FLAGS)
+
+mnld0_LDADD = mnl/libs/linux/${PACKAGE_ARCH}/libmnl_gnss.so \
+        mnl/libs/linux/${PACKAGE_ARCH}/libhotstill.a \
+        mnl/libs/linux/${PACKAGE_ARCH}/libsupl.a \
+        -lm -lrt -lpthread -lz -lssl -lcrypto -lcurl
+
+include_HEADERS = mnl/inc/mtk_gps_type.h
diff --git a/src/connectivity/gps/mtk_mnld/NOTICE b/src/connectivity/gps/mtk_mnld/NOTICE
new file mode 100644
index 0000000..7868067
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/NOTICE
@@ -0,0 +1,23 @@
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>.

+

+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/mtk_mnld/README b/src/connectivity/gps/mtk_mnld/README
new file mode 100644
index 0000000..7394158
--- /dev/null
+++ b/src/connectivity/gps/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/mtk_mnld/configure.ac b/src/connectivity/gps/mtk_mnld/configure.ac
new file mode 100644
index 0000000..627af4c
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/configure.ac
@@ -0,0 +1,9 @@
+AC_INIT([mnld0], [1.0])
+AM_INIT_AUTOMAKE([foreign])
+AC_CONFIG_HEADER(defines.h)
+AC_PROG_CC
+AC_DISABLE_STATIC
+LT_INIT
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
+AC_PROG_CXX
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/curl/inc/curl.h b/src/connectivity/gps/mtk_mnld/curl/inc/curl.h
new file mode 100644
index 0000000..b57b3c4
--- /dev/null
+++ b/src/connectivity/gps/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/mtk_mnld/curl/inc/curlbuild.h b/src/connectivity/gps/mtk_mnld/curl/inc/curlbuild.h
new file mode 100644
index 0000000..f09419a
--- /dev/null
+++ b/src/connectivity/gps/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/mtk_mnld/curl/inc/curlrules.h b/src/connectivity/gps/mtk_mnld/curl/inc/curlrules.h
new file mode 100644
index 0000000..301ce6e
--- /dev/null
+++ b/src/connectivity/gps/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/mtk_mnld/curl/inc/curlver.h b/src/connectivity/gps/mtk_mnld/curl/inc/curlver.h
new file mode 100644
index 0000000..7976c1f
--- /dev/null
+++ b/src/connectivity/gps/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/mtk_mnld/curl/inc/easy.h b/src/connectivity/gps/mtk_mnld/curl/inc/easy.h
new file mode 100644
index 0000000..c1e3e76
--- /dev/null
+++ b/src/connectivity/gps/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/mtk_mnld/curl/inc/multi.h b/src/connectivity/gps/mtk_mnld/curl/inc/multi.h
new file mode 100644
index 0000000..42306a9
--- /dev/null
+++ b/src/connectivity/gps/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/mtk_mnld/curl/inc/typecheck-gcc.h b/src/connectivity/gps/mtk_mnld/curl/inc/typecheck-gcc.h
new file mode 100644
index 0000000..0e3d6c9
--- /dev/null
+++ b/src/connectivity/gps/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/mtk_mnld/curl/libs/Android.mk b/src/connectivity/gps/mtk_mnld/curl/libs/Android.mk
new file mode 100644
index 0000000..deea3fc
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/libs/Android.mk
@@ -0,0 +1,16 @@
+ifneq ($(TRUSTONIC_TEE_SUPPORT),true)
+
+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/mtk_mnld/curl/libs/NOTICE b/src/connectivity/gps/mtk_mnld/curl/libs/NOTICE
new file mode 100644
index 0000000..163b299
--- /dev/null
+++ b/src/connectivity/gps/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/mtk_mnld/curl/libs/README b/src/connectivity/gps/mtk_mnld/curl/libs/README
new file mode 100644
index 0000000..c713169
--- /dev/null
+++ b/src/connectivity/gps/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/mtk_mnld/curl/libs/libcurl_32.so b/src/connectivity/gps/mtk_mnld/curl/libs/libcurl_32.so
new file mode 100644
index 0000000..8a3449e
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/libs/libcurl_32.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/curl/libs/libcurl_64.so b/src/connectivity/gps/mtk_mnld/curl/libs/libcurl_64.so
new file mode 100644
index 0000000..5669ca5
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/libs/libcurl_64.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/etc/gps.conf b/src/connectivity/gps/mtk_mnld/etc/gps.conf
new file mode 100644
index 0000000..33c2fb9
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/etc/gps.conf
@@ -0,0 +1,4 @@
+EPO_ENABLE=1
+DW_DAYS=9
+EPO_WIFI_TRIGGER=0
+RAW_DEBUG_MODE=1
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/etc/mnl.prop b/src/connectivity/gps/mtk_mnld/etc/mnl.prop
new file mode 100644
index 0000000..3f6ab89
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/etc/mnl.prop
@@ -0,0 +1,4 @@
+#
+# ADDITIONAL_DEFAULT_PROPERTIES
+#
+debug.dbg2file=1
diff --git a/src/connectivity/gps/mtk_mnld/etc/mpe.conf b/src/connectivity/gps/mtk_mnld/etc/mpe.conf
new file mode 100644
index 0000000..6f15a86
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/etc/mpe.conf
@@ -0,0 +1,4 @@
+mpe_enable=1
+print_rawdata=0
+auto_calib=0
+indoor_enable=1
diff --git a/src/connectivity/gps/mtk_mnld/etc/updateEPOconfig.bat b/src/connectivity/gps/mtk_mnld/etc/updateEPOconfig.bat
new file mode 100644
index 0000000..31d4e76
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/etc/updateEPOconfig.bat
@@ -0,0 +1 @@
+adb push gps.conf /data/misc/gps/gps.conf
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/etc/update_mnl.bat b/src/connectivity/gps/mtk_mnld/etc/update_mnl.bat
new file mode 100644
index 0000000..3d99516
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/etc/update_mnl.bat
@@ -0,0 +1,6 @@
+adb wait-for-device

+adb remount

+

+adb push mnl.prop /data/misc/gps/

+

+PAUSE
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/flashdownload/bin/3333_da.bin b/src/connectivity/gps/mtk_mnld/flashdownload/bin/3333_da.bin
new file mode 100644
index 0000000..69046ef
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/flashdownload/bin/3333_da.bin
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/flashdownload/bin/3333_fw.bin b/src/connectivity/gps/mtk_mnld/flashdownload/bin/3333_fw.bin
new file mode 100644
index 0000000..2b8c31f
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/flashdownload/bin/3333_fw.bin
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/bin/Android.mk b/src/connectivity/gps/mtk_mnld/mnl/bin/Android.mk
new file mode 100644
index 0000000..be3069c
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/bin/Android.mk
@@ -0,0 +1,62 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+$(warning MTK_COMBO_CHIP=$(MTK_COMBO_CHIP))
+
+ifneq ($(filter CONSYS_6771,$(MTK_COMBO_CHIP)),)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := MNL_MT6771_E1.bin
+LOCAL_MODULE := MNL.bin
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/firmware
+$(warning LOCAL_SRC_FILES=$(LOCAL_SRC_FILES))
+include $(BUILD_PREBUILT)
+endif
+
+ifneq ($(filter CONSYS_6775,$(MTK_COMBO_CHIP)),)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := MNL_MT6775_E1.bin
+LOCAL_MODULE := MNL.bin
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/firmware
+$(warning LOCAL_SRC_FILES=$(LOCAL_SRC_FILES))
+include $(BUILD_PREBUILT)
+endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl/bin/MNL_MT6771_E1.bin b/src/connectivity/gps/mtk_mnld/mnl/bin/MNL_MT6771_E1.bin
new file mode 100644
index 0000000..9286c0d
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/bin/MNL_MT6771_E1.bin
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/bin/MNL_MT6775_E1.bin b/src/connectivity/gps/mtk_mnld/mnl/bin/MNL_MT6775_E1.bin
new file mode 100644
index 0000000..4736608
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/bin/MNL_MT6775_E1.bin
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_BEE.h b/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_BEE.h
new file mode 100644
index 0000000..a2763aa
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/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/mtk_mnld/mnl/inc/MTK_SDK_Bee.h b/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_SDK_Bee.h
new file mode 100644
index 0000000..51277e4
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/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/mtk_mnld/mnl/inc/MTK_Sys.h b/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_Sys.h
new file mode 100644
index 0000000..9d4bca0
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/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/mtk_mnld/mnl/inc/MTK_Type.h b/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_Type.h
new file mode 100644
index 0000000..b704863
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/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/mtk_mnld/mnl/inc/SUPL_encryption.h b/src/connectivity/gps/mtk_mnld/mnl/inc/SUPL_encryption.h
new file mode 100644
index 0000000..dc79a90
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/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/mtk_mnld/mnl/inc/agps_agent.h b/src/connectivity/gps/mtk_mnld/mnl/inc/agps_agent.h
new file mode 100644
index 0000000..c3f4edd
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/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/mtk_mnld/mnl/inc/mtk_gps.h b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps.h
new file mode 100644
index 0000000..244dce2
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps.h
@@ -0,0 +1,2280 @@
+/***********************************************************************
+*   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);
+
+/*****************************************************************************
+ * 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, &param_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, &param_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);
+
+//****************************************************************************
+// 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],INT32 ChnSNR[5]);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_cn0_test_CW
+ * DESCRIPTION
+ *  Get Channel CNR and Doppler 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_CW(INT32 PRN[5],INT32 SV_type[5],INT32 ChnSNR[5],INT32 Doppler[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[195], UINT16 JNR[195]);
+
+/*****************************************************************************
+ * 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 30 float.
+//  Example:
+//     float SNR[30];
+//     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[30]);
+
+
+/*****************************************************************************
+ * 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[40], Gnssmeasurement GloMeasurement[24],
+Gnssmeasurement BDMeasurement[37], Gnssmeasurement GalMeasurement[36],Gnssmeasurement SBASMeasurement[42],
+INT8 GpQz_Ch_Proc_Ord_PRN[40],INT8 Glo_Ch_Proc_Ord_PRN[24],INT8 BD_Ch_Proc_Ord_PRN[37],
+INT8 Gal_Ch_Proc_Ord_PRN[36],INT8 SBAS_Ch_Proc_Ord_PRN[42]);
+
+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(void);
+
+/*****************************************************************************
+ * 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
+
+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);
+
+//*************************************************************************************
+// 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);
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif /* MTK_GPS_H */
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_agps.h b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_agps.h
new file mode 100644
index 0000000..a4cd3a8
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_agps.h
@@ -0,0 +1,1146 @@
+/***********************************************************************
+*   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
+
+
+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[24];
+} 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[8];
+} 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
+
+#define AGPS_RRLP_MAX_PRM 14
+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;
+
+} 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 24
+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[12];
+} MTK_GLO_ASSIST_EPH_T;
+
+typedef struct
+{
+  UINT8 u1SvId;  // BD SV PRN number 1~30
+  UINT32 au4Word[15];
+} MTK_BDS_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  rAGalEph;     /* for Gallileo */
+    } data;
+} MTK_GNSS_ASSIST_EPH_T;
+
+//aGLONASS ALM
+typedef struct
+{
+  UINT8 u1SvId;//GLONASS SV PRN:1~24
+  UINT16 u2DayNum;
+  UINT32 au4Word[6];
+} MTK_GLO_ASSIST_ALM_T;
+
+//ABD ALM
+typedef struct
+{
+  UINT8 u1SvId;
+  UINT16 u2DayNum;
+  UINT32 au4Word[8];
+} MTK_BDS_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_QZS_ASSIST_ALM_T  rAQzsEph;     /* for GLONASS */
+      // MTK_GAL_ASSIST_ALM_T  rAGalEph;     /* for Gallileo */
+    } 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   i1Dopp1;        /* [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;
+
+
+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 */       
+    } 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;
+} 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
+} 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/mtk_mnld/mnl/inc/mtk_gps_bee.h b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_bee.h
new file mode 100644
index 0000000..06f8933
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/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/mtk_mnld/mnl/inc/mtk_gps_driver_wrapper.h b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_driver_wrapper.h
new file mode 100644
index 0000000..2ab4442
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/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/mtk_mnld/mnl/inc/mtk_gps_sys_fp.h b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_sys_fp.h
new file mode 100644
index 0000000..dc64f28
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_sys_fp.h
@@ -0,0 +1,90 @@
+/***********************************************************************
+*   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 *);
+
+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);
+} 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/mtk_mnld/mnl/inc/mtk_gps_sys_fp_macro.h b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_sys_fp_macro.h
new file mode 100644
index 0000000..46fb9ec
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_sys_fp_macro.h
@@ -0,0 +1,55 @@
+/***********************************************************************
+*   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
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif /* MTK_GPS_SYS_FP_MACRO_H */
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_type.h b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_type.h
new file mode 100644
index 0000000..68f6201
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_type.h
@@ -0,0 +1,3601 @@
+/***********************************************************************
+*   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      48
+#define MTK_GPS_SV_MAX_PRN      32
+#define MTK_QZS_SV_MAX_PRN      5   // QZSS PRN : 193~197
+#define MTK_GLEO_SV_MAX_NUM     53  // 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     37  // Beidou SV number, should be >= MBEDOID
+#define MTK_GPS_ENABLE_DEBUG_MSG (0x01)
+#define MTK_GPS_NMEA_SOCKET_DISABLE (0xFFFFF)
+#define MTK_GPS_LIB_VER_LEN_MAX      64
+
+/**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 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 64
+#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_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_UNCORRECTED_PSEUDORANGE_RATE      (1<<18)
+
+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_CYCLE_SLIP                (1<<2)
+#define MTK_GNSS_ADR_STATE_HALF_CYCLE_RES            (1<<3)  // half cycle resolved 
+
+
+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)
+
+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
+
+// 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_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_END_LIST
+} MTK_GPS_AGPS_CB_MSG_TYPE;
+
+typedef struct
+{
+  UINT32 ntp[2];           //ntp: mini-second, indicate the time tick(mini-second) from Jan.1.1970
+  UINT32 timeReference[2]; //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;
+
+
+// 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;
+} 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_GPS_PARAM;
+
+/*------- 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_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;
+} MTK_GNSS_PARAM_AUTODSN_MODE;
+
+typedef struct{
+UINT16 sv_id;
+float snr;
+INT8 ele;
+UINT16 azm;
+}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_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;
+  void*     reservedy;
+  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     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;
+
+
+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         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[30]; // epo working file
+  UINT8        epo_update_file_name[30]; // epo updated file
+  UINT8        qepo_file_name[30]; // qepo working file
+  UINT8        qepo_update_file_name[30]; // qepo updated file
+  UINT8        qepo_bd_file_name[30]; // qepo working file
+  UINT8        qepo_bd_update_file_name[30]; // 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;
+  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[30]; // mtknav working file
+  UINT8        mtknav_update_file_name[30]; // mtknav updated file
+  UINT8        qepo_ga_file_name[30]; // Galileo qepo working file
+  UINT8        qepo_ga_update_file_name[30]; //Galileo qepo updated file
+  /* new member should be added bellow here */
+  UINT8        raw_meas_enable;
+} MTK_GPS_DRIVER_CFG;
+
+/** 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;
+} Gnssmeasurement;
+
+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;
+} 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;
+
+
+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   LS_velocitySigma[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 */
+    unsigned int   gps_sec; /* Timestamp of GPS location */
+    unsigned int   leap_sec; /* correct GPS time with phone kernel time */
+} MNL_location_output_t;
+
+typedef struct
+{
+    double  latitude; /* latitude in radius */
+    double  longitude; /* longitude in radius */
+    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   acceleration[3]; /* SENSOR acceleration 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   bearing; /* SENSOR heading in degrees UNDER (N,E,D) frame*/
+    float   confidenceIndex[3]; /*  SENSOR confidence index */
+    float   barometerHeight;         /*barometer height in meter*/
+    int     valid_flag[4]; /*  SENSOR AGMB hardware valid flag */
+    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_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_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_NUM              = 8
+} 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
+} 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
+}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)
+
+/* 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 */
+
+/* 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) */
+
+
+
+/* NNUM ********************************************************************/
+typedef enum
+{
+    PMTK_CMD_VER_0 = 0,   //conversional GPS
+    PMTK_CMD_VER_1 = 1,   //GNSS
+    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_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_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 doesn¡¦t 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
+};
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif /* MTK_GPS_TYPE_H */
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/Android.mk b/src/connectivity/gps/mtk_mnld/mnl/libs/android/Android.mk
new file mode 100644
index 0000000..315db6a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/Android.mk
@@ -0,0 +1,54 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libhotstill
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_SRC_FILES_arm := libhotstill.a
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MULTILIB := 32
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libsupl
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_SRC_FILES_arm := libsupl.a
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MULTILIB := 32
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libmnl
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_SRC_FILES_arm := libmnl.so
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MULTILIB := 32
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libgeofence
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_SRC_FILES_arm := libgeofence.so
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MULTILIB := 32
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libDR
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_SRC_FILES_arm := libDR.so
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MULTILIB := 32
+include $(BUILD_PREBUILT)
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/NOTICE b/src/connectivity/gps/mtk_mnld/mnl/libs/android/NOTICE
new file mode 100644
index 0000000..7868067
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/NOTICE
@@ -0,0 +1,23 @@
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>.

+

+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/mtk_mnld/mnl/libs/android/README b/src/connectivity/gps/mtk_mnld/mnl/libs/android/README
new file mode 100644
index 0000000..e18aacc
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/README
@@ -0,0 +1,15 @@
+WHAT IT DOES?
+=============
+libhotstill.a,libsupl.a and libmnl.so is the implementation that mediatek navigating technology to work well as three libraries.
+
+HOW IT WAS BUILT?
+==================
+As library files, these are built by arm gcc tool chain.
+
+HOW TO USE IT?
+==============
+The three libraries is linked to vendor/bin/mnld daemon,their API will be called when GPS running.
+
+Source
+==============
+All the source code of these libraries were written by MediaTek co..
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/libDR.so b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libDR.so
new file mode 100644
index 0000000..0016358
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libDR.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/libgeofence.so b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libgeofence.so
new file mode 100644
index 0000000..8142e82
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libgeofence.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/libhotstill.a b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libhotstill.a
new file mode 100644
index 0000000..3dc8e2e
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libhotstill.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/libmnl.so b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libmnl.so
new file mode 100644
index 0000000..9a6e294
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libmnl.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/libsupl.a b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libsupl.a
new file mode 100644
index 0000000..dd0f5a3
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libsupl.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/NOTICE b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/NOTICE
new file mode 100644
index 0000000..7868067
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/NOTICE
@@ -0,0 +1,23 @@
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>.

+

+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/mtk_mnld/mnl/libs/linux/aarch64/README b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/README
new file mode 100644
index 0000000..e18aacc
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/README
@@ -0,0 +1,15 @@
+WHAT IT DOES?
+=============
+libhotstill.a,libsupl.a and libmnl.so is the implementation that mediatek navigating technology to work well as three libraries.
+
+HOW IT WAS BUILT?
+==================
+As library files, these are built by arm gcc tool chain.
+
+HOW TO USE IT?
+==============
+The three libraries is linked to vendor/bin/mnld daemon,their API will be called when GPS running.
+
+Source
+==============
+All the source code of these libraries were written by MediaTek co..
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libhotstill.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libhotstill.a
new file mode 100644
index 0000000..5f3264a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libhotstill.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libmnl_gnss.so b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libmnl_gnss.so
new file mode 100644
index 0000000..8d0de94
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libmnl_gnss.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libsupl.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libsupl.a
new file mode 100644
index 0000000..0114fed
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libsupl.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/NOTICE b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/NOTICE
new file mode 100644
index 0000000..38fb1bb
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/NOTICE
@@ -0,0 +1,34 @@
+/* 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.
+ */
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/README b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/README
new file mode 100644
index 0000000..7936bfb
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/README
@@ -0,0 +1,15 @@
+WHAT IT DOES?
+=============
+libhotstill.a,libsupl.a and libmnl.so is the implementation that mediatek navigating technology to work well as three libraries.
+
+HOW IT WAS BUILT?
+==================
+As library files, these are built by arm gcc tool chain.
+
+HOW TO USE IT?
+==============
+The three libraries is linked to system/xbin/mnld daemon,their API will be called when GPS running.
+
+Source
+==============
+All the source code of these libraries were written by MediaTek co..
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libhotstill.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libhotstill.a
new file mode 100644
index 0000000..4cdc5ae
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libhotstill.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libmnl_gnss.so b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libmnl_gnss.so
new file mode 100644
index 0000000..2c3b5e1
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libmnl_gnss.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libsupl.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libsupl.a
new file mode 100644
index 0000000..6c333ec
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libsupl.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/NOTICE b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/NOTICE
new file mode 100644
index 0000000..7868067
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/NOTICE
@@ -0,0 +1,23 @@
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>.

+

+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/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/README b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/README
new file mode 100644
index 0000000..e18aacc
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/README
@@ -0,0 +1,15 @@
+WHAT IT DOES?
+=============
+libhotstill.a,libsupl.a and libmnl.so is the implementation that mediatek navigating technology to work well as three libraries.
+
+HOW IT WAS BUILT?
+==================
+As library files, these are built by arm gcc tool chain.
+
+HOW TO USE IT?
+==============
+The three libraries is linked to vendor/bin/mnld daemon,their API will be called when GPS running.
+
+Source
+==============
+All the source code of these libraries were written by MediaTek co..
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libhotstill.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libhotstill.a
new file mode 100644
index 0000000..a12db49
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libhotstill.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libmnl_gnss.so b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libmnl_gnss.so
new file mode 100644
index 0000000..2c3b5e1
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libmnl_gnss.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libsupl.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libsupl.a
new file mode 100644
index 0000000..5c1e86c
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libsupl.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/NOTICE b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/NOTICE
new file mode 100644
index 0000000..7868067
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/NOTICE
@@ -0,0 +1,23 @@
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>.

+

+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/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/README b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/README
new file mode 100644
index 0000000..e18aacc
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/README
@@ -0,0 +1,15 @@
+WHAT IT DOES?
+=============
+libhotstill.a,libsupl.a and libmnl.so is the implementation that mediatek navigating technology to work well as three libraries.
+
+HOW IT WAS BUILT?
+==================
+As library files, these are built by arm gcc tool chain.
+
+HOW TO USE IT?
+==============
+The three libraries is linked to vendor/bin/mnld daemon,their API will be called when GPS running.
+
+Source
+==============
+All the source code of these libraries were written by MediaTek co..
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libhotstill.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libhotstill.a
new file mode 100644
index 0000000..a12db49
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libhotstill.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libmnl_gnss.so b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libmnl_gnss.so
new file mode 100644
index 0000000..9c82cce
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libmnl_gnss.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libsupl.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libsupl.a
new file mode 100644
index 0000000..5c1e86c
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libsupl.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/NOTICE b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/NOTICE
new file mode 100644
index 0000000..7868067
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/NOTICE
@@ -0,0 +1,23 @@
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>.

+

+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/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/README b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/README
new file mode 100644
index 0000000..e18aacc
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/README
@@ -0,0 +1,15 @@
+WHAT IT DOES?
+=============
+libhotstill.a,libsupl.a and libmnl.so is the implementation that mediatek navigating technology to work well as three libraries.
+
+HOW IT WAS BUILT?
+==================
+As library files, these are built by arm gcc tool chain.
+
+HOW TO USE IT?
+==============
+The three libraries is linked to vendor/bin/mnld daemon,their API will be called when GPS running.
+
+Source
+==============
+All the source code of these libraries were written by MediaTek co..
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libhotstill.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libhotstill.a
new file mode 100644
index 0000000..a12db49
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libhotstill.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libmnl_gnss.so b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libmnl_gnss.so
new file mode 100644
index 0000000..9c82cce
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libmnl_gnss.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libsupl.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libsupl.a
new file mode 100644
index 0000000..5c1e86c
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libsupl.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/src/pseudo_mnl.c b/src/connectivity/gps/mtk_mnld/mnl/src/pseudo_mnl.c
new file mode 100644
index 0000000..a5fd43a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/src/pseudo_mnl.c
@@ -0,0 +1,301 @@
+#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 <private/android_filesystem_config.h>
+#endif
+
+#include "mtk_gps_sys_fp.h"
+#include "nmea_parser.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_gps_agps.h"
+#include "mnld_utile.h"
+#include "mtk_auto_log.h"
+#include "mpe.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
+#define LOG_TAG "pseudo"
+#endif
+
+#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
+//#define MTK_GPS_LOG_FULL_PRINT
+
+#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
+    /* 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("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) {
+        read(gps_nvram_fd.iFileDesc, &stGPSReadback , rec_size*rec_num);
+        NVM_CloseFileDesc(gps_nvram_fd);
+
+        if (strlen(stGPSReadback.dsp_dev) != 0) {
+            gps_nvram_valid = 1;
+            // strncpy(mnl_config.dev_dsp, stGPSReadback.dsp_dev, sizeof(mnl_config.dev_dsp));
+
+            LOGD("GPS NVRam :(%d * %d), dsp_dev(/dev/stpgps) : %s\n", rec_size, rec_num, stGPSReadback.dsp_dev);
+            LOGD("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) {
+    UNUSED(length);
+    MTK_GPS_BOOL ret = MTK_GPS_FALSE;
+
+    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;
+}
+
+#ifdef CONFIG_GPS_MT3303
+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
+        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", length);
+#ifdef MTK_ADR_SUPPORT
+    if (mnl2adr_send_nmea_data(buffer, length) == -1) {
+        mtk_mnl_nmea_parser_process(buffer, length);  //Send to nmea parser and HAL directly, if sent to adr fail
+    }else {
+        mtk_mnl_nmea_parser_process(buffer, length);
+    }
+#else
+    mtk_mnl_nmea_parser_process(buffer, length);
+#endif
+    return MTK_GPS_SUCCESS;
+}
+#else
+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
+#ifdef MTK_GPS_LOG_FULL_PRINT
+        LOGD("len:%d, %s", length, buffer);
+#else
+        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_log_is_hide() == 1) &&
+                (mtk_gps_sys_ofl_log_filter(buffer, length) == MTK_GPS_TRUE)) {
+            // 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 {
+            // No limitation, print directly
+            LOGD("len:%d, %s", length, buffer);
+        }
+#endif
+    }
+    return MTK_GPS_SUCCESS;
+}
+
+INT32 mtk_gps_sys_nmea_output_to_mnld(const char * buffer, UINT32 length) {
+    LOGD("received %d bytes", length);
+#ifdef MTK_ADR_SUPPORT
+    if (mnl2adr_send_nmea_data(buffer, length) == -1) {
+        mtk_mnl_nmea_parser_process(buffer, length);  //Send to nmea parser and HAL directly, if sent to adr fail
+    }else {
+        mtk_mnl_nmea_parser_process(buffer, length);
+    }
+#else
+    mtk_mnl_nmea_parser_process(buffer, length);
+#endif
+    return MTK_GPS_SUCCESS;
+}
+#endif
+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));
+    sprintf(sztmp, "PMTK%d,1,%d", PMTK_FS_REQ_MEAS, mode);
+    sprintf(outbuf, "$%s*%02X\r\n", sztmp, calc_nmea_checksum1(sztmp));
+
+    // SUPL_encrypt((unsigned char *)outbuf, (unsigned char *)szBuf_cipher, strlen(outbuf));
+    memcpy(szBuf_cipher, outbuf, strlen(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_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));
+    sprintf(sztmp, "PMTK%d,%d", PMTK_FS_SLEEPMODE, mode);
+    sprintf(outbuf, "$%s*%02X\r\n", sztmp, calc_nmea_checksum1(sztmp));
+
+    // SUPL_encrypt((unsigned char *)outbuf, (unsigned char *)szBuf_cipher, strlen(outbuf));
+    memcpy(szBuf_cipher, outbuf, strlen(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));
+    sprintf(sztmp, "PMTK%d,0,0", PMTK_FS_REQ_MEAS);
+    sprintf(outbuf, "$%s*%02X\r\n", sztmp, calc_nmea_checksum1(sztmp));
+
+    // SUPL_encrypt((unsigned char *)outbuf, (unsigned char *)szBuf_cipher, strlen(outbuf));
+    memcpy(szBuf_cipher, outbuf, strlen(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/mtk_mnld/mnl_agps_interface/inc/agps2mnl_interface.h b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/agps2mnl_interface.h
new file mode 100644
index 0000000..3fb31c9
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/agps2mnl_interface.h
@@ -0,0 +1,93 @@
+
+#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);
+    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);
+    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
+} mnl2agps_interface;
+
+int agps2mnl_agps_reboot();
+
+int agps2mnl_agps_open_gps_req(int show_gps_icon);
+int agps2mnl_agps_close_gps_req();
+int agps2mnl_agps_reset_gps_req(int flags);
+
+int agps2mnl_agps_session_done();
+
+int agps2mnl_ni_notify(int session_id, mnl_agps_notify_type type, const char* requestor_id, const char* client_name);
+int agps2mnl_ni_notify2(int session_id, 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);
+int agps2mnl_data_conn_release();
+// 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_location* location);
+int agps2mnl_cell_location(mnl_agps_agps_location* 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
+void mnl2agps_hdlr(int fd, mnl2agps_interface* agps_interface);
+
+
+int create_mnl2agps_fd();
+// debug purpose
+int create_mnl2agps_fd2(const char* agps2mnl_path);
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/mnl2agps_interface.h b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/mnl2agps_interface.h
new file mode 100644
index 0000000..ae5e3ab
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/mnl2agps_interface.h
@@ -0,0 +1,90 @@
+
+#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);
+    void (*agps_close_gps_req)();
+    void (*agps_reset_gps_req)(int flags);
+
+    void (*agps_session_done)();
+
+    void (*ni_notify)(int session_id, 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)();
+
+    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_location* location);
+    void (*ni_notify2)(int session_id, 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);
+    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
+} 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);
+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_pmtk(const char* pmtk);
+int mnl2agps_raw_dbg(int enabled);
+int mnl2agps_reaiding_req();
+int mnl2agps_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);
+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
+
+void agps2mnl_hdlr(int fd, agps2mnl_interface* mnl_interface);
+
+
+int create_agps2mnl_fd();
+int mnl2agps_set_position_mode(int pos_mode);
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/mnl_agps_interface.h b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/mnl_agps_interface.h
new file mode 100644
index 0000000..f300c4a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/mnl_agps_interface.h
@@ -0,0 +1,204 @@
+#ifndef __GPS_AGPS_INTERFACE_H__
+#define __GPS_AGPS_INTERFACE_H__
+
+#include <stdbool.h>
+#include "mtk_auto_log.h"
+
+#define AGPS_TO_MNL "/data/agps_supl/agps_to_mnl"
+#define MNL_TO_AGPS "/data/agps_supl/mnl_to_agps"
+
+#define MNL_AGPS_MAX_BUFF_SIZE (64 * 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
+
+#define MNLD_STRNCPY(dst,src,size) do{\
+                                       strncpy((char *)(dst), (src), (size - 1));\
+                                      (dst)[size - 1] = '\0';\
+                                     }while(0)
+
+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_GSM7 = 1,
+    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
+    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_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,             // refer to gnss_ha_assist_data_req_struct
+    MNL_AGPS_TYPE_LPPE_ASSIST_DATA_PROVIDE_ACK,     // refer to gnss_ha_assist_ack_struct
+    MNL_AGPS_TYPE_SET_POSITION_MODE,
+
+    // ---------------------------------------
+    // 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_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;
+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;
+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 {
+    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 {
+    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/mtk_mnld/mnl_agps_interface/src/agps2mnl_interface.c b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/agps2mnl_interface.c
new file mode 100644
index 0000000..0d3a949
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/agps2mnl_interface.c
@@ -0,0 +1,643 @@
+#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 "mtk_lbs_utility.h"
+#include "agps2mnl_interface.h"
+#include "data_coder.h"
+#include "mtk_auto_log.h"
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#include <cutils/properties.h>
+#endif
+
+#if defined(__ANDROID_OS__)
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "agps"
+#endif
+
+#endif
+
+#define HIDE_LOG_PROP "ro.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 agps_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 char g_agps2mnl_path[128] = AGPS_TO_MNL;
+
+// -1 means failure
+static int send2mnl(const char* buff, int len) {
+    int ret = 0;
+    int sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+    if (sockfd < 0) {
+        LOGE("socket failed reason=[%s]\n", strerror(errno));
+        return -1;
+    }
+
+    if (agps_safe_sendto(sockfd, g_agps2mnl_path, buff, len) < 0) {
+        LOGE("external_snd_cmd safe_sendto failed\n");
+        ret = -1;
+    }
+    close(sockfd);
+    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) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  agps_open_gps_req  show_gps_icon=%d\n", show_gps_icon);
+
+    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);
+
+    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_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_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 type=%d requestor_id=[%s] client_name=[%s]\n",
+                 session_id, 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);
+    put_string(buff, &offset, client_name);
+
+    return send2mnl(buff, offset);
+}
+
+int agps2mnl_ni_notify2(int session_id, 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 type=%d requestor_id=[%s] type=%d client_name=[%s] type=%d\n",
+        session_id, 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);
+    put_string(buff, &offset, client_name);
+    put_int(buff, &offset, requestor_id_encoding);
+    put_int(buff, &offset, client_name_encoding);
+
+    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) {
+    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);
+
+    return send2mnl(buff, offset);
+}
+
+int agps2mnl_data_conn_release() {
+    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);
+
+    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);
+
+    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_location* location) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+#if ANDROID_MNLD_PROP_SUPPORT
+    char result[PROPERTY_VALUE_MAX] = {0};
+
+    property_get(HIDE_LOG_PROP, result, NULL);
+    if (result[0] != '1') {
+        LOGD("write  agps_location  lat=%f lng=%f\n", location->latitude, location->longitude);
+    }
+#endif
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_LOC);
+    put_binary(buff, &offset, (const char*)location, sizeof(mnl_agps_agps_location));
+
+    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));
+        if (agps_interface->data_conn_open_ip_type) {
+           agps_interface->data_conn_open_ip_type(apn, ip_type);
+        } 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_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));
+            agps_interface->location_sync(lat, lng, acc, alt_valid, alt, source_valid, source_gnss, source_nlp, source_sensor);
+        } else {
+            LOGE("location_sync is NULL\n");
+        }
+        break;
+    }
+    default:
+        LOGE("mnl2agps unknown type=%d\n", type);
+        break;
+    }
+}
+
+int create_mnl2agps_fd() {
+    int fd = bind_udp_socket(MNL_TO_AGPS);
+    set_socket_blocking(fd, 0);
+    return fd;
+}
+
+int create_mnl2agps_fd2(const char* agps2mnl_path) {
+    int fd = bind_udp_socket(MNL_TO_AGPS);
+    set_socket_blocking(fd, 0);
+    MNLD_STRNCPY(g_agps2mnl_path, agps2mnl_path,sizeof(g_agps2mnl_path));
+    return fd;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/mnl2agps_interface.c b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/mnl2agps_interface.c
new file mode 100644
index 0000000..8556f85
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/mnl2agps_interface.c
@@ -0,0 +1,809 @@
+#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 "mnl2agps_interface.h"
+#include "data_coder.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "MNL2AGPS"
+#endif
+
+// -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;
+}
+
+// -1 means failure
+static int send2agps(const char* buff, int len) {
+    int ret = 0;
+    int sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+    if (sockfd < 0) {
+        LOGE("socket failed reason=[%s]\n", strerror(errno));
+        return -1;
+    }
+
+    if (safe_sendto(sockfd, MNL_TO_AGPS, buff, len) < 0) {
+        LOGE("external_snd_cmd safe_sendto failed, path:%s", MNL_TO_AGPS);
+        ret = -1;
+    }
+    close(sockfd);
+    return ret;
+}
+
+int mnl2agps_set_position_mode(int pos_mode) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+    LOGD("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_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);
+    put_int(buff, &offset, length);
+
+    return send2agps(buff, offset);
+}
+
+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 (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);
+    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);
+
+    return send2agps(buff, offset);
+}
+
+int mnl2agps_data_conn_open_ip_type(const char* apn, int ip_type) {
+    //LOGD("mnl2agps_data_conn_open  apn=%s ip_type=%d\n", apn, ip_type);
+
+    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);
+    put_int(buff, &offset, ip_type);
+
+    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_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);
+
+    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);
+
+    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);
+
+    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);
+
+    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(double lat, double lng, int acc, bool alt_valid, float alt, bool source_valid, bool source_gnss, bool source_nlp, bool source_sensor) {
+    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, lat);
+    put_double(buff, &offset, lng);
+    put_int(buff, &offset, acc);
+    put_byte(buff, &offset, alt_valid);
+    put_float(buff, &offset, alt);
+    put_byte(buff, &offset, source_valid);
+    put_byte(buff, &offset, source_gnss);
+    put_byte(buff, &offset, source_nlp);
+    put_byte(buff, &offset, source_sensor);
+
+    //LOGW("LPPe debug:mnl2agps_location_sync: lat:%.3f, lng:%.3f, acc:%d, alt_valid:%d, alt:%.2f, source_valid:%d, gnss:%d, nlp:%d, sensor:%d", \
+    //    lat, lng, acc, alt_valid, alt, source_valid, source_gnss, source_nlp, source_sensor);
+    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);
+}
+
+void agps2mnl_hdlr(int fd, agps2mnl_interface* mnl_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("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));
+        if (mnl_interface->agps_open_gps_req) {
+            mnl_interface->agps_open_gps_req(show_gps_icon);
+        } 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_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));
+        if (mnl_interface->ni_notify) {
+            mnl_interface->ni_notify(session_id, 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));
+        if (mnl_interface->ni_notify2) {
+            mnl_interface->ni_notify2(session_id, 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));
+        if (mnl_interface->data_conn_req2) {
+            mnl_interface->data_conn_req2(&addr, is_emergency);
+        } else {
+            LOGE("data_conn_req2 is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_DATA_CONN_RELEASE: {
+        if (mnl_interface->data_conn_release) {
+            mnl_interface->data_conn_release();
+        } 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_location agps_location;
+        get_binary(buff, &offset, (char*)&agps_location, sizeof(buff), sizeof(mnl_agps_agps_location));
+        if (mnl_interface->agps_location) {
+            mnl_interface->agps_location(&agps_location);
+        } else {
+            LOGE("agps_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;
+    }
+    default:
+        LOGE("agps2mnl unknown type=%d\n", type);
+        break;
+    }
+}
+
+int create_agps2mnl_fd() {
+    int fd = bind_udp_socket(AGPS_TO_MNL);
+    set_socket_blocking(fd, 0);
+    return fd;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/mnl_agps_interface.c b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/mnl_agps_interface.c
new file mode 100644
index 0000000..e5648e6
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/mnl_agps_interface.c
@@ -0,0 +1,91 @@
+
+#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_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_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/mtk_mnld/mnl_at_cmd_interface/inc/mnl_at_interface.h b/src/connectivity/gps/mtk_mnld/mnl_at_cmd_interface/inc/mnl_at_interface.h
new file mode 100644
index 0000000..e1c4c4e
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_at_cmd_interface/inc/mnl_at_interface.h
@@ -0,0 +1,43 @@
+#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(char* ack, int len);
+void at_command_send_test_result();
+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/mtk_mnld/mnl_at_cmd_interface/src/mnl_at_interface.c b/src/connectivity/gps/mtk_mnld/mnl_at_cmd_interface/src/mnl_at_interface.c
new file mode 100644
index 0000000..580abbd
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_at_cmd_interface/src/mnl_at_interface.c
@@ -0,0 +1,705 @@
+#include <time.h>

+#include <sys/socket.h>

+#include <sys/un.h>

+#include <arpa/inet.h>

+#include <netinet/in.h>

+#include <math.h>

+#include <stdlib.h>

+#include <errno.h>

+

+#include "mnl_at_interface.h"

+#include "nmea_parser.h"

+#include "mtk_lbs_utility.h"

+#include "mtk_auto_log.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "at2mnl"

+#endif

+

+/*AT command test state*/

+#define GPS_TEST_PRN 1

+int MNL_AT_TEST_FLAG = 0;

+int MNL_AT_SIGNAL_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,

+};

+

+int* Dev_CNr = NULL;

+int prn[32] = {0};

+int snr[32] = {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;

+

+#define  GPS_OP   "AT%GPS"

+#define  GNSS_OP  "AT%GNSS"

+#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_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);

+   }

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

+   Dev_CNr = (int*)malloc(sizeof(int)*hal_test_data.test_num);

+   memset(Dev_CNr, 0, test_num*sizeof(int));

+

+   if ((0 == hal_test_data.test_num) && (0 == test_mode)) {

+       LOGE("%s: test number is 0!!", __FUNCTION__);

+       return -1;

+   }

+   if (1 == test_mode) {

+       LOGD("Signal test mode");

+       MNL_AT_SIGNAL_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;

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

+

+    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];

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

+

+    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 {

+            // 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));

+    }

+}

+

+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 {

+        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(char* ack, int len) {

+    remotelen = sizeof(remote);

+    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

+        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];

+        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];

+        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");

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

+            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) {

+    unsigned long int res;

+    char* command = cmdline;

+    char** pos = (char**)malloc(sizeof(char)*strlen(command));

+

+    if (!memcmp(command, GNSS_OP, 7)) {

+           // AT%GNSS=n

+        res = strtoul(command+8, pos, 10);

+    } else {

+           // AT%GPS=n

+        res = strtoul(command+7, pos, 10);

+    }

+

+    if ((res != 0) && ((**pos) =='\0')) {

+        LOGD("** AT Command Parse: get test_num = %ld success!**", res);

+    } else {

+        LOGD("** AT Command Parse: the test num may incorrect**");

+        res = -1;

+    }

+

+    if (NULL != pos) {

+        LOGD("free pos!!");

+        free(pos);

+    }

+    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(&current_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;

+        }

+    }

+}

+/*****************************************

+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 {

+            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), 0, (struct sockaddr *)&remote, &remotelen);

+        if (ret < 0) {

+            if (errno == EINTR)

+                continue;

+            if (errno != EWOULDBLOCK)

+                LOGE("error while reading AT Command socket: %s: %p", strerror(errno), cmd);

+            break;

+        }

+        LOGD("received %d bytes: %d.%s", ret, ret, cmd);

+        cmd[ret] = 0x00;

+        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/mtk_mnld/mnl_debug_interface/inc/Debug2MnldInterface.h b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/inc/Debug2MnldInterface.h
new file mode 100644
index 0000000..e51b36c
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/inc/Debug2MnldInterface.h
@@ -0,0 +1,60 @@
+// 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 12
+
+/**
+ * The interface from Debug to Mnld
+ */
+typedef enum {
+    DEBUG2MNLD_INTERFACE_DEBUG_REQ_MNLD_MSG = 0,
+} 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);
+
+// Receiver
+typedef struct {
+    void (*Debug2MnldInterface_debugReqMnldMsg_handler) (Debug2MnldInterface_DebugReqStatusCategory status);
+} 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/mtk_mnld/mnl_debug_interface/inc/Mnld2DebugInterface.h b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/inc/Mnld2DebugInterface.h
new file mode 100644
index 0000000..21acd06
--- /dev/null
+++ b/src/connectivity/gps/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, 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/mtk_mnld/mnl_debug_interface/src/Debug2MnldInterface.c b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/src/Debug2MnldInterface.c
new file mode 100644
index 0000000..ea8d783
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/src/Debug2MnldInterface.c
@@ -0,0 +1,167 @@
+// 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;
+    LOGD("Debug2MnldInterface_DebugReqStatusCategory_array_dump() size=[%d]", size);
+    for(i = 0; i < size; i++) {
+        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:
+        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])) {
+            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)) {
+        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)) {
+        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) {
+        LOGE("Debug2MnldInterface_debugReqMnldMsg() mtk_socket_write() failed, fd=%p err=[%s]%d", 
+            client_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) {
+        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) {
+            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;
+    }
+    default: {
+        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));
+    if(_ret == -1) {
+        LOGE("Debug2MnldInterface_receiver_read_and_decode() mtk_socket_read() failed, fd=%d err=[%s]%d", 
+            server_fd, strerror(errno), errno);
+        return false;
+    }
+    return Debug2MnldInterface_receiver_decode(_buff, callbacks);
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_debug_interface/src/Mnld2DebugInterface.c b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/src/Mnld2DebugInterface.c
new file mode 100644
index 0000000..e721279
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/src/Mnld2DebugInterface.c
@@ -0,0 +1,276 @@
+// 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;
+    LOGD("Mnld2DebugInterface_MnldGpsStatusCategory_array_dump() size=[%d]", size);
+    for(i = 0; i < size; i++) {
+        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:
+        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])) {
+            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)) {
+        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) {
+        LOGE("Mnld2DebugInterface_mnldAckDebugReq() mtk_socket_write() failed, err=[%s]%d", 
+            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) {
+    LOGE("Mnld2DebugInterface_mnldUpdateReboot");
+    pthread_mutex_lock(&client_fd->mutex);
+    if(!mtk_socket_client_connect(client_fd)) {
+        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) {
+        LOGE("Mnld2DebugInterface_mnldUpdateReboot() mtk_socket_write() failed, err=[%s]%d", 
+            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)) {
+        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)) {
+        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) {
+        LOGE("Mnld2DebugInterface_mnldUpdateGpsStatus() mtk_socket_write() failed, err=[%s]%d", 
+            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, char* msg) {
+    pthread_mutex_lock(&client_fd->mutex);
+    if(!mtk_socket_client_connect(client_fd)) {
+        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) {
+        LOGE("Mnld2DebugInterface_mnldUpdateMessageInfo() strlen of msg=[%d] 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) {
+        LOGE("Mnld2DebugInterface_mnldUpdateMessageInfo() mtk_socket_write() failed, err=[%s]%d", 
+            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) {
+        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) {
+            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) {
+            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) {
+            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) {
+            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: {
+        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));
+    if(_ret == -1) {
+        LOGE("Mnld2DebugInterface_receiver_read_and_decode() mtk_socket_read() failed, fd=%d err=[%s]%d", 
+            server_fd, strerror(errno), errno);
+        return false;
+    }
+    return Mnld2DebugInterface_receiver_decode(_buff, callbacks);
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/fused_location.h b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/fused_location.h
new file mode 100644
index 0000000..a5e59ca
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/fused_location.h
@@ -0,0 +1,826 @@
+/*
+ * Copyright (C) 2013 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_FUSED_LOCATION_H
+#define ANDROID_INCLUDE_HARDWARE_FUSED_LOCATION_H
+
+#if defined(__ANDROID_OS__)
+#include <hardware/hardware.h>
+#include "gnss-base.h"
+#endif
+
+/**
+ * This header file defines the interface of the Fused Location Provider.
+ * Fused Location Provider is designed to fuse data from various sources
+ * like GPS, Wifi, Cell, Sensors, Bluetooth etc to provide a fused location to the
+ * upper layers. The advantage of doing fusion in hardware is power savings.
+ * The goal is to do this without waking up the AP to get additional data.
+ * The software implementation of FLP will decide when to use
+ * the hardware fused location. Other location features like geofencing will
+ * also be implemented using fusion in hardware.
+ */
+__BEGIN_DECLS
+
+#define FLP_HEADER_VERSION          1
+#define FLP_MODULE_API_VERSION_0_1  HARDWARE_MODULE_API_VERSION(0, 1)
+#define FLP_DEVICE_API_VERSION_0_1  HARDWARE_DEVICE_API_VERSION_2(0, 1, FLP_HEADER_VERSION)
+
+/**
+ * The id of this module
+ */
+#define FUSED_LOCATION_HARDWARE_MODULE_ID "flp"
+
+/**
+ * Name for the FLP location interface
+ */
+#define FLP_LOCATION_INTERFACE     "flp_location"
+
+/**
+ * Name for the FLP location interface
+ */
+#define FLP_DIAGNOSTIC_INTERFACE     "flp_diagnostic"
+
+/**
+ * Name for the FLP_Geofencing interface.
+ */
+#define FLP_GEOFENCING_INTERFACE   "flp_geofencing"
+
+/**
+ * Name for the FLP_device context interface.
+ */
+#define FLP_DEVICE_CONTEXT_INTERFACE   "flp_device_context"
+
+/**
+ * Constants to indicate the various subsystems
+ * that will be used.
+ */
+#define FLP_TECH_MASK_GNSS      (1U<<0)
+#define FLP_TECH_MASK_WIFI      (1U<<1)
+#define FLP_TECH_MASK_SENSORS   (1U<<2)
+#define FLP_TECH_MASK_CELL      (1U<<3)
+#define FLP_TECH_MASK_BLUETOOTH (1U<<4)
+
+/**
+ * Set when your implementation can produce GNNS-derived locations,
+ * for use with flp_capabilities_callback.
+ *
+ * GNNS is a required capability for a particular feature to be used
+ * (batching or geofencing).  If not supported that particular feature
+ * won't be used by the upper layer.
+ */
+#define CAPABILITY_GNSS         (1U<<0)
+/**
+ * Set when your implementation can produce WiFi-derived locations, for
+ * use with flp_capabilities_callback.
+ */
+#define CAPABILITY_WIFI         (1U<<1)
+/**
+ * Set when your implementation can produce cell-derived locations, for
+ * use with flp_capabilities_callback.
+ */
+#define CAPABILITY_CELL         (1U<<3)
+
+/**
+ * Status to return in flp_status_callback when your implementation transitions
+ * from being unsuccessful in determining location to being successful.
+ */
+#define FLP_STATUS_LOCATION_AVAILABLE         0
+/**
+ * Status to return in flp_status_callback when your implementation transitions
+ * from being successful in determining location to being unsuccessful.
+ */
+#define FLP_STATUS_LOCATION_UNAVAILABLE       1
+
+/**
+ * While batching, the implementation should not call the
+ * flp_location_callback on every location fix. However,
+ * sometimes in high power mode, the system might need
+ * a location callback every single time the location
+ * fix has been obtained. This flag controls that option.
+ * Its the responsibility of the upper layers (caller) to switch
+ * it off, if it knows that the AP might go to sleep.
+ * When this bit is on amidst a batching session, batching should
+ * continue while location fixes are reported in real time.
+ */
+#define FLP_BATCH_CALLBACK_ON_LOCATION_FIX   0x0000002
+
+/** Flags to indicate which values are valid in a FlpLocation. */
+typedef uint16_t FlpLocationFlags;
+
+// IMPORTANT: Note that the following values must match
+// constants in the corresponding java file.
+
+/** FlpLocation has valid latitude and longitude. */
+#define FLP_LOCATION_HAS_LAT_LONG   (1U<<0)
+/** FlpLocation has valid altitude. */
+#define FLP_LOCATION_HAS_ALTITUDE   (1U<<1)
+/** FlpLocation has valid speed. */
+#define FLP_LOCATION_HAS_SPEED      (1U<<2)
+/** FlpLocation has valid bearing. */
+#define FLP_LOCATION_HAS_BEARING    (1U<<4)
+/** FlpLocation has valid accuracy. */
+#define FLP_LOCATION_HAS_ACCURACY   (1U<<8)
+
+
+typedef int64_t FlpUtcTime;
+
+/** Represents a location. */
+typedef struct {
+    /** set to sizeof(FlpLocation) */
+    size_t          size;
+
+    /** Flags associated with the location object. */
+    FlpLocationFlags 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. */
+    FlpUtcTime      timestamp;
+
+    /** Sources used, will be Bitwise OR of the FLP_TECH_MASK bits. */
+    uint32_t         sources_used;
+} FlpLocation;
+
+typedef enum {
+    ASSOCIATE_JVM,
+    DISASSOCIATE_JVM,
+} ThreadEvent;
+
+/**
+ *  Callback with location information.
+ *  Can only be called from a thread associated to JVM using set_thread_event_cb.
+ *  Parameters:
+ *     num_locations is the number of batched locations available.
+ *     location is the pointer to an array of pointers to location objects.
+ */
+typedef void (*flp_location_callback)(int32_t num_locations, FlpLocation** location);
+
+/**
+ * Callback utility for acquiring a wakelock.
+ * This can be used to prevent the CPU from suspending while handling FLP events.
+ */
+typedef void (*flp_acquire_wakelock)();
+
+/**
+ * Callback utility for releasing the FLP wakelock.
+ */
+typedef void (*flp_release_wakelock)();
+
+/**
+ * Callback for associating a thread that can call into the Java framework code.
+ * This must be used to initialize any threads that report events up to the framework.
+ * Return value:
+ *      FLP_RESULT_SUCCESS on success.
+ *      FLP_RESULT_ERROR if the association failed in the current thread.
+ */
+typedef int (*flp_set_thread_event)(ThreadEvent event);
+
+/**
+ * Callback for technologies supported by this implementation.
+ *
+ * Parameters: capabilities is a bitmask of FLP_CAPABILITY_* values describing
+ * which features your implementation supports.  You should support
+ * CAPABILITY_GNSS at a minimum for your implementation to be utilized.  You can
+ * return 0 in FlpGeofenceCallbacks to indicate you don't support geofencing,
+ * or 0 in FlpCallbacks to indicate you don't support location batching.
+ */
+typedef void (*flp_capabilities_callback)(int capabilities);
+
+/**
+ * Callback with status information on the ability to compute location.
+ * To avoid waking up the application processor you should only send
+ * changes in status (you shouldn't call this method twice in a row
+ * with the same status value).  As a guideline you should not call this
+ * more frequently then the requested batch period set with period_ns
+ * in FlpBatchOptions.  For example if period_ns is set to 5 minutes and
+ * the status changes many times in that interval, you should only report
+ * one status change every 5 minutes.
+ *
+ * Parameters:
+ *     status is one of FLP_STATUS_LOCATION_AVAILABLE
+ *     or FLP_STATUS_LOCATION_UNAVAILABLE.
+ */
+typedef void (*flp_status_callback)(int32_t status);
+
+/** FLP callback structure. */
+typedef struct {
+    /** set to sizeof(FlpCallbacks) */
+    size_t      size;
+    flp_location_callback location_cb;
+    flp_acquire_wakelock acquire_wakelock_cb;
+    flp_release_wakelock release_wakelock_cb;
+    flp_set_thread_event set_thread_event_cb;
+    flp_capabilities_callback flp_capabilities_cb;
+    flp_status_callback flp_status_cb;
+} FlpCallbacks;
+
+
+/** Options with the batching FLP APIs */
+typedef struct {
+    /**
+     * Maximum power in mW that the underlying implementation
+     * can use for this batching call.
+     * If max_power_allocation_mW is 0, only fixes that are generated
+     * at no additional cost of power shall be reported.
+     */
+    double max_power_allocation_mW;
+
+    /** Bitwise OR of the FLP_TECH_MASKS to use */
+    uint32_t sources_to_use;
+
+    /**
+     * FLP_BATCH_WAKEUP_ON_FIFO_FULL - If set the hardware
+     * will wake up the AP when the buffer is full. If not set, the
+     * hardware will drop the oldest location object.
+     *
+     * FLP_BATCH_CALLBACK_ON_LOCATION_FIX - If set the location
+     * callback will be called every time there is a location fix.
+     * Its the responsibility of the upper layers (caller) to switch
+     * it off, if it knows that the AP might go to sleep. When this
+     * bit is on amidst a batching session, batching should continue
+     * while location fixes are reported in real time.
+     *
+     * Other flags to be bitwised ORed in the future.
+     */
+    uint32_t flags;
+
+    /**
+     * Frequency with which location needs to be batched in nano
+     * seconds.
+     */
+    int64_t period_ns;
+
+    /**
+     * The smallest displacement between reported locations in meters.
+     *
+     * If set to 0, then you should report locations at the requested
+     * interval even if the device is stationary.  If positive, you
+     * can use this parameter as a hint to save power (e.g. throttling
+     * location period if the user hasn't traveled close to the displacement
+     * threshold).  Even small positive values can be interpreted to mean
+     * that you don't have to compute location when the device is stationary.
+     *
+     * There is no need to filter location delivery based on this parameter.
+     * Locations can be delivered even if they have a displacement smaller than
+     * requested. This parameter can safely be ignored at the cost of potential
+     * power savings.
+     */
+    float smallest_displacement_meters;
+} FlpBatchOptions;
+
+#define FLP_RESULT_SUCCESS                       0
+#define FLP_RESULT_ERROR                        -1
+#define FLP_RESULT_INSUFFICIENT_MEMORY          -2
+#define FLP_RESULT_TOO_MANY_GEOFENCES           -3
+#define FLP_RESULT_ID_EXISTS                    -4
+#define FLP_RESULT_ID_UNKNOWN                   -5
+#define FLP_RESULT_INVALID_GEOFENCE_TRANSITION  -6
+
+/**
+ * Represents the standard FLP interface.
+ */
+typedef struct {
+    /**
+     * set to sizeof(FlpLocationInterface)
+     */
+    size_t size;
+
+    /**
+     * Opens the interface and provides the callback routines
+     * to the implementation of this interface.  Once called you should respond
+     * by calling the flp_capabilities_callback in FlpCallbacks to
+     * specify the capabilities that your implementation supports.
+     */
+    int (*init)(FlpCallbacks* callbacks );
+
+    /**
+     * Return the batch size (in number of FlpLocation objects)
+     * available in the hardware.  Note, different HW implementations
+     * may have different sample sizes.  This shall return number
+     * of samples defined in the format of FlpLocation.
+     * This will be used by the upper layer, to decide on the batching
+     * interval and whether the AP should be woken up or not.
+     */
+    int (*get_batch_size)();
+
+    /**
+     * Start batching locations. This API is primarily used when the AP is
+     * asleep and the device can batch locations in the hardware.
+     *   flp_location_callback is used to return the locations. When the buffer
+     * is full and FLP_BATCH_WAKEUP_ON_FIFO_FULL is used, the AP is woken up.
+     * When the buffer is full and FLP_BATCH_WAKEUP_ON_FIFO_FULL is not set,
+     * the oldest location object is dropped. In this case the  AP will not be
+     * woken up. The upper layer will use get_batched_location
+     * API to explicitly ask for the location.
+     *   If FLP_BATCH_CALLBACK_ON_LOCATION_FIX is set, the implementation
+     * will call the flp_location_callback every single time there is a location
+     * fix. This overrides FLP_BATCH_WAKEUP_ON_FIFO_FULL flag setting.
+     * It's the responsibility of the upper layers (caller) to switch
+     * it off, if it knows that the AP might go to sleep. This is useful
+     * for nagivational applications when the system is in high power mode.
+     * Parameters:
+     *    id - Id for the request.
+     *    options - See FlpBatchOptions struct definition.
+     * Return value:
+     *    FLP_RESULT_SUCCESS on success, FLP_RESULT_INSUFFICIENT_MEMORY,
+     *    FLP_RESULT_ID_EXISTS, FLP_RESULT_ERROR on failure.
+     */
+    int (*start_batching)(int id, FlpBatchOptions* options);
+
+    /**
+     * Update FlpBatchOptions associated with a batching request.
+     * When a batching operation is in progress and a batching option
+     * such as FLP_BATCH_WAKEUP_ON_FIFO_FULL needs to be updated, this API
+     * will be used. For instance, this can happen when the AP is awake and
+     * the maps application is being used.
+     * Parameters:
+     *    id - Id of an existing batch request.
+     *    new_options - Updated FlpBatchOptions
+     * Return value:
+     *    FLP_RESULT_SUCCESS on success, FLP_RESULT_ID_UNKNOWN,
+     *    FLP_RESULT_ERROR on error.
+     */
+    int (*update_batching_options)(int id, FlpBatchOptions* new_options);
+
+    /**
+     * Stop batching.
+     * Parameters:
+     *    id - Id for the request.
+     * Return Value:
+     *    FLP_RESULT_SUCCESS on success, FLP_RESULT_ID_UNKNOWN or
+     *    FLP_RESULT_ERROR on failure.
+     */
+    int (*stop_batching)(int id);
+
+    /**
+     * Closes the interface. If any batch operations are in progress,
+     * they should be stopped.
+     */
+    void (*cleanup)();
+
+    /**
+     * Get the fused location that was batched.
+     *   flp_location_callback is used to return the location. The location object
+     * is dropped from the buffer only when the buffer is full. Do not remove it
+     * from the buffer just because it has been returned using the callback.
+     * In other words, when there is no new location object, two calls to
+     * get_batched_location(1) should return the same location object.
+     * Parameters:
+     *      last_n_locations - Number of locations to get. This can be one or many.
+     *      If the last_n_locations is 1, you get the latest location known to the
+     *      hardware.
+     */
+    void (*get_batched_location)(int last_n_locations);
+
+    /**
+     * Injects current location from another location provider
+     * latitude and longitude are measured in degrees
+     * expected accuracy is measured in meters
+     * Parameters:
+     *      location - The location object being injected.
+     * Return value: FLP_RESULT_SUCCESS or FLP_RESULT_ERROR.
+     */
+    int  (*inject_location)(FlpLocation* location);
+
+    /**
+     * Get a pointer to extension information.
+     */
+    const void* (*get_extension)(const char* name);
+
+    /**
+     * Retrieve all batched locations currently stored and clear the buffer.
+     * flp_location_callback MUST be called in response, even if there are
+     * no locations to flush (in which case num_locations should be 0).
+     * Subsequent calls to get_batched_location or flush_batched_locations
+     * should not return any of the locations returned in this call.
+     */
+    void (*flush_batched_locations)();
+} FlpLocationInterface;
+
+#if defined(__ANDROID_OS__)
+struct flp_device_t {
+    struct hw_device_t common;
+
+    /**
+     * Get a handle to the FLP Interface.
+     */
+    const FlpLocationInterface* (*get_flp_interface)(struct flp_device_t* dev);
+};
+#elif defined(__LINUX_OS__)
+struct flp_device_t {
+    /**
+     * Get a handle to the FLP Interface.
+     */
+    const FlpLocationInterface* (*get_flp_interface)(struct flp_device_t* dev);
+};
+#endif
+
+/**
+ * Callback for reports diagnostic data into the Java framework code.
+*/
+typedef void (*report_data)(char* data, int length);
+
+/**
+ * FLP diagnostic callback structure.
+ * Currently, not used - but this for future extension.
+ */
+typedef struct {
+    /** set to sizeof(FlpDiagnosticCallbacks) */
+    size_t      size;
+
+    flp_set_thread_event set_thread_event_cb;
+
+    /** reports diagnostic data into the Java framework code */
+    report_data data_cb;
+} FlpDiagnosticCallbacks;
+
+/** Extended interface for diagnostic support. */
+typedef struct {
+    /** set to sizeof(FlpDiagnosticInterface) */
+    size_t          size;
+
+    /**
+     * Opens the diagnostic interface and provides the callback routines
+     * to the implemenation of this interface.
+     */
+    void  (*init)(FlpDiagnosticCallbacks* callbacks);
+
+    /**
+     * Injects diagnostic data into the FLP subsystem.
+     * Return 0 on success, -1 on error.
+     **/
+    int  (*inject_data)(char* data, int length );
+} FlpDiagnosticInterface;
+
+/**
+ * Context setting information.
+ * All these settings shall be injected to FLP HAL at FLP init time.
+ * Following that, only the changed setting need to be re-injected
+ * upon changes.
+ */
+
+#define FLP_DEVICE_CONTEXT_GPS_ENABLED                     (1U<<0)
+#define FLP_DEVICE_CONTEXT_AGPS_ENABLED                    (1U<<1)
+#define FLP_DEVICE_CONTEXT_NETWORK_POSITIONING_ENABLED     (1U<<2)
+#define FLP_DEVICE_CONTEXT_WIFI_CONNECTIVITY_ENABLED       (1U<<3)
+#define FLP_DEVICE_CONTEXT_WIFI_POSITIONING_ENABLED        (1U<<4)
+#define FLP_DEVICE_CONTEXT_HW_NETWORK_POSITIONING_ENABLED  (1U<<5)
+#define FLP_DEVICE_CONTEXT_AIRPLANE_MODE_ON                (1U<<6)
+#define FLP_DEVICE_CONTEXT_DATA_ENABLED                    (1U<<7)
+#define FLP_DEVICE_CONTEXT_ROAMING_ENABLED                 (1U<<8)
+#define FLP_DEVICE_CONTEXT_CURRENTLY_ROAMING               (1U<<9)
+#define FLP_DEVICE_CONTEXT_SENSOR_ENABLED                  (1U<<10)
+#define FLP_DEVICE_CONTEXT_BLUETOOTH_ENABLED               (1U<<11)
+#define FLP_DEVICE_CONTEXT_CHARGER_ON                      (1U<<12)
+
+/** Extended interface for device context support. */
+typedef struct {
+    /** set to sizeof(FlpDeviceContextInterface) */
+    size_t          size;
+
+    /**
+     * Injects debug data into the FLP subsystem.
+     * Return 0 on success, -1 on error.
+     **/
+    int  (*inject_device_context)(uint32_t enabledMask);
+} FlpDeviceContextInterface;
+
+
+/**
+ * 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 FLP 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
+ * FLP 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 FLP 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 FLP 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 FLP system is unavailable, flp_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.
+ *
+ */
+#define FLP_GEOFENCE_TRANSITION_ENTERED     (1L<<0)
+#define FLP_GEOFENCE_TRANSITION_EXITED      (1L<<1)
+#define FLP_GEOFENCE_TRANSITION_UNCERTAIN   (1L<<2)
+
+#define FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE (1L<<0)
+#define FLP_GEOFENCE_MONITOR_STATUS_AVAILABLE   (1L<<1)
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ *      geofence_id - The id associated with the add_geofence_area.
+ *      location    - The current location as determined by the FLP subsystem.
+ *      transition  - Can be one of FLP_GEOFENCE_TRANSITION_ENTERED, FLP_GEOFENCE_TRANSITION_EXITED,
+ *                    FLP_GEOFENCE_TRANSITION_UNCERTAIN.
+ *      timestamp   - Timestamp when the transition was detected; -1 if not available.
+ *      sources_used - Bitwise OR of FLP_TECH_MASK flags indicating which
+ *                     subsystems were used.
+ *
+ * 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
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*flp_geofence_transition_callback) (int32_t geofence_id,  FlpLocation* location,
+        int32_t transition, FlpUtcTime timestamp, uint32_t sources_used);
+
+/**
+ * The callback associated with the availablity of one the sources used for geofence
+ * monitoring by the FLP sub-system For example, 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 FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE parameter and the
+ * source set to FLP_TECH_MASK_GNSS.
+ *
+ * Parameters:
+ *  status - FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE or FLP_GEOFENCE_MONITOR_STATUS_AVAILABLE.
+ *  source - One of the FLP_TECH_MASKS
+ *  last_location - Last known location.
+ */
+typedef void (*flp_geofence_monitor_status_callback) (int32_t status, uint32_t source,
+                                                      FlpLocation* last_location);
+
+/**
+ * The callback associated with the add_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * result - FLP_RESULT_SUCCESS
+ *          FLP_RESULT_ERROR_TOO_MANY_GEOFENCES  - geofence limit has been reached.
+ *          FLP_RESULT_ID_EXISTS  - geofence with id already exists
+ *          FLP_RESULT_INVALID_GEOFENCE_TRANSITION - the monitorTransition contains an
+ *              invalid transition
+ *          FLP_RESULT_ERROR - for other errors.
+ */
+typedef void (*flp_geofence_add_callback) (int32_t geofence_id, int32_t result);
+
+/**
+ * The callback associated with the remove_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * result - FLP_RESULT_SUCCESS
+ *          FLP_RESULT_ID_UNKNOWN - for invalid id
+ *          FLP_RESULT_ERROR for others.
+ */
+typedef void (*flp_geofence_remove_callback) (int32_t geofence_id, int32_t result);
+
+
+/**
+ * The callback associated with the pause_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * result - FLP_RESULT_SUCCESS
+ *          FLP_RESULT__ID_UNKNOWN - for invalid id
+ *          FLP_RESULT_INVALID_TRANSITION -
+ *                    when monitor_transitions is invalid
+ *          FLP_RESULT_ERROR for others.
+ */
+typedef void (*flp_geofence_pause_callback) (int32_t geofence_id, int32_t result);
+
+/**
+ * The callback associated with the resume_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * result - FLP_RESULT_SUCCESS
+ *          FLP_RESULT_ID_UNKNOWN - for invalid id
+ *          FLP_RESULT_ERROR for others.
+ */
+typedef void (*flp_geofence_resume_callback) (int32_t geofence_id, int32_t result);
+
+typedef struct {
+    /** set to sizeof(FlpGeofenceCallbacks) */
+    size_t size;
+    flp_geofence_transition_callback geofence_transition_callback;
+    flp_geofence_monitor_status_callback geofence_status_callback;
+    flp_geofence_add_callback geofence_add_callback;
+    flp_geofence_remove_callback geofence_remove_callback;
+    flp_geofence_pause_callback geofence_pause_callback;
+    flp_geofence_resume_callback geofence_resume_callback;
+    flp_set_thread_event set_thread_event_cb;
+    flp_capabilities_callback flp_capabilities_cb;
+} FlpGeofenceCallbacks;
+
+
+/** Type of geofence */
+typedef enum {
+    TYPE_CIRCLE = 0,
+} GeofenceType;
+
+/** Circular geofence is represented by lat / long / radius */
+typedef struct {
+    double latitude;
+    double longitude;
+    double radius_m;
+} GeofenceCircle;
+
+/** Represents the type of geofence and data */
+typedef struct {
+    GeofenceType type;
+    union {
+        GeofenceCircle circle;
+    } geofence;
+} GeofenceData;
+
+/** Geofence Options */
+typedef struct {
+   /**
+    * 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 FLP_GEOFENCE_TRANSITION_ENTERED. In most cases, it
+    * will be FLP_GEOFENCE_TRANSITION_UNCERTAIN. */
+    int last_transition;
+
+   /**
+    * Transitions to monitor. Bitwise OR of
+    * FLP_GEOFENCE_TRANSITION_ENTERED, FLP_GEOFENCE_TRANSITION_EXITED and
+    * FLP_GEOFENCE_TRANSITION_UNCERTAIN.
+    */
+    int monitor_transitions;
+
+   /**
+    * 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 FLP_GEOFENCE_TRANSITION_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.
+    */
+    int notification_responsivenes_ms;
+
+   /**
+    * The time limit after which the UNCERTAIN transition
+    * should be triggered. This paramter is defined in milliseconds.
+    */
+    int unknown_timer_ms;
+
+    /**
+     * The sources to use for monitoring geofences. Its a BITWISE-OR
+     * of FLP_TECH_MASK flags.
+     */
+    uint32_t sources_to_use;
+} GeofenceOptions;
+
+/** Geofence struct */
+typedef struct {
+    int32_t geofence_id;
+    GeofenceData* data;
+    GeofenceOptions* options;
+} Geofence;
+
+/** Extended interface for FLP_Geofencing support */
+typedef struct {
+   /** set to sizeof(FlpGeofencingInterface) */
+   size_t          size;
+
+   /**
+    * Opens the geofence interface and provides the callback routines
+    * to the implemenation of this interface.  Once called you should respond
+    * by calling the flp_capabilities_callback in FlpGeofenceCallbacks to
+    * specify the capabilities that your implementation supports.
+    */
+   void  (*init)( FlpGeofenceCallbacks* callbacks );
+
+   /**
+    * Add a list of geofences.
+    * Parameters:
+    *     number_of_geofences - The number of geofences that needed to be added.
+    *     geofences - Pointer to array of pointers to Geofence structure.
+    */
+   void (*add_geofences) (int32_t number_of_geofences, Geofence** geofences);
+
+   /**
+    * 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
+    *       FLP_GEOFENCE_TRANSITION_ENTERED, FLP_GEOFENCE_TRANSITION_EXITED and
+    *       FLP_GEOFENCE_TRANSITION_UNCERTAIN.
+    *       This supersedes the value associated provided in the
+    *       add_geofence_area call.
+    */
+   void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+   /**
+    * Modify a particular geofence option.
+    * Parameters:
+    *    geofence_id - The id for the geofence.
+    *    options - Various options associated with the geofence. See
+    *        GeofenceOptions structure for details.
+    */
+   void (*modify_geofence_option) (int32_t geofence_id, GeofenceOptions* options);
+
+   /**
+    * Remove a list of geofences. After the function returns, no notifications
+    * should be sent.
+    * Parameter:
+    *     number_of_geofences - The number of geofences that needed to be added.
+    *     geofence_id - Pointer to array of geofence_ids to be removed.
+    */
+   void (*remove_geofences) (int32_t number_of_geofences, int32_t* geofence_id);
+} FlpGeofencingInterface;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_HARDWARE_FLP_H */
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/gnss-base.h b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/gnss-base.h
new file mode 100644
index 0000000..b7bd503
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/gnss-base.h
@@ -0,0 +1,22 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+// Source: android.hardware.gnss@1.0
+// Root: android.hardware:hardware/interfaces
+
+#ifndef GNSS_BASE_H
+#define GNSS_BASE_H
+
+enum {
+    GNSS_MAX_SVS_COUNT = 64,
+};
+
+enum {
+    GNSS_CONSTELLATION_UNKNOWN = 0,
+    GNSS_CONSTELLATION_GPS = 1,
+    GNSS_CONSTELLATION_SBAS = 2,
+    GNSS_CONSTELLATION_GLONASS = 3,
+    GNSS_CONSTELLATION_QZSS = 4,
+    GNSS_CONSTELLATION_BEIDOU = 5,
+    GNSS_CONSTELLATION_GALILEO = 6,
+};
+
+#endif  // HIDL_GENERATED_ANDROID_HARDWARE_GNSS_V1_0_EXPORTED_CONSTANTS_H_
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mnl_flp_test_interface.h b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mnl_flp_test_interface.h
new file mode 100644
index 0000000..1b5f284
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mnl_flp_test_interface.h
@@ -0,0 +1,39 @@
+#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>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define IOCTL_MNL_IMAGE_FILE_TO_MEM  1
+#define IOCTL_MNL_NVRAM_FILE_TO_MEM  2
+#define IOCTL_MNL_NVRAM_MEM_TO_FILE  3
+
+
+typedef struct {
+    void (*flp_test_gps_start)();
+    void (*flp_test_gps_stop)();
+    int (*flp_test_lpbk_start)();
+    int (*flp_test_lpbk_stop)();
+} flp_test2mnl_interface;
+
+//======================================================
+// GPS FLP test -> MNLD
+//======================================================
+#define MTK_FLP_TEST2MNL "mtk_flp_test2mnl"
+
+int flp_test2mnl_hdlr(int fd, flp_test2mnl_interface* hdlr);
+int create_flp_test2mnl_fd(void);
+void flp_mnl_emi_download(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_controller.h b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_controller.h
new file mode 100644
index 0000000..52d0610
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_controller.h
@@ -0,0 +1,30 @@
+#ifndef MTK_FLP_LOWPOWER_H
+#define MTK_FLP_LOWPOWER_H
+
+#include "mtk_flp_main.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define FLP_VERSION_HEAD 'F','L','P','_','V','E','R','_'
+#define FLP_MAJOR_VERSION '1','7','0','6','1','9','0','1'  // y,y,m,m,d,d,rev,rev
+#define FLP_BRANCH_INFO '_','0','.','5','8','_'
+#define FLP_MINER_VERSION 'N','1'
+#define FLP_VER_INFO FLP_VERSION_HEAD,FLP_MAJOR_VERSION,FLP_BRANCH_INFO,FLP_MINER_VERSION
+
+#define MTK_FLP_ZPG_NORMAL_SEC 90
+#define MTK_FLP_ZPG_MAX_TIMEOUT_SEC 600
+
+int64_t mtk_flp_get_timestamp(struct timeval *ptv);
+int mtk_flp_controller_report_loc(MTK_FLP_LOCATION_T outloc);
+int mtk_flp_controller_process(MTK_FLP_MSG_T *prmsg) ;
+int mtk_flp_controller_query_mode ();
+int mtk_flp_controller_reset_status(void);
+
+#ifdef __cplusplus
+   }  /* extern "C" */
+#endif
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_main.h b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_main.h
new file mode 100644
index 0000000..d87bdc8
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_main.h
@@ -0,0 +1,240 @@
+#ifndef __MNL_FLP_MAIN_H__
+#define __MNL_FLP_MAIN_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+
+#if defined(__ANDROID_OS__)
+#include <hardware/fused_location.h>
+#elif defined(__LINUX_OS__)
+#include "fused_location.h"
+#endif
+
+#include "mtk_gps_type.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FLP_MNL_BUFF_SIZE           (1 * 1024)
+#define FLP_MNL_INTERFACE_VERSION   1
+#define OFFLOAD_PAYLOAD_LEN (600)
+#define OFL_VER "OFL_VER_2016.11.01-01"
+
+//======================================================
+// FLP -> FLP HAL
+//======================================================
+#define FLP_TO_MNL "flp_to_mnl"
+#define MNL_TO_FLP "mnl_to_flp"
+
+#define FLP_MNL_PAYLOAD_LEN 128
+#define MNLD_FLP_CAPABILITY_AP_MODE      1
+#define MNLD_FLP_CAPABILITY_OFL_MODE     2
+#define MNLD_FLP_CAPABILITY_AP_OFL_MODE  3
+
+//FLP source type
+#define FLP_TECH_MASK_GNSS      (1U<<0)
+#define FLP_TECH_MASK_WIFI      (1U<<1)
+#define FLP_TECH_MASK_SENSORS   (1U<<2)
+#define FLP_TECH_MASK_CELL      (1U<<3)
+#define FLP_TECH_MASK_BLUETOOTH (1U<<4)
+#define FLP_TECH_MASK_PSEUDO    (1U<<5)
+
+#define HAL_FLP_BUFF_SIZE   (1 * 1024)
+#define MTK_FLP_SUCCESS     (0)
+#define MTK_FLP_ERROR       (-1)
+
+typedef struct {
+    UINT32 type;
+    UINT32 session;
+    UINT32 length;
+    UINT8  data[FLP_MNL_PAYLOAD_LEN];
+} MTK_FLP_MNL_MSG_T;
+
+typedef struct {
+    size_t  size;
+    unsigned short  flags;
+    double          latitude;
+    double          longitude;
+    double          altitude;
+    float           speed;
+    float           bearing;
+    float           accuracy;
+    int64_t         timestamp;
+    unsigned int    sources_used;
+} MTK_FLP_LOCATION_T;
+
+typedef struct {
+    double max_power_allocation_mW;
+    UINT32 sources_to_use;
+    INT32 flags;
+    INT64 period_ns;
+} MTK_FLP_BATCH_OPTION_T;
+
+typedef struct {
+    UINT32 type;
+    UINT32 length;
+    UINT8 data[OFFLOAD_PAYLOAD_LEN];
+} MTK_FLP_OFFLOAD_MSG_T;
+
+typedef struct {
+    UINT32 type;
+    UINT32 session;
+    UINT32 length;
+} MTK_FLP_MNL_MSG_HEADER_T;
+
+typedef struct {
+    int (*mnld_flp_attach)();
+    void (*mnld_flp_hbd_gps_open)();
+    void (*mnld_flp_hbd_gps_close)();
+    void (*mnld_flp_ofl_link_open)();
+    void (*mnld_flp_ofl_link_close)();
+    int (*mnld_flp_ofl_link_send)();
+} flp2mnl_interface;
+
+typedef struct {
+    int (*flp_start_batching)(int id, FlpBatchOptions* options);
+    int (*flp_update_batching_option)(int id, FlpBatchOptions* options);
+    int (*flp_stop_batching)(int id);
+    void (*flp_get_batched_location)(int last_n_locations);
+    int (*flp_inject_location)(MTK_FLP_LOCATION_T* location);
+    void (*flp_flush_batched_location)();
+} flphal2flp_interface;
+
+
+typedef struct {
+    UINT32 type;   // 1:AP mode(default)   2: Offload mode  3:AP+Offload mode
+    UINT32 pre_type;
+    UINT32 id;
+} MTK_FLP_Session_T;
+
+typedef struct {
+    int type;
+    int length;
+} MTK_FLP_MSG_T;
+
+
+extern MTK_FLP_Session_T mnld_flp_session;
+
+/*************************************************
+  Message Table from FLP thread to MNL
+*************************************************/
+typedef enum {
+    // MNL -> FLP
+    MNLD_FLP_TYPE_MNL_BOOTUP = 100,
+    MNLD_FLP_TYPE_FLP_ATTACH_DONE,
+    MNLD_FLP_TYPE_SESSION_UPDATE,
+
+    MNLD_FLP_TYPE_HBD_GPS_OPEN_DONE = 110,
+    MNLD_FLP_TYPE_HBD_GPS_CLOSE_DONE,
+    MNLD_FLP_TYPE_HBD_GPS_LOCATION,
+
+    MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE = 120,
+    MNLD_FLP_TYPE_OFL_LINK_CLOSE_DONE,
+
+    MNLD_FLP_TYPE_OFL_LINK_RECV = 130,
+
+    // FLP -> MNL
+    MNLD_FLP_TYPE_FLP_ATTACH = 200,
+
+    MNLD_FLP_TYPE_HBD_GPS_OPEN = 210,
+    MNLD_FLP_TYPE_HBD_GPS_CLOSE,
+
+    MNLD_FLP_TYPE_OFL_LINK_OPEN = 220,
+    MNLD_FLP_TYPE_OFL_LINK_CLOSE,
+
+    MNLD_FLP_TYPE_OFL_LINK_SEND = 230,
+} mnld_flp_type;
+
+/*************************************************
+  Message Table from FLP HAL to FLP thread
+*************************************************/
+typedef enum {
+    MTK_FLP_MSG_SYS_FLPD_RESET_NTF = 100,
+
+    //HAL messages
+    MTK_FLP_MSG_HAL_INIT_CMD = 200,
+    MTK_FLP_MSG_HAL_START_CMD,
+    MTK_FLP_MSG_HAL_STOP_CMD,
+    MTK_FLP_MSG_HAL_STOP_RSP,
+    MTK_FLP_MSG_HAL_SET_OPTION_CMD,
+    MTK_FLP_MSG_HAL_INJECT_LOC_CMD,
+    MTK_FLP_MSG_HAL_DIAG_INJECT_DATA_NTF,
+    MTK_FLP_MSG_HAL_DIAG_REPORT_DATA_NTF,
+
+    MTK_FLP_MSG_HSB_REPORT_LOC_NTF = 300,
+    MTK_FLP_MSG_OFL_REPORT_LOC_NTF,
+
+    MTK_FLP_MSG_HAL_GEOFENCE_CALLBACK_NTF = 400,
+    MTK_FLP_MSG_HAL_REQUEST_LOC_NTF,
+    MTK_FLP_MSG_HAL_FLUSH_LOC_NTF,
+    MTK_FLP_MSG_HAL_REPORT_STATUS_NTF,
+    MTK_FLP_MSG_OFL_GEOFENCE_CALLBACK_NTF,
+    MTK_FLP_MSG_OFL_GEOFENCE_CMD,
+
+    MTK_FLP_MSG_DC_START_CMD = 500,
+    MTK_FLP_MSG_DC_STOP_CMD,
+    MTK_FLP_MSG_CONN_SCREEN_STATUS,
+    MTK_FLP_MSG_END,
+}MTK_FLP_MSG_TYPE;
+
+typedef enum {
+    FLP_AP_MODE      = 1,
+    FLP_OFFLOAD_MODE = 2,
+} MTK_FLP_SYS_MODE_T;
+
+typedef enum {
+    MTK_FLP_IDLE_MODE = -1,
+    MTK_FLP_BATCH_SLEEP_ON_FIFO_FULL = 0,
+    MTK_FLP_BATCH_WAKE_ON_FIFO_FULL = 1,
+} MTK_FLP_BATCH_MODE_T;
+
+typedef enum {
+    EARLYSUSPEND_ON,
+    EARLYSUSPEND_MEM,
+} MTK_FLP_SCR_STATE;
+
+enum {
+    MNL_STATUS_NONE,
+    MNL_STATUS_ATTACH,
+    MNL_STATUS_ATTACH_DONE,
+    MNL_STATUS_HBD_GPS_OPEN,
+    MNL_STATUS_HBD_GPS_OPEN_DONE,
+    MNL_STATUS_HBD_GPS_CLOSE,
+    MNL_STATUS_HBD_GPS_CLOSE_DONE,
+    MNL_STATUS_OFL_LINK_OPEN,
+    MNL_STATUS_OFL_LINK_OPEN_DONE,
+    MNL_STATUS_OFL_LINK_CLOSE,
+    MNL_STATUS_OFL_LINK_CLOSE_DONE,
+};
+
+int mnl2flp_mnld_reboot();
+int mnl2flp_data_send(UINT8 *buf, UINT32 len);
+int mnld_flp_attach_done();
+int mnld_flp_hbd_gps_open_done();
+int mnld_flp_hbd_gps_close_done();
+int mnld_flp_ofl_gps_open_done();
+int mnld_flp_ofl_gps_close_done();
+int mnld_flp_session_update();
+int mnld_flp_gen_new_session();
+int mtk_hal2flp_main_hdlr(int fd, flp2mnl_interface* hdlr);
+int flp2mnl_hdlr(MTK_FLP_MNL_MSG_T  *prMsg);
+int mtk_flp2mnl_process(MTK_FLP_MSG_T *prmsg);
+int mnl2flp_hdlr(MTK_FLP_MNL_MSG_T* prmsg);
+int mtk_flp_get_sys_mode();
+void mtk_flp_set_sys_mode (unsigned int sysMode);
+int mnl_send2flp(const char* buff, int len);
+
+
+
+// -1 means failure
+int create_flphal2mnl_fd();
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_screen_monitor.h b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_screen_monitor.h
new file mode 100644
index 0000000..be96082
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_screen_monitor.h
@@ -0,0 +1,21 @@
+#ifndef __MNL_FLP_SCREEN_MONITOR_H__
+#define __MNL_FLP_SCREEN_MONITOR_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+#include "mtk_gps_type.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void flp_monitor_init();
+void mtk_flp_get_wake_monitor_state(UINT8 *state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mnl_flp_test_interface.c b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mnl_flp_test_interface.c
new file mode 100644
index 0000000..2941718
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mnl_flp_test_interface.c
@@ -0,0 +1,115 @@
+#include <errno.h>
+#include <unistd.h>  // for close
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sys/ioctl.h>
+
+#include "mnl_flp_test_interface.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_gps_type.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnl_flp_test"
+#endif
+
+/*****************************************
+FLP test -> MNL Testing
+*****************************************/
+int flp_test2mnl_hdlr(int fd, flp_test2mnl_interface* hdlr) {
+    int ret;
+    char buff[1024] = {0};
+    ret = safe_recvfrom(fd, buff, sizeof(buff));
+
+    LOGD("[OFL]data from ofl tst: %d\n", (int)buff[0]);
+    switch (buff[0]) {
+    case '1':
+        if (hdlr->flp_test_gps_start) {
+            hdlr->flp_test_gps_start();
+        } else {
+            LOGE("flp2mnl_hdlr() flp_test_gps_start is NULL");
+            ret = -1;
+        }
+        break;
+    case '2':
+        if (hdlr->flp_test_gps_stop) {
+            hdlr->flp_test_gps_stop();
+        } else {
+            LOGE("flp2mnl_hdlr() flp_test_gps_stop is NULL");
+            ret = -1;
+        }
+        break;
+
+    case '3':
+    {
+        // Loopback test start
+        if (hdlr->flp_test_lpbk_start) {
+            hdlr->flp_test_lpbk_start();
+        } else {
+            LOGE("flp2mnl_hdlr() flp_lpbk is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case '4':
+        // Loopback test stop
+        if (hdlr->flp_test_lpbk_stop) {
+            hdlr->flp_test_lpbk_stop();
+        } else {
+            LOGE("flp2mnl_hdlr() flp_lpbk is NULL");
+            ret = -1;
+        }
+        break;
+
+    default:
+        LOGD("[OFL] invalide opid :%d!", buff[0]);
+        break;
+    }
+
+    return MTK_GPS_SUCCESS;
+}
+
+void *thread_emi_download(void* arg) {
+    int emi_fd;
+    LOGD("create: %.8X, arg = %p\r\n", (unsigned int)pthread_self(), arg);
+    pthread_detach(pthread_self());
+
+    LOGD("EMI download thread start arg=%p\n", arg);
+    emi_fd = open("/dev/gps_emi", O_RDWR);
+    if (emi_fd == -1) {
+        LOGD("open_port: Unable to open /dev/gps_emi\n");
+        return 0;
+    } else {
+        LOGD("open gps_emi successfully\n");
+    }
+
+    if (ioctl(emi_fd, IOCTL_MNL_IMAGE_FILE_TO_MEM, NULL) <= 0) {
+        LOGD("set IOCTL_MNL_IMAGE_FILE_TO_MEM failed\n");
+        close(emi_fd);
+        return 0;
+    }
+    usleep(2000000);
+    LOGD("EMI download successful and thread exit done");
+    pthread_exit(NULL);
+    return 0;
+}
+void flp_mnl_emi_download(void) {
+    int ret = -1;
+    pthread_t emi_download_thread;
+
+    ret = pthread_create(&emi_download_thread, NULL, thread_emi_download, NULL);
+    if (0 != ret) {
+        LOGE("emi download thread create fail: %s\n", strerror(errno));
+        exit(1);
+    }
+}
+// -1 means failure
+int create_flp_test2mnl_fd() {
+    int fd = socket_bind_udp(MTK_FLP_TEST2MNL);
+    socket_set_blocking(fd, 0);
+    return fd;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_controller.c b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_controller.c
new file mode 100644
index 0000000..ca362bc
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_controller.c
@@ -0,0 +1,272 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <gps_dbg_log.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "mtk_flp_controller.h"
+#include "data_coder.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnl2flp"
+#endif
+
+#define ONE_SEC_NS 1000000000
+
+/**********************************************************
+ *  Global vars                                           *
+ **********************************************************/
+char pFLPVersion[] = {FLP_VER_INFO,0x00};
+static unsigned int flp_enabled = 0, flp_source_to_use = 0;
+static UINT32 flp_running_source = 0;
+static int flp_batch_mode = MTK_FLP_IDLE_MODE;
+static int g_loc_available = -1;
+static int64_t g_flp_period_ns = 0;
+static int64_t g_flp_update_last_time = 0;
+static float current_gnss_acc = 0;
+
+
+int64_t mtk_flp_get_timestamp(struct timeval *ptv) {
+    struct timeval tv;
+
+    if(ptv) {
+        return ((unsigned long long)ptv->tv_sec*1000ULL+(unsigned long long)ptv->tv_usec/1000ULL);
+    } else {
+        gettimeofday(&tv, NULL);
+        return ((unsigned long long)tv.tv_sec*1000ULL + (unsigned long long)tv.tv_usec/1000ULL);
+    }
+}
+
+unsigned int mtk_flp_sys_get_time_tick() {
+    struct timeval t;
+    gettimeofday(&t, NULL);
+    return t.tv_sec;
+}
+
+int mtk_flp_controller_query_mode () {
+    return flp_batch_mode;
+}
+
+void mtk_flp_controller_check_loc_available_expired() {
+    int current_available;
+    int ret, offset = 0;
+    char buff[HAL_FLP_BUFF_SIZE] = {0};
+    MTK_FLP_MSG_T *flp_header = NULL;
+
+    int64_t current_time = (int64_t)mtk_flp_sys_get_time_tick();
+
+    if (mtk_flp_controller_query_mode() == MTK_FLP_IDLE_MODE) {
+        return;
+    }
+
+    if ((current_time - g_flp_update_last_time) > (g_flp_period_ns/ONE_SEC_NS + 1)) {
+        current_available = 1;
+    } else {
+        current_available = 0;
+    }
+    if (g_loc_available != current_available) {
+        g_loc_available = current_available;
+
+        flp_header = malloc(sizeof(MTK_FLP_MSG_T)+ sizeof(int));
+        if(flp_header==NULL) {
+            LOGE("report status malloc failed");
+            return;
+        }
+        flp_header->type = MTK_FLP_MSG_HAL_REPORT_STATUS_NTF;
+        flp_header->length = sizeof(int);
+        memcpy((char *)flp_header+sizeof(MTK_FLP_MSG_T), &g_loc_available, sizeof(int));
+        put_binary(buff, &offset, (const char*)flp_header, (sizeof(MTK_FLP_MSG_T) + flp_header->length));
+        ret = mnl_send2flp(buff, offset);
+        free(flp_header);
+        if(ret < 0) {
+            LOGE("MTK_FLP2HAL send error return error");
+        }
+    }
+}
+
+int mtk_flp_controller_report_loc(MTK_FLP_LOCATION_T outloc) {
+    unsigned char update_flploc = 0;
+    int64_t current_time = 0;
+
+    // one second timer
+    if (flp_enabled) {
+        mtk_flp_controller_check_loc_available_expired();
+    } else {
+        LOGE("flp bypass, no source open");
+        return MTK_FLP_ERROR;
+    }
+
+    current_gnss_acc = outloc.accuracy;
+    if (outloc.accuracy < 0.001) {
+        LOGE("bypass loc - loc no fix");
+        return MTK_FLP_ERROR;
+    }
+
+    // Location fix
+    if (g_flp_update_last_time == 0) {
+        g_flp_update_last_time = (int64_t)(mtk_flp_sys_get_time_tick());
+        update_flploc = 1;
+    } else {
+        current_time = (int64_t)(mtk_flp_sys_get_time_tick());
+        if(g_flp_update_last_time > current_time) {
+            g_flp_update_last_time = 0;
+        }
+
+        if((current_time - g_flp_update_last_time) >= g_flp_period_ns/ONE_SEC_NS) {
+            update_flploc = 1;
+            g_flp_update_last_time = current_time;
+        }
+    }
+    if (!update_flploc) {
+        LOGE("bypass loc - on period");
+        return MTK_FLP_ERROR;
+    }
+#if 0
+    LOGD("Location,LNG:%f LAT:%f ALT:%f ACC:%f SPD:%f BEARING:%f, FLAGS:%04X SOURCES:%08X Timestamp:%lld",
+    outloc.longitude, outloc.latitude, outloc.altitude, outloc.accuracy,
+    outloc.speed, outloc.bearing, outloc.flags, outloc.sources_used, outloc.timestamp);
+#endif
+    return MTK_FLP_SUCCESS;
+}
+
+
+void mtk_flp_controller_update_option(FlpBatchOptions *option) {
+    UINT32 local_source = 0;
+    UINT32 new_source = 0;
+    MTK_FLP_MSG_T *flp_cmd;
+    MTK_FLP_BATCH_OPTION_T batch_option;
+
+    //assign stop command;
+    memset(&batch_option,0,sizeof(MTK_FLP_BATCH_OPTION_T));
+    if(option != NULL) {
+        local_source = flp_running_source;
+        new_source = flp_source_to_use;
+        LOGD("local:%d,new:%d",local_source,new_source);
+        if(local_source != new_source) {
+            if((local_source == 0) && (new_source >= 1)) { //new req is open dc_xxx
+                current_gnss_acc = 0;
+                g_flp_update_last_time = 0;
+                flp_cmd = malloc(sizeof(MTK_FLP_BATCH_OPTION_T)+ sizeof(MTK_FLP_MSG_T));
+                if(flp_cmd == NULL) {
+                    LOGE("update opt failed");
+                    return;
+                }
+                flp_cmd->type = MTK_FLP_MSG_DC_START_CMD;
+                flp_cmd->length = sizeof(MTK_FLP_BATCH_OPTION_T);
+                batch_option.flags = flp_batch_mode;
+                batch_option.max_power_allocation_mW = option->max_power_allocation_mW;
+                batch_option.period_ns = g_flp_period_ns;
+                batch_option.sources_to_use = FLP_TECH_MASK_GNSS;
+                memcpy((char *)flp_cmd + sizeof(MTK_FLP_MSG_T), &batch_option, sizeof(MTK_FLP_BATCH_OPTION_T));
+                mtk_flp2mnl_process(flp_cmd);
+                free(flp_cmd);
+            } else if((local_source >= 1) && (new_source == 0)) {//new req is close dc_xxx
+                flp_cmd = malloc(sizeof(MTK_FLP_MSG_T));
+                if(flp_cmd == NULL) {
+                    LOGE("update opt failed");
+                    return;
+                }
+                flp_cmd->type = MTK_FLP_MSG_DC_STOP_CMD;
+                flp_cmd->length = 0;
+                mtk_flp2mnl_process(flp_cmd);
+                free(flp_cmd);
+            }
+        }
+        flp_running_source = flp_source_to_use;
+    }
+}
+
+int mtk_flp_controller_reset_status(void) {
+    LOGD("clear flp ap status");
+    flp_enabled = 0;
+    flp_source_to_use = 0;
+    flp_running_source =0;
+    flp_batch_mode = MTK_FLP_IDLE_MODE;
+    g_flp_period_ns = 0;
+    current_gnss_acc = 0;
+    return MTK_FLP_SUCCESS;
+}
+
+//*****************************************************************************
+//  Low Power Main Function:
+//  1. Obtain Source_to_use(FLP & geofence) from FLP mtk_flp_input
+//  2. Relay command to FLP kernel
+//
+//  AP --> FLP HAL Offload (mtk_flp_input) --> Low power --> FLP kernel --> DC
+//*****************************************************************************
+int mtk_flp_controller_process(MTK_FLP_MSG_T *prmsg) {
+    FlpBatchOptions option;
+
+    memset(&option, 0, sizeof(option));
+
+    if(prmsg == NULL) {
+        LOGE("mtk_flp_controller_process, recv prmsg is null pointer\r\n");
+        return MTK_FLP_ERROR;
+    }
+
+    LOGD("mtk_flp_controller_process, recv prmsg, type: 0x%02x, len:%d\r\n", prmsg->type, prmsg->length);
+
+    switch( prmsg->type ) {
+        case MTK_FLP_MSG_HAL_START_CMD:      //process init request from HAL
+            LOGD("%s", pFLPVersion);
+            if(prmsg->length >= (int)(sizeof(FlpBatchOptions))) {
+                memcpy(&option, (FlpBatchOptions *)( (unsigned char*)prmsg+sizeof(MTK_FLP_MSG_T) ), sizeof(FlpBatchOptions));
+                flp_enabled = 1;
+                flp_batch_mode = option.flags;
+                g_flp_period_ns = option.period_ns;
+                flp_source_to_use = option.sources_to_use; //update flp source
+                mtk_flp_controller_update_option(&option);
+                //LOGD("low power enabled %u %u %"PRId64, flp_source_to_use, flp_enabled, g_flp_period_ns);
+            } else {
+                LOGE("incrorrect size %d",prmsg->length);
+            }
+            break;
+        case MTK_FLP_MSG_HAL_STOP_CMD:
+            LOGD("stop flp");
+            memset(&option, 0, sizeof(FlpBatchOptions));
+            flp_enabled = 0;
+            flp_source_to_use = 0;
+            option.sources_to_use = flp_source_to_use;
+            mtk_flp_controller_update_option(&option);
+            break;
+        case MTK_FLP_MSG_HAL_SET_OPTION_CMD:
+            if(!flp_enabled) {
+                LOGD("hal start");
+            }
+            flp_enabled = 1;
+            if(prmsg->length >= (int)(sizeof(FlpBatchOptions))) {
+                memcpy(&option, (FlpBatchOptions *)( (UINT8*)prmsg+sizeof(MTK_FLP_MSG_T) ), sizeof(FlpBatchOptions));
+
+                if(g_flp_period_ns != option.period_ns) {
+                    if(option.period_ns > 0) {
+                        //LOGD("update period from %lld to %lld",g_flp_period_ns,option.period_ns);
+                        g_flp_period_ns = option.period_ns;
+                    }
+                }
+
+                if(flp_batch_mode != (int)option.flags) {
+                    LOGD("update batch mode from %d to %d",flp_batch_mode,option.flags);
+                    flp_batch_mode = option.flags;
+                }
+
+                if(flp_source_to_use != option.sources_to_use) {
+                    LOGD("update source mode from %d to %d",flp_source_to_use,option.sources_to_use);
+                    flp_source_to_use = option.sources_to_use;
+                }
+                mtk_flp_controller_update_option(&option);
+            } else {
+                LOGE("incrorrect size %d",prmsg->length);
+            }
+            break;
+        default:
+            LOGD("lowpower pass through");
+            break;
+    }
+    return MTK_FLP_SUCCESS;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_main.c b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_main.c
new file mode 100644
index 0000000..61fcaf0
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_main.c
@@ -0,0 +1,573 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include "mtk_flp_main.h"
+#include "data_coder.h"
+#include "gps_controller.h"
+#include "mtk_gps.h"
+#include "mnld.h"
+//#include "mtk_flp_wake_monitor.h"
+#include "mtk_flp_controller.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "flpmain"
+#endif
+
+#define MNLD_STRNCPY(dst,src,size) do{\
+                                       strncpy((char *)(dst), (src), (size - 1));\
+                                      (dst)[size - 1] = '\0';\
+                                     }while(0)
+
+/**********************************************************
+ *  Global vars                                           *
+ **********************************************************/
+flp2mnl_interface* flp2mnl_hdlr_cb;
+static unsigned int gModeFlag = FLP_AP_MODE;
+static char g_mnl2flp_path[128] = MNL_TO_FLP;
+int ofl_lpbk_tst_start = 0;
+int ofl_lpbk_tst_size = 300;
+
+MTK_FLP_Session_T mnld_flp_session = {
+    .type = MNLD_FLP_CAPABILITY_AP_MODE,
+    .pre_type = MNLD_FLP_CAPABILITY_AP_MODE,
+    .id = 1,
+};
+
+/**********************************************************
+ *  Function Declaration                                  *
+ **********************************************************/
+extern int mnl2gfc_data_send(unsigned char *buf, unsigned int len);
+
+/**********************************************************
+ *  Socket Function                                       *
+ **********************************************************/
+static int flp_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 flp_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 flp_safe_sendto(int sockfd, const char* dest, const char* buf, int size) {
+    int len = 0;
+    struct sockaddr_un soc_addr;
+    int retry = 10;
+
+    memset(&soc_addr, 0, sizeof(soc_addr));
+    soc_addr.sun_path[0] = 0;
+    MNLD_STRNCPY(soc_addr.sun_path + 1, dest,sizeof(soc_addr.sun_path) - 1);
+    soc_addr.sun_family = AF_UNIX;
+    while ((len = sendto(sockfd, buf, size, 0,(const struct sockaddr *)&soc_addr, sizeof(soc_addr))) == -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;
+}
+
+int mnl_send2flp(const char* buff, int len) {
+    int ret = 0;
+    int sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+
+    if (sockfd < 0) {
+        LOGE("mnl_send2flp() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+
+    if (flp_safe_sendto(sockfd, g_mnl2flp_path, buff, len) < 0) {
+        LOGE("mnl_send2gfc safe_sendto failed\n");
+        ret = -1;
+    }
+    close(sockfd);
+    return ret;
+}
+
+static int flp_bind_udp_socket(char* path) {
+    int sockfd;
+    struct sockaddr_un soc_addr;
+
+    sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+    if (sockfd < 0) {
+        LOGE("socket failed reason=[%s]\n", strerror(errno));
+        return -1;
+    }
+    memset(&soc_addr, 0, sizeof(soc_addr));
+    soc_addr.sun_path[0] = 0;
+    MNLD_STRNCPY(soc_addr.sun_path + 1, path,sizeof(soc_addr.sun_path) - 1);
+    soc_addr.sun_family = AF_UNIX;
+    unlink(soc_addr.sun_path);
+    if (bind(sockfd, (struct sockaddr *)&soc_addr, sizeof(soc_addr)) < 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;
+}
+
+
+/**********************************************************
+ *  Response from Offload kernel                          *
+ **********************************************************/
+INT32 mtk_gps_ofl_sys_rst_stpgps_req() {
+    int ret = 0;
+
+    LOGD("");
+    gps_mnld_restart_mnl_process();
+    return ret;
+}
+
+INT32 mtk_gps_ofl_sys_submit_flp_data(UINT8 *buf, UINT32 len) {
+    static UINT8 tmp_buf[1024];
+    static int  tmp_buf_w = 0;
+    UINT8 buff[1024] = {0};
+    MTK_FLP_MNL_MSG_T *prMsg = NULL;
+
+    LOGD("[OFL]flp submit to host, buf=%p, len=%d", buf, len);
+    if (ofl_lpbk_tst_start == 1) {
+        memcpy(&tmp_buf[tmp_buf_w], buf, len);
+        tmp_buf_w+=len;
+        if (tmp_buf_w >= ofl_lpbk_tst_size) {
+            LOGD("[OFL] lpbk recv enougth data, actual=%d, except=%d, lpbk restart...",
+            tmp_buf_w, ofl_lpbk_tst_size);
+            mtk_gps_ofl_send_flp_data(&tmp_buf[0], ofl_lpbk_tst_size);
+            tmp_buf_w = 0;
+        }
+    } else if ((buf != NULL) && (len != 0) && (len < 1023)) {
+        //MTK_FLP_OFFLOAD_MSG_T *prMsg = (MTK_FLP_OFFLOAD_MSG_T *)&buff[0];
+        prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+        prMsg->type = MNLD_FLP_TYPE_OFL_LINK_RECV;
+        prMsg->length = len;
+        prMsg->session = mnld_flp_session.id;
+        if (len < sizeof(prMsg->data)) {
+            memcpy(&prMsg->data[0], buf, len);
+        } else {
+            LOGE("memcpy buf to prMsg->data out of bounds");
+        }
+
+        if (-1 == mnl2flp_data_send(buff, sizeof(buff))) {
+            LOGE("[FLP2MNLD]Send to FLP failed, %s\n", strerror(errno));
+        } else {
+            //LOGD("[FLP2MNLD]Send to FLP successfully\n");
+        }
+        ///TODO: single CB func from ofl GPS, add another delicate CB func for geofence
+        if (-1 == mnl2gfc_data_send(buff, sizeof(buff))) {
+            LOGE("[GFC2MNLD]Send to GFC failed, %s\n", strerror(errno));
+        }
+        else {
+            //LOGD("[GFC2MNLD]Send to GFC successfully\n");
+        }
+    }
+    return MTK_GPS_SUCCESS;
+}
+
+
+INT32 mtk_gps_ofl_sys_mnl_offload_callback(MTK_GPS_OFL_CB_TYPE type, UINT16 length, UINT8 *data) {
+    int offset;
+    UINT32 first_heartbeat, heartbeat_idx, ms_to_next;
+    //LOGD("type:%d, length:%d\n", type, length);
+
+    switch (type) {
+        case MTK_GPS_OFL_CB_HEART_BEAT:
+        {
+            if (length >= 12) {
+                offset = 0;
+                first_heartbeat = get_int((char*)data, &offset, length);
+                heartbeat_idx   = get_int((char*)data, &offset, length);
+                ms_to_next      = get_int((char*)data, &offset, length);
+                LOGD("type:%d, heartbeat, is_first:%u, idx:%u, next:%u",
+                type, first_heartbeat, heartbeat_idx, ms_to_next);
+                if (mnl_offload_is_enabled() && (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+                    if (first_heartbeat) {
+                        LOGD("mnl offload notify start done (mnl offload thread running)");
+                        // TODO: flp-dedicated timer
+                        mnld_gps_start_done(0);  // notify GPS is start
+                    } else {
+                        // TODO: set flp timer by ms_to_next_heartbeat
+                    }
+                }
+            }
+            else {
+                LOGE("type:0x%02x, error length:%d", type, length);
+            }
+        }
+            break;
+        default:
+            break;
+    }
+    return MTK_GPS_SUCCESS;
+}
+
+/*********************************************************/
+/* Response functions from mnl                           */
+/*********************************************************/
+int mnl2flp_mnld_reboot() {
+    LOGD("mnl2flp_mnld_reboot");
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    int * payload = NULL;
+    MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+
+    if (mnld_flp_session_update() == -1) {
+        LOGE("mnld_main_thread() mnld_flp_session_update failed");
+    }
+    prMsg->type = MNLD_FLP_TYPE_MNL_BOOTUP;
+    prMsg->session = mnld_flp_session.id;
+    prMsg->length = sizeof(int);
+    payload = (int *)&prMsg->data[0];
+    *payload = FLP_MNL_INTERFACE_VERSION;
+    return mnl2flp_hdlr(prMsg);
+}
+
+int mnl2flp_data_send(UINT8 *buf, UINT32 len) {
+    int ret = 0;
+    if(len >0) {
+        ret = mnl2flp_hdlr((MTK_FLP_MNL_MSG_T *)buf);
+    } else {
+        LOGE("len err %d",len);
+    }
+    return ret;
+}
+
+int mnld_flp_attach_done() {
+    LOGD("mnld_flp_attach_done");
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+
+    prMsg->type = MNLD_FLP_TYPE_FLP_ATTACH_DONE;
+    prMsg->length = 0;
+    prMsg->session = mnld_flp_session.id;
+    return mnl2flp_hdlr(prMsg);
+}
+
+int mnld_flp_hbd_gps_open_done() {
+    LOGD("mnld_flp_hbd_gps_open_done");
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+
+    prMsg->type = MNLD_FLP_TYPE_HBD_GPS_OPEN_DONE;
+    prMsg->length = 0;
+    prMsg->session = mnld_flp_session.id;
+    return mnl2flp_hdlr(prMsg);
+}
+
+int mnld_flp_hbd_gps_close_done() {
+    LOGD("mnld_flp_hbd_gps_close_done");
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+
+    prMsg->type = MNLD_FLP_TYPE_HBD_GPS_CLOSE_DONE;
+    prMsg->length = 0;
+    prMsg->session = mnld_flp_session.id;
+    return mnl2flp_hdlr(prMsg);
+}
+
+int mnld_flp_ofl_gps_open_done() {
+    LOGD("mnld_flp_ofl_gps_open_done");
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+
+    prMsg->type = MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE;
+    prMsg->length = 0;
+    prMsg->session = mnld_flp_session.id;
+    return mnl2flp_hdlr(prMsg);
+}
+
+int mnld_flp_ofl_gps_close_done() {
+    LOGD("mnld_flp_ofl_gps_close_done");
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+
+    prMsg->type = MNLD_FLP_TYPE_OFL_LINK_CLOSE_DONE;
+    prMsg->length = 0;
+    prMsg->session = mnld_flp_session.id;
+    return mnl2flp_hdlr(prMsg);
+}
+
+int mnld_flp_session_update() {
+    LOGD("mnld_flp_session_update,id=%d,type=%d",mnld_flp_session.id,mnld_flp_session.type);
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    int * payload = NULL;
+    MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+
+    prMsg->type = MNLD_FLP_TYPE_SESSION_UPDATE;
+    prMsg->length = sizeof(int);
+    prMsg->session = mnld_flp_session.id;
+    payload = (int *)&prMsg->data[0];
+    *payload = mnld_flp_session.type;
+    return mnl2flp_hdlr(prMsg);
+}
+
+int mnld_flp_gen_new_session() {
+    mnld_flp_session.id++;
+    if (mnld_flp_session.id >= 0xFFFFFFFF) {
+        mnld_flp_session.id = 0;
+        LOGW("Session id overflow!!");
+    }
+    return mnld_flp_session.id;
+}
+
+// Add for dbg usage
+#define MAX_DUMP_CHAR 128
+void mnl_flp_dump_buf(char *p, int len) {
+    int i, r, n;
+    char str[MAX_DUMP_CHAR] = {0};
+    for (i = 0, n = 0; i < len ; i++) {
+        r = snprintf(&str[n], MAX_DUMP_CHAR - n, "%3d,", p[i]);
+        if (r + n >= MAX_DUMP_CHAR || r <= 0) {
+            LOGE("[FLP2MNLD]data from flp: data=%s, error return", str);
+            return;
+        }
+
+        n += r;
+        if ((i % 8 == 7) || i + 1 == len) {
+            LOGD("[FLP2MNLD]data from flp: data=%s", str);
+            n = 0;
+            str[0] = '0';
+        }
+    }
+}
+
+void mtk_flp_set_sys_mode (unsigned int sysMode) {
+    if(sysMode == FLP_AP_MODE || sysMode == FLP_OFFLOAD_MODE) {
+        gModeFlag = sysMode;
+        LOGD("mtk_flp_set_sys_mode success = %d", gModeFlag);
+    } else {
+        LOGD("mtk_flp_set_sys_mode error = %d", sysMode);
+    }
+}
+
+
+int mtk_flp_get_sys_mode() {
+    return gModeFlag;
+}
+
+//*****************************************************************************
+//
+// mtk_hal2flp_main_hdlr(): FLP main function to process CMD from FLP HAL
+//
+// CMD from FWK: FLP JNI --> FLP HAL --> Mnld main --> mtk_hal2flp_main_hdlr
+// RSP to FWK  : mtk_flp2hal_main_hdlr --> mnl2flphal_hdlr(HAL) --> FLP JNI
+//*****************************************************************************
+int mtk_hal2flp_main_hdlr(int fd, flp2mnl_interface* hdlr) {
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    char data_recv[1024] ={0};
+    int ret = MTK_FLP_SUCCESS, read_len, offset = 0, len;
+    MTK_FLP_MSG_T *prmsg = NULL;
+
+    read_len = flp_safe_recvfrom(fd, buff, sizeof(buff));
+    if ((read_len <= 0) || (read_len>FLP_MNL_BUFF_SIZE)) {
+        LOGE("flp2mnl_hdlr_cb() safe_recvfrom() failed read_len=%d", read_len);
+        return MTK_FLP_ERROR;
+    }
+    if(hdlr != NULL) {
+        flp2mnl_hdlr_cb = hdlr;
+    } else {
+        LOGD("flp2mnl_hdlr_cb is null");
+    }
+
+    len = get_binary(buff, &offset, data_recv, sizeof(buff), sizeof(data_recv));
+    if((len > 0) && (len<=FLP_MNL_BUFF_SIZE)) {
+        prmsg = (MTK_FLP_MSG_T *)&data_recv[0];
+    } else {
+        LOGE("len err:%d",len);
+        return ret;
+    }
+
+    switch (prmsg->type) {
+        case MTK_FLP_MSG_HAL_INIT_CMD:                  //process init request from HAL
+            break;
+        case MTK_FLP_MSG_HAL_START_CMD:               //process init request from HAL
+        case MTK_FLP_MSG_HAL_STOP_CMD:                //process init request from HAL
+        case MTK_FLP_MSG_HAL_SET_OPTION_CMD:            //process init request from HAL
+            if(mtk_flp_get_sys_mode() == FLP_OFFLOAD_MODE) {
+                mtk_flp2mnl_process(prmsg);
+            } else {
+                mtk_flp_controller_process(prmsg);
+            }
+            break;
+        case MTK_FLP_MSG_HAL_DIAG_INJECT_DATA_NTF:      //process init request from HAL
+        case MTK_FLP_MSG_CONN_SCREEN_STATUS:            //process synch screen status from HAL
+            if(mtk_flp_get_sys_mode() == FLP_OFFLOAD_MODE) {
+                mtk_flp2mnl_process(prmsg);             //send HAL(AP)->Kernel(connsys) msg here
+            }
+            break;
+        case MTK_FLP_MSG_HAL_REQUEST_LOC_NTF:           //message from JNI, need forwarding only.
+        case MTK_FLP_MSG_HAL_FLUSH_LOC_NTF:             //message from JNI, need forwarding only.
+            if(mtk_flp_get_sys_mode() == FLP_OFFLOAD_MODE) {
+                mtk_flp2mnl_process(prmsg);
+            } else {
+                put_binary(buff, &offset, (const char*)prmsg, sizeof(MTK_FLP_MSG_T)+ sizeof(prmsg->length));
+                ret = mnl_send2flp(buff, offset);
+                if(ret < 0) {
+                    LOGE("MTK_FLP2HAL send error return error");
+                }
+            }
+            break;
+        default:
+            LOGE("FLP HAL: Uknown msessage, type:0x%02x", prmsg->type);
+            break;
+    }
+    return ret;
+}
+
+/************************************************************************/
+//  Handle FLP Request                                                  */
+/************************************************************************/
+int flp2mnl_hdlr(MTK_FLP_MNL_MSG_T  *prMsg) {
+    int ret = MTK_FLP_ERROR, read_len;
+
+    if(prMsg != NULL) {
+        read_len = prMsg->length + sizeof(MTK_FLP_MNL_MSG_HEADER_T);
+        LOGD("[FLP2MNLD]data from flp: type=0x%02x, session_id=%u, len=%d, read_len = %d\n", prMsg->type, prMsg->session, prMsg->length, read_len);
+        //mnl_flp_dump_buf((char*)prMsg, read_len);
+    } else {
+        LOGE("flp2mnl_hdlr recv null msg");
+        return ret;
+    }
+    if(flp2mnl_hdlr_cb == NULL) {
+        LOGE("flp2mnl_hdlr_cb is NULL");
+        return ret;
+    }
+
+    switch (prMsg->type) {
+        case MNLD_FLP_TYPE_FLP_ATTACH: {
+            if (flp2mnl_hdlr_cb->mnld_flp_attach) {
+                flp2mnl_hdlr_cb->mnld_flp_attach();
+                if (mnld_flp_session_update() == -1) {
+                    LOGE("mnld_main_thread() mnld_flp_session_update failed");
+                }
+                ret = MTK_FLP_SUCCESS;
+            } else {
+                LOGE("flp2mnl_hdlr_cb() mnld_flp_attach is NULL");
+            }
+            break;
+        }
+        case MNLD_FLP_TYPE_HBD_GPS_OPEN: {
+            if (prMsg->session != mnld_flp_session.id) {
+                LOGE("flp2mnl_hdlr() session_id doesn't match, ignore");
+                break;
+            }
+            if (flp2mnl_hdlr_cb->mnld_flp_hbd_gps_open) {
+                flp2mnl_hdlr_cb->mnld_flp_hbd_gps_open();
+                ret = MTK_FLP_SUCCESS;
+            } else {
+                LOGE("flp2mnl_hdlr() mnld_flp_hbd_gps_open is NULL");
+            }
+            break;
+        }
+        case MNLD_FLP_TYPE_HBD_GPS_CLOSE: {
+            if (prMsg->session != mnld_flp_session.id) {
+                LOGE("flp2mnl_hdlr() session_id doesn't match, ignore");
+                break;
+            }
+            if (flp2mnl_hdlr_cb->mnld_flp_hbd_gps_close) {
+                flp2mnl_hdlr_cb->mnld_flp_hbd_gps_close();
+                ret = MTK_FLP_SUCCESS;
+            } else {
+                LOGE("flp2mnl_hdlr() mnld_flp_hbd_gps_close is NULL");
+            }
+            break;
+        }
+        case MNLD_FLP_TYPE_OFL_LINK_OPEN: {
+            if (prMsg->session != mnld_flp_session.id) {
+                LOGE("flp2mnl_hdlr() session_id doesn't match, ignore");
+                break;
+            }
+            if (flp2mnl_hdlr_cb->mnld_flp_ofl_link_open) {
+                flp2mnl_hdlr_cb->mnld_flp_ofl_link_open();
+                ret = MTK_FLP_SUCCESS;
+            } else {
+                LOGE("flp2mnl_hdlr() mnld_flp_ofl_link_open is NULL");
+            }
+            break;
+        }
+        case MNLD_FLP_TYPE_OFL_LINK_CLOSE: {
+            if (prMsg->session != mnld_flp_session.id) {
+                LOGE("flp2mnl_hdlr() session_id doesn't match, ignore");
+                break;
+            }
+            if (flp2mnl_hdlr_cb->mnld_flp_ofl_link_close) {
+                flp2mnl_hdlr_cb->mnld_flp_ofl_link_close();
+                ret = MTK_FLP_SUCCESS;
+            } else {
+                LOGE("flp2mnl_hdlr() mnld_flp_ofl_link_close is NULL");
+            }
+            break;
+        }
+        case MNLD_FLP_TYPE_OFL_LINK_SEND: {
+            if (prMsg->session != mnld_flp_session.id) {
+                LOGE("flp2mnl_hdlr() session_id doesn't match, ignore");
+                break;
+            }
+            if (flp2mnl_hdlr_cb->mnld_flp_ofl_link_send) {
+                flp2mnl_hdlr_cb->mnld_flp_ofl_link_send(prMsg);
+                ret = MTK_FLP_SUCCESS;
+            } else {
+                LOGE("flp2mnl_hdlr() mnld_flp_ofl_link_send is NULL");
+            }
+            break;
+        }
+        default: {
+            LOGE("flp2mnl_hdlr() unknown cmd=0x%02x", prMsg->type);
+            break;
+        }
+    }
+    return ret;
+}
+
+int create_flphal2mnl_fd() {
+    int fd = flp_bind_udp_socket(FLP_TO_MNL);
+    flp_set_socket_blocking(fd, 0);
+    return fd;
+}
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_mnl_interface.c b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_mnl_interface.c
new file mode 100644
index 0000000..38a042e
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_mnl_interface.c
@@ -0,0 +1,473 @@
+/*****************************************************************************
+ * Include
+ *****************************************************************************/
+#include <stdlib.h>
+#include <pthread.h>
+#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 <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <sys/ipc.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <math.h>
+#include "mtk_flp_controller.h"
+#include "data_coder.h"
+//#include "mtk_flp_wake_monitor.h"
+#include "mtk_auto_log.h"
+#if defined(__ANDROID_OS__)
+#include <hardware/gps.h>
+#elif defined(__LINUX_OS__)
+#include "gps.h"
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "flpint"
+#endif
+
+#define MAX_FLP_BATCHING_MSG   10
+/**********************************************************
+ *  Global vars                                           *
+ **********************************************************/
+static unsigned int fgMnldStatus = MNL_STATUS_NONE;
+static unsigned int gCurrentSession = 0;
+static unsigned int gCurrentSupport = 0;
+
+static int gFlp2mnl_cnt = 0;
+static MTK_FLP_MNL_MSG_T gFlp2mnl_msg[MAX_FLP_BATCHING_MSG];
+
+enum{
+    CMD_FLP_REPORT_GNSS_LOC = 58,
+};
+
+
+static int mtk_flp_gpsloc2flploc(GpsLocation* gpsloc, FlpLocation *flploc) {
+    if (gpsloc == NULL || flploc == NULL) {
+        return MTK_FLP_ERROR;
+    }
+
+    memset(flploc,0,sizeof(FlpLocation));
+    flploc->size = sizeof(FlpLocation);
+    flploc->sources_used = FLP_TECH_MASK_GNSS;
+    flploc->accuracy = 1.7*(gpsloc->accuracy); //convert accuracy from 67% to 95%
+    flploc->altitude = gpsloc->altitude;
+    flploc->bearing = gpsloc->bearing;
+    flploc->flags =gpsloc->flags;
+    flploc->latitude = gpsloc->latitude;
+    flploc->longitude = gpsloc->longitude;
+    flploc->speed = gpsloc->speed;
+    flploc->timestamp = gpsloc->timestamp;//mtk_flp_get_timestamp(NULL);
+    #if 0
+    LOGD("[DC_GNSS]:dc2gnss: acc:%.4f,alt:%.4f,bearing:%.4f,flag:%d,lat:%.4f,lon:%.4f,spd:%.4f",
+    flploc->accuracy,flploc->altitude,flploc->bearing,flploc->flags,flploc->latitude,
+    flploc->longitude,flploc->speed);
+    #endif
+
+    return MTK_FLP_SUCCESS;
+}
+
+static void mtk_flp_dc_loc_rearrange(MTK_FLP_LOCATION_T *loc_in, MTK_FLP_LOCATION_T *loc_out) {
+    loc_out->size = loc_in->size;
+    loc_out->sources_used = loc_in->sources_used;
+    loc_out->flags = loc_in->flags;
+    loc_out->latitude = loc_in->latitude;
+    loc_out->longitude = loc_in->longitude;
+    loc_out->accuracy = loc_in->accuracy;
+    loc_out->altitude = loc_in->altitude;
+    loc_out->speed = loc_in->speed;
+    loc_out->bearing = loc_in->bearing;
+    loc_out->timestamp = loc_in->timestamp;
+    #if 0
+    LOGD("Loc from CNN:LNG:%f LAT:%f ALT:%f ACC:%f SPD:%f BEARING:%f, FLAGS:%04X SOURCES:%08X Timestamp:%lld",
+    loc_out->longitude, loc_out->latitude, loc_out->altitude, loc_out->accuracy,
+    loc_out->speed, loc_out->bearing, loc_out->flags, loc_out->sources_used, loc_out->timestamp);
+    LOGD("Loc processed:LNG:%f LAT:%f ALT:%f ACC:%f SPD:%f BEARING:%f, FLAGS:%04X SOURCES:%08X Timestamp:%lld",
+    loc_in->longitude, loc_in->latitude, loc_in->altitude, loc_in->accuracy,
+    loc_in->speed, loc_in->bearing, loc_in->flags, loc_in->sources_used, loc_in->timestamp);
+    #endif
+}
+
+#if 0
+void mtk_flp2mnl_send_screen_state() {
+    MTK_FLP_MNL_MSG_HEADER_T *flp2mnl_msg;
+    MTK_FLP_MSG_T flp2cnn_msg;
+    unsigned char screen_state = 0;
+    mtk_flp_get_wake_monitor_state(&screen_state);
+    flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_FLP_MNL_MSG_HEADER_T) + sizeof(MTK_FLP_MSG_T) + sizeof(unsigned char));
+  if(flp2mnl_msg != NULL) {
+    flp2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_SEND;
+    flp2mnl_msg->session= gCurrentSession;
+    flp2mnl_msg->length = sizeof(MTK_FLP_MSG_T) + sizeof(UINT8);
+    flp2cnn_msg.type = MTK_FLP_MSG_CONN_SCREEN_STATUS;
+    flp2cnn_msg.length = sizeof(UINT8);
+    memcpy(((char*)flp2mnl_msg) + sizeof(MTK_FLP_MNL_MSG_HEADER_T), ((char*)&flp2cnn_msg), sizeof(MTK_FLP_MSG_T));
+    memcpy(((char*)flp2mnl_msg) + sizeof(MTK_FLP_MNL_MSG_HEADER_T) + sizeof(MTK_FLP_MSG_T), &screen_state, sizeof(unsigned char));
+    LOGD("Send to OFL FLP, screen_state = %u", screen_state);
+    flp2mnl_hdlr(flp2mnl_msg);
+    free(flp2mnl_msg);
+  }
+}
+#endif
+
+/************************************************************************/
+//  Process msgs from FLP HAL and send to offload kernel
+/************************************************************************/
+int mtk_flp2mnl_process(MTK_FLP_MSG_T *prmsg) {
+    MTK_FLP_MNL_MSG_HEADER_T* flp2mnl_msg = NULL;
+    MTK_FLP_MSG_T flp2cnn_msg;
+
+    if(prmsg == NULL) {
+        LOGD("mtk_flp2mnl_process, recv prmsg is null pointer\n");
+        return MTK_FLP_ERROR;
+    }
+
+    LOGD("mtk_flp2mnl_process, recv prmsg, type:%d, len:%d status:%u\r\n", prmsg->type, prmsg->length, fgMnldStatus);
+
+    switch(prmsg->type) {
+        case MTK_FLP_MSG_HAL_START_CMD:
+        case MTK_FLP_MSG_HAL_DIAG_INJECT_DATA_NTF:
+            if (fgMnldStatus != MNL_STATUS_OFL_LINK_OPEN_DONE) {
+                if (gFlp2mnl_cnt == 0) {
+                    //send init message to mnld first
+                    flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_FLP_MNL_MSG_HEADER_T)); //send header only, no message body
+                    if(flp2mnl_msg != NULL) {
+                        flp2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_OPEN;
+                        flp2mnl_msg->session = gCurrentSession;
+                        flp2mnl_msg->length = 0;
+                        LOGD("MNLD_FLP_TYPE_OFL_LINK_OPEN");
+                        fgMnldStatus = MNL_STATUS_OFL_LINK_OPEN;
+                        flp2mnl_hdlr((MTK_FLP_MNL_MSG_T *)flp2mnl_msg);
+                        free(flp2mnl_msg);
+                    }
+                }
+                if (gFlp2mnl_cnt < MAX_FLP_BATCHING_MSG) {
+                    gFlp2mnl_msg[gFlp2mnl_cnt].type = MNLD_FLP_TYPE_OFL_LINK_SEND;
+                    gFlp2mnl_msg[gFlp2mnl_cnt].length = prmsg->length + sizeof(MTK_FLP_MSG_T);
+                    gFlp2mnl_msg[gFlp2mnl_cnt].session = gCurrentSession;
+                    memcpy(&gFlp2mnl_msg[gFlp2mnl_cnt].data[0], ((char*)prmsg), (sizeof(MTK_FLP_MSG_T)+ prmsg->length));
+                    gFlp2mnl_cnt++;
+                    LOGD("Keep flp data cnt %d", gFlp2mnl_cnt);
+                } else {
+                    LOGD("Batching size overflow");
+                }
+            }
+            break;
+        case MTK_FLP_MSG_HAL_STOP_CMD:
+            //send msg stop mnl first
+            flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc( sizeof(MTK_FLP_MNL_MSG_HEADER_T)+sizeof(MTK_FLP_MSG_T));
+            if(flp2mnl_msg != NULL) {
+                flp2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_SEND;
+                flp2mnl_msg->session = gCurrentSession;
+                flp2mnl_msg->length = sizeof(MTK_FLP_MSG_T); // data sent structure: [type, length for AP_conn recognition] + [type,length]
+                flp2cnn_msg.type = MTK_FLP_MSG_HAL_STOP_CMD;
+                flp2cnn_msg.length = 0;
+                memcpy(((char*)flp2mnl_msg)+sizeof(MTK_FLP_MNL_MSG_HEADER_T), ((char*)&flp2cnn_msg), sizeof(MTK_FLP_MSG_T));
+                LOGD("Send to OFL FLP,message type:0x%02x, len:%u", flp2cnn_msg.type, (flp2mnl_msg->length + sizeof(MTK_FLP_MNL_MSG_HEADER_T)));
+                flp2mnl_hdlr((MTK_FLP_MNL_MSG_T *)flp2mnl_msg);
+                free(flp2mnl_msg);
+            }
+            break;
+        case MTK_FLP_MSG_DC_START_CMD: // host-based start gnss
+            //send init message to mnld first
+            flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_FLP_MNL_MSG_HEADER_T)); //send header only, no message body
+            if(flp2mnl_msg != NULL) {
+                flp2mnl_msg->type = MNLD_FLP_TYPE_HBD_GPS_OPEN;
+                flp2mnl_msg->length = 0;
+                flp2mnl_msg->session = gCurrentSession;
+                LOGD("MNLD_FLP_TYPE_HBD_GPS_OPEN");
+                fgMnldStatus = MNL_STATUS_HBD_GPS_OPEN;
+                flp2mnl_hdlr((MTK_FLP_MNL_MSG_T *)flp2mnl_msg);
+                free(flp2mnl_msg);
+            }
+            break;
+        case MTK_FLP_MSG_DC_STOP_CMD:
+            //send stop message to mnld
+            flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_FLP_MNL_MSG_HEADER_T)); //send header only, no message body
+            if(flp2mnl_msg != NULL) {
+                flp2mnl_msg->type = MNLD_FLP_TYPE_HBD_GPS_CLOSE;
+                flp2mnl_msg->length = 0;
+                flp2mnl_msg->session = gCurrentSession;
+                LOGD("Send to mnld for deinit,message type:0x%02x, len:%d", flp2mnl_msg->type, flp2mnl_msg->length);
+                fgMnldStatus = MNL_STATUS_HBD_GPS_CLOSE;
+                flp2mnl_hdlr((MTK_FLP_MNL_MSG_T *)flp2mnl_msg);
+                free(flp2mnl_msg);
+            }
+            break;
+        case MTK_FLP_MSG_CONN_SCREEN_STATUS:
+            if(fgMnldStatus == MNL_STATUS_OFL_LINK_OPEN_DONE) {
+                flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc( sizeof(MTK_FLP_MNL_MSG_HEADER_T)+ sizeof(MTK_FLP_MSG_T)+prmsg->length);
+                if(flp2mnl_msg != NULL) {
+                    flp2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_SEND;
+                    flp2mnl_msg->session = gCurrentSession;
+                    flp2mnl_msg->length = (prmsg->length) + sizeof(MTK_FLP_MSG_T);
+                    memcpy(((char*)flp2mnl_msg)+sizeof(MTK_FLP_MNL_MSG_HEADER_T), ((char*)prmsg), (sizeof(MTK_FLP_MSG_T)+ (prmsg->length)));
+                    LOGD("Send to OFL FLP,message type:0x%02x, len:%d", prmsg->type, (flp2mnl_msg->length + sizeof(MTK_FLP_MSG_T)));
+                    flp2mnl_hdlr((MTK_FLP_MNL_MSG_T *)flp2mnl_msg);
+                    free(flp2mnl_msg);
+                }
+            } else {
+                LOGD("free screen dbg");
+            }
+            break;
+        default:
+            if(mtk_flp_get_sys_mode() == FLP_OFFLOAD_MODE) {
+                if(fgMnldStatus == MNL_STATUS_OFL_LINK_OPEN_DONE) {
+                    flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc( sizeof(MTK_FLP_MNL_MSG_HEADER_T)+ sizeof(MTK_FLP_MSG_T)+prmsg->length);
+                    if(flp2mnl_msg != NULL) {
+                        flp2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_SEND;  //for loopback test between mnld & FLP AP  use FLP_MNL_CMD_LOOPBACK
+                        flp2mnl_msg->session = gCurrentSession;
+                        flp2mnl_msg->length = (prmsg->length) + sizeof(MTK_FLP_MSG_T); // data sent structure: [type, length for AP_conn recognition] + [type,length+buff for flp recognition]
+                        memcpy(((INT8*)flp2mnl_msg)+sizeof(MTK_FLP_MNL_MSG_HEADER_T), ((INT8*)prmsg), (sizeof(MTK_FLP_MSG_T)+ (prmsg->length)));
+                        flp2mnl_hdlr((MTK_FLP_MNL_MSG_T *)flp2mnl_msg);
+                        free(flp2mnl_msg);
+                    }
+                } else {
+                    LOGD("mnld_ret=%u", fgMnldStatus);
+                }
+            }
+            break;
+    }
+    return MTK_FLP_SUCCESS;
+}
+
+/************************************************************************/
+//  Handle MNL Response                                                 */
+/************************************************************************/
+int mnl2flp_hdlr(MTK_FLP_MNL_MSG_T* prmsg) {
+    char buff[HAL_FLP_BUFF_SIZE] = {0};
+    int ret, i;
+    int offset = 0;
+    MTK_FLP_MNL_MSG_HEADER_T *flp2mnl_msg = NULL;
+    MTK_FLP_MSG_T *flp2hal_msg = NULL;
+    MTK_FLP_MSG_T *cnn2flp_msg = NULL;
+    MTK_FLP_LOCATION_T  loc_in, loc_out;
+    GpsLocation  *gps_loc;
+    MTK_FLP_LOCATION_T  flp_loc;
+
+    if(prmsg == NULL) {
+        LOGD("mnl2flp_hdlr recv null msg");
+        return MTK_FLP_ERROR;
+        }
+
+    LOGD("mtk_mnl2flp_recv_msg type = 0x%02x, session = %u, len = %u, state = %u\n",  prmsg->type, prmsg->session, prmsg->length, fgMnldStatus);
+
+    switch(prmsg->type) {
+        case MNLD_FLP_TYPE_MNL_BOOTUP:
+            fgMnldStatus = MNL_STATUS_ATTACH_DONE;
+            flp2hal_msg = malloc(sizeof(MTK_FLP_MSG_T));
+            if(flp2hal_msg == NULL) {
+                LOGE("reset ntf malloc failed");
+                return MTK_FLP_ERROR;
+            }
+            flp2hal_msg->type = MTK_FLP_MSG_SYS_FLPD_RESET_NTF;
+            flp2hal_msg->length = 0;
+            put_binary(buff, &offset, (const char*)flp2hal_msg, sizeof(MTK_FLP_MSG_T));
+            ret = mnl_send2flp(buff, offset);
+            free(flp2hal_msg);
+            if(ret < 0) {
+                LOGD("MTK_FLP2HAL send error return error");
+            }
+            break;
+        case MNLD_FLP_TYPE_SESSION_UPDATE:
+            gCurrentSession = prmsg->session;
+            memcpy(&gCurrentSupport, ((char*)prmsg)+sizeof(MTK_FLP_MNL_MSG_HEADER_T), sizeof(gCurrentSupport));
+            LOGD("SESSION_UPDATE %u support %u mode %u", gCurrentSession, gCurrentSupport, fgMnldStatus);
+            if (fgMnldStatus == MNL_STATUS_HBD_GPS_OPEN_DONE && gCurrentSupport == FLP_AP_MODE) {
+                LOGD("SESSION_UPDATE: already run on host");
+            } else if (fgMnldStatus == MNL_STATUS_OFL_LINK_OPEN_DONE && (gCurrentSupport & FLP_OFFLOAD_MODE)) {
+                LOGD("SESSION_UPDATE: already run on offlaod");
+            } else if (fgMnldStatus == MNL_STATUS_HBD_GPS_OPEN_DONE && (gCurrentSupport & FLP_OFFLOAD_MODE)) {
+                LOGD("SESSION_UPDATE: switch to ofl mode");
+                mtk_flp_controller_reset_status();
+                mtk_flp_set_sys_mode(FLP_OFFLOAD_MODE);
+
+                flp2hal_msg = malloc(sizeof(MTK_FLP_MSG_T));
+                if(flp2hal_msg == NULL) {
+                    LOGE("reset ntf malloc failed");
+                    return MTK_FLP_ERROR;
+                }
+                flp2hal_msg->type = MTK_FLP_MSG_SYS_FLPD_RESET_NTF;
+                flp2hal_msg->length = 0;
+                put_binary(buff, &offset, (const char*)flp2hal_msg, sizeof(MTK_FLP_MSG_T));
+                ret = mnl_send2flp(buff, offset);
+                free(flp2hal_msg);
+                if(ret < 0) {
+                    LOGD("mnl2flp_hdlr send error return error");
+                }
+            } else if (fgMnldStatus == MNL_STATUS_OFL_LINK_OPEN_DONE && (gCurrentSupport == FLP_AP_MODE)) {
+                LOGD("SESSION_UPDATE: switch to ap mode");
+                mtk_flp_set_sys_mode(FLP_AP_MODE);
+                flp2hal_msg = malloc(sizeof(MTK_FLP_MSG_T));
+                if(flp2hal_msg == NULL) {
+                    LOGE("reset ntf malloc failed");
+                    return MTK_FLP_ERROR;
+                }
+                flp2hal_msg->type = MTK_FLP_MSG_SYS_FLPD_RESET_NTF;
+                flp2hal_msg->length = 0;
+                put_binary(buff, &offset, (const char*)flp2hal_msg, sizeof(MTK_FLP_MSG_T));
+                ret = mnl_send2flp(buff, offset);
+                free(flp2hal_msg);
+                if(ret < 0) {
+                    LOGD("mnl2flp_hdlr send error return error");
+                }
+            } else {
+                if (gCurrentSupport & FLP_OFFLOAD_MODE) {
+                    mtk_flp_set_sys_mode(FLP_OFFLOAD_MODE);
+                    LOGD("SESSION_UPDATE: set offload mode");
+                } else if (gCurrentSupport == FLP_AP_MODE) {
+                    mtk_flp_set_sys_mode(FLP_AP_MODE);
+                    LOGD("SESSION_UPDATE: set ap mode");
+                }
+            }
+            break;
+        case MNLD_FLP_TYPE_HBD_GPS_LOCATION:
+            gps_loc = (GpsLocation *)(((char*)prmsg)+sizeof(MTK_FLP_MNL_MSG_HEADER_T));
+            //LOGD("GNSS LOC DBG: %f, %lf, %lf, %d", gps_loc->accuracy, gps_loc->latitude, gps_loc->longitude, gps_loc->size);
+
+            if(mtk_flp_gpsloc2flploc(gps_loc, (FlpLocation *)&flp_loc) != MTK_FLP_SUCCESS) {
+                LOGD("Incorrect data received");
+            } else {
+                if (mtk_flp_controller_report_loc(flp_loc) == -1) {
+                    break;
+                }
+                //send loc to FLP HAL
+                if(mtk_flp_controller_query_mode() > MTK_FLP_IDLE_MODE) {
+                    flp2hal_msg = malloc(sizeof(MTK_FLP_MSG_T)+sizeof(MTK_FLP_LOCATION_T));
+                    if(flp2hal_msg == NULL) {
+                        LOGE("report loc malloc failed");
+                        return MTK_FLP_ERROR;
+                    }
+                    flp2hal_msg->type = MTK_FLP_MSG_HSB_REPORT_LOC_NTF;
+                    flp2hal_msg->length = sizeof(MTK_FLP_LOCATION_T);
+                    memcpy((char *)flp2hal_msg + sizeof(MTK_FLP_MSG_T),&flp_loc, sizeof(MTK_FLP_LOCATION_T) );
+                    put_binary(buff, &offset, (const char*)flp2hal_msg, (sizeof(MTK_FLP_MSG_T)+flp2hal_msg->length));
+                    ret = mnl_send2flp(buff, offset);
+                    free(flp2hal_msg);
+                    if(ret < 0) {
+                        LOGD("MTK_FLP2HAL send error return error");
+                    }
+                }
+#if 0 // android o no diag CB
+                //send location diag ntf
+                if(mtk_flp_controller_query_mode() > MTK_FLP_IDLE_MODE) {
+                sprintf(localbuf,"FLP_NTF=LNG:%f LAT:%f ALT:%f", flp_loc.longitude, flp_loc.latitude, flp_loc.altitude);
+                LOGD("%s",localbuf);
+                flp2hal_diag = malloc(sizeof(MTK_FLP_MSG_T)+strlen(localbuf));
+                if(flp2hal_diag == NULL) {
+                LOGE("diag report malloc failed");
+                return MTK_FLP_ERROR;
+                }
+                memset(buff,0,HAL_FLP_BUFF_SIZE*sizeof(char));
+                offset = 0;
+                flp2hal_diag->type = MTK_FLP_MSG_HAL_DIAG_REPORT_DATA_NTF;
+                flp2hal_diag->length = strlen(localbuf);
+                memcpy((char *)flp2hal_diag + sizeof(MTK_FLP_MSG_T),&localbuf[0], strlen(localbuf) );
+                put_binary(buff, &offset, (const char*)flp2hal_diag, (sizeof(MTK_FLP_MSG_T)+flp2hal_diag->length));
+                ret = mnl_send2flp(buff, offset);
+                free(flp2hal_diag);
+                if(ret < 0) {
+                LOGD("MTK_FLP2HAL send error return error");
+                }
+                }
+#endif
+            }
+            break;
+        case MNLD_FLP_TYPE_OFL_LINK_RECV:
+            cnn2flp_msg = malloc(prmsg->length);
+            if(cnn2flp_msg == NULL) {
+                return MTK_FLP_ERROR;
+            }
+            memcpy((char*)cnn2flp_msg, ((char*)prmsg)+ sizeof(MTK_FLP_MNL_MSG_HEADER_T), prmsg->length);
+            LOGD("Received OFFLOAD message type: 0x%02x, len = %u", cnn2flp_msg->type, cnn2flp_msg->length);
+            switch(cnn2flp_msg->type) {
+                case MTK_FLP_MSG_HAL_STOP_RSP:
+                    //send stop message to mnld
+                    flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_FLP_MNL_MSG_HEADER_T));
+                    if(flp2mnl_msg!= NULL) {
+                        flp2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_CLOSE;
+                        flp2mnl_msg->session= gCurrentSession;
+                        flp2mnl_msg->length = 0;
+                        //LOGD("Send to mnld for deinit,message type:%u, len:%u", flp2mnl_msg->type, flp2mnl_msg->length);
+                        flp2mnl_hdlr((MTK_FLP_MNL_MSG_T *)flp2mnl_msg);
+                        fgMnldStatus = MNL_STATUS_OFL_LINK_CLOSE;
+                        free(flp2mnl_msg);
+                        LOGD("mnld deinit success");
+                    }
+                    break;
+                case MTK_FLP_MSG_OFL_REPORT_LOC_NTF:
+                    //check location size
+                    if(cnn2flp_msg->length >= (int)sizeof(MTK_FLP_LOCATION_T)) {
+                        //LOGD("size check: %d %d \n", (cnn2flp_msg->length), sizeof(MTK_FLP_LOCATION_T));
+                        memcpy(&loc_in, ((char*)cnn2flp_msg)+sizeof(MTK_FLP_MSG_T), sizeof(MTK_FLP_LOCATION_T));
+                        mtk_flp_dc_loc_rearrange(&loc_in, &loc_out);
+
+                        //send loc to FLP HAL
+                        flp2hal_msg = malloc(sizeof(MTK_FLP_MSG_T)+sizeof(MTK_FLP_LOCATION_T));
+                        if(flp2hal_msg == NULL) {
+                            LOGE("report loc malloc failed");
+                            free(cnn2flp_msg);
+                            return MTK_FLP_ERROR;
+                        }
+                        flp2hal_msg->type = cnn2flp_msg->type;
+                        flp2hal_msg->length = sizeof(MTK_FLP_LOCATION_T);
+                        memcpy((char *)flp2hal_msg + sizeof(MTK_FLP_MSG_T),&loc_out, sizeof(MTK_FLP_LOCATION_T) );
+                        put_binary(buff, &offset, (const char*)flp2hal_msg, (sizeof(MTK_FLP_MSG_T)+flp2hal_msg->length));
+                        ret = mnl_send2flp(buff, offset);
+                        free(flp2hal_msg);
+                        if(ret < 0) {
+                            LOGD("MTK_FLP2HAL send error return error");
+                        }
+                    }
+                    break;
+                default:
+                    if(cnn2flp_msg->type < MTK_FLP_MSG_END) {
+                        put_binary(buff, &offset, (const char*)cnn2flp_msg, sizeof(MTK_FLP_MSG_T)+cnn2flp_msg->length);
+                        ret = mnl_send2flp(buff, offset);
+                        if(ret < 0) {
+                            LOGD("MTK_FLP2HAL send error return error");
+                        }
+                    }
+                    break;
+            }
+            free(cnn2flp_msg);
+            break;
+        case MNLD_FLP_TYPE_HBD_GPS_OPEN_DONE:
+            fgMnldStatus = MNL_STATUS_HBD_GPS_OPEN_DONE;
+            LOGD("MNLD_FLP_TYPE_HBD_GPS_OPEN_DONE");
+            break;
+        case MNLD_FLP_TYPE_HBD_GPS_CLOSE_DONE:
+            fgMnldStatus = MNL_STATUS_HBD_GPS_CLOSE_DONE;
+            LOGD("MNL_STATUS_HBD_GPS_CLOSE_DONE");
+            break;
+        case MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE:
+            if (fgMnldStatus == MNL_STATUS_OFL_LINK_OPEN) {
+                fgMnldStatus = MNL_STATUS_OFL_LINK_OPEN_DONE;
+                LOGD("MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE flush %d", gFlp2mnl_cnt);
+                for (i = 0; i < gFlp2mnl_cnt; i++) {
+                    flp2mnl_hdlr(&gFlp2mnl_msg[i]);
+                }
+                gFlp2mnl_cnt = 0;
+            } else {
+                LOGD("FLP_DBG: mnld state expect 7, get %u", fgMnldStatus);
+            }
+            LOGD("MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE");
+            break;
+        case MNLD_FLP_TYPE_OFL_LINK_CLOSE_DONE:
+            fgMnldStatus = MNL_STATUS_OFL_LINK_CLOSE_DONE;
+            LOGD("MNLD_FLP_TYPE_OFL_LINK_CLOSE_DONE");
+            break;
+        default:
+            LOGE("undefined cmd:0x%02x",prmsg->type);
+            break;
+    }
+    return MTK_FLP_SUCCESS;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_screen_monitor.c b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_screen_monitor.c
new file mode 100644
index 0000000..a6c6b77
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_screen_monitor.c
@@ -0,0 +1,209 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <sys/inotify.h>
+#include "data_coder.h"
+#include "mtk_gps.h"
+#include "mnld.h"
+#include "mtk_flp_screen_monitor.h"
+#include "mtk_flp_main.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "flpscreen"
+#endif
+
+#define MNLD_STRNCPY(dst,src,size) do{\
+                                       strncpy((char *)(dst), (src), (size - 1));\
+                                      (dst)[size - 1] = '\0';\
+                                     }while(0)
+
+/**********************************************************
+ *  Global vars                                           *
+ **********************************************************/
+static UINT8 earlysuspend_state = EARLYSUSPEND_ON;
+static pthread_mutex_t earlysuspend_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t earlysuspend_cond = PTHREAD_COND_INITIALIZER;
+
+/**********************************************************
+ *  Function Declaration                                  *
+ **********************************************************/
+static int wait_for_fb_wake(void) {
+    int ino_len;
+    int ino_fd;
+    int ino_wd;
+    char ino_buf[1024];
+    char buf[100];
+    FILE *fd;
+    while(1) {
+        ino_fd = inotify_init();
+        if(ino_fd < 0) {
+            LOGE("inotify_init error");
+            return 1;
+        }
+        ino_wd = inotify_add_watch(ino_fd, "/sys/power/wake_lock", IN_MODIFY);
+        if (ino_wd == -1) {
+            LOGE("inotify add fail: %s(%d)\n", strerror(errno), errno);
+            return 1;
+        }
+        ino_len = read(ino_fd, ino_buf, 1024);
+        if(ino_len < 0) {
+            LOGE("inotify read error");
+            return 1;
+        }
+        (void)inotify_rm_watch(ino_fd, ino_wd);
+        (void)close(ino_fd);
+
+        fd = fopen("/sys/power/wake_lock" , "r");
+        if(fd) {
+            while(fscanf(fd, "%99s", buf) != EOF) {
+                if(strstr(buf, "Display") != NULL) {
+                    fclose(fd);
+                    return 0;
+                }
+            }
+        }
+        else {
+            LOGE("fopen error\n");
+            return 1;
+        }
+        fclose(fd);
+    }
+}
+
+static int wait_for_fb_sleep(void)
+{
+    int ino_len;
+    int ino_fd;
+    int ino_wd;
+    char ino_buf[1024];
+    char buf[100];
+    FILE *fd;
+    while(1) {
+        ino_fd = inotify_init();
+        if (ino_fd < 0) {
+            LOGE("inotify_init error");
+            return 1;
+        }
+        ino_wd = inotify_add_watch(ino_fd, "/sys/power/wake_unlock", IN_MODIFY);
+        if (ino_wd == -1) {
+            LOGE("inotify add fail: %s(%d)\n", strerror(errno), errno);
+            return 1;
+        }
+        ino_len = read(ino_fd, ino_buf, 1024);
+        if (ino_len < 0) {
+            LOGE("inotify read error");
+            return 1;
+        }
+        (void)inotify_rm_watch(ino_fd, ino_wd);
+        (void)close(ino_fd);
+
+        fd = fopen("/sys/power/wake_unlock" , "r");
+        if(fd) {
+            while(fscanf(fd, "%99s", buf) != EOF) {
+                if (strstr(buf, "Display") != NULL) {
+                    fclose(fd);
+                    return 0;
+                }
+            }
+        } else {
+            LOGE("fopen error\n");
+            return 1;
+        }
+        fclose(fd);
+    }
+}
+
+static int flp_screen_send2mnl(const char* buff, int len) {
+    int ret = 0;
+    if (safe_sendto("flp_to_mnl", buff, len) < 0) {
+        LOGE("flp_screen_send2mnl safe_sendto flp failed\n");
+        ret = -1;
+    }
+    if (safe_sendto("gfc_to_mnl", buff, len) < 0) {
+        LOGE("flp_screen_send2mnl safe_sendto gfc failed\n");
+        ret = -1;
+    }
+    return ret;
+}
+
+static void* flp_screen_monitor_thread(void *arg) {
+    MTK_FLP_MSG_T *flp_header;
+    int ret, offset = 0;
+    char buff[HAL_FLP_BUFF_SIZE] = {0};
+    UNUSED(arg);
+
+    LOGE("Create\n");
+    while (1) {
+        LOGE("Wake Monitor Restart");
+        if (wait_for_fb_sleep()) {
+            LOGE("Failed reading wait_for_fb_sleep");
+            break;
+        }
+        pthread_mutex_lock(&earlysuspend_mutex);
+        earlysuspend_state = EARLYSUSPEND_MEM;
+        pthread_cond_signal(&earlysuspend_cond);
+        pthread_mutex_unlock(&earlysuspend_mutex);
+        LOGE("Screen off");
+
+        //Send NTF to CONNsys
+        offset = 0;
+        flp_header = malloc(sizeof(MTK_FLP_MSG_T) + sizeof(UINT8));
+        if (flp_header) {
+            flp_header->type = MTK_FLP_MSG_CONN_SCREEN_STATUS;
+            flp_header->length = sizeof(UINT8);
+            memcpy((char *)flp_header +sizeof(MTK_FLP_MSG_T),&earlysuspend_state, sizeof(UINT8));
+            put_binary(buff, &offset, (const char*)flp_header, (flp_header->length+sizeof(MTK_FLP_MSG_T)));
+            ret = flp_screen_send2mnl(buff, offset);
+            free(flp_header);
+        }
+
+        if (wait_for_fb_wake()) {
+            LOGE("Failed reading wait_for_fb_wake");
+            break;
+        }
+        pthread_mutex_lock(&earlysuspend_mutex);
+        earlysuspend_state = EARLYSUSPEND_ON;
+        pthread_cond_signal(&earlysuspend_cond);
+        pthread_mutex_unlock(&earlysuspend_mutex);
+        LOGE("Screen on");
+
+        offset = 0;
+        flp_header = malloc(sizeof(MTK_FLP_MSG_T) + sizeof(UINT8));
+        if (flp_header) {
+            flp_header->type = MTK_FLP_MSG_CONN_SCREEN_STATUS;
+            flp_header->length = sizeof(UINT8);
+            memcpy((char *)flp_header +sizeof(MTK_FLP_MSG_T),&earlysuspend_state, sizeof(UINT8));
+            put_binary(buff, &offset, (const char*)flp_header, (flp_header->length+sizeof(MTK_FLP_MSG_T)));
+            ret = flp_screen_send2mnl(buff, offset);
+            free(flp_header);
+        }
+    }
+
+    LOGE("exit\n");
+    pthread_exit(NULL);
+    return 0;
+}
+
+void mtk_flp_get_wake_monitor_state(UINT8 *state) {
+    if(state) {
+        memcpy(state, &earlysuspend_state, sizeof(UINT8));
+    }
+}
+
+void flp_monitor_init() {
+    pthread_t pthread_wakelock;
+    pthread_create(&pthread_wakelock, NULL, flp_screen_monitor_thread, NULL);
+}
+
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/inc/Geofence.h b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/inc/Geofence.h
new file mode 100644
index 0000000..d7bcb06
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/inc/Geofence.h
@@ -0,0 +1,134 @@
+#ifndef _GEOFENCE_H_
+#define _GEOFENCE_H_
+
+#include <time.h>
+#include <stdint.h>
+
+#if defined(__ANDROID_OS__)
+#include <hardware/gps.h>
+#include <hardware/fused_location.h>
+#elif defined(__LINUX_OS__)
+#include "gps.h"
+#include "fused_location.h"
+#endif
+
+#define GEO_CONFIG_MASK_DISABLE_SMD     (1U<<0)
+
+typedef enum {
+    inside,
+    outside,
+    uncertain
+} SET_STATE;
+
+typedef enum {
+    INIT_GEOFENCE,
+    ADD_GEOFENCE_AREA,
+    PAUSE_GEOFENCE,
+    RESUME_GEOFENCE,
+    REMOVE_GEOFENCE,
+    RECOVER_GEOFENCE,
+    CLEAR_GEOFENCE,
+} MTK_GFC_COMMAND_T;
+
+typedef enum {
+    SMART_NO_TRIGGER       = 0,
+    SMART_ACC_TRIGGER      = 1,
+    SMART_TIMEOUT_TRIGGER  = 2,
+} MTK_SMART_GEOFENCE_T;
+
+typedef enum {
+    MTK_GEOFENCE_IDLE_MODE = -1,
+    MTK_BATCH_GEOFENCE_ONLY = 3,
+    MTK_SMART_GEOFENCE_MODE = 4,
+} MTK_GFC_MODE_T;
+
+typedef enum {
+    GFC_AP_MODE      = 1,
+    GFC_OFFLOAD_MODE = 2,
+} MTK_GFC_SYS_MODE_T;
+
+typedef struct {
+    unsigned int type;
+    unsigned int session;
+    unsigned int length;
+} MTK_GFC_MNL_MSG_HEADER_T;
+
+typedef struct {
+    unsigned int type;   // 1:AP mode(default)   2: Offload mode  3:AP+Offload mode
+    unsigned int pre_type;
+    unsigned int id;
+} MTK_GFC_Session_T;
+
+typedef enum {
+    GEOFENCE_ADD_CALLBACK,
+    GEOFENCE_REMOVE_CALLBACK,
+    GEOFENCE_PAUSE_CALLBACK,
+    GEOFENCE_RESUME_CALLBACK
+} GEOFENCE_CALLBACK_T;
+
+typedef struct mtk_geofence_callback {
+    int32_t cb_id;
+    int32_t geofence_id;
+    int32_t result;
+} MTK_GEOFENCE_CALLBACK_T;
+
+typedef struct mtk_geofence_area {
+    int32_t geofence_id;
+    double latitude;
+    double longitude;
+    double radius;
+    float coordinate_dn;
+    float coordinate_de;
+    int last_transition; /*current state, most cases is GPS_GEOFENCE_UNCERTAIN*/
+    int monitor_transition; /*bitwise or of  entered/exited/uncertain*/
+    int notification_period;/*timer  interval, period of report transition status*/
+    int unknown_timer;/*continue positioning time limitied while positioning*/
+    int alive;/*geofence status, 1 alive, 0 sleep*/
+    SET_STATE latest_state;/*latest status: outside, inside, uncertain*/
+    uint32_t config;
+} MTK_GEOFENCE_PROPERTY_T;
+
+typedef struct mtk_pause_geofence {
+    int32_t geofence_id;
+} MTK_PAUSE_GEOFENCE_T;
+
+typedef struct mtk_resume_geofence {
+    int32_t geofence_id;
+    int transition;
+} MTK_RESUME_GEOFENCE_T;
+
+typedef struct mtk_remove_geofence {
+    int32_t geofence_id;
+} MTK_REMOVE_GEOFENCE_T;
+
+typedef struct mtk_modify_geofence {
+    int32_t geofence_id;
+    uint32_t source_to_use; /* source to use for geofence */
+    int last_transition; /*current state, most cases is GPS_GEOFENCE_UNCERTAIN*/
+    int monitor_transition; /*bitwise or of  entered/exited/uncertain*/
+    int notification_period;/*timer  interval, period of report transition status*/
+    int unknown_timer;/*continue positioning time limitied while positioning*/
+} MTK_MODIFY_GEOFENCE;
+
+typedef float          R4;      // 4 byte floating point
+typedef double         R8;      // 8 byte floating point
+
+typedef struct geofence_new_alarm {
+    unsigned int unknown_init_ttick;  //record the ttick of fence starting time
+    int unknown_elapsed_ttick;  //update the ttick elapsed time since the starting time
+    int geofence_operating_mode; //[start, stop/ pause] = [0,1]
+} GEOFENCE_NEW_ALARM_T;
+
+typedef enum {
+    START,
+    STOP,
+    UNKNOW
+} MTK_GEOFENCE_ACTION;
+
+//static int start_unknown_monitor(const int item);
+unsigned int update_fence_source();
+void mtk_flp_geofence_clear_geofences();
+void  mtk_set_geofence_location(const FlpLocation* location);
+
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/inc/mtk_geofence_main.h b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/inc/mtk_geofence_main.h
new file mode 100644
index 0000000..e39cea0
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/inc/mtk_geofence_main.h
@@ -0,0 +1,90 @@
+#ifndef MTK_GEOFENCE_H

+#define MTK_GEOFENCE_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"

+#include "mtk_flp_main.h"

+#include "mtk_auto_log.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

+

+

+//======================================================

+// GEOFENCE -> GPS/GEOFENCE HAL

+//======================================================

+#define GEOFENCE_TO_MNL "gfc_to_mnl"

+#define MNL_TO_GEOFENCE "mnl_to_gfc"

+

+#define MTK_GFC_SUCCESS     (0)

+#define MTK_GFC_ERROR       (-1)

+#define MTK_GFC_TIMEOUT     (-2)

+

+#define MNLD_GFC_CAPABILITY_AP_MODE      1

+#define MNLD_GFC_CAPABILITY_OFL_MODE     2

+#define MNLD_GFC_CAPABILITY_AP_OFL_MODE  3

+

+#define GFC_MNL_BUFF_SIZE   (1 * 1024)

+#define GFC_MNL_PAYLOAD_LEN 256

+

+typedef struct {

+    unsigned int type;

+    unsigned int session;

+    unsigned int length;

+    unsigned char  data[GFC_MNL_PAYLOAD_LEN];

+} MTK_GFC_MNL_MSG_T;

+

+typedef struct {

+    int (*mnld_gfc_attach)();

+    void (*mnld_gfc_hbd_gps_open)();

+    void (*mnld_gfc_hbd_gps_close)();

+    void (*mnld_gfc_ofl_link_open)();

+    void (*mnld_gfc_ofl_link_close)();

+    int (*mnld_gfc_ofl_link_send)();

+} gfc2mnl_interface;

+

+

+//Function Declarations

+extern MTK_GFC_Session_T mnld_gfc_session;

+

+int create_gfchal2mnl_fd();

+int mtk_hal2gfc_main_hdlr(int fd, gfc2mnl_interface* hdlr);

+int mnld_gfc_gen_new_session();

+int mnl2gfc_mnld_reboot();

+int mnl2gfc_data_send(unsigned char *buf, unsigned int len);

+int mnld_gfc_attach_done();

+int mnld_gfc_session_update();

+int mnld_gfc_ofl_gps_open_done();

+int mnld_gfc_hbd_gps_open_done();

+int mnld_gfc_ofl_gps_close_done();

+int mnld_gfc_hbd_gps_close_done();

+void mtk_gfc_set_sys_mode (unsigned int sysMode);

+int mtk_gfc_get_sys_mode ();

+int mnl2gfc_hdlr(MTK_GFC_MNL_MSG_T* prmsg);

+int gfc_kernel_2gfc_hdlr(MTK_FLP_MSG_T* prmsg);

+void mtk_gfc_ofl2mnl_process(MTK_FLP_MSG_T *prmsg);

+int mtk_gfc_controller_reset_status(void);

+int mtk_gfc_controller_process(MTK_FLP_MSG_T *prmsg);

+int gfc2mnl_hdlr(MTK_GFC_MNL_MSG_T  *prMsg);

+int mnl_send2gfc(const char* buff, int len);

+

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

+

diff --git a/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_controller.c b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_controller.c
new file mode 100644
index 0000000..c5c1895
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_controller.c
@@ -0,0 +1,500 @@
+#include "mtk_geofence_main.h"
+#include "mtk_flp_main.h"
+#include "data_coder.h"
+#include "mtk_auto_log.h"
+
+#if defined(__ANDROID_OS__)
+#include <hardware/gps.h>
+#elif defined(__LINUX_OS__)
+#include "gps.h"
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "gps_dbg_log"
+#endif
+
+#define ONE_SEC_NS 1000000000
+#define FLP_TECH_MASK_GNSS      (1U<<0)
+#define MAX_GFC_BATCHING_MSG   100
+
+/**********************************************************
+*  Global vars                                           *
+**********************************************************/
+static unsigned int fgMnldGfcStatus = MNL_STATUS_NONE;
+static unsigned int gCurrentSession = 0;
+static unsigned int gCurrentSupport = 0;
+static unsigned int geofence_enabled = 0;
+static unsigned int flp_geofence_source = 0;
+static int gfc_mode = MTK_GEOFENCE_IDLE_MODE;
+static int32_t geofence_in_use = 0;
+static uint32_t geofence_source_to_use = 0;
+static float current_gnss_acc = 0;
+char pGFCVersion[] = {GEOFENCE_VER_INFO,0x00};
+static MTK_GFC_MNL_MSG_T gGfc2mnl_msg[MAX_GFC_BATCHING_MSG];
+static int gGfc2mnl_cnt = 0;
+
+/**********************************************************
+*  Function Declaration                                  *
+**********************************************************/
+extern void mtk_geofence_offload_main(MTK_FLP_MSG_T *prmsg);
+extern void mtk_flp_geofence_expire();
+
+/************************************************************************/
+//  Process msgs from GPS/GFC HAL and send to offload kernel
+/************************************************************************/
+void mtk_gfc_ofl2mnl_process(MTK_FLP_MSG_T *prmsg) {
+    MTK_GFC_MNL_MSG_HEADER_T* gfc2mnl_msg = NULL;
+    if (prmsg->type == MTK_FLP_MSG_CONN_SCREEN_STATUS) {
+        if(fgMnldGfcStatus == MNL_STATUS_OFL_LINK_OPEN_DONE) {
+            gfc2mnl_msg = (MTK_GFC_MNL_MSG_HEADER_T *)malloc( sizeof(MTK_FLP_MNL_MSG_HEADER_T)+ sizeof(MTK_FLP_MSG_T)+prmsg->length);
+            if(gfc2mnl_msg != NULL) {
+                gfc2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_SEND;
+                gfc2mnl_msg->session = gCurrentSession;
+                gfc2mnl_msg->length = (prmsg->length) + sizeof(MTK_FLP_MSG_T);
+                memcpy(((char*)gfc2mnl_msg)+sizeof(MTK_FLP_MNL_MSG_HEADER_T), ((char*)prmsg), (sizeof(MTK_FLP_MSG_T)+ (prmsg->length)));
+                gfc2mnl_hdlr((MTK_GFC_MNL_MSG_T *)gfc2mnl_msg);
+                free(gfc2mnl_msg);
+            }
+        } else {
+            LOGD("free screen dbg");
+        }
+        return;
+    }
+    if (fgMnldGfcStatus != MNL_STATUS_OFL_LINK_OPEN_DONE) {
+        if (gGfc2mnl_cnt == 0) {
+            //send init message to mnld first
+            gfc2mnl_msg = (MTK_GFC_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_GFC_MNL_MSG_HEADER_T));
+            //send header only, no message body
+            if(gfc2mnl_msg != NULL) {
+                gfc2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_OPEN;
+                gfc2mnl_msg->session = gCurrentSession;
+                gfc2mnl_msg->length = 0;
+                LOGD("MNLD_FLP_TYPE_OFL_LINK_OPEN");
+                fgMnldGfcStatus = MNL_STATUS_OFL_LINK_OPEN;
+                gfc2mnl_hdlr((MTK_GFC_MNL_MSG_T *)gfc2mnl_msg);
+                free(gfc2mnl_msg);
+            }
+        }
+        if (gGfc2mnl_cnt < MAX_GFC_BATCHING_MSG) {
+            gGfc2mnl_msg[gGfc2mnl_cnt].type = MNLD_FLP_TYPE_OFL_LINK_SEND;
+            gGfc2mnl_msg[gGfc2mnl_cnt].length = prmsg->length + sizeof(MTK_FLP_MSG_T);
+            gGfc2mnl_msg[gGfc2mnl_cnt].session = gCurrentSession;
+            memcpy(&gGfc2mnl_msg[gGfc2mnl_cnt].data[0], ((char*)prmsg), (sizeof(MTK_FLP_MSG_T)+ prmsg->length));
+            gGfc2mnl_cnt++;
+            LOGD("Keep gfc data cnt %d", gGfc2mnl_cnt);
+        } else {
+            LOGD("Batching size overflow");
+        }
+    } else {
+        //send flp message to ofl gfc
+        gfc2mnl_msg = (MTK_GFC_MNL_MSG_HEADER_T *)malloc( sizeof(MTK_GFC_MNL_MSG_HEADER_T)+sizeof(MTK_FLP_MSG_T)+prmsg->length);
+        if(gfc2mnl_msg != NULL) {
+            gfc2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_SEND;
+            gfc2mnl_msg->session = gCurrentSession;
+            gfc2mnl_msg->length = prmsg->length + sizeof(MTK_FLP_MSG_T);
+            memcpy( ((char*)gfc2mnl_msg)+sizeof(MTK_GFC_MNL_MSG_HEADER_T), ((char*)prmsg), (sizeof(MTK_FLP_MSG_T)+ prmsg->length));
+            LOGD("Send to OFL GFC,message type:0x%02x, len:%u", prmsg->type, (gfc2mnl_msg->length + sizeof(MTK_GFC_MNL_MSG_HEADER_T)));
+            gfc2mnl_hdlr((MTK_GFC_MNL_MSG_T *)gfc2mnl_msg);
+            free(gfc2mnl_msg);
+        }
+    }
+    return;
+}
+
+int mtk_gfc_controller_query_mode () {
+    return gfc_mode;
+}
+
+float mtk_flp_controller_get_current_acc() {
+    return current_gnss_acc;
+}
+
+void mtk_smart_geofence_entry(int mode, unsigned int duration_sec) {
+    LOGD("Smart geofence entry mode:%d timeout:%u", mode, duration_sec);
+    gfc_mode = mode;
+}
+
+void mtk_smart_geofence_exit() {
+    gfc_mode = MTK_BATCH_GEOFENCE_ONLY;
+}
+
+static int mtk_loc_check(GpsLocation* gpsloc, MTK_FLP_LOCATION_T *flploc) {
+    if (gpsloc == NULL || flploc == NULL) {
+        return MTK_GFC_ERROR;
+    }
+    memcpy(flploc, gpsloc, sizeof(GpsLocation));
+    flploc->size = sizeof(MTK_FLP_LOCATION_T);
+    flploc->sources_used = FLP_TECH_MASK_GNSS;
+    flploc->accuracy = 1.7*(gpsloc->accuracy); //convert accuracy from 67% to 95%
+    flploc->altitude = gpsloc->altitude;
+    flploc->bearing = gpsloc->bearing;
+    flploc->flags =gpsloc->flags;
+    flploc->latitude = gpsloc->latitude;
+    flploc->longitude = gpsloc->longitude;
+    flploc->speed = gpsloc->speed;
+    flploc->timestamp = gpsloc->timestamp;//mtk_flp_get_timestamp(NULL);
+#if 0
+    LOGD("[DC_GNSS]:dc2gnss: acc:%.4f,alt:%.4f,bearing:%.4f,flag:%d,lat:%.4f,lon:%.4f,spd:%.4f",
+    flploc->accuracy,flploc->altitude,flploc->bearing,flploc->flags,flploc->latitude,
+    flploc->longitude,flploc->speed);
+#endif
+    return MTK_GFC_SUCCESS;
+}
+
+/************************************************************************/
+//  Process msgs from GFC HAL and send to offload kernel
+/************************************************************************/
+int mtk_gfc2mnl_process(MTK_FLP_MSG_T *prmsg) {
+    MTK_GFC_MNL_MSG_HEADER_T* gfc2mnl_msg = NULL;
+    if(prmsg == NULL) {
+        LOGE("mtk_gfc2mnl_process, recv prmsg is null pointer\n");
+        return MTK_GFC_ERROR;
+    }
+    //LOGD("mtk_gfc2mnl_process, recv prmsg, type: 0x%02x, len:%u status:%u\r\n", prmsg->type, prmsg->length, fgMnldGfcStatus);
+    switch(prmsg->type) {
+        case MTK_FLP_MSG_DC_START_CMD: // host-based start gnss
+            //send init message to mnld first
+            gfc2mnl_msg = (MTK_GFC_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_GFC_MNL_MSG_HEADER_T));
+            //send header only, no message body
+            if(gfc2mnl_msg != NULL) {
+                gfc2mnl_msg->type = MNLD_FLP_TYPE_HBD_GPS_OPEN;
+                gfc2mnl_msg->length = 0;
+                gfc2mnl_msg->session = gCurrentSession;
+                LOGD("MNLD_FLP_TYPE_HBD_GPS_OPEN");
+                fgMnldGfcStatus = MNL_STATUS_HBD_GPS_OPEN;
+                gfc2mnl_hdlr((MTK_GFC_MNL_MSG_T *)gfc2mnl_msg);
+                free(gfc2mnl_msg);
+            }
+            break;
+        case MTK_FLP_MSG_DC_STOP_CMD:
+            //send stop message to mnld
+            gfc2mnl_msg = (MTK_GFC_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_GFC_MNL_MSG_HEADER_T));
+            //send header only, no message body
+            if(gfc2mnl_msg != NULL) {
+                gfc2mnl_msg->type = MNLD_FLP_TYPE_HBD_GPS_CLOSE;
+                gfc2mnl_msg->length = 0;
+                gfc2mnl_msg->session = gCurrentSession;
+                //LOGD("Send to mnld for deinit,message type:0x%02x, len:%d", gfc2mnl_msg->type, gfc2mnl_msg->length);
+                fgMnldGfcStatus = MNL_STATUS_HBD_GPS_CLOSE;
+                gfc2mnl_hdlr((MTK_GFC_MNL_MSG_T *)gfc2mnl_msg);
+                free(gfc2mnl_msg);
+            }
+            break;
+    }
+    return MTK_GFC_SUCCESS;
+}
+
+void mtk_gfc_controller_update_option() {
+    unsigned int local_source = 0;
+    unsigned int new_source = 0;
+    MTK_FLP_MSG_T *flp_cmd;
+    MTK_FLP_BATCH_OPTION_T batch_option;
+    //assign stop command;
+    memset(&batch_option,0,sizeof(MTK_FLP_BATCH_OPTION_T));
+    local_source = flp_geofence_source;
+    new_source = geofence_source_to_use;
+    if(local_source != new_source) {
+        if((local_source == 0) && (new_source == 1)) {
+            //new req is open dc_xxx
+            current_gnss_acc = 0;
+            flp_cmd = malloc(sizeof(MTK_FLP_BATCH_OPTION_T)+ sizeof(MTK_FLP_MSG_T));
+            if(flp_cmd != NULL) {
+                flp_cmd->type = MTK_FLP_MSG_DC_START_CMD;
+                flp_cmd->length = sizeof(MTK_FLP_BATCH_OPTION_T);
+                batch_option.flags = gfc_mode;
+                batch_option.max_power_allocation_mW = 0;
+                batch_option.period_ns = ONE_SEC_NS;
+                batch_option.sources_to_use = FLP_TECH_MASK_GNSS;
+                memcpy((INT8 *)flp_cmd + sizeof(MTK_FLP_MSG_T), &batch_option, sizeof(MTK_FLP_BATCH_OPTION_T));
+                mtk_gfc2mnl_process(flp_cmd);
+                free(flp_cmd);
+            } else {
+                LOGE("open DC: malloc failed");
+            }
+        } else if((local_source == 1) && (new_source == 0)) {
+            //new req is close dc_xxx
+            flp_cmd = malloc(sizeof(MTK_FLP_MSG_T));
+            if(flp_cmd != NULL) {
+                flp_cmd->type = MTK_FLP_MSG_DC_STOP_CMD;
+                flp_cmd->length = 0;
+                mtk_gfc2mnl_process(flp_cmd);
+                free(flp_cmd);
+            } else {
+                LOGE("close DC malloc failed");
+            }
+        }
+    }
+    flp_geofence_source = geofence_source_to_use;
+}
+
+int mtk_gfc_controller_reset_status(void) {
+    geofence_enabled = 0;
+    gfc_mode = MTK_GEOFENCE_IDLE_MODE;
+    geofence_in_use = 0;
+    geofence_source_to_use = 0;
+    current_gnss_acc = 0;
+    flp_geofence_source = 0;
+#if defined(__ANDROID_OS__)
+    mtk_flp_geofence_clear_geofences();
+#endif
+    return MTK_GFC_SUCCESS;
+}
+
+int mtk_gfc_controller_process(MTK_FLP_MSG_T *prmsg) {
+    MTK_FLP_MSG_T *geofence_msg = NULL;
+    MTK_GEOFENCE_PROPERTY_T geofence_input;
+    int32_t fence_num;
+    if(prmsg == NULL) {
+        LOGE("mtk_gfc_controller_process, recv prmsg is null pointer\r\n");
+        return MTK_GFC_ERROR;
+    }
+    LOGD("mtk_gfc_controller_process, recv prmsg, type:%d, len:%d\r\n", prmsg->type, prmsg->length);
+    switch( prmsg->type ) {
+        case MTK_FLP_MSG_OFL_GEOFENCE_CMD:
+            geofence_msg = malloc((prmsg->length)-sizeof(MTK_FLP_MSG_T));
+            if(geofence_msg != NULL ) {
+                memcpy( geofence_msg, ((char*)prmsg)+sizeof(MTK_FLP_MSG_T), ((prmsg->length)-sizeof(MTK_FLP_MSG_T)));
+                if(geofence_enabled) {
+                    if (mtk_gfc_controller_query_mode() > MTK_BATCH_GEOFENCE_ONLY) {
+                        LOGD("DEV_GEO: Smart geofence exit from geofence");
+                        mtk_smart_geofence_exit();
+                    }
+                }
+#if defined(__ANDROID_OS__)
+                mtk_geofence_offload_main(geofence_msg);
+#endif
+                if( (geofence_msg->type == ADD_GEOFENCE_AREA) || (geofence_msg->type == RECOVER_GEOFENCE) ) {
+                    LOGD("%s", pGFCVersion);
+                    memcpy(&fence_num, ((char *)geofence_msg + sizeof(MTK_FLP_MSG_T)), sizeof(int32_t));
+                    memcpy(&geofence_input, ((char *)geofence_msg + sizeof(MTK_FLP_MSG_T)+sizeof(int32_t)),sizeof(MTK_GEOFENCE_PROPERTY_T));
+                    if (geofence_in_use > 0) {
+#if defined(__ANDROID_OS__)
+                        geofence_source_to_use = update_fence_source();
+#endif
+                    } else {
+                        // first fence
+                        geofence_source_to_use = 1;
+                    }
+                    if (geofence_in_use == 0) {
+                        gfc_mode = MTK_BATCH_GEOFENCE_ONLY;
+                    }
+                    mtk_gfc_controller_update_option();
+                    geofence_enabled = 1;
+                    geofence_in_use++;
+                } else if(geofence_msg->type == REMOVE_GEOFENCE ) {
+                    memcpy( &fence_num, ((char *)geofence_msg + sizeof(MTK_FLP_MSG_T)), sizeof(int32_t));
+                    if(geofence_in_use > 0) {
+                        geofence_in_use -= 1;
+                    }
+#if defined(__ANDROID_OS__)
+                    geofence_source_to_use = update_fence_source();
+#endif
+                    mtk_gfc_controller_update_option();
+                    if( geofence_in_use == 0 ) {
+                        geofence_enabled = 0;
+                        gfc_mode = MTK_GEOFENCE_IDLE_MODE;
+                    }
+                } else if(geofence_msg->type == CLEAR_GEOFENCE) {
+                    geofence_in_use = 0;
+                    geofence_enabled = 0;
+                    geofence_source_to_use = 0;
+                    mtk_gfc_controller_update_option();
+                    gfc_mode = MTK_GEOFENCE_IDLE_MODE;
+                }
+                free(geofence_msg);
+            }
+            break;
+        default:
+            LOGE("unknown cmd:0x%02x",prmsg->type);
+            break;
+    }
+    return MTK_GFC_SUCCESS;
+}
+
+/************************************************************************/
+//  Handle MNL Response                                                 */
+/************************************************************************/
+int mnl2gfc_hdlr(MTK_GFC_MNL_MSG_T* prmsg) {
+    char buff[GFC_MNL_BUFF_SIZE] = {0};
+    int ret, i;
+    int offset = 0;
+    MTK_GFC_MNL_MSG_HEADER_T *gfc2mnl_msg;
+    MTK_FLP_MSG_T *gfc2hal_msg;
+    MTK_FLP_MSG_T *cnn2gfc_msg;
+    GpsLocation  *gps_loc;
+    FlpLocation  flp_loc;
+
+    if(prmsg == NULL) {
+        LOGE("mnl2gfc_hdlr recv null msg");
+        return MTK_GFC_ERROR;
+    }
+    LOGD("mtk_mnl2gfc_recv_msg type = %u, session = %u, len = %u, state = %u\n",  prmsg->type, prmsg->session, prmsg->length, fgMnldGfcStatus);
+    switch(prmsg->type) {
+        case MNLD_FLP_TYPE_MNL_BOOTUP:
+            fgMnldGfcStatus = MNL_STATUS_ATTACH_DONE;
+            gfc2hal_msg = malloc(sizeof(MTK_FLP_MSG_T));
+            if(gfc2hal_msg == NULL) {
+                LOGE("reset ntf malloc failed");
+                return MTK_FLP_ERROR;
+            }
+            gfc2hal_msg->type = MTK_FLP_MSG_SYS_FLPD_RESET_NTF;
+            gfc2hal_msg->length = 0;
+            put_binary(buff, &offset, (const char*)gfc2hal_msg, sizeof(MTK_FLP_MSG_T));
+            ret = mnl_send2gfc(buff, offset);
+            free(gfc2hal_msg);
+            if(ret < 0) {
+                LOGD("mnl2gfc_hdlr send error return error");
+            }
+            break;
+        case MNLD_FLP_TYPE_SESSION_UPDATE:
+            gCurrentSession = prmsg->session;
+            memcpy(&gCurrentSupport, ((char*)prmsg)+sizeof(MTK_GFC_MNL_MSG_HEADER_T), sizeof(gCurrentSupport));
+            LOGD("SESSION_UPDATE %u support %u mode %u", gCurrentSession, gCurrentSupport, fgMnldGfcStatus);
+            if (fgMnldGfcStatus == MNL_STATUS_HBD_GPS_OPEN_DONE && gCurrentSupport == GFC_AP_MODE) {
+                LOGD("SESSION_UPDATE: already run on host");
+            } else if (fgMnldGfcStatus == MNL_STATUS_OFL_LINK_OPEN_DONE && (gCurrentSupport & GFC_OFFLOAD_MODE)) {
+                LOGD("SESSION_UPDATE: already run on offlaod");
+            } else if (fgMnldGfcStatus == MNL_STATUS_HBD_GPS_OPEN_DONE && (gCurrentSupport & GFC_OFFLOAD_MODE)) {
+                LOGD("SESSION_UPDATE: switch to ofl mode");
+                mtk_gfc_controller_reset_status();
+                mtk_gfc_set_sys_mode(GFC_OFFLOAD_MODE);
+                gfc2hal_msg = malloc(sizeof(MTK_FLP_MSG_T));
+                if(gfc2hal_msg == NULL) {
+                    LOGE("reset ntf malloc failed");
+                    return MTK_FLP_ERROR;
+                }
+                gfc2hal_msg->type = MTK_FLP_MSG_SYS_FLPD_RESET_NTF;
+                gfc2hal_msg->length = 0;
+                put_binary(buff, &offset, (const char*)gfc2hal_msg, sizeof(MTK_FLP_MSG_T));
+                ret = mnl_send2gfc(buff, offset);
+                free(gfc2hal_msg);
+                if(ret < 0) {
+                    LOGE("mnl2gfc_hdlr send error return error");
+                }
+            } else if (fgMnldGfcStatus == MNL_STATUS_OFL_LINK_OPEN_DONE && (gCurrentSupport == GFC_AP_MODE)) {
+                LOGD("SESSION_UPDATE: switch to ap mode");
+                mtk_gfc_set_sys_mode(GFC_AP_MODE);
+                gfc2hal_msg = malloc(sizeof(MTK_FLP_MSG_T));
+                if(gfc2hal_msg == NULL) {
+                    LOGE("reset ntf malloc failed");
+                    return MTK_FLP_ERROR;
+                }
+                gfc2hal_msg->type = MTK_FLP_MSG_SYS_FLPD_RESET_NTF;
+                gfc2hal_msg->length = 0;
+                put_binary(buff, &offset, (const char*)gfc2hal_msg, sizeof(MTK_FLP_MSG_T));
+                ret = mnl_send2gfc(buff, offset);
+                free(gfc2hal_msg);
+                if(ret < 0) {
+                    LOGE("mnl2gfc_hdlr send error return error");
+                }
+            } else {
+                if (gCurrentSupport & GFC_OFFLOAD_MODE) {
+                    mtk_gfc_set_sys_mode(GFC_OFFLOAD_MODE);
+                    LOGD("SESSION_UPDATE: set offload mode");
+                } else if (gCurrentSupport == GFC_AP_MODE) {
+                    mtk_gfc_set_sys_mode(GFC_AP_MODE);
+                    LOGD("SESSION_UPDATE: set ap mode");
+                }
+            }
+            break;
+        case MNLD_FLP_TYPE_HBD_GPS_LOCATION:
+            if (!flp_geofence_source) {
+                LOGE("bypass loc - no source open");
+                return MTK_GFC_ERROR;
+            }
+            gps_loc = (GpsLocation *)(((char*)prmsg)+sizeof(MTK_GFC_MNL_MSG_HEADER_T));
+            //LOGD("GNSS LOC DBG: %f, %lf, %lf, %d", gps_loc->accuracy, gps_loc->latitude, gps_loc->longitude, gps_loc->size);
+            if(mtk_loc_check(gps_loc, (MTK_FLP_LOCATION_T *)&flp_loc) != MTK_GFC_SUCCESS) {
+                LOGE("Incorrect data received");
+            } else {
+                if (geofence_enabled) {
+#if defined(__ANDROID_OS__)
+                    mtk_flp_geofence_expire();
+#endif
+                    current_gnss_acc = flp_loc.accuracy;
+                    if (flp_loc.accuracy < 0.001) {
+                        LOGE("bypass loc - loc no fix");
+                        return MTK_GFC_ERROR;
+                    }
+#if defined(__ANDROID_OS__)
+                    mtk_set_geofence_location(&flp_loc);
+#endif
+                    //LOGD("Location,LNG:%f LAT:%f ALT:%f ACC:%f SPD:%f BEARING:%f, FLAGS:%04X SOURCES:%08X Timestamp:%lld",
+                    //    flp_loc.longitude, flp_loc.latitude, flp_loc.altitude, flp_loc.accuracy,
+                    //    flp_loc.speed, flp_loc.bearing, flp_loc.flags, flp_loc.sources_used, flp_loc.timestamp);
+                }
+            }
+            break;
+        case MNLD_FLP_TYPE_OFL_LINK_RECV:
+            cnn2gfc_msg = malloc(prmsg->length);
+            if(cnn2gfc_msg == NULL) {
+                LOGE("cnn2gfc_msg malloc failed");
+                return MTK_GFC_ERROR;
+            }
+            memcpy((char*)cnn2gfc_msg, ((char*)prmsg)+ sizeof(MTK_GFC_MNL_MSG_HEADER_T), prmsg->length);
+            //LOGD("Received OFFLOAD message type: 0x%02x, len = %u", cnn2gfc_msg->type, cnn2gfc_msg->length);
+            switch(cnn2gfc_msg->type) {
+                case MTK_FLP_MSG_HAL_STOP_RSP:
+                    //send stop message to mnld
+                    gfc2mnl_msg = (MTK_GFC_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_GFC_MNL_MSG_HEADER_T));
+                    if(gfc2mnl_msg!= NULL) {
+                        gfc2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_CLOSE;
+                        gfc2mnl_msg->session= gCurrentSession;
+                        gfc2mnl_msg->length = 0;
+                        LOGD("Send to mnld for deinit,message type:%u, len:%u", gfc2mnl_msg->type, gfc2mnl_msg->length);
+                        gfc2mnl_hdlr((MTK_GFC_MNL_MSG_T *)gfc2mnl_msg);
+                        fgMnldGfcStatus = MNL_STATUS_OFL_LINK_CLOSE;
+                        LOGD("mnld deinit success");
+                        free(gfc2mnl_msg);
+                    }
+                    break;
+                case MTK_FLP_MSG_HAL_GEOFENCE_CALLBACK_NTF:
+                case MTK_FLP_MSG_OFL_GEOFENCE_CALLBACK_NTF:
+                    put_binary(buff, &offset, (const char*)cnn2gfc_msg, sizeof(MTK_FLP_MSG_T)+cnn2gfc_msg->length);
+                    ret = mnl_send2gfc(buff, offset);
+                    if(ret < 0) {
+                        LOGE("MTK_GFC2HAL send error return error");
+                    }
+                    break;
+                default:
+                    LOGE("mnl2gfc_hdlr unrecognize msg 0x%02x",cnn2gfc_msg->type);
+                    break;
+            }
+            free(cnn2gfc_msg);
+            break;
+        case MNLD_FLP_TYPE_HBD_GPS_OPEN_DONE:
+            fgMnldGfcStatus = MNL_STATUS_HBD_GPS_OPEN_DONE;
+            LOGD("MNLD_FLP_TYPE_HBD_GPS_OPEN_DONE");
+            break;
+        case MNLD_FLP_TYPE_HBD_GPS_CLOSE_DONE:
+            fgMnldGfcStatus = MNL_STATUS_HBD_GPS_CLOSE_DONE;
+            LOGD("MNL_STATUS_HBD_GPS_CLOSE_DONE");
+            break;
+        case MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE:
+            if (fgMnldGfcStatus == MNL_STATUS_OFL_LINK_OPEN) {
+                fgMnldGfcStatus = MNL_STATUS_OFL_LINK_OPEN_DONE;
+                LOGD("MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE flush %d", gGfc2mnl_cnt);
+                for (i = 0; i < gGfc2mnl_cnt; i++) {
+                    gfc2mnl_hdlr(&gGfc2mnl_msg[i]);
+                }
+                gGfc2mnl_cnt = 0;
+            } else {
+                LOGD("GFC_DBG: mnld state expect 7, get %u", fgMnldGfcStatus);
+            }
+            LOGD("MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE");
+            break;
+        case MNLD_FLP_TYPE_OFL_LINK_CLOSE_DONE:
+            fgMnldGfcStatus = MNL_STATUS_OFL_LINK_CLOSE_DONE;
+            LOGD("MNLD_FLP_TYPE_OFL_LINK_CLOSE_DONE");
+            break;
+        case MNLD_FLP_TYPE_FLP_ATTACH_DONE:
+            fgMnldGfcStatus = MNL_STATUS_ATTACH_DONE;
+            LOGD("MNL_STATUS_ATTACH_DONE");
+            break;
+        default:
+            LOGE("undefined cmd:0x%02x",prmsg->type);
+            break;
+    }
+    return MTK_GFC_SUCCESS;
+}
diff --git a/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_main.c b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_main.c
new file mode 100644
index 0000000..5e2ddd8
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_main.c
@@ -0,0 +1,500 @@
+#include <string.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <errno.h>

+#include <unistd.h>

+#include <fcntl.h>

+#include <sys/socket.h>

+#include <sys/types.h>

+#include <sys/stat.h>

+#include <sys/un.h>

+

+#include "mtk_geofence_main.h"

+#include "data_coder.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "gps_dbg_log"

+#endif

+

+/**********************************************************

+ *  Define                                                *

+ **********************************************************/

+#define GEOFENCE_INJECT_LOC_ENUM 600

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

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

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

+                                     }while(0)

+

+

+/**********************************************************

+ *  Global vars                                           *

+ **********************************************************/

+gfc2mnl_interface* gfc2mnl_hdlr_cb;

+static unsigned int gModeFlag = GFC_AP_MODE;

+static char g_mnl2gfc_path[128] = MNL_TO_GEOFENCE;

+//static char g_gfc2mnl_path[128] = GEOFENCE_TO_MNL;

+

+

+MTK_GFC_Session_T mnld_gfc_session = {

+    .type = MNLD_GFC_CAPABILITY_AP_MODE,

+    .pre_type = MNLD_GFC_CAPABILITY_AP_MODE,

+    .id = 1,

+};

+

+/**********************************************************

+ *  Socket Function                                       *

+ **********************************************************/

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

+    int retry = 10;

+

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

+    soc_addr.sun_path[0] = 0;

+    MNLD_STRNCPY(soc_addr.sun_path + 1, dest,sizeof(soc_addr.sun_path) - 1);

+    soc_addr.sun_family = AF_UNIX;

+

+    while ((len = sendto(sockfd, buf, size, 0,(const struct sockaddr *)&soc_addr,sizeof(soc_addr))) == -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;

+}

+

+int mnl_send2gfc(const char* buff, int len) {

+    int ret = 0;

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

+

+    if (sockfd < 0) {

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

+            strerror(errno), errno);

+        return -1;

+    }

+

+    if (safe_sendto(sockfd, g_mnl2gfc_path, buff, len) < 0) {

+        LOGE("mnl_send2gfc safe_sendto failed\n");

+        ret = -1;

+    }

+    close(sockfd);

+    return ret;

+}

+

+static int bind_udp_socket(char* path) {

+    int sockfd;

+    struct sockaddr_un soc_addr;

+

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

+    if (sockfd < 0) {

+        LOGE("socket failed reason=[%s]\n", strerror(errno));

+        return -1;

+    }

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

+    soc_addr.sun_path[0] = 0;

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

+    soc_addr.sun_family = AF_UNIX;

+    unlink(soc_addr.sun_path);

+    if (bind(sockfd, (struct sockaddr *)&soc_addr, sizeof(soc_addr)) < 0) {

+        LOGE("bind failed path=[%s] reason=[%s]\n", path, strerror(errno));

+        close(sockfd);

+        return -1;

+    }

+

+    return sockfd;

+}

+

+

+/*********************************************************/

+/* GPS HAL to mnl_geofence socket                        */

+/*********************************************************/

+int create_gfchal2mnl_fd() {

+    int fd = bind_udp_socket(GEOFENCE_TO_MNL);

+    set_socket_blocking(fd, 0);

+    return fd;

+}

+

+/*********************************************************/

+/* MNLD Response                                         */

+/*********************************************************/

+int mnld_gfc_ofl_gps_open_done() {

+    LOGD("mnld_gfc_ofl_gps_open_done");

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];

+

+    prMsg->type = MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE;

+    prMsg->length = 0;

+    prMsg->session = mnld_gfc_session.id;

+    return mnl2gfc_hdlr(prMsg);

+}

+

+int mnld_gfc_hbd_gps_open_done() {

+    LOGD("mnld_gfc_hbd_gps_open_done");

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];

+

+    prMsg->type = MNLD_FLP_TYPE_HBD_GPS_OPEN_DONE;

+    prMsg->length = 0;

+    prMsg->session = mnld_gfc_session.id;

+    return mnl2gfc_hdlr(prMsg);

+}

+

+int mnld_gfc_ofl_gps_close_done() {

+    LOGD("mnld_gfc_ofl_gps_close_done");

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];

+

+    prMsg->type = MNLD_FLP_TYPE_OFL_LINK_CLOSE_DONE;

+    prMsg->length = 0;

+    prMsg->session = mnld_gfc_session.id;

+    return mnl2gfc_hdlr(prMsg);

+}

+

+int mnld_gfc_hbd_gps_close_done() {

+    LOGD("mnld_gfc_hbd_gps_close_done");

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];

+

+    prMsg->type = MNLD_FLP_TYPE_HBD_GPS_CLOSE_DONE;

+    prMsg->length = 0;

+    prMsg->session = mnld_gfc_session.id;

+    return mnl2gfc_hdlr(prMsg);

+}

+

+int mnld_gfc_attach_done() {

+    LOGD("mnld_gfc_attach_done");

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];

+

+    prMsg->type = MNLD_FLP_TYPE_FLP_ATTACH_DONE;

+    prMsg->length = 0;

+    prMsg->session = mnld_gfc_session.id;

+    return mnl2gfc_hdlr(prMsg);

+}

+

+

+int mnld_gfc_session_update() {

+    LOGD("mnld_gfc_session_update,id=%d,type=%d",mnld_gfc_session.id,mnld_gfc_session.type);

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    int * payload = NULL;

+    MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];

+

+    prMsg->type = MNLD_FLP_TYPE_SESSION_UPDATE;

+    prMsg->length = sizeof(int);

+    prMsg->session = mnld_gfc_session.id;

+    payload = (int *)&prMsg->data[0];

+    *payload = mnld_gfc_session.type;

+    return mnl2gfc_hdlr(prMsg);

+}

+

+int mnld_gfc_gen_new_session() {

+    mnld_gfc_session.id++;

+    if (mnld_gfc_session.id >= 0xFFFFFFFF) {

+        mnld_gfc_session.id = 0;

+        LOGW("Session id overflow!!");

+    }

+    return mnld_gfc_session.id;

+}

+

+int mnl2gfc_mnld_reboot() {

+    LOGD("mnl2gfc_mnld_reboot");

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    int * payload = NULL;

+    MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];

+

+    if (mnld_gfc_session_update() == -1) {

+        LOGE("mnld_main_thread() mnld_gfc_session_update failed");

+    }

+    prMsg->type = MNLD_FLP_TYPE_MNL_BOOTUP;

+    prMsg->session = mnld_gfc_session.id;

+    prMsg->length = sizeof(int);

+    payload = (int *)&prMsg->data[0];

+    *payload = FLP_MNL_INTERFACE_VERSION;

+    return mnl2gfc_hdlr(prMsg);

+}

+

+int mnl2gfc_data_send(unsigned char *buf, unsigned int len) {

+    int ret = MTK_GFC_ERROR;

+    if(len >0) {

+        ret = mnl2gfc_hdlr((MTK_GFC_MNL_MSG_T *)buf);

+    } else {

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

+    }

+    return ret;

+}

+

+void mtk_gfc_set_sys_mode (unsigned int sysMode) {

+    if(sysMode == GFC_AP_MODE || sysMode == GFC_OFFLOAD_MODE)

+    {

+        gModeFlag = sysMode;

+        LOGD("mtk_gfc_set_sys_mode success = %d", gModeFlag);

+    } else {

+        LOGE("mtk_gfc_set_sys_mode error = %d", sysMode);

+    }

+}

+

+

+int mtk_gfc_get_sys_mode () {

+    return gModeFlag;

+}

+

+#define MAX_DUMP_CHAR 128

+/*********************************************************/

+/* Geofence Debug Function                               */

+/*********************************************************/

+void mnl_gfc_dump_buf(char *p, int len) {

+    int i, r, n;

+    char str[MAX_DUMP_CHAR] = {0};

+    for (i = 0, n = 0; i < len ; i++) {

+        r = snprintf(&str[n], MAX_DUMP_CHAR - n, "%3d,", p[i]);

+        if (r + n >= MAX_DUMP_CHAR || r <= 0) {

+            LOGE("[GFC2MNLD]data from gfc: data=%s, error return", str);

+            return;

+        }

+

+        n += r;

+        if ((i % 8 == 7) || i + 1 == len) {

+            LOGD("[GFC2MNLD]data from gfc: data=%s", str);

+            n = 0;

+            str[0] = '0';

+        }

+    }

+}

+

+//********************************************************************************

+//

+// mtk_hal2gfc_main_hdlr(): Geofence main function to process CMD from GPS/GFC HAL

+//

+// CMD from FWK: GPS JNI --> GFC HAL --> Mnld main --> mtk_hal2gfc_main_hdlr

+//********************************************************************************

+int mtk_hal2gfc_main_hdlr(int fd, gfc2mnl_interface* hdlr) {

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    char buff_send[GFC_MNL_BUFF_SIZE] = {0};

+    char data[GFC_MNL_BUFF_SIZE] = {0};

+    int ret = MTK_GFC_ERROR, read_len, offset = 0, len;

+    MTK_FLP_MSG_T *prmsg = NULL;

+

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

+    if ((read_len <= 0) || (read_len>GFC_MNL_BUFF_SIZE)) {

+        LOGE("hal2gfc_main_hdlr() safe_recvfrom() failed read_len=%d",read_len);

+        return ret;

+    }

+    if(hdlr != NULL) {

+        gfc2mnl_hdlr_cb = hdlr;

+    } else {

+        LOGE("gfc2mnl_hdlr_cb = NULL");

+        return ret;

+    }

+

+    len = get_binary(buff, &offset, data, sizeof(buff), sizeof(data));

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

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

+    } else {

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

+        return ret;

+    }

+#if 0

+    LOGD("mtk_hal2gfc_main_hdlr:%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x",

+    data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],

+    data[8],data[9],data[10],data[11],data[12],data[13],data[14],data[15]);

+#endif

+    if(prmsg->type == GEOFENCE_INJECT_LOC_ENUM) {

+        //relay from flpHAL to geofenceHAL

+        offset = 0;

+        put_binary(buff_send, &offset, (const char*)data,read_len);

+        ret = mnl_send2gfc(buff_send, offset);

+        if(ret < 0) {

+            LOGD("GFC2FLP send error return error");

+        }

+        return ret;

+    }

+    if (prmsg->type == MTK_FLP_MSG_HAL_INIT_CMD) {

+    } else if (prmsg->type == MTK_FLP_MSG_CONN_SCREEN_STATUS) {

+        if (mtk_gfc_get_sys_mode() == GFC_OFFLOAD_MODE) {

+            mtk_gfc_ofl2mnl_process(prmsg);

+        }

+    } else {

+        if (mtk_gfc_get_sys_mode() == GFC_OFFLOAD_MODE) {

+            mtk_gfc_ofl2mnl_process(prmsg);

+        } else {

+            mtk_gfc_controller_process(prmsg);

+        }

+    }

+    ret = MTK_GFC_SUCCESS;

+

+    return ret;

+}

+

+/************************************************************************/

+//  Handle Geofence Kernel Response                                     */

+/************************************************************************/

+int gfc_kernel_2gfc_hdlr(MTK_FLP_MSG_T* prmsg) {

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    int ret, offset = 0;

+

+    if(prmsg == NULL) {

+        LOGE("gfc_kernel_2gfc_hdlr = NULL");

+        return MTK_GFC_ERROR;

+    }

+    put_binary(buff, &offset, (const char*)prmsg,sizeof(MTK_FLP_MSG_T)+prmsg->length);

+    ret = mnl_send2gfc(buff, offset);

+    if(ret < 0) {

+        LOGE("MTK_GFC2HAL send error return error");

+    } else {

+        LOGD("gfc_kernel_2gfc_hdlr success");

+    }

+    return MTK_GFC_SUCCESS;

+}

+

+

+/************************************************************************/

+//  Handle GFC Request                                                  */

+/************************************************************************/

+int gfc2mnl_hdlr(MTK_GFC_MNL_MSG_T  *prMsg) {

+    int ret = MTK_GFC_ERROR, read_len;

+

+    if(prMsg != NULL) {

+        read_len = prMsg->length + sizeof(MTK_GFC_MNL_MSG_HEADER_T);

+        LOGD("[GFC2MNLD]data from gfc: type=0x%02x, session_id=%u, len=%d,read_len = %d\n", prMsg->type, prMsg->session, prMsg->length, read_len);

+        //mnl_gfc_dump_buf((char*)prMsg, read_len);

+    } else {

+        LOGE("gfc2mnl_hdlr recv null msg");

+        return ret;

+    }

+    if(gfc2mnl_hdlr_cb == NULL) {

+        LOGE("gfc2mnl_hdlr_cb is NULL");

+        return ret;

+    }

+

+    switch (prMsg->type) {

+        case MNLD_FLP_TYPE_FLP_ATTACH: {

+            if (gfc2mnl_hdlr_cb->mnld_gfc_attach) {

+                gfc2mnl_hdlr_cb->mnld_gfc_attach();

+                if (mnld_gfc_session_update() == -1) {

+                    LOGE("mnld_main_thread() mnld_gfc_session_update failed");

+                } else {

+                    ret = MTK_GFC_SUCCESS;

+                }

+            } else {

+                LOGE("gfc2mnl_hdlr() mnld_flp_attach is NULL");

+            }

+            break;

+        }

+        case MNLD_FLP_TYPE_HBD_GPS_OPEN: {

+            if (prMsg->session != mnld_gfc_session.id) {

+                LOGE("gfc2mnl_hdlr() session_id doesn't match, ignore");

+                break;

+            }

+            if (gfc2mnl_hdlr_cb->mnld_gfc_hbd_gps_open) {

+                gfc2mnl_hdlr_cb->mnld_gfc_hbd_gps_open();

+                ret = MTK_GFC_SUCCESS;

+            } else {

+                LOGE("gfc2mnl_hdlr() mnld_gfc_hbd_gps_open is NULL");

+            }

+            break;

+        }

+        case MNLD_FLP_TYPE_HBD_GPS_CLOSE: {

+            if (prMsg->session != mnld_gfc_session.id) {

+                LOGE("gfc2mnl_hdlr() session_id doesn't match, ignore");

+                break;

+            }

+            if (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_close is NULL");

+            }

+            break;

+        }

+        case MNLD_FLP_TYPE_OFL_LINK_OPEN: {

+            if (prMsg->session != mnld_gfc_session.id) {

+                LOGE("gfc2mnl_hdlr() session_id doesn't match, ignore");

+                break;

+            }

+            if (gfc2mnl_hdlr_cb->mnld_gfc_ofl_link_open) {

+                gfc2mnl_hdlr_cb->mnld_gfc_ofl_link_open();

+                ret = MTK_GFC_SUCCESS;

+            } else {

+                LOGE("gfc2mnl_hdlr() mnld_gfc_ofl_link_open is NULL");

+            }

+            break;

+        }

+        case MNLD_FLP_TYPE_OFL_LINK_CLOSE: {

+            if (prMsg->session != mnld_gfc_session.id) {

+                LOGE("gfc2mnl_hdlr() session_id doesn't match, ignore");

+                break;

+            }

+            if (gfc2mnl_hdlr_cb->mnld_gfc_ofl_link_close) {

+                gfc2mnl_hdlr_cb->mnld_gfc_ofl_link_close();

+                ret = MTK_GFC_SUCCESS;

+            } else {

+                LOGE("gfc2mnl_hdlr() mnld_gfc_ofl_link_close is NULL");

+            }

+            break;

+        }

+        case MNLD_FLP_TYPE_OFL_LINK_SEND: {

+            if (prMsg->session != mnld_gfc_session.id) {

+                LOGE("gfc2mnl_hdlr() session_id doesn't match, ignore");

+                break;

+            }

+            if (gfc2mnl_hdlr_cb->mnld_gfc_ofl_link_send) {

+                gfc2mnl_hdlr_cb->mnld_gfc_ofl_link_send(prMsg);

+                ret = MTK_GFC_SUCCESS;

+            } else {

+                LOGE("gfc2mnl_hdlr() mnld_flp_ofl_link_send is NULL");

+            }

+            break;

+        }

+        default: {

+            LOGE("gfc2mnl_hdlr() unknown cmd=0x%02x", prMsg->type);

+            break;

+        }

+    }

+    return ret;

+}

+

+

diff --git a/src/connectivity/gps/mtk_mnld/mnl_log_interface/inc/LbsLogInterface.h b/src/connectivity/gps/mtk_mnld/mnl_log_interface/inc/LbsLogInterface.h
new file mode 100644
index 0000000..0f111d5
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_log_interface/inc/LbsLogInterface.h
@@ -0,0 +1,68 @@
+// 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 15376
+
+/**
+ * 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, 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/mtk_mnld/mnl_log_interface/src/LbsLogInterface.c b/src/connectivity/gps/mtk_mnld/mnl_log_interface/src/LbsLogInterface.c
new file mode 100644
index 0000000..0238e35
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_log_interface/src/LbsLogInterface.c
@@ -0,0 +1,262 @@
+// 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, 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=[%d] 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[15360];
+        int log_size = mtk_socket_get_char_array(_buff, &_offset, log, 15360);
+        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));
+    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;
+    }
+    return LbsLogInterface_receiver_decode(_buff, callbacks);
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_meta_interface/inc/Meta2MnldInterface.h b/src/connectivity/gps/mtk_mnld/mnl_meta_interface/inc/Meta2MnldInterface.h
new file mode 100644
index 0000000..42a6dc5
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_meta_interface/inc/Meta2MnldInterface.h
@@ -0,0 +1,43 @@
+// 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
+
+/**
+ * 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;
+
+bool Meta2MnldInterface_receiver_decode(char* _buff, Meta2MnldInterface_callbacks* callbacks);
+bool Meta2MnldInterface_receiver_read_and_decode(int server_fd, Meta2MnldInterface_callbacks* callbacks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_meta_interface/src/Meta2MnldInterface.c b/src/connectivity/gps/mtk_mnld/mnl_meta_interface/src/Meta2MnldInterface.c
new file mode 100644
index 0000000..8b1b767
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_meta_interface/src/Meta2MnldInterface.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 "Meta2MnldInterface.h"
+#include "mtk_socket_data_coder.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)) {
+        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) {
+        LOGE("Meta2MnldInterface_reqGnssLocation() mtk_socket_write() failed, fd=%p err=[%s]%d", 
+            client_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)) {
+        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) {
+        LOGE("Meta2MnldInterface_cancelGnssLocation() mtk_socket_write() failed, fd=%p err=[%s]%d", 
+            client_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) {
+        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) {
+            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) {
+            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: {
+        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 _ret;
+    char _buff[META2MNLD_INTERFACE_BUFF_SIZE] = {0};
+
+    _ret = mtk_socket_read(server_fd, _buff, sizeof(_buff));
+    if(_ret == -1) {
+        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);
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_Attitude.h b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_Attitude.h
new file mode 100644
index 0000000..cece8bf
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_Attitude.h
@@ -0,0 +1,231 @@
+/* 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.
+ */
+/* Usage:
+ * 1. Fill in struct IMU
+ * 2. Call mpe_update_posture()
+ * 3. Call mpe_get_euler_angle() or mpe_get_rotation_vector() to get
+ *    <azimuth, pitch, roll> or the rotation vector.
+ *
+ * E.g.
+ *      struct IMU imu;
+ *
+ *      // Fill in the acceleration value from the accelerometer
+ *      imu.acceleration[0] = acc_x;
+ *      imu.acceleration[1] = acc_y;
+ *      imu.acceleration[2] = acc_z;
+ *
+ *      // Fill in the angular velocity from the gyroscope
+ *      imu.angularVelocity[0] = gyro_x;
+ *      imu.angularVelocity[1] = gyro_y;
+ *      imu.angularVelocity[2] = gyro_z;
+ *
+ *      // Fill in magnetic field values from magnetic sensor
+ *      imu.magnetic[0] = mag_x;
+ *      imu.magnetic[1] = mag_y;
+ *      imu.magnetic[2] = mag_z;
+ *
+ *      mpe_update_posture(&imu, (curr_time - prev_time));
+ *
+ *  #ifdef ANDROID_2_3
+ *      float vector[3];
+ *      mpe_get_rotation_vector(vector);
+ *  #else
+ *      float angle[3];
+ *      mpe_get_euler_angle(angle);
+ *  #endif
+ */
+#ifndef __MPE_ATTITUDE_H_INCLUDED__
+#define __MPE_ATTITUDE_H_INCLUDED__
+
+#include <sys/types.h>
+#include <stdint.h>
+
+#define use_speciall_name 0
+/* Sensor Fusion Mode */
+/*
+ * 1) low latency (real time)
+ * 2) 3-DOF rotation detection
+ * 3) eliminate accumulated error
+ * 4) Solve gyroscope temperature drift issue
+ * 5) decouple linear acceleration and gravity of G-sensor
+ * 6) provide absolute orientation (for applications like : navigation)
+ * 7) anti-interference from sudden change of ambient magnetism
+ */
+#define SENSOR_FUSION_MODE_ACC_GYRO_MAG 0
+/*
+ * 1) Need AGM and AG output in the same time
+ * 2) Provide both absolute yaw angle and reletive
+ * 3) Support Android two sensor types
+ */
+#define SENSOR_FUSION_MODE_BOTH_AGM_AG 1
+
+/**
+ * 1) unbounded accumulate error
+ * 2) temperature drift issue from gyro
+ * 3) relative orientation (NOT absolute)
+ */
+#define SENSOR_FUSION_MODE_ACC_GYRO   2
+/*
+ * 1) delayed response
+ * 2) can not resist the magnetic interference
+ * 3) confuse by linear acceleration and gravity
+ */
+#define SENSOR_FUSION_MODE_ACC_MAG    3
+
+/*
+ * 1) use for pedestrian dead reckoning
+ * 2) fused with radio localization system (like : GPS/WF)
+ */
+#define SENSOR_FUSION_MODE_PDR        4
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Definitions of the axis
+ *
+ *          |   /
+ *          |  /
+ *          | /
+ *     ---- |/ ------ x+
+ *          /
+ *         /|
+ *        / |
+ *       /  y-
+ *     z+
+ */
+/*
+ * The input data structure for the Sensor Fusion algorithm
+ */
+typedef struct IMU {
+    /* acceleration values are in meter per second per second (m/s^2) */
+    float acceleration[3];
+    float acceleration_raw[3];
+    /* angular rate values are in radians per second */
+    float  angularVelocity[3];
+    float  angularVelocity_raw[3];
+    /* magnetic vector values are in micro-Tesla (uT) */
+    float magnetic[3];
+    float magnetic_raw[3];
+
+    //float light[3];
+    //float proximity[3];
+    float thermometer;
+    float pressure;
+    int64_t input_time_acc;
+    int64_t input_time_gyro;
+    int64_t input_time_mag;
+    int64_t input_time_baro;
+
+} IMU, *LPIMU;
+
+/*
+ * Updates the posture of the device
+ *
+ * @param pImu A pointer to input data structure.
+ * @param deltaTime The time difference between calls. The unit is millisecond.
+ */
+int mpe_update_posture(LPIMU pImu, int deltaTime);
+/*
+ * Filter the raw data of the gyroscope
+ *
+ * @param pImu A pointer to input data structure.
+ * @param threshold Low-pass filter threshold. The unit is degree.
+ */
+void mpe_gyro_filter(LPIMU pImu, float threshold);
+/*
+ * Returns the rotation vector of the device
+ *
+ * The rotation vector represents the orientation of the device as a
+ * combination of an angle and an axis, in which the device has rotated
+ * through an angle theta around an axis [x, y, z]. The three elements
+ * of the rotation vector are
+ *
+ * vector = [x*sin(theta/2), y*sin(theta/2), z*sin(theta/2]
+ *
+ * @param vector The result rotation vector
+ * @return 0 on success, < 0 on failure
+ */
+int mpe_get_rotation_vector(float *vector);
+/*
+ * Returns a gravity vector
+ *
+ * Gravity vector provides faster tilt angle change detection.
+ *
+ * @param gravity a 3-element array contains the result gravity vector
+ * @return 0 on success, < 0 on failure
+ */
+int mpe_get_gravity(float *gravity);
+/*
+ * Returns a acceleration vector without gravity
+ *
+ * Linear acceleration decouples gravity so that applications can get more
+ * faster and precise motion.
+ *
+ * @param acceleration a 3-element array contains the result acceleration vector
+ * @return 0 on success, < 0 on failure
+ */
+int mpe_get_linear_acceleration(float *acceleration);
+/*
+ * Returns euler angles of the device.
+ *
+ * Euler angles are used to describe the orientation of a rigid body. All
+ * values are angles in degrees.
+ * The three elements of euler angles are [azimuth, pitch, roll].
+ *
+ * @param angles a 3-element array contains the result euler angles
+ * @return 0 on success, < 0 on failure
+ */
+int mpe_get_euler_angle(float *angles);
+
+int mpe_get_game_rotation_vector(float *vector);
+int mpe_get_rotation_matrix(float *matrix);
+void mpe_set_fusion_mode(int mode);
+int mpe_re_initialize(void);
+int mpe_calculate_GEO_rotation_vector(float *gravity, float *geomagnetic, float *vector, float *euler);
+int mpe_get_global_rotation(LPIMU pImu, float *rotation);
+int mpe_set_radio_information(float *speed, float *confidence);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MPE_ATTITUDE_H_INCLUDED__ */
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_DR.h b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_DR.h
new file mode 100644
index 0000000..f989e04
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_DR.h
@@ -0,0 +1,83 @@
+#ifndef __MPE_DR_H_INCLUDED__
+#define __MPE_DR_H_INCLUDED__
+
+#include "stdint.h"
+#include "mpe_Attitude.h"
+
+/******************************************************************************
+* Version Info
+******************************************************************************/
+
+#define MPE_VERSION_HEAD 'M','P','E','_','V','E','R','_'
+#define MPE_MAJOR_VERSION '1','8','0','3','2','0','0','1' // y,y,m,m,d,d,rev,rev
+#define MPE_BRANCH_INFO '_','3','.','0','0','_'
+#define MPE_MINER_VERSION '0','0'
+
+#define MPE_VER_INFO MPE_VERSION_HEAD,MPE_MAJOR_VERSION,MPE_BRANCH_INFO,MPE_MINER_VERSION
+
+#define MPE_GRAVITY_EARTH   9.8066f
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct MNL2MPE_AIDING_DATA{
+    double  latitude[2]; /* latitude in radian */
+    double  longitude[2]; /* longitude in radian */
+    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   LS_velocitySigma[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 */
+    unsigned int   gps_sec; /* Timestamp of GPS location */
+    unsigned int   leap_sec; /* correct GPS time with phone kernel time */
+} MNL2MPE_AIDING_DATA;
+
+
+typedef struct MPE2MNL_AIDING_DATA{
+    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   acceleration[3]; /* SENSOR acceleration 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   bearing; /* SENSOR heading in degrees UNDER (N,E,D) frame*/
+    float   confidenceIndex[3]; /*  SENSOR confidence index */
+    float   barometerHeight;         /*barometer height in meter*/
+    int     valid_flag[4]; /*  SENSOR AGMB hardware valid flag */
+    int     staticIndex; /* AR status [static, move, uncertain],[0,1,99]*/
+    unsigned long long timestamp; /* Timestamp of SENSOR location */
+} MPE2MNL_AIDING_DATA;
+
+
+typedef enum{
+    MTK_MPE_SYS_FLAG = 0x00,
+    MTK_MPE_KER_FLAG,
+    MTK_MPE_RAW_FLAG,
+    MTK_MPE_RES1_FLAG,
+    MTK_MPE_MAX_FLAG
+}MTK_VALID_FLAG_TYPE;
+
+
+int mpe_update_dead_reckoning(LPIMU pImu, int deltaTime_us, MNL2MPE_AIDING_DATA *pGPS);
+int get_map_matching_result(LPIMU pImu, MNL2MPE_AIDING_DATA *pGPS, MPE2MNL_AIDING_DATA dr_position, MNL2MPE_AIDING_DATA *pMAP);
+int mpe_get_dr_position(MPE2MNL_AIDING_DATA *pos);
+int mpe_get_dr_gyro_bias(float *bias);
+int mpe_get_dr_acc_bias(float *bias);
+int mpe_dr_re_initialize(void);
+int mpe_get_dr_entry(LPIMU pImu, MNL2MPE_AIDING_DATA *pGPS, MPE2MNL_AIDING_DATA *pos);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MPE_DR_H_INCLUDED__ */
diff --git a/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_common.h b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_common.h
new file mode 100644
index 0000000..6004282
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_common.h
@@ -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) 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.
+ */
+#ifndef MPE_COMMON_H
+#define MPE_COMMON_H
+
+#include <string.h>
+#include <pthread.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include "mtk_gps_type.h"
+
+#ifdef __cplusplus
+  extern "C" {
+#include <climits>   // C++ header
+#else
+#include <limits.h>  // C header
+#endif
+
+/******************************************************************************
+* Define
+******************************************************************************/
+/* MPE Conf flag */
+#define MPE_CONF_MPE_ENABLE     (1U<<0)
+#define MPE_CONF_PRT_RAWDATA    (1U<<1)
+#define MPE_CONF_AUTO_CALIB     (1U<<2)
+#define MPE_CONF_INDOOR_ENABLE  (1U<<3)
+
+// define TRUE and FALSE
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+// Ensure NULL is defined
+#ifdef NULL
+#undef NULL
+#endif
+#define NULL 0
+
+#define SECS_IN_DAY  (86400)            // Seconds in a Day
+#define DIFF_GPS_C_TIME ((365*10+2+5)*SECS_IN_DAY) // GPS epoch = 06Jan1980,  C epoch   = 01Jan1970,10years+leap years+,5 days Jan * sec in day
+
+typedef pthread_mutex_t MPE_MUTEX;
+typedef pthread_cond_t MPE_EVENT;
+
+//Socket name
+#define MNLD_MNL2ADR_SOCKET                 "mnl2adr_socket"
+#define MNLD_ADR2MNL_SOCKET                 "adr2mnl_socket"
+
+/*****************************************************************************
+ * FLP specific types
+ *****************************************************************************/
+//Define debug buffer size
+#define DEBUG_LOG
+#define MNL_MPE_MAX_BUFF_SIZE (6*1024)
+#define MNL_MPE_NMEA_MAX_SIZE (10*1024)
+
+#define MAX_NUM_SAMPLES 15
+#define MPE_LOG_NAME_MAX_LEN 128
+
+#define CMD_SEND_FROM_MNLD 0x40
+#define CMD_MPED_REBOOT_DONE 0x41
+/******************************************************************************
+* enum
+******************************************************************************/
+typedef enum {
+    MPE_IDLE_MODE = 0,
+    MPE_START_MODE  = 1,
+} MPE_OPERATION_MODE;
+
+typedef enum {
+    SENSOR_USER_ID_CALIB = 0,
+    SENSOR_USER_ID_MPE = 1,
+    SENSOR_USER_ID_MAX
+} SENSOR_USER_ID;
+
+typedef enum {
+    SENSOR_TYPE_ACC = 0,
+    SENSOR_TYPE_GYR,
+    SENSOR_TYPE_UNCAL_GYR,
+    SENSOR_TYPE_MAG,
+    SENSOR_TYPE_BAR,
+    SENSOR_TYPE_GYR_TMP,
+    SENSOR_TYPE_MAX
+} SENSOR_TYPE;
+
+typedef enum{
+    MNL_ADR_TYPE_MNL2ADR_GPS_OPEN = 0x100,
+    MNL_ADR_TYPE_MNL2ADR_GPS_OPEN_DONE,
+    MNL_ADR_TYPE_MNL2ADR_GPS_CLOSE,
+    MNL_ADR_TYPE_MNL2ADR_GPS_CLOSE_DONE,
+    MNL_ADR_TYPE_MNL2ADR_MNL_REBOOT,
+    MNL_ADR_TYPE_MNL2ADR_NMEA_DATA,
+
+    MNL_ADR_TYPE_ADR2MNL_NMEA_DATA = 0x200,
+    MNL_ADR_TYPE_ADR2MNL_PMTK_CMD
+}MNL_ADR_TYPE;
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/******************************************************************************
+* functions Prototype
+******************************************************************************/
+unsigned char mpe_sys_sensor_threads_create(void);
+UINT32 mpe_sys_get_mpe_conf_flag( void );
+void mpe_sys_read_mpe_conf_flag(void);
+INT32 mpe_sys_gps_to_sys_time ( UINT32 gps_sec);
+void mpe_sys_get_time_stamp(double* timetag, UINT32 leap_sec);
+
+void mpe_log_init();
+void mpe_log_deinit();
+UINT16 mpe_log_check_file();
+void mpe_log_mtklogger_check(INT16 record_mode, char *logpath, INT8 log_location);
+
+void mpe_run_algo( void );
+void mpe_kernel_initialize( void );
+int mnl2mpe_hdlr(int fd);
+void mnl2mpe_hdlr_init(void);
+int mpe2mnl_hdlr(char *buff);
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif //#ifndef MPE_COMMON_H
diff --git a/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_sensor.h b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_sensor.h
new file mode 100644
index 0000000..812eb25
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_sensor.h
@@ -0,0 +1,72 @@
+/* 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.
+ */
+#ifndef SE_SENSOR_LISTENER_API_H
+#define SE_SENSOR_LISTENER_API_H
+
+#include "mpe_Attitude.h"
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+typedef struct EVENT_DATA {
+    float x;
+    float y;
+    float z;
+    int64_t timestamp;
+} EVENT_DATA;
+
+//unsigned char mpe_sensor_get_listen_mode(void);
+void mpe_sensor_set_listen_mode(unsigned char mode);
+void mpe_sensor_get_accuracy(INT8 *accuracy);
+unsigned char mpe_sensor_init(SENSOR_USER_ID id);
+unsigned char mpe_sensor_deinit(SENSOR_USER_ID id);
+unsigned char mpe_sensor_start(SENSOR_USER_ID id, SENSOR_TYPE mpe_type, UINT32 periodInMs);
+unsigned char mpe_sensor_stop(SENSOR_USER_ID id, SENSOR_TYPE mpe_type);
+void mpe_sensor_get_calib_accuracy(INT8 *accuracy);
+unsigned char mpe_sensor_get_calib_gyr_data(void);
+unsigned char mpe_sensor_check_mnl_response(void);
+UINT16 mpe_sensor_check_time();
+UINT16 mpe_sensor_acquire_Data (IMU* data);
+void mpe_sensor_run (void);
+void mpe_sensor_update_mnl_sec(UINT32 gps_sec, UINT32 leap_sec);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //#ifndef SE_SENSOR_LISTENER_API_H
diff --git a/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_logger.c b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_logger.c
new file mode 100644
index 0000000..e80b4f3
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_logger.c
@@ -0,0 +1,362 @@
+/* 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 <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <dirent.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include "mpe_common.h"
+#include "mpe_sensor.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "MPE_LOG"
+#endif
+
+//-----------------------------------------------------------------------------
+//using namespace android;
+//-----------------------------------------------------------------------------
+
+#define MAX_DBG_LOG_W_SEC 3600
+#define MAX_DBG_LOG_DIR_SIZE   (300UL*1024UL*1024UL)
+#define MPE_DBG_LOG_FILE_NUM_LIMIT  200
+
+enum {
+    GPS_DEBUGLOG_DISABLE       = 0x00,
+    GPS_DEBUGLOG_ENABLE        = 0x01,
+};
+
+enum {
+    log_in_sdcard = 0x00,
+    log_in_data_misc,
+};
+
+FILE *data_file_local = NULL;
+static UINT32 current_file_w_sec = 0;
+static long long current_file_sec = 0;
+static INT32 current_file_index = 0;
+
+//for mtklogger
+INT16 u2Log_enable = 0;
+static INT8 u1Log_location = log_in_sdcard;
+static char Log_path[MPE_LOG_NAME_MAX_LEN];
+
+//extern UINT32 current_gps_sec;
+UINT32 current_gps_sec;
+
+static void mpe_log_check_and_delete_file (void);
+
+/*******************************************************************************
+* Static function
+********************************************************************************/
+
+static int GetFileSize(char *filename)
+{
+    char dir_filename[MPE_LOG_NAME_MAX_LEN];
+    struct stat statbuff;
+
+    memset(dir_filename, 0x00, sizeof(dir_filename));
+
+    if (NULL == filename) {
+        LOGD("File name is NULL!! %s", filename);
+        return 0;
+    }
+
+    snprintf(dir_filename, sizeof(dir_filename), "%s/%s", Log_path,filename);
+
+    if (stat(dir_filename,&statbuff) < 0) {
+        LOGD("open file(%s) state  fail(%s)!!", dir_filename, strerror(errno));
+        return 0;
+    } else {
+        return statbuff.st_size;
+    }
+}
+
+//-----------------------------------------------------------------------------
+static INT16 mpe_log_check_total_file(char se_filename[][MPE_LOG_NAME_MAX_LEN], unsigned long *total_file_size )
+{
+    DIR *dir;
+    struct dirent *ptr;
+    struct stat buf;
+    INT16 i= 0;
+    unsigned long tmp_size = 0, total_size = 0;
+    char pathname[MPE_LOG_NAME_MAX_LEN];
+    char *file_in_dir, name_tmp[MPE_LOG_NAME_MAX_LEN];
+
+    dir = opendir(Log_path);
+    *total_file_size = 0;
+
+    if (dir != NULL) {
+        while((ptr = readdir(dir)) != NULL && i < MPE_DBG_LOG_FILE_NUM_LIMIT) {
+            memset(pathname, 0, MPE_LOG_NAME_MAX_LEN);
+            memset(name_tmp, 0, MPE_LOG_NAME_MAX_LEN);
+            sprintf(pathname, "%s%s", Log_path, ptr->d_name );
+            if (stat(pathname, &buf) == -1) {
+                LOGD("stat return failed %s%s\n", Log_path, ptr->d_name);
+                continue;
+            }
+            if (i >= MPE_DBG_LOG_FILE_NUM_LIMIT) {
+                LOGD("max file reached %d\n",i);
+                break;
+            }
+            if (S_ISREG(buf.st_mode)) {
+                file_in_dir = ptr->d_name;
+                if(!strncmp(file_in_dir, "se_ut", 5)) {
+                    memcpy(&name_tmp,file_in_dir, MPE_LOG_NAME_MAX_LEN);
+                    memcpy((se_filename+i), &name_tmp, MPE_LOG_NAME_MAX_LEN);
+                    tmp_size = GetFileSize(*(se_filename+i));
+                    total_size += tmp_size;
+                    i++;
+                }
+            }
+        }
+        closedir(dir);
+        *total_file_size = total_size;
+        LOGD("total file size = %lu %"PRId16, total_size, i);
+    }
+    return i;
+}
+
+//-----------------------------------------------------------------------------
+static void mpe_log_conv_filename_to_time( UINT16 file_cnt, char se_filename[][MPE_LOG_NAME_MAX_LEN], INT32 *file_time[],UINT16 *oldest_file_indx  )
+{
+    UINT16 min_index = 0, j;
+    INT32 min_time = 0, min_subtag = 0;
+    INT32 local_file_time[MPE_DBG_LOG_FILE_NUM_LIMIT];
+    INT32 local_file_subtag[MPE_DBG_LOG_FILE_NUM_LIMIT] = { 0 };
+    char tmp_file_time[12];
+    char tmp_file_subtag[12];
+    char tmp_file_name[MPE_LOG_NAME_MAX_LEN];
+
+    if (file_cnt < 1) {
+        return;
+    }
+
+    for (j = 0; j < file_cnt; j++) {
+        memset(tmp_file_time, 0, sizeof(tmp_file_time));
+        memset(tmp_file_subtag, 0, sizeof(tmp_file_subtag));
+        memset(tmp_file_name, 0, sizeof(tmp_file_name));
+        strncpy(tmp_file_name, se_filename[j], strlen(se_filename[j]));
+        tmp_file_name[strlen(tmp_file_name)-4] = 0;
+        if (tmp_file_name[16] == '_') {
+            strncpy(tmp_file_subtag, tmp_file_name+17, strlen(tmp_file_name+17));
+            local_file_subtag[j] = atoi(tmp_file_subtag);
+        } else {
+            local_file_subtag[j] = 0;
+        }
+
+        tmp_file_name[16] = 0;
+        strncpy(tmp_file_time, tmp_file_name+5, strlen(tmp_file_name+5));
+        local_file_time[j] = atoi(tmp_file_time);
+
+        if ((j == 0) || (local_file_time[j] < min_time) ||
+            (local_file_time[j] == min_time && local_file_subtag[j] < min_subtag))
+        {
+            min_time = local_file_time[j];
+            min_subtag = local_file_subtag[j];
+            min_index = j;
+        }
+    }
+    memcpy(file_time,local_file_time, file_cnt*sizeof(INT32));
+
+    *oldest_file_indx = min_index;
+    LOGD("oldest_file = %u, %s, %d %d\n", *oldest_file_indx, se_filename[min_index], min_time, min_subtag);
+
+    return;
+}
+
+
+//-----------------------------------------------------------------------------
+static void mpe_log_check_and_delete_file (void)
+{
+    unsigned long total_file_size;
+    char se_filename[MPE_DBG_LOG_FILE_NUM_LIMIT][MPE_LOG_NAME_MAX_LEN];
+    INT16 total_file;
+    UINT16 oldest_indx;
+    INT32 *file_time[MPE_DBG_LOG_FILE_NUM_LIMIT];
+    char del_filename[MPE_LOG_NAME_MAX_LEN];
+
+    total_file = mpe_log_check_total_file(se_filename, &total_file_size);
+
+    if (total_file > 0) {
+        mpe_log_conv_filename_to_time(total_file, se_filename, file_time, &oldest_indx);
+        while (total_file_size > MAX_DBG_LOG_DIR_SIZE || total_file >= MPE_DBG_LOG_FILE_NUM_LIMIT) {
+            LOGD("total size = %lu, total file = %"PRId16, total_file_size, total_file);
+
+            //remove oldest file
+            memset(del_filename, 0, MPE_LOG_NAME_MAX_LEN);
+            sprintf(del_filename, "%s%s", Log_path,*(se_filename + oldest_indx));
+            LOGD("delete filename %s %s", del_filename, *(se_filename+oldest_indx));
+
+            if (remove(del_filename) == 0) {
+                LOGD("remove %s success", del_filename);
+            } else {
+                LOGD("remove %s failed", del_filename);
+            }
+
+            total_file = mpe_log_check_total_file(se_filename, &total_file_size);
+            mpe_log_conv_filename_to_time(total_file, se_filename, file_time, &oldest_indx);
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+static unsigned char mpe_log_open_new_file (void)
+{
+    char name[MPE_LOG_NAME_MAX_LEN];
+    unsigned char ret = FALSE;
+    char header_name[6] = "se_ut";
+
+    if (data_file_local != NULL) {
+        fclose(data_file_local);
+    } else {
+        return ret;
+    }
+
+    if (u2Log_enable) {
+        current_file_index++;
+        sprintf(name, "%s%s0%lld_%d.txt", Log_path, header_name, current_file_sec, current_file_index);
+        LOGD("open file - time %s", name);
+        data_file_local = fopen(name, "w+");
+        if (data_file_local == NULL) {
+            LOGD("se file open %s\n", strerror(errno));
+            ret = FALSE;
+        } else {
+            ret = TRUE;
+        }
+        mpe_log_check_and_delete_file();
+    }
+    return ret;
+}
+
+/*******************************************************************************
+* Global function
+********************************************************************************/
+void mpe_log_mtklogger_check ( INT16 record_mode, char *logpath, INT8 log_location)
+{
+    //char name[MPE_LOG_NAME_MAX_LEN];
+    //char header_name[6] = "se_ut";
+
+    if (record_mode == GPS_DEBUGLOG_DISABLE) {
+        u2Log_enable = 0;
+
+        if (data_file_local != NULL) {
+            LOGD("stop recording se data");
+            data_file_local = NULL;
+        }
+    } else if(record_mode == GPS_DEBUGLOG_ENABLE) {
+        memcpy(&Log_path, logpath, MPE_LOG_NAME_MAX_LEN);
+        u2Log_enable = 1;
+        LOGD("se logger path: %s", Log_path);
+
+        /*if (data_file_local == NULL && mpe_sensor_get_listen_mode() == MPE_START_MODE) {
+            sprintf(name, "%s%s0%u.txt", Log_path, header_name, current_gps_sec);
+            current_file_sec = (long long)current_gps_sec;
+            current_file_index = 0;
+            data_file_local = fopen(name,"w+");
+            LOGD("open file - mtklog %s\n", name);
+            if (data_file_local == NULL) {
+                LOGD("se file open %s\n", strerror(errno));
+            }
+            if (chmod(name, 0600) < 0) {
+                LOGD("se file chmod %s\n", strerror(errno));
+            }
+            mpe_log_check_and_delete_file();
+        }*/
+    }
+    u1Log_location = log_location;
+}
+
+UINT16 mpe_log_check_file()
+{
+    unsigned char file_stat;
+
+    if (u2Log_enable) {
+        current_file_w_sec++;
+        if (current_file_w_sec >= MAX_DBG_LOG_W_SEC) {
+            file_stat = mpe_log_open_new_file();
+            if (file_stat) {
+                current_file_w_sec = 0;
+            }
+        }
+    }
+    return 0;
+}
+
+void mpe_log_init()
+{
+    char name[MPE_LOG_NAME_MAX_LEN];
+    char header_name[6] = "se_ut";
+
+    current_file_w_sec = 0;
+    if (u2Log_enable) {
+        LOGD("logpath : %s", Log_path);
+        sprintf(name, "%s%s0%u.txt",Log_path, header_name ,current_gps_sec);
+        current_file_sec = (long long)current_gps_sec;
+        current_file_index = 0;
+
+        LOGD("open file - gps %s", name);
+        data_file_local = fopen(name, "w+");
+        if (data_file_local == NULL) {
+            LOGD("se file open %s\n", strerror(errno));
+        }
+        if(chmod(name, 0600) < 0) {
+            LOGD("se file chmod %s\n", strerror(errno));
+        }
+        mpe_log_check_and_delete_file();
+    }
+    return;
+}
+void mpe_log_deinit()
+{
+    if(data_file_local != NULL) {
+        fclose(data_file_local);
+    }
+    current_file_w_sec = 0;
+    return;
+}
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_main.c b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_main.c
new file mode 100644
index 0000000..8460eb5
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_main.c
@@ -0,0 +1,315 @@
+/*****************************************************************************
+*  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) 2008
+*
+*  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).
+*
+***************************************************************/
+#ifndef MPE_MAIN_C
+#define MPE_MAIN_C
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*****************************************************************************
+ * Include
+ *****************************************************************************/
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/epoll.h>
+#include <errno.h>
+#include <math.h>
+#include <inttypes.h>
+
+#include "mpe_common.h"
+#include "mpe_DR.h"
+#include "mpe_sensor.h"
+#include "mpe.h"
+#include "data_coder.h"
+#include "mtk_lbs_utility.h"
+#include "mnld.h"
+#include "mtk_auto_log.h"
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#include <cutils/properties.h>
+#endif
+#if defined(__ANDROID_OS__)
+#include <private/android_filesystem_config.h>
+#endif
+
+#if defined(__ANDROID_OS__)
+#define MPE_DEFAULT_CONFIG_FILE "/system/vendor/etc/adr/mpe.conf"
+#elif defined(__LINUX_OS__)
+#define MPE_DEFAULT_CONFIG_FILE "/etc/adr/mpe.conf"
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "MPE_MA"
+#endif
+
+/*****************************************************************************
+ * GLobal Variable
+ *****************************************************************************/
+static const char pMPEVersion[] = {MPE_VER_INFO,0x00};
+unsigned char isUninit_SE = FALSE;
+static MNL2MPE_AIDING_DATA mnl_latest_in;
+static MNL2MPE_AIDING_DATA mnl_glo_in;
+static MPE2MNL_AIDING_DATA mnl_glo_out;
+static UINT32 gMPEConfFlag = 0;
+
+//Mtklogger function
+char mpe_debuglog_file_name[MPE_LOG_NAME_MAX_LEN];
+
+//check for baro validity
+//extern unsigned char isfirst_baro;
+unsigned char isfirst_baro = 0;
+
+// se log
+extern FILE *data_file_local;
+
+float gyr_temperature = 0.0f;
+float gyr_scp_calib_done = 0.0f;
+
+unsigned char gMpeThreadExist = 0;
+
+UINT32 mpe_sys_get_mpe_conf_flag(void) {
+    return gMPEConfFlag;
+}
+
+void mpe_sys_read_mpe_conf_flag(void) {
+    const char mpe_prop_path[] = MPE_DEFAULT_CONFIG_FILE;
+    char propbuf[512];
+    UINT32 flag = 0;
+    FILE *fp = fopen(mpe_prop_path, "rb");
+    LOGD("%s\n", pMPEVersion);
+    if(!fp) {
+        LOGD("mpe config flag - can't open");
+        gMPEConfFlag = 0;
+        return;
+    }
+    while(fgets(propbuf, sizeof(propbuf), fp)) {
+        if(strstr(propbuf, "mpe_enable=1")) {
+            flag |= MPE_CONF_MPE_ENABLE;
+        } else if(strstr(propbuf, "print_rawdata=1")) {
+            flag |= MPE_CONF_PRT_RAWDATA;
+        } else if(strstr(propbuf, "auto_calib=1")) {
+            flag |= MPE_CONF_AUTO_CALIB;
+        } else if(strstr(propbuf, "indoor_enable=1")) {
+            flag |= MPE_CONF_INDOOR_ENABLE;
+        }
+    }
+    LOGD("mpe config flag %u", flag);
+    fclose(fp);
+    gMPEConfFlag = flag;
+    return;
+}
+
+INT32 mpe_sys_gps_to_sys_time( UINT32 gps_sec ) {
+    return (INT32) ( gps_sec + DIFF_GPS_C_TIME );// difference between GPS and
+}
+
+void mpe_sys_get_time_stamp(double* timetag, UINT32 leap_sec) {
+    struct tm tm_pt;
+    struct timeval tv;
+    //get second and usec
+    gettimeofday(&tv, NULL);
+    //convert to local time
+    localtime_r(&tv.tv_sec, &tm_pt);
+    (*timetag) = mktime(&tm_pt);
+    (*timetag)= (*timetag) + leap_sec +((float)tv.tv_usec)/1000000;
+}
+
+void mnl2mpe_hdlr_init(void) {
+    memset(&mnl_latest_in, 0 , sizeof(MNL2MPE_AIDING_DATA));
+    memset(&mnl_glo_in, 0 , sizeof(MNL2MPE_AIDING_DATA));
+    memset(&mnl_glo_out, 0 , sizeof(MPE2MNL_AIDING_DATA));
+}
+
+int adr2mnl_send_nmea_data(const char * nmea_buffer, const UINT32 length) {
+    LOGD("adr2mnl_send_nmea_data");
+    char buff[MNL_MPE_NMEA_MAX_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_ADR_TYPE_ADR2MNL_NMEA_DATA);
+    put_int(buff, &offset, length);
+    put_binary(buff, &offset, nmea_buffer, length);
+
+    return safe_sendto(MNLD_ADR2MNL_SOCKET, buff, MNL_MPE_NMEA_MAX_SIZE);
+}
+
+int mnl2mpe_hdlr(int fd) {
+    char mnl2mpe_buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int mnl2mpe_offset = 0;
+    int read_len;
+    int log_rec = 0, rec_loc =0;
+    UINT32 type, length;
+
+    read_len = safe_recvfrom(fd, mnl2mpe_buff, sizeof(mnl2mpe_buff));
+    if (read_len <= 0) {
+        LOGE("safe_recvfrom() failed read_len=%d", read_len);
+        return -1;
+    }
+
+    type = get_int(mnl2mpe_buff, &mnl2mpe_offset, sizeof(mnl2mpe_buff));
+    length = get_int(mnl2mpe_buff, &mnl2mpe_offset, sizeof(mnl2mpe_buff));
+    LOGD("mpe recv, type = %u, len = %u", type, length);
+
+    switch (type) {
+        case CMD_SEND_FROM_MNLD: {
+            log_rec = get_int(mnl2mpe_buff, &mnl2mpe_offset, sizeof(mnl2mpe_buff));
+            rec_loc = get_int(mnl2mpe_buff, &mnl2mpe_offset, sizeof(mnl2mpe_buff));
+            get_binary(mnl2mpe_buff, &mnl2mpe_offset, mpe_debuglog_file_name, sizeof(mnl2mpe_buff), sizeof(mpe_debuglog_file_name));
+            LOGD("log_rec =%d, rec_loc=%d, mpelog_path:%s", log_rec, rec_loc,mpe_debuglog_file_name );
+            mpe_log_mtklogger_check((INT16)log_rec, mpe_debuglog_file_name, (INT8)rec_loc);
+            break;
+        }
+        case MNL_ADR_TYPE_MNL2ADR_NMEA_DATA: {
+            char nmea[MNL_MPE_NMEA_MAX_SIZE] = {0};
+            get_binary(mnl2mpe_buff, &mnl2mpe_offset, nmea, sizeof(mnl2mpe_buff), sizeof(nmea));
+            LOGD("rec nmea:%s", nmea);
+            if(length <= MNL_MPE_NMEA_MAX_SIZE) {
+                adr2mnl_send_nmea_data(nmea, length);
+            }
+            break;
+        }
+        default: {
+            LOGD("MPE_DBG: invalid msg type = %d", type);
+        }
+    }
+    return 0;
+}
+
+int mpe_kernel_inject(IMU* data, UINT16 len, MPE2MNL_AIDING_DATA *mnl_out) {
+    int i=0;
+    UNUSED(mnl_out);
+
+    if(data == NULL) {
+        LOGD("allocate sensor cb error\n");
+        return MTK_GPS_ERROR;
+    }
+
+    for(i = 0; i < len; i++ ) {
+        if(data + i != NULL) {
+            if (mpe_sys_get_mpe_conf_flag() & MPE_CONF_PRT_RAWDATA) {
+                LOGD("[%d] MPErpy %"PRId64" %f %f %f %f %f %f %f %f %f %f %lf %lf %lf %lf %lf %lf %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %u %u %f",
+                    i, (data+i)->input_time_gyro,
+                    (data+i)->acceleration[0], (data+i)->acceleration[1], (data+i)->acceleration[2],
+                    (data+i)->angularVelocity[0], (data+i)->angularVelocity[1], (data+i)->angularVelocity[2],
+                    (data+i)->magnetic[0], (data+i)->magnetic[1], (data+i)->magnetic[2],
+                    (data+i)->pressure,
+                    mnl_glo_in.latitude[0], mnl_glo_in.longitude[0], mnl_glo_in.altitude[0],
+                    mnl_glo_in.latitude[1], mnl_glo_in.longitude[1], mnl_glo_in.altitude[1],
+                    mnl_glo_in.LS_velocity[0], mnl_glo_in.LS_velocity[1], mnl_glo_in.LS_velocity[2],
+                    mnl_glo_in.KF_velocity[0], mnl_glo_in.KF_velocity[1], mnl_glo_in.KF_velocity[2],
+                    mnl_glo_in.LS_velocitySigma[0], mnl_glo_in.LS_velocitySigma[1], mnl_glo_in.LS_velocitySigma[2],
+                    mnl_glo_in.KF_velocitySigma[0], mnl_glo_in.KF_velocitySigma[1], mnl_glo_in.KF_velocitySigma[2],
+                    mnl_glo_in.HACC, mnl_glo_in.VACC, mnl_glo_in.HDOP,
+                    mnl_glo_in.confidenceIndex[0], mnl_glo_in.confidenceIndex[1], mnl_glo_in.confidenceIndex[2],
+                    mnl_glo_in.gps_sec, mnl_glo_in.leap_sec, (data+i)->thermometer);
+            }
+
+            /*if (mpe_get_dr_entry(data+i, &mnl_glo_in, mnl_out)) {
+                if (mpe_sys_get_mpe_conf_flag() & MPE_CONF_PRT_RAWDATA) {
+                    LOGD("MPE_DBG: MPE mpe_update_posture return false");
+                }
+            }*/
+        } else {
+            LOGD("accept null data\n");
+        }
+    }
+    return MTK_GPS_SUCCESS;
+}
+
+void mpe_set_mnl_out_flag(MPE2MNL_AIDING_DATA *mnl_out) {
+    //if (mpe_sensor_get_listen_mode() == MPE_START_MODE) {
+    if (0) {
+        mnl_out->valid_flag[MTK_MPE_SYS_FLAG] = 1;
+    } else {
+        mnl_out->valid_flag[MTK_MPE_SYS_FLAG] = 0;
+    }
+    mnl_out->valid_flag[MTK_MPE_RAW_FLAG] = 1;
+    if(isfirst_baro == 1) {
+        mnl_out->barometerHeight= -16000;
+    }
+    if (!(mpe_sys_get_mpe_conf_flag() & MPE_CONF_INDOOR_ENABLE) || gyr_scp_calib_done == 0) {
+        mnl_out->HACC= 20000;
+    }
+}
+
+/*void mpe_sensor_stop_notify( void ) {
+    char mpe2mpe_buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(mpe2mpe_buff, &offset, CMD_STOP_MPE_REQ);
+    put_int(mpe2mpe_buff, &offset, sizeof(INT32));
+    put_int(mpe2mpe_buff, &offset, 2);
+    safe_sendto(MNLD_MPE_SOCKET, mpe2mpe_buff, MNL_MPE_MAX_BUFF_SIZE);
+    isUninit_SE = TRUE;
+    LOGD("send uninit request from listener \n");
+}*/
+
+void mpe_run_algo( void ) {
+    //int data_ret = 0;
+    IMU SE_data[MAX_NUM_SAMPLES];
+    //UINT16 data_cnt = 0;
+    MPE2MNL_AIDING_DATA mnl_out;
+
+    memset(SE_data, 0 ,MAX_NUM_SAMPLES*sizeof(IMU));
+    memset(&mnl_out, 0, sizeof(MPE2MNL_AIDING_DATA));
+
+    //data_cnt = mpe_sensor_acquire_Data(SE_data);
+#if 0
+    if(data_cnt) {
+        data_ret = mpe_kernel_inject(SE_data, data_cnt, &mnl_out);
+        mpe_set_mnl_out_flag(&mnl_out);
+        memcpy(&mnl_glo_out, &mnl_out, sizeof(MPE2MNL_AIDING_DATA));
+    }
+#endif
+    memcpy(&mnl_glo_in, &mnl_latest_in, sizeof(MNL2MPE_AIDING_DATA));
+}
+
+#ifdef __cplusplus
+  extern "C" }
+#endif
+
+#endif //#ifndef MPE_FUSION_MAIN_C
diff --git a/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_sensor.cpp b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_sensor.cpp
new file mode 100644
index 0000000..86e315b
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_sensor.cpp
@@ -0,0 +1,589 @@
+/* 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 <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <dirent.h>
+#include <errno.h>
+#include "mpe_common.h"
+#include "mpe_sensor.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "MPE_SE"
+#endif
+
+#if defined(__ANDROID_OS__)
+/* HIDL */
+#include <sys/prctl.h>
+#include <android/sensor.h>
+#include <android-base/macros.h>
+#include <android/frameworks/sensorservice/1.0/IEventQueue.h>
+#include <android/frameworks/sensorservice/1.0/IEventQueueCallback.h>
+#include <android/frameworks/sensorservice/1.0/ISensorManager.h>
+#include <sensors/convert.h>
+#include <utils/Mutex.h>
+
+using namespace android;
+using android::frameworks::sensorservice::V1_0::ISensorManager;
+using android::frameworks::sensorservice::V1_0::Result;
+using android::hardware::sensors::V1_0::SensorType;
+using android::frameworks::sensorservice::V1_0::IEventQueueCallback;
+using android::hardware::Return;
+using android::hardware::sensors::V1_0::Event;
+using android::frameworks::sensorservice::V1_0::IEventQueue;
+#endif
+
+#define SENSOR_TYPE_DEVICE_PRIVATE_BASE       65536
+#define SENSOR_TYPE_GYRO_TEMPERATURE          (71 + SENSOR_TYPE_DEVICE_PRIVATE_BASE)
+
+#define SENSOR_LOG_SCALE 1e6
+
+unsigned char isfirst_baro = 1;
+UINT32 current_gps_sec = 0;
+
+static unsigned char phone_time_reset = 0;
+static UINT32 current_leap_sec = 18;
+static double mnl_inject_sys_time = 0.0;
+static unsigned char SE_listener_mode = MPE_IDLE_MODE;
+static UINT16 gyr_log_cnt = 0;
+static INT64 gyr_log_time = 0;
+
+//chre data sync
+static UINT16 acc_cnt = 0;
+static UINT16 gyr_cnt = 0;
+static unsigned char prev_data_is_gyro = false;
+static EVENT_DATA acc_samples[MAX_NUM_SAMPLES];
+static EVENT_DATA gyr_samples[MAX_NUM_SAMPLES];
+static EVENT_DATA mag_samples;
+static float bar_samples = 0;
+float gyr_temperature = 0.0f;
+float gyr_scp_calib_done = 0.0f;
+
+static INT8 raw_accuracy[SENSOR_TYPE_MAX] = {0};
+static INT8 calib_accuracy[SENSOR_TYPE_MAX] = {0};
+static unsigned char calib_get_gyro_data = false;
+
+extern FILE *data_file_local;
+extern INT16 u2Log_enable;
+
+typedef enum {
+    SENSOR_ERR   = -1,
+    SENSOR_INIT   = 0,
+    SENSOR_UNINIT = 1,
+} SENSOR_STATUS;
+
+#if defined(__ANDROID_OS__)
+class SensorDeathRecipient : public android::hardware::hidl_death_recipient
+{
+public:
+    // hidl_death_recipient interface
+    virtual void serviceDied(uint64_t cookie,
+            const ::android::wp<::android::hidl::base::V1_0::IBase>& who) override;
+};
+#endif
+
+typedef struct SENSOR_CONTEXT {
+#if defined(__ANDROID_OS__)
+
+    Mutex   mDataLock;
+    int32_t sensorHandle[SENSOR_TYPE_MAX];
+    int     mSensorStatus[SENSOR_TYPE_MAX];
+    sp<IEventQueueCallback> mpListener;
+    sp<IEventQueue> queue;
+    sp<SensorDeathRecipient> mpDeathRecipient;
+#endif
+} SENSOR_CONTEXT;
+
+static SENSOR_CONTEXT sensorContext[SENSOR_USER_ID_MAX];
+
+//-----------------------------------------------------------------------------
+unsigned char mpe_sensor_get_listen_mode(void)
+{
+    return SE_listener_mode;
+}
+
+void mpe_sensor_set_listen_mode(unsigned char mode)
+{
+    LOGD("Set listen mode from %u to %u", SE_listener_mode, mode);
+    SE_listener_mode = mode;
+}
+
+
+UINT16 mpe_sensor_check_time()
+{
+    INT32 mnl_inject_gps_time;
+    double time_diff;
+
+    mnl_inject_gps_time = mpe_sys_gps_to_sys_time(current_gps_sec);
+    time_diff = abs((int)(mnl_inject_sys_time - mnl_inject_gps_time));
+
+    if (time_diff > 3600) {
+        LOGD("Detect change in global time, global: %lf, gps: %d, diff: %lf \n",mnl_inject_sys_time, mnl_inject_gps_time, time_diff);
+        phone_time_reset = 1;
+    } else {
+        phone_time_reset = 0;
+    }
+    return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+void mpe_sensor_get_accuracy(INT8 *accuracy)
+{
+    memcpy(accuracy, raw_accuracy, sizeof(raw_accuracy));
+}
+
+//-----------------------------------------------------------------------------
+
+UINT16 mpe_sensor_acquire_Data (IMU* data)
+{
+    INT16 i = 0, j = 0;
+    UINT16 size = 0;
+
+    //LOGD("SE_Acquire_Data acc_cnt:%u gyr:%u",acc_cnt, gyr_cnt);
+    if (gyr_cnt >= MAX_NUM_SAMPLES || gyr_cnt == 0) {
+        LOGD("MPE_DBG: gyr data abnormal, acc_cnt:%d, gyr_cnt:%d",acc_cnt, gyr_cnt);
+        size = 0;
+    } else if (acc_cnt >= MAX_NUM_SAMPLES || acc_cnt == 0) {
+        LOGD("MPE_DBG: acc data abnormal, acc_cnt:%d, gyr_cnt:%d",acc_cnt, gyr_cnt);
+        size = 0;
+    } else {
+        for(i = 0; i < gyr_cnt; i++) {
+            // acc
+            if(i >= acc_cnt) {
+                j = acc_cnt - 1;
+            } else {
+                j = i;
+            }
+            data[i].acceleration[0] = acc_samples[j].x;
+            data[i].acceleration[1] = acc_samples[j].y;
+            data[i].acceleration[2] = acc_samples[j].z;
+            data[i].acceleration_raw[0] = acc_samples[j].x;
+            data[i].acceleration_raw[1] = acc_samples[j].y;
+            data[i].acceleration_raw[2] = acc_samples[j].z;
+            data[i].input_time_acc = acc_samples[j].timestamp;
+
+            // gyro
+            data[i].angularVelocity[0] = gyr_samples[i].x;
+            data[i].angularVelocity[1] = gyr_samples[i].y;
+            data[i].angularVelocity[2] = gyr_samples[i].z;
+            data[i].angularVelocity_raw[0] = gyr_samples[i].x;
+            data[i].angularVelocity_raw[1] = gyr_samples[i].y;
+            data[i].angularVelocity_raw[2] = gyr_samples[i].z;
+            data[i].input_time_gyro = gyr_samples[i].timestamp;
+            data[i].thermometer = gyr_temperature;
+
+            // mag
+            data[i].magnetic[0] = mag_samples.x;
+            data[i].magnetic[1] = mag_samples.y;
+            data[i].magnetic[2] = mag_samples.z;
+            data[i].magnetic_raw[0] = mag_samples.x;
+            data[i].magnetic_raw[1] = mag_samples.y;
+            data[i].magnetic_raw[2] = mag_samples.z;
+            data[i].input_time_mag = mag_samples.timestamp;
+
+            // pres
+            data[i].pressure = bar_samples;
+        }
+        size = gyr_cnt;
+    }
+    acc_cnt = 0;
+    gyr_cnt = 0;
+    memset(&acc_samples, 0 ,MAX_NUM_SAMPLES*sizeof(EVENT_DATA));
+    memset(&gyr_samples, 0 ,MAX_NUM_SAMPLES*sizeof(EVENT_DATA));
+    return size;
+}
+
+// Update mnl_inject_sys_time, current_gps_sec, current_leap_sec
+void mpe_sensor_update_mnl_sec(UINT32 gps_sec, UINT32 leap_sec)
+{
+    current_gps_sec = gps_sec;
+    current_leap_sec = leap_sec;
+    mpe_sys_get_time_stamp(&mnl_inject_sys_time, current_leap_sec);
+    return;
+}
+
+//-----------------------------------------------------------------------------
+void mpe_sensor_run(void)
+{
+    unsigned char ret = FALSE;
+    INT32 mnl_inject_gps_time;
+
+    LOGD("SE sensor run source\n");
+    mnl_inject_gps_time = mpe_sys_gps_to_sys_time(current_gps_sec);
+    LOGD("mnl_inject_gps_time: %d, mnl_inject_sys_time: %lf",mnl_inject_gps_time, mnl_inject_sys_time);
+    LOGD("global_gps_diff =%lf\n", (fabs(mnl_inject_sys_time - mnl_inject_gps_time)));
+
+    if(fabs(mnl_inject_sys_time - mnl_inject_gps_time) <= 3600.0)
+    {
+        if(!mpe_sys_sensor_threads_create())
+        {
+            return;
+        }
+        mpe_sensor_set_listen_mode(MPE_START_MODE);
+        mpe_log_init();
+
+        //register sensor listener
+        mpe_kernel_initialize();
+        LOGD("SE_sensor_run success");
+    }
+    return;
+}
+
+#if defined(__ANDROID_OS__)
+class CalibListenrCallback : public IEventQueueCallback {
+  public:
+    Return<void> onEvent(const Event &e) {
+        sensors_event_t sensorEvent;
+        android::hardware::sensors::V1_0::implementation::convertToSensorEvent(e, &sensorEvent);
+
+        switch(e.sensorType)
+        {
+            case SensorType::GYROSCOPE:
+                calib_accuracy[SENSOR_TYPE_GYR] = sensorEvent.gyro.status;
+                calib_get_gyro_data = TRUE;
+                break;
+            default:
+                LOGD("unknown type(%d)", sensorEvent.type);
+        }
+        return android::hardware::Void();
+    }
+};
+
+class MpeListenrCallback : public IEventQueueCallback {
+  public:
+    Return<void> onEvent(const Event &e) {
+        sensors_event_t sensorEvent;
+        android::hardware::sensors::V1_0::implementation::convertToSensorEvent(e, &sensorEvent);
+
+        switch(e.sensorType)
+        {
+            case SensorType::ACCELEROMETER:
+                if(prev_data_is_gyro) {
+                    prev_data_is_gyro = false;
+                    mpe_run_algo();
+                }
+                if(acc_cnt < MAX_NUM_SAMPLES) {
+                    acc_samples[acc_cnt].x = sensorEvent.acceleration.x;
+                    acc_samples[acc_cnt].y = sensorEvent.acceleration.y;
+                    acc_samples[acc_cnt].z = sensorEvent.acceleration.z;
+                    acc_samples[acc_cnt].timestamp = sensorEvent.timestamp;
+                    acc_cnt++;
+                    raw_accuracy[SENSOR_TYPE_ACC] = sensorEvent.acceleration.status;
+
+                    if(u2Log_enable && (data_file_local != NULL)) {
+                        fprintf(data_file_local,"$%c%X%c%X%c%X\n",(sensorEvent.acceleration.x<0)?'-':' ',abs((int)(sensorEvent.acceleration.x*SENSOR_LOG_SCALE)),
+                            (sensorEvent.acceleration.y<0)?'-':' ',abs((int)(sensorEvent.acceleration.y*SENSOR_LOG_SCALE)),
+                            (sensorEvent.acceleration.z<0)?'-':' ',abs((int)(sensorEvent.acceleration.z*SENSOR_LOG_SCALE)));
+                    }
+                }
+                break;
+            case SensorType::GYROSCOPE:
+                if(gyr_cnt < MAX_NUM_SAMPLES) {
+                    gyr_samples[gyr_cnt].x = sensorEvent.gyro.x;
+                    gyr_samples[gyr_cnt].y = sensorEvent.gyro.y;
+                    gyr_samples[gyr_cnt].z = sensorEvent.gyro.z;
+                    gyr_samples[gyr_cnt].timestamp = sensorEvent.timestamp;
+                    gyr_cnt++;
+                    raw_accuracy[SENSOR_TYPE_GYR] = sensorEvent.gyro.status;
+                }
+                prev_data_is_gyro = true;
+                if(u2Log_enable && (data_file_local != NULL)) {
+                    if(gyr_log_cnt >= 200 || gyr_log_cnt == 0) {
+                        fprintf(data_file_local,"^ %llX\n",(sensorEvent.timestamp));
+                        gyr_log_cnt = 0;
+                        gyr_log_time = sensorEvent.timestamp;
+                    }
+                    gyr_log_cnt++;
+                    fprintf(data_file_local, "! %X%c%X%c%X%c%X\n",(int)((sensorEvent.timestamp-gyr_log_time)/1000.0),
+                        (sensorEvent.gyro.x<0)?'-':' ',abs((int)(sensorEvent.gyro.x*SENSOR_LOG_SCALE)),
+                        (sensorEvent.gyro.y<0)?'-':' ',abs((int)(sensorEvent.gyro.y*SENSOR_LOG_SCALE)),
+                        (sensorEvent.gyro.z<0)?'-':' ',abs((int)(sensorEvent.gyro.z*SENSOR_LOG_SCALE)));
+                }
+                break;
+            case SensorType::GYROSCOPE_UNCALIBRATED:
+                if(gyr_cnt < MAX_NUM_SAMPLES) {
+                    gyr_samples[gyr_cnt].x = sensorEvent.uncalibrated_gyro.x_uncalib;
+                    gyr_samples[gyr_cnt].y = sensorEvent.uncalibrated_gyro.y_uncalib;
+                    gyr_samples[gyr_cnt].z = sensorEvent.uncalibrated_gyro.z_uncalib;
+                    gyr_samples[gyr_cnt].timestamp = sensorEvent.timestamp;
+                    gyr_cnt++;
+                    raw_accuracy[SENSOR_TYPE_GYR] = 3;
+                }
+                prev_data_is_gyro = true;
+                if(u2Log_enable && (data_file_local != NULL)) {
+                    if(gyr_log_cnt >= 200 || gyr_log_cnt == 0) {
+                        fprintf(data_file_local,"^ %llX\n",(sensorEvent.timestamp));
+                        gyr_log_cnt = 0;
+                        gyr_log_time = sensorEvent.timestamp;
+                    }
+                    gyr_log_cnt++;
+                    fprintf(data_file_local, "! %X%c%X%c%X%c%X%c%X\n",(int)((sensorEvent.timestamp-gyr_log_time)/1000.0),
+                        (sensorEvent.gyro.x<0)?'-':' ',abs((int)(sensorEvent.gyro.x*SENSOR_LOG_SCALE)),
+                        (sensorEvent.gyro.y<0)?'-':' ',abs((int)(sensorEvent.gyro.y*SENSOR_LOG_SCALE)),
+                        (sensorEvent.gyro.z<0)?'-':' ',abs((int)(sensorEvent.gyro.z*SENSOR_LOG_SCALE)),
+                        (gyr_temperature<0)?'-':' ',abs((int)(gyr_temperature*SENSOR_LOG_SCALE)));
+                }
+                break;
+            case SensorType::MAGNETIC_FIELD:
+                mag_samples.x = sensorEvent.magnetic.x;
+                mag_samples.y = sensorEvent.magnetic.y;
+                mag_samples.z = sensorEvent.magnetic.z;
+                mag_samples.timestamp = sensorEvent.timestamp;
+                raw_accuracy[SENSOR_TYPE_MAG] = sensorEvent.magnetic.status;
+                if(u2Log_enable && (data_file_local != NULL)) {
+                    fprintf(data_file_local,"@%c%X%c%X%c%X\n",(sensorEvent.magnetic.x<0)?'-':' ',abs((int)(sensorEvent.magnetic.x*SENSOR_LOG_SCALE)),
+                        (sensorEvent.magnetic.y<0)?'-':' ',abs((int)(sensorEvent.magnetic.y*SENSOR_LOG_SCALE)),
+                        (sensorEvent.magnetic.z<0)?'-':' ',abs((int)(sensorEvent.magnetic.z*SENSOR_LOG_SCALE)));
+                }
+                break;
+            case SensorType::PRESSURE:
+                bar_samples = sensorEvent.pressure;
+                isfirst_baro = 0;
+                if(u2Log_enable && (data_file_local != NULL)) {
+                    fprintf(data_file_local,"~%c%X\n",(bar_samples<0)?'-':' ',abs((int)(bar_samples*SENSOR_LOG_SCALE)));
+                }
+                break;
+            case (android::hardware::sensors::V1_0::SensorType)SENSOR_TYPE_GYRO_TEMPERATURE:
+                gyr_temperature = sensorEvent.data[0];
+                gyr_scp_calib_done = sensorEvent.data[1];
+                break;
+            default:
+                LOGD("unknown type(%d)", sensorEvent.type);
+        }
+        return android::hardware::Void();
+    }
+};
+
+void SensorDeathRecipient::serviceDied(uint64_t, const wp<::android::hidl::base::V1_0::IBase>&)
+{
+
+    Mutex::Autolock lock(sensorContext[SENSOR_USER_ID_MPE].mDataLock);
+    LOGD("Sensor service died. Cleanup sensor manager instance!");
+    sensorContext[SENSOR_USER_ID_MPE].mpListener = NULL;
+    sensorContext[SENSOR_USER_ID_MPE].queue = NULL;
+    sensorContext[SENSOR_USER_ID_MPE].mpDeathRecipient = NULL;
+}
+#endif
+unsigned char mpe_sensor_init(SENSOR_USER_ID id)
+{
+    if (id >= SENSOR_USER_ID_MAX) {
+        LOGD("mpe_sensor_init wrong id=%d", id);
+        return FALSE;
+    }
+#if defined(__ANDROID_OS__)
+    if (id == SENSOR_USER_ID_CALIB) {
+        ::prctl(PR_SET_NAME,"CalibThread", 0, 0, 0);
+    } else if (id == SENSOR_USER_ID_MPE) {
+        ::prctl(PR_SET_NAME,"MpeThread", 0, 0, 0);
+    }
+    sensorContext[id].mpListener = NULL;
+    sensorContext[id].queue = NULL;
+    sensorContext[id].mpDeathRecipient = NULL;
+#endif
+    return TRUE;
+}
+
+unsigned char mpe_sensor_deinit(SENSOR_USER_ID id)
+{
+    if (id >= SENSOR_USER_ID_MAX) {
+        LOGD("mpe_sensor_deinit wrong id=%d", id);
+        return FALSE;
+    }
+#if defined(__ANDROID_OS__)
+    sensorContext[id].mpListener = NULL;
+    sensorContext[id].queue = NULL;
+    sensorContext[id].mpDeathRecipient = NULL;
+#endif
+
+    if (id == SENSOR_USER_ID_MPE) {
+        mpe_log_deinit();
+        mpe_sensor_set_listen_mode(MPE_IDLE_MODE);
+        phone_time_reset = 0;
+        isfirst_baro = 1;
+        acc_cnt = 0;
+        gyr_cnt = 0;
+        gyr_log_cnt = 0;
+        prev_data_is_gyro = false;
+        gyr_temperature = 0;
+        gyr_scp_calib_done = 0;
+    }
+    return TRUE;
+}
+
+unsigned char mpe_sensor_start(SENSOR_USER_ID id, SENSOR_TYPE mpe_type, UINT32 periodInMs)
+{
+#if defined(__ANDROID_OS__)
+    android::hardware::sensors::V1_0::SensorType type;
+
+    LOGD("mpe_sensor_start id=%d type=%d periodMs=%u",id, mpe_type, periodInMs);
+    if (mpe_type == SENSOR_TYPE_ACC) {
+        type = SensorType::ACCELEROMETER;
+    } else if (mpe_type == SENSOR_TYPE_GYR) {
+        type = SensorType::GYROSCOPE;
+    } else if (mpe_type == SENSOR_TYPE_UNCAL_GYR) {
+        type = SensorType::GYROSCOPE_UNCALIBRATED;
+    } else if (mpe_type == SENSOR_TYPE_MAG) {
+        type = SensorType::MAGNETIC_FIELD;
+    } else if (mpe_type == SENSOR_TYPE_BAR) {
+        type = SensorType::PRESSURE;
+    } else if (mpe_type == SENSOR_TYPE_GYR_TMP) {
+        type = (android::hardware::sensors::V1_0::SensorType)SENSOR_TYPE_GYRO_TEMPERATURE;
+    } else {
+        LOGD("unknown type");
+        return FALSE;
+    }
+    Mutex::Autolock lock(sensorContext[id].mDataLock);
+    sensorContext[id].mSensorStatus[mpe_type] = SENSOR_ERR;
+    // sensor HIDL interface
+    sp<ISensorManager> manager = ISensorManager::getService();
+    if (manager == NULL) {
+        LOGD("getService() failed");
+        return FALSE;
+    }
+    if (sensorContext[id].mpDeathRecipient == NULL) {
+        sensorContext[id].mpDeathRecipient = new SensorDeathRecipient();
+        ::android::hardware::Return<bool> linked = manager->linkToDeath(sensorContext[id].mpDeathRecipient, /*cookie*/ 0);
+        if (!linked || !linked.isOk()) {
+            LOGE("Unable to link to sensor service death notifications");
+            return FALSE;
+        }
+    }
+    manager->getDefaultSensor(type,
+        [&](const auto &sensor, Result result) {
+            if (result == Result::OK) {
+                sensorContext[id].sensorHandle[mpe_type] = sensor.sensorHandle;
+            }
+        });
+    if (sensorContext[id].sensorHandle[mpe_type] == 0) {
+        LOGD("getDefaultSensor FAIL!");
+        return FALSE;
+    }
+    Result res;
+    if (sensorContext[id].mpListener == NULL) {
+        if (id == SENSOR_USER_ID_CALIB) {
+            sensorContext[id].mpListener = new CalibListenrCallback();
+        } else if (id == SENSOR_USER_ID_MPE) {
+            sensorContext[id].mpListener = new MpeListenrCallback();
+        }
+        manager->createEventQueue(sensorContext[id].mpListener,
+            [&] (const auto &q, Result result) {
+                if (result == Result::OK) {
+                    sensorContext[id].queue = q;
+                }
+            });
+        if (sensorContext[id].queue == NULL) {
+            LOGD("createEventQueue FAIL!");
+            return FALSE;
+        }
+    }
+    ::android::hardware::Return<Result> _ret =
+        sensorContext[id].queue->enableSensor(
+        sensorContext[id].sensorHandle[mpe_type], periodInMs*1000, 0);
+    if (!_ret.isOk()) {
+            LOGD("enableSensor FAIL!");
+            return FALSE;
+    }
+    sensorContext[id].mSensorStatus[mpe_type] = SENSOR_INIT;
+#endif
+
+    return TRUE;
+}
+
+unsigned char mpe_sensor_stop(SENSOR_USER_ID id, SENSOR_TYPE mpe_type)
+{
+#if defined(__ANDROID_OS__)
+    Mutex::Autolock lock(sensorContext[id].mDataLock);
+
+    LOGD("mpe_sensor_stop id=%d type=%d",id, mpe_type);
+
+    if (sensorContext[id].mSensorStatus[mpe_type] != SENSOR_INIT) {
+        LOGD("mpe_sensor_stop no need");
+        return FALSE;
+    }
+    if (sensorContext[id].queue == NULL) {
+        LOGD("mpe_sensor_stop bypass: serviceDied");
+        return FALSE;
+    }
+    ::android::hardware::Return<Result> _ret =
+        sensorContext[id].queue->disableSensor(sensorContext[id].sensorHandle[mpe_type]);
+    if (!_ret.isOk()) {
+        LOGD("disableSensor FAIL!");
+        return FALSE;
+    }
+    sensorContext[id].mSensorStatus[mpe_type] = SENSOR_UNINIT;
+    sensorContext[id].sensorHandle[mpe_type] = 0;
+#endif
+    return TRUE;
+}
+
+void mpe_sensor_get_calib_accuracy(INT8 *accuracy)
+{
+    memcpy(accuracy, calib_accuracy, sizeof(calib_accuracy));
+}
+
+unsigned char mpe_sensor_get_calib_gyr_data(void)
+{
+    return calib_get_gyro_data;
+}
+
+unsigned char mpe_sensor_check_mnl_response(void)
+{
+    double current_sys_time, delta_input_time;
+
+    mpe_sys_get_time_stamp(&current_sys_time, current_leap_sec);
+    delta_input_time = fabs(current_sys_time - mnl_inject_sys_time);
+
+    LOGD("mpe_sensor_check_mnl_response %lf, %lf %lf %d %d\n",delta_input_time, current_sys_time, mnl_inject_sys_time, phone_time_reset, mpe_sensor_get_listen_mode());
+
+    if (delta_input_time > 2.f || phone_time_reset)
+    {
+        mpe_sensor_set_listen_mode(MPE_IDLE_MODE);
+        LOGD("close SE, dt = %lf, %lf, ,%lf, %u\n",delta_input_time,current_sys_time, mnl_inject_sys_time, phone_time_reset);
+        return FALSE;
+    }
+    return TRUE;
+}
+}
diff --git a/src/connectivity/gps/mtk_mnld/mnl_nlp_interface/inc/Mnld2NlpUtilsInterface.h b/src/connectivity/gps/mtk_mnld/mnl_nlp_interface/inc/Mnld2NlpUtilsInterface.h
new file mode 100644
index 0000000..ea048ef
--- /dev/null
+++ b/src/connectivity/gps/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/mtk_mnld/mnl_nlp_interface/src/Mnld2NlpUtilsInterface.c b/src/connectivity/gps/mtk_mnld/mnl_nlp_interface/src/Mnld2NlpUtilsInterface.c
new file mode 100644
index 0000000..1cadc1b
--- /dev/null
+++ b/src/connectivity/gps/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)) {
+        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) {
+        LOGE("Mnld2NlpUtilsInterface_reqNlpLocation() mtk_socket_write() failed, fd=%p err=[%s]%d",
+            client_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)) {
+        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) {
+        LOGE("Mnld2NlpUtilsInterface_cancelNlpLocation() mtk_socket_write() failed, fd=%p err=[%s]%d",
+            client_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) {
+        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) {
+            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) {
+            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: {
+        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) {
+        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/mtk_mnld/mnld.service b/src/connectivity/gps/mtk_mnld/mnld.service
new file mode 100644
index 0000000..c2a69bf
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=MNL Daemon
+
+[Service]
+ExecStart=/usr/bin/mnld0
+Restart=always
+#StandardOutput=kmsg+console
+
+[Install]
+WantedBy=basic.target
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps.h b/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps.h
new file mode 100644
index 0000000..11804f3
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps.h
@@ -0,0 +1,2234 @@
+/*
+ * 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
+
+/*
+ * 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/mtk_mnld/mnld_entity/hardware/gps_internal.h b/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps_internal.h
new file mode 100644
index 0000000..67a16e8
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/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/mtk_mnld/mnld_entity/hardware/gps_mtk.h b/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps_mtk.h
new file mode 100644
index 0000000..df13674
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps_mtk.h
@@ -0,0 +1,698 @@
+/*
+ * 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 ////////////////////////////
+
+/** 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;
+
+} GpsLocation_ext;
+
+
+typedef struct {
+    GnssSvInfo legacySvInfo;
+
+    /// v1.0 ///
+    float carrier_frequency;
+
+} 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;
+
+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.
+     */
+    double agc_level_db;
+} GnssMeasurement_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. */
+    GnssClock clock;
+} 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);
+
+/** 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;
+    gnss_request_location_callback request_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);
+} GnssConfigurationInterface_ext;
+
+
+#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/mtk_mnld/mnld_entity/inc/epo.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/epo.h
new file mode 100644
index 0000000..d72ce08
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/epo.h
@@ -0,0 +1,61 @@
+#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 EPO_MD5_FILE_MAX_SIZE   500
+
+#define GPS_EPO_FILE_LEN  32
+#define GPS_EPO_URL_LEN 256
+
+typedef struct EPO_Status {
+    unsigned int EPO_piece_flag[MAX_EPO_PIECE];
+    int last_DL_Date;
+    int today_retry_time;
+} EPO_Status_T;
+
+#ifdef CONFIG_GPS_MT3303
+void __getEpoUrl(char* filename, char* url);
+#endif
+
+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);
+void GpsToUtcTime(int i2Wn, double dfTow, time_t* uSecond);
+void getEpoUrl(char * filename, char * url);
+int mtk_gps_sys_epo_ga_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond);
+int mtk_gps_sys_read_lock(int fd, off_t offset, int whence, off_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps.h
new file mode 100644
index 0000000..596499c
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps.h
@@ -0,0 +1,2233 @@
+/*
+ * 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
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+#ifdef __ANDROID_OS__
+#include <hardware/hardware.h>
+#endif
+__BEGIN_DECLS
+
+/*
+ * 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 /* ANDROID_INCLUDE_HARDWARE_GPS_H */
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps_controller.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps_controller.h
new file mode 100644
index 0000000..6b94470
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps_controller.h
@@ -0,0 +1,68 @@
+#ifndef __GPS_CONTROLER_H__
+#define __GPS_CONTROLER_H__
+
+// #include <time.h>
+// #include <stdint.h>
+#include <stdbool.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MNLD_VERSION "MTK_MNLD_5_5_0_18011501"
+
+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);
+
+void gps_control_kernel_wakelock_init();
+void gps_control_kernel_wakelock_take();
+void gps_control_kernel_wakelock_give();
+void gps_control_kernel_wakelock_uninit();
+
+bool mnl_offload_is_enabled(void);
+void mnl_offload_set_enabled(void);
+void mnl_offload_clear_enabled(void);
+bool mnld_offload_is_auto_mode(void);
+bool mnld_offload_is_always_on_mode(void);
+bool mnld_support_auto_switch_mode(void);
+void mnld_offload_check_capability(void);
+
+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_agps_session_done(void);
+void gps_controller_rcv_pmtk(const char* pmtk);
+
+void get_chip_sv_support_capability(unsigned char* sv_type);
+#ifdef CONFIG_GPS_MT3303
+int gps_driver_state_init(void);
+void gps_control_mnl_set_status(void);
+void gps_control_mnl_set_pwrctl(void);
+int mnl_set_pwrctl(unsigned char pwrctl);
+
+int mnl_set_rdelay(int delay) ;
+
+int mnl_get_rdelay(void) ;
+
+
+#endif
+
+#if ANDROID_MNLD_PROP_SUPPORT
+int get_gps_cmcc_log_enabled();
+#endif
+
+bool mnld_timeout_ne_enabled(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps_dbg_log.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps_dbg_log.h
new file mode 100644
index 0000000..a00d7f7
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps_dbg_log.h
@@ -0,0 +1,79 @@
+#ifndef __GPS_DBG_LOG_H__
+#define __GPS_DBG_LOG_H__
+
+#include "mtk_gps_type.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         "mtklog/gpsdbglog/"
+#define LOG_FILE_EXTEN_NAME ".nma"
+#define LOG_FILE_WRITING_EXTEN_NAME ".nmac"
+
+#if defined(__ANDROID_OS_P__)
+#define GPS_LOG_PERSIST_STATE "vendor.gpsdbglog.enable"
+#define GPS_LOG_PERSIST_PATH "vendor.gpsdbglog.path"
+#define GPS_LOG_PERSIST_FLNM "vendor.gpsdbglog.file"
+#elif defined(__ANDROID_OS_O__)
+#define GPS_LOG_PERSIST_STATE "debug.gpsdbglog.enable"
+#define GPS_LOG_PERSIST_PATH "debug.gpsdbglog.path"
+#define GPS_LOG_PERSIST_FLNM "debug.gpsdbglog.file"
+#endif
+
+#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_DIR_SIZE       (3UL*1024*1024*1024)
+#define MAX_DBG_LOG_FILE_SIZE      (25UL*1024*1024)
+
+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,
+};
+// Task synchronization related type
+typedef enum{
+  MNLD_MUTEX_PINGPANG_WRITE = 0,
+  MNLD_MUTEX_MAX
+} mnld_mutex_enum;
+
+int gps_dbg_log_thread_init();
+
+int create_mtklogger2mnl_fd();
+
+int mtklogger2mnl_hdlr(int fd);
+
+size_t gps_log_dir_check(char * dirname);
+
+void gps_stop_dbglog_release_condition(void);
+
+void mtklogger_mped_reboot_message_update(void);
+int mnl_debug_file_check(char * dbg_file);
+//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) ;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/hal_mnl_interface_common.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/hal_mnl_interface_common.h
new file mode 100644
index 0000000..a77e739
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/hal_mnl_interface_common.h
@@ -0,0 +1,1350 @@
+#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           (16 * 1024)
+#define HAL_MNL_INTERFACE_VERSION   1
+
+//======================================================
+// GPS HAL -> MNLD
+//======================================================
+#define MTK_HAL2MNL "mtk_hal2mnl"
+
+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_SEND_PMTK                       = 701,
+} 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
+
+//======================================================
+// 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_cmd;
+
+#define MTK_MNLD_GNSS_MAX_SVS            64
+#define GPS_MAX_MEASUREMENT     32
+#define MTK_MNLD_GNSS_MAX_MEASUREMENT    64
+
+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
+
+typedef int gps_capabilites;
+#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
+
+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
+
+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;
+} gps_location;
+
+typedef struct {
+    int16_t   svid;
+    uint8_t   constellation;
+    float   c_n0_dbhz;
+    float   elevation;
+    float   azimuth;
+    uint8_t flags;
+    float     carrier_frequency;
+} 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 {
+    /**
+     * 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;
+} 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;
+
+    /**
+       * 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;
+} 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;
+
+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[40];
+} 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;
+} gnss_nav_msg;
+
+#if 0
+void dump_gps_location(gps_location in);
+void dump_gnss_sv(gnss_sv in);
+void dump_gnss_sv_info(gnss_sv_info in);
+void dump_gps_data(gps_data in);
+void dump_gps_measurement(gps_measurement in);
+void dump_gps_clock(gps_clock in);
+void dump_gps_nav_msg(gps_nav_msg in);
+void dump_gnss_data(gnss_data in);
+void dump_gnss_measurement(gnss_measurement in);
+void dump_gnss_clock(gnss_clock in);
+void dump_gnss_nav_msg(gnss_nav_msg in);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnl2hal_interface.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnl2hal_interface.h
new file mode 100644
index 0000000..34a275f
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnl2hal_interface.h
@@ -0,0 +1,89 @@
+#ifndef __MNL2HAL_INTERFACE_H__
+#define __MNL2HAL_INTERFACE_H__
+
+#include "hal_mnl_interface_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    void (*hal_reboot)();
+
+    void (*gps_init)();
+    void (*gps_start)();
+    void (*gps_stop)();
+    void (*gps_cleanup)();
+
+    void (*gps_inject_time)(int64_t time, int64_t time_reference, int uncertainty);
+    void (*gps_inject_location)(double lat, double lng, float acc);
+    void (*gps_delete_aiding_data)(int flags);
+    void (*gps_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)(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)(char* msg, int len);
+    void (*ni_respond)(int notif_id, ni_user_response_type user_response);
+
+    void (*update_network_state)(int connected, network_type type, int roaming,
+        const char* extra_info);
+    void (*update_network_availability)(int available, const char* apn);
+
+    void (*set_gps_measurement)(bool enabled, bool enableFullTracking);
+    void (*set_gps_navigation)(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);
+	#if defined(__LINUX_OS__)
+    void (*send_pmtk)(char* msg, int len);
+    #endif
+} hal2mnl_interface;
+
+int mnl2hal_mnld_reboot();
+
+int mnl2hal_location(gps_location location);
+int mnl2hal_gps_status(gps_status status);
+int mnl2hal_gps_sv(gnss_sv_info sv);
+int mnl2hal_nmea(int64_t timestamp, const char* nmea, int length);
+int mnl2hal_gps_capabilities(gps_capabilites capabilities);
+int mnl2hal_gps_measurements(gps_data data);
+int mnl2hal_gps_navigation(gps_nav_msg msg);
+int mnl2hal_gnss_measurements(gnss_data data);
+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);
+int mnl2hal_release_data_conn();
+int mnl2hal_request_ni_notify(int session_id, 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);
+
+// -1 means failure
+int hal2mnl_hdlr(int fd, hal2mnl_interface* hdlr);
+
+// -1 means failure
+int create_hal2mnl_fd();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnl_common.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnl_common.h
new file mode 100644
index 0000000..0914002
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnl_common.h
@@ -0,0 +1,209 @@
+/* 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
+
+#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  -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
+/****************************************************************************** 
+ * 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;
+
+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_gps[32];
+    char bee_path[32];
+    char epo_file[30];
+    char epo_update_file[30];
+    char qepo_file[30];
+    char qepo_update_file[30];
+    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 fix_interval;    /* fix interval in milliseconds */
+
+    /*for pps*/
+    int pps_mode;    /* 1PPS mode, Default: MTK_PPS_3D_FIX */
+    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
+/*---------------------------------------------------------------------------*/
+C_EXT int  mnl_utl_load_property(MNL_CONFIG_T* prConfig);
+/*---------------------------------------------------------------------------*/
+#undef C_EXT
+/*---------------------------------------------------------------------------*/
+
+int str2int(const char*  p, const char*  end);
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnld.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnld.h
new file mode 100644
index 0000000..230abfd
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnld.h
@@ -0,0 +1,229 @@
+#ifndef __MNLD_H__
+#define __MNLD_H__
+
+#include <time.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "mnl2hal_interface.h"
+#include "mtk_socket_utils.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"
+#ifdef CONFIG_GPS_MT3303
+#define MNLD_MT3333_CONTROLLER_SOCKET     "mnld_mt3333_controller_socket"
+#endif
+
+#ifdef MTK_ADR_SUPPORT
+#define MNLD_MPE_SOCKET                 "mnl2adr_socket"
+#else
+#define MNLD_MPE_SOCKET                 "mnld_mpe_socket"
+#endif
+#define META_TO_MNLD_SOCKET             "mtk_meta2mnld"
+#define DEBUG_TO_MNLD_SOCKET            "mtk_debugService2mnld"
+#define MNLD_TO_DEBUG_SOCKET            "mtk_mnld2debugService"
+
+#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      (5 * 1000)
+#define MNLD_GPS_LOG_HANDLER_TIMEOUT    (60 * 1000)
+#define MNLD_GPS_SWITCH_OFL_MODE_TIMEOUT (30 * 1000)
+
+#define MNLD_INTERNAL_BUFF_SIZE         (8 * 1024)
+#define MNLD_TO_APP_BUFF_SIZE           (1023)
+
+
+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;
+
+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,
+} mnld_gps_event;
+
+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,
+} 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;
+    int fd_agps;
+    int fd_flp;
+    int fd_flp_test;
+    int fd_geofence;
+    int fd_at_cmd;
+    int fd_int;
+    int fd_mtklogger;
+    int fd_mtklogger_client;
+    int fd_meta;
+    int fd_debug;
+    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_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;
+    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;
+
+    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 struct {
+    mnld_fds            fds;
+    mnld_gps_status     gps_status;
+    mnl_epo_status      epo_status;
+} mnld_context;
+
+// 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);
+
+// 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();
+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);
+
+int mtk_gps_get_gps_user(void);
+
+void factory_mnld_gps_start(void);
+void factory_mnld_gps_stop(void);
+
+void flp_test2mnl_gps_start(void);
+void flp_test2mnl_gps_stop(void);
+
+int is_flp_user_exist();
+int is_geofence_user_exist();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnld_utile.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnld_utile.h
new file mode 100644
index 0000000..93e2a89
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnld_utile.h
@@ -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.
+ */
+ #define PMTK_MAX_PKT_LENGTH     256
+ #define MNL_GPS_DATA_PATH_MAX_LENGTH 256
+
+/*****************************************************************************
+ * 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(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(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(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, 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, 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: hide location sensitivity log;
+ *****************************************************************************/
+int mtk_gps_log_is_hide(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mnl_init_gps_data_path
+ * DESCRIPTION
+ *  To create all levels of the appointed path
+ *  data_path  [IN]: the full path
+ *  length     [IN]: the length of the path
+ * RETURNS
+ *  0: Create all levels successed; -1: Failed to create path;
+ *****************************************************************************/
+int mnl_init_gps_data_path(const char* data_path, const int length);
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mpe.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mpe.h
new file mode 100644
index 0000000..cc8929d
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mpe.h
@@ -0,0 +1,24 @@
+#ifndef __MPE_H__
+#define __MPE_H__
+
+#include "mtk_gps_type.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int mpe_function_init(int self_recv);
+int mnl_mpe_thread_init();
+int mnl2mpe_set_log_path(char* path, int status_flag, int mode_flag);
+int mnl2adr_gps_open(void);
+int mnl2adr_gps_close(void);
+int mnl2adr_mnl_reboot(void);
+int mnl2adr_open_gps_done(void);
+int mnl2adr_close_gps_done(void);
+int mnl2adr_send_nmea_data(const char * nmea_buffer, const UINT32 length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mt3333_controller.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mt3333_controller.h
new file mode 100644
index 0000000..dba8c34
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mt3333_controller.h
@@ -0,0 +1,76 @@
+#ifndef __MT3333_CONTROLLER_H__
+#define __MT3333_CONTROLLER_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "mtk_gps.h"
+#include "mtk_auto_log.h"
+
+#if defined(__ANDROID_OS_10__) || defined(CONFIG_GPS_MT3303_TTYS1)
+#define  MT3333_CONTROLLER_TTY_NAME       "/dev/ttyS1"
+#else
+#define  MT3333_CONTROLLER_TTY_NAME       "/dev/ttyS2"
+#endif
+
+typedef enum {
+    MAIN_MT3333_CONTROLLER_EVENT_GPSREBOOT,
+    MAIN_MT3333_CONTROLLER_EVENT_GPSENABLE,
+    MAIN_MT3333_CONTROLLER_EVENT_GPSSTART,
+    MAIN_MT3333_CONTROLLER_EVENT_GPSSTOP,
+    MAIN_MT3333_CONTROLLER_EVENT_GPSDISABLE,
+    MAIN_MT3333_CONTROLLER_EVENT_GPSDELETEAIDING,
+    MAIN_MT3333_CONTROLLER_EVENT_REQUES1STNMEA,
+    MAIN_MT3333_CONTROLLER_EVENT_REQUESTNTP,
+    MAIN_MT3333_CONTROLLER_EVENT_REQUESTNLP,
+    MAIN_MT3333_CONTROLLER_EVENT_REQUESTEPO,
+    MAIN_MT3333_CONTROLLER_EVENT_REQUESTQEPO,
+    MAIN_MT3333_CONTROLLER_EVENT_ENABLEDEBUGLOG,
+    MAIN_MT3333_CONTROLLER_EVENT_DISABLEDEBUGLOG,
+    MAIN_MT3333_CONTROLLER_EVENT_ONCEPERSECOND,
+    MAIN_MT3333_CONTROLLER_EVENT_FACTORYMETA,
+    MAIN_MT3333_CONTROLLER_EVENT_ENABLEDEASYMODE,
+    MAIN_MT3333_CONTROLLER_EVENT_DISABLEDEASYMODE,
+    MAIN_MT3333_CONTROLLER_EVENT_NMEA_ONOFF,
+    MAIN_MT3333_CONTROLLER_EVENT_GNSS_SYSTEM,
+    MAIN_MT3333_CONTROLLER_EVENT_GNSS_FIXINTERVAL,
+    MAIN_MT3333_CONTROLLER_EVENT_PPS_CONFIG,
+#ifdef MTK_ADR_SUPPORT
+    MAIN_MT3333_CONTROLLER_EVENT_PMTK876_NMEA_ONOFF,
+#endif
+} main_mt3333_controller_event;
+
+int mt3333_controller_Utc2GpsTime(unsigned short* pi2Wn, unsigned int* pdfTow, unsigned int* sys_time);
+
+int mt3333_controller_init() ;
+int mt3333_controller_delete_aiding_data(int flags);
+
+int mt3333_controller_inject_location(double latitude, double longitude, float accuracy);
+
+int mt3333_controller_inject_time(int64_t time, int64_t timeReference, int uncertainty);
+int mt3333_controller_inject_epo(int qepo);
+
+int mt3333_controller_socket_send_cmd(main_mt3333_controller_event cmd);
+
+void* mt3333_thread_control(void *arg);
+void* mt3333_thread_data(void *arg);
+void* mt3333_thread_data_debug( void*  arg );
+
+int mt3333_controller_set_baudrate_length_parity_stopbits(int fd, unsigned int new_baudrate, int length, char parity_c, int stopbits);
+int mt3333_controller_set_gnss_working_satellite_system(MTK_GNSS_CONFIGURATION gnssmode);
+int mt3333_controller_set_gnss_position_fix_interval(int fix_interval);
+int mt3333_controller_set_pps_config(int pps_mode, int pps_duty);
+
+int mt3333_controller_check_uart_baudrate(void);
+int mt3333_controller_check_if_gpsfunctionok(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mtknav.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mtknav.h
new file mode 100644
index 0000000..a818666
--- /dev/null
+++ b/src/connectivity/gps/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/mtk_mnld/mnld_entity/inc/nmea_parser.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/nmea_parser.h
new file mode 100644
index 0000000..518944a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/nmea_parser.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 __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,
+} SV_TYPE;
+
+/*****************************************************************/
+/*****************************************************************/
+/*****                                                       *****/
+/*****       N M E A   P A R S E R                           *****/
+/*****                                                       *****/
+/*****************************************************************/
+/*****************************************************************/
+#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 nmea_reader_addc(NmeaReader* const r, int   c);
+void mtk_mnl_nmea_parser_process(const char * buffer, UINT32 length);
+extern int op01_log_write_internal(const char* log);
+int get_gps_nmea_parser_end_status();
+void nmea_reader_init(NmeaReader* const r);
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/op01_log.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/op01_log.h
new file mode 100644
index 0000000..fca0fde
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/op01_log.h
@@ -0,0 +1,22 @@
+#ifndef __OP01_LOG_H__
+#define __OP01_LOG_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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/mtk_mnld/mnld_entity/inc/qepo.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/qepo.h
new file mode 100644
index 0000000..c32d998
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/qepo.h
@@ -0,0 +1,62 @@
+#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
+
+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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/epo.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/epo.c
new file mode 100644
index 0000000..92f601b
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/epo.c
@@ -0,0 +1,1867 @@
+// SPDX-License-Identifier: MediaTekProprietary
+#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 <inttypes.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_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "epo"
+#endif
+
+/*smart_phone*/
+//#define EPO_URL_1 "https://ogepodownload.mediatek.com/"
+//#define EPO_URL_2 "https://oepodownload.mediatek.com/"
+#define EPO_URL_1 "https://aepodownload.mediatek.com/"
+#define EPO_URL_2 "https://aepodownload.mediatek.com/"
+
+#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 epo_data_updated = 0;
+static int gps_epo_period = 3;
+static int wifi_epo_period = 3;
+#ifndef CONFIG_GPS_MT3303
+static int gps_epo_download_days = MTK_EPO_DEFAULT_DL_DAY;
+#else
+int gps_epo_download_days = MTK_EPO_DEFAULT_DL_DAY;
+#endif
+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;
+    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
+        sprintf(szMode, "rb");
+        break;
+    case MTK_FS_WRITE:      // 1
+        sprintf(szMode, "wb");
+        break;
+    case MTK_FS_APPEND:     // 2
+        sprintf(szMode, "ab");
+        break;
+    case MTK_FS_RW:         // 3
+        sprintf(szMode, "r+b");
+        break;
+    case MTK_FS_RW_DISCARD: // 4
+        sprintf(szMode, "w+b");
+        break;
+    case MTK_FS_RW_APPEND:  // 5
+        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)
+{
+    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;
+}
+
+#ifndef CONFIG_GPS_MT3303
+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);
+    }
+}
+#else
+void epo_update_epo_file() {
+    
+}
+time_t epo_get_now_time(){
+	return time(NULL);
+}
+#endif
+
+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};
+    unsigned 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, (char *)gen_md5_str, MTK_EPO_MD5_STR_LEN) == MTK_GPS_ERROR) {
+        LOGE("Gen md5 str failed");
+        fclose(fp_epo);
+        return MTK_GPS_ERROR;
+    }
+    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';
+    fclose(fp_md5);
+    if (read_len <= 0) {
+        return MTK_GPS_ERROR;
+    }
+
+    if(strncmp((const char *)gen_md5_str, (const char *)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};
+    char md5[MD5_DIGEST_LENGTH] = {0};
+    int i;
+
+    if (f == NULL || md_str == NULL) {
+        //LOGE("NULL pointer: f=0x%08x, md_str=0x%08x", f, md_str);
+        LOGE("NULL pointer");
+        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((uint8_t *)&(md5[0]),&c);
+
+    for (i=0; i<MD5_DIGEST_LENGTH; i++)
+    {
+        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++)
+    {
+        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) {
+    UNUSED(retry_time);
+    int ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+    if (mnld_is_gps_or_ofl_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 {
+                LOGE("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_or_ofl_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, MTK_GPS_DATA_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;
+                }
+            }
+            fclose(fp);
+        } else {
+            LOGE("Open merged file fp=NULL\n");
+        }
+        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;
+    int max_sv_num;
+    int max_segment_size;
+    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("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("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("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 {
+                    LOGE("%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
+            }
+            LOGW("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) {
+        LOGD("'=' is not found!!\n");
+        return -1;       // 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, *val;
+    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__);
+            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);
+    }
+
+    fclose(fp);
+    return 1;
+}
+
+/*****************************************************************************/
+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) {
+    LOGD("size: %zu, nmemb: %zu", size, nmemb);
+    size_t written;
+    written = fwrite(ptr, size, nmemb, stream);
+    if(written < nmemb) {
+        LOGE("error: written %zu", written);
+    }
+    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) {
+            LOGE("fopen %s failed.errno:%d, reson: %s", filename, errno, strerror(errno));
+            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);
+        res = curl_easy_perform(curl);
+        if(res != CURLE_OK){
+            LOGE("failed: %s", curl_easy_strerror(res));
+        }
+        curl_easy_cleanup(curl);
+        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(char* filename, char* url) {
+    char count_str[15] = {0};
+
+    if (counter <= 1) {
+        strncat(url, EPO_URL_1, GPS_EPO_URL_LEN - strlen(url));
+    } else {
+        strncat(url, EPO_URL_2, GPS_EPO_URL_LEN -strlen(url));
+    }
+
+    strncat(url, filename, GPS_EPO_URL_LEN  - strlen(url));
+    strncat(url, "?retryCount=", GPS_EPO_URL_LEN  - strlen(url));
+    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);
+    LOGD("curl_easy_download result: %d", res);
+
+    filesize = get_file_size(gps_epo_md5_file_name);
+
+    if (filesize <= 0 || filesize > EPO_MD5_FILE_MAX_SIZE) {
+        res = CURLE_READ_ERROR;
+        LOGE("error:download file size %d, EPO_MD5_FILE_MAX_SIZE %d.", filesize, EPO_MD5_FILE_MAX_SIZE);
+    }
+
+    //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;
+}
+
+#ifndef CONFIG_GPS_MT3303
+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);
+                }
+                fclose(fp);
+            } else {
+                LOGE("Open merged file fp=NULL\n");
+            }
+            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;
+}
+#else
+void __getEpoUrl(char* filename, char* url) {
+    char count_str[15] = {0};
+
+    if (counter <= 1) {
+        strcat(url, "https://mgepodownload.mediatek.com/");
+    } else {
+        strcat(url, "https://mepodownload.mediatek.com/");
+    }
+    strcat(url, filename);
+    strcat(url, "?retryCount=");
+    sprintf(count_str, "%d", counter-1);
+    strcat(url, count_str);
+    LOGD("url = %s\n", url);
+}
+
+CURLcode curl_easy_download_epo(void) {
+    int res_val;
+    CURLcode res;
+    char gps_epo_data_file_name[60] = {0};
+    char url[256]={0};
+
+    LOGD("curl_easy_download_epo");
+    __getEpoUrl(gps_epo_file_name, url);
+    strcat(gps_epo_data_file_name, "/data/misc/gps/");
+    strcat(gps_epo_data_file_name, gps_epo_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);
+                }
+                fclose(fp);
+            } else {
+                LOGE("Open merged file fp=NULL\n");
+            }
+            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;
+}
+#endif
+
+#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;
+}
+#endif
+
+/*****************************************************************************/
+/*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, MTK_GPS_DATA_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, MTK_GPS_DATA_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, MTK_GPS_DATA_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;
+}*/
+
+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("download epo file completed!file count=%d, epo_download_result=%d\n",
+        gps_epo_file_count, ret);
+
+    mnld_epo_download_done(ret);
+
+    //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: {
+        LOGW("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;
+}
+
+/*static void epo_downloader_thread_timeout() {
+    if (mnld_timeout_ne_enabled() == false) {
+        LOGE("epo_downloader_thread_timeout() dump and exit.");
+        mnld_block_exit();
+    } else {
+        LOGE("epo_downloader_thread_timeout() crash here for debugging");
+        CRASH_TO_DEBUG();
+    }
+}*/
+
+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];
+    memset(&events, 0, sizeof(events));
+
+    UNUSED(arg);
+
+    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_epo) == -1) {
+        LOGE("epoll_add_fd() failed for g_fd_epo failed");
+        return 0;
+    }
+    while (1) {
+        int i;
+        int n;
+        LOGD("wait");
+        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;
+            }
+        }
+        //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("unknown fd=%d",
+                    events[i].data.fd);
+            }
+        }
+        //stop_timer(hdlr_timer);
+    }
+
+    LOGE("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/mtk_mnld/mnld_entity/src/flashdownload/DOWNLOAD.H b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/DOWNLOAD.H
new file mode 100644
index 0000000..18b0827
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/DOWNLOAD.H
@@ -0,0 +1,121 @@
+/*******************************************************************************

+*  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) 2016

+*

+*******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *      download.h

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *   This file is intends for download agent specific definition

+ *

+ *******************************************************************************/

+#ifndef _DOWNLOAD_H_

+#define _DOWNLOAD_H_

+

+/* DA Version */

+#define DA_MAJOR_VER    0x04

+#define DA_MINOR_VER    0x00

+

+

+/* RETURN VALUE */

+#define HW_ERROR              0x1c

+#define HW_RAM_OK             0xE0

+#define HW_RAM_FLOARTING      0xE1

+#define HW_RAM_UNACCESSABLE   0xE2

+#define HW_RAM_ERROR          0xE3

+#define SOC_FAIL              0x0c

+#define SYNC_CHAR             0xc0

+#define CONT_CHAR             0x69

+#define STOP_CHAR             0x96

+#define ACK                   0x5a

+#define NACK                  0xa5

+#define UNKNOWN_CMD           0xbb

+

+/* FLASH OPERATION STATUS */

+typedef enum {

+    S_DONE = 0

+   ,S_PGM_FAILED

+   ,S_ERASE_FAILED

+   ,S_TIMEOUT

+   ,S_IN_PROGRESS

+   ,S_CMD_ERR

+   ,S_BLOCK_LOCKED_ERR

+   ,S_BLOCK_UNSTABLE

+   ,S_VPP_RANGE_ERR

+   ,S_ERASE_ADDR_ERR

+   ,S_ERASE_RANGE_ERR

+   ,S_PGM_AT_ODD_ADDR

+   ,S_PGM_WITH_ODD_LENGTH

+   ,S_BUFPGM_NO_SUPPORT

+   ,S_UNKNOWN_ERR

+} STATUS_E;

+

+/* COMMANDS */

+#define DA_EXT_CLOCK_CMD        0xD0

+#define DA_BBCHIP_TYPE_CMD      0xD1

+#define DA_SPEED_CMD            0xD2

+#define DA_MEM_CMD              0xD3

+#define DA_FORMAT_CMD           0xD4

+#define DA_WRITE_CMD            0xD5

+#define DA_READ_CMD             0xD6

+#define DA_WRITE_REG16_CMD      0xD7

+#define DA_READ_REG16_CMD       0xD8

+#define DA_FINISH_CMD           0xD9

+#define DA_GET_DSP_VER_CMD      0xDA

+#define DA_ENABLE_WATCHDOG_CMD  0xDB

+

+/* SPEED_PARA */

+typedef enum {

+   UART_BAUD_921600  = 0x01,

+   UART_BAUD_460800  = 0x02,

+   UART_BAUD_230400  = 0x03,

+   UART_BAUD_115200  = 0x04,

+   UART_BAUD_57600   = 0x05,

+   UART_BAUD_38400   = 0x06,

+   UART_BAUD_19200   = 0x07,

+   UART_BAUD_14400   = 0x08,

+   UART_BAUD_9600    = 0x09,

+   UART_BAUD_4800    = 0x0a,

+   UART_BAUD_2400    = 0x0b,

+   UART_BAUD_1200    = 0x0c,

+   UART_BAUD_300     = 0x0d,

+   UART_BAUD_110     = 0x0e,

+   UART_BAUD_AUTO    = 0x0f,	

+   

+}UART_BAUDRATE;

+

+typedef enum

+{

+   TIMEOUT_DATA = 0,

+   CKSUM_ERROR,

+   RX_BUFFER_FULL,

+   TIMEOUT_CKSUM_LSB,

+   TIMEOUT_CKSUM_MSB,

+   ERASE_TIMEOUT,

+   PROGRAM_TIMEOUT,

+   RECOVERY_BUFFER_FULL,

+   UNKNOWN_ERROR

+}eRX_error;

+

+/* DEVICE_INFO */

+typedef enum

+{

+   DEVICE_TV0057A003AABD,

+   DEVICE_LAST = DEVICE_TV0057A003AABD,

+   DEVICE_UNKNOWN = 0xFF         // Unknown Device 

+}DEVICE_INFO;

+

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/GPS_AIO_Flash_Download_Sample_Code_MCU_Base.zip b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/GPS_AIO_Flash_Download_Sample_Code_MCU_Base.zip
new file mode 100644
index 0000000..ef05251
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/GPS_AIO_Flash_Download_Sample_Code_MCU_Base.zip
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/GPS_DL_api.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/GPS_DL_api.h
new file mode 100644
index 0000000..15ee44d
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/GPS_DL_api.h
@@ -0,0 +1,88 @@
+/*******************************************************************************

+*  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) 2016

+*

+******************************************************************************/

+

+/*******************************************************************************

+* Filename:

+* ---------

+*  GPS_DL_api.h

+*

+* Project:

+* --------

+*  GPS Download Library.

+*

+*******************************************************************************/

+#ifndef _GPS_DL_API_H_

+#define _GPS_DL_API_H_

+

+

+#define MAX_GPS_IMAGE_NUM 16

+

+#define GPS_FW_DOWNLOAD_OK 0

+#define GPS_FW_DOWNLOAD_UPLOAD_ERR -1  

+

+typedef int (*CALLBACK_DOWNLOAD_PROGRESS_INIT)(void *usr_arg);

+typedef int (*CALLBACK_DOWNLOAD_PROGRESS)(unsigned char finished_percentage,

+                                           unsigned int finished_bytes,

+                                           unsigned int total_bytes, void *usr_arg);

+

+typedef int (*CALLBACK_CONN_BROM_WRITE_BUF_INIT)(void *usr_arg);

+typedef int (*CALLBACK_CONN_BROM_WRITE_BUF)(unsigned char finished_percentage,

+                                           unsigned int sent_bytes,

+                                           unsigned int total_bytes, void *usr_arg);

+

+typedef struct{

+    const unsigned char     *m_image;  //buffer to store DA image

+    unsigned int            m_size;    //DA image size

+}GPS_DA;

+

+typedef struct{

+    const unsigned char     *m_image; // buffer to store firmware image 

+    unsigned int            m_size;   // firmware image size

+}GPS_Image;

+

+typedef struct{

+    unsigned int    m_num;

+    GPS_Image       m_image_list[MAX_GPS_IMAGE_NUM];

+}GPS_Image_List;

+

+typedef struct{

+   unsigned int      m_packet_length;

+   unsigned char     m_num_of_unchanged_data_blocks;

+   const unsigned char     *m_buf;

+   unsigned int      m_len;   

+   unsigned int      m_begin_addr; 

+   unsigned int      m_end_addr;

+}ROM_HANDLE_T;

+

+typedef struct{

+    int                                 m_bEnableLog;                   //can be used to enable or disable debug log

+    int *                               m_p_bootstop;                   //can be used to stop download process

+    CALLBACK_CONN_BROM_WRITE_BUF_INIT   m_cb_download_conn_da_init;     //callback function which is invoked at the beginning of DA transimitting.

+    void *                              m_cb_download_conn_da_init_arg; // parameter of the callback function upper

+    CALLBACK_CONN_BROM_WRITE_BUF        m_cb_download_conn_da;          //callback function which is invoked during the DA transimitting.

+    void *                              m_cb_download_conn_da_arg;      // parameter of the callback function upper

+}GPS_DA_Arg;

+

+typedef struct{

+    CALLBACK_DOWNLOAD_PROGRESS_INIT     m_cb_download_conn_init;        //callback function which is invoked at the beginning of firmware transimitting.

+    void *                              m_cb_download_conn_init_arg;    // parameter of the callback function upper

+    CALLBACK_DOWNLOAD_PROGRESS          m_cb_download_conn;             //callback function which is invoked during the firmware transimitting.

+    void *                              m_cb_download_conn_arg;         // parameter of the callback function upper

+    CALLBACK_CONN_BROM_WRITE_BUF_INIT   m_cb_download_conn_da_init;     //callback function which is invoked at the beginning of DA transimitting.

+    void *                              m_cb_download_conn_da_init_arg; // parameter of the callback function upper

+    CALLBACK_CONN_BROM_WRITE_BUF        m_cb_download_conn_da;          //callback function which is invoked during the DA transimitting.

+    void *                              m_cb_download_conn_da_arg;

+    int                                 m_bEnableLog;                   //can be used to enable or disable debug log

+    int *                               m_p_bootstop;                   //can be used to stop download process

+}GPS_Download_Arg;

+

+

+

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/bbchip_id.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/bbchip_id.h
new file mode 100644
index 0000000..58c3f41
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/bbchip_id.h
@@ -0,0 +1,38 @@
+/*******************************************************************************

+ *  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) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  bbchip_id.h

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *  Baseband Chip Information.

+ *

+ *******************************************************************************/

+#ifndef  _ROM_ID_H_

+#define  _ROM_ID_H_

+

+//-----------------------------------------------------------------------------

+// FAT info                                                                    

+//-----------------------------------------------------------------------------

+typedef struct FlashDeviceKey {

+   unsigned short m_ManufactureId;

+   unsigned short m_DeviceCode;

+   unsigned short m_ExtDeviceCode1;

+   unsigned short m_ExtDeviceCode2;

+}s_FlashDeviceKey;

+

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom.h
new file mode 100644
index 0000000..6df8387
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom.h
@@ -0,0 +1,105 @@
+/*******************************************************************************

+ *  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) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  brom.h

+ *

+ * Project:

+ * --------

+ *  BootRom Library

+ *

+ *******************************************************************************/

+#ifndef _BROM_H_

+#define _BROM_H_

+

+

+#ifdef   __cplusplus

+extern "C" {

+#endif

+

+// The magic value to stop boot process 

+#define BOOT_STOP 9876

+

+

+//------------------------------------------------------------------------------

+// Boolean                                                                      

+//------------------------------------------------------------------------------

+typedef enum {

+   _FALSE = 0,

+   _TRUE = 1

+} _BOOL;

+

+//------------------------------------------------------------------------------

+// return code                                                                  

+//------------------------------------------------------------------------------

+

+#define BROM_RET(ret)   (ret&0x00FF0000)

+

+#define BROM_OK                           0x000000

+#define BROM_ERROR                        0x010000

+#define BROM_NO_MEMORY                    0x020000

+#define BROM_INVALID_ARGUMENTS            0x030000

+#define BROM_SET_COM_STATE_FAIL           0x040000

+#define BROM_PURGE_COM_FAIL               0x050000

+#define BROM_SET_META_REG_FAIL            0x060000

+#define BROM_SET_FLASHTOOL_REG_FAIL       0x070000

+#define BROM_SET_REMAP_REG_FAIL           0x080000

+#define BROM_SET_MEM_WAIT_STATE_FAIL      0x090000

+#define BROM_DOWNLOAD_DA_FAIL             0x0A0000

+#define BROM_CMD_START_FAIL               0x0B0000

+#define BROM_CMD_JUMP_FAIL                0x0C0000

+#define BROM_CMD_WRITE16_MEM_FAIL         0x0D0000

+#define BROM_CMD_READ16_MEM_FAIL          0x0E0000

+#define BROM_CMD_WRITE16_REG_FAIL         0x0F0000

+#define BROM_CMD_READ16_REG_FAIL          0x100000

+#define BROM_CMD_CHKSUM16_MEM_FAIL        0x110000

+#define BROM_CMD_WRITE32_MEM_FAIL         0x120000

+#define BROM_CMD_READ32_MEM_FAIL          0x130000

+#define BROM_CMD_WRITE32_REG_FAIL         0x140000

+#define BROM_CMD_READ32_REG_FAIL          0x150000

+#define BROM_CMD_CHKSUM32_MEM_FAIL        0x160000

+#define BROM_WR16_RD16_MEM_RESULT_DIFF    0x170000

+#define BROM_WR16_RD16_REG_RESULT_DIFF    0x180000

+#define BROM_WR32_RD32_MEM_RESULT_DIFF    0x190000

+#define BROM_WR32_RD32_REG_RESULT_DIFF    0x1A0000

+#define BROM_CHKSUM16_MEM_RESULT_DIFF     0x1B0000

+#define BROM_CHKSUM32_MEM_RESULT_DIFF     0x1C0000

+#define BROM_BBCHIP_HW_VER_INCORRECT      0x1D0000

+#define BROM_FAIL_TO_GET_BBCHIP_HW_VER    0x1E0000

+#define BROM_SKIP_BBCHIP_HW_VER_CHECK     0x1F0000

+#define BROM_UNKNOWN_BBCHIP               0x200000

+#define BROM_UNKNOWN_TGT_BBCHIP           0x210000

+#define BROM_BBCHIP_DSP_VER_INCORRECT     0x220000

+#define BROM_MULTIPLE_BAUDRATE_FAIL       0x230000

+#define BROM_JUMP_TO_NFB_DETECTION_FAIL   0x240000

+

+

+//------------------------------------------------------------------------------

+// boot FlashTool download mode                                                 

+//------------------------------------------------------------------------------

+typedef struct BOOT_FLASHTOOL_ARG{

+

+   // Download Agent 

+   unsigned int         m_da_start_addr;     // DA start address 

+   const unsigned char  *m_da_buf;           // buffer stored DA code 

+   unsigned int         m_da_len;            // length of DA buffer 

+

+} s_BOOT_FLASHTOOL_ARG;

+

+

+#ifdef   __cplusplus

+}

+#endif

+

+#endif

+

+

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_base.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_base.c
new file mode 100644
index 0000000..2ed1deb
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_base.c
@@ -0,0 +1,376 @@
+#ifdef CONFIG_GPS_MT3303

+

+/*******************************************************************************

+ *  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) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  brom_base.cpp

+ *

+ * Project:

+ * --------

+ *  BootRom Library

+ *

+ * Description:

+ * ------------

+ *  BootRom communication functions implementation which are used to sync with BootRom.

+ *

+ *******************************************************************************/

+#include "DOWNLOAD.H"

+#include "brom_base.h"

+#include "GPS_DL_api.h"

+#include "flashtool.h"

+#include "sw_types.h"

+#include "gps_uart.h"

+#include <string.h>

+

+#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 <unistd.h>

+#include <mtk_auto_log.h>

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "flashtool"

+#endif

+

+// BootRom Command 

+#define BOOT_ROM_WRITE_CMD    0xA1

+#define BOOT_ROM_CHECKSUM_CMD 0xA4

+#define BOOT_ROM_JUMP_CMD     0xA8

+

+

+//------------------------------------------------------------------------------

+// bootrom command                                                              

+//------------------------------------------------------------------------------

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_WriteBuf

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to download 'download agent' file(DA) to target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  u1BaseAddr: the start address of DA in internal SRAM.

+ *  buf_in: DA file buffer.

+ *  num_of_byte: DA file size.

+ *

+ *******************************************************************************/

+int BRom_WriteBuf(

+      GPS_Download_Arg arg,

+      unsigned int ulBaseAddr,

+      const unsigned char *buf_in, unsigned int num_of_byte)

+{

+    const unsigned char *buf = (const unsigned char *)buf_in;

+    unsigned short data;

+    unsigned int num_of_word = (num_of_byte+1)/2;

+    int err;

+    unsigned char rate;

+    unsigned int finish_rate = 0;

+    unsigned int i = 0;

+    unsigned short checksum = 0;

+    unsigned short brom_checksum = 0;

+    unsigned int accuracy;

+    unsigned char write_buf[10];

+    unsigned char read_buf[10];

+    int j;

+

+    if( NULL==buf || 0>=num_of_byte )

+    {

+        return 1;

+    }

+

+    //Callback function of DA download initialize

+    if (arg.m_cb_download_conn_da_init != NULL)

+    {

+        arg.m_cb_download_conn_da_init(arg.m_cb_download_conn_da_init_arg);

+    }

+

+   if(BRom_CmdSend(arg, BOOT_ROM_WRITE_CMD ))

+      return 2;

+

+   LOGE("[FUNET]BRom_Base::BRom_WriteBuf(): Send BaseAddr ");

+   

+   if((err=BRom_OutData(arg, ulBaseAddr)))

+   {

+       LOGE( "[FUNET]BRom_Base::BRom_WriteBuf(): BRom_OutData(%x): send base address fail!, Err(%d).", ulBaseAddr, err );

+       return 3;

+   }

+   

+   if((err=BRom_OutData(arg, num_of_word)))

+   {

+       LOGE( "[FUNET]BRom_Base::BRom_WriteBuf(): BRom_OutData(%d): send number of word fail!, num_of_byte(%d), Err(%d).", num_of_word, num_of_byte, err );

+        return 4;

+   }

+

+   // Set finish rate of callback function to 100(%)

+   accuracy = 100;

+   

+   LOGE( "[FUNET]BRom_Base::BRom_WriteBuf(): DA download Start ");

+

+   while( i < num_of_byte )

+   {

+       if( NULL!=arg.m_p_bootstop && BOOT_STOP==(*(arg.m_p_bootstop)) )

+       {

+           LOGE("[FUNET]BRom_Base::WriteData(): BOOT_STOP!, m_p_bootstop(0x%08X)=%u. ", (unsigned int)arg.m_p_bootstop, *(arg.m_p_bootstop));

+          return 1;

+       }

+

+         // copy from buf to write_buf by swap order

+         for(j=0; j<10; j+=2)

+         {

+            write_buf[j] = buf[i+j+1];

+            write_buf[j+1] = buf[i+j];

+

+            data = (((unsigned short)write_buf[j])<<8)&0xFF00;

+            data |= ((unsigned short)write_buf[j+1])&0x00FF;

+

+            // update checksum

+            checksum ^= data;

+         }

+

+         // write 

+         // This function should be implemented by user.

+         GPS_UART_PutByte_Buffer((uint32 *) write_buf, 10);

+         

+

+         // read bootrom echo to verify

+         // This function should be implemented by user.

+         GPS_UART_GetByte_Buffer((uint32 *) read_buf, 10);

+

+         LOGE("[FUNET]BRom_Base::BRom_WriteBuf(): Progress(%d%%),already:%d, to_do:%d ", (int)((float)i/(float)num_of_byte*100.0f),i,num_of_byte);

+         

+         if(memcmp(write_buf, read_buf, 10))

+         {

+             LOGE( "[FUNET]BRom_Base::BRom_WriteBuf(): write_buf={ %x, %x, %x, %x, %x, %x, %x, %x, %x, %x }. ", write_buf[0], write_buf[1], write_buf[2], write_buf[3], write_buf[4], write_buf[5], write_buf[6], write_buf[7], write_buf[8], write_buf[9]);

+             LOGE( "[FUNET]BRom_Base::BRom_WriteBuf():  read_buf={ %x, %x, %x, %x, %x, %x, %x, %x, %x, %x }. ", read_buf[0], read_buf[1], read_buf[2], read_buf[3], read_buf[4], read_buf[5], read_buf[6], read_buf[7], read_buf[8], read_buf[9]);

+             LOGE("[FUNET]BRom_Base::BRom_WriteBuf(): write_buf != read_buf  ");

+            return 8;

+         }

+

+         // increase by 10, because we send 5 WORDs each time 

+         i += 10;

+         

+        //Callback function of DA download

+        if (arg.m_cb_download_conn_da!= NULL)

+        {

+             if( accuracy < (rate=(unsigned int)(((float)i/num_of_byte)*accuracy)) )

+             {

+                rate = accuracy;

+             }

+

+             if( 0 < (rate-finish_rate) )

+             {

+                finish_rate = rate;

+                // progress callback 

+                arg.m_cb_download_conn_da((unsigned char)finish_rate, i, num_of_byte, arg.m_cb_download_conn_da_arg);

+             }

+        }

+

+   }

+

+   // perform checksum verification

+   if((err=BRom_CheckSumCmd(arg, ulBaseAddr, num_of_word, &brom_checksum)))

+   {

+      LOGE( "[FUNET]BRom_Base::BRom_WriteBuf(): BRom_CheckSumCmd() fail!, Err(%d). ", err);

+      return 9;

+   }

+

+/*to_do_debug

+   // compare checksum

+   if( checksum != brom_checksum )

+   {

+       LOGE("[FUNET]BRom_Base::BRom_WriteBuf(): checksum error!, checksum(%x) != brom_checksum(%x) ", checksum, brom_checksum);

+      return 10;

+   }

+   else

+   {*/

+       LOGI("[FUNET]BRom_Base::BRom_WriteBuf(): checksum ok!, checksum(%x) == brom_checksum(%x). ", checksum, brom_checksum);

+   /*}*/

+

+   return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_CheckSumCmd

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to request checksum which be calculated on target side.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  u1BaseAddr: the start address of DA in internal SRAM.

+ *  num_of_byte: DA file size.

+ *

+ * Output:

+ * --------

+ *  result: the received checksum. 

+ *

+ *******************************************************************************/

+int BRom_CheckSumCmd(GPS_Download_Arg arg, unsigned int ulBaseAddr, unsigned int num_of_word, unsigned short *result)

+{

+   int ret;

+

+   if(BRom_CmdSend(arg, BOOT_ROM_CHECKSUM_CMD ))

+      return 1;

+

+   if((ret=BRom_OutData(arg, ulBaseAddr)))

+   {

+      LOGE("[FUNET]BRom_Base::BRom_CheckSumCmd(): BRom_OutData(%x): send base address fail!, Err(%d). ", ulBaseAddr, ret);

+      return 2;

+   }

+   

+   if((ret=BRom_OutData(arg, num_of_word)))

+   {

+      LOGE("[FUNET]BRom_Base::BRom_CheckSumCmd(): BRom_OutData(%d): send number of word fail!, Err(%d). ", num_of_word, ret);

+      return 3;

+   }

+

+   *result = GPS_UART_GetData16();

+

+   return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_JumpCmd

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to jump to DA start address to execute DA in internal SRAM.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  addr: the start address of DA in internal SRAM.

+ *

+ *******************************************************************************/

+int BRom_JumpCmd(GPS_Download_Arg arg, unsigned int addr)

+{

+   int ret;

+   

+   if(BRom_CmdSend(arg, BOOT_ROM_JUMP_CMD ))

+      return 1;

+

+   if((ret=BRom_OutData(arg, addr)))

+   {

+       LOGE("[FUNET]BRom_Base::BRom_JumpCmd(): BRom_OutData(%x): send jump address fail!, Err(%d). ", addr, ret);

+      return 2;

+   }

+   return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_CmdSend

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send one byte data to UART and check received data.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  cmd: the ont byte data want to be sent.

+ *

+ *******************************************************************************/

+

+int BRom_CmdSend(GPS_Download_Arg arg, unsigned char cmd)

+{

+   unsigned char result;

+   unsigned char *p_result;

+

+   p_result = &result;

+   

+   if( NULL!=arg.m_p_bootstop && BOOT_STOP==(*(arg.m_p_bootstop)) ) 

+   {

+       LOGE("BRom_StartCmd: BOOT_STOP!, m_p_bootstop(0x%08X)=%u.", (unsigned int)arg.m_p_bootstop, *(arg.m_p_bootstop));

+       return (BROM_CMD_START_FAIL+6);

+   }

+

+   GPS_UART_PutByte(cmd); 

+   

+   *p_result = GPS_UART_GetByte();

+

+   if( cmd != *p_result )

+   {

+     LOGE("BRom_Base::BRom_CmdSend(0x%02X): bootrom response is incorrect!, cmd(0x%02X) != result(0x%02X).", cmd, cmd, *p_result);

+      return 4;

+   }

+   else

+      return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_OutData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send 32-bits data to UART and check received data.

+ *  'BL_PRINT' is a sample to output debug log.

+ *  GPS_UART_PutData32/GPS_UART_GetData32 should be implemented by user.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  data: 32-bits data want to be sent.

+ *

+ *******************************************************************************/

+int BRom_OutData(GPS_Download_Arg arg, unsigned int data)

+{

+   unsigned int tmp32;

+

+   if( NULL!=arg.m_p_bootstop && BOOT_STOP==(*(arg.m_p_bootstop)) ) 

+   {

+       LOGE("BRom_StartCmd: BOOT_STOP!, m_p_bootstop(0x%08X)=%u.", (unsigned int)arg.m_p_bootstop, *(arg.m_p_bootstop));

+       return (BROM_CMD_START_FAIL+6);

+   }

+

+   GPS_UART_PutData32(data);

+   

+    tmp32 = GPS_UART_GetData32();

+

+    if (tmp32 != data)

+     return 4;

+

+   return 0;

+}

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_base.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_base.h
new file mode 100644
index 0000000..ca8df29
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_base.h
@@ -0,0 +1,178 @@
+/*******************************************************************************

+ *  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) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  brom_base.h

+ *

+ * Project:

+ * --------

+ *  BootRom Library

+ *

+ * Description:

+ * ------------

+ *  BootRom communication functions implementation which are used to sync with BootRom.

+ *

+ *******************************************************************************/

+#ifndef   _BROM_BASE_H_

+#define   _BROM_BASE_H_

+

+#include "brom.h"

+#include "bbchip_id.h"

+#include "GPS_DL_api.h"

+#include <stdio.h>

+   

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_StartCmd

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send SYNC_CHAR to build connection with bootRom.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *

+ *******************************************************************************/

+int BRom_StartCmd(GPS_Download_Arg arg);

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  Boot_FlashTool

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to build connection with bootRom and download DA to target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  p_arg: download arguments structure includes start address, DA buffer and DA length.

+ *

+ *******************************************************************************/

+int Boot_FlashTool(const s_BOOT_FLASHTOOL_ARG  *p_arg, GPS_Download_Arg arg);

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_WriteBuf

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to download 'download agent' file(DA) to target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  u1BaseAddr: the start address of DA in internal SRAM.

+ *  buf_in: DA file buffer.

+ *  num_of_byte: DA file size.

+ *

+ *******************************************************************************/

+int BRom_WriteBuf(GPS_Download_Arg arg,

+                        unsigned int ulBaseAddr,

+                        const unsigned char *buf_in, 

+                        unsigned int num_of_byte);

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_CheckSumCmd

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to request checksum which be calculated on target side.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  u1BaseAddr: the start address of DA in internal SRAM.

+ *  num_of_byte: DA file size.

+ *

+ * Output:

+ * --------

+ *  result: the received checksum. 

+ *

+ *******************************************************************************/

+int BRom_CheckSumCmd(GPS_Download_Arg arg, unsigned int baseaddr,

+                        unsigned int num_of_word, unsigned short *result);

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_JumpCmd

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to jump to DA start address to execute DA in internal SRAM.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  addr: the start address of DA in internal SRAM.

+ *

+ *******************************************************************************/

+int BRom_JumpCmd(GPS_Download_Arg arg, unsigned int addr);

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_CmdSend

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send one byte data to UART and check received data.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  cmd: the ont byte data want to be sent.

+ *

+ *******************************************************************************/

+int BRom_CmdSend(GPS_Download_Arg arg, unsigned char cmd);

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_OutData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send 32-bits data to UART and check received data.

+ *  'BL_PRINT' is a sample to output debug log.

+ *  GPS_UART_PutData32/GPS_UART_GetData32 should be implemented by user.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  data: 32-bits data want to be sent.

+ *

+ *******************************************************************************/

+int BRom_OutData(GPS_Download_Arg arg, unsigned int data);

+

+#endif

+//-----------------------------------------------------------------------------

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_mt3301.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_mt3301.c
new file mode 100644
index 0000000..f725f50
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_mt3301.c
@@ -0,0 +1,318 @@
+#ifdef CONFIG_GPS_MT3303

+

+/*******************************************************************************

+ *  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) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  brom_mt3301.cpp

+ *

+ * Project:

+ * --------

+ *  BootRom Library

+ *

+ * Description:

+ * ------------

+ *  BootRom communication functions implementation which are used to sync with BootRom.

+ *

+ *******************************************************************************/

+#include <stdio.h>

+#include "flashtool.h"

+#include "gps_uart.h"

+#include "brom_base.h"

+#include "sw_types.h"

+

+

+#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 <unistd.h>

+#include "mt3333_controller.h"

+#include "mnl_common.h"

+#include "gps_controller.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "flashtool"

+#endif

+

+// MT3301 BootRom Start Command

+#define MT3301_BOOT_ROM_START_CMD1      0xA0

+#define MT3301_BOOT_ROM_START_CMD2      0x0A

+#define MT3301_BOOT_ROM_START_CMD3      0x50

+#define MT3301_BOOT_ROM_START_CMD4      0x05

+

+#define NMEA_START_CMD1         '$'

+#define NMEA_START_CMD2         'P'

+#define NMEA_START_CMD3         'M'

+#define NMEA_START_CMD4         'T'

+#define NMEA_START_CMD5         'K'

+#define NMEA_START_CMD6         '1'

+#define NMEA_START_CMD7         '8'

+#define NMEA_START_CMD8         '0'

+#define NMEA_START_CMD9         '*'

+#define NMEA_START_CMD10        '3'

+#define NMEA_START_CMD11        'B'

+#define NMEA_START_CMD12      0x0D

+#define NMEA_START_CMD13      0x0A

+

+

+static const unsigned char MT3301_BOOT_ROM_START_CMD[] =

+{

+   MT3301_BOOT_ROM_START_CMD1,

+   MT3301_BOOT_ROM_START_CMD2,

+   MT3301_BOOT_ROM_START_CMD3,

+   MT3301_BOOT_ROM_START_CMD4

+};                              

+

+static unsigned char NMEA_START_CMD[] =

+{

+   NMEA_START_CMD1,

+   NMEA_START_CMD2,

+   NMEA_START_CMD3,

+   NMEA_START_CMD4,

+   NMEA_START_CMD5,

+   NMEA_START_CMD6,

+   NMEA_START_CMD7,

+   NMEA_START_CMD8,

+   NMEA_START_CMD9,

+   NMEA_START_CMD10, 

+   NMEA_START_CMD11, 

+   NMEA_START_CMD12, 

+   NMEA_START_CMD13 

+};                              

+extern int g_fd_mt3333_data;    

+extern MNL_CONFIG_T mnld_cfg;

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_StartCmd

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send SYNC_CHAR to build connection with bootRom.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *

+ *******************************************************************************/

+int BRom_StartCmd(GPS_Download_Arg arg)

+{

+    unsigned char data8;

+    unsigned long i;

+    unsigned char tmp8;

+    unsigned long cnt = 0;

+    int retry_max=5;

+#if 0

+    LOGE("[FUNET]Send PMTK180 to force MT3333/39 into boot rom mode");

+    //Send PMTK180 to force 3333 into boot rom

+    GPS_UART_PutByte_Buffer((unsigned long *)NMEA_START_CMD, sizeof(NMEA_START_CMD));

+    if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(g_fd_mt3333_data ,115200, 8, 'N', 1)){

+        LOGE("configure uart baudrate failed");

+        return 1;

+    }

+    //delay 500ms. 

+    usleep(500 * 1000);

+    GPS_UART_IgnoreData();

+

+#else

+    LOGE("[FUNET]Send PMTK180 to force MT3333/39 into boot rom mode");

+    //Send PMTK180 to force 3333 into boot rom

+    if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(g_fd_mt3333_data ,921600, 8, 'N', 1)){

+        LOGE("configure uart baudrate failed");

+        return 1;

+    }

+    GPS_UART_PutByte_Buffer((unsigned long *)NMEA_START_CMD, sizeof(NMEA_START_CMD));

+    //delay 500ms. 

+    usleep(500 * 1000);

+    GPS_UART_IgnoreData();

+

+    UNUSED(arg);

+    //usleep(3000 * 1000);

+    if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(g_fd_mt3333_data ,115200, 8, 'N', 1)){

+        LOGE("configure uart baudrate failed");

+        return 1;

+    }

+

+    LOGI("[FUNET]Send first sync char111");

+    //mnl_get_rdelay();

+    //mnl_set_rdelay(1500);

+    //mnl_get_rdelay();

+    pthread_mutex_t mutx = PTHREAD_MUTEX_INITIALIZER;

+

+HADK_AWAKE_BEGIN:

+    cnt = 0;

+    pthread_mutex_lock(&mutx);

+    //for(int j=0; j<2048 ;j++){GPS_UART_PutByte(MT3301_BOOT_ROM_START_CMD[0]);}

+    mnl_set_pwrctl(0);

+    mnl_set_pwrctl(1);

+    GPS_UART_PutByte(MT3301_BOOT_ROM_START_CMD[0]);

+    pthread_mutex_unlock(&mutx);

+#endif

+    while(1)

+    {

+        GPS_UART_PutByte(MT3301_BOOT_ROM_START_CMD[0]); //First start command sync char

+        if(1 == GPS_UART_GetByte_NO_TIMEOUT(&data8))

+        {

+             tmp8 = 0x5F;

+             LOGE("[FUNET]Received data:%x", data8);

+             if(tmp8 == data8)

+             {

+                 LOGE("[FUNET] First char sync ok");

+                 goto SECOND_CHAR;    

+             }

+        }

+        else

+        {

+            LOGE("[FUNET]No data received");

+        }

+

+        cnt++;

+        if (cnt > 20000)

+        {

+            cnt = 0;

+            retry_max--;

+            LOGE("[FUNET] First char sync timeout,retry=%d",retry_max);

+            if(retry_max > 0){

+                mnl_set_pwrctl(0);

+                usleep(100 * 1000);

+                goto HADK_AWAKE_BEGIN;

+            }

+            return 1;

+        }

+    }

+

+

+SECOND_CHAR:

+    cnt=0;

+    GPS_UART_IgnoreData();

+    LOGE("[FUNET]Sync second char");

+

+    i = 1;

+    GPS_UART_PutByte(MT3301_BOOT_ROM_START_CMD[i]); //2nd sync char

+    tmp8 = 0xF5; // ~MT3301_BOOT_ROM_START_CMD[i]

+SECOND_CHAR_1:    

+    data8 = GPS_UART_GetByte();

+    if(tmp8 != data8)

+    {

+        LOGE("[FUNET]Wrong ack data received:%x", data8);

+        if(data8 == 0x5F){

+            goto SECOND_CHAR_1;

+        }

+        retry_max--;

+        LOGE("[FUNET] Second char sync timeout,retry=%d",retry_max);

+        if(retry_max > 0){

+            mnl_set_pwrctl(0);

+            usleep(100 * 1000);

+            goto HADK_AWAKE_BEGIN;

+        }

+        return 1;

+    }

+

+    LOGE("[FUNET]Sync third char");

+    i = 2;

+    GPS_UART_PutByte(MT3301_BOOT_ROM_START_CMD[i]); //3rd sync char

+    tmp8 = 0xAF;

+    data8 = GPS_UART_GetByte();

+    if(tmp8 != data8)

+    {

+        LOGE( "[FUNET]Wrong ack data received:%x", data8);

+        

+        retry_max--;

+        LOGE("[FUNET] Third char sync timeout,retry=%d",retry_max);

+        if(retry_max > 0){

+            mnl_set_pwrctl(0);

+            usleep(100 * 1000);

+            goto HADK_AWAKE_BEGIN;

+        }

+        return 1;

+    }

+

+    LOGE("[FUNET]Sync forth char");

+    i = 3;

+    GPS_UART_PutByte(MT3301_BOOT_ROM_START_CMD[i]); //4th sync char

+    tmp8 = 0xFA;

+    data8 = GPS_UART_GetByte();

+    if(tmp8 != data8)

+    {

+        LOGE("[FUNET]Wrong ack data received:%x", data8);

+        

+        retry_max--;

+        LOGE("[FUNET] Four char sync timeout,retry=%d",retry_max);

+        if(retry_max > 0){

+            mnl_set_pwrctl(0);

+            usleep(100 * 1000);

+            goto HADK_AWAKE_BEGIN;

+        }

+        return 1;

+    }

+

+    return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  Boot_FlashTool

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to build connection with bootRom and download DA to target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  p_arg: download arguments structure includes start address, DA buffer and DA length.

+ *

+ *******************************************************************************/

+int Boot_FlashTool(const s_BOOT_FLASHTOOL_ARG  *p_arg, GPS_Download_Arg arg)

+{

+   // check data

+   if( NULL == p_arg )

+      return BROM_INVALID_ARGUMENTS;

+

+   LOGI("[FUNET]Enter BRom_StartCmd");

+

+   // send start command 

+   if( BRom_StartCmd(arg) )

+   {

+       return BROM_CMD_START_FAIL;

+   }

+   LOGI( "[FUNET]Start Command Sync Done");

+

+   if(BRom_WriteBuf(arg, p_arg->m_da_start_addr, p_arg->m_da_buf, p_arg->m_da_len))

+   {

+      return BROM_DOWNLOAD_DA_FAIL;

+   }

+

+   LOGI("[FUNET]Boot_FlashTool: BRom_WriteBuf() Pass!");

+

+   // jump to m_da_start_addr to execute DA code on Internal SRAM 

+   if(BRom_JumpCmd( arg, p_arg->m_da_start_addr ))

+      return BROM_CMD_JUMP_FAIL;

+   LOGI("[FUNET]Boot_FlashTool: BRom_JumpCmd() Pass!");

+   return BROM_OK;

+}

+//------------------------------------------------------------------------------

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.c
new file mode 100644
index 0000000..567e737
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.c
@@ -0,0 +1,774 @@
+#ifdef CONFIG_GPS_MT3303

+

+/*******************************************************************************

+ *  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) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  da_cmd.cpp

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *  DA(Download Agent) handshake command.

+ *

+ *******************************************************************************/

+#include "brom_base.h"

+#include "da_cmd.h"

+#include "sw_types.h"

+#include "gps_uart.h"

+#include <string.h>

+

+#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 <unistd.h>

+#include "mt3333_controller.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "flashtool"

+#endif

+

+#define UART_BAUDRATE_SYNC_RETRY      50

+#define PACKET_RE_TRANSMISSION_TIMES   3

+#define DA_FLASH_ERASE_WAITING_TIME      1000

+

+const unsigned int g_BaudrateTable[] = {

+   921600,  // 0x01 

+   460800,  // 0x02 

+   230400,  // 0x03 

+   115200,  // 0x04 

+   57600,   // 0x05 

+   38400,   // 0x06 

+   19200,   // 0x07 

+   9600,    // 0x08 

+   4800,    // 0x09 

+   2400,    // 0x0a 

+   1200,    // 0x0b 

+   300,     // 0x0c

+   110,     // 0x0d

+   14400    // 0x0e

+};

+extern int g_fd_mt3333_data;

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  WriteData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send firmware data to target.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  write_buf: data buffer want to be sent.

+ *  write_len: data length.

+ *

+ *******************************************************************************/

+int WriteData(GPS_Download_Arg arg, const void *write_buf, unsigned int write_len) {

+

+    unsigned int BytesOfWriiten = 0;

+    unsigned int rest_of_bytes = 0;

+    unsigned long wbytes = 0;

+    unsigned short RetryCount = 0;

+

+    if( NULL == write_buf || 0 >= write_len ) {

+        LOGE("DA_cmd::WriteData(): invalid arguments, write_buf(0x%08X), write_len(%u).", (unsigned int)write_buf, write_len);

+        return 1;

+    }

+

+    RetryCount = 0;

+    BytesOfWriiten = 0;

+    while( BytesOfWriiten < write_len ) 

+    {

+        // check stop flag 

+        if( NULL!=arg.m_p_bootstop && BOOT_STOP==*(arg.m_p_bootstop) ) {

+            LOGE( "DA_cmd::WriteData(): m_stopflag(0x%08X)=%d, force to stop!", (unsigned int)arg.m_p_bootstop, *(arg.m_p_bootstop));

+            return 2;

+        }

+        wbytes = 0;

+        rest_of_bytes = write_len-BytesOfWriiten;

+        GPS_UART_PutByte_Buffer((uint32 *) write_buf, rest_of_bytes);

+

+        //update write bytes

+        BytesOfWriiten += rest_of_bytes;

+

+    }

+

+    LOGE("DA_cmd::WriteData(): OK. total=(%u/%u).", BytesOfWriiten, write_len);

+    return 0;

+}

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  ReadData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to read ack from target.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  read_buf: data buffer want to be read.

+ *  read_len: data length.

+ *

+ *******************************************************************************/

+int ReadData(GPS_Download_Arg arg, void *read_buf, unsigned int read_len)

+{

+   unsigned int BytesOfRead = 0;

+   unsigned int rest_of_bytes = 0;

+   unsigned long rbytes = 0;

+   unsigned short RetryCount = 0;

+

+   if( NULL == read_buf || 0 >= read_len )

+   {

+      LOGE("DA_cmd::ReadData(): invalid arguments, read_buf(0x%08X), read_len(%u).", (unsigned int)read_buf, read_len);

+      return 1;

+   }

+

+   // initialize read buffer

+   memset(read_buf, '\0' , read_len);

+

+   RetryCount = 0;

+   BytesOfRead = 0;

+   while( BytesOfRead < read_len )

+   {

+      // check stop flag 

+      if( NULL!=arg.m_p_bootstop && BOOT_STOP==*(arg.m_p_bootstop) )

+      {

+         LOGE("DA_cmd::ReadData(): m_stopflag(0x%08X)=%d, force to stop!", (unsigned int)arg.m_p_bootstop, *(arg.m_p_bootstop));

+         return 2;

+      }

+   

+      rbytes = 0;

+      rest_of_bytes = read_len-BytesOfRead;

+	  

+	  GPS_UART_GetByte_Buffer((uint32 *) read_buf, rest_of_bytes);

+

+	  BytesOfRead += rest_of_bytes;

+

+   }

+

+   LOGE( "DA_cmd::ReadData(): OK. total=(%u/%u).", BytesOfRead, read_len);

+   return 0;

+}

+

+

+int CMD_ChangeUartSpeed(GPS_Download_Arg arg, unsigned char max_full_sync_count) 

+{

+

+   unsigned char buf[3];

+   volatile unsigned char data8;

+   //int ret;

+   int i;

+   unsigned char BaudrateId = 0x01; //921600, refer to g_BaudrateTable

+   volatile unsigned char full_sync_char;

+   //unsigned char count;

+

+   // send speed change command 

+   buf[0] = DA_SPEED_CMD;

+   buf[1] = BaudrateId;

+   buf[2] = max_full_sync_count;

+   LOGE("send DA_SPEED_CMD(0x%02X) + BaudrateId(0x%02X) + FULL_SYNC_CNT(0x%02X).", buf[0], buf[1], buf[2]);

+   if(WriteData( arg, buf, 3))

+   {

+      return 2;

+   }

+

+   // read ack 

+   LOGE( "wait for ACK.");

+   LOGE( " before: buf 0x%x", buf[0]);

+   if(ReadData( arg, buf, 1))

+   {

+      return 3;

+   }

+   if( ACK != buf[0] ) {

+      LOGE( "non-ACK(0x%02X) return.", buf[0]);

+      return 4;

+   }

+   // wait 2523 side UART baudrate change to 921600bps

+   LOGE( "Wait 2523 side baudrate change to BaudrateId(%u)=%u successfully.", BaudrateId, g_BaudrateTable[BaudrateId-1]);

+	

+   // sleep awhile for target uart state machine is ready 

+   if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(g_fd_mt3333_data ,921600, 8, 'N', 1)){

+		LOGE("configure uart baudrate failed");

+		return 1;

+	}

+   usleep(100*1000);

+

+   // sync mechanism: wait for baudrate change is done on both Target and PC sides 

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

+      {

+         // send sync char 

+         buf[0] = SYNC_CHAR;

+		 if(WriteData( arg, buf, 1))

+         {

+			LOGE(" Write SYNC_CHAR failed");

+            continue;

+         }

+

+         // wait for sync char

+         if( !ReadData( arg, buf, 1) ) 

+         {

+            if( SYNC_CHAR == buf[0] ) 

+            {

+               // receive correct SYNC_CHAR 

+               LOGE( "SYNC(%u): SYNC_CHAR(0x%02X) received!", g_BaudrateTable[BaudrateId-1], buf[0]);

+               break;

+            }

+            else 

+            {

+               // receive non-SYNC_CHAR

+               LOGE( "SYNC(%u): non-SYNC_CHAR(0x%02X) received, keep on sync.", g_BaudrateTable[BaudrateId-1], buf[0]);

+            }

+         }

+         else 

+         {

+            // wait for SYNC_CHAR timeout

+            LOGE( "SYNC(%u): sync timeout, keep on sync.", g_BaudrateTable[BaudrateId-1]);

+         }

+      }

+

+      // if fail over UART_BAUDRATE_SYNC_RETRY times, return error 

+      if( UART_BAUDRATE_SYNC_RETRY <= i ) 

+      {

+         LOGE( "SYNC(%u): retry %d times and sync fail!", g_BaudrateTable[BaudrateId-1], i);

+         return 6;

+      }

+

+      // send pc side purge ok ack 

+      //buf[0] = ACK;

+      LOGE( "SYNC(%u): send PC side TX & RX purge ok ACK. ", g_BaudrateTable[BaudrateId-1]);

+	  do

+	  {

+		  buf[0] = ACK;

+		  if(WriteData(arg, buf, 1)) 

+		  {

+			 return 8;

+		  }

+

+		  // wait for target side TX & RX purge ok ACK 

+		  LOGE( "SYNC(%u): wait for target side TX & RX purge ok ACK.", g_BaudrateTable[BaudrateId-1]);

+		  if( !ReadData(arg, buf, 1) ) 

+		  {

+			 if( ACK != buf[0] ) 

+			 {

+				LOGE( "SYNC(%u): non-ACK(0x%02X) received!", g_BaudrateTable[BaudrateId-1], buf[0]);

+				//return 9;

+			 }

+		  }

+		  else 

+		  {

+			 LOGE("SYNC(%u): ReadData(): fail. ", g_BaudrateTable[BaudrateId-1]);

+			 return 10;

+		  }

+	  }while (ACK != buf[0]);

+

+	  

+	  /*if(WriteData(com_driver, arg, buf, 1)) {

+         return 8;

+      }

+

+      // wait for target side TX & RX purge ok ACK 

+      MTRACE(g_hBROM_DEBUG, "DA_cmd::CMD_ChangeUartSpeed(): SYNC(%lu): wait for target side TX & RX purge ok ACK.", g_BaudrateTable[BaudrateId-1]);

+      if( 0 == (ret=ReadData(com_driver, arg, buf, 1)) ) 

+      {

+         if( ACK != buf[0] ) 

+         {

+            MTRACE_ERR(g_hBROM_DEBUG, "DA_cmd::CMD_ChangeUartSpeed(): SYNC(%lu): non-ACK(0x%02X) received!", g_BaudrateTable[BaudrateId-1], buf[0]);

+            return 9;

+         }

+      }

+      else 

+      {

+         MTRACE_ERR(g_hBROM_DEBUG, "DA_cmd::CMD_ChangeUartSpeed(): SYNC(%lu): ReadData(): fail, Err(%d). ", g_BaudrateTable[BaudrateId-1], ret);

+         return 10;

+      }*/

+      LOGE( "SYNC(%u): ACK(0x%02X) received, sync ok!", g_BaudrateTable[BaudrateId-1], buf[0]);

+

+      if( 0 < max_full_sync_count ) {

+         LOGE( "FULL_SYNC(%u): full sync all char to observe if baudrate is stable.", g_BaudrateTable[BaudrateId-1]);

+         full_sync_char = 0;

+         while(1) {

+

+            for(i=0; i<max_full_sync_count; i++) {

+

+               // fill sync char 

+               data8 = full_sync_char;

+

+               // send sync char 

+               if(WriteData(arg, (const void *)&data8, 1)) {

+                  // write fail 

+                  LOGE("FULL_SYNC(%u)[%u]: can't write KEEP_SYNC_CHAR(0x%02X) to target, full sync fail, baudrate is not stable!!", g_BaudrateTable[BaudrateId-1], i, full_sync_char);

+                  return 11;

+               }

+

+               // wait for sync char 

+               if(!ReadData(arg, buf, 1)) {

+                  if( full_sync_char != buf[0] ) {

+                     // receive non-SYNC_CHAR 

+                     LOGE( "FULL_SYNC(%u)[%u]: expect KEEP_SYNC_CHAR(0x%02X), but receive 0x%02X, full sync fail, baudrate is not stable!!", g_BaudrateTable[BaudrateId-1], i, full_sync_char, buf[0]);

+                     return 12;

+                  }

+               }

+               else {

+                  // wait for SYNC_CHAR timeout 

+                  LOGE( "FULL_SYNC(%u)[%u]: wait for KEEP_SYNC_CHAR(0x%02X) timeout, full sync fail, baudrate is not stable!!", g_BaudrateTable[BaudrateId-1], i, full_sync_char);

+                  return 13;

+               }

+            //MTRACE(g_hBROM_DEBUG, "DA_cmd::CMD_ChangeUartSpeed(): FULL_SYNC(%lu)[%u]: expect KEEP_SYNC_CHAR(0x%02X), receive 0x%02X, That's right!!", g_BaudrateTable[BaudrateId-1], i, full_sync_char, buf[0]);

+            }

+            

+            if( 0xFF > full_sync_char ) {

+               //MTRACE(g_hBROM_DEBUG, "DA_cmd::CMD_ChangeUartSpeed(): FULL_SYNC(%lu)[%u]: KEEP_SYNC_CHAR(0x%02X) done.", g_BaudrateTable[BaudrateId-1], i, full_sync_char);

+               full_sync_char++;

+            }

+            else {

+               break;

+            }

+         }

+         LOGE("FULL_SYNC(%u): successful!", g_BaudrateTable[BaudrateId-1]);

+      }

+      else {

+         LOGE( "skip FULL_SYNC(%u) procedure after baudrate changed.", g_BaudrateTable[BaudrateId-1]);

+      }

+

+   LOGE( " OK!");

+   return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_SetMemBlock

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to set download memory block.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  dl_handle: firmware packet information.

+ *

+ *******************************************************************************/

+int CMD_SetMemBlock(GPS_Download_Arg arg, ROM_HANDLE_T  *dl_handle)

+{

+   unsigned char buf[4];

+   unsigned int begin_addr;

+   unsigned int end_addr;

+

+   // check arguments

+   if( NULL==dl_handle )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): invalid arguments! dl_handle(%x).", (unsigned int)dl_handle);

+      return 1;

+   }

+

+   // send mem block command

+   buf[0] = DA_MEM_CMD;

+   buf[1] = 0x01;

+   LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): send DA_MEM_CMD(%x) + MEM_BLOCK_COUNT(%x).",  buf[0], buf[1]);

+   if(WriteData(arg, buf, 2))

+   {

+      return 2;

+   }

+

+   // send MEM begin addr, end addr

+	// MOD with 0x08000000(bank1 start address), because our maui_sw remap flash to bank1 on MT6218B series project. 

+	begin_addr = dl_handle->m_begin_addr%0x08000000;

+	end_addr = dl_handle->m_end_addr%0x08000000;

+

+	// send begin addr, high byte first

+	buf[0] = (unsigned char)((begin_addr>>24)&0x000000FF);

+	buf[1] = (unsigned char)((begin_addr>>16)&0x000000FF);

+	buf[2] = (unsigned char)((begin_addr>> 8)&0x000000FF);

+	buf[3] = (unsigned char)((begin_addr)    &0x000000FF);

+	LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): send MEM_BEGIN_ADDR( %x%x%x%x).", buf[0], buf[1], buf[2], buf[3]);

+	if(WriteData(arg, buf, 4))

+	{

+	 return 3;

+	}

+

+	// send end addr, high byte first

+	buf[0] = (unsigned char)((end_addr>>24)&0x000000FF);

+	buf[1] = (unsigned char)((end_addr>>16)&0x000000FF);

+	buf[2] = (unsigned char)((end_addr>> 8)&0x000000FF);

+	buf[3] = (unsigned char)((end_addr)    &0x000000FF);

+	LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): send MEM_END_ADDR(%x%x%x%x).", buf[0], buf[1], buf[2], buf[3]);

+	if(WriteData(arg, buf, 4))

+	{

+	 return 4;

+	}

+

+   // read ack 

+	LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): wait for ACK..");

+   if(ReadData(arg, buf, 1))

+   {

+      return 5;

+   }

+

+   if( ACK != buf[0] )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): non-ACK(%x) return.", buf[0]);

+	  return 6;

+   }

+   LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): ACK(%x) OK!", buf[0]);

+   if(ReadData(arg, buf, 1))

+   {

+      return 7;

+   }

+   dl_handle->m_num_of_unchanged_data_blocks = buf[0];

+   LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): UNCHANED_DATA_BLOCKS=( %x)", dl_handle->m_num_of_unchanged_data_blocks);

+   return 0;   

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_Finish

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send finish command to notify target download process is over.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *

+ *******************************************************************************/

+int CMD_Finish(GPS_Download_Arg arg)

+{

+   unsigned char buf[2];

+

+   UNUSED(arg);

+   // send DA_FINISH_CMD command

+   buf[0] = DA_FINISH_CMD;

+   GPS_UART_PutByte(buf[0]); 

+   LOGE( "[FUNET]DA_cmd::CMD_Finish(): OK!");

+   return 0;

+}

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_WriteData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send firmware data to target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  dl_handle: firmware packet information.

+ *  cb_download_flash_init: callback function which is invoked at the beginning of transimitting.

+ *  cb_download_flash_init_arg: parameter of initial callback function.

+ *  cb_download_flash: callback function which is invoked during the transimitting.

+ *  cb_download_flash_arg: parameter of  callback function upper.

+ *

+ *******************************************************************************/

+int CMD_WriteData(

+      GPS_Download_Arg arg,

+      ROM_HANDLE_T  *dl_handle,

+      CALLBACK_DOWNLOAD_PROGRESS_INIT  cb_download_flash_init,  void *cb_download_flash_init_arg,

+      CALLBACK_DOWNLOAD_PROGRESS  cb_download_flash,  void *cb_download_flash_arg)

+{

+   static const char ErrAckTable[][64]= {

+      "TIMEOUT_DATA",

+      "CKSUM_ERROR",

+      "RX_BUFFER_FULL",

+      "TIMEOUT_CKSUM_LSB",

+      "TIMEOUT_CKSUM_MSB",

+      "ERASE_TIMEOUT",

+      "PROGRAM_TIMEOUT",

+      "RECOVERY_BUFFER_FULL",

+      "UNKNOWN_ERROR"

+   };

+   unsigned char buf[5];

+   unsigned int finish_rate = 0;

+   unsigned int total_bytes = 0;

+   unsigned int total_sent_bytes = 0;

+   unsigned int accuracy;

+   int ret;

+   unsigned int sent_bytes;

+   unsigned int retry_count=0;

+   unsigned int j;

+   unsigned int rate;

+   unsigned short checksum;

+   unsigned int frame_bytes;

+

+   // check arguments

+   if( NULL==dl_handle )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_WriteData(): invalid arguments! dl_handle( %x)..", (unsigned int)dl_handle);

+      return 1;

+   }

+

+   total_bytes = dl_handle->m_len;

+

+   // send write command + packet length

+   buf[0] = DA_WRITE_CMD;

+   buf[1] = (unsigned char)((dl_handle->m_packet_length>>24) &0x000000FF);

+   buf[2] = (unsigned char)((dl_handle->m_packet_length>>16) &0x000000FF);

+   buf[3] = (unsigned char)((dl_handle->m_packet_length>>8)  &0x000000FF);

+   buf[4] = (unsigned char)((dl_handle->m_packet_length)     &0x000000FF);

+   LOGE("[FUNET]DA_cmd::CMD_WriteData(): send DA_WRITE_CMD( %x), PACKET_LENGTH( %x%x%x%x)=%u..", buf[0], buf[1], buf[2], buf[3], buf[4], dl_handle->m_packet_length);

+   if(WriteData(arg, buf, 5))

+   {

+      return 3;

+   }

+

+   // initialization callback

+   if( NULL != cb_download_flash_init )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): CALLBACK: cb_download_flash_init().");

+	  cb_download_flash_init(cb_download_flash_init_arg);

+   }

+

+   // Set finish rate of callback function to 100(%)

+   accuracy = 100;

+

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d).", ret);

+      return 4;

+   }

+

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): read ack( %x).", buf[0]);

+   

+   if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %s( %x): fail to save all the unchanged data from flash!", buf[0]>UNKNOWN_ERROR?"UNKNOWN_ACK":ErrAckTable[buf[0]], buf[0]);

+	  return 5;

+   }

+

+   // wait for 1st sector erase done 

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): wait for 1st sector erase done.");

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d)", ret);

+      return 6;

+   }

+

+   LOGE("[FUNET]DA_cmd::CMD_WriteData(): read ack( %x).", buf[0]);

+   

+   if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %s( %x): fail to erase the 1st sector!.", buf[0]>UNKNOWN_ERROR?"UNKNOWN_ACK":ErrAckTable[buf[0]], buf[0]);

+	  return 7;

+   }

+

+   // send all rom files

+   finish_rate = 0;

+   total_sent_bytes = 0;

+	// send each rom file

+	sent_bytes = 0;

+	retry_count = 0;

+	LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %d bytes, total_sent_bytes=%d/%d..", dl_handle->m_len, total_sent_bytes, total_bytes);

+	while( sent_bytes < dl_handle->m_len )

+	{

+

+	re_transmission:

+

+	 // reset the frame checksum

+	 checksum = 0;

+

+	 // if the last frame is less than PACKET_LENGTH bytes

+	 if( dl_handle->m_packet_length > (dl_handle->m_len-sent_bytes) )

+	 {

+	    frame_bytes = dl_handle->m_len - sent_bytes;

+	 }

+	 else

+	 {

+	    // the normal frame

+	    frame_bytes = dl_handle->m_packet_length;

+	 }

+

+	  GPS_UART_PutByte_Buffer((uint32 *) (dl_handle->m_buf+sent_bytes), frame_bytes);

+

+	 // calculate checksum

+	 for(j=0; j<frame_bytes; j++)

+	 {

+	    // WARNING: MUST make sure it unsigned value to do checksum

+	    checksum += dl_handle->m_buf[sent_bytes+j];

+	 }

+

+	 // send 2 bytes checksum, high byte first

+	 buf[0] = (unsigned char)((checksum>> 8)&0x000000FF);

+	 buf[1] = (unsigned char)((checksum)    &0x000000FF);

+	 

+	 if(WriteData(arg, buf, 2))

+	 {

+	    goto read_cont_char;

+	 }

+

+	read_cont_char:

+	 // read CONT_CHAR

+	 buf[0] = 0xEE;

+	 if( 0 != (ret=ReadData(arg, buf, 1)) )

+	 {

+		LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d).",ret);

+		return 8;

+	 }

+	 LOGE("[FUNET]CONT_CHART Received( %x).", buf[0]);

+

+	 switch(buf[0])

+	 {

+	    case CONT_CHAR:

+	       // sent ok!, reset retry_count			   

+		   LOGE( "[FUNET]CONT_CHART Ok( %x).", buf[0]);

+	       retry_count = 0;

+	       break;

+	    case ERASE_TIMEOUT:

+		   return 9;

+	    case PROGRAM_TIMEOUT:

+		   return 10;

+	    case RECOVERY_BUFFER_FULL:

+		   return 11;

+	    case RX_BUFFER_FULL:

+	    case CKSUM_ERROR:

+	    case TIMEOUT_DATA:

+	    case TIMEOUT_CKSUM_LSB:

+	    case TIMEOUT_CKSUM_MSB:

+	    default:

+	       // check retry times

+	       if( PACKET_RE_TRANSMISSION_TIMES > retry_count )

+	       {

+	          retry_count++;

+	       }

+	       else

+	       {

+	          // fail to re-transmission

+	          // send NACK to wakeup DA to stop

+	          buf[0] = NACK;

+			  if(WriteData(arg, buf, 1))

+	          {

+				 LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %u bytes sent, total_bytes=%u/%u.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+	          }

+	          return 12;

+	       }

+

+	       // wait for DA clean RX buffer

+		   if( 0 != (ret=ReadData(arg, buf, 1)) )

+	       {

+	          LOGE( "DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d)", ret);

+	          LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %u bytes sent, total_bytes=%u/%u.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+			  return 13;

+	       }

+		   

+	       if( ACK != buf[0] )

+	       {

+	          LOGE("DA_cmd::CMD_WriteData(): Retry(%u): wrong ack(0x%02X) return!", retry_count, buf[0]);

+	          LOGE("DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %u bytes sent, total_bytes=%u/%u.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+			  return 14;

+	       }

+

+	       // send CONT_CHAR to wakeup DA to start recieving again

+	       buf[0] = CONT_CHAR;

+	       LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): send CONT_CHAR to wakeup DA to start recieving again.", retry_count);

+		   if(WriteData(arg, buf, 1))

+	       {

+	          LOGE("DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %u bytes sent, total_bytes=%u/%u.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+	          return 15;

+	       }

+

+	       // re-transmission this frame

+	       LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): re-transmission this frame, offset(%u).", retry_count, sent_bytes);

+		   goto re_transmission;

+

+	       break;

+	 }

+

+	 // update progress state

+	 sent_bytes += frame_bytes;

+	 total_sent_bytes += frame_bytes;

+

+	 // calculate finish rate

+	 if( accuracy < (rate=(unsigned int)(((float)total_sent_bytes/total_bytes)*accuracy)) )

+	 {

+	    rate = accuracy;

+	 }

+

+	 if( 0 < (rate-finish_rate) )

+	 {

+	    finish_rate = rate;

+	    // calling callback 

+	    LOGE( "[FUNET]DA_cmd::CMD_WriteData(): (%d%%): %d bytes sent, total_bytes=%d/%d.",(unsigned char)finish_rate, sent_bytes, total_sent_bytes, total_bytes);

+	    if( NULL != cb_download_flash )

+	    {

+		   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): CALLBACK: cb_download_flash().");

+	       cb_download_flash((unsigned char)finish_rate, total_sent_bytes, total_bytes, cb_download_flash_arg);

+	    }

+	 }

+	}

+	LOGE( "[FUNET]DA_cmd::CMD_WriteData(): (%d%%): %d bytes sent, total_bytes=%d/%d.",(unsigned char)finish_rate, sent_bytes, total_sent_bytes, total_bytes);

+

+   // wait for recovery done ack 

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): wait for DA to perform unchanged data recovery.");

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d)", ret);

+	  return 16;

+   }

+

+   if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %s( %x): fail to recover all the unchanged data to flash!", buf[0]>UNKNOWN_ERROR?"UNKNOWN_ACK":ErrAckTable[buf[0]], buf[0]);

+	  return 17;

+   }

+

+   // wait for checksum ack 

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): wait for DA to perform flash checksum.!");

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d).!", ret);

+	  return 18;

+   }

+

+   if( NACK == buf[0] )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_WriteData(): NACK( %x) return, flash checksum error!", buf[0]);

+	  return 19;

+   }

+   else if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): non-ACK( %x) return.", buf[0]);

+      return 20;

+   }

+

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ACK( %x): checksum OK!", buf[0]);

+   return 0;

+}

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.c.bak b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.c.bak
new file mode 100644
index 0000000..69019e6
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.c.bak
@@ -0,0 +1,588 @@
+/*******************************************************************************

+ *  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) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  da_cmd.cpp

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *  DA(Download Agent) handshake command.

+ *

+ *******************************************************************************/

+#include "brom_base.h"

+#include "da_cmd.h"

+#include "sw_types.h"

+#include "gps_uart.h"

+#include <string.h>

+

+#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 <unistd.h>

+

+#ifdef LOGD

+#undef LOGD

+#endif

+#ifdef LOGW

+#undef LOGW

+#endif

+#ifdef LOGE

+#undef LOGE

+#endif

+#if 0

+#define LOGD(...) tag_log(1, "[op01]", __VA_ARGS__);

+#define LOGW(...) tag_log(1, "[op01] WARNING: ", __VA_ARGS__);

+#define LOGE(...) tag_log(1, "[op01] ERR: ", __VA_ARGS__);

+#else

+#define LOG_TAG "flashtool"

+#include <cutils/sockets.h>

+#include <cutils/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

+

+

+#define PACKET_RE_TRANSMISSION_TIMES   3

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  WriteData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send firmware data to target.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  write_buf: data buffer want to be sent.

+ *  write_len: data length.

+ *

+ *******************************************************************************/

+int WriteData(GPS_Download_Arg arg, const void *write_buf, unsigned int write_len) {

+

+   unsigned int BytesOfWriiten = 0;

+   unsigned int rest_of_bytes = 0;

+   unsigned long wbytes = 0;

+   unsigned short RetryCount = 0;

+

+   if( NULL == write_buf || 0 >= write_len ) {

+      LOGE("DA_cmd::WriteData(): invalid arguments, write_buf(0x%08X), write_len(%lu).", write_buf, write_len);

+      return 1;

+   }

+

+   RetryCount = 0;

+   BytesOfWriiten = 0;

+   while( BytesOfWriiten < write_len ) 

+   	{

+   

+      // check stop flag 

+      if( NULL!=arg.m_p_bootstop && BOOT_STOP==*(arg.m_p_bootstop) ) {

+         LOGE( "DA_cmd::WriteData(): m_stopflag(0x%08X)=%lu, force to stop!", m_stopflag, *m_stopflag);

+         return 2;

+      }

+   

+      wbytes = 0;

+      rest_of_bytes = write_len-BytesOfWriiten;

+

+	  GPS_UART_PutByte_Buffer((uint32 *) write_buf, rest_of_bytes);

+

+      // update write bytes

+         BytesOfWriiten += rest_of_bytes;

+

+   }

+

+   LOGE("DA_cmd::WriteData(): OK. total=(%lu/%lu).", BytesOfWriiten, write_len);

+   return 0;

+}

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  ReadData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to read ack from target.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  read_buf: data buffer want to be read.

+ *  read_len: data length.

+ *

+ *******************************************************************************/

+int ReadData(GPS_Download_Arg arg, void *read_buf, unsigned int read_len)

+{

+   unsigned int BytesOfRead = 0;

+   unsigned int rest_of_bytes = 0;

+   unsigned long rbytes = 0;

+   unsigned short RetryCount = 0;

+

+   if( NULL == read_buf || 0 >= read_len )

+   {

+      LOGE("DA_cmd::ReadData(): invalid arguments, read_buf(0x%08X), read_len(%lu).", read_buf, read_len);

+      return 1;

+   }

+

+   // initialize read buffer

+   memset(read_buf, '\0' , read_len);

+

+   RetryCount = 0;

+   BytesOfRead = 0;

+   while( BytesOfRead < read_len )

+   {

+      // check stop flag 

+      if( NULL!=arg.m_p_bootstop && BOOT_STOP==*(arg.m_p_bootstop) )

+      {

+         LOGE("DA_cmd::ReadData(): m_stopflag(0x%08X)=%lu, force to stop!", m_stopflag, *m_stopflag);

+         return 2;

+      }

+   

+      rbytes = 0;

+      rest_of_bytes = read_len-BytesOfRead;

+	  

+	  GPS_UART_GetByte_Buffer((uint32 *) read_buf, rest_of_bytes);

+

+	  BytesOfRead += rest_of_bytes;

+

+   }

+

+   LOGE( "DA_cmd::ReadData(): OK. total=(%lu/%lu).", BytesOfRead, read_len);

+   return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_SetMemBlock

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to set download memory block.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  dl_handle: firmware packet information.

+ *

+ *******************************************************************************/

+int CMD_SetMemBlock(GPS_Download_Arg arg, ROM_HANDLE_T  *dl_handle)

+{

+   unsigned char buf[4];

+   unsigned int begin_addr;

+   unsigned int end_addr;

+

+   // check arguments

+   if( NULL==dl_handle )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): invalid arguments! dl_handle(%x).", dl_handle);

+      return 1;

+   }

+

+   // send mem block command

+   buf[0] = DA_MEM_CMD;

+   buf[1] = 0x01;

+   LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): send DA_MEM_CMD(%x) + MEM_BLOCK_COUNT(%x).",  buf[0], buf[1]);

+   if(WriteData(arg, buf, 2))

+   {

+      return 2;

+   }

+

+   // send MEM begin addr, end addr

+	// MOD with 0x08000000(bank1 start address), because our maui_sw remap flash to bank1 on MT6218B series project. 

+	begin_addr = dl_handle->m_begin_addr%0x08000000;

+	end_addr = dl_handle->m_end_addr%0x08000000;

+

+	// send begin addr, high byte first

+	buf[0] = (unsigned char)((begin_addr>>24)&0x000000FF);

+	buf[1] = (unsigned char)((begin_addr>>16)&0x000000FF);

+	buf[2] = (unsigned char)((begin_addr>> 8)&0x000000FF);

+	buf[3] = (unsigned char)((begin_addr)    &0x000000FF);

+	LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): send MEM_BEGIN_ADDR( %x%x%x%x).\n\r", buf[0], buf[1], buf[2], buf[3]);

+	if(WriteData(arg, buf, 4))

+	{

+	 return 3;

+	}

+

+	// send end addr, high byte first

+	buf[0] = (unsigned char)((end_addr>>24)&0x000000FF);

+	buf[1] = (unsigned char)((end_addr>>16)&0x000000FF);

+	buf[2] = (unsigned char)((end_addr>> 8)&0x000000FF);

+	buf[3] = (unsigned char)((end_addr)    &0x000000FF);

+	LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): send MEM_END_ADDR(%x%x%x%x).\n\r", buf[0], buf[1], buf[2], buf[3]);

+	if(WriteData(arg, buf, 4))

+	{

+	 return 4;

+	}

+

+   // read ack 

+	LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): wait for ACK..\n\r");

+   if(ReadData(arg, buf, 1))

+   {

+      return 5;

+   }

+

+   if( ACK != buf[0] )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): non-ACK(%x) return.\n\r", buf[0]);

+	  return 6;

+   }

+   LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): ACK(%x) OK!\n\r", buf[0]);

+   if(ReadData(arg, buf, 1))

+   {

+      return 7;

+   }

+   dl_handle->m_num_of_unchanged_data_blocks = buf[0];

+   LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): UNCHANED_DATA_BLOCKS=( %x)\n\r", dl_handle->m_num_of_unchanged_data_blocks);

+   return 0;   

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_Finish

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send finish command to notify target download process is over.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *

+ *******************************************************************************/

+int CMD_Finish(GPS_Download_Arg arg)

+{

+   unsigned char buf[2];

+

+   // send DA_FINISH_CMD command

+   buf[0] = DA_FINISH_CMD;

+   GPS_UART_PutByte(buf[0]); 

+   LOGE( "[FUNET]DA_cmd::CMD_Finish(): OK!\n\r");

+   return 0;

+}

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_WriteData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send firmware data to target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  dl_handle: firmware packet information.

+ *  cb_download_flash_init: callback function which is invoked at the beginning of transimitting.

+ *  cb_download_flash_init_arg: parameter of initial callback function.

+ *  cb_download_flash: callback function which is invoked during the transimitting.

+ *  cb_download_flash_arg: parameter of  callback function upper.

+ *

+ *******************************************************************************/

+int CMD_WriteData(

+      GPS_Download_Arg arg,

+      ROM_HANDLE_T  *dl_handle,

+      CALLBACK_DOWNLOAD_PROGRESS_INIT  cb_download_flash_init,  void *cb_download_flash_init_arg,

+      CALLBACK_DOWNLOAD_PROGRESS  cb_download_flash,  void *cb_download_flash_arg)

+{

+   static const char ErrAckTable[][64]= {

+      "TIMEOUT_DATA",

+      "CKSUM_ERROR",

+      "RX_BUFFER_FULL",

+      "TIMEOUT_CKSUM_LSB",

+      "TIMEOUT_CKSUM_MSB",

+      "ERASE_TIMEOUT",

+      "PROGRAM_TIMEOUT",

+      "RECOVERY_BUFFER_FULL",

+      "UNKNOWN_ERROR"

+   };

+   unsigned char buf[5];

+   unsigned int finish_rate = 0;

+   unsigned int total_bytes = 0;

+   unsigned int total_sent_bytes = 0;

+   unsigned int accuracy;

+   int ret;

+   unsigned int sent_bytes;

+   unsigned int retry_count=0;

+   unsigned int j;

+   unsigned int rate;

+   unsigned short checksum;

+   unsigned int frame_bytes;

+

+   // check arguments

+   if( NULL==dl_handle )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_WriteData(): invalid arguments! dl_handle( %x)..\n\r", dl_handle);

+      return 1;

+   }

+

+   total_bytes = dl_handle->m_len;

+

+   // send write command + packet length

+   buf[0] = DA_WRITE_CMD;

+   buf[1] = (unsigned char)((dl_handle->m_packet_length>>24) &0x000000FF);

+   buf[2] = (unsigned char)((dl_handle->m_packet_length>>16) &0x000000FF);

+   buf[3] = (unsigned char)((dl_handle->m_packet_length>>8)  &0x000000FF);

+   buf[4] = (unsigned char)((dl_handle->m_packet_length)     &0x000000FF);

+   LOGE("[FUNET]DA_cmd::CMD_WriteData(): send DA_WRITE_CMD( %x), PACKET_LENGTH( %x%x%x%x)=%u..\n\r", buf[0], buf[1], buf[2], buf[3], buf[4], dl_handle->m_packet_length);

+   if(WriteData(arg, buf, 5))

+   {

+      return 3;

+   }

+

+   // initialization callback

+   if( NULL != cb_download_flash_init )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): CALLBACK: cb_download_flash_init().\n\r");

+	  cb_download_flash_init(cb_download_flash_init_arg);

+   }

+

+   // Set finish rate of callback function to 100(%)

+   accuracy = 100;

+

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d).\n\r", ret);

+      return 4;

+   }

+

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): read ack( %x).\n\r", buf[0]);

+   

+   if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %s( %x): fail to save all the unchanged data from flash!\n\r", buf[0]>UNKNOWN_ERROR?"UNKNOWN_ACK":ErrAckTable[buf[0]], buf[0]);

+	  return 5;

+   }

+

+   // wait for 1st sector erase done 

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): wait for 1st sector erase done.\n\r");

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d)\n\r", ret);

+      return 6;

+   }

+

+   LOGE("[FUNET]DA_cmd::CMD_WriteData(): read ack( %x).\n\r", buf[0]);

+   

+   if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %s( %x): fail to erase the 1st sector!.\n\r", buf[0]>UNKNOWN_ERROR?"UNKNOWN_ACK":ErrAckTable[buf[0]], buf[0]);

+	  return 7;

+   }

+

+   // send all rom files

+   finish_rate = 0;

+   total_sent_bytes = 0;

+	// send each rom file

+	sent_bytes = 0;

+	retry_count = 0;

+	LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %d bytes, total_sent_bytes=%d/%d..\n\r", dl_handle->m_len, total_sent_bytes, total_bytes);

+	while( sent_bytes < dl_handle->m_len )

+	{

+

+	re_transmission:

+

+	 // reset the frame checksum

+	 checksum = 0;

+

+	 // if the last frame is less than PACKET_LENGTH bytes

+	 if( dl_handle->m_packet_length > (dl_handle->m_len-sent_bytes) )

+	 {

+	    frame_bytes = dl_handle->m_len - sent_bytes;

+	 }

+	 else

+	 {

+	    // the normal frame

+	    frame_bytes = dl_handle->m_packet_length;

+	 }

+

+	  GPS_UART_PutByte_Buffer((uint32 *) (dl_handle->m_buf+sent_bytes), frame_bytes);

+

+	 // calculate checksum

+	 for(j=0; j<frame_bytes; j++)

+	 {

+	    // WARNING: MUST make sure it unsigned value to do checksum

+	    checksum += dl_handle->m_buf[sent_bytes+j];

+	 }

+

+	 // send 2 bytes checksum, high byte first

+	 buf[0] = (unsigned char)((checksum>> 8)&0x000000FF);

+	 buf[1] = (unsigned char)((checksum)    &0x000000FF);

+	 

+	 if(WriteData(arg, buf, 2))

+	 {

+	    goto read_cont_char;

+	 }

+

+	read_cont_char:

+	 // read CONT_CHAR

+	 buf[0] = 0xEE;

+	 if( 0 != (ret=ReadData(arg, buf, 1)) )

+	 {

+		LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d).\n\r",ret);

+		return 8;

+	 }

+	 LOGE("[FUNET]CONT_CHART Received( %x).\n\r", buf[0]);

+

+	 switch(buf[0])

+	 {

+	    case CONT_CHAR:

+	       // sent ok!, reset retry_count			   

+		   LOGE( "[FUNET]CONT_CHART Ok( %x).\n\r", buf[0]);

+	       retry_count = 0;

+	       break;

+	    case ERASE_TIMEOUT:

+		   return 9;

+	    case PROGRAM_TIMEOUT:

+		   return 10;

+	    case RECOVERY_BUFFER_FULL:

+		   return 11;

+	    case RX_BUFFER_FULL:

+	    case CKSUM_ERROR:

+	    case TIMEOUT_DATA:

+	    case TIMEOUT_CKSUM_LSB:

+	    case TIMEOUT_CKSUM_MSB:

+	    default:

+	       // check retry times

+	       if( PACKET_RE_TRANSMISSION_TIMES > retry_count )

+	       {

+	          retry_count++;

+	       }

+	       else

+	       {

+	          // fail to re-transmission

+	          // send NACK to wakeup DA to stop

+	          buf[0] = NACK;

+			  if(WriteData(arg, buf, 1))

+	          {

+				 LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %lu bytes sent, total_bytes=%lu/%lu.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+	          }

+	          return 12;

+	       }

+

+	       // wait for DA clean RX buffer

+		   if( 0 != (ret=ReadData(arg, buf, 1)) )

+	       {

+	          LOGE( "DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d)", ret);

+	          LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %lu bytes sent, total_bytes=%lu/%lu.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+			  return 13;

+	       }

+		   

+	       if( ACK != buf[0] )

+	       {

+	          LOGE("DA_cmd::CMD_WriteData(): Retry(%u): wrong ack(0x%02X) return!", retry_count, buf[0]);

+	          LOGE("DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %lu bytes sent, total_bytes=%lu/%lu.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+			  return 14;

+	       }

+

+	       // send CONT_CHAR to wakeup DA to start recieving again

+	       buf[0] = CONT_CHAR;

+	       LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): send CONT_CHAR to wakeup DA to start recieving again.", retry_count);

+		   if(WriteData(arg, buf, 1))

+	       {

+	          LOGE("DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %lu bytes sent, total_bytes=%lu/%lu.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+	          return 15;

+	       }

+

+	       // re-transmission this frame

+	       LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): re-transmission this frame, offset(%lu).", retry_count, sent_bytes);

+		   goto re_transmission;

+

+	       break;

+	 }

+

+	 // update progress state

+	 sent_bytes += frame_bytes;

+	 total_sent_bytes += frame_bytes;

+

+	 // calculate finish rate

+	 if( accuracy < (rate=(unsigned int)(((float)total_sent_bytes/total_bytes)*accuracy)) )

+	 {

+	    rate = accuracy;

+	 }

+

+	 if( 0 < (rate-finish_rate) )

+	 {

+	    finish_rate = rate;

+	    // calling callback 

+	    LOGE( "[FUNET]DA_cmd::CMD_WriteData(): (%d%%): %d bytes sent, total_bytes=%d/%d.\n\r",(unsigned char)finish_rate, sent_bytes, total_sent_bytes, total_bytes);

+	    if( NULL != cb_download_flash )

+	    {

+		   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): CALLBACK: cb_download_flash().\n\r");

+	       cb_download_flash((unsigned char)finish_rate, total_sent_bytes, total_bytes, cb_download_flash_arg);

+	    }

+	 }

+	}

+	LOGE( "[FUNET]DA_cmd::CMD_WriteData(): (%d%%): %d bytes sent, total_bytes=%d/%d.\n\r",(unsigned char)finish_rate, sent_bytes, total_sent_bytes, total_bytes);

+

+   // wait for recovery done ack 

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): wait for DA to perform unchanged data recovery.\n\r");

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d)\n\r", ret);

+	  return 16;

+   }

+

+   if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %s( %x): fail to recover all the unchanged data to flash!\n\r", buf[0]>UNKNOWN_ERROR?"UNKNOWN_ACK":ErrAckTable[buf[0]], buf[0]);

+	  return 17;

+   }

+

+   // wait for checksum ack 

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): wait for DA to perform flash checksum.!\n\r");

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d).!\n\r", ret);

+	  return 18;

+   }

+

+   if( NACK == buf[0] )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_WriteData(): NACK( %x) return, flash checksum error!\n\r", buf[0]);

+	  return 19;

+   }

+   else if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): non-ACK( %x) return.\n\r", buf[0]);

+      return 20;

+   }

+

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ACK( %x): checksum OK!\n\r", buf[0]);

+   return 0;

+}

+

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.h
new file mode 100644
index 0000000..df8678a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.h
@@ -0,0 +1,139 @@
+/*******************************************************************************

+ *  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) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  da_cmd.h

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *  DA(Download Agent) handshake command.

+ *

+ *******************************************************************************/

+#ifndef  _DA_CMD_H_

+#define  _DA_CMD_H_

+

+#include "flashtool.h"

+

+//------------------------------------------------------------------------------

+// DA Command Object                                                            

+//------------------------------------------------------------------------------

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  WriteData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send firmware data to target.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  write_buf: data buffer want to be sent.

+ *  write_len: data length.

+ *

+ *******************************************************************************/

+int WriteData(GPS_Download_Arg arg, const void *write_buf, unsigned int write_len);

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  ReadData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to read ack from target.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  read_buf: data buffer want to be read.

+ *  read_len: data length.

+ *

+ *******************************************************************************/

+int ReadData(GPS_Download_Arg arg, void *read_buf, unsigned int read_len);

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_SetMemBlock

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to set download memory block.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  dl_handle: firmware packet information.

+ *

+ *******************************************************************************/

+ int CMD_ChangeUartSpeed(GPS_Download_Arg arg, unsigned char max_full_sync_count) ;

+int CMD_SetMemBlock(GPS_Download_Arg arg, ROM_HANDLE_T  *dl_handle);

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_Finish

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send finish command to notify target download process is over.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *

+ *******************************************************************************/

+int CMD_Finish(GPS_Download_Arg arg);

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_WriteData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send firmware data to target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  dl_handle: firmware packet information.

+ *  cb_download_flash_init: callback function which is invoked at the beginning of transimitting.

+ *  cb_download_flash_init_arg: parameter of initial callback function.

+ *  cb_download_flash: callback function which is invoked during the transimitting.

+ *  cb_download_flash_arg: parameter of  callback function upper.

+ *

+ *******************************************************************************/

+int CMD_WriteData(

+               GPS_Download_Arg arg,

+               ROM_HANDLE_T  *dl_handle,

+               CALLBACK_DOWNLOAD_PROGRESS_INIT  cb_download_flash_init,  void *cb_download_flash_init_arg,

+               CALLBACK_DOWNLOAD_PROGRESS  cb_download_flash,  void *cb_download_flash_arg);

+

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/flashtool.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/flashtool.c
new file mode 100644
index 0000000..cbf5c32
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/flashtool.c
@@ -0,0 +1,672 @@
+#ifdef CONFIG_GPS_MT3303

+/*******************************************************************************

+ *  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) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  flashtool.cpp

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *  Main function of MCU download.

+ *

+ *******************************************************************************/

+#include "flashtool.h"

+#include "da_cmd.h"

+#include "brom_base.h"

+#include "DOWNLOAD.H"

+#include "GPS_DL_api.h"

+#include <stdio.h>

+#include <string.h>

+#include "sw_types.h"

+#include "brom.h"

+

+#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 <unistd.h>

+

+#include "mt3333_controller.h"

+#include "gps_controller.h"

+#include "mnl_common.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "flashtool"

+#endif

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  SyncWithDA

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to recevied the information from target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *

+ * Output:

+ * --------

+ *  p_da_report: information that DA will report. 

+ *  p_FlashDeviceKey:  information that DA will report.

+ *

+ *******************************************************************************/

+static int SyncWithDA(GPS_Download_Arg arg, s_DA_REPORT_T *p_da_report, s_FlashDeviceKey *p_FlashDeviceKey)

+{

+   unsigned char   buf[32];

+   s_FlashDeviceKey   flash_id;

+

+   if( NULL == p_da_report )

+   {

+      return FT_INVALID_ARGUMENTS;

+   }

+

+   // initialize first 

+   memset(p_da_report, 0, sizeof(s_DA_REPORT_T));

+   p_da_report->expected_da_major_ver = DA_MAJOR_VER;

+   p_da_report->expected_da_minor_ver = DA_MINOR_VER;

+   p_da_report->flash_device_id = DEVICE_UNKNOWN;

+

+   // get SYNC_CHAR 

+   LOGE("[FUNET]SyncWithDA(): wait SYNC_CHAR");

+   if(ReadData(arg, buf, 1))

+   {

+       LOGE( "[FUNET]SyncWithDA(): SYNC_CHAR no response.");

+      return FT_DA_NO_RESPONSE;

+   }

+   LOGE("[FUNET]SyncWithDA(): SYNC_CHAR Get:%x.", buf[0]);

+   

+   if( SOC_FAIL == buf[0] )

+   {

+      LOGE("[FUNET]SyncWithDA(): SOC_FAIL(%x) received from DA.", buf[0]);

+      return FT_DA_SOC_CHECK_FAIL;

+   }

+   else if( HW_ERROR == buf[0] )

+   {

+      return FT_DA_HW_ERROR;

+   }

+   else if( SYNC_CHAR != buf[0] )

+   {

+      LOGE("[FUNET]SyncWithDA(): non-SYNC_CHAR(%x) received from DA.", buf[0]);

+      return FT_DA_SYNC_INCORRECT;

+   }

+

+   // get DA_MAJOR_VER, DA_MINOR_VER    

+   LOGE("[FUNET]SyncWithDA(): wait DA_MAJOR_VER(%x), DA_MINOR_VER.", buf[0]);

+   if(ReadData(arg, buf, 2))

+   {

+      return FT_DA_NO_RESPONSE;

+   }

+

+   p_da_report->da_major_ver = buf[0];

+   p_da_report->da_minor_ver = buf[1];

+   if( DA_MAJOR_VER!=p_da_report->da_major_ver || DA_MINOR_VER!=p_da_report->da_minor_ver )

+   {

+      LOGE( "[FUNET]SyncWithDA(): DA_v%d.%d was expired, expect DA_v%d.%d .",  p_da_report->da_major_ver, p_da_report->da_minor_ver, DA_MAJOR_VER, DA_MINOR_VER);

+      return FT_DA_VERSION_INCORRECT;

+   }

+

+   LOGE( "[FUNET]SyncWithDA(): DA_v%d.%d.",  p_da_report->da_major_ver, p_da_report->da_minor_ver);

+   LOGE( "[FUNET]SyncWithDA(): wait DEVICE_INFO.");

+   if(ReadData(arg, buf, 1))

+   {

+      return FT_DA_NO_RESPONSE;

+   }

+   p_da_report->flash_device_id = (DEVICE_INFO)buf[0];

+   if( DEVICE_UNKNOWN == p_da_report->flash_device_id )

+   {

+      return FT_DA_UNKNOWN_FLASH_DEVICE;

+   }

+

+   // get flash size, manufacture id and device code and ext sram size 

+   if(ReadData(arg, buf, 16))

+   {

+      return FT_DA_NO_RESPONSE;

+   }

+   // get flash size 

+   p_da_report->flash_size = ((buf[0]<<24)&0xFF000000)|((buf[1]<<16)&0x00FF0000)|((buf[2]<<8)&0x0000FF00)|((buf[3])&0x000000FF);

+   // get flash manufacture id and device code 

+   flash_id.m_ManufactureId   = ((buf[4]<<8)&0xFF00)|((buf[5])&0x00FF);

+   flash_id.m_DeviceCode      = ((buf[6]<<8)&0xFF00)|((buf[7])&0x00FF);

+   flash_id.m_ExtDeviceCode1   = ((buf[8]<<8)&0xFF00)|((buf[9])&0x00FF);

+   flash_id.m_ExtDeviceCode2   = ((buf[10]<<8)&0xFF00)|((buf[11])&0x00FF);

+   if( NULL != p_FlashDeviceKey )

+   {

+      *p_FlashDeviceKey = flash_id;

+   }

+   // get external sram size 

+   p_da_report->ext_sram_size = ((buf[12]<<24)&0xFF000000)|((buf[13]<<16)&0x00FF0000)|((buf[14]<<8)&0x0000FF00)|((buf[15])&0x000000FF);

+

+   LOGE("[FUNET]SyncWithDA(): SYNC ok.");

+   return FT_OK;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  FlashDownload_Internal

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to manage the download flow.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  GPS_da: import Download Agent(DA) buffer and size. 

+ *  GPS_image_list:  import firmware buffer and size.

+ *  p_arg: Callback function pointer.

+ *

+ *******************************************************************************/

+static int FlashDownload_Internal(

+    GPS_DA* GPS_da,

+    GPS_Image_List* GPS_image_list,

+    FLASHTOOL_ARG  *p_arg,

+    GPS_Download_Arg arg)

+{

+    int ret;

+    //int *p_stopflag = arg.m_p_bootstop;

+    s_BOOT_FLASHTOOL_ARG boot_flashtool_arg;

+    ROM_HANDLE_T dl_handle,*p_dl_handle;

+    s_DA_REPORT_T      da_report;

+    s_DA_REPORT_T      *pDA_Report;

+    s_FlashDeviceKey   flash_id;

+    p_dl_handle = &dl_handle;

+

+

+    p_dl_handle->m_buf = GPS_image_list->m_image_list[0].m_image;

+    p_dl_handle->m_len = GPS_image_list->m_image_list[0].m_size;

+    p_dl_handle->m_begin_addr = 0x00000000;

+    p_dl_handle->m_end_addr = p_dl_handle->m_begin_addr + p_dl_handle->m_len - 1;

+    p_dl_handle->m_packet_length = 1024; 

+

+

+    // check arguments

+    if( NULL==GPS_image_list || NULL==p_arg || NULL==GPS_da) 

+    {

+        LOGE("[FUNET]Input parameters error");

+       return FT_INVALID_ARGUMENTS;

+    }

+

+    // fill boot flashtool arg 

+    boot_flashtool_arg.m_da_start_addr           = 0x00000C00;

+    boot_flashtool_arg.m_da_buf                  = GPS_da->m_image;

+    boot_flashtool_arg.m_da_len                  = GPS_da->m_size;

+

+     LOGI("[FUNET]Enter Boot_FlashTool");

+

+     // boot target to flashtool mode 

+     ret = Boot_FlashTool(&boot_flashtool_arg, arg);

+

+

+     // check return value 

+     if( BROM_OK != ret )

+     {

+        // boot up failed!

+        LOGE( "[FUNET]FlashDownload_Internal(): BRom_AutoBoot::Boot_FlashTool() fail! , Err(%x).", ret);

+        return (FT_BROM_ERROR|ret);

+     }

+

+    LOGE( "[FUNET]Sync With DA");

+

+    // sync with DA 

+    pDA_Report=&da_report;

+    if( FT_OK != (ret=SyncWithDA(arg, pDA_Report, &flash_id)) )

+    {

+      return ret;

+    }

+

+    // Doesn't format 

+    pDA_Report->fat_begin_addr = 0;

+    pDA_Report->fat_length = 0;

+    // change UART speed for high speed(921600bps)

+    LOGE( "Change to high speed baudrate(921600) ");

+

+    int status = CMD_ChangeUartSpeed(arg, 1);

+    if(status) 

+    {

+      LOGE( "CMD_ChangeUartSpeed fail status %d", status);

+      return FT_DA_CHANGE_BAUDRATE_FAIL;

+    }

+    else

+    {

+      LOGE("CMD_ChangeUartSpeed OK");                 

+    }

+

+    LOGE("[FUNET]CMD_SetMemBlock.");

+    // set memory block

+    if(CMD_SetMemBlock(arg, p_dl_handle))

+    {

+      return FT_DA_SET_DOWNLOAD_BLOCK_FAIL;

+    }

+    LOGE("[FUNET]da_cmd.CMD_WriteData.");

+    // write to flash by memory block

+    if(CMD_WriteData(arg, p_dl_handle, p_arg->m_cb_download_conn_init, p_arg->m_cb_download_conn_init_arg, p_arg->m_cb_download_conn, p_arg->m_cb_download_conn_arg))

+    {

+      return FT_DA_DOWNLOAD_FAIL;

+    }

+

+    // set ret to FT_OK 

+    ret = FT_OK;

+

+    LOGE("[FUNET]FlashDownload_Internal(): Success!");

+

+    // Finish Cmd

+    CMD_Finish(arg);

+

+    return ret;

+}

+

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  FlashDownload

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to manage the download flow.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  GPS_da: import Download Agent(DA) buffer and size. 

+ *  GPS_image_list:  import firmware buffer and size.

+ *

+ *******************************************************************************/

+int  FlashDownload(

+    GPS_DA* GPS_da,

+    GPS_Image_List* GPS_image_list,

+    GPS_Download_Arg arg)

+{

+   FLASHTOOL_ARG  flashtool_arg,*p_arg;

+   p_arg = &flashtool_arg;

+

+   // check arguments

+   if( NULL == GPS_image_list || NULL == GPS_da) 

+   {

+      LOGE("[FUNET]Input parameters error"); //Show debug log, please use your own logger API to replace 'BL_PRINT' function.

+      return FT_INVALID_ARGUMENTS;

+   }

+

+   p_arg->m_cb_download_conn_init = arg.m_cb_download_conn_init;

+   p_arg->m_cb_download_conn_init_arg = arg.m_cb_download_conn_init_arg;

+   p_arg->m_cb_download_conn = arg.m_cb_download_conn;

+   p_arg->m_cb_download_conn_arg = arg.m_cb_download_conn_arg;

+   p_arg->m_cb_download_conn_da_init = arg.m_cb_download_conn_da_init;

+   p_arg->m_cb_download_conn_da_init_arg = arg.m_cb_download_conn_da_init_arg;

+   p_arg->m_cb_download_conn_da = arg.m_cb_download_conn_da;

+   p_arg->m_cb_download_conn_da_arg = arg.m_cb_download_conn_da_arg;

+   

+   LOGI("[FUNET]Enter FlashDownload_Internal");

+   return FlashDownload_Internal(GPS_da, GPS_image_list, p_arg, arg);

+}

+

+

+//Example code of callback function

+int gps_download_progress_callback(unsigned char finished_percentage,

+                                           unsigned int finished_bytes,

+                                           unsigned int total_bytes, void *usr_arg)

+{

+    int percentage[] = {5, 15, 100};

+    int stage = (int) usr_arg;

+    LOGE( "[FUNET]current update progress: %d, stage:%d ",finished_percentage, stage);

+    UNUSED(finished_bytes);

+    UNUSED(total_bytes);

+    if (stage >= sizeof(percentage)/sizeof(int) - 1)

+    {

+        LOGE( "[FUNET]display error, stage:%d ", stage);

+        return 1;

+    }

+    finished_percentage = (percentage[stage + 1] - percentage[stage]) * finished_percentage/100 + percentage[stage];

+    LOGE("[FUNET]real update progress: %d ",finished_percentage);

+    return 0;

+}

+

+#if defined(__ANDROID_OS_10__)

+#define DA_FILE_NADA MTK_GPS_FW_PATH"3333_da.bin"

+#define FW_FILE_NADA MTK_GPS_FW_PATH"3333_fw.bin"

+#define FW_FILE_NADA_OLD MTK_GPS_DATA_PATH"3333_fw_old.bin"

+#else

+#define DA_FILE_NADA MTK_GPS_DATA_PATH"3333_da.bin"

+#define FW_FILE_NADA MTK_GPS_DATA_PATH"3333_fw.bin"

+#define FW_FILE_NADA_OLD MTK_GPS_DATA_PATH"3333_fw_old.bin"

+#endif

+

+uint8 *fw_buf=NULL;

+int32 fw_size=0;

+uint8 *da_buf=NULL;

+int32 da_size=0;

+int fw_downloading=0;

+extern int g_fd_mt3333_data;

+extern MNL_CONFIG_T mnld_cfg;

+

+int flashtool_file_isvalid(void){

+    int result_da=0;

+    int result_fw=0;

+#if defined(__ANDROID_OS_10__)

+    int result_fw_old=0;

+    result_fw_old=access(FW_FILE_NADA_OLD, F_OK);

+    result_da=access(DA_FILE_NADA, F_OK);

+    result_fw=access(FW_FILE_NADA, F_OK);

+

+    if(result_da>=0 && result_fw>=0 && result_fw_old<0){

+        //LOGE("result=ok");

+        return 1;

+    }

+#else

+    result_da=access(DA_FILE_NADA, F_OK);

+    result_fw=access(FW_FILE_NADA, F_OK);

+

+    if(result_da>=0 && result_fw>=0){

+        //LOGE("result=ok");

+        return 1;

+    }

+#endif

+    LOGE("da=%d, fw=%d, result=wrong", result_da,result_fw);

+    return 0;

+}

+

+int flashtool_read_da_file(void){

+    int result=0;

+    int fd=0;

+    int file_size=0;

+    int ret=0;

+

+    fd = open(DA_FILE_NADA, O_RDONLY);

+    if(fd < 0){

+        LOGE("open %s fail",DA_FILE_NADA);

+        ret=-1;

+        goto DEINIT;

+    }

+    

+    file_size=lseek(fd, 0, SEEK_END);

+    if(file_size < 0){

+        LOGE("point file tail error-1");

+        ret=-2;

+        goto DEINIT;

+    }

+    da_size=(int32)file_size;

+    LOGI("file size=%ld",da_size);

+    da_buf=malloc(da_size);

+    if(NULL == da_buf){

+        LOGE("malloc error");

+        ret=-3;

+        goto DEINIT;

+    }

+    

+

+    result=lseek(fd, 0, SEEK_SET);

+    if(result < 0){

+        LOGE("point file tail error-2");

+        ret=-4;

+        goto DEINIT;

+    }

+

+    if(da_size != (result=read(fd, da_buf, da_size))){

+        LOGE("read file error,len=%d,orilen=%ld",result,da_size);

+        ret=-5;

+        goto DEINIT;

+    }

+

+    close(fd);

+    return 0;

+

+DEINIT:

+    if(fd>=0){

+        close(fd);

+    }

+    

+    if(NULL != da_buf){

+        free(da_buf);

+        da_buf=NULL;

+    }

+    return ret;

+}

+

+int flashtool_read_fw_file(void){

+    int result=0;

+    int fd=0;

+    int file_size=0;

+    int ret=0;

+

+    fd = open(FW_FILE_NADA, O_RDONLY);

+    if(fd < 0){

+        LOGE("open %s fail",FW_FILE_NADA);

+        ret=-1;

+        goto DEINIT;

+    }

+    

+    file_size=lseek(fd, 0, SEEK_END);

+    if(file_size < 0){

+        LOGE("point file tail error-1");

+        ret=-2;

+        goto DEINIT;

+        

+    }

+    fw_size=file_size;

+    LOGI("file size=%ld",fw_size);

+    fw_buf=malloc(fw_size);

+    if(NULL == fw_buf){

+        LOGE("malloc error");

+        ret=-3;

+        goto DEINIT;

+    }

+    

+

+    result=lseek(fd, 0, SEEK_SET);

+    if(result < 0){

+        LOGE("point file tail error-2");

+        ret=-4;

+        goto DEINIT;

+    }

+

+    if(fw_size != (result=read(fd, fw_buf, fw_size))){

+        LOGE("read file error,len=%d,orilen=%ld",result,fw_size);

+        ret=-5;

+        goto DEINIT;

+    }

+

+    close(fd);

+    return 0;

+

+DEINIT:

+    if(fd>=0){

+        close(fd);

+    }

+    

+    if(NULL != fw_buf){

+        free(fw_buf);

+        fw_buf=NULL;

+    }

+    return ret;

+    return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  main

+ *

+ * Description:

+ * ------------

+ *  Main funciton. 

+ *  Please invoke this funciton to start download process.

+ *  User must load DA and firmware file at MCU side and provide buffer pointer to the parameters in the sample

+ *  code below.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ *******************************************************************************/

+void* flashtool_download_thread(void *arg1)

+{

+    int ret;

+    GPS_DA gps_da;

+    GPS_Image_List gps_image;

+    GPS_Download_Arg arg;

+    pthread_t pthread_mt3333_controller;

+    pthread_t pthread_mt3333_data;

+    pthread_t pthread_mt3333_data_debug;

+    unsigned int retry_max=3;

+#if defined(__ANDROID_OS_10__)

+    FILE *fw_data_old = NULL;

+    char str[] = "FW download pass";

+#endif

+

+    UNUSED(arg1);

+    //mnl_set_pwrctl(1);

+    LOGI("everything is begin");

+    

+    for(int i=0;i<1; i++){

+        usleep(1000 * 1000);

+    }

+    

+

+    //User must provide the pointer of download agent file(DA) buffer and image size to the below parameters.

+    //gps_da.m_image = ......;

+    //gps_da.m_size = ......;

+    

+    //MT3333/3339 only has one image file, so set image number as 1.

+    gps_image.m_num = 1;

+    //User must provide the pointer of firmware buffer and image size to the below parameters.

+    //gps_image.m_image_list[0].m_image = ......;

+    //gps_image.m_image_list[0].m_size = ......;

+    if(flashtool_file_isvalid()){

+        if(0 == flashtool_read_da_file()){

+            if(0 == flashtool_read_fw_file()){

+                gps_image.m_image_list[0].m_image = fw_buf;

+                gps_image.m_image_list[0].m_size = fw_size;

+                gps_da.m_image = da_buf;

+                gps_da.m_size = da_size;

+            }else{

+                goto DEINIT;

+            }

+        }else{

+            goto DEINIT;

+        }

+        

+    }else{

+        goto DEINIT;

+    }

+

+    LOGI("file is ready");

+    fw_downloading=1;

+    

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

+    //Callback functions which are invoked while downloading image to GPS chip help to show the rate of progress. 

+    //Callback functions are implemented by user.

+    //If do not want to use callback function, set them as 'NULL'.

+    //If callback functions do not need input parameter, set argument as 'NULL'. 

+    arg.m_cb_download_conn = gps_download_progress_callback;

+    arg.m_cb_download_conn_arg = (void*) 1;

+    arg.m_cb_download_conn_da = gps_download_progress_callback;

+    arg.m_cb_download_conn_da_arg = (void*) 0;

+

+    //Note: before downloading, user must confirm:

+    //1. MCU UART which connects to GPS chip UART has been initialized.

+    //2. UART baud rate has been set correctly.

+    //3. GPS has been power on correctly.

+    //4. GPS 32KHz clock has been input correctly.

+    

+    do{

+        ret = FlashDownload(&gps_da, &gps_image, arg);

+        retry_max--;

+        mnl_set_pwrctl(0);

+        usleep(100 * 1000);

+        LOGE("ret=0x%x, retry=%d", ret,retry_max);

+        if(ret == FT_OK ){

+            break;

+        }

+    }while(retry_max != 0);

+    

+    fw_downloading=0;

+    if(ret == FT_OK){

+#if defined(__ANDROID_OS_10__)

+        fw_data_old = fopen(FW_FILE_NADA_OLD, "w+");

+        if (fw_data_old != NULL) {

+            fwrite(str, sizeof(str), 1, fw_data_old);

+            fclose(fw_data_old);

+            LOGE("result pass");

+        } else {

+            LOGE("result fail=%s\n", strerror(errno));

+        }

+#else

+        LOGE("rename result=%d",rename(FW_FILE_NADA, FW_FILE_NADA_OLD));

+#endif

+    }

+

+DEINIT:

+    if(fw_buf){

+        free(fw_buf);

+        fw_buf = NULL;

+    }    

+    if(da_buf){

+        free(da_buf);

+        da_buf = NULL;

+    }

+#if 0    

+    if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(g_fd_mt3333_data ,mnld_cfg.link_speed, 8, 'N', 1)){

+        LOGE("configure uart baudrate failed");

+        return;

+    }

+#endif

+

+    gps_driver_state_init();

+

+#if 1

+        //LOGE("uart baudrate:%d", mnld_cfg.init_speed);

+        if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(g_fd_mt3333_data ,mnld_cfg.init_speed, 8, 'N', 1)){

+            LOGE("configure uart baudrate failed");

+            return NULL;

+        }

+        if(1 != mt3333_controller_check_if_gpsfunctionok()){

+        #if 0    

+            if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(

+                g_fd_mt3333_data ,

+                mnld_cfg.init_speed == 115200?921600:115200, 

+                8, 'N', 1)){

+                LOGE("configure uart baudrate failed");

+                return -1;

+            }

+        #endif    

+        }

+#endif    

+

+    

+    pthread_create(&pthread_mt3333_controller, NULL, mt3333_thread_control, NULL);

+    pthread_create(&pthread_mt3333_data, NULL, mt3333_thread_data, NULL);

+    pthread_create(&pthread_mt3333_data_debug, NULL, mt3333_thread_data_debug, NULL);

+

+    pthread_exit(NULL);

+    return NULL;

+}

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/flashtool.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/flashtool.h
new file mode 100644
index 0000000..97b798a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/flashtool.h
@@ -0,0 +1,140 @@
+/*******************************************************************************

+ *  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) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  flashtool.h

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *  APIs for FlashTool Library.

+ *

+ *******************************************************************************/

+#ifndef _FLASHTOOL_H_

+#define _FLASHTOOL_H_

+

+#include "brom.h"

+#include "DOWNLOAD.H"

+#include "GPS_DL_api.h"

+#include <stdio.h>

+

+#ifdef   __cplusplus

+extern "C" {

+#endif

+

+//------------------------------------------------------------------------------

+// return code                                                                  

+//------------------------------------------------------------------------------

+

+#define FT_RET(ret)  (ret&0x000000FF)

+

+#define FT_OK                          0x000000

+#define FT_ERROR                       0x000001

+#define FT_INVALID_ARGUMENTS           0x000002

+#define FT_COM_PORT_OPEN_ERR           0x000003

+#define FT_DA_HANDLE_ERROR             0x000004

+#define FT_DL_HANDLE_ERROR             0x000005

+#define FT_BROM_ERROR                  0x000007

+#define FT_COM_PORT_SET_TIMEOUT_ERR    0x000008

+#define FT_DA_NO_RESPONSE              0x000009

+#define FT_DA_SYNC_INCORRECT           0x00000A

+#define FT_DA_VERSION_INCORRECT        0x00000B

+#define FT_DA_UNKNOWN_FLASH_DEVICE     0x00000C

+#define FT_DA_SET_EXT_CLOCK_FAIL       0x00000D

+#define FT_DA_SET_BBCHIP_TYPE_FAIL     0x00000E

+#define FT_DA_CHANGE_BAUDRATE_FAIL     0x00000F

+#define FT_DA_SET_DOWNLOAD_BLOCK_FAIL  0x000010

+#define FT_DA_DOWNLOAD_FAIL            0x000011

+#define FT_DA_FORMAT_FAIL              0x000013

+#define FT_DA_FINISH_CMD_FAIL          0x000014

+#define FT_DA_SOC_CHECK_FAIL           0x000015

+#define FT_DA_BBCHIP_DSP_VER_INCORRECT 0x000016

+#define FT_SKIP_AUTO_FORMAT_FAT        0x000017

+#define FT_DA_HW_ERROR                 0x000018

+#define FT_DA_ENABLE_WATCHDOG_FAIL     0x000019

+#define FT_CALLBACK_ERROR              0x000020

+             

+

+//------------------------------------------------------------------------------

+// DA report structure                                                          

+//------------------------------------------------------------------------------

+typedef  struct DA_REPORT_T{

+   unsigned char  expected_da_major_ver;

+   unsigned char  expected_da_minor_ver;

+   unsigned char  da_major_ver;

+   unsigned char  da_minor_ver;

+   DEVICE_INFO    flash_device_id;

+   unsigned int   flash_size;

+   unsigned int   fat_begin_addr;

+   unsigned int   fat_length;

+   unsigned int   ext_sram_size;

+}s_DA_REPORT_T;

+

+

+//------------------------------------------------------------------------------

+// FLASHTOOL_ARG structure                                                      

+//------------------------------------------------------------------------------

+

+typedef  struct {

+   CALLBACK_DOWNLOAD_PROGRESS_INIT m_cb_download_conn_init; //callback function which is invoked at the beginning of firmware transimitting.

+   void  *m_cb_download_conn_init_arg; // parameter of the callback function upper

+

+   CALLBACK_CONN_BROM_WRITE_BUF_INIT m_cb_download_conn_da_init;//callback function which is invoked at the beginning of DA transimitting.

+   void *m_cb_download_conn_da_init_arg; // parameter of the callback function upper

+

+   CALLBACK_DOWNLOAD_PROGRESS  m_cb_download_conn; //callback function which is invoked during the firmware transimitting.

+   void  *m_cb_download_conn_arg; // parameter of the callback function upper

+

+   CALLBACK_CONN_BROM_WRITE_BUF  m_cb_download_conn_da; //callback function which is invoked during the DA transimitting.

+   void *m_cb_download_conn_da_arg; // parameter of the callback function upper

+   

+}FLASHTOOL_ARG;

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  FlashDownload

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to manage the download flow.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  GPS_da: import Download Agent(DA) buffer and size. 

+ *  GPS_image_list:  import firmware buffer and size.

+ *

+ *******************************************************************************/

+extern int  FlashDownload(

+   GPS_DA* GPS_da,

+   GPS_Image_List* GPS_image_list,

+   GPS_Download_Arg arg);

+

+void* flashtool_download_thread(void *arg);

+int flashtool_file_isvalid(void);

+

+

+#ifdef   __cplusplus

+}

+#endif

+

+#endif

+

+

+

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/gps_uart.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/gps_uart.c
new file mode 100644
index 0000000..c1deed2
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/gps_uart.c
@@ -0,0 +1,226 @@
+#ifdef CONFIG_GPS_MT3303

+

+/*******************************************************************************

+*  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) 2016

+*

+*******************************************************************************/

+

+/*******************************************************************************

+ *

+ * Filename:

+ * ---------

+ *       gps_uart.c

+ *

+ * Description:

+ * ------------

+ *    This file defines the sample code of uart driver.

+ *    User must implement all the functions in this file based on your MCU.

+ *

+ *******************************************************************************/

+#include "gps_uart.h"

+#include "sw_types.h"

+#include <stdio.h>

+#include <stdarg.h>

+#include <sys/time.h>

+#include <string.h>

+#include <sys/epoll.h>

+#include <errno.h>

+#include <pthread.h>

+#include <termios.h>

+#include <time.h>

+#include <unistd.h>

+

+#include "mtk_auto_log.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "flashtool"

+#endif

+

+extern int g_fd_mt3333_data;

+static uint32 err_threshold = 0xFFFFF; //Timeout flag, can be changed.

+

+void GPS_UART_IgnoreData(void)

+{

+    uint8 buf[1024];

+    int count=0;

+    while(1)

+    {

+        count = read(g_fd_mt3333_data, &buf, 1024);

+        if(count>=0){

+            LOGE("count=%d",count);

+             continue;

+        }

+        break;

+    }

+

+    //usleep(500 * 1000);

+

+    while(1)

+    {

+        count = read(g_fd_mt3333_data, &buf, 1024);

+        if(count>=0){

+            LOGE("count1=%d",count);

+             continue;

+        }

+        break;

+    }

+}

+

+void GPS_UART_Init(void)    

+{

+

+    /* uart pinmux configure */

+

+    /* enable uart clock */

+    

+    //Set Baudrate

+

+}

+

+//Get one byte data from UART and return this byte.

+//This function should wait in a while loop until received a data.

+uint8 GPS_UART_GetByte(void)

+{

+    uint8    g_uart_last_rx_data = 0;

+

+    while(1)

+    {

+        if(1 == read(g_fd_mt3333_data, &g_uart_last_rx_data, 1)){

+            return g_uart_last_rx_data;

+        }

+    }

+}

+

+//Get one byte data from UART and output this byte by formal parameter.

+//This function will return finally if received a data or timeout.

+BOOL GPS_UART_GetByteStatus(uint8 *data)

+{

+    //uint8    g_uart_last_rx_data = 0;

+    uint32  err_count=0;

+

+    while((err_count++)<err_threshold)

+    {

+        if(1 == read(g_fd_mt3333_data, data, 1)){

+            return TRUE;

+        }

+    }

+    return FALSE;

+}

+

+//Get one byte data from UART and output this byte by formal parameter.

+//This function will return immediatelly after trying reading data from UART no matter any data is read.

+BOOL GPS_UART_GetByte_NO_TIMEOUT(uint8 *data)

+{    

+    if(1 == read(g_fd_mt3333_data, data, 1)){

+        return TRUE;

+    }

+    return FALSE;

+}

+

+//Read data from UART, read length is defined by input parameter, and output the string by formal parameter.

+BOOL GPS_UART_GetByte_Buffer(uint32* buf, uint32 length)

+{

+    bool ret;

+    uint32 i;

+    uint8 * buf8 = (uint8*)buf;

+

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

+    {

+        ret = GPS_UART_GetByteStatus(buf8+i);

+        if(!ret){ return FALSE;}

+    }

+

+    return TRUE;

+}

+void GPS_UART_Flush(void)

+{

+    LOGE("result:%d",fsync(g_fd_mt3333_data));

+}

+

+//Put one byte data to UART.

+void GPS_UART_PutByte(uint8 data)

+{

+    while(1)

+    {

+        if(1 == write(g_fd_mt3333_data, &data, 1)){

+            return;

+        }

+    }

+}

+

+//Put data to UART, write buffer and length are defined by input parameter.

+void GPS_UART_PutByte_Buffer(uint32* buf, uint32 length)

+{

+    uint32 i;

+    uint8* tmp_buf = (uint8*)buf;

+

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

+    {

+        GPS_UART_PutByte(*(tmp_buf+i));

+    }

+}

+

+//Get 16 bits data from UART.

+uint16 GPS_UART_GetData16(void)            //ok, high byte is first

+{

+    uint8    tmp,index;

+    uint16     tmp16;

+    uint16  result =0;

+    for (index =0;index < 2;index++)

+    {

+        tmp = GPS_UART_GetByte();

+        tmp16 = (uint16)tmp;

+        result |= (tmp16 << (8-8*index));

+    }

+    return result;

+}

+

+//Put 16 bits data from UART.

+void GPS_UART_PutData16(uint16 data)        //ok, high byte is first

+{

+    uint8    tmp,index;

+    uint16     tmp16;

+

+    for (index =0;index < 2;index++)

+    {

+        tmp16 = (data >> (8-8*index));

+        tmp = (uint8)tmp16;

+        GPS_UART_PutByte(tmp);

+    }

+}

+

+//Get 32 bits data from UART.

+uint32 GPS_UART_GetData32(void)            //ok, high byte is first

+{

+    uint8    tmp,index;

+    uint32     tmp32;

+    uint32  result =0;

+    for (index =0;index < 4;index++)

+    {

+        tmp = GPS_UART_GetByte();

+        tmp32 = (uint32)tmp;

+        result |= (tmp32 << (24-8*index));

+    }

+    return result;

+}

+

+//Put 32 bits data from UART.

+void GPS_UART_PutData32(uint32 data)        //ok, high byte is first

+{

+    uint8    tmp,index;

+    uint32     tmp32;

+

+    for (index =0;index < 4;index++)

+    {

+        tmp32 = (data >> (24-8*index));

+        tmp = (uint8)tmp32;

+        GPS_UART_PutByte(tmp);

+    }

+}

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/gps_uart.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/gps_uart.h
new file mode 100644
index 0000000..3b98daa
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/gps_uart.h
@@ -0,0 +1,49 @@
+/*******************************************************************************

+ *  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) 2016

+ *

+ *******************************************************************************/

+//Sample code of gps_uart.h

+//User must implement this file based on your MCU.

+

+#include "sw_types.h"

+

+

+#define UART2_base       (0x00000000)

+

+//UART2 MMP address

+#define   UART2_RBR		(UART2_base+0x0000)		/* Read only */

+#define   UART2_THR		(UART2_base+0x0000)		/* Write only */

+#define   UART2_LSR		(UART2_base+0x0014)

+

+//LSR

+#define   UART_LSR_DR         	0x0001

+#define   UART_LSR_OE         	0x0002

+#define   UART_LSR_PE         	0x0004

+#define   UART_LSR_THRE     	  0x0020

+#define   UART_LSR_FIFOERR    	0x0080

+

+#define UART_ReadReg(_addr)   		(uint16)(*(volatile uint8 *)_addr)

+#define UART_WriteReg(_addr,_data)  *(volatile uint8 *)_addr = (uint8)_data

+

+

+void GPS_UART_IgnoreData(void);

+

+void GPS_UART_Init(void);

+uint8 GPS_UART_GetByte(void);

+BOOL GPS_UART_GetByteStatus(uint8 *data);

+BOOL GPS_UART_GetByte_NO_TIMEOUT(uint8 *data);

+BOOL GPS_UART_GetByte_Buffer(uint32* buf, uint32 length);

+void GPS_UART_PutByte(uint8 data);

+void GPS_UART_PutByte_Buffer(uint32* buf, uint32 length);

+uint16 GPS_UART_GetData16(void);

+void GPS_UART_PutData16(uint16 data);

+uint32 GPS_UART_GetData32(void);

+void GPS_UART_PutData32(uint32 data);

+void GPS_UART_Flush(void);

+

+

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/sw_types.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/sw_types.h
new file mode 100644
index 0000000..697670f
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/sw_types.h
@@ -0,0 +1,102 @@
+/*******************************************************************************

+ *  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) 2016

+ *

+ *******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *   sw_types.h

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *   Common type and structure definition

+ *

+ *******************************************************************************/

+

+#ifndef SW_TYPES_H

+#define SW_TYPES_H

+

+#define COMPILE_ASSERT(condition) ((void)sizeof(char[1 - 2*!!!(condition)]))

+

+/*

+ * general definitions

+ */

+

+typedef signed char    int8;

+typedef signed short   int16;

+typedef signed long    int32;

+typedef signed int     intx;

+typedef unsigned char  uint8;

+typedef unsigned short uint16;

+typedef unsigned long  uint32;

+#ifdef WIN32

+	typedef unsigned long uint64;

+#else

+	typedef unsigned long long uint64;

+#endif

+typedef unsigned int   uintx;

+typedef unsigned char  U8;

+typedef unsigned short U16;

+typedef unsigned long  U32;

+typedef int32          S32;

+typedef unsigned int   Ux;

+typedef unsigned char*  P_U8;

+typedef unsigned short* P_U16;

+typedef unsigned long*  P_U32;

+typedef unsigned int*   P_Ux;

+

+typedef int8    int8_t;

+typedef int16   int16_t;

+//typedef int32   int32_t;

+typedef uint8   uint8_t;

+typedef uint16  uint16_t;

+//typedef uint32  uint32_t;

+

+#ifndef __cplusplus

+typedef unsigned char  bool;

+#endif

+

+/*

+ * Definitions for BOOLEAN

+ */

+/*

+#define FALSE          0

+#define TRUE           1

+*/

+/*

+ * Definitions for BOOLEAN

+ */

+typedef enum BOOL

+{

+    FALSE = 0,

+    TRUE = 1

+} BOOL;

+

+

+/*

+ * Definitions for NULL

+ */

+#ifndef NULL

+#define NULL           0

+#endif

+

+/*

+ * For GFH library

+ */

+#if defined(WIN32)

+#define __WIN32_STDCALL   __stdcall

+#else

+#define __WIN32_STDCALL

+#endif

+

+#endif  /* SW_TYPES_H */

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/gps_controller.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/gps_controller.c
new file mode 100644
index 0000000..6976fc6
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/gps_controller.c
@@ -0,0 +1,3373 @@
+// SPDX-License-Identifier: MediaTekProprietary
+#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>
+//#include <linux/fm.h>
+#include <signal.h>
+#include <inttypes.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_flp_main.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"
+#include "epo.h"
+#include "qepo.h"
+#include "mtknav.h"
+#include "mtk_auto_log.h"
+#ifdef CONFIG_GPS_MT3303
+#include "mt3333_controller.h"
+#endif
+
+int network_count = 0;
+int g_agc_level = 0;
+
+#if MTK_GPS_NVRAM
+//#include "CFG_GPS_File.h"
+#endif
+
+typedef enum {
+    MAIN2GPS_EVENT_START            = 0,
+    MAIN2GPS_EVENT_STOP             = 1,
+    MAIN2GPS_DELETE_AIDING_DATA     = 2,
+    GPS2GPS_NMEA_DATA_TIMEOUT       = 3,
+} main2gps_event;
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "gps_controlller"
+#endif
+
+/*#define QEPO_BD 1
+#define QEPO_GA 1*/
+
+#ifdef MTK_GPS_CO_CLOCK_DATA_IN_MD
+#define GPS_CALI_DATA_PATH "/data/nvram/md/NVRAM/CALIBRAT/ML4A_000"
+#define GPS_CALI_DATA_DENALI_PATH "/data/nvram/md/NVRAM/CALIBRAT/EL6N_000"
+#endif
+
+#ifdef CONFIG_GPS_MT3303
+#define MNL_ATTR_PWRCTL  "/sys/class/gpsdrv/gps/pwrctl"
+#define MNL_ATTR_SUSPEND "/sys/class/gpsdrv/gps/suspend"
+#define MNL_ATTR_STATE   "/sys/class/gpsdrv/gps/state"
+#define MNL_ATTR_PWRSAVE "/sys/class/gpsdrv/gps/pwrsave"
+#define MNL_ATTR_STATUS  "/sys/class/gpsdrv/gps/status"
+#define MNL_ATTR_RDELAY  "/sys/class/gpsdrv/gps/rdelay"
+
+enum {
+    GPS_PWRCTL_UNSUPPORTED  = 0xFF,
+    GPS_PWRCTL_OFF          = 0x00,
+    GPS_PWRCTL_ON           = 0x01,
+    GPS_PWRCTL_RST          = 0x02,
+    GPS_PWRCTL_OFF_FORCE    = 0x03,
+    GPS_PWRCTL_RST_FORCE    = 0x04,
+    GPS_PWRCTL_MAX          = 0x05,
+};
+
+enum {
+    MNL_GPS_STATE_UNSUPPORTED   = 0xFF,
+    MNL_GPS_STATE_PWROFF        = 0x00, /*cleanup/power off, default state*/
+    MNL_GPS_STATE_INIT          = 0x01, /*init*/
+    MNL_GPS_STATE_START         = 0x02, /*start navigating*/
+    MNL_GPS_STATE_STOP          = 0x03, /*stop navigating*/
+    MNL_GPS_STATE_DEC_FREQ      = 0x04,
+    MNL_GPS_STATE_SLEEP         = 0x05,
+    MNL_GPS_STATE_MAX           = 0x06,
+};
+
+extern MNL_CONFIG_T mnl_config;
+extern int is_ygps_delete_data;
+
+#if 0
+/*****************************************************************************/
+static int mnl_read_attr(const char *name, unsigned char *attr) {
+    int fd = open(name, O_RDWR);
+    unsigned char buf;
+    int err = 0;
+
+    if (fd == -1) {
+        LOGE("open %s err = %s\n", name, strerror(errno));
+        return err;
+    }
+    do {
+        err = read(fd, &buf, sizeof(buf));
+    } while (err < 0 && errno == EINTR);
+    if (err != sizeof(buf)) {
+        LOGE("read fails = %s\n", strerror(errno));
+        err = -1;
+    } else {
+        err = 0;    /*no error*/
+    }
+    if (close(fd) == -1) {
+        LOGE("close fails = %s\n", strerror(errno));
+        err = (err) ? (err) : (-1);
+    }
+    if (!err)
+        *attr = buf - '0';
+    else
+        *attr = 0xFF;
+    return err;
+}
+#endif
+
+static int mnl_write_attr(const char *name, unsigned char attr) {
+    int err, fd = open(name, O_RDWR);
+    char buf[] = {attr + '0'};
+
+    if (fd == -1) {
+        LOGE("open %s err = %s\n", name, strerror(errno));
+        return -errno;
+    }
+    do { err = write(fd, buf, sizeof(buf));
+    } while (err < 0 && errno == EINTR);
+
+    if (err != sizeof(buf)) {
+        LOGE("write fails = %s\n", strerror(errno));
+        err = -errno;
+    } else {
+        err = 0;    // no error
+    }
+    if (close(fd) == -1) {
+        LOGE("close fails = %s\n", strerror(errno));
+        err = (err) ? (err) : (-errno);
+    }
+    LOGD("write '%d' to %s okay\n", attr, name);
+    return err;
+}
+
+#ifdef CONFIG_GPS_MT3303_WITHOUT_POWER_CONTROL
+extern int g_fd_mt3333_data;
+extern unsigned char gps_nmea_cal_checksum(unsigned char *ptr, unsigned char len);
+
+int mnl_hot_start(void)
+{ 
+    int err=0;
+    int count=0;
+    const char hot_cmd[]="$PMTK101";
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",hot_cmd);
+
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s\n" ,err, nmea_cmd);
+    
+    return 0;
+}
+#endif
+
+int mnl_set_pwrctl(unsigned char pwrctl) {
+    if (pwrctl < GPS_PWRCTL_MAX) {
+        #ifdef CONFIG_GPS_MT3303_WITHOUT_POWER_CONTROL
+        if(pwrctl == GPS_PWRCTL_ON) {
+            mnl_hot_start();
+            LOGD("$PMTK101 pwrctl = %d\n", pwrctl);
+        }
+        #endif
+        return mnl_write_attr(MNL_ATTR_PWRCTL, pwrctl);
+    } else {
+        LOGE("invalid pwrctl = %d\n", pwrctl);
+        errno = -EINVAL;
+        return -1;
+    }
+}
+
+#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 DSP_DEV                     "/dev/stpgps" /* stp-gps char dev */
+#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 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
+
+#if defined(__ANDROID_OS_P__)
+#define GPS_CLOCK_TYPE_P    "vendor.gps.clock.type"
+#define GPS_GPS_VERSION     "vendor.gps.gps.version"
+#elif defined(__ANDROID_OS_O__)
+#define GPS_CLOCK_TYPE_P    "gps.clock.type"
+#define GPS_GPS_VERSION     "gps.gps.version"
+#endif
+
+#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*/
+
+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 char storagePath[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 assist_data_bit_map = FLAG_HOT_START;
+#ifndef CONFIG_GPS_MT3303
+static UINT32 delete_aiding_data;
+#endif
+#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;
+#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;
+static int in_meta_factory = 0;
+
+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;
+
+#define HIDE_LOG_PROP "ro.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 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(int index);
+#endif
+static int gps_raw_data_enable(void);
+#if 0
+static void get_gps_measurement_clock_data();
+#endif
+static void get_gnss_measurement_clock_data();
+#if 0
+static void get_gps_navigation_event();
+#endif
+static void get_gnss_navigation_event();
+
+/////////////////////////////////////////////////////////////////////////////
+// MAIN -> GPS Control (handlers)
+static int mnld_gps_start(int delete_aiding_data_flags) {
+    LOGD("mnld_gps_start flag=0x%x", delete_aiding_data_flags);
+
+    int ret = 0;
+    assist_data_bit_map = delete_aiding_data_flags;
+
+#ifdef CONFIG_GPS_MT3303
+    ret = mnl_set_pwrctl(GPS_PWRCTL_ON);  /*if current state is power off*/
+#endif
+    if ((ret = mnld_gps_start_impl())) {
+        LOGE("mnld_gps_start() fail, ret=%d", ret);
+        return ret;
+    } else {
+        LOGD("mnld_gps_start() success");
+    }
+
+    return ret;
+}
+
+
+static int mnld_gps_stop() {
+    LOGD("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 {
+        mnld_gps_stop_done();
+        LOGD("mnld_gps_stop_impl success");
+    }
+#ifdef CONFIG_GPS_MT3303
+    mnl_set_pwrctl(GPS_PWRCTL_OFF);
+#endif
+
+    return 0;
+}
+
+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};
+#ifndef CONFIG_GPS_MT3303
+    int ret = 0;
+#endif
+    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 {
+#ifndef CONFIG_GPS_MT3303
+        assist_data_bit_map = delete_aiding_data_flags;
+        mtk_gps_delete_nv_data(assist_data_bit_map);
+#endif
+    }
+#ifndef CONFIG_GPS_MT3303
+    if ((ret = mtk_gps_set_param(MTK_PARAM_CMD_RESTART, &restart))) {
+        LOGE("GPS restart fail %d", ret);
+    }
+#else
+    is_ygps_delete_data=10;
+    mt3333_controller_delete_aiding_data(delete_aiding_data_flags);
+#endif
+    gps_restart = 1;
+    get_condition(&lock_for_sync[M_RESTART]);
+    gps_restart = 0;
+    mnld_gps_reset_done();
+    return 0;
+}
+/////////////////////////////////////////////////////////////////////////////
+
+/*****************************************************************************/
+#ifndef CONFIG_GPS_MT3303
+static MNL_CONFIG_T mnld_cfg = {
+#else
+MNL_CONFIG_T mnld_cfg = {
+    .init_speed = 921600,
+    .link_speed = 921600,
+#endif 
+    .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
+};
+
+#ifndef CONFIG_GPS_MT3303
+static MNL_CONFIG_T mnl_config = {
+#else
+MNL_CONFIG_T mnl_config = {
+#endif
+    .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 = 7000,
+    .dev_dbg = DBG_DEV,
+    .dev_dsp = DSP_DEV,
+    .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,
+    .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,
+#ifndef CONFIG_GPS_MT3303
+    .GNSSOPMode = MTK_CONFIG_GPS_GLONASS_BEIDOU,     // 0: G+G; 1: G+B
+#else
+    .GNSSOPMode = MTK_CONFIG_GPS_BEIDOU,
+#endif
+    .dbglog_file_max_size = 25*1024*1024,
+    .dbglog_folder_max_size = 300*1024*1024,
+    .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
+};
+void mtk_null(UINT16 a) {
+    LOGD("mtk_null a=%d\n", a);
+    return;
+}
+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);
+}
+
+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_gps_ofl_sys_rst_stpgps_req,
+    .ofl_sys_submit_flp_data = mtk_gps_ofl_sys_submit_flp_data,
+    .sys_alps_gps_dbg2file_mnld = mnl_sys_alps_gps_dbg2file_mnld,
+    .ofl_sys_mnl_offload_callback = mtk_gps_ofl_sys_mnl_offload_callback,
+    .sys_gps_mnl_data2mnld_callback = sys_gps_mnl_data2mnld_callback,
+};
+
+/*****************************************************************************/
+int mtk_gps_log_is_hide(void){
+    return !!(mtk_gps_log_hide );
+}
+
+bool mnl_offload_is_enabled() {
+    return !!(mnld_cfg.OFFLOAD_enabled);
+}
+
+void mnl_offload_set_enabled(void) {
+    mnld_cfg.OFFLOAD_enabled = 1;
+}
+
+void mnl_offload_clear_enabled(void) {
+    mnld_cfg.OFFLOAD_enabled = 0;
+}
+
+/*****************************************************************************
+ * 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("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 disabled!!!");
+        return false;
+    }
+#endif
+}
+bool mnld_support_auto_switch_mode() {
+    bool ret = false;
+    if (mnld_cfg.OFFLOAD_enabled && (mnld_cfg.OFFLOAD_switchMode == 1)) {
+        ret = true;
+    }
+    return ret;
+}
+
+bool mnld_offload_is_auto_mode() {
+    bool ret = false;
+    if (mnld_cfg.OFFLOAD_enabled && (mnld_cfg.OFFLOAD_switchMode == 1) &&
+        ((mnld_flp_session.type == MNLD_FLP_CAPABILITY_OFL_MODE) ||
+        (mnld_gfc_session.type == MNLD_GFC_CAPABILITY_OFL_MODE))) {
+        ret = true;
+    }
+    return ret;
+}
+
+bool mnld_offload_is_always_on_mode() {
+    bool ret = false;
+    if (mnld_cfg.OFFLOAD_enabled && (mnld_cfg.OFFLOAD_switchMode == 0)) {
+        ret = true;
+    }
+    return ret;
+}
+
+void mnld_offload_check_capability() {
+    if (chip_id[0] == 0) {
+        chip_detector();
+    }
+    if (strcmp(chip_id, "0x6758") == 0 || strcmp(chip_id, "0x6771") == 0
+        || strcmp(chip_id, "0x6775") == 0) {
+        mnld_cfg.OFFLOAD_enabled = 1;
+        mnld_cfg.OFFLOAD_switchMode = 1;
+        mnld_flp_session.type = MNLD_FLP_CAPABILITY_AP_OFL_MODE;
+        mnld_flp_session.pre_type = MNLD_FLP_CAPABILITY_AP_OFL_MODE;
+        mnld_gfc_session.type = MNLD_GFC_CAPABILITY_AP_OFL_MODE;
+        mnld_gfc_session.pre_type = MNLD_GFC_CAPABILITY_AP_OFL_MODE;
+    }
+}
+
+#ifdef CONFIG_GPS_MT3303
+/*****************************************************************************/
+static int mnl_set_state(unsigned char state) {
+
+    int err;
+    if (state < MNL_GPS_STATE_MAX) {
+        if ((err = mnl_write_attr(MNL_ATTR_STATE, state)))
+            return err;
+        return 0;
+    } else {
+        LOGE("invalid state = %d\n", state);
+        errno = -EINVAL;
+        return -1;
+    }
+}
+
+#if 0
+/*****************************************************************************/
+static int mnl_get_state(unsigned char *state) {
+    return mnl_read_attr(MNL_ATTR_STATE, state);
+}
+#endif
+
+void gps_control_mnl_set_pwrctl(void) {
+    mnl_set_pwrctl(GPS_PWRCTL_RST_FORCE);
+}
+
+/*****************************************************************************/
+static int mnl_set_status(char *buf, int len) {
+    const char *name = MNL_ATTR_STATUS;
+    int err, fd = open(name, O_RDWR);
+
+    if (fd == -1) {
+        LOGE("open %s err = %s\n", name, strerror(errno));
+        return -errno;
+    }
+    do {
+        err = write(fd, buf, len);
+    } while (err < 0 && errno == EINTR);
+
+    if (err != len) {
+        LOGE("write fails = %s\n", strerror(errno));
+        err = -errno;
+    } else {
+        err = 0;    /*no error*/
+    }
+    if (close(fd) == -1) {
+        LOGE("close fails = %s\n", strerror(errno));
+        err = (err) ? (err) : (-errno);
+    }
+    return err;
+}
+
+void gps_control_mnl_set_status(void) {
+    static int restart_count = 0;
+    time_t tm;
+    struct tm *p;
+
+    time(&tm);
+    p = localtime(&tm);
+
+    restart_count++;
+    LOGD("restart_count=%d\n", restart_count);
+    if (p != NULL) {
+        char buf_restart[48];
+        snprintf(buf_restart, sizeof(buf_restart), "(%d/%d/%d %d:%d:%d) - %d/%d",
+            p->tm_year, 1 + p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec,
+            restart_count, 0x02);  // MNL_RESTART_TIMEOUT_NMEA_MONITOR
+        mnl_set_status(buf_restart, strlen(buf_restart));
+    }
+}
+
+extern int fw_downloading; //wangguojun modify
+int gps_driver_state_init() {
+    int ret = 0;
+    if(fw_downloading==1)//wangguojun modify
+        return 0;
+    if ((ret = mnl_set_pwrctl(GPS_PWRCTL_OFF)))  /*default power off*/
+        return ret;
+    ret = mnl_set_state(MNL_GPS_STATE_INIT);
+    return ret;
+}
+
+#endif
+
+int mnl_init() {
+    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;
+    }
+
+    gps_dbg_log_property_load();
+
+#ifndef CONFIG_GPS_MT3303
+    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);
+    }
+#endif
+    LOGD("MNLD can support offload/non-offload, ver = %s.\n", OFL_VER);
+    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(GPS_GPS_VERSION, "0x6735");  // Denali1/2/3
+    } else {
+        property_set(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) {
+        *sv_type = 15;  // GPS+Glonass+Beidou+Galileo
+    }
+}
+
+int hasAlmanac() {
+    char ch;
+    char* ptr;
+    int i = -1;
+    int size = -1;
+    FILE *fp;
+    char fileName[] = "/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) {
+        LOGE("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 = 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 = fgetc(fp);
+    }
+
+    i = 0;
+    ch = fgetc(fp);
+
+    while (!feof(fp)) {
+        if ((ch >= '0' && ch <= '9') || (ch == ',')) {
+            str[i] = ch;
+            i++;
+        }
+        ch = 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 ANDROID_MNLD_PROP_SUPPORT
+    if (almanac_sat_num >= 25) {
+        property_set("gps.almanac", strTime);
+        return 1;
+    } else {
+        property_set("gps.almanac", "0");
+    }
+#endif
+    return 0;
+}
+
+static int mnld_gps_start_impl(void) {
+    int ret = 0;
+    int gps_user = GPS_USER_UNKNOWN;
+
+#ifdef CONFIG_GPS_MT3303
+    char name[128] = "Version: MTK_MNLD_5_6_0_18041201, GNSS chip is 3303, there is no MNL";
+#else
+    char name[128] = "Version: MTK_MNLD_5_6_0_18041201, MNL_5_0_W1824_MP";
+#endif
+    gps_debuglog_state = MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD;
+    //LOGD("mnld_gps_start_impl");
+    mnl_utl_load_property(&mnl_config);
+
+    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);
+#ifndef CONFIG_GPS_MT3303
+        mtk_gps_ofl_set_user(gps_user);
+#endif
+
+    // GNSS HIDL v1.1 update driver/mnl version
+        mnl2hal_update_gnss_name(name, strlen(name));
+
+    /*initialize system resource (message queue, mutex) used by library*/
+    if ((ret = mtk_gps_sys_init())) {
+        LOGD("mtk_gps_sys_init err = %d\n", errno);
+    } else {
+        LOGD("mtk_gps_sys_init() success\n");
+    }
+    // mnld_gps_start_nmea_monitor();
+    // start library gps run
+    if ((ret = linux_gps_init())) {
+        LOGE("linux_gps_init err = %d\n", errno);
+        mnld_gps_stop_impl();
+        return ret;
+    } else {
+        LOGD("linux_gps_init() success\n");
+    }
+
+    if ((ret = linux_setup_signal_handler())) {
+        LOGE("linux_setup_signal_handler err = %d\n", errno);
+        mnld_gps_stop_impl();
+        return ret;
+    } else {
+        LOGD("linux_setup_signal_handler() success\n");
+    }
+
+    get_gps_version();
+    return ret;
+}
+
+/*****************************************************************************/
+#ifndef CONFIG_GPS_MT3303
+static int linux_gps_init(void) {
+    int 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;
+    int dsp_open_retry;
+
+    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;
+
+#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("Denali calibration,chip_id:%s",chip_id);
+        //fd = open(GPS_CALI_DATA_DENALI_PATH, O_RDONLY, 660);
+        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, 660);
+        fd = open(GPS_CALI_DATA_DENALI_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)) {
+            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 %d\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("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
+
+#ifdef MTK_ADR_SUPPORT
+    init_cfg.fix_interval = 1000;                //  1Hz update rate
+#else
+    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);
+#endif
+
+    init_cfg.datum = MTK_DATUM_WGS84;           //  datum
+    init_cfg.dgps_mode = MTK_DGPS_MODE_SBAS;    //  enable SBAS
+
+    dsp_open_retry = 0;
+    while (1) {
+        dsp_fd = open(mnl_config.dev_dsp, O_RDWR);
+        if (dsp_fd == -1) {
+            LOGD("open_port: Unable to open - %s \n", mnl_config.dev_dsp);
+            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\n");
+        }
+        break;
+    }
+#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{
+        mtk_gps_log_hide = 0;
+    }
+}
+#endif
+
+    if (chip_id[0] == 0) {
+        chip_detector();
+    }
+
+#if ANDROID_MNLD_PROP_SUPPORT
+    // strcpy(driver_cfg.mnl_chip_id, chip_id);
+    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) {
+        clock_type = 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 (property_set(GPS_CLOCK_TYPE_P, "20") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x10:
+            LOGD("TCXO, buffer 1\n");
+            init_cfg.u1ClockType = 0xFF;
+            if (property_set(GPS_CLOCK_TYPE_P, "10") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x20:
+            LOGD("TCXO, buffer 2\n");
+            init_cfg.u1ClockType = 0xFF;
+            if (property_set(GPS_CLOCK_TYPE_P, "20") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x30:
+            LOGD("TCXO, buffer 3\n");
+            init_cfg.u1ClockType = 0xFF;
+            if (property_set(GPS_CLOCK_TYPE_P, "30") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x40:
+            LOGD("TCXO, buffer 4\n");
+            init_cfg.u1ClockType = 0xFF;
+            if (property_set(GPS_CLOCK_TYPE_P, "40") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x01:
+            LOGD("GPS coclock, buffer 2, coTMS\n");
+            init_cfg.u1ClockType = 0xFE;
+            if (property_set(GPS_CLOCK_TYPE_P, "21") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x02:
+        case 0x03:
+            LOGD("TCXO, buffer 2, coVCTCXO\n");
+            init_cfg.u1ClockType = 0xFF;
+            if (property_set(GPS_CLOCK_TYPE_P, "20") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x11:
+            LOGD("GPS coclock, buffer 1\n");
+            init_cfg.u1ClockType = 0xFE;
+            if (property_set(GPS_CLOCK_TYPE_P, "11") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x21:
+            LOGD("GPS coclock, buffer 2\n");
+            init_cfg.u1ClockType = 0xFE;
+            if (property_set(GPS_CLOCK_TYPE_P, "21") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x31:
+            LOGD("GPS coclock, buffer 3\n");
+            init_cfg.u1ClockType = 0xFE;
+            if (property_set(GPS_CLOCK_TYPE_P, "31") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x41:
+            LOGD("GPS coclock, buffer 4\n");
+            init_cfg.u1ClockType = 0xFE;
+            if (property_set(GPS_CLOCK_TYPE_P, "41") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        default:
+            LOGE("unknown clock type, clocktype = %x\n", clock_type);
+        }
+    } 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 (property_set(GPS_CLOCK_TYPE_P, "90") != 0) {
+                    LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+                }
+            } else if (0xFE == init_cfg.u1ClockType) {
+                LOGD("GPS coclock\n");
+                if (property_set(GPS_CLOCK_TYPE_P, "91") != 0) {
+                    LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+                }
+            } else {
+                LOGD("GPS unknown clock\n");
+            }
+        }
+        /*Add clock type to display on YGPS by mtk06325 2013-12-09 end */
+    }
+#endif
+    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, "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("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;
+    LOGI("GNSSOPMode: 0x%x\n", init_cfg.GNSSOPMode);
+
+    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((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;
+
+    extern MTK_GPS_BOOL enable_dbg_log;
+    enable_dbg_log = mnl_config.debug_nmea;
+
+    gps_debuglog_state = gps_debuglog_state | mnl_config.dbg2file;
+     // driver_cfg.DebugType: 0x01-> libmnl write file;0x11 -> libmnl write file.
+    driver_cfg.DebugType    =   gps_debuglog_state;
+    if(mnl_debug_file_check(mnl_config.debug_file_name) == MTK_GPS_SUCCESS)
+    {
+        strncpy(gps_debuglog_file_name,mnl_config.debug_file_name,GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+    } else {
+        LOGW("debug file(%s) invalide, use the default(%s)\r\n", mnl_config.debug_file_name, LOG_FILE);
+        strncpy(storagePath, LOG_FILE_PATH, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+        strncpy(gps_debuglog_file_name,LOG_FILE,GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+    }
+    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;
+
+    driver_cfg.u1AgpsMachine = mnl_config.u1AgpsMachine;
+    if (driver_cfg.u1AgpsMachine == 1) {
+        LOGD("use CRTU to test\n");
+    } else {
+        LOGD("use Spirent to test\n");
+    }
+
+    if (network_count > 0) {
+        //driver_cfg.network_connect = 1; //network is connect
+    } else {
+        //driver_cfg.network_connect = 0; //network is disconnect
+    }
+    //LOGD("start gps network_count:%d", driver_cfg.network_connect);
+
+    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("start gps raw meas enable:%d", driver_cfg.raw_meas_enable);
+
+    status = mtk_gps_delete_nv_data(assist_data_bit_map);
+
+    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\n",
+        status, init_cfg.C0, init_cfg.C1, init_cfg.initU, init_cfg.lastU, init_cfg.GNSSOPMode, init_cfg.eLNA_pin_num);
+    driver_cfg.dsp_fd = dsp_fd;
+    if (strcmp(chip_id, "0x6797") == 0 || strcmp(chip_id, "0x6632") == 0 ||
+        strcmp(chip_id, "0x6759") == 0 || strcmp(chip_id, "0x6758") == 0 ||
+        strcmp(chip_id, "0x6771") == 0 || strcmp(chip_id, "0x6775") == 0) {
+        LOGD("OFFLOAD_STATUS:OFFLOAD_enabled:%d,OFFLOAD_switchMode:%d,type=%d",
+            mnld_cfg.OFFLOAD_enabled,mnld_cfg.OFFLOAD_switchMode,mnld_flp_session.type);
+        if (mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+            gps_control_kernel_wakelock_init();
+            mtk_gps_ofl_set_option(MNL_OFL_OPTION_ENALBE_OFFLOAD);
+            LOGD("MNL_OFL_OPTION_ENALBE_OFFLOAD = 1");
+        } else {
+            mtk_gps_ofl_set_option(0);
+            LOGD("MNL_OFL_OPTION_ENALBE_OFFLOAD = 0");
+        }
+    } else {
+        mtk_gps_ofl_set_option(0);
+        LOGD("MNL_OFL_OPTION_ENALBE_OFFLOAD = 0");
+    }
+    gps_dbg_log_thread_init();
+
+    if (PDN_test_enable == 1 || PDN_test_enable == 0) {
+        init_cfg.Int_IMAX_Config = PDN_test_enable;
+        LOGD("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;
+    }
+
+    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);
+    if (mnl_status != MNL_INIT_SUCCESS) {
+        status = MTK_GPS_ERROR;
+        return status;
+    }
+    mnl_mpe_thread_init();
+
+    if (access(EPO_UPDATE_HAL, F_OK) == -1) {
+        LOGD("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("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("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\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);
+    if (epo_setconfig == 1) {
+        userprofile.EPO_enabled = mnl_config.EPO_enabled;
+    } else {
+#if ANDROID_MNLD_PROP_SUPPORT
+        userprofile.EPO_enabled = get_prop(7);
+#else
+    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;
+    bool alt_valid = false;
+    float altitude = 0.0f;
+    bool source_valid = true;
+    bool source_gnss = true;
+    bool source_nlp = false;
+    bool source_sensor = false;
+    //  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("%d st send profile to agent OK \n", i);
+            break;
+        }
+    }
+
+    if (mtk_gps_get_position_accuracy(&latitude, &longitude, &accuracy) == MTK_GPS_SUCCESS) {
+        if (mtk_gps_log_is_hide() == 0) {
+            LOGD("mnl init, mtk_gps_get_position_accuracy success, %lf, %lf, %d", latitude, longitude, accuracy);
+        }
+        if (accuracy < 100) {
+            ret_val = mnl2agps_location_sync(latitude, longitude, accuracy, alt_valid, altitude, source_valid, source_gnss, source_nlp, source_sensor);
+            if (0 == ret_val) {
+                LOGD("mnl2agps_location_sync success");
+            }
+        }
+    }
+    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);
+    }
+    return  status;
+}
+#else
+static int linux_gps_init(void) {
+ // power on gps on another place.
+#if ANDROID_MNLD_PROP_SUPPORT
+    // strcpy(driver_cfg.mnl_chip_id, chip_id);
+    if (strcmp(chip_id, "0x3303") == 0 ) {
+        LOGD("TCXO\n");
+        if (property_set(GPS_CLOCK_TYPE_P, "90") != 0) {
+            LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+        }
+    }
+#endif
+
+#ifdef MTK_ADR_SUPPORT
+    mnl_config.fix_interval = 1000;  //1Hz update rate
+    LOGD("mnl_config.fix_interval = %d \n", mnl_config.fix_interval);
+#endif
+
+    gps_debuglog_state = gps_debuglog_state | mnl_config.dbg2file;
+    if(mnl_debug_file_check(mnl_config.debug_file_name) == MTK_GPS_SUCCESS)
+    {
+        strncpy(gps_debuglog_file_name, mnl_config.debug_file_name,GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+    } else {
+        LOGW("debug file(%s) invalide, use the default(%s)\r\n", mnl_config.debug_file_name, LOG_FILE);
+        strncpy(storagePath, LOG_FILE_PATH, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+        strncpy(gps_debuglog_file_name,LOG_FILE,GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+    }
+
+    extern MTK_GPS_BOOL enable_dbg_log;
+    enable_dbg_log = mnl_config.debug_nmea;
+
+    gps_dbg_log_thread_init();
+#if RAW_DATA_SUPPORT
+    gps_raw_data_enable();
+#endif
+
+    hasAlmanac();
+
+    return  0;
+}
+
+#endif
+
+/*****************************************************************************/
+static int mnld_gps_stop_impl(void) {
+    int ret = 0;
+    LOGD("MNL exiting \n");
+#ifndef CONFIG_GPS_MT3303	
+    mtk_gps_mnl_stop();
+    LOGD("mtk_gps_mnl_stop()\n");
+#endif
+
+    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);
+    }
+#ifndef CONFIG_GPS_MT3303    
+    if (dsp_fd > 0) {
+        if (mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+            gps_control_kernel_wakelock_uninit();
+        }
+        close(dsp_fd);
+        dsp_fd = -1;
+    }
+    mnld_gps_stop_nmea_monitor();  //Stop monitor timer again for GPS stop and nmea report timing issue
+    // cancel alarm
+    LOGD("Cancel alarm");
+    alarm(0);
+#endif
+    return ret;
+}
+
+/*****************************************************************************/
+//static time_t last_send_time = 0;
+//static time_t current_time = 0;
+
+int send_active_notify() {
+    int gps_user = mtk_gps_get_gps_user();
+    // if no other users except GPS_USER_FLP or GPS_USER_OFL_TEST, bypass restart
+    if (((gps_user & (GPS_USER_FLP | GPS_USER_OFL_TEST | GPS_USER_GEOFENCE)) == gps_user) && mnl_offload_is_enabled()
+        && (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+        LOGE("gps_user: %d,offload: %d\n", gps_user, mnld_cfg.OFFLOAD_enabled);
+        return -1;
+    }
+    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("msg:%d\n", msg);
+    switch (msg) {
+    case MTK_GPS_MSG_FIX_READY:
+        {
+            send_active_notify();
+#if 0
+            // For NI open GPS
+            double dfRtcD = 0.0, dfAge = 0.0;
+            send_active_notify();
+            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;
+                        time(&current_time);
+                        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 navigation 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
+            if (is_flp_user_exist() && !(mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+                UINT8 buff[1024] = {0};
+                UINT8 playload[OFFLOAD_PAYLOAD_LEN] = {0};
+                UINT32 p_get_len = 0;
+                //MTK_FLP_OFFLOAD_MSG_T *prMsg = (MTK_FLP_OFFLOAD_MSG_T *)&buff[0];
+                MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+                mtk_gps_flp_get_location(playload, OFFLOAD_PAYLOAD_LEN, &p_get_len);
+                //prMsg->type = FLPMNL_GPS_REPORT_LOC;
+                prMsg->type = MNLD_FLP_TYPE_HBD_GPS_LOCATION;
+                prMsg->length = p_get_len;
+                prMsg->session = mnld_flp_session.id;
+                memcpy(&prMsg->data[0], playload, p_get_len);
+                if (-1 == mnl2flp_data_send(buff, sizeof(buff))) {
+                    LOGE("[FLP2MNLD]Send to FLP failed, %s\n", strerror(errno));
+                } else {
+                    //LOGD("[FLP2MNLD]Send to FLP successfully\n");
+                }
+            }
+            if (is_geofence_user_exist() && !(mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+                UINT8 buff[1024] = {0};
+                UINT8 playload[OFFLOAD_PAYLOAD_LEN] = {0};
+                UINT32 p_get_len = 0;
+                //MTK_FLP_OFFLOAD_MSG_T *prMsg = (MTK_FLP_OFFLOAD_MSG_T *)&buff[0];
+                MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];
+                mtk_gps_flp_get_location(playload, OFFLOAD_PAYLOAD_LEN, &p_get_len);
+                //prMsg->type = FLPMNL_GPS_REPORT_LOC;
+                prMsg->type = MNLD_FLP_TYPE_HBD_GPS_LOCATION;
+                prMsg->length = p_get_len;
+                prMsg->session = mnld_gfc_session.id;
+                memcpy(&prMsg->data[0], playload, p_get_len);
+                if (-1 == mnl2gfc_data_send(buff, sizeof(buff))) {
+                    LOGE("[GFC2MNLD]Send to GFC failed, %s\n", strerror(errno));
+                } else {
+                    //LOGD("[GFC2MNLD]Send to GFC successfully\n");
+                }
+            }
+
+        }
+        break;
+    case MTK_GPS_MSG_FIX_PROHIBITED:
+        {
+            send_active_notify();
+            LOGD("MTK_GPS_MSG_FIX_PROHIBITED\n");
+        }
+        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;
+
+MTK_AGPS_DISPATCH_STATE state_mode = ST_IDLE;
+MTK_AGPS_DISPATCH_STATE last_state_mode = ST_UNKNOWN;
+int AGENT_SET_ALARM = 0;
+static void alarm_handler() {
+    if (AGENT_SET_ALARM == 1) {
+        if ((mtk_gps_get_gps_user()& GPS_USER_AGPS) != 0) {
+            // SI alarm handler: ignore, as current user is AGPS, it may in NI session
+            // NI alarm handler: ignore, as AGPSD send close_gps_req(timer be canceled)
+            return;
+        }
+        if (mnld_is_gps_and_ofl_stopped()) {
+            LOGD("GPS driver is stopped");
+            AGENT_SET_ALARM = 0;
+            last_state_mode = state_mode;
+            state_mode = ST_IDLE;
+            return;
+        }
+        // SI only session and GPS driver is running
+        LOGD("Send MTK_AGPS_SUPL_END to MNL");
+        mtk_agps_set_param(MTK_MSG_AGPS_MSG_SUPL_TERMINATE, NULL, MTK_MOD_DISPATCHER, MTK_MOD_AGENT);
+        last_state_mode = state_mode;
+        state_mode = ST_IDLE;
+        LOGD("Receive MTK_AGPS_SUPL_END , last_state_mode = %d, state_mode = %d", last_state_mode, state_mode);
+    }
+    AGENT_SET_ALARM = 0;
+}
+
+void gps_controller_agps_session_done() {
+    LOGD("agps_session_done");
+    if (mnld_is_gps_and_ofl_stopped()) {
+        LOGD("GPS driver is stopped");
+        AGENT_SET_ALARM = 0;
+        last_state_mode = state_mode;
+        state_mode = ST_IDLE;
+        return;
+    }
+    if (0 == AGENT_SET_ALARM) {
+        LOGD("Set up signal & alarm!");
+        signal(SIGALRM, alarm_handler);
+        alarm(30);
+        AGENT_SET_ALARM = 1;
+    } else {
+        LOGD("AGENT_SET_ALARM == 1");
+    }
+}
+
+void gps_controller_rcv_pmtk(const char* pmtk) {
+    // LOGD("rcv_pmtk: %s", pmtk);
+    if (mnld_is_gps_and_ofl_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)
+                  mnl2agps_pmtk(data);
+                return 0;
+            } else if (type == MTK_AGPS_CB_ASSIST_REQ) {
+                if (state_mode == ST_IDLE || state_mode == ST_SI) {
+                    LOGD("GPS re-aiding\n");
+                    mnl2agps_reaiding_req();
+                    return 0;
+                } else {
+                    LOGE("Dispatcher in %d mode, ignore current request\n", state_mode);
+                    return MTK_GPS_ERROR;
+                }
+            }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 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;
+                }
+                // mnl2agps_gps_open(assist_req);
+                if (gps_restart == 1) {
+                    release_condition(&lock_for_sync[M_RESTART]);
+                    LOGD("release condition for restart");
+                }
+                mnld_gps_start_done(assist_req);
+                return ret;
+            }
+
+        } else {
+            LOGD("mtk_sys_agps_disaptcher_callback: SUPL disable");
+            ret = MTK_GPS_ERROR;
+        }
+    }  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");
+            mnl2hal_request_utc_time();
+        }
+        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) {
+                qepo_downloader_start();
+            }
+
+            if ((dl_bitmap & AGT_QEPO_BD_BIT) == AGT_QEPO_BD_BIT) {
+                qepo_bd_downloader_start();
+            }
+
+            if ((dl_bitmap & AGT_QEPO_GA_BIT) == AGT_QEPO_GA_BIT) {
+                qepo_ga_downloader_start();
+            }
+
+        }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");
+        }
+    }
+    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) {
+        LOGD("'=' is not found!!\n");
+        return -1;    // 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, *val;
+    if (!fp) {
+        LOGD("open %s fail!\n", RAW_DATA_CONTROL_FILE_PATH);
+        return 1;
+    }
+
+    while (fgets(result, sizeof(result), fp)) {
+        if (get_val(result, &key, &val)) {
+            LOGD("Get data fails!!\n");
+            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_gps_measurement(gps_measurement in) {
+    LOGD("===== print_gps_measurement ====");
+    LOGD("flags=0x%x", in.flags);
+    LOGD("prn=%d", in.prn);
+    LOGD("time_offset_ns=%f", in.time_offset_ns);
+    LOGD("state=0x%x", in.state);
+    LOGD("received_gps_tow_ns=%"PRId64, in.received_gps_tow_ns);
+    LOGD("received_gps_tow_uncertainty_ns=%"PRId64, in.received_gps_tow_uncertainty_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("pseudorange_m=%f", in.pseudorange_m);
+    LOGD("pseudorange_uncertainty_m=%f", in.pseudorange_uncertainty_m);
+    LOGD("code_phase_chips=%f", in.code_phase_chips);
+    LOGD("code_phase_uncertainty_chips=%f", in.code_phase_uncertainty_chips);
+    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("loss_of_lock=%d", in.loss_of_lock);
+    LOGD("bit_number=%d", in.bit_number);
+    LOGD("time_from_last_bit_ms=%d", in.time_from_last_bit_ms);
+    LOGD("doppler_shift_hz=%f", in.doppler_shift_hz);
+    LOGD("doppler_shift_uncertainty_hz=%f", in.doppler_shift_uncertainty_hz);
+    LOGD("multipath_indicator=%d", in.multipath_indicator);
+    LOGD("snr_db=%f", in.snr_db);
+    LOGD("elevation_deg=%f", in.elevation_deg);
+    LOGD("elevation_uncertainty_deg=%f", in.elevation_uncertainty_deg);
+    LOGD("azimuth_deg=%f", in.azimuth_deg);
+    LOGD("azimuth_uncertainty_deg=%f", in.azimuth_uncertainty_deg);
+    LOGD("used_in_fix=%d", in.used_in_fix);
+}
+
+void print_gps_clock(gps_clock in) {
+    LOGD("===== print_gps_clock ====");
+    LOGD("flags=0x%x", in.flags);
+    LOGD("leap_second=%d", in.leap_second);
+    LOGD("type=%d", in.type);
+    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);
+}
+
+void print_gps_nav_msg(gps_nav_msg in) {
+    LOGD("===== print_gps_nav_msg ====");
+    LOGD("prn=%d", in.prn);
+    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);
+}
+
+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("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);
+}
+
+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=%d", in.data_length);
+}
+
+#if 0
+static void get_gps_measurement_clock_data() {
+    LOGD("get_gps_measurement_clock_data begin");
+
+    int i;
+    int num = 0;
+    int ret;
+    gps_data gpsdata;
+    MTK_GPS_MEASUREMENT mtk_gps_measurement[GPS_MAX_MEASUREMENT];
+    INT8 ch_proc_ord_prn[GPS_MAX_MEASUREMENT]={0};
+    mtk_gps_get_measurement(mtk_gps_measurement, ch_proc_ord_prn);
+    LOGD("sizeof(mtk_gps_get_measurement) = %d,sizeof(mtk_gps_get_measurement[0]) = %d\n",
+        sizeof(mtk_gps_measurement), sizeof(mtk_gps_measurement[0]));
+
+    MTK_GPS_CLOCK mtk_gps_clock;
+    ret = mtk_gps_get_clock(&mtk_gps_clock);
+    if (ret == 0) {
+        LOGD("mtk_gps_get_clock fail,[ret=%d]\n", ret);
+    }
+
+    gps_clock gpsclock;
+    memset(&gpsclock, 0, sizeof(gps_clock));
+    // gpsclock.size = sizeof(gps_clock);
+    gpsclock.bias_ns = mtk_gps_clock.BiasInNs;
+    gpsclock.bias_uncertainty_ns = mtk_gps_clock.BiasUncertaintyInNs;
+    gpsclock.drift_nsps = mtk_gps_clock.DriftInNsPerSec;
+    gpsclock.flags = mtk_gps_clock.flag;
+    gpsclock.leap_second = mtk_gps_clock.leapsecond;
+    gpsclock.time_ns = mtk_gps_clock.TimeInNs;
+    gpsclock.time_uncertainty_ns = mtk_gps_clock.TimeUncertaintyInNs;
+    gpsclock.type = mtk_gps_clock.type;
+    gpsclock.full_bias_ns = mtk_gps_clock.FullBiasInNs;
+    gpsclock.drift_uncertainty_nsps = mtk_gps_clock.DriftUncertaintyInNsPerSec;
+    if (gps_raw_debug_mode) {
+        print_gps_clock(gpsclock);
+    }
+
+    memset(&gpsdata, 0, sizeof(gps_data));
+    // gpsdata.size = sizeof(gps_data);
+    for (i = 0; i < GPS_MAX_MEASUREMENT; i++) {
+        if (mtk_gps_measurement[i].PRN != 0) {
+            num = gpsdata.measurement_count;
+
+            // gpsdata.measurements[num].size = sizeof(gps_measurement);
+            gpsdata.measurements[num].accumulated_delta_range_m = mtk_gps_measurement[i].AcDRInMeters;
+            gpsdata.measurements[num].accumulated_delta_range_state = mtk_gps_measurement[i].AcDRState10;
+            gpsdata.measurements[num].accumulated_delta_range_uncertainty_m = \
+            mtk_gps_measurement[i].AcDRUnInMeters;
+            gpsdata.measurements[num].azimuth_deg = mtk_gps_measurement[i].AzInDeg;
+            gpsdata.measurements[num].azimuth_uncertainty_deg = mtk_gps_measurement[i].AzUnInDeg;
+            gpsdata.measurements[num].bit_number = mtk_gps_measurement[i].BitNumber;
+            gpsdata.measurements[num].carrier_cycles = mtk_gps_measurement[i].CarrierCycle;
+            gpsdata.measurements[num].carrier_phase = mtk_gps_measurement[i].CarrierPhase;
+            gpsdata.measurements[num].carrier_phase_uncertainty = mtk_gps_measurement[i].CarrierPhaseUn;
+            gpsdata.measurements[num].carrier_frequency_hz = mtk_gps_measurement[i].CFInhZ;
+            gpsdata.measurements[num].c_n0_dbhz = mtk_gps_measurement[i].Cn0InDbHz;
+            gpsdata.measurements[num].code_phase_chips = mtk_gps_measurement[i].CPInChips;
+            gpsdata.measurements[num].code_phase_uncertainty_chips = mtk_gps_measurement[i].CPUnInChips;
+            gpsdata.measurements[num].doppler_shift_hz = mtk_gps_measurement[i].DopperShiftInHz;
+            gpsdata.measurements[num].doppler_shift_uncertainty_hz = mtk_gps_measurement[i].DopperShiftUnInHz;
+            gpsdata.measurements[num].elevation_deg = mtk_gps_measurement[i].ElInDeg;
+            gpsdata.measurements[num].elevation_uncertainty_deg = mtk_gps_measurement[i].ElUnInDeg;
+            gpsdata.measurements[num].flags = mtk_gps_measurement[i].flag;
+            gpsdata.measurements[num].loss_of_lock = mtk_gps_measurement[i].LossOfLock;
+            gpsdata.measurements[num].multipath_indicator = mtk_gps_measurement[i].MultipathIndicater;
+            gpsdata.measurements[num].pseudorange_m = mtk_gps_measurement[i].PRInMeters;
+            gpsdata.measurements[num].prn = mtk_gps_measurement[i].PRN;
+            gpsdata.measurements[num].pseudorange_rate_mps = mtk_gps_measurement[i].PRRateInMeterPreSec;
+            gpsdata.measurements[num].pseudorange_rate_uncertainty_mps = \
+            mtk_gps_measurement[i].PRRateUnInMeterPreSec;
+            gpsdata.measurements[num].pseudorange_uncertainty_m = mtk_gps_measurement[i].PRUnInMeters;
+            gpsdata.measurements[num].received_gps_tow_ns = mtk_gps_measurement[i].ReGpsTowInNs;
+            gpsdata.measurements[num].received_gps_tow_uncertainty_ns = mtk_gps_measurement[i].ReGpsTowUnInNs;
+            gpsdata.measurements[num].snr_db = mtk_gps_measurement[i].SnrInDb;
+            gpsdata.measurements[num].state = mtk_gps_measurement[i].state;
+            gpsdata.measurements[num].time_from_last_bit_ms = mtk_gps_measurement[i].TimeFromLastBitInMs;
+            gpsdata.measurements[num].time_offset_ns = mtk_gps_measurement[i].TimeOffsetInNs;
+            gpsdata.measurements[num].used_in_fix = mtk_gps_measurement[i].UsedInFix;
+            if (gpsdata.measurements[num].state == 0) {
+                gpsdata.measurements[num].received_gps_tow_ns = 0;
+                gpsdata.measurements[num].pseudorange_rate_mps = 1;
+            }
+            LOGD("gpsdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gpsdata.measurements[num].prn);
+            if (gps_raw_debug_mode) {
+                print_gps_measurement(gpsdata.measurements[num]);
+            }
+            gpsdata.measurement_count++;
+        }
+    }
+    memcpy(&gpsdata.clock , &gpsclock, sizeof(gpsclock));
+    if (gpsdata.measurement_count > 0) {
+        ret = mnl2hal_gps_measurements(gpsdata);
+        LOGD("mnl2hal_gps_measurements done ,ret = %d", ret);
+    }
+}
+static void get_gps_navigation_event() {
+    LOGD("get_gps_navigation_event begin");
+
+    int svid;
+    int i;
+    int ret;
+    MTK_GPS_NAVIGATION_EVENT gps_navigation_event;
+    gps_nav_msg gpsnavigation;
+
+    for (svid = 0; svid < GPS_MAX_MEASUREMENT; svid++) {
+        ret = mtk_gps_get_navigation_event(&gps_navigation_event, svid);
+        if (ret == 0) {
+            LOGD("mtk_gps_get_navigation_event fail,SVID = %d,[ret=%d]\n", svid, ret);
+            memset(&gps_navigation_event, 0, sizeof(MTK_GPS_NAVIGATION_EVENT));
+        }
+
+        memset(&gpsnavigation, 0, sizeof(gps_nav_msg));
+        // gpsnavigation.size = sizeof(gps_nav_msg);
+        gpsnavigation.prn = gps_navigation_event.prn;
+        gpsnavigation.type = gps_navigation_event.type;
+        gpsnavigation.message_id = gps_navigation_event.messageID;
+        gpsnavigation.submessage_id = gps_navigation_event.submessageID;
+        gpsnavigation.data_length = sizeof(gps_navigation_event.data);
+        memcpy(gpsnavigation.data, gps_navigation_event.data, sizeof(gps_navigation_event.data));
+
+        if (gps_raw_debug_mode) {
+            print_gps_nav_msg(gpsnavigation);
+            for (i = 0; i < 40; i++) {
+                LOGD("gpsnavigation.data[%d] = %x, %p",
+                    i, gpsnavigation.data[i], &gpsnavigation.data[i]);
+            }
+        }
+        ret = mnl2hal_gps_navigation(gpsnavigation);
+        LOGD("mnl2hal_gps_navigation done ,ret = %d", ret);
+    }
+}
+#endif
+
+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);
+
+    ///TODO FIX IT
+    //    fieldp_copy(dst, src, agc_level_db);
+    dst->agc_level_db = g_agc_level;
+//    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);
+    dst->flags = (dst->flags | (1<<0)| (1<<9) |(1<<13));
+
+    //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);
+
+    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));
+    }
+}
+#ifndef CONFIG_GPS_MT3303
+static void get_gnss_measurement_clock_data() {
+    LOGD("get_gnss_measurement_clock_data begin");
+
+    int i;
+    int num = 0;
+    int ret;
+    gnss_data gnssdata;
+    Gnssmeasurement gpqzmeasurement[40];
+    Gnssmeasurement glomeasurement[24];
+    Gnssmeasurement bdmeasurement[37];
+    Gnssmeasurement galmeasurement[36];
+    Gnssmeasurement sbasmeasurement[42];
+
+    INT8 GpQz_Ch_Proc_Ord_PRN[40] = {0};
+    INT8 Glo_Ch_Proc_Ord_PRN[24] = {0};
+    INT8 BD_Ch_Proc_Ord_PRN[37] = {0};
+    INT8 Gal_Ch_Proc_Ord_PRN[36] = {0};
+    INT8 SBAS_Ch_Proc_Ord_PRN[42] = {0};
+
+    mtk_gnss_get_measurement(gpqzmeasurement, glomeasurement, bdmeasurement, galmeasurement, sbasmeasurement,
+        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);
+
+    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 < 40; 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("GP gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For Glonass
+    for (i = 0; i < 24; 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("GL gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For Beidou
+    for (i = 0; i < 37; 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("BD gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For Galileo
+    for (i = 0; i < 36; 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("GA gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For SBAS
+    for (i = 0; i < 42; 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 gnssdata 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 = %d, sizeof(gnssdata) = %d", 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);
+        memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GP_data, gnssnavigation.data_length);
+        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);
+        memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GL_data, gnssnavigation.data_length);
+        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);
+        memcpy(gnssnavigation.data, gnss_navigation_msg.uData.BD_data, gnssnavigation.data_length);
+        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);
+        memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GA_data, gnssnavigation.data_length);
+        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);
+    }
+}
+#else
+gnss_sv_info cts_sv_data;
+
+ void get_gnss_measurement_clock_data() {
+    LOGD("get_gnss_measurement_clock_data begin");
+
+    int i;
+    int num = 0;
+    int ret;
+    gnss_data gnssdata;
+    Gnssmeasurement gpqzmeasurement[40];
+    Gnssmeasurement glomeasurement[24];
+    Gnssmeasurement bdmeasurement[37];
+    Gnssmeasurement galmeasurement[36];
+    Gnssmeasurement sbasmeasurement[42];
+
+#if 0
+    INT8 GpQz_Ch_Proc_Ord_PRN[40] = {0};
+    INT8 Glo_Ch_Proc_Ord_PRN[24] = {0};
+    INT8 BD_Ch_Proc_Ord_PRN[37] = {0};
+    INT8 Gal_Ch_Proc_Ord_PRN[36] = {0};
+    INT8 SBAS_Ch_Proc_Ord_PRN[42] = {0};
+#endif
+    
+    
+
+    for (i = 0; i < 40; i++) {
+        gpqzmeasurement[i].accumulated_delta_range_m=0;
+        gpqzmeasurement[i].accumulated_delta_range_state=0x0;
+        gpqzmeasurement[i].accumulated_delta_range_uncertainty_m=0;
+        gpqzmeasurement[i].carrier_cycles=0;
+        gpqzmeasurement[i].carrier_frequency_hz=1575420032.000000;
+        gpqzmeasurement[i].carrier_phase=0;
+        gpqzmeasurement[i].carrier_phase_uncertainty=0;
+
+        gpqzmeasurement[i].svid=0;
+        gpqzmeasurement[i].snr_db=0;
+        gpqzmeasurement[i].constellation=0;
+        gpqzmeasurement[i].c_n0_dbhz=0 ;
+        for(int cnt=cts_sv_data.num_svs; cnt>0; cnt--){
+            if(cts_sv_data.sv_list[cnt-1].svid == (i+1)){
+                if(cts_sv_data.sv_list[cnt-1].c_n0_dbhz - 17 < 0){
+                    gpqzmeasurement[i].snr_db=0;
+                }else{
+                    gpqzmeasurement[i].snr_db=cts_sv_data.sv_list[cnt-1].c_n0_dbhz - 17;
+                }
+                
+                gpqzmeasurement[i].constellation=cts_sv_data.sv_list[cnt-1].constellation;
+                gpqzmeasurement[i].c_n0_dbhz=cts_sv_data.sv_list[cnt-1].c_n0_dbhz ;
+                if(gpqzmeasurement[i].c_n0_dbhz <= 5.0){
+                    gpqzmeasurement[i].svid=0;
+                }else{
+                    gpqzmeasurement[i].svid=cts_sv_data.sv_list[cnt-1].svid;
+                }
+                break;
+            }
+            
+        }
+        
+        gpqzmeasurement[i].flags=0x40201;
+        gpqzmeasurement[i].multipath_indicator=0;
+        gpqzmeasurement[i].pseudorange_rate_mps=14522.145508;
+        gpqzmeasurement[i].pseudorange_rate_uncertainty_mps=0.150000;
+        gpqzmeasurement[i].received_sv_time_in_ns=20000;
+        gpqzmeasurement[i].received_sv_time_uncertainty_in_ns=33353074;
+        gpqzmeasurement[i].size=sizeof(gpqzmeasurement[i]);
+        gpqzmeasurement[i].state=0x02;
+        gpqzmeasurement[i].time_offset_ns=421235.186561;
+    }
+
+    for (i = 0; i < 24; i++) {
+        glomeasurement[i].accumulated_delta_range_m=0;
+        glomeasurement[i].accumulated_delta_range_state=0x0;
+        glomeasurement[i].accumulated_delta_range_uncertainty_m=0;
+        glomeasurement[i].carrier_cycles=0;
+        glomeasurement[i].carrier_frequency_hz=1575420032.000000;
+        glomeasurement[i].carrier_phase=0;
+        glomeasurement[i].carrier_phase_uncertainty=0;
+
+        glomeasurement[i].svid=0;
+        glomeasurement[i].snr_db=0;
+        glomeasurement[i].constellation=0;
+        glomeasurement[i].c_n0_dbhz=0 ;
+        for(int cnt=cts_sv_data.num_svs; cnt>0; cnt--){
+            if(cts_sv_data.sv_list[cnt-1].svid == (i+65)){
+                if(cts_sv_data.sv_list[cnt-1].c_n0_dbhz - 17 < 0){
+                    glomeasurement[i].snr_db=0;
+                }else{
+                    glomeasurement[i].snr_db=cts_sv_data.sv_list[cnt-1].c_n0_dbhz - 17;
+                }
+                
+                glomeasurement[i].constellation=cts_sv_data.sv_list[cnt-1].constellation;
+                glomeasurement[i].c_n0_dbhz=cts_sv_data.sv_list[cnt-1].c_n0_dbhz ;
+                if(glomeasurement[i].c_n0_dbhz <= 5.0){
+                    glomeasurement[i].svid=0;
+                }else{
+                    glomeasurement[i].svid=cts_sv_data.sv_list[cnt-1].svid - 65 + 1;
+                }
+                break;
+            }
+            
+        }
+        
+        glomeasurement[i].flags=0x40201;
+        glomeasurement[i].multipath_indicator=0;
+        glomeasurement[i].pseudorange_rate_mps=14522.145508;
+        glomeasurement[i].pseudorange_rate_uncertainty_mps=0.150000;
+        glomeasurement[i].received_sv_time_in_ns=20000;
+        glomeasurement[i].received_sv_time_uncertainty_in_ns=33353074;
+        glomeasurement[i].size=sizeof(glomeasurement[i]);
+        glomeasurement[i].state=0x02;
+        glomeasurement[i].time_offset_ns=421235.186561;
+    }
+    for (i = 0; i < 37; i++) {
+        bdmeasurement[i].accumulated_delta_range_m=0;
+        bdmeasurement[i].accumulated_delta_range_state=0x0;
+        bdmeasurement[i].accumulated_delta_range_uncertainty_m=0;
+        bdmeasurement[i].carrier_cycles=0;
+        bdmeasurement[i].carrier_frequency_hz=1575420032.000000;
+        bdmeasurement[i].carrier_phase=0;
+        bdmeasurement[i].carrier_phase_uncertainty=0;
+
+        bdmeasurement[i].svid=0;
+        bdmeasurement[i].snr_db=0;
+        bdmeasurement[i].constellation=0;
+        bdmeasurement[i].c_n0_dbhz=0 ;
+        for(int cnt=cts_sv_data.num_svs; cnt>0; cnt--){
+            if(cts_sv_data.sv_list[cnt-1].svid == (i+201)){
+                if(cts_sv_data.sv_list[cnt-1].c_n0_dbhz - 17 < 0){
+                    bdmeasurement[i].snr_db=0;
+                }else{
+                    bdmeasurement[i].snr_db=cts_sv_data.sv_list[cnt-1].c_n0_dbhz - 17;
+                }
+                
+                bdmeasurement[i].constellation=cts_sv_data.sv_list[cnt-1].constellation;
+                bdmeasurement[i].c_n0_dbhz=cts_sv_data.sv_list[cnt-1].c_n0_dbhz ;
+                if(bdmeasurement[i].c_n0_dbhz <= 5.0){
+                    bdmeasurement[i].svid=0;
+                }else{
+                    bdmeasurement[i].svid=cts_sv_data.sv_list[cnt-1].svid - 201 + 1;
+                }
+                break;
+            }
+            
+        }
+        
+        bdmeasurement[i].flags=0x40201;
+        bdmeasurement[i].multipath_indicator=0;
+        bdmeasurement[i].pseudorange_rate_mps=14522.145508;
+        bdmeasurement[i].pseudorange_rate_uncertainty_mps=0.150000;
+        bdmeasurement[i].received_sv_time_in_ns=20000;
+        bdmeasurement[i].received_sv_time_uncertainty_in_ns=33353074;
+        bdmeasurement[i].size=sizeof(bdmeasurement[i]);
+        bdmeasurement[i].state=0x02;
+        bdmeasurement[i].time_offset_ns=421235.186561;
+    }
+    for (i = 0; i < 36; i++) {
+        memset(galmeasurement,0,sizeof(galmeasurement));
+    }
+    for (i = 0; i < 42; i++) {
+        memset(sbasmeasurement,0,sizeof(sbasmeasurement));
+    }
+
+    Gnssclock gnssclock;
+    memset(&gnssclock,0,sizeof(gnssclock));
+    gnssclock.bias_ns=0.186561;
+    gnssclock.bias_uncertainty_ns=609.745098;
+    gnssclock.drift_nsps=7183.074831;
+    gnssclock.drift_uncertainty_nsps=16.441889;
+    gnssclock.flags=0x01;
+    gnssclock.full_bias_ns=421235;
+    gnssclock.hw_clock_discontinuity_count=0;
+    gnssclock.leap_second=18;
+    gnssclock.size=sizeof(gnssclock);
+    gnssclock.time_ns=1185356046700000000;
+    gnssclock.time_uncertainty_ns=33353073.878863;
+    
+    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 < 40; i++) {
+        if (gpqzmeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= 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("gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For Glonass
+    for (i = 0; i < 24; i++) {
+        if (glomeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= 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("gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For Beidou
+    for (i = 0; i < 37; i++) {
+        if (bdmeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= 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("gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For Galileo
+    for (i = 0; i < 36; i++) {
+        if (galmeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= 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("gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For SBAS
+    for (i = 0; i < 42; i++) {
+        if (sbasmeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= 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("gnssdata 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 = %d, sizeof(gnssdata) = %d", gnssdata.measurement_count, sizeof(gnssdata));
+    if (gnssdata.measurement_count > 0) {
+        ret = mnl2hal_gnss_measurements(gnssdata);
+        LOGD("mnl2hal_gnss_measurements done ,ret = %d", ret);
+    }
+
+    memset(&cts_sv_data,0,sizeof(cts_sv_data));
+}
+
+#ifdef __ANDROID_OS_10__ 
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L1CA GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA
+#endif
+  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 = 0;
+         gnss_navigation_msg.data_length=40;
+         gnss_navigation_msg.message_id=1;
+         gnss_navigation_msg.submessage_id=1;
+         gnss_navigation_msg.size=sizeof(gnss_navigation_msg);
+         gnss_navigation_msg.status=0x0;
+         gnss_navigation_msg.svid=svid;
+         gnss_navigation_msg.type=GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA;
+         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);
+         memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GP_data, gnssnavigation.data_length);
+         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 = 0;
+         gnss_navigation_msg.data_length=12;
+         gnss_navigation_msg.message_id=1;
+         gnss_navigation_msg.submessage_id=1;
+         gnss_navigation_msg.size=sizeof(gnss_navigation_msg);
+         gnss_navigation_msg.status=0x0;
+         gnss_navigation_msg.svid=svid;
+         gnss_navigation_msg.type=GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA;
+         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);
+         memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GL_data, gnssnavigation.data_length);
+         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 = 0;
+         gnss_navigation_msg.data_length=40;
+         gnss_navigation_msg.message_id=1;
+         gnss_navigation_msg.submessage_id=1;
+         gnss_navigation_msg.size=sizeof(gnss_navigation_msg);
+         gnss_navigation_msg.status=0x0;
+         gnss_navigation_msg.svid=svid;
+         gnss_navigation_msg.type=GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1;
+         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);
+         memcpy(gnssnavigation.data, gnss_navigation_msg.uData.BD_data, gnssnavigation.data_length);
+         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 = 0;
+         gnss_navigation_msg.data_length=40;
+         gnss_navigation_msg.message_id=1;
+         gnss_navigation_msg.submessage_id=1;
+         gnss_navigation_msg.size=sizeof(gnss_navigation_msg);
+         gnss_navigation_msg.status=0x0;
+         gnss_navigation_msg.svid=svid;
+         gnss_navigation_msg.type=GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I;
+         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);
+         memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GA_data, gnssnavigation.data_length);
+         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
+#endif
+
+#if ANDROID_MNLD_PROP_SUPPORT
+/*---------------------------------------------------------------------------*/
+#define  MNL_CONFIG_STATUS      "persist.vendor.radio.mnl.prop"
+static int get_prop(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("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));
+        LOGI("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;
+    }
+    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
+        int gps_user = mtk_gps_get_gps_user();
+        if (((gps_user & (GPS_USER_FLP | GPS_USER_OFL_TEST | GPS_USER_GEOFENCE)) == gps_user) &&
+            mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+            break;
+        }
+
+        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_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];
+    memset(&events, 0, sizeof(events));
+    UNUSED(arg);
+
+    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;
+        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;
+            }
+        }
+        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);
+    }
+
+    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;
+
+    #ifdef MTK_ADR_SUPPORT
+    mnl2adr_gps_open();
+    #endif
+    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;
+
+    #ifdef MTK_ADR_SUPPORT
+    mnl2adr_gps_close();
+    #endif
+    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);
+}
+
+int gps_control_init() {
+    pthread_t pthread_gps;
+
+    hasAlmanac();
+    g_fd_gps = socket_bind_udp(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) {
+        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_debuglog_state = MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD;
+            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);
+            }
+#ifdef CONFIG_GPS_MT3303
+            else{
+                mnld_gps_stop();
+            }
+#endif
+            exit_meta_factory = 1;
+        }
+    }
+    LOGD("Signal handler of %.8x -> %s\n", (unsigned int)self, sys_siglist[signo]);
+}
+
+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);
+    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 {
+            LOGD("MNL is offload, for meta/factory mode");
+            // factory_mnld_gps_start();
+#ifdef CONFIG_GPS_MT3303
+            mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_FACTORYMETA);
+#endif
+            mnld_gps_start(FLAG_HOT_START);
+        }
+    } else {
+        LOGD("MNL is offload, for meta/factory mode");
+        // factory_mnld_gps_start();
+#ifdef CONFIG_GPS_MT3303
+        mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_FACTORYMETA);
+#endif
+
+        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;
+}
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/gps_dbg_log.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/gps_dbg_log.c
new file mode 100644
index 0000000..d2a8dd5
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/gps_dbg_log.c
@@ -0,0 +1,1180 @@
+/* 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 <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 <sys/types.h>
+#include <fcntl.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 "mtk_auto_log.h"
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#include <cutils/properties.h>
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "gps_dbg_log"
+#endif
+
+/*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;
+  */
+#if defined(__ANDROID_OS__)
+#define GPSLOG_FCLOSE(fd,fn) do {\
+    if (NULL != fd) {\
+        fclose(fd);\
+        fd = NULL;\
+        gps_log_file_rename(fn);\
+        property_set(GPS_LOG_PERSIST_FLNM, GPS_LOG_PERSIST_VALUE_NONE);\
+    }\
+} while (0)
+#elif defined(__LINUX_OS__)
+#define FILE_FCLOSE(fd) do {\
+    if (NULL != fd) {\
+        fclose(fd);\
+        fd = NULL;}\
+    } while (0)
+
+#endif
+
+#define GPSLog_TIMESTRING_LEN 25
+#define C_INVALID_TID  (-1)   /*invalid thread id*/
+
+unsigned char gps_debuglog_state = MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD;
+char gps_debuglog_file_name[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = "/mnt/sdcard/mtklog/gpsdbglog/gpsdebug.log";
+char storagePath_mtklogger_set[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = "/mnt/sdcard/mtklog/gpsdbglog/";
+char storagePath[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = "/mnt/sdcard/mtklog/gpsdbglog/";
+static char log_filename_suffix[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = "gpsdebug.log";
+static char gsGpsLogFileName[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+static char gsGpsLogFileName_full[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+static int total_file_count = 0;
+static size_t Current_FileSize = 0;
+static int Filenum = 0;
+static size_t 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 PINGPANG_BUFFER_SIZE         (20*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;
+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 size_t 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 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 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
+            mnld_block_exit();
+        }
+    }
+}
+
+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};
+    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') {
+            snprintf(filename2, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s"LOG_FILE_EXTEN_NAME, filename1);
+        } else if(tmp_suffix <= 'z') {
+            snprintf(filename2, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s_%c"LOG_FILE_EXTEN_NAME, filename1, tmp_suffix);
+        } else {
+            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));
+    }
+}
+
+/*************Check the debug file valid or not***************/
+int mnl_debug_file_check(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;
+    }
+
+    MNLD_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);
+    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 (mnl_init_gps_data_path(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;
+        }
+    }
+    MNLD_STRNCPY(storagePath, dirname, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+    return MTK_GPS_SUCCESS;
+}
+
+static int get_mtklog_path(char *logpath) {
+    char mtklogpath[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+    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, MTK_GPS_DATA_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)) {
+        sprintf(logpath, "%smtklog/gpsdbglog/", temp);
+        LOGD("get_mtklog_path:logpath is %s", logpath);
+    }
+
+    if (len <= GPS_DEBUG_LOG_FILE_NAME_MAX_LEN-7) {
+        snprintf(mtklogpath, sizeof(mtklogpath), "%smtklog/", 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, MTK_GPS_DATA_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;
+int mtklogger2mnl_hdlr(int fd) {
+    int ret = 0;
+    int read_len;
+    char ans[255] = {0};
+    char buff_msg[253] = {0};
+
+    read_len = safe_recvfrom(fd, buff_msg, sizeof(buff_msg) - 1);
+    if (read_len <= 0) {
+        LOGE("mtklogger2mnl_hdlr() safe_recvfrom() failed read_len=%d, reason=[%s]%d",
+            read_len, strerror(errno), errno);
+        return -1;
+    }
+
+    // response "msg,1" to mtklogger
+    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"
+        MNLD_STRNCPY(storagePath_mtklogger_set, buff_msg, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+        get_mtklog_path(storagePath_mtklogger_set);
+        write(fd, ans, strlen(ans));
+    } else if (!strncmp(buff_msg, "deep_start,1", 12)) {
+        time_t tm;
+        struct tm *p;
+        static char GPSLog_timestamp[GPSLog_TIMESTRING_LEN];
+
+        time(&tm);
+        p = localtime(&tm);
+
+        // GPS debug log dir is not exit, mkdir, before add time string, return value 0:success, -1 : fail
+        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, strerror(errno));
+             }
+        }
+
+        memset(GPSLog_timestamp, 0x00, sizeof(GPSLog_timestamp));
+        snprintf(GPSLog_timestamp, sizeof(GPSLog_timestamp), "GPSLog_%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);
+
+        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_debuglog_state = MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD;
+        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
+        write(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_debuglog_state = MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD;
+        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
+        write(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_debuglog_state = MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD;
+        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
+        write(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]);
+        }
+        mnl2mpe_set_log_path(storagePath, 0, 0);
+        mode = 0;
+    } else {
+        write(fd, ans, strlen(ans));
+        LOGE("unknown message: %s\n", buff_msg);
+    }
+    return 0;
+}
+
+void mtklogger_mped_reboot_message_update(void) {
+    if (gps_debuglog_state == MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD) {
+        mnl2mpe_set_log_path(storagePath, 0, mode);
+    } else if (gps_debuglog_state == MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD) {
+        mnl2mpe_set_log_path(storagePath, 1, mode);
+    }
+}
+void* gps_dbg_log_thread(void* arg) {
+    size_t count = 0;
+    LOGD("create: %.8X, arg = %p\r\n", (unsigned int)pthread_self(), arg);
+    pthread_detach(pthread_self());
+
+    init_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+    init_condition(&lock_for_sync[PINGPANG_FLUSH_LOCK]);
+    #if defined(__ANDROID_OS__)
+    GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);
+    #elif defined(__LINUX_OS__)
+    FILE_FCLOSE(g_hLogFile);
+    #endif
+    if (gps_debuglog_state == MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD) {
+        LOGD("gps_debuglog_state: MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD");
+        create_debug_log_file();
+        mnl2mpe_set_log_path(storagePath, 1, 0); //Notify MPE to enable log and pass the log path to MPE, the 3rd param is unused
+    }
+
+    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_debuglog_state == MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD && !g_gpsdbglogThreadExit) {
+            if (fg_create_dir_done == 0){
+                mtklog_gps_set_debug_file(gps_debuglog_file_name);
+                mnl2mpe_set_log_path(storagePath, 1, 0); //Notify MPE to enable log and pass the log path to MPE, the 3rd param is unused
+            }
+
+            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));
+                #if defined(__ANDROID_OS__)
+                GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);// close file before open,  if the file has been open.
+                #elif defined(__LINUX_OS__)
+                FILE_FCLOSE(g_hLogFile);
+                #endif
+
+                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++;
+                    #if defined(__ANDROID_OS__)
+                    GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);// close file before open,  if the file has been open.
+                    #elif defined(__LINUX_OS__)
+                    FILE_FCLOSE(g_hLogFile);
+                    #endif
+                    DirLogSize = DirLogSize + Current_FileSize;
+                    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
+                    property_set(GPS_LOG_PERSIST_FLNM, strstr(gsGpsLogFileName_full, log_filename_suffix));
+                    #endif
+                    g_hLogFile = fopen(gsGpsLogFileName_full, "w");
+                    if (NULL == g_hLogFile) {
+                        LOGE("open file fail, NULL == g_hLogFile\r\n");
+                        break;
+                    }
+                    if (DirLogSize  > (size_t)(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 ((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 (g_hLogFile != NULL) {
+                    gps_dbg_log_pingpang_flush(&ping_pang_buffer_body, g_hLogFile);
+                }
+                gps_dbg_log_pingpang_free();
+                #if defined(__ANDROID_OS__)
+                GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);// close file before open,  if the file has been open.
+                #elif defined(__LINUX_OS__)
+                FILE_FCLOSE(g_hLogFile);
+                #endif
+            }
+        }
+    }
+
+    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");
+            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 defined(__ANDROID_OS__)
+        GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);
+        #elif defined(__LINUX_OS__)
+        FILE_FCLOSE(g_hLogFile);
+        #endif
+
+        LOGD("close log file\r\n");
+    }
+
+    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_debuglog_state == MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD)) {
+        if (MTK_GPS_ERROR == gps_dbg_log_pingpang_init()) {
+            g_gpsdbglogThreadExit = true;
+            LOGE("gps dbg log pingpang init fail, thread exit");
+        }
+    }
+    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(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 size_t GetFileSize(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);
+    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
+    }
+}
+
+/*static int CmpStrFile(char a[], char b[]) {  // compare two log files
+    char *pa = a, *pb = b;
+    while (*pa == *pb) {
+        pa++;
+        pb++;
+    }
+    return (*pa - *pb);
+}*/
+
+static int CmpFileTime(char *filename1, 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);
+
+    snprintf(dir_filename1, sizeof(dir_filename1), "%s%s", storagePath, filename1);
+    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;
+    char file_tree[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+    FILE* fd = NULL;
+
+    time(&tm);
+    p = localtime(&tm);
+    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 (mnl_init_gps_data_path(storagePath, MNL_GPS_DATA_PATH_MAX_LENGTH) == -1)
+        {  // mkdir ,if fail print the fail info to main log
+            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
+                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) {
+                    fwrite(storagePath, 1, strlen(storagePath), fd);
+                    fwrite("\n", 1, 1, fd);
+                    fclose(fd);
+                } else {
+                    LOGE("write file %s fail(%s)", file_tree, strerror(errno));
+                }
+             }
+        }
+
+        memset(gsGpsLogFileName, 0x00, sizeof(gsGpsLogFileName));
+        snprintf(gsGpsLogFileName, sizeof(gsGpsLogFileName), "%s.%04d%02d%02d%02d%02d%02d", 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 defined(__ANDROID_OS__)
+        GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);// close file before open,  if the file has been open.
+        #elif defined(__LINUX_OS__)
+        FILE_FCLOSE(g_hLogFile);
+        #endif
+
+        snprintf(gsGpsLogFileName_full, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s"LOG_FILE_WRITING_EXTEN_NAME, gsGpsLogFileName);
+        #if ANDROID_MNLD_PROP_SUPPORT
+        property_set(GPS_LOG_PERSIST_FLNM, strstr(gsGpsLogFileName_full, log_filename_suffix));
+        #endif
+
+        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");
+            }
+            g_hLogFile = fdopen(LogFile_fd, "w");
+        }
+        LOGD("file(%s) created successfully(0x%x)\r\n", gsGpsLogFileName, (unsigned int)g_hLogFile);
+
+        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;
+}
+
+size_t 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};
+    size_t DirLogSize_temp;
+    DIR *p_dir;
+    char OldFile[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+
+    struct dirent *p_dirent;
+    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.
+            size_t ret = 0;
+
+            ret = GetFileSize(OldGpsFile);
+            memset(OldFile, 0x00, sizeof(OldFile));
+            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) {
+    if (mtk_gps_log_is_hide() == 1) {   //Forbit to print gps debug log
+         return MTK_GPS_SUCCESS;
+    }
+
+    if ((gps_debuglog_state == MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD) \
+                 && (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;
+}
+
+// the real write to flash
+static size_t gps_dbg_log_pingpang_write(ping_pang_buffer* pingpang, FILE* filp) {
+    size_t count = 0;
+    if ((pingpang->buffer1_state == READABLE)\
+        && (pingpang->buffer2_state != READABLE)\
+        && ((pingpang->buffer1_lenth_to_write) != 0)) {
+        pingpang->buffer1_state = READING;
+        count = fwrite(pingpang->start_address_buffer1, 1, pingpang->buffer1_lenth_to_write, filp);
+        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;
+        count = fwrite(pingpang->start_address_buffer2, 1, pingpang->buffer2_lenth_to_write, filp);
+        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);
+    }
+    if (ping_pang_buffer_body.start_address_buffer2 != NULL) {
+        free(ping_pang_buffer_body.start_address_buffer2);
+    }
+    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) {
+            fwrite(pingpang->start_address_buffer2, 1, pingpang->buffer2_lenth_to_write, filp);
+        }
+        fwrite(pingpang->start_address_buffer1, 1, tmp_next_write - pingpang->start_address_buffer1, filp);
+    } else if ((pingpang->buffer2_state == WRITING) && (pingpang->buffer1_state != WRITING)) {
+        if (pingpang->buffer1_state == READABLE) {
+            fwrite(pingpang->start_address_buffer1, 1, pingpang->buffer1_lenth_to_write, filp);
+        }
+        fwrite(pingpang->start_address_buffer2, 1, tmp_next_write - pingpang->start_address_buffer2, filp);
+    } 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) {
+            if(state_result[0] == '1') {
+                gps_debuglog_state = MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD;
+            } else {
+                gps_debuglog_state = MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD;
+            }
+        }
+
+        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);
+            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)) {
+                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
+}
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnl2hal_interface.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnl2hal_interface.c
new file mode 100644
index 0000000..492d293
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnl2hal_interface.c
@@ -0,0 +1,581 @@
+#include "mnl2hal_interface.h"
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#include "mpe.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnl2hal"
+#endif
+
+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 safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_gps_status(gps_status status) {
+    LOGD("mnl2hal_gps_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 safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_gps_sv(gnss_sv_info sv) {
+    //LOGD("mnl2hal_gps_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(sv));
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_nmea(int64_t timestamp, const char* nmea, int length) {
+    #ifdef CONFIG_GPS_ENG_LOAD
+    if ('$' == nmea[0] && (strncmp(&nmea[3],"RMC", 3)==0)) {
+        LOGD("timestamp=%llu, 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);
+    put_int(buff, &offset, length);
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_gps_capabilities(gps_capabilites capabilities) {
+    LOGD("mnl2hal_gps_capabilities  capabilities=0x%x", capabilities);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_GPS_CAPABILITIES);
+    put_binary(buff, &offset, (const char*)&capabilities, sizeof(capabilities));
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_gps_measurements(gps_data data) {
+    LOGD("mnl2hal_gps_measurements");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_GPS_MEASUREMENTS);
+    put_binary(buff, &offset, (const char*)&data, sizeof(data));
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_gps_navigation(gps_nav_msg msg) {
+    LOGD("mnl2hal_gps_navigation");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_GPS_NAVIGATION);
+    put_binary(buff, &offset, (const char*)&msg, sizeof(msg));
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_gnss_measurements(gnss_data data) {
+    LOGD("mnl2hal_gnss_measurements");
+    char buff[HAL_MNL_BUFF_SIZE] = {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 safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_gnss_navigation(gnss_nav_msg msg) {
+    LOGD("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 safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+
+int mnl2hal_request_wakelock() {
+    LOGD("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 safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_release_wakelock() {
+    LOGD("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 safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_request_utc_time() {
+    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 safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_request_data_conn(struct sockaddr_storage addr) {
+    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));
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_release_data_conn() {
+    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);
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_request_ni_notify(int session_id, 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);
+    put_string(buff, &offset, client_name);
+    put_int(buff, &offset, requestor_id_encoding);
+    put_int(buff, &offset, client_name_encoding);
+
+    return safe_sendto(MTK_MNL2HAL, 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 safe_sendto(MTK_MNL2HAL, 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 safe_sendto(MTK_MNL2HAL, 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);
+
+    return safe_sendto(MTK_MNL2HAL, 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);
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_request_nlp(bool type) {
+    LOGD("mnl2hal_request_nlp, type=%d", type);
+    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);
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+// -1 means failure
+int hal2mnl_hdlr(int fd, hal2mnl_interface* hdlr) {
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    int ver;
+    hal2mnl_cmd cmd;
+    int read_len;
+    int ret = 0;
+
+    read_len = safe_recvfrom(fd, buff, sizeof(buff));
+    if (read_len <= 0) {
+        LOGE("hal2mnl_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+        return -1;
+    }
+    ver = get_int(buff, &offset, sizeof(buff));
+    UNUSED(ver);
+    cmd = get_int(buff, &offset, sizeof(buff));
+
+    switch (cmd) {
+    case HAL2MNL_HAL_REBOOT: {
+        if (hdlr->hal_reboot) {
+            hdlr->hal_reboot();
+        } else {
+            LOGE("hal_reboot is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_INIT: {
+        if (hdlr->gps_init) {
+            hdlr->gps_init();
+        } else {
+            LOGE("gps_init is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_START: {
+        if (hdlr->gps_start) {
+            hdlr->gps_start();
+        } else {
+            LOGE("gps_start is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_STOP: {
+        if (hdlr->gps_stop) {
+            hdlr->gps_stop();
+        } else {
+            LOGE("gps_stop is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_CLEANUP: {
+        if (hdlr->gps_cleanup) {
+            hdlr->gps_cleanup();
+        } else {
+            LOGE("gps_cleanup is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_INJECT_TIME: {
+        if (hdlr->gps_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->gps_inject_time(time, time_reference, uncertainty);
+        } else {
+            LOGE("gps_inject_time is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_INJECT_LOCATION: {
+        if (hdlr->gps_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->gps_inject_location(lat, lng, acc);
+        } else {
+            LOGE("gps_inject_location is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_DELETE_AIDING_DATA: {
+        if (hdlr->gps_delete_aiding_data) {
+            int flags = get_int(buff, &offset, sizeof(buff));
+            hdlr->gps_delete_aiding_data(flags);
+        } else {
+            LOGE("gps_delete_aiding_data is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_SET_POSITION_MODE: {
+        if (hdlr->gps_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->gps_set_position_mode(mode, recurrence, min_interval,
+                preferred_acc, preferred_time, lowPowerMode);
+        } else {
+            LOGE("gps_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("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) {
+            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(apn, ip_type);
+        } else {
+            LOGE("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("data_conn_closed is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_DATA_CONN_FAILED: {
+        if (hdlr->data_conn_failed) {
+            hdlr->data_conn_failed();
+        } else {
+            LOGE("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("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("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("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("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("ni_respond is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_UPDATE_NETWORK_STATE: {
+        if (hdlr->update_network_state) {
+            int connected = get_int(buff, &offset, sizeof(buff));
+            network_type type = get_int(buff, &offset, sizeof(buff));
+            int roaming  = get_int(buff, &offset, sizeof(buff));
+            char* extra_info = get_string(buff, &offset, sizeof(buff));
+            hdlr->update_network_state(connected, type, roaming, extra_info);
+        } else {
+            LOGE("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("update_network_availability 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("update_gnss_config is NULL");
+        ret = -1;
+    }
+    break;
+    }
+    case HAL2MNL_GPS_MEASUREMENT: {
+        if (hdlr->set_gps_measurement) {
+            bool enabled = get_int(buff, &offset, sizeof(buff));
+            bool enableFullTracking = get_int(buff, &offset, sizeof(buff));
+            hdlr->set_gps_measurement(enabled, enableFullTracking);
+        } else {
+            LOGE("set_gps_measurement is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_NAVIGATION: {
+        if (hdlr->set_gps_navigation) {
+            bool enabled = get_int(buff, &offset, sizeof(buff));
+            hdlr->set_gps_navigation(enabled);
+        } else {
+            LOGE("set_gps_navigation 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("set_vzw_debug is NULL");
+            ret = -1;
+        }
+        break;
+    }
+#if defined(__LINUX_OS__)
+    case HAL2MNL_SEND_PMTK: {
+        if (hdlr->send_pmtk) {
+            char msg[MTK_PMTK_CMD_MAX_SIZE] = {0};
+            int len = get_binary(buff, &offset, msg, sizeof(buff), sizeof(msg));
+            hdlr->send_pmtk(msg, len);
+        } else {
+            LOGE("send_pmtk is NULL");
+            ret = -1;
+        }
+        break;
+    }
+#endif
+    default: {
+        LOGE("unknown cmd=%d", cmd);
+        ret = -1;
+        break;
+    }
+    }
+
+    return ret;
+}
+
+// -1 means failure
+int create_hal2mnl_fd() {
+    int fd = socket_bind_udp(MTK_HAL2MNL);
+    socket_set_blocking(fd, 0);
+    return fd;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnl_common.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnl_common.c
new file mode 100644
index 0000000..2b5c5f0
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnl_common.c
@@ -0,0 +1,337 @@
+/* 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 "mnl_common.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnl_linux"
+#endif
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#include <cutils/properties.h>
+#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;
+#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) {
+        LOGE("%s: '=' is not found!!\n", __FUNCTION__);
+        return -1;    // 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, char* key, 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.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);
+    }
+    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, "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, "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);
+    } else if ((!strcmp(key, "elev_mask"))) {
+        prConfig->elev_mask = 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("%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';
+#ifdef CONFIG_GPS_MT3303
+        prConfig->dbg2file = result[6] - '0';
+#endif
+        LOGD("dbg2file: %d\n", prConfig->dbg2file);
+        prConfig->debug_nmea = result[3] - '0';
+        LOGD("debug_nmea:%d \n", prConfig->debug_nmea);
+        prConfig->BEE_enabled = result[4] - '0';
+        LOGD("BEE_enabled: %d", prConfig->BEE_enabled);
+        // prConfig->test_mode = result[5] - '0';
+        // LOGD("test_mode: %d", prConfig->test_mode);
+    } else {
+        LOGE("Config is not set yet, ignore");
+    }
+#endif
+    if (idx < cnt)  /* successfully read property from file */  {
+        LOGD("[setting] reading from %s\n", mnl_prop_path[idx]);
+        res = 0;
+    } else {
+        LOGD("[setting] load default value\n");
+        res = -1;
+    }
+    LOGD("dev_dsp/dev_gps : %s %s,init_speed/link_speed: %d %d\n",
+        prConfig->dev_dsp, prConfig->dev_gps,
+        prConfig->init_speed, prConfig->link_speed);
+    LOGD("pmtk_conn/socket_port/dev_dbg : %d %d %s\n",
+        prConfig->pmtk_conn, prConfig->socket_port, prConfig->dev_dbg);
+    LOGD("debug_nmea/debug_mnl: %d 0x%04X,nmea2file/dbg2file: %d/%d\n",
+        prConfig->debug_nmea, prConfig->debug_mnl, prConfig->nmea2file, prConfig->dbg2file);
+    LOGD("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("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("EPO_priority: %d,BEE_priority: %d, SUPL_priority: %d\n",
+        prConfig->EPO_priority, prConfig->BEE_priority, prConfig->SUPL_priority);
+    LOGD("AVAILIABLE_AGE: %d,RTC_DRIFT: %d,TIME_INTERVAL: %d\n",
+        prConfig->AVAILIABLE_AGE, prConfig->RTC_DRIFT, prConfig->TIME_INTERVAL);
+    return res;
+}
+#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/mtk_mnld/mnld_entity/src/mnld.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnld.c
new file mode 100644
index 0000000..295c502
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnld.c
@@ -0,0 +1,2944 @@
+// SPDX-License-Identifier: MediaTekProprietary
+#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 <inttypes.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"
+#ifdef CONFIG_GPS_MT3303
+#include "mt3333_controller.h"
+#endif
+#include "mtk_flp_main.h"
+#include "mnl_flp_test_interface.h"
+#include "mtk_geofence_main.h"
+#include "gps_dbg_log.h"
+#include "mpe.h"
+#include "mnl_at_interface.h"
+#include "Mnld2NlpUtilsInterface.h"
+#include "mtk_flp_screen_monitor.h"
+#include "Meta2MnldInterface.h"
+#include "Mnld2DebugInterface.h"
+#include "Debug2MnldInterface.h"
+#include "mtk_auto_log.h"
+
+extern int network_count;
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#include <cutils/properties.h>
+#endif
+
+int log_dbg_level = L_DEBUG;
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnld"
+#endif
+
+static void mnld_fsm(mnld_gps_event event, int data1, int data2, void* data3);
+
+static mnld_context g_mnld_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;
+#if ANDROID_MNLD_PROP_SUPPORT
+extern char chip_id[PROPERTY_VALUE_MAX];
+#else
+extern char chip_id[100];
+#endif
+volatile UINT8 enable_debug2app = DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_STOP_DEBUG;
+
+/*****************************************
+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_OFL_STARTING:
+        return "OFL_STARTING";
+    case MNLD_GPS_STATE_OFL_STARTED:
+        return "OFL_STARTED";
+    case MNLD_GPS_STATE_OFL_STOPPING:
+        return "OFL_STOPPING";
+    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_OFFLOAD_START:
+        return "OFFLOAD_START";
+    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;
+        mnl2agps_reset_gps_done();
+    }
+}
+
+static void do_gps_started_hdlr(int si_assist_req) {
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    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;
+        mnl2hal_gps_status(MTK_GPS_STATUS_SESSION_ENGINE_ON);
+        mnl2hal_gps_status(MTK_GPS_STATUS_SESSION_BEGIN);
+        mnl2agps_gps_open(si_assist_req);
+    }
+
+    if (agps->need_open_ack) {
+        agps->need_open_ack = false;
+        mnl2agps_open_gps_done();
+    }
+
+    if (flp->need_open_ack) {
+        flp->need_open_ack = false;
+        /*add open ack message to flp*/
+        LOGD("MNLD_FLP_DEBUG:support_auto_switch:%d,offload_auto:%d",mnld_support_auto_switch_mode(),mnld_offload_is_auto_mode());
+        if (mnld_support_auto_switch_mode()) {   //New offload auto switch mode
+            LOGD("Auto switch mode");
+            if (mnld_offload_is_auto_mode()) {
+                LOGD("Offload Auto mode");
+                mnld_flp_ofl_gps_open_done();
+            } else {
+                LOGD("HBD auto mode");
+                mnld_flp_hbd_gps_open_done();
+            }
+        } else { //always host
+            LOGD("HBD auto mode");
+            mnld_flp_hbd_gps_open_done();
+        }
+        mnl2agps_gps_open(si_assist_req);
+    }
+
+    if (geofence->need_open_ack) {
+        geofence->need_open_ack = false;
+        /*add open ack message to gfc*/
+        LOGD("MNLD_GFC_DEBUG:support_auto_switch:%d,offload_auto:%d",mnld_support_auto_switch_mode(),mnld_offload_is_auto_mode());
+        if (mnld_support_auto_switch_mode()) {   //New offload auto switch mode
+            LOGD("Auto switch mode");
+            if (mnld_offload_is_auto_mode()) {
+                LOGD("Offload Auto mode");
+                mnld_gfc_ofl_gps_open_done();
+            } else {
+                LOGD("HBD auto mode");
+                mnld_gfc_hbd_gps_open_done();
+            }
+        } else { //always host
+            LOGD("HBD auto mode");
+            mnld_gfc_hbd_gps_open_done();
+        }
+        mnl2agps_gps_open(si_assist_req);
+    }
+
+    if (flp_test->need_open_ack) {
+        flp_test->need_open_ack = false;
+        /*add open ack message to flp_test*/
+    }
+
+    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*/
+    }
+
+    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);
+        gps_control_gps_reset(g_mnld_ctx.gps_status.delete_aiding_flag);
+        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;
+        mnl2hal_gps_status(MTK_GPS_STATUS_SESSION_END);
+        mnl2hal_gps_status(MTK_GPS_STATUS_SESSION_ENGINE_OFF);
+        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* flp = &g_mnld_ctx.gps_status.clients.flp;
+    if (flp->need_close_ack) {
+        flp->need_close_ack = false;
+        /* add close ack message to flp*/
+        LOGD("MNLD_FLP_DEBUG:support_auto_switch:%d,offload_auto:%d",mnld_support_auto_switch_mode(),mnld_offload_is_auto_mode());
+        if (mnld_support_auto_switch_mode()) {   //New offload auto switch mode
+            LOGD("Auto switch mode");
+            if (mnld_offload_is_auto_mode()) {
+                LOGD("Offload Auto mode");
+                mnld_flp_ofl_gps_close_done();
+            } else {
+                LOGD("HBD auto mode");
+                mnld_flp_hbd_gps_close_done();
+            }
+        } else { //always host
+            LOGD("HBD auto mode");
+            mnld_flp_hbd_gps_close_done();
+        }
+    }
+
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    if (geofence->need_close_ack) {
+        geofence->need_close_ack = false;
+        /* add close ack message to geofence*/
+        LOGD("MNLD_GFC_DEBUG:support_auto_switch:%d,offload_auto:%d",mnld_support_auto_switch_mode(),mnld_offload_is_auto_mode());
+        if (mnld_support_auto_switch_mode()) {   //New offload auto switch mode
+            LOGD("Auto switch mode");
+            if (mnld_offload_is_auto_mode()) {
+                LOGD("Offload Auto mode");
+                mnld_gfc_ofl_gps_close_done();
+            } else {
+                LOGD("HBD auto mode");
+                mnld_gfc_hbd_gps_close_done();
+            }
+        } else {
+            LOGD("HBD auto mode");
+            mnld_gfc_hbd_gps_close_done();
+        }
+    }
+
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    if (flp_test->need_close_ack) {
+        flp_test->need_close_ack = false;
+        /* add close ack message to flp_test*/
+    }
+
+    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*/
+    }
+    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);
+    #ifdef MTK_ADR_SUPPORT
+    mnl2adr_close_gps_done();
+    #endif
+    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* agps = &g_mnld_ctx.gps_status.clients.agps;
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    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 && flp->gps_used == false
+        && flp_test->gps_used == false && at_cmd_test->gps_used == false && factory->gps_used == false
+ && geofence->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* agps = &g_mnld_ctx.gps_status.clients.agps;
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    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 || flp->gps_used == true || flp_test->gps_used == true
+        || at_cmd_test->gps_used == true || factory->gps_used == true || geofence->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* agps = &g_mnld_ctx.gps_status.clients.agps;
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    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 (flp->gps_used)
+        flp->gps_used = false;
+    if (flp_test->gps_used)
+        flp_test->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;
+}
+int mtk_gps_get_gps_user() {
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    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;
+    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 (flp->gps_used)
+        gps_user |= GPS_USER_FLP;
+    if (flp_test->gps_used)
+        gps_user |= GPS_USER_OFL_TEST;
+    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;
+    return gps_user;
+}
+
+int is_flp_user_exist() {
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    return flp->gps_used;
+}
+
+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* 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) {
+        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* 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) {
+        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("fsm_gps_state_idle() data1=%d,data2=%d,data3=%p\n", data1, data2, data3);
+    switch (event) {
+    case GPS_EVENT_START: {
+        if (!(mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode()))) {
+            mnl2hal_request_wakelock();
+        }
+        #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;
+        int gps_user = mtk_gps_get_gps_user();
+        // if no other users except GPS_USER_FLP or GPS_USER_OFL_TEST, bypass restart
+        if (((gps_user & (GPS_USER_FLP | GPS_USER_OFL_TEST | GPS_USER_GEOFENCE)) == gps_user) && mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+            LOGE("gps_user: %d, not run MNL start timer\n", gps_user);
+            LOGE("still enable start timer");
+            start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+        } else {
+            start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+        }
+        gps_control_gps_start(g_mnld_ctx.gps_status.delete_aiding_flag);
+        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_OFFLOAD_START: {
+        if (!(mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode()))) {
+            mnl2hal_request_wakelock();
+        }
+        #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_OFL_STARTING;
+        int gps_user = mtk_gps_get_gps_user();
+        // if no other users except GPS_USER_FLP or GPS_USER_OFL_TEST, bypass restart
+        if (((gps_user & (GPS_USER_FLP | GPS_USER_OFL_TEST | GPS_USER_GEOFENCE)) == gps_user) && mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+            LOGE("gps_user: %d, not run MNL start timer\n", gps_user);
+            LOGE("still enable start timer");
+            start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+        } else {
+            start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+        }
+        gps_control_gps_start(g_mnld_ctx.gps_status.delete_aiding_flag);
+        g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+        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("data2=%d,data3=%p", data2, data3);
+    switch (event) {
+    case GPS_EVENT_STOP: {
+        // Need to handle starting-stop event for FLP offload like started-stop
+        if (mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+            #if 1
+            LOGE("!NOT! handle starting stop event for offload");
+            #else
+            LOGE("fsm_gps_state_starting, handle starting stop event for offload");
+            do_gps_started_hdlr(0);
+            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);
+                gps_control_gps_stop();
+            }
+            #endif
+        }
+        break;
+    }
+    case GPS_EVENT_START:
+    case GPS_EVENT_OFFLOAD_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);
+            gps_control_gps_stop();
+        } 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;
+            }
+            if (is_a_hbd_gps_client_exist() || !(mnld_support_auto_switch_mode())) {
+                mnld_flp_session.type = MNLD_FLP_CAPABILITY_AP_MODE;
+                mnld_gfc_session.type = MNLD_GFC_CAPABILITY_AP_MODE;
+                if (mnld_flp_session.type != mnld_flp_session.pre_type) {
+                    mnld_flp_session.id = mnld_flp_gen_new_session();
+                    mnld_flp_session.pre_type = mnld_flp_session.type;
+                    g_mnld_ctx.gps_status.clients.flp.gps_used = false;
+                    mnld_flp_session_update();
+                }
+                if (mnld_gfc_session.type != mnld_gfc_session.pre_type) {
+                    mnld_gfc_session.id = mnld_gfc_gen_new_session();
+                    mnld_gfc_session.pre_type = mnld_gfc_session.type;
+                    g_mnld_ctx.gps_status.clients.geofence.gps_used = false;
+                    mnld_gfc_session_update();
+                }
+            } else {
+                mnld_flp_session.type = MNLD_FLP_CAPABILITY_AP_MODE;
+                mnld_flp_session.pre_type = mnld_flp_session.type;
+                mnld_gfc_session.type = MNLD_GFC_CAPABILITY_AP_MODE;
+                mnld_gfc_session.pre_type = mnld_gfc_session.type;
+                start_timer(g_mnld_ctx.gps_status.timer_switch_ofl_mode, MNLD_GPS_SWITCH_OFL_MODE_TIMEOUT);
+            }
+        }
+        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) {
+    LOGE("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);
+            stop_timer(g_mnld_ctx.gps_status.timer_switch_ofl_mode);
+            gps_control_gps_stop();
+        } else {
+            do_gps_stopped_hdlr();
+            if (is_all_hbd_gps_client_exit() && mnld_support_auto_switch_mode()) {
+                start_timer(g_mnld_ctx.gps_status.timer_switch_ofl_mode, MNLD_GPS_SWITCH_OFL_MODE_TIMEOUT);
+            }
+        }
+        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);
+            gps_control_gps_reset(g_mnld_ctx.gps_status.delete_aiding_flag);
+            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()) {
+            mnl2agps_reaiding_req();
+        }
+        LOGE("fsm_gps_state_started() unexpected event=%d", event);
+        break;
+    case GPS_EVENT_OFFLOAD_START:
+        // Do nothing
+        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) {
+    LOGE("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()) {
+            LOGD("OFFLOAD debug: restarting");
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STARTING;
+            int gps_user = mtk_gps_get_gps_user();
+            // if no other users except GPS_USER_FLP or GPS_USER_OFL_TEST, bypass restart
+            if (((gps_user & (GPS_USER_FLP | GPS_USER_OFL_TEST | GPS_USER_GEOFENCE)) == gps_user) && mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+                LOGE("gps_user: %d\n", gps_user);
+            } else {
+                start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+            }
+            gps_control_gps_start(g_mnld_ctx.gps_status.delete_aiding_flag);
+            g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+        } else {
+            LOGD("OFFLOAD debug: stop done");
+            if (!(mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode()))) {
+                mnl2hal_release_wakelock();
+            }
+            #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;
+            LOGD("OFFLOAD debug: update session");
+
+            if(mnld_support_auto_switch_mode()) {
+                mnld_flp_session.type = MNLD_FLP_CAPABILITY_AP_OFL_MODE;
+                if (mnld_flp_session.type != mnld_flp_session.pre_type) {
+                    mnld_flp_session.id = mnld_flp_gen_new_session();
+                    mnld_flp_session.pre_type = mnld_flp_session.type;
+                    g_mnld_ctx.gps_status.clients.flp.gps_used = false;
+                    mnld_flp_session_update();
+                }
+                mnld_gfc_session.type = MNLD_GFC_CAPABILITY_AP_OFL_MODE;
+                if (mnld_gfc_session.type != mnld_gfc_session.pre_type) {
+                    mnld_gfc_session.id = mnld_gfc_gen_new_session();
+                    mnld_gfc_session.pre_type = mnld_gfc_session.type;
+                    g_mnld_ctx.gps_status.clients.geofence.gps_used = false;
+                    mnld_gfc_session_update();
+                }
+            }
+        }
+        break;
+    }
+    case GPS_EVENT_OFFLOAD_START:
+    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;
+    }
+    }
+}
+
+static void fsm_gps_state_ofl_starting(mnld_gps_event event, int data1, int data2, void* data3) {
+    LOGD("fsm_gps_state_starting() data2=%d,data3=%p\n", data2, data3);
+    switch (event) {
+    case GPS_EVENT_STOP: {
+        // Need to handle starting-stop event for FLP offload like started-stop
+        if (mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+            #if 1
+            LOGE("fsm_gps_state_starting, !NOT! handle starting stop event for offload");
+            #else
+            LOGE("fsm_gps_state_starting, handle starting stop event for offload");
+            do_gps_started_hdlr(0);
+            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);
+                gps_control_gps_stop();
+            }
+            #endif
+        }
+        break;
+    }
+    case GPS_EVENT_START:
+    case GPS_EVENT_OFFLOAD_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() || is_a_hbd_gps_client_exist()) {
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_OFL_STOPPING;
+            start_timer(g_mnld_ctx.gps_status.timer_stop, MNLD_GPS_STOP_TIMEOUT);
+            gps_control_gps_stop();
+        } else {
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_OFL_STARTED;
+            mnld_flp_session.type = MNLD_FLP_CAPABILITY_OFL_MODE;
+            mnld_gfc_session.type = MNLD_GFC_CAPABILITY_OFL_MODE;
+        }
+        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_ofl_started(mnld_gps_event event, int data1, int data2, void* data3) {
+    LOGE("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);
+        if (is_a_hbd_gps_client_exist()) {
+            //flp
+            g_mnld_ctx.gps_status.clients.flp.gps_used = false;
+            g_mnld_ctx.gps_status.clients.flp.need_open_ack = false;
+            g_mnld_ctx.gps_status.clients.flp.need_close_ack = false;
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_OFL_STOPPING;
+            //geofence
+            g_mnld_ctx.gps_status.clients.geofence.gps_used = false;
+            g_mnld_ctx.gps_status.clients.geofence.need_open_ack = false;
+            g_mnld_ctx.gps_status.clients.geofence.need_close_ack = false;
+            start_timer(g_mnld_ctx.gps_status.timer_stop, MNLD_GPS_STOP_TIMEOUT);
+            gps_control_gps_stop();
+        }
+        break;
+    }
+    case GPS_EVENT_STOP: {
+        if (is_flp_user_exist() || is_geofence_user_exist()) {
+            do_gps_stopped_hdlr();
+            LOGW("GPS_EVENT_STOP cmd sent by error user!!");
+        } else {
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_OFL_STOPPING;
+            start_timer(g_mnld_ctx.gps_status.timer_stop, MNLD_GPS_STOP_TIMEOUT);
+            gps_control_gps_stop();
+        }
+        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);
+        //    gps_control_gps_reset(g_mnld_ctx.gps_status.delete_aiding_flag);
+        //    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()) {
+            mnl2agps_reaiding_req();
+        }
+        LOGE("fsm_gps_state_started() unexpected event=%d", event);
+        break;
+    case GPS_EVENT_OFFLOAD_START:
+        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_ofl_stopping(mnld_gps_event event, int data1, int data2, void* data3) {
+    LOGE("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_flp_user_exist() || is_geofence_user_exist()) && is_all_hbd_gps_client_exit()) {
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_OFL_STARTING;
+            int gps_user = mtk_gps_get_gps_user();
+            // if no other users except GPS_USER_FLP or GPS_USER_OFL_TEST, bypass restart
+            if (((gps_user & (GPS_USER_FLP | GPS_USER_OFL_TEST| GPS_USER_GEOFENCE)) == gps_user) && mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+                LOGE("gps_user: %d\n", gps_user);
+            } else {
+                start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+            }
+            gps_control_gps_start(g_mnld_ctx.gps_status.delete_aiding_flag);
+            g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+        } else {
+            if (!(mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode()))) {
+                mnl2hal_release_wakelock();
+            }
+            #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;
+
+            if (is_a_hbd_gps_client_exist()) {  //some hbd user exist, must switch to AP mode and start gps
+                mnld_flp_session.type = MNLD_FLP_CAPABILITY_AP_MODE;
+                if (mnld_flp_session.type != mnld_flp_session.pre_type) {
+                    mnld_flp_session.id = mnld_flp_gen_new_session();
+                    mnld_flp_session.pre_type = mnld_flp_session.type;
+                    g_mnld_ctx.gps_status.clients.flp.gps_used = false;
+                    mnld_flp_session_update();
+                }
+                mnld_gfc_session.type = MNLD_GFC_CAPABILITY_AP_MODE;
+                if (mnld_gfc_session.type != mnld_gfc_session.pre_type) {
+                    mnld_gfc_session.id = mnld_gfc_gen_new_session();
+                    mnld_gfc_session.pre_type = mnld_gfc_session.type;
+                    g_mnld_ctx.gps_status.clients.geofence.gps_used = false;
+                    mnld_gfc_session_update();
+                }
+                mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+            } else {   // flp user exit normally and no user exist, so switch to idle state directly
+                if(mnld_support_auto_switch_mode()) {
+                    mnld_flp_session.type = MNLD_FLP_CAPABILITY_AP_OFL_MODE;
+                    if (mnld_flp_session.type != mnld_flp_session.pre_type) {
+                        mnld_flp_session.id = mnld_flp_gen_new_session();
+                        mnld_flp_session.pre_type = mnld_flp_session.type;
+                        g_mnld_ctx.gps_status.clients.flp.gps_used = false;
+                        mnld_flp_session_update();
+                    }
+                    mnld_gfc_session.type = MNLD_GFC_CAPABILITY_AP_OFL_MODE;
+                    if (mnld_gfc_session.type != mnld_gfc_session.pre_type) {
+                        mnld_gfc_session.id = mnld_gfc_gen_new_session();
+                        mnld_gfc_session.pre_type = mnld_gfc_session.type;
+                        g_mnld_ctx.gps_status.clients.geofence.gps_used = false;
+                        mnld_gfc_session_update();
+                    }
+                }
+            }
+        }
+        break;
+    }
+    case GPS_EVENT_OFFLOAD_START:
+    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;
+    }
+    }
+}
+
+int mnld_gps_controller_mnl_nmea_timeout(void) {
+    if (g_mnld_ctx.gps_status.timer_nmea_monitor != 0) {
+        // stop_timer(g_mnld_ctx.gps_status.timer_nmea_monitor);
+        start_timer(g_mnld_ctx.gps_status.timer_nmea_monitor, nmea_data_time_out);
+    }
+    return 0;
+}
+
+int mnld_gps_start_nmea_monitor() {
+    if (g_mnld_ctx.gps_status.timer_nmea_monitor != 0) {
+        start_timer(g_mnld_ctx.gps_status.timer_nmea_monitor, nmea_data_time_out);
+    }
+    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 int mnld_fsm_offload_old_user = 0;
+static int mnld_fsm_offload_lp_mode = 0;
+static int mnld_fsm_offload_fwk_wakelock = 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;
+
+    if (!(mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode()))) {
+        LOGD("mnld_fsm() state=[%s] event=[%s]",
+            get_mnld_gps_state_str(gps_state), get_mnld_gps_event_str(event));
+    } else {
+        // Wakelock control for FLP offload user
+        int user_bitmap;
+        user_bitmap = mtk_gps_get_gps_user();
+        LOGD("mnld_fsm() state=[%s] event=[%s], user=0x%08x, old user=0x%08x",
+            get_mnld_gps_state_str(gps_state), get_mnld_gps_event_str(event),
+            user_bitmap, mnld_fsm_offload_old_user);
+
+        // Libmnl.so need to know once the users changed, then
+        // it can notify connsys to enter low power mode or NMEA mode
+        mtk_gps_ofl_set_user(user_bitmap);
+
+        // If only FLP offload user or No user, should stop nmea timer
+        if ((user_bitmap & (GPS_USER_FLP | GPS_USER_OFL_TEST | GPS_USER_GEOFENCE)) == user_bitmap) {
+            if (!mnld_fsm_offload_lp_mode) {
+                LOGD("mnld_fsm() enter offload lp mode");
+                mnld_gps_stop_nmea_monitor();
+                gps_control_kernel_wakelock_give();
+                if (mnld_fsm_offload_fwk_wakelock) {
+                    mnl2hal_release_wakelock();
+                    mnld_fsm_offload_fwk_wakelock = 0;
+                }
+                mnld_fsm_offload_lp_mode = 1;
+            }
+        } else {
+            if (mnld_fsm_offload_lp_mode) {
+                LOGD("mnld_fsm() leave offload lp mode");
+                mnl2hal_request_wakelock();
+                gps_control_kernel_wakelock_take();
+                mnld_gps_start_nmea_monitor();
+                mnld_fsm_offload_lp_mode = 0;
+                mnld_fsm_offload_fwk_wakelock = 1;
+            }
+        }
+        mnld_fsm_offload_old_user = 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;
+    }
+    case MNLD_GPS_STATE_OFL_STARTING: {
+        fsm_gps_state_ofl_starting(event, data1, data2, data3);
+        break;
+    }
+    case MNLD_GPS_STATE_OFL_STARTED: {
+        fsm_gps_state_ofl_started(event, data1, data2, data3);
+        break;
+    }
+    case MNLD_GPS_STATE_OFL_STOPPING: {
+        fsm_gps_state_ofl_stopping(event, data1, data2, data3);
+        break;
+    }
+    default: {
+        LOGE("mnld_fsm() unexpected gps_state=%d", gps_state);
+        CRASH_TO_DEBUG();
+        break;
+    }
+    }
+}
+
+/*****************************************
+HAL -> MNL
+*****************************************/
+static void hal_reboot() {
+    LOGW("hal_reboot");
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    hal->gps_used = false;
+    hal->need_open_ack = false;
+    hal->need_close_ack = false;
+    hal->need_reset_ack = false;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+#ifdef CONFIG_GPS_MT3303
+    mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GPSREBOOT);
+#endif    
+}
+
+static void hal_gps_init() {
+    LOGW("hal_gps_init");
+    g_mnld_ctx.gps_status.is_gps_init = true;
+    mnl2agps_gps_init();
+#ifdef CONFIG_GPS_MT3303
+    mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GPSENABLE);
+#endif
+}
+
+static void hal_gps_start() {
+    LOGI("hal_gps_start");
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    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);
+#ifdef CONFIG_GPS_MT3303
+    mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GPSSTART);
+#endif
+}
+
+static void hal_gps_stop() {
+    LOGI("hal_gps_stop");
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    hal->gps_used = false;
+    hal->need_open_ack = false;
+    hal->need_close_ack = true;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+#ifdef CONFIG_GPS_MT3303
+    mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GPSSTOP);
+#endif
+}
+
+static void hal_gps_cleanup() {
+    LOGI("hal_gps_cleanup");
+    g_mnld_ctx.gps_status.is_gps_init = false;
+    mnl2agps_gps_cleanup();
+#ifdef CONFIG_GPS_MT3303
+    mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GPSDISABLE);
+#endif
+}
+
+static void hal_gps_inject_time(int64_t time, int64_t time_reference, int uncertainty) {
+    LOGD("hal_gps_inject_time  time=%"PRId64" time_reference=%"PRId64" 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()) {
+#ifndef CONFIG_GPS_MT3303
+        mtk_gps_inject_ntp_time((MTK_GPS_NTP_T*)&ntp_inject);
+#else
+        mt3333_controller_inject_time(time, time_reference, uncertainty);
+#endif
+    }
+}
+
+static void hal_gps_inject_location(double lat, double lng, float acc) {
+    int ret = 0;
+    MTK_GPS_NLP_T nlp_inject;
+    nlp_context context;
+    bool alt_valid = false;
+    float altitude = 0.0f;
+    bool source_valid = true;
+    bool source_gnss = false;
+    bool source_nlp = true;
+    bool 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 = mnld_is_gps_started_done();
+    nlp_inject.type = 0;
+    if (mnld_is_gps_started_done()) {
+#ifndef CONFIG_GPS_MT3303
+        mtk_gps_inject_nlp_location(&nlp_inject);
+#else
+        mt3333_controller_inject_location(lat, lng, acc);
+#endif
+    }
+    ret = mnl2agps_location_sync(lat, lng, acc, alt_valid, altitude, source_valid, source_gnss, source_nlp, source_sensor);
+    LOGD("ret = %d\n", ret);
+    if (0 == ret) {
+        LOGD("mnl2agps_location_sync success\n");
+    }
+}
+
+static void hal_gps_delete_aiding_data(int flags) {
+    LOGW("hal_gps_delete_aiding_data  flags=0x%x", flags);
+    mnl2agps_delete_aiding_data(flags);
+    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 |= flags;
+    mnld_fsm(GPS_EVENT_RESET, 0, 0, NULL);
+#ifdef CONFIG_GPS_MT3303
+    extern int is_ygps_delete_data ;
+    if(g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_IDLE){
+        is_ygps_delete_data = 1;    
+        
+         if (flags == GPS_DELETE_RTI){
+             g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+            is_ygps_delete_data = 0;
+         }
+    }
+#endif    
+}
+
+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);
+    mnl2agps_set_position_mode(mode);
+}
+
+static void hal_data_conn_open(const char* apn) {
+    LOGD("hal_data_conn_open  apn=[%s]", apn);
+    mnl2agps_data_conn_open(apn);
+}
+
+static void hal_data_conn_open_with_apn_ip_type(const char* apn, apn_ip_type ip_type) {
+    LOGD("hal_data_conn_open_with_apn_ip_type  apn=[%s] ip_type=%d", apn, ip_type);
+    mnl2agps_data_conn_open_ip_type(apn, ip_type);
+}
+
+static void hal_data_conn_closed() {
+    LOGD("hal_data_conn_closed");
+    mnl2agps_data_conn_closed();
+}
+
+static void hal_data_conn_failed() {
+    LOGD("hal_data_conn_failed");
+    mnl2agps_data_conn_failed();
+}
+
+static void hal_set_server(agps_type type, const char* hostname, int port) {
+    LOGD("hal_set_server  type=%d hostname=[%s] port=%d", type, hostname, port);
+    mnl2agps_set_server(type, hostname, port);
+}
+
+static void hal_set_ref_location(cell_type type, int mcc, int mnc, int lac, int cid) {
+    LOGD("hal_set_ref_location  type=%d mcc=%d mnc=%d lac=%d cid=%d", type, mcc, mnc, lac, cid);
+    mnl2agps_set_ref_loc(type, mcc, mnc, lac, cid);
+}
+
+static void hal_set_id(agps_id_type type, const char* setid) {
+    LOGD("hal_set_id  type=%d setid=[%s]", type, setid);
+    mnl2agps_set_set_id(type, setid);
+}
+
+static void hal_ni_message(char* msg, int len) {
+    LOGD("hal_ni_message, len=%d", len);
+    mnl2agps_ni_message(msg, len);
+}
+
+#if defined(__LINUX_OS__)
+static void hal_send_pmtk(const char* msg, int len) {
+    LOGD("hal_send_pmtk");
+
+    if(len < MTK_PMTK_CMD_MAX_SIZE)
+    {
+        gps_controller_rcv_pmtk(msg);
+    }else{
+        LOGW("len over spec:%d\r\n",len);
+    }
+}
+#endif
+
+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);
+    mnl2agps_ni_respond(notif_id, user_response);
+}
+
+static void hal_update_network_state(int connected, network_type type, int roaming,
+        const char* extra_info) {
+    LOGD("hal_update_network_state  connected=%d type=%d roaming=%d extra_info=[%s]",
+        connected, type, roaming, extra_info);
+    mnl2agps_update_network_state(connected, type, roaming, extra_info);
+    mnl_epo_status* epo_status = &g_mnld_ctx.epo_status;
+
+    if (connected == 1) {
+        network_count++;
+    } else if (connected == 0) {
+        network_count--;
+        if (network_count < 0) {
+            network_count = 0;
+        }
+    }
+    LOGD("hal_update_network_state network_count=%d", network_count);
+
+    epo_status->is_network_connected = connected;
+    if (type == NETWORK_TYPE_WIFI) {
+        epo_status->is_wifi_connected = connected;
+    } else {
+        epo_status->is_wifi_connected = false;
+    }
+
+    if (mnld_is_gps_or_ofl_started()) {
+        epo_read_cust_config();
+        if (connected && 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();
+        }
+    } else if (type == NETWORK_TYPE_WIFI) {
+        epo_read_cust_config();
+        if (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;
+            epo_downloader_start();
+        }
+    }
+}
+
+void hal_start_gps_trigger_epo_download() {
+    mnl_epo_status* epo_status = &g_mnld_ctx.epo_status;
+    LOGD("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("available=%d apn=[%s]", available, apn);
+    mnl2agps_update_network_availability(available, apn);
+}
+
+static void hal_set_gps_measurement(bool enabled, bool enableFullTracking) {
+    LOGD("enabled=%d, flag=%d", enabled, enableFullTracking);
+    g_mnld_ctx.gps_status.is_gps_meas_enabled = enabled;
+    // TODO: set parameter to MNL
+}
+
+static void hal_set_gps_navigation(bool enabled) {
+    LOGD("enabled=%d", enabled);
+    g_mnld_ctx.gps_status.is_gps_navi_enabled = enabled;
+}
+
+static void hal_set_vzw_debug(bool enabled) {
+    LOGD("enabled=%d", enabled);
+    mnl2agps_vzw_debug_screen_enable(enabled);
+}
+
+static void hal_update_gnss_config(const char* config_data, int length) {
+    int ret = mnl2agps_update_configuration(config_data, length);
+    LOGD("length=%d, ret=%d", length, ret);
+}
+
+static hal2mnl_interface g_hal2mnl_interface = {
+    hal_reboot,
+    hal_gps_init,
+    hal_gps_start,
+    hal_gps_stop,
+    hal_gps_cleanup,
+    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_measurement,
+    hal_set_gps_navigation,
+    hal_set_vzw_debug,
+    hal_update_gnss_config,
+#if defined(__LINUX_OS__)
+    hal_send_pmtk,
+#endif
+};
+
+/*****************************************
+AGPSD -> MNL
+*****************************************/
+#ifdef MTK_AGPS_SUPPORT
+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;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static void agps_open_gps_req(int show_gps_icon) {
+    LOGW("agps_open_gps_req  show_gps_icon=%d", show_gps_icon);
+    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;
+    mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+}
+
+static void agps_close_gps_req() {
+    LOGW("agps_close_gps_req");
+    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);
+}
+
+static void agps_reset_gps_req(int flags) {
+    LOGW("agps_reset_gps_req  flags=0x%x", flags);
+    if (flags == 0) {
+        mnl2agps_reset_gps_done();
+        return;
+    }
+    g_mnld_ctx.gps_status.delete_aiding_flag |= 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_session_done() {
+    LOGW("agps_session_done");
+    // TODO libmnl.so
+    gps_controller_agps_session_done();
+}
+
+static void agps_ni_notify(int session_id, 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 requestorId[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(requestorId, 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);
+
+    mnl2hal_request_ni_notify(session_id, type, requestorId, clientName,
+        NI_ENCODING_TYPE_UCS2, NI_ENCODING_TYPE_UCS2);
+}
+
+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;
+    mnl2hal_request_data_conn(addr);
+}
+
+static void agps_data_conn_release() {
+    LOGD("agps_data_conn_release");
+    mnl2hal_release_data_conn();
+}
+
+static void agps_set_id_req(int flags) {
+    LOGD("agps_set_id_req  flags=%d", flags);
+    mnl2hal_request_set_id(flags);
+}
+
+static void agps_ref_loc_req(int flags) {
+    LOGD("agps_ref_loc_req  flags=%d", flags);
+    mnl2hal_request_ref_loc(flags);
+}
+
+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;
+          mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct));
+    }
+}
+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;
+         mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct));
+    }
+
+}
+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;
+         mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct));
+    }
+
+}
+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;
+         mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct));
+    }
+
+}
+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;
+         mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct));
+    }
+
+}
+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;
+         mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct));
+    }
+
+}
+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;
+         mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct));
+    }
+
+}
+static void agps_location(mnl_agps_agps_location* location) {
+    if (mtk_gps_log_is_hide() == 0) {
+        LOGD("agps_location  lat,lng %f,%f acc=%f used=%d",
+            location->latitude, location->longitude, location->accuracy, location->accuracy_used);
+    }
+
+    gps_location loc;
+    memset(&loc, 0, sizeof(loc));
+    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;
+    }
+    mnl2hal_location(loc);
+    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 = 0;
+    c2k_cell_location.started = 1;
+    if (mtk_gps_log_is_hide() == 0) {
+        LOGD("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);
+    }
+}
+
+static void agps_ni_notify2(int session_id,
+    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);
+    mnl2hal_request_ni_notify(session_id, type, requestor_id, client_name, requestor_id_encoding, client_name_encoding);
+}
+
+static void agps_data_conn_req2(struct sockaddr_storage* addr, int is_emergency) {
+    LOGD("agps_data_conn_req2  is_emergency=%d", is_emergency);
+    UNUSED(is_emergency);
+    mnl2hal_request_data_conn(*addr);
+}
+#endif
+
+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;
+
+    // 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;
+
+    sprintf(pmtk_str, "$PMTK764,0,0,0");
+    sprintf(tmp, ",%d", gnss_num);
+    strncat(pmtk_str, tmp, PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+
+    if (agps_cap) {
+        strncat(pmtk_str, ",0,128", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+    }
+    if (agalileo_cap) {
+        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);
+        mnl2agps_pmtk(pmtk_str);
+    }
+}
+
+#ifdef MTK_AGPS_SUPPORT
+static void vzw_debug_screen_output(const char* str) {
+    LOGD("vzw_debug_screen_output  str=%s", str);
+    mnl2hal_vzw_debug_screen_output(str);
+}
+
+static agps2mnl_interface g_agps2mnl_interface = {
+    agps_reboot,
+    agps_open_gps_req,
+    agps_close_gps_req,
+    agps_reset_gps_req,
+    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_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
+};
+#endif
+
+/*****************************************
+META -> MNL
+*****************************************/
+static void meta_req_gnss_location(int source) {
+    LOGW("meta_req_gnss_location source: %d", source);
+    factory_mnld_gps_start();
+}
+
+static void meta_cancel_gnss_location(int source) {
+    LOGW("meta_cancel_gnss_location source: %d", source);
+    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", data);
+            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 void *)&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 Debug2MnldInterface_callbacks g_debug2mnl_callbacks = {
+    debug_req_mnld_message
+};
+/////// end of debug
+
+/*static void flp2mnl_flp_reboot() {
+    LOGW("flp2mnl_flp_reboot");
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    flp->gps_used = false;
+    flp->need_open_ack = false;
+    flp->need_close_ack = false;
+    flp->need_reset_ack = false;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static void flp2mnl_gps_start() {
+    LOGW("flp2mnl_gps_start\n");
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    flp->gps_used = true;
+    flp->need_open_ack = true;  // need to confirm flp deamon
+    flp->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+}
+
+static void flp2mnl_gps_stop() {
+    LOGW("flp2mnl_gps_stop");
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    flp->gps_used = false;
+    flp->need_open_ack = false;
+    flp->need_close_ack = true;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static int flp2mnl_flp_lpbk(char *buff, int len) {
+    int ret = 0;
+    if (-1 == mnl2flp_data_send((UINT8 *)buff, len)) {
+        LOGE("[FLP2MNLD]Send to HAL failed, %s\n", strerror(errno));
+        ret = -1;
+    }
+    else {
+        LOGD("[FLP2MNLD]Send to HAL successfully\n");
+    }
+    return ret;
+}
+
+static int flp2mnl_flp_data(MTK_FLP_OFFLOAD_MSG_T *prMsg) {
+    LOGD("[FLP2MNLD]to connsys: len=%d\n", prMsg->length);
+    if (prMsg->length > 0 && prMsg->length <= OFFLOAD_PAYLOAD_LEN) {
+        mtk_gps_ofl_send_flp_data((UINT8 *)&prMsg->data[0], prMsg->length);
+    } else {
+        LOGD("[FLP2MNLD]to connsys: length is invalid\n");
+    }
+    return 0;
+}
+*/
+
+static int mnld_flp_attach() {
+    LOGD("mnld_flp_attach");
+    if (-1 == mnld_flp_attach_done()) {
+        LOGE("Send attach done to FLP failed\n");
+    } else {
+        LOGD("Send attach done to FLP succeed\n");
+    }
+    return 0;
+}
+
+static void mnld_flp_hbd_gps_open() {
+    LOGD("mnld_flp_hbd_gps_open\n");
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    flp->gps_used = true;
+    flp->need_open_ack = true;  // need to confirm flp deamon
+    flp->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+}
+
+static void mnld_flp_hbd_gps_close() {
+    LOGD("mnld_flp_hbd_gps_close");
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    flp->gps_used = false;
+    flp->need_open_ack = false;
+    flp->need_close_ack = true;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static void mnld_flp_ofl_link_open() {
+    LOGD("mnld_flp_ofl_link_open\n");
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    flp->gps_used = true;
+    flp->need_open_ack = true;  // need to confirm flp deamon
+    flp->need_close_ack = false;
+    mnld_flp_session.type = MNLD_FLP_CAPABILITY_OFL_MODE;
+    mnld_fsm(GPS_EVENT_OFFLOAD_START, 0, 0, NULL);
+}
+
+static void mnld_flp_ofl_link_close() {
+    LOGD("mnld_flp_ofl_link_close");
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    flp->gps_used = false;
+    flp->need_open_ack = false;
+    flp->need_close_ack = true;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static int mnld_flp_ofl_link_send(MTK_FLP_MNL_MSG_T *prMsg) {
+    LOGD("mnld_flp_ofl_link_send to connsys: len=%d,session_id=%u\n", prMsg->length, prMsg->session);
+    if (prMsg->session == mnld_flp_session.id) {
+        if (prMsg->length > 0 && prMsg->length <= OFFLOAD_PAYLOAD_LEN) {
+            mtk_gps_ofl_send_flp_data((UINT8 *)&prMsg->data[0], prMsg->length);
+        } else {
+            LOGW("mnld_flp_ofl_link_send to connsys: length is invalid\n");
+        }
+    } else {
+        LOGW("session id doesn't match\n");
+    }
+    return 0;
+}
+
+static flp2mnl_interface g_flp2mnl_interface = {
+    mnld_flp_attach,
+    mnld_flp_hbd_gps_open,
+    mnld_flp_hbd_gps_close,
+    mnld_flp_ofl_link_open,
+    mnld_flp_ofl_link_close,
+    mnld_flp_ofl_link_send
+};
+
+/*
+static void gfc2mnl_gfc_reboot() {
+    LOGW("gfc2mnl_gfc_reboot");
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    geofence->gps_used = false;
+    geofence->need_open_ack = false;
+    geofence->need_close_ack = false;
+    geofence->need_reset_ack = false;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static void gfc2mnl_gps_start() {
+    LOGW("gfc2mnl_gps_start\n");
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    geofence->gps_used = true;
+    geofence->need_open_ack = true;  // need to confirm flp deamon
+    geofence->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+}
+
+static void gfc2mnl_gps_stop() {
+    LOGW("gfc2mnl_gps_stop");
+    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 int mnld_gfc_attach() {
+    LOGD("mnld_gfc_attach");
+    if (-1 == mnld_gfc_attach_done()) {
+        LOGE("Send attach done to GFC failed\n");
+    } else {
+        LOGD("Send attach done to GFC succeed\n");
+    }
+    return 0;
+}
+
+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 void mnld_gfc_ofl_link_open() {
+    LOGD("mnld_gfc_ofl_link_open\n");
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    geofence->gps_used = true;
+    geofence->need_open_ack = true;  // need to confirm flp deamon
+    geofence->need_close_ack = false;
+    mnld_gfc_session.type = MNLD_GFC_CAPABILITY_OFL_MODE;
+    mnld_fsm(GPS_EVENT_OFFLOAD_START, 0, 0, NULL);
+}
+
+static void mnld_gfc_ofl_link_close() {
+    LOGD("mnld_gfc_ofl_link_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 int mnld_gfc_ofl_link_send(MTK_GFC_MNL_MSG_T *prMsg) {
+    LOGD("mnld_gfc_ofl_link_send to connsys: len=%d,session_id=%u\n", prMsg->length, prMsg->session);
+    if (prMsg->session == mnld_gfc_session.id) {
+        if (prMsg->length > 0 && prMsg->length <= OFFLOAD_PAYLOAD_LEN) {
+            mtk_gps_ofl_send_flp_data((UINT8 *)&prMsg->data[0], prMsg->length);
+        } else {
+            LOGW("mnld_gfc_ofl_link_send to connsys: length is invalid\n");
+        }
+    } else {
+        LOGW("session id doesn't match\n");
+    }
+    return 0;
+}
+
+static gfc2mnl_interface g_gfc2mnl_interface = {
+    mnld_gfc_attach,
+    mnld_gfc_hbd_gps_open,
+    mnld_gfc_hbd_gps_close,
+    mnld_gfc_ofl_link_open,
+    mnld_gfc_ofl_link_close,
+    mnld_gfc_ofl_link_send
+};
+
+/*
+void flp_test2mnl_gps_start() {
+    LOGD("flp_test2mnl_gps_start\n");
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    flp_test->gps_used = true;
+    flp_test->need_open_ack = false;  // need to confirm flp deamon
+    flp_test->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+}
+
+void flp_test2mnl_gps_stop() {
+    LOGD("flp_test2mnl_gps_stop");
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    flp_test->gps_used = false;
+    flp_test->need_open_ack = false;
+    flp_test->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+extern int ofl_lpbk_tst_start;
+extern int ofl_lpbk_tst_size;
+
+static int flp_test2mnl_flp_lpbk_start() {
+    char tmp_buf[1024];
+    int i;
+
+    LOGD("[OFL]lpbk start!");
+    for (i=0; i < ofl_lpbk_tst_size; i++) {
+        tmp_buf[i] = 0x80;
+    }
+    mtk_gps_ofl_send_flp_data((UINT8 *)&tmp_buf[0], ofl_lpbk_tst_size);
+    ofl_lpbk_tst_start = 1;
+    return 0;
+}
+
+static int flp_test2mnl_flp_lpbk_stop() {
+    LOGD("[OFL]lpbk stop!");
+    ofl_lpbk_tst_start = 0;
+
+    return 0;
+}
+
+#if 0
+static flp_test2mnl_interface g_flp_test2mnl_interface = {
+    flp_test2mnl_gps_start,
+    flp_test2mnl_gps_stop,
+    flp_test2mnl_flp_lpbk_start,
+    flp_test2mnl_flp_lpbk_stop,
+};
+#endif
+*/
+
+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 = false;  // 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);
+}
+
+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) {
+    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));
+    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);
+}
+
+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));
+    switch (cmd) {
+    case GPS2MAIN_EVENT_START_DONE: {
+        int is_assist_req = get_int(buff, &offset, sizeof(buff));
+        LOGI("GPS2MAIN_EVENT_START_DONE  is_assist_req=%d", is_assist_req);
+        mnld_fsm(GPS_EVENT_START_DONE, is_assist_req, 0, NULL);
+        #ifdef MTK_ADR_SUPPORT
+        mnl2adr_open_gps_done();
+        #endif
+        break;
+    }
+    case GPS2MAIN_EVENT_STOP_DONE: {
+        LOGW("GPS2MAIN_EVENT_STOP_DONE");
+        mnld_fsm(GPS_EVENT_STOP_DONE, 0, 0, NULL);
+        break;
+    }
+    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");
+        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
+            mnl2hal_mnld_reboot();
+            mnl2agps_mnl_reboot();
+            mnl2flp_mnld_reboot();
+            mnl2gfc_mnld_reboot();
+            #ifdef MTK_ADR_SUPPORT
+                mnl2adr_mnl_reboot();
+            #endif
+        }
+        break;
+        }
+    case GPS2MAIN_EVENT_UPDATE_LOCATION: {
+        gps_location location;
+        get_binary(buff, &offset, (char*)&location, sizeof(buff), sizeof(gps_location));
+        bool alt_valid = (location.flags & MTK_GPS_LOCATION_HAS_ALT)? true : false;
+        bool source_valid = true;
+        bool source_gnss = true;
+        bool source_nlp = false;
+        bool source_sensor = false;
+        float valid_acc = (location.flags & MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY)? location.h_accuracy : 2000;
+        if (mtk_gps_log_is_hide() == 0) {
+            LOGW("GPS2MAIN_EVENT_UPDATE_LOCATION  lat=%f lng=%f acc=%f",
+                location.lat, location.lng, valid_acc);
+        }
+        LOGD("wait_first_location=%d\n", g_mnld_ctx.gps_status.wait_first_location);
+        mnl2agps_location_sync(location.lat, location.lng, (int)valid_acc, alt_valid, (float)location.alt, source_valid, source_gnss, source_nlp, source_sensor);
+        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
+        }
+        LOGD("location_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;
+    }
+    }
+    return 0;
+}
+
+/*****************************************
+Threads
+*****************************************/
+static void mnld_main_thread_timeout() {
+    if (mnld_timeout_ne_enabled() == false) {
+        LOGE("mnld_main_thread_timeout() dump and exit.");
+        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_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_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_block_exit();
+    } else {
+        LOGE("mnld_gps_reset_timeout() crash here for debugging");
+        CRASH_TO_DEBUG();
+    }
+}
+
+static void mnld_gps_switch_ofl_mode_timeout() {
+    if (is_all_hbd_gps_client_exit()) {
+        LOGD("switch to offload mode timer timeout, flp user prepare to stop gps");
+        mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+        mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+        //flp
+        flp->gps_used = false;
+        flp->need_open_ack = false;
+        flp->need_close_ack = false;
+        //geofence
+        geofence->gps_used = false;
+        geofence->need_open_ack = false;
+        geofence->need_close_ack = false;
+        mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+    } else {
+        LOGD("switch to offload mode timer timeout. But some HBD user exist, so not stop gps");
+    }
+}
+
+void gps_mnld_restart_mnl_process(void) {
+    LOGD("gps_mnld_restart_mnl_process\n");
+    mnld_gps_start_nmea_timeout();
+}
+
+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);
+    mnl2hal_request_nlp((bool)src);
+}
+
+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];
+    memset(&events, 0, sizeof(events));
+    UNUSED(arg);
+
+    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;
+    }
+#ifdef MTK_AGPS_SUPPORT
+    int fd_agps = g_mnld_ctx.fds.fd_agps;
+#endif
+    int fd_hal = g_mnld_ctx.fds.fd_hal;
+    int fd_flp = g_mnld_ctx.fds.fd_flp;
+    int fd_flp_test = g_mnld_ctx.fds.fd_flp_test;
+    int fd_geofence = g_mnld_ctx.fds.fd_geofence;
+    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_mtklogger_client = g_mnld_ctx.fds.fd_mtklogger_client = -1;
+    int fd_meta = g_mnld_ctx.fds.fd_meta;
+    int fd_debug = g_mnld_ctx.fds.fd_debug;
+#ifdef MTK_AGPS_SUPPORT
+    if (epoll_add_fd(epfd, fd_agps) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_agps failed");
+        return 0;
+    }
+#endif
+    if (epoll_add_fd(epfd, fd_hal) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_hal failed");
+        return 0;
+    }
+    if (epoll_add_fd(epfd, fd_flp) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_flp failed");
+        return 0;
+    }
+    if (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_flp_test) == -1) {
+    //    LOGE("mnld_main_thread() epoll_add_fd() failed for fd_flp_test failed");
+    //    return 0;
+    //}
+    if (epoll_add_fd(epfd, fd_at_cmd) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_at_cmd failed");
+        return 0;
+    }
+    if (epoll_add_fd(epfd, fd_int) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_int failed");
+        return 0;
+    }
+    if (epoll_add_fd(epfd, fd_mtklogger) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_mtklogger failed");
+        return 0;
+    }
+
+    if (epoll_add_fd(epfd, fd_meta) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_meta failed");
+        return 0;
+    }
+
+    if (epoll_add_fd(epfd, fd_debug) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_debug failed");
+        return 0;
+    }
+
+    while (1) {
+        int i;
+        int n = 0;
+        #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;
+            }
+        }
+        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) {
+                if (events[i].events & EPOLLIN) {
+                    LOGD("hal2mnl_hdlr msg");
+                    hal2mnl_hdlr(fd_hal, &g_hal2mnl_interface);
+                }
+            } else if (events[i].data.fd == fd_flp) {
+                if (events[i].events & EPOLLIN) {
+                    LOGD("flp2mnl_hdlr msg");
+                    mtk_hal2flp_main_hdlr(fd_flp, &g_flp2mnl_interface);
+                }
+            }  else if (events[i].data.fd == fd_geofence) {
+                if (events[i].events & EPOLLIN) {
+                    LOGD("gfc2mnl_hdlr msg");
+                    mtk_hal2gfc_main_hdlr(fd_geofence, &g_gfc2mnl_interface);
+                }
+            } else if (events[i].data.fd == fd_flp_test) {
+                    if (events[i].events & EPOLLIN) {
+                    LOGD("fd_flp_test msg");
+                    //flp_test2mnl_hdlr(fd_flp_test, &g_flp_test2mnl_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("main_event_hdlr msg");
+                    main_event_hdlr(fd_int);
+                }
+            } else if (events[i].data.fd == fd_mtklogger) {
+                if (events[i].events & EPOLLIN) {
+                        struct sockaddr addr;
+                        socklen_t alen = sizeof(addr);
+                        if (fd_mtklogger_client >= 0) {  // mtklogger exeception exit,  then reconnect
+                            LOGD("mtklogger old client_fd = %d, epoll_del it\n", fd_mtklogger_client);
+                            epoll_del_fd(epfd, fd_mtklogger_client);
+                            close(fd_mtklogger_client);
+                            g_mnld_ctx.fds.fd_mtklogger_client = -1;
+                        }
+                        fd_mtklogger_client = accept(fd_mtklogger, &addr, &alen);
+                        if (fd_mtklogger_client < 0) {
+                            LOGE("accept failed, %s", strerror(errno));
+                            return 0;
+                        }
+                        g_mnld_ctx.fds.fd_mtklogger_client = fd_mtklogger_client;
+                        LOGD("mtklogger new client fd: %d", fd_mtklogger_client);
+                        if (epoll_add_fd(epfd, fd_mtklogger_client) == -1) {
+                            LOGE("mnld_main_thread() epoll_add_fd() failed for fd_mtklogger_client failed");
+                            return 0;
+                    }
+                }
+            } else if (events[i].data.fd == fd_mtklogger_client) {
+                if ((events[i].events & (EPOLLERR|EPOLLHUP)) != 0) {
+                    LOGE("wait fd_mtklogger_client EPOLLERR|EPOLLHUP");
+                    epoll_del_fd(epfd, fd_mtklogger_client);
+                    close(fd_mtklogger_client);
+                    fd_mtklogger_client = g_mnld_ctx.fds.fd_mtklogger_client = -1;
+                    break;
+                } else 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_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("debug2mnl_event_hdlr msg");
+                    Debug2MnldInterface_receiver_read_and_decode(fd_debug, &g_debug2mnl_callbacks);
+                }
+            } else {
+                LOGE("mnld_main_thread() unknown fd=%d",
+                    events[i].data.fd);
+            }
+        }
+        stop_timer(hdlr_timer);
+    }
+    LOGE("mnld_main_thread() exit");
+    return 0;
+}
+
+static 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 = create_hal2mnl_fd();
+    if (g_mnld_ctx.fds.fd_hal < 0) {
+        LOGE("create_hal2mnl_fd() failed");
+        return -1;
+    }
+
+    g_mnld_ctx.fds.fd_flp = create_flphal2mnl_fd();
+    if (g_mnld_ctx.fds.fd_flp < 0) {
+        LOGE("create_flphal2mnl_fd() failed");
+        return -1;
+    }
+    #if 0
+    g_mnld_ctx.fds.fd_flp_test = create_flp_test2mnl_fd();
+    if (g_mnld_ctx.fds.fd_flp_test < 0) {
+        LOGE("create_flp2mnl_fd() failed");
+        return -1;
+    }
+    #endif
+
+    g_mnld_ctx.fds.fd_geofence= create_gfchal2mnl_fd();
+    if (g_mnld_ctx.fds.fd_geofence< 0) {
+        LOGE("create_gfchal2mnl_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(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_mtklogger = create_mtklogger2mnl_fd();
+    if (g_mnld_ctx.fds.fd_mtklogger < 0) {
+        LOGE("create_mtklogger2mnl_fd() failed");
+        return -1;
+    }
+    g_mnld_ctx.fds.fd_meta = mtk_socket_server_bind_local(META_TO_MNLD_SOCKET, SOCK_NS_ABSTRACT);
+    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;
+    }
+
+    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);
+    // init timers
+    g_mnld_ctx.gps_status.timer_start = init_timer(mnld_gps_start_timeout);
+    if (g_mnld_ctx.gps_status.timer_start == (timer_t)-1) {
+        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 == (timer_t)-1) {
+        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 == (timer_t)-1) {
+        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 == (timer_t)-1) {
+        LOGE("init_timer(gps_mnld_restart_mnl_process) failed");
+        return -1;
+    }
+
+    g_mnld_ctx.gps_status.timer_switch_ofl_mode = init_timer(mnld_gps_switch_ofl_mode_timeout);
+    if (g_mnld_ctx.gps_status.timer_switch_ofl_mode == (timer_t)-1) {
+        LOGE("init_timer(mnld_gps_switch_ofl_mode_timeout) failed");
+        return -1;
+    }
+
+    // init threads
+    pthread_create(&pthread_main, NULL, mnld_main_thread, NULL);
+
+    // send the reboot message to the related modules
+    mnl2hal_mnld_reboot();
+    mnl2agps_mnl_reboot();
+    mnl2flp_mnld_reboot();
+    mnl2gfc_mnld_reboot();
+    Mnld2DebugInterface_mnldUpdateReboot(&g_mnld_ctx.fds.fd_debug_client);
+    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() {
+    if (mnld_is_gps_started() ||
+        g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_OFL_STARTING ||
+        g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_OFL_STARTED) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+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;
+    }
+}
+
+bool mnld_is_epo_download_finished() {
+    if (g_mnld_ctx.epo_status.is_epo_downloading == false) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+
+void daemon_parse_commandline(int argc, char *argv[])
+{
+    for (int 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) {
+    daemon_parse_commandline(argc, argv);
+#ifdef CONFIG_GPS_MT3303
+    LOGI("mnld version=2017/08/05 19:39 start");
+#else
+    LOGI("mnld version=0.03, offload ver=%s\n", OFL_VER);
+#endif
+    memset(&g_mnld_ctx, 0, sizeof(g_mnld_ctx));
+    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) {
+        gps_epo_type = 0;   // G+G
+    } else {
+        gps_epo_type = 0;   // Default is G+G
+    }
+    /*get gps_epo_type end*/
+    mnld_offload_check_capability();
+    if (mnl_init()) {
+        LOGE("mnl_init: %d (%s)\n", errno, strerror(errno));
+    }
+    flp_mnl_emi_download();
+#ifdef CONFIG_GPS_MT3303
+    mt3333_controller_init();
+#endif
+    if (!strncmp(argv[2], "meta", 4) || !strncmp(argv[2], "factory", 4)
+        || !strncmp(argv[0], "test", 4) || !strncmp(argv[2], "PDNTest", 7)) {
+        mnld_factory_test_entry(argc, argv);
+    } else {
+        gps_control_init();
+        epo_downloader_init();
+        qepo_downloader_init();
+        mtknav_downloader_init();
+        op01_log_init();
+        mpe_function_init(0);
+        flp_monitor_init();
+        mnld_init();
+#ifdef __TEST__
+        mnld_test_start();
+#else
+        block_here();
+        //Will go here after calling mnld_block_exit
+        //mnld_dump_exit();
+#endif
+    }
+#ifdef CONFIG_GPS_MT3303
+        LOGE("mnld version=2017/06/25 17:27 end");
+#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/mtk_mnld/mnld_entity/src/mnld_uti.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnld_uti.c
new file mode 100644
index 0000000..207beb2
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnld_uti.c
@@ -0,0 +1,358 @@
+/* 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>
+#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>
+
+#include "mnl_agps_interface.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#if defined(__ANDROID_OS__)
+#include <private/android_filesystem_config.h>
+#endif
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#include <cutils/properties.h>
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnld_uti"
+#endif
+
+extern int mtk_gps_sys_init();
+#if MTK_GPS_NVRAM
+extern ap_nvram_gps_config_struct stGPSReadback;
+#endif
+
+/*****************************************************************************/
+int read_NVRAM() {
+    int ret = 0;
+    ret = mtk_gps_sys_init();
+    #if MTK_GPS_NVRAM
+    if (strcmp(stGPSReadback.dsp_dev, "/dev/stpgps") == 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 %zd, error message is %s\n", bytewrite, strerror(errno));
+        return 1;
+    }
+}
+
+int hand_shake() {
+#if MTK_GPS_NVRAM
+    int fd;
+#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() {
+#ifndef CONFIG_GPS_MT3303
+    int get_time = 20;
+    int res;
+#if ANDROID_MNLD_PROP_SUPPORT
+    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;
+    }
+
+    /* detect if there is 3332, yes set GPS property to 3332,
+    then else read from combo chip to see which GPS chip used */
+    res = confirm_if_3332();    /* 0 means 3332, 1 means not 3332, other value means error */
+    if (res == 0) {
+        strncpy(chip_id, "0x3332",sizeof(chip_id));
+        LOGD("we get MT3332\n");
+    }
+#else
+    strncpy(chip_id, "0x6630",sizeof(chip_id));
+#endif
+#else
+    strncpy(chip_id, "0x3303",sizeof(chip_id));
+#endif
+    LOGI("exit chip_detector\n");
+    LOGI("combo_chip_id is %s\n", chip_id);
+    return;
+}
+
+int buff_get_int(char* buff, int* offset) {
+    int ret = *((int*)&buff[*offset]);
+    *offset += 4;
+    return ret;
+}
+
+int buff_get_string(char* str, 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(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(void* input, int size, char* buff, int* offset) {
+    memcpy(&buff[*offset], input, size);
+    *offset += size;
+}
+
+void buff_get_struct(char* output, int size, char* buff, int* offset) {
+    memcpy(output, &buff[*offset], size);
+    *offset += size;
+}
+
+int buff_get_binary(void* output, 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;
+}
+
+int mnl_init_gps_data_path(const char* data_path, const int length){
+    int index = 0;
+    char dir[MNL_GPS_DATA_PATH_MAX_LENGTH] = {0};
+
+    for(index=2;(index<length)&&data_path[index];index++)
+    {
+        if(data_path[index] == '/'){
+            memset(dir, 0, MNL_GPS_DATA_PATH_MAX_LENGTH);
+            strncpy(dir, data_path, index+1);
+            if (mkdir(dir, 00775) < 0)
+            {
+                if (errno == EEXIST)
+                {
+                    LOGD("directory %s existed.\n", dir);
+                }else{
+                    LOGE("mkdir (%s) failed: %s\n", dir, strerror(errno));
+                    goto fail;
+                }
+            }else{
+                LOGD("mkdir (%s) succeed\n", dir);
+            }
+        }
+    }
+    return 0;
+fail:
+    return -1;
+}
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/mpe.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mpe.c
new file mode 100644
index 0000000..fedd486
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mpe.c
@@ -0,0 +1,350 @@
+/* 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_auto_log.h"
+#include "nmea_parser.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "MPE"
+#endif
+
+MPECallBack gMpeCallBackFunc = NULL;
+static int g_fd_mpe = -1;
+static int g_fd_mpe2mnl = -1;
+extern unsigned char gMpeThreadExist;
+
+int mnl2adr_gps_open(void) {
+    LOGD("mnl2adr_gps_open");
+    char buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_ADR_TYPE_MNL2ADR_GPS_OPEN);
+    put_int(buff, &offset, 0);//No payload, length is 0
+
+    return safe_sendto(MNLD_MNL2ADR_SOCKET, buff, offset);
+}
+
+int mnl2adr_gps_close(void) {
+    LOGD("mnl2adr_gps_close");
+    char buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_ADR_TYPE_MNL2ADR_GPS_CLOSE);
+    put_int(buff, &offset, 0);//No payload, length is 0
+
+    return safe_sendto(MNLD_MNL2ADR_SOCKET, buff, offset);
+}
+
+int mnl2adr_mnl_reboot(void) {
+    LOGD("mnl2adr_mnl_reboot");
+    char buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_ADR_TYPE_MNL2ADR_MNL_REBOOT);
+    put_int(buff, &offset, 0);//No payload, length is 0
+
+    return safe_sendto(MNLD_MNL2ADR_SOCKET, buff, offset);
+}
+
+int mnl2adr_open_gps_done(void) {
+    LOGD("mnl2adr_open_gps_done");
+    char buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_ADR_TYPE_MNL2ADR_GPS_OPEN_DONE);
+    put_int(buff, &offset, 0);//No payload, length is 0
+
+    return safe_sendto(MNLD_MNL2ADR_SOCKET, buff, offset);
+}
+
+int mnl2adr_close_gps_done(void) {
+    LOGD("mnl2adr_close_gps_done");
+    char buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_ADR_TYPE_MNL2ADR_GPS_CLOSE_DONE);
+    put_int(buff, &offset, 0);//No payload, length is 0
+
+    return safe_sendto(MNLD_MNL2ADR_SOCKET, buff, offset);
+}
+
+char nmea_sbuff[MNL_MPE_NMEA_MAX_SIZE] = {0};
+
+int mnl2adr_send_nmea_data(const char * nmea_buffer, const UINT32 length) {
+    //LOGD("len:%d, %s", length, nmea_buffer);
+    int offset = 0;
+    if(length < (MNL_MPE_NMEA_MAX_SIZE - 2)) {
+        memset(nmea_sbuff, 0, MNL_MPE_NMEA_MAX_SIZE);
+        put_int(nmea_sbuff, &offset, MNL_ADR_TYPE_MNL2ADR_NMEA_DATA);
+        put_int(nmea_sbuff, &offset, length);
+        put_binary(nmea_sbuff, &offset, nmea_buffer, length);
+
+        return safe_sendto(MNLD_MNL2ADR_SOCKET, nmea_sbuff, offset);
+    } else {
+        LOGE("over length(%d):%d", MNL_MPE_NMEA_MAX_SIZE, length);
+        return -1;
+    }
+}
+
+int mnl2mpe_set_log_path(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;
+        }
+
+        case MNL_ADR_TYPE_ADR2MNL_NMEA_DATA: {
+            char nmea[MNL_MPE_NMEA_MAX_SIZE] = {0};
+            get_binary(buff, &offset, nmea, MNL_MPE_NMEA_MAX_SIZE, MNL_MPE_NMEA_MAX_SIZE);
+
+            mtk_mnl_nmea_parser_process(nmea, length);
+            break;
+        }
+        case MNL_ADR_TYPE_ADR2MNL_PMTK_CMD: {
+            char pmtk[MNL_MPE_NMEA_MAX_SIZE];
+            get_binary(buff, &offset, pmtk, MNL_MPE_NMEA_MAX_SIZE, sizeof(pmtk));
+            gps_controller_rcv_pmtk(pmtk);
+            break;
+        }
+        default: {
+           LOGE("unknown cmd=%d\n", type);
+           break;
+       }
+    }
+    return 0;
+}
+
+int mtk_gps_mnl_trigger_mpe(void) {
+    int ret = MTK_GPS_ERROR;
+    #ifdef MTK_ADR_SUPPORT
+    UINT16 mpe_len;
+    char mnl2mpe_buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+
+    mpe_len = mtk_gps_set_mpe_info((UINT8 *)mnl2mpe_buff);
+    LOGD("mpemsg len=%d\n", mpe_len);
+
+    if (mpe_len > 0) {
+        if (!(mpe_sys_get_mpe_conf_flag() & MPE_CONF_MPE_ENABLE)) {
+            LOGE("MPE not enable\n");
+            return MTK_GPS_ERROR;
+        }
+        safe_sendto(MNLD_MPE_SOCKET, mnl2mpe_buff, MNL_MPE_MAX_BUFF_SIZE);
+        ret = MTK_GPS_SUCCESS;
+    }
+    #endif
+    return ret;
+}
+
+/*static void mpe_thread_timeout() {
+    if (mnld_timeout_ne_enabled() == false) {
+        LOGE("mpe_thread_timeout() dump and exit.");
+        mnld_block_exit();
+    } else {
+        LOGE("mpe_thread_timeout() crash here for debugging");
+        CRASH_TO_DEBUG();
+    }
+}*/
+
+int mnl_mpe_thread_init() {
+    int ret;
+    LOGD("mpe init");
+
+    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;
+}
+
+static void* mpe_main_thread(void *arg) {
+    #define MAX_EPOLL_EVENT 50
+    struct epoll_event events[MAX_EPOLL_EVENT];
+    memset(&events, 0, sizeof(events));
+    UNUSED(arg);
+
+    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 (g_fd_mpe > 0) {
+        if (epoll_add_fd(epfd, g_fd_mpe) == -1) {
+            LOGE("epoll_add_fd() failed for g_fd_epo failed");
+            return 0;
+        }
+    } else {
+        LOGW("g_fd_mpe invalid");
+    }
+
+    if (g_fd_mpe2mnl > 0) {
+        if (epoll_add_fd(epfd, g_fd_mpe2mnl) == -1) {
+            LOGE("epoll_add_fd() failed for g_fd_epo failed");
+            return 0;
+        }
+    } else {
+        LOGW("g_fd_mpe2mnl invalid");
+    }
+
+    while (1) {
+        int i;
+        int n;
+        LOGD("wait");
+        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;
+            }
+        }
+        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 if (events[i].data.fd == g_fd_mpe2mnl) {
+                if (events[i].events & EPOLLIN) {
+                    char mpe2mnl_buff[MNL_MPE_NMEA_MAX_SIZE] = {0};
+                    int read_len = 0;
+                    read_len = safe_recvfrom(g_fd_mpe2mnl, mpe2mnl_buff, sizeof(mpe2mnl_buff));
+                    if (read_len <= 0) {
+                        LOGE("safe_recvfrom() failed read_len=%d", read_len);
+                    } else {
+                        mpe2mnl_hdlr(mpe2mnl_buff);
+                    }
+                }
+            } else {
+                LOGE("unknown fd=%d", events[i].data.fd);
+            }
+        }
+    }
+
+    LOGE("exit");
+    pthread_exit(NULL);
+    return 0;
+}
+
+int mpe_function_init(int self_recv) {
+    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 (self_recv) {
+        g_fd_mpe = socket_bind_udp(MNLD_MPE_SOCKET);
+    } else {
+        g_fd_mpe = -1;
+    }
+    g_fd_mpe2mnl = socket_bind_udp(MNLD_ADR2MNL_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/mtk_mnld/mnld_entity/src/mt3333_controller.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mt3333_controller.c
new file mode 100644
index 0000000..8eae7a4
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mt3333_controller.c
@@ -0,0 +1,1633 @@
+#ifdef CONFIG_GPS_MT3303
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <errno.h>
+#include <pthread.h>
+#include <termios.h>
+#include <time.h>
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#include "mt3333_controller.h"
+#include "mnld.h"
+#include "qepo.h"
+#include "epo.h"
+#include "mnl_common.h"
+#include "mtk_gps_sys_fp.h"
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "flashtool.h"
+#include "gps_controller.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mt3333_controller"
+#endif
+
+static int g_fd_mt3333_controller;
+int g_fd_mt3333_data;
+static struct tm g_mt3333_time_st;
+static int nmea_1st_after_powerongps=1;
+int factory_meta_exist=0;
+int is_ygps_delete_data = 0;
+
+extern int gps_epo_type; 
+extern int gps_epo_download_days;
+extern MTK_GPS_SYS_FUNCTION_PTR_T porting_layer_callback;
+extern MNL_CONFIG_T mnld_cfg;
+extern MNL_CONFIG_T mnl_config;
+extern int first_entry;
+
+/**
+ * Utc2GpsTime converts UTC time to GPS time
+ *
+ * @param u2Yr, u2Mo, u2Day, u2Hr, u2Min, dfSec: UTC time
+ * @param pi2Wn GPS week
+ * @param pdfTow GPS time
+
+ *
+ * @return None
+ */
+void __mt3333_controller_Utc2GpsTime(unsigned int u2Yr, unsigned int u2Mo, unsigned int u2Day,
+                 unsigned int u2Hr, unsigned int u2Min, unsigned int dfSec,
+                 unsigned short* pi2Wn, unsigned int* pdfTow)
+{
+  int iYearsElapsed;     // Years since 1980.
+  int iDaysElapsed;      // Days elapsed since Jan 5/Jan 6, 1980.
+  int iLeapDays;         // Leap days since Jan 5/Jan 6, 1980.
+  int i;
+  // Number of days into the year at the start of each month (ignoring leap
+  // years).
+  unsigned short  doy[12] = {0,31,59,90,120,151,181,212,243,273,304,334};
+
+  iYearsElapsed = u2Yr - 1980;
+
+
+  i = 0;
+  iLeapDays = 0;
+  while(i <= iYearsElapsed)
+  {
+    if((i % 100) == 20)
+    {
+      if((i % 400) == 20)
+      {
+        iLeapDays++;
+      }
+    }
+    else if((i % 4) == 0)
+    {
+      iLeapDays++;
+    }
+    i++;
+  }
+
+/*  iLeapDays = iYearsElapsed / 4 + 1; */
+  if((iYearsElapsed % 100) == 20)
+  {
+    if(((iYearsElapsed % 400) == 20) && (u2Mo <= 2))
+    {
+      iLeapDays--;
+    }
+  }
+  else if(((iYearsElapsed % 4) == 0) && (u2Mo <= 2))
+  {
+    iLeapDays--;
+  }
+  iDaysElapsed = iYearsElapsed * 365 + doy[u2Mo - 1] + u2Day + iLeapDays - 6;
+
+  // Convert time to GPS weeks and seconds
+  *pi2Wn = iDaysElapsed / 7;
+  *pdfTow = (iDaysElapsed % 7) * 86400
+            + u2Hr * 3600 + u2Min * 60 + dfSec;
+}
+
+int mt3333_controller_Utc2GpsTime(unsigned short* pi2Wn, unsigned int* pdfTow, unsigned int* sys_time){
+    
+    struct tm *time_st = NULL;
+#if 0
+    long long time_s = 0;
+
+    time_s = time/1000;
+    time_st = localtime(&time_s);
+    g_mt3333_time_st = *time_st;
+#else
+    time_t         now;
+    extern time_t epo_get_now_time();
+    //now = time(NULL);
+    now = epo_get_now_time();
+    gmtime_r(&now, &g_mt3333_time_st);
+    time_st = &g_mt3333_time_st;
+#endif
+    
+    LOGD("%d-%d-%d %d:%d:%d\n", 
+        time_st->tm_year + 1900, time_st->tm_mon + 1, time_st->tm_mday, 
+        time_st->tm_hour, time_st->tm_min, time_st->tm_sec);
+    __mt3333_controller_Utc2GpsTime(time_st->tm_year + 1900, time_st->tm_mon + 1, time_st->tm_mday, 
+        time_st->tm_hour, time_st->tm_min, time_st->tm_sec,
+        pi2Wn,pdfTow);
+    *sys_time = now;
+    return 0;
+}
+
+
+#if 1
+
+typedef struct __baudrate_mpping{
+    unsigned int        ul_baud_rate;
+    speed_t            linux_baud_rate;
+}BAUD_RATE_SETTING;
+
+static BAUD_RATE_SETTING speeds_mapping[] = {
+    {0        ,B0        },
+    {50        ,B50        },
+    {75        ,B75        },
+    {110    ,B110        },
+    {134    ,B134,        },
+    {150    ,B150        },
+    {200    ,B200        },
+    {300    ,B300        },
+    {600    ,B600        },
+    {1200    ,B1200        },
+    {1800    ,B1800        },
+    {2400    ,B2400        },
+    {4800    ,B4800        },
+    {9600    ,B9600        },
+    {19200    ,B19200        },
+    {38400    ,B38400        },
+    {57600    ,B57600        },
+    {115200    ,B115200    },
+    {230400    ,B230400    },
+    {460800    ,B460800    },
+    {500000    ,B500000    },
+    {576000    ,B576000    },
+    {921600    ,B921600    },
+    {1000000    ,B1000000    }, 
+    {1152000    ,B1152000    }, 
+    {1500000    ,B1500000    }, 
+    {2000000    ,B2000000    }, 
+    {2500000    ,B2500000    }, 
+    {3000000    ,B3000000    }, 
+    {3500000    ,B3500000    }, 
+    {4000000    ,B4000000    },
+};
+
+static speed_t mt3333_controller_get_speed(unsigned int baudrate) 
+{
+    unsigned int idx;
+    for (idx = 0; idx < sizeof(speeds_mapping)/sizeof(speeds_mapping[0]); idx++){
+        if (baudrate == (unsigned int)speeds_mapping[idx].ul_baud_rate){
+            return speeds_mapping[idx].linux_baud_rate;
+        }
+    }
+    return CBAUDEX;        
+}
+#if 0
+int mt3333_controller_set_baudrate_length_parity_stopbits(int fd, unsigned int new_baudrate, int length, char parity_c, int stopbits)
+{
+    struct termios uart_cfg_opt;
+    speed_t speed;
+    char  using_custom_speed = 0;
+    
+    if(-1==fd)
+        return -1;
+
+    /* Get current uart configure option */
+    if(-1 == tcgetattr(fd, &uart_cfg_opt))
+        return -1;
+
+    tcflush(fd, TCIOFLUSH);
+
+    /* Baud rate setting section */
+    speed = mt3333_controller_get_speed(new_baudrate);
+    if(CBAUDEX != speed){
+        /*set standard buadrate setting*/
+        cfsetospeed(&uart_cfg_opt, speed);
+        cfsetispeed(&uart_cfg_opt, speed);
+        LOGE("Standard baud=%d",new_baudrate);
+    }else{
+        LOGE("Custom baud=%d",new_baudrate);
+        using_custom_speed = 1;
+    }
+    /* Apply baudrate settings */
+    if(-1==tcsetattr(fd, TCSANOW, &uart_cfg_opt))
+        return -1;
+    
+    /* Set time out */
+    uart_cfg_opt.c_cc[VTIME] = 1;
+    uart_cfg_opt.c_cc[VMIN] = 0;
+
+    /*if((ioctl(fd,TIOCGSERIAL,&ss)) < 0)
+        return -1;
+
+    if(using_custom_speed){
+        ss.flags |= ASYNC_SPD_CUST;  
+            ss.custom_divisor = 1<<31|new_baudrate;
+        }else
+            ss.flags &= ~ASYNC_SPD_CUST;    
+
+    if((ioctl(fd, TIOCSSERIAL, &ss)) < 0)
+        return -1;//*/
+
+    /* Data length setting section */
+    uart_cfg_opt.c_cflag &= ~CSIZE;
+    switch(length)
+    {
+    default:
+    case 8:
+        uart_cfg_opt.c_cflag |= CS8;
+        break;
+    case 5:
+        uart_cfg_opt.c_cflag |= CS5;
+        break;
+    case 6:
+        uart_cfg_opt.c_cflag |= CS6;
+        break;
+    case 7:
+        uart_cfg_opt.c_cflag |= CS7;
+        break;
+    }
+
+    /* Parity setting section */
+    uart_cfg_opt.c_cflag &= ~(PARENB|PARODD);
+    switch(parity_c)
+    {
+    default:
+    case 'N':
+    case 'n':
+        uart_cfg_opt.c_iflag &= ~INPCK;
+        break;
+    case 'O':
+    case 'o':
+        uart_cfg_opt.c_cflag |= (PARENB|PARODD);
+        uart_cfg_opt.c_iflag |= INPCK;
+        break;
+    case 'E':
+    case 'e':
+        uart_cfg_opt.c_cflag |= PARENB;
+        uart_cfg_opt.c_iflag |= INPCK;
+        break;
+    }
+
+    /* Stop bits setting section */
+    if(2==stopbits)
+        uart_cfg_opt.c_cflag |= CSTOPB;
+    else
+        uart_cfg_opt.c_cflag &= ~CSTOPB;
+
+    /* Using raw data mode */
+    uart_cfg_opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+    uart_cfg_opt.c_iflag &= ~(INLCR | IGNCR | ICRNL | IXON | IXOFF);
+    uart_cfg_opt.c_oflag &=~(INLCR|IGNCR|ICRNL);
+    uart_cfg_opt.c_oflag &=~(ONLCR|OCRNL);
+
+    /* Apply new settings */
+    if(-1==tcsetattr(fd, TCSANOW, &uart_cfg_opt))
+        return -1;
+
+    tcflush(fd,TCIOFLUSH);
+
+    /* All setting applied successful */
+    LOGE("setting apply done\r\n");
+    return 0;
+}
+#else
+int mt3333_controller_set_baudrate_length_parity_stopbits(int fd, unsigned int new_baudrate, int length, char parity_c, int stopbits)
+{
+
+    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;
+
+    
+    // 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, mt3333_controller_get_speed(new_baudrate));  /*set baudrate to 115200, which is 3332 default bd*/
+    cfsetospeed(&termOptions, mt3333_controller_get_speed(new_baudrate));
+
+    tcsetattr(fd, TCSANOW, &termOptions);
+    LOGE("Custom baud=%d length=%d parity_c=%c stopbits=%d\n",new_baudrate, length, parity_c, stopbits);
+    return 0;
+}
+
+#endif
+
+
+#endif
+#if 1
+int mt3333_thread_pmtk_input_fd[5]={C_INVALID_SOCKET,C_INVALID_SOCKET,C_INVALID_SOCKET,C_INVALID_SOCKET,C_INVALID_SOCKET};
+
+void * mt3333_thread_pmtk_input_func(void * arg)
+{
+    int exit = 0;
+    ssize_t bytes = 0;
+    char buf[MNLD_INTERNAL_BUFF_SIZE]={0};
+    //char cmd[MNLD_INTERNAL_BUFF_SIZE]={0};
+    int fd = (int)arg;
+    
+    LOGD("thread pmtk create: %.8X,fd = %d", (unsigned int)pthread_self(),fd);
+
+    while(!exit)
+    {
+        bytes = read(fd, buf, MNLD_INTERNAL_BUFF_SIZE);
+
+        if (bytes > 0) {
+            LOGD("len=%d,%s", bytes, buf);
+
+            if(bytes != write(g_fd_mt3333_data , buf, bytes)){
+                LOGD("3333 not receive data");
+                break;
+            }
+
+            if (strstr(buf, "PMTK101")
+                || strstr(buf, "PMTK102")
+                || strstr(buf, "PMTK103")
+                || strstr(buf, "PMTK104"))
+            {
+                first_entry = 0;
+                LOGD("PMTK START reset first_entry");
+            }
+
+        } else {
+            if (errno == EINTR) {
+                LOGD("thread pmtk input exit");
+                break;
+            } else if (bytes == 0) { /*client close*/    
+                LOGD("client %d close", fd);
+                close(fd);
+                for(int i=0;i<5; i++){
+                    if(mt3333_thread_pmtk_input_fd[i] == fd){
+                        mt3333_thread_pmtk_input_fd[i] = C_INVALID_SOCKET;
+                        break;
+                    }
+                }
+                break;
+            } else {
+                LOGD("pmtk sleep 200ms. bytes=%d", (int)bytes);
+                usleep(200000);  // sleep 200 ms
+            }
+        }
+    }
+
+    pthread_exit(NULL);
+    return NULL;
+}
+
+void* mt3333_thread_data_debug( void*  arg ) 
+{
+    int server_fd = C_INVALID_SOCKET, conn_fd = C_INVALID_SOCKET, on;
+    struct sockaddr_in server_addr;
+    struct sockaddr_in client_addr;
+    socklen_t size;
+    //char buf[128];
+
+    UNUSED(arg);
+    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
+    {
+        LOGE("socket error = %d (%s)", errno, strerror(errno));
+        pthread_exit(NULL);
+        return NULL;
+    }
+
+    /* Enable address reuse */
+    on = 1;
+    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) 
+    {
+        close(server_fd);
+        LOGE("setsockopt error = %d (%s)", errno, strerror(errno));
+        pthread_exit(NULL);
+        return NULL;
+    }
+
+    server_addr.sin_family = AF_INET;   /*host byte order*/
+    server_addr.sin_port = htons(7000); /*short, network byte order*/
+    server_addr.sin_addr.s_addr = 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);
+        LOGE("bind error = %d (%s)", errno, strerror(errno));
+        pthread_exit(NULL);
+        return NULL;
+    }
+
+    if (listen(server_fd, 5) == -1) 
+    {
+        close(server_fd);
+        LOGE("listen error = %d (%s)", errno, strerror(errno));
+        pthread_exit(NULL);
+        return NULL;
+    }
+
+    LOGD("listening debug port: %d", 7000);
+
+    while (1) 
+    {
+        size = sizeof(client_addr);
+        conn_fd = accept(server_fd, (struct sockaddr*)&client_addr, &size);
+        if (conn_fd <= 0) 
+        {
+            LOGE("accept error: %d (%s)", errno, strerror(errno));
+            continue;
+        } 
+        else 
+        {
+            LOGD("accept connection [%d] %s:%d", conn_fd, 
+                inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));     
+            /*loop until being interrupted or client close*/ 
+            pthread_t pthread_mt3333_controller_accept;
+            for(int i=0;i<5; i++){
+                if(mt3333_thread_pmtk_input_fd[i] == C_INVALID_SOCKET){
+                    mt3333_thread_pmtk_input_fd[i] = conn_fd;
+                    break;
+                }
+            }
+            pthread_create(&pthread_mt3333_controller_accept, NULL, mt3333_thread_pmtk_input_func, (void*)conn_fd);
+        }
+    }
+    pthread_exit(NULL);
+    return NULL;
+}
+
+#endif
+
+unsigned char gps_nmea_cal_checksum(unsigned char *ptr, unsigned char len){
+    unsigned char i=0;
+    unsigned char checksum=0;
+
+    checksum=ptr[1];
+    for(i=2; i<len; i++){
+        checksum ^= ptr[i];
+    }
+    return checksum;
+}
+
+#if 1
+
+#define MT3333_CONTROLLER_EPO_RECORD_SIZE (72)
+#define MT3333_CONTROLLER_EPO_SV_NUMBER (32+24)
+#define MT3333_CONTROLLER_EPO_SEG_BUF_SIZE ((MT3333_CONTROLLER_EPO_RECORD_SIZE * MT3333_CONTROLLER_EPO_SV_NUMBER) >> 2)
+
+int mt3333_controller_u4EPOWORD[MT3333_CONTROLLER_EPO_SEG_BUF_SIZE];
+
+
+
+int mtk_gps_epo_UtcToGpsHour (struct tm* time_st)
+{
+    int iYearsElapsed; // Years since 1980
+    int iDaysElapsed; // Days elapsed since Jan 6, 1980
+    int iLeapDays; // Leap days since Jan 6, 1980
+    int i;
+    int iYr =time_st->tm_year + 1900;
+    int iMo =time_st->tm_mon + 1;
+    int iDay =time_st->tm_mday;
+    int iHr = time_st->tm_hour;
+    // Number of days into the year at the start of each month (ignoring leap years)
+    const int 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 + doy[iMo - 1] + iDay + iLeapDays - 6;
+    
+    
+    return (iDaysElapsed * 24 + iHr);
+}
+
+int gps_data_convert(int dat){
+    char *ptr = (char *)(&dat);
+    
+    return (ptr[0]<<24) + (ptr[1]<<16) + (ptr[2]<<8) + (ptr[3]<<0);
+}
+
+void gps_timer_epo_send_assistance_data(void)
+{
+    int i=0, SatID;
+    int *pBuf;
+    char nmea_cmd[300], temp[50];
+    int err=0;
+    int count=0;
+
+    if(g_fd_mt3333_data < 0){
+        return;
+    }
+    
+    
+
+    if (gps_epo_type == 0)// G+G
+    {
+        // read binary EPO data and sent it to MT3333
+        for (i =0; i < (MT3333_CONTROLLER_EPO_SV_NUMBER); i++)
+        {
+            pBuf = mt3333_controller_u4EPOWORD + (i * 18);
+            // assume host system is little-endian
+            SatID = (pBuf[0] & 0xFF000000) >> 24;
+            if (SatID == 0){
+                continue;
+            }
+            
+            // assume host system is little-endian
+            sprintf(nmea_cmd,
+            "$PMTK721,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X",
+            SatID,
+#if 0            
+            gps_data_convert(pBuf[0]), gps_data_convert(pBuf[1]), gps_data_convert(pBuf[2]), gps_data_convert(pBuf[3]), 
+            gps_data_convert(pBuf[4]), gps_data_convert(pBuf[5]), gps_data_convert(pBuf[6]), gps_data_convert(pBuf[7]), 
+            gps_data_convert(pBuf[8]), gps_data_convert(pBuf[9]), gps_data_convert(pBuf[10]),gps_data_convert(pBuf[11]), 
+            gps_data_convert(pBuf[12]), gps_data_convert(pBuf[13]), gps_data_convert(pBuf[14]), gps_data_convert(pBuf[15]), 
+            gps_data_convert(pBuf[16]), gps_data_convert(pBuf[17]));
+#else 
+            (pBuf[0]), (pBuf[1]), (pBuf[2]), (pBuf[3]), 
+            (pBuf[4]), (pBuf[5]), (pBuf[6]), (pBuf[7]), 
+            (pBuf[8]), (pBuf[9]), (pBuf[10]),(pBuf[11]), 
+            (pBuf[12]), (pBuf[13]), (pBuf[14]), (pBuf[15]), 
+            (pBuf[16]), (pBuf[17]));
+
+#endif
+            sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+            strcat(nmea_cmd , temp);
+            count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+            if((strlen(nmea_cmd)+1) != count){
+                err=-1;
+            }
+
+            LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+            //UART DMA buffer is 2K, so GPS can send max 2K bytes once
+            //one satellite EPO sentence contain max 174 bytes, every 12 satellites contain max 2088 bytes,
+            //send 2088 bytes need cost 180ms(baudrate 115200) ,so when send 12 satellites EPO data, wait 180ms
+            if (( (i + 1) % 12 ) == 0){
+                usleep(360*1000);
+            }
+        }
+    }
+    
+}
+
+
+
+int mt3333_controller_inject_epo(int qepo){
+
+    int fd = 0;
+    //int addLock, res_epo, res_epo_hal;
+    //unsigned int u4GpsSecs_start;    // GPS seconds
+    //unsigned int u4GpsSecs_expire;
+    //char *epo_file = EPO_FILE;
+    char *epo_file_hal = qepo?QEPO_UPDATE_HAL:EPO_UPDATE_HAL;
+    //char epofile[32] = {0};
+    //time_t uSecond_start;      // UTC seconds
+    //time_t uSecond_expire;
+    int ret = 0;
+    pthread_mutex_t mutx = PTHREAD_MUTEX_INITIALIZER;
+    int epofile_begin_utc_hour=0;
+
+#if 1
+        time_t           now;
+        extern time_t epo_get_now_time();
+        //now = time(NULL);
+        now = epo_get_now_time();
+        gmtime_r(&now, &g_mt3333_time_st);
+#endif
+    int current_gps_hour = mtk_gps_epo_UtcToGpsHour(&g_mt3333_time_st);
+    
+    
+    ret = pthread_mutex_lock(&mutx);
+    if (access(epo_file_hal, 0) == -1) {
+        LOGE("EPOHAL.DAT is not exist\n");
+        ret = pthread_mutex_unlock(&mutx);
+        return -1;
+    }
+
+    fd = open(epo_file_hal, 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;
+   }
+
+    if(qepo == 0){
+        // EPO start time
+        if (sizeof(epofile_begin_utc_hour) != read(fd, &epofile_begin_utc_hour, sizeof(epofile_begin_utc_hour))) {
+            LOGE("Get EPO file start time error, return\n");
+            close(fd);
+            ret = pthread_mutex_unlock(&mutx);
+            return -1;
+        }else{
+            epofile_begin_utc_hour = epofile_begin_utc_hour & 0x00FFFFFF;
+        }
+
+        
+
+        LOGD("current_gps_hour - epofile_begin_utc_hour =%d\n" , current_gps_hour - epofile_begin_utc_hour);
+        if (current_gps_hour - epofile_begin_utc_hour > gps_epo_download_days*24){
+            close(fd);
+            ret = pthread_mutex_unlock(&mutx);
+            LOGE("EPOHAL.DAT is expired, return\n");
+            return -1;
+        }
+
+        if (lseek(fd, ((current_gps_hour - epofile_begin_utc_hour) / 6)*(MT3333_CONTROLLER_EPO_RECORD_SIZE)*(MT3333_CONTROLLER_EPO_SV_NUMBER), SEEK_SET) == -1){
+            close(fd);
+            ret = pthread_mutex_unlock(&mutx);
+            LOGE("lseek error: %s\n", strerror(errno));
+            return -1;
+        }
+    }
+    
+        
+    
+    if ((MT3333_CONTROLLER_EPO_SEG_BUF_SIZE*sizeof(int)) != read(fd, mt3333_controller_u4EPOWORD, MT3333_CONTROLLER_EPO_SEG_BUF_SIZE*sizeof(int))) {
+        close(fd);
+        ret = pthread_mutex_unlock(&mutx);
+        LOGE("lseek error: %s\n", strerror(errno));
+        return -1;
+    }
+
+    close(fd);
+    ret = pthread_mutex_unlock(&mutx);
+
+    gps_timer_epo_send_assistance_data();
+    return 0;
+}
+
+#endif
+
+
+int mt3333_controller_delete_aiding_data(int flags)
+{
+    
+    int err=0;
+    int count=0;
+    //int count1=10*5;
+
+    const char hot_cmd[]="$PMTK101";
+    const char warm_cmd[]="$PMTK102";
+    const char cold_cmd[]="$PMTK103";
+    const char full_cmd[]="$PMTK104";
+    //const char agps_cmd[]="$PMTK106";
+
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    LOGD("%s:0x%X\n", __FUNCTION__, flags);
+
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+    if(is_ygps_delete_data == 0){
+        return -1;
+    }
+    
+
+    if ((flags&(GPS_DELETE_EPHEMERIS|GPS_DELETE_POSITION|GPS_DELETE_RTI)) == (GPS_DELETE_EPHEMERIS|GPS_DELETE_POSITION|GPS_DELETE_RTI)) {
+        LOGD("Send MNL_CMD_RESTART_FULL in HAL\n");
+        sprintf(nmea_cmd ,"%s",full_cmd);
+    } else if ((flags&(GPS_DELETE_EPHEMERIS|GPS_DELETE_POSITION)) == (GPS_DELETE_EPHEMERIS|GPS_DELETE_POSITION)) {
+        LOGD("Send MNL_CMD_RESTART_COLD in HAL\n");
+        sprintf(nmea_cmd ,"%s",cold_cmd);
+    } else if ((flags&(GPS_DELETE_EPHEMERIS)) == (GPS_DELETE_EPHEMERIS)) {
+        LOGD("Send MNL_CMD_RESTART_WARM in HAL\n");
+        sprintf(nmea_cmd ,"%s",warm_cmd);
+    } else if ((flags&GPS_DELETE_RTI) == GPS_DELETE_RTI) {
+        LOGD("Send MNL_CMD_RESTART_HOT in HAL\n");
+        sprintf(nmea_cmd ,"%s",hot_cmd);
+    } else{
+        LOGD("Send MNL_CMD_RESTART_HOT in HAL\n");
+        sprintf(nmea_cmd ,"%s",hot_cmd);
+    }
+
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s\n" ,err, nmea_cmd);
+    
+    return 0;
+
+}
+
+int mt3333_controller_inject_location(double latitude, double longitude, float accuracy)
+{
+
+    const char time_aiding_cmd[]="$PMTK741";
+    
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+    struct tm *time_st = NULL;
+    //long long time_s = 0;
+
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+
+    LOGD("inject location lati= %f, longi = %f, accuracy =%f\n", latitude, longitude, accuracy);
+    sprintf(temp ,",%.6f,%.6f,0", latitude , longitude);
+    strcat(nmea_cmd , temp);
+    
+    
+#if 0
+        time_st = &g_mt3333_time_st;
+#else
+        time_t           now;
+        extern time_t epo_get_now_time();
+        //now = time(NULL);
+        now = epo_get_now_time();
+        gmtime_r(&now, &g_mt3333_time_st);
+        time_st = &g_mt3333_time_st;
+#endif
+
+    
+    LOGD("%d-%d-%d %d:%d:%d\n", 
+        time_st->tm_year + 1900, time_st->tm_mon + 1, time_st->tm_mday, 
+        time_st->tm_hour, time_st->tm_min, time_st->tm_sec);
+    sprintf(temp ,",%4d,%02d,%02d,%02d,%02d,%02d", 
+        time_st->tm_year + 1900, time_st->tm_mon + 1, time_st->tm_mday, 
+        time_st->tm_hour, time_st->tm_min, time_st->tm_sec);
+    strcat(nmea_cmd , temp);
+    
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+    
+    return 0;
+}
+
+int mt3333_controller_inject_time(int64_t time, int64_t timeReference, int uncertainty)
+{
+    
+    
+    const char time_aiding_cmd[]="$PMTK740";
+    
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+    struct tm *time_st = NULL;
+#if 0
+    long long time_s = 0;
+#else
+    time_t time_s = 0;
+    UNUSED(uncertainty);
+#endif
+    time_t         now;
+    extern time_t epo_get_now_time();
+    
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+
+    if(time==0 && timeReference == 0){
+        LOGD("local time\n");
+        //now = time(NULL);
+        now = epo_get_now_time();
+        gmtime_r(&now, &g_mt3333_time_st);
+        time_st = &g_mt3333_time_st;
+    }else{// network time is wrong ,diffrect about 20s
+        return 0;
+        now = epo_get_now_time();
+        LOGD("network time %lld, ref=%lld,local=%ld\n",time,timeReference,now);
+        time_s = time/1000;
+        //time_st = localtime(&time_s);
+        //g_mt3333_time_st = *time_st;
+        gmtime_r(&time_s, &g_mt3333_time_st);
+        time_st = &g_mt3333_time_st;
+    }
+
+    
+    LOGD("%d-%d-%d %d:%d:%d\n", 
+        time_st->tm_year + 1900, time_st->tm_mon + 1, time_st->tm_mday, 
+        time_st->tm_hour, time_st->tm_min, time_st->tm_sec);
+    
+    sprintf(temp ,",%4d,%02d,%02d,%02d,%02d,%02d", 
+        time_st->tm_year + 1900, time_st->tm_mon + 1, time_st->tm_mday, 
+        time_st->tm_hour, time_st->tm_min, time_st->tm_sec);
+    strcat(nmea_cmd , temp);
+    
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+
+int mt3333_controller_enable_debuglog(int enable)
+{
+    
+    
+    const char time_aiding_cmd[]="$PMTK299";
+    
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+    //struct tm *time_st = NULL;
+    //long long time_s = 0;
+
+    
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+    
+    
+    
+    sprintf(temp ,",%d", enable);
+    strcat(nmea_cmd , temp);
+    
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+
+int mt3333_controller_enable_easymode(int enable)
+{
+    
+    
+    const char time_aiding_cmd[]="$PMTK869,1";
+    
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+    //struct tm *time_st = NULL;
+    //long long time_s = 0;
+
+    
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+    
+    
+    
+    sprintf(temp ,",%d", enable);
+    strcat(nmea_cmd , temp);
+    
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+int mt3333_controller_set_nmea_onoff()
+{
+    int gll =0;
+    int rmc =1;
+    int vtg =1;
+    int gga =1;
+    int gsa =1;
+    int gsv =1;
+    int accuracy =1;
+    const char time_aiding_cmd[]="$PMTK314";
+    
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+    //struct tm *time_st = NULL;
+    //long long time_s = 0;
+
+    
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+    
+    
+    
+    sprintf(temp ,",%d,%d,%d,%d,%d,%d", gll,rmc,vtg,gga,gsa,gsv);
+    strcat(nmea_cmd , temp);
+    sprintf(temp ,",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
+    strcat(nmea_cmd , temp);
+    sprintf(temp ,",%d", accuracy);
+    strcat(nmea_cmd , temp);
+    
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+
+
+int mt3333_controller_set_gnss_working_satellite_system(MTK_GNSS_CONFIGURATION gnssmode)
+{
+    int gps_enable=0;
+    int glonass_enable=0;
+    int galileo_enable=0;
+    int galileo_full_enable=0;
+    int beidou_enable=0;
+    
+    const char time_aiding_cmd[]="$PMTK353";
+    
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+
+    switch(gnssmode){
+    case MTK_CONFIG_GPS_GLONASS:
+    case MTK_CONFIG_GPS_GLONASS_BEIDOU:
+        gps_enable=1;
+        glonass_enable=1;
+        galileo_enable=0;
+        galileo_full_enable=0;
+        beidou_enable=0;
+        break;
+    case MTK_CONFIG_GPS_BEIDOU:
+        gps_enable=1;
+        glonass_enable=0;
+        galileo_enable=0;
+        galileo_full_enable=0;
+        beidou_enable=1;
+        break;    
+    case MTK_CONFIG_GPS_ONLY:
+        gps_enable=1;
+        glonass_enable=0;
+        galileo_enable=0;
+        galileo_full_enable=0;
+        beidou_enable=0;
+        break;    
+    case MTK_CONFIG_BEIDOU_ONLY:
+        gps_enable=0;
+        glonass_enable=0;
+        galileo_enable=0;
+        galileo_full_enable=0;
+        beidou_enable=1;
+        break;    
+    case MTK_CONFIG_GLONASS_ONLY:
+        gps_enable=0;
+        glonass_enable=1;
+        galileo_enable=0;
+        galileo_full_enable=0;
+        beidou_enable=0;
+        break;    
+    case MTK_CONFIG_GPS_GLONASS_BEIDOU_GALILEO:
+        gps_enable=1;
+        glonass_enable=1;
+        galileo_enable=1;
+        galileo_full_enable=0;
+        beidou_enable=0;
+        break;    
+    case MTK_CONFIG_GPS_GLONASS_GALILEO:
+        gps_enable=1;
+        glonass_enable=1;
+        galileo_enable=1;
+        galileo_full_enable=0;
+        beidou_enable=0;
+        break;
+    case MTK_CONFIG_GALILEO_ONLY:
+        gps_enable=0;
+        glonass_enable=0;
+        galileo_enable=1;
+        galileo_full_enable=0;
+        beidou_enable=0;
+        break;
+    case MTK_CONFIG_GPS_GALILEO:
+        gps_enable=1;
+        glonass_enable=0;
+        galileo_enable=1;
+        galileo_full_enable=0;
+        beidou_enable=0;
+        break;
+    }
+    
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+    
+    
+    
+    sprintf(temp ,",%d,%d,%d,%d,%d", gps_enable,glonass_enable,galileo_enable,galileo_full_enable,beidou_enable);
+    strcat(nmea_cmd , temp);
+    
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+
+int mt3333_controller_set_gnss_position_fix_interval(int fix_interval)
+{
+    const char time_aiding_cmd[]="$PMTK220";
+
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+    //struct tm *time_st = NULL;
+    //long long time_s = 0;
+
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+
+    sprintf(temp ,",%d", fix_interval);
+    strcat(nmea_cmd , temp);
+
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+
+int mt3333_controller_set_pps_config(int pps_mode, int pps_duty)
+{
+    const char time_aiding_cmd[]="$PMTK285";
+
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+
+    sprintf(temp ,",%d,%d", pps_mode,pps_duty);
+    strcat(nmea_cmd , temp);
+
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+
+#ifdef MTK_ADR_SUPPORT
+int mt3333_controller_set_gnss_pmtk876_nmea_onoff(int enable)
+{
+    const char time_aiding_cmd[]="$PMTK876";
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+    int err=0;
+    int count=0;
+
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+    sprintf(temp ,",%d", enable);
+    strcat(nmea_cmd , temp);
+
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+#endif
+
+static int mt3333_controller_event_hdlr(int fd) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    main_mt3333_controller_event cmd;
+    int read_len;
+    char assist_data_req=0; // show gps icon
+    int fix_interval = 1000;    /* fix interval in milliseconds */
+
+    read_len = safe_recvfrom(fd, buff, sizeof(buff));
+    if (read_len <= 0) {
+        LOGE("safe_recvfrom() failed read_len=%d, err:%s", read_len, strerror(errno));
+        return -1;
+    }
+
+    while(offset < read_len){
+        
+        cmd = get_int(buff, &offset, sizeof(buff));
+        LOGD("cmd =%d",cmd);
+        switch (cmd) {
+        case MAIN_MT3333_CONTROLLER_EVENT_GPSREBOOT:
+        case MAIN_MT3333_CONTROLLER_EVENT_GPSENABLE:
+            break;
+        case MAIN_MT3333_CONTROLLER_EVENT_GPSSTART:
+            nmea_1st_after_powerongps = 1;
+            break;
+        case MAIN_MT3333_CONTROLLER_EVENT_GPSSTOP:
+        case MAIN_MT3333_CONTROLLER_EVENT_GPSDISABLE:
+        case MAIN_MT3333_CONTROLLER_EVENT_GPSDELETEAIDING:
+            break;
+        case MAIN_MT3333_CONTROLLER_EVENT_REQUES1STNMEA:
+            assist_data_req=0; // show gps icon
+            porting_layer_callback.sys_agps_disaptcher_callback(MTK_AGPS_CB_START_REQ, 0, &assist_data_req);
+            //usleep(800*1000);
+            //mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_NMEA_ONOFF);
+            break;
+        case MAIN_MT3333_CONTROLLER_EVENT_REQUESTNTP:
+            //assist_data_req=1;
+            //porting_layer_callback.sys_agps_disaptcher_callback(MTK_AGPS_CB_BITMAP_UPDATE, 0, &assist_data_req);
+            mt3333_controller_inject_time(0,0,0);
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_REQUESTNLP:
+            assist_data_req=2;
+            porting_layer_callback.sys_agps_disaptcher_callback(MTK_AGPS_CB_BITMAP_UPDATE, 0, &assist_data_req);
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_REQUESTEPO:
+            if(epo_downloader_is_file_invalid()){
+                // download QEPO , but now we can't get wk + tow, so need to add.
+                porting_layer_callback.sys_agps_disaptcher_callback(MTK_AGPS_CB_QEPO_DOWNLOAD_REQ, 0, NULL);
+            }else{
+                mt3333_controller_inject_epo(0);
+            }
+            break;
+        case MAIN_MT3333_CONTROLLER_EVENT_REQUESTQEPO:
+            mt3333_controller_inject_epo(1);
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_ENABLEDEBUGLOG:
+            mt3333_controller_enable_debuglog(1);
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_DISABLEDEBUGLOG:
+            mt3333_controller_enable_debuglog(0);
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_ONCEPERSECOND:
+            // tell mnld nmea monitor that data is comming normally.
+            porting_layer_callback.sys_gps_mnl_callback(MTK_GPS_MSG_FIX_READY);
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_FACTORYMETA:
+            factory_meta_exist = 1;
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_ENABLEDEASYMODE:
+            mt3333_controller_enable_easymode(1);
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_DISABLEDEASYMODE:
+            mt3333_controller_enable_easymode(0);
+            break;        
+        case MAIN_MT3333_CONTROLLER_EVENT_NMEA_ONOFF:
+            mt3333_controller_set_nmea_onoff();
+            break;        
+        case MAIN_MT3333_CONTROLLER_EVENT_GNSS_SYSTEM:
+            mt3333_controller_set_gnss_working_satellite_system(mnl_config.GNSSOPMode);
+            break;            
+        case MAIN_MT3333_CONTROLLER_EVENT_GNSS_FIXINTERVAL:
+            #ifdef MTK_ADR_SUPPORT
+            fix_interval = 1000;                //  1Hz update rate
+            #else
+            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)) {
+                fix_interval = mnl_config.fix_interval;
+            }else{
+                fix_interval = 1000;
+            }
+            LOGD("fix_interval = %d \n", fix_interval);
+            #endif
+            mt3333_controller_set_gnss_position_fix_interval(fix_interval);
+            break;
+        case MAIN_MT3333_CONTROLLER_EVENT_PPS_CONFIG:
+            mt3333_controller_set_pps_config(mnl_config.pps_mode, mnl_config.pps_duty);
+            break;
+        #ifdef MTK_ADR_SUPPORT
+        case MAIN_MT3333_CONTROLLER_EVENT_PMTK876_NMEA_ONOFF:
+            mt3333_controller_set_gnss_pmtk876_nmea_onoff(1);
+            break;
+        #endif
+        }
+    }
+
+    return 0;
+}
+
+static int mt3333_data_event_hdlr(int fd) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    //int offset = 0;
+    //char assist_data_req=0;
+    int read_len;
+
+    do{
+        memset(buff, 0, sizeof(buff));
+        read_len = read(fd, buff, sizeof(buff));
+        LOGD("read len=%d, err:%s", read_len, strerror(errno));
+        if (read_len <= 0) {
+            break;
+        }else{
+            if((mnld_is_gps_started()) || (factory_meta_exist == 1)){
+            }else{
+                continue;
+            }
+
+            // bypass data to app.
+            porting_layer_callback.sys_nmea_output_to_mnld(buff, read_len);
+            // debug log when issue occur.
+            porting_layer_callback.sys_nmea_output_to_app(buff, read_len);
+
+            //save log to debug log file.
+            porting_layer_callback.sys_alps_gps_dbg2file_mnld(buff, read_len);
+
+            for(int i=0;i<5; i++){
+                if(mt3333_thread_pmtk_input_fd[i] != C_INVALID_SOCKET){
+                    write(mt3333_thread_pmtk_input_fd[i] , buff, read_len);
+                }
+            }
+        }
+    }while(1);
+    
+
+    return 0;
+}
+
+#if 0
+static void mt3333_controller_thread_timeout() {
+    LOGE("mt3333_controller_thread_timeout() crash here for debugging");
+    CRASH_TO_DEBUG();
+}
+#endif
+
+void* mt3333_thread_control(void *arg) {
+    #define MAX_EPOLL_EVENT 1
+    //timer_t hdlr_timer = init_timer(mt3333_controller_thread_timeout);
+    struct epoll_event events[MAX_EPOLL_EVENT];
+    UNUSED(arg);
+
+    int epfd = epoll_create(MAX_EPOLL_EVENT);
+    if (epfd == -1) {
+        LOGE("epoll_create failure reason=[%s]%d",
+            strerror(errno), errno);
+        return 0;
+    }
+
+    if (epoll_add_fd(epfd, g_fd_mt3333_controller) == -1) {
+        LOGE("epoll_add_fd() failed for g_fd_mt3333_controller failed");
+        return 0;
+    }
+
+    while (1) {
+        int i;
+        int n;
+        LOGD("wait");
+        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;
+            }
+        }
+        
+        for (i = 0; i < n; i++) {
+            if (events[i].data.fd == g_fd_mt3333_controller) {
+                if (events[i].events & EPOLLIN) {
+                    mt3333_controller_event_hdlr(g_fd_mt3333_controller);
+                }
+            } else {
+                LOGE("unknown fd=%d", events[i].data.fd);
+            }
+        }
+        
+    }
+    pthread_exit(NULL);
+    LOGE("exit");
+    return 0;
+}
+int mt3333_controller_check_if_gpsfunctionok(void) {
+    char buff[32]={0};
+    int read_len = 0;
+    int temp=0;
+    int result=1;
+
+    mnl_set_pwrctl(1);
+
+    int cnt_1s=0;
+    int retry_cnt=0;
+    do{
+        temp = read(g_fd_mt3333_data, buff, sizeof(buff)-1-read_len);
+        if(temp<=0){
+            temp=0;
+        }
+        read_len += temp;
+        usleep(100 * 1000);
+        if((++cnt_1s) > 30){// wait 3s
+            
+            LOGE("read summary len=%d", read_len);
+            cnt_1s = 0;
+            read_len =0;
+            retry_cnt++;
+            mnl_set_pwrctl(4);// reset 3333 power
+        }
+        if(retry_cnt > 1){
+            LOGE("retry max count=5, maybe chip is broken");
+            mnl_set_pwrctl(0);
+            #if ANDROID_MNLD_PROP_SUPPORT
+            if (property_set("3333.gps", "fail") != 0) {
+                LOGE("set 3333.gps %s\n", strerror(errno));
+            }
+            #endif
+            return result;
+        }
+    }while(read_len<31);
+    
+    LOGE("read len=%d,content=%s", read_len,buff);
+    for(int i=0; i<sizeof(buff); i++){
+        if(buff[i] >= 0x80){
+            result=0;
+            break;
+        }
+    }
+    mnl_set_pwrctl(0);
+    LOGE("result= %d",result); 
+    if(1 == result){
+        #if ANDROID_MNLD_PROP_SUPPORT
+        if (property_set("3333.gps", "ok") != 0) {
+            LOGE("set 3333.gps %s\n", strerror(errno));
+        }
+        #endif
+    }else{
+        #if ANDROID_MNLD_PROP_SUPPORT
+        if (property_set("3333.gps", "fail") != 0) {
+            LOGE("set 3333.gps %s\n", strerror(errno));
+        }
+        #endif
+    }
+    
+    return result;
+}
+
+
+int mt3333_controller_check_uart_baudrate(void) {
+    char buff[32]={0};
+    int read_len = 0;
+    int temp=0;
+    int result=1;
+    
+    mnl_set_pwrctl(1);
+
+    int cnt_1s=0;
+    int retry_cnt=0;
+    do{
+        temp = read(g_fd_mt3333_data, buff, sizeof(buff)-1-read_len);
+        if(temp<=0){
+            temp=0;
+        }
+        read_len += temp;
+        usleep(100 * 1000);
+        if((++cnt_1s) > 30){// wait 3s
+            
+            LOGE("read summary len=%d", read_len);
+            cnt_1s = 0;
+            read_len =0;
+            retry_cnt++;
+            mnl_set_pwrctl(4);// reset 3333 power
+        }
+        if(retry_cnt > 1){
+            LOGE("retry max count=5, maybe chip is broken");
+            mnl_set_pwrctl(0);
+            return result;
+        }
+    }while(read_len<31);
+    
+    LOGE("read len=%d,content=%s", read_len,buff);
+    for(int i=0; i<sizeof(buff); i++){
+        if(buff[i] >= 0x80){
+            result=0;
+            break;
+        }
+    }
+    mnl_set_pwrctl(0);
+    LOGE("result= %d",result); 
+    return result;
+}
+
+
+void* mt3333_thread_data(void *arg) {
+    #define MAX_EPOLL_EVENT 1
+    //timer_t hdlr_timer = init_timer(mt3333_controller_thread_timeout);
+    struct epoll_event events[MAX_EPOLL_EVENT];
+    UNUSED(arg);
+
+    int epfd = epoll_create(MAX_EPOLL_EVENT);
+    if (epfd == -1) {
+        LOGE("epoll_create failure reason=[%s]%d",
+            strerror(errno), errno);
+        return 0;
+    }
+
+    if (epoll_add_fd(epfd, g_fd_mt3333_data) == -1) {
+        LOGE("epoll_add_fd() failed for g_fd_mt3333_data failed");
+        return 0;
+    }
+
+    while (1) {
+        int i;
+        int n;
+        LOGD("wait");
+        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;
+            }
+        }
+        
+        for (i = 0; i < n; i++) {
+            if (events[i].data.fd == g_fd_mt3333_data) {
+                if (events[i].events & EPOLLIN) {
+                    mt3333_data_event_hdlr(g_fd_mt3333_data);
+                }
+            } else {
+                LOGE("unknown fd=%d",
+                    events[i].data.fd);
+            }
+        }
+        
+    }
+    pthread_exit(NULL);
+    LOGE("exit");
+    return 0;
+}
+
+
+
+int mt3333_controller_init() {
+    pthread_t pthread_mt3333_controller;
+    pthread_t pthread_mt3333_data;
+    pthread_t pthread_mt3333_data_debug;
+    pthread_t pthread_flashtool;
+
+    g_fd_mt3333_controller = socket_bind_udp(MNLD_MT3333_CONTROLLER_SOCKET);
+    if (g_fd_mt3333_controller < 0) {
+        LOGE("socket_bind_udp(MNLD_MT3333_CONTROLLER_SOCKET) failed");
+        return -1;
+    }
+
+    g_fd_mt3333_data= open(MT3333_CONTROLLER_TTY_NAME, O_RDWR|O_NOCTTY|O_NONBLOCK);
+    if (g_fd_mt3333_data < 0) {
+        LOGE("no gps hardware detected: %s:%d, %s", MT3333_CONTROLLER_TTY_NAME, g_fd_mt3333_data, strerror(errno));
+        return -1;
+    }
+
+    if(flashtool_file_isvalid()){
+        pthread_create(&pthread_flashtool, NULL, flashtool_download_thread, NULL);
+    }else{
+#if 1
+        LOGE("uart baudrate:%d", mnld_cfg.init_speed);
+        if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(g_fd_mt3333_data ,mnld_cfg.init_speed, 8, 'N', 1)){
+            LOGE("configure uart baudrate failed");
+            return -1;
+        }
+        if(1 != mt3333_controller_check_if_gpsfunctionok()){
+        #if 0    
+            if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(
+                g_fd_mt3333_data ,
+                mnld_cfg.init_speed == 115200?921600:115200, 
+                8, 'N', 1)){
+                LOGE("configure uart baudrate failed");
+                return -1;
+            }
+        #endif    
+        }
+#endif
+        
+        pthread_create(&pthread_mt3333_controller, NULL, mt3333_thread_control, NULL);
+
+        pthread_create(&pthread_mt3333_data, NULL, mt3333_thread_data, NULL);
+
+        pthread_create(&pthread_mt3333_data_debug, NULL, mt3333_thread_data_debug, NULL);
+    }
+    
+    return 0;
+}
+
+
+int mt3333_controller_socket_send_cmd(main_mt3333_controller_event cmd) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, cmd);
+    //put_int(buff, &offset, delete_aiding_data_flags);
+    return safe_sendto(MNLD_MT3333_CONTROLLER_SOCKET, buff, offset);
+}
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/mtknav.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mtknav.c
new file mode 100644
index 0000000..856bad6
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mtknav.c
@@ -0,0 +1,433 @@
+#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"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mtknav"
+#endif
+
+#ifdef GPS_EPO_FILE_LEN
+#undef GPS_EPO_FILE_LEN
+#define GPS_EPO_FILE_LEN  20
+#endif
+
+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 check_mtknav_file_exist(void) {
+    if ( (access(MTKNAV_MD5_FILE, F_OK) == -1) ||
+         (access(MTKNAV_DAT_FILE, F_OK) == -1) ) {
+        LOGD("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[256]={0};
+
+    LOGD("curl_easy_download_mtknav_DAT");
+    getEpoUrl(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[256]={0};
+
+    LOGD("curl_easy_download_mtknav_MD5");
+    getEpoUrl(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("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 {
+        LOGW("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) {
+        if (1) {
+            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("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("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){
+        LOGW("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: {
+        LOGW("mnld_mtknav_download() before");
+        mnld_mtknav_download();
+        LOGW("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];
+    memset(&events, 0, sizeof(events));
+    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("mtknav_downloader_thread wait");
+        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;
+            }
+        }
+        //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);
+    }
+
+    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/mtk_mnld/mnld_entity/src/nmea_parser.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/nmea_parser.c
new file mode 100644
index 0000000..db19f2a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/nmea_parser.c
@@ -0,0 +1,975 @@
+// SPDX-License-Identifier: MediaTekProprietary
+/* 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_auto_log.h"
+#ifdef CONFIG_GPS_MT3303
+#include "mt3333_controller.h"
+#endif
+
+extern int g_agc_level;
+
+#define CARRIER_FREQ_GPS_L1    (1575.42*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 NEMA_DEBUG 0
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "nmea_parser"
+#endif
+
+/*******************************************************************************
+* structure & enumeration
+*******************************************************************************/
+static int gps_nmea_end_tag = 0;
+
+static NmeaCash nmea_cash[450];
+
+extern int prn[32];
+extern int snr[32];
+extern int MNL_AT_TEST_FLAG;
+extern int MNL_AT_SIGNAL_MODE;
+
+#ifdef CONFIG_GPS_MT3303
+extern MNL_CONFIG_T mnl_config;
+extern int is_ygps_delete_data ;
+extern unsigned int assist_data_bit_map;
+static int has_accuracy = 0;
+int first_entry = 0;
+#endif
+
+/******************************************************************************
+ * 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;
+
+    gmtime_r(&now, &tm_utc);
+    localtime_r(&now, &tm_local);
+    tm_local.tm_isdst = -1;
+    tm_utc.tm_isdst = -1;
+    time_local = mktime(&tm_local);
+    time_utc = mktime(&tm_utc);
+
+    r->utc_diff = time_utc - time_local;
+}
+
+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 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_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'", 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'", 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'", 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'", 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;
+    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;
+#ifdef CONFIG_GPS_MT3303
+    if (htok.p >= htok.end)
+#else
+    if (htok.p >= htok.end || btok.p >= btok.end || stok.p >= stok.end || vtok.p >= vtok.end)
+#endif
+        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, v=%f, s=%f, b= %f", r->fix.h_accuracy, r->fix.v_accuracy,
+        r->fix.s_accuracy, r->fix.b_accuracy);
+    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;
+    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 = (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 <= 237)) {
+        r->sv_status.sv_list[sv_index].svid = prn-200;
+        r->sv_status.sv_list[sv_index].constellation = BDS_SV;
+        r->sv_status.sv_list[sv_index].carrier_frequency = (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-400;
+        r->sv_status.sv_list[sv_index].constellation = GALILEO_SV;
+        r->sv_status.sv_list[sv_index].carrier_frequency = (float)CARRIER_FREQ_GAL_E1;
+        r->sv_status.sv_list[sv_index].flags |= 0x08;
+    } else if ((prn >= 193) && (prn <= 197)) {
+        r->sv_status.sv_list[sv_index].svid = prn;
+        r->sv_status.sv_list[sv_index].constellation = QZSS_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 >= 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 {
+        LOGW("sv_status: ignore (%d)", prn);
+        return 0;
+    }
+
+    r->sv_status.sv_list[sv_index].c_n0_dbhz = str2float(snr.p, snr.end);
+    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 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 = 1;
+
+    #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.", tok.end-tok.p, tok.p);
+        return;
+    }
+
+    // ignore first two characters.
+    mtok.p = tok.p;  // Mark the first two char for GPS,GLONASS,BDS , GALILEO SV parse.
+    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;
+    }
+    #ifdef CONFIG_GPS_MT3303
+    else if (!memcmp(mtok.p, "PMTK010", 7)) {
+        Token  result          = nmea_tokenizer_get(tzer, 1);
+        int pmtk010_result = str2int(result.p, result.end);
+        
+        LOGD("[GNSS_Performance]:pmtk010_result: %d, delete state=%d first_entry=%d",
+            pmtk010_result,is_ygps_delete_data, first_entry);
+
+        mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GNSS_FIXINTERVAL);
+        mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_PPS_CONFIG);
+
+    #ifdef MTK_ADR_SUPPORT
+        mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_PMTK876_NMEA_ONOFF);
+    #endif
+
+        if(pmtk010_result == 1){
+            if(is_ygps_delete_data == 1){
+                is_ygps_delete_data = 2;
+                mt3333_controller_delete_aiding_data(assist_data_bit_map);
+                first_entry = 0;
+                return;
+            }else if(is_ygps_delete_data == 2){
+                is_ygps_delete_data = 0;
+            }else if(is_ygps_delete_data == 10){
+                is_ygps_delete_data = 0;
+            }
+
+            mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_REQUES1STNMEA);
+
+            //mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GNSS_SYSTEM);
+            
+        }else if(pmtk010_result == 2){  
+            if(is_ygps_delete_data != 0){
+                return;
+            }   
+
+            if(first_entry == 0){
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GNSS_FIXINTERVAL);
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_PPS_CONFIG);
+
+                #ifdef MTK_ADR_SUPPORT
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_PMTK876_NMEA_ONOFF);
+                #endif
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GNSS_SYSTEM);
+                first_entry = 1;
+                LOGD("[GNSS_Performance]:pmtk353_cmd: fix_interval=%d pps_mode=%d pps_duty=%d GNSSOPMode=%d",
+                    mnl_config.fix_interval, mnl_config.pps_mode,mnl_config.pps_duty, mnl_config.GNSSOPMode);
+            } else{
+                first_entry = 0;
+            }
+            LOGD("[GNSS_Performance]:pmtk353_cmd: %d, delete state=%d first_entry=%d", pmtk010_result,
+                is_ygps_delete_data, first_entry);
+
+            mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_NMEA_ONOFF);
+            if(mnl_config.EPO_enabled == 1){
+                //3303 qepo is not  implemented
+                //mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_REQUESTEPO); 
+            }
+        }
+        return;
+    }
+    else if (!memcmp(mtok.p, "PMTK001", 7)) {
+        gps_nmea_end_tag = 0;
+        Token  cmd          = nmea_tokenizer_get(tzer, 1);
+        Token  cmd_result          = nmea_tokenizer_get(tzer, 2);
+        int pmtk001_cmd = str2int(cmd.p, cmd.end);
+        int pmtk001_cmd_result = str2int(cmd_result.p, cmd_result.end);
+        
+        LOGD("[GNSS_Performance]:pmtk001_cmd: PMTK%03d, cmd result=%d", pmtk001_cmd ,pmtk001_cmd_result);
+
+        
+        if(pmtk001_cmd == 314){
+            mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_REQUESTNTP);
+            mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_REQUESTNLP);
+            
+            if(mnl_config.BEE_enabled == 1){
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_ENABLEDEASYMODE);
+            }else{
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_DISABLEDEASYMODE);
+            }
+            
+            if(mnl_config.dbg2file == 1){
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_ENABLEDEBUGLOG);
+            }else{
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_DISABLEDEBUGLOG);
+            }
+        }
+    }
+    if(is_ygps_delete_data != 0){
+        return;
+    }
+#endif
+    #if NEMA_DEBUG
+    LOGD("SV type: %d", sv_type);
+    #endif
+    tok.p += 2;
+    if ( !memcmp(tok.p, "GGA", 3) ) {
+#ifdef CONFIG_GPS_MT3303
+        gps_nmea_end_tag = 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->fix, 0x00, sizeof(r->fix));
+        nmea_reader_update_utc_diff(r);
+#endif
+
+        // 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(tok.p, "GSA", 3) ) {
+        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) {
+                    #if NEMA_DEBUG
+                    LOGD("GSA: found %d active satellites\n", idx);
+                    #endif
+                    break;
+                }
+                int sate_id = str2int(tok_satellite.p, tok_satellite.end);
+                if (sv_type == BDS_SV) {
+                    sate_id += 200;
+                    #if NEMA_DEBUG
+                    LOGD("It is BDS SV: %d", sate_id);
+                    #endif
+                } else if (sv_type == GALILEO_SV) {
+                    sate_id += 400;
+                    #if NEMA_DEBUG
+                    LOGD("It is GALILEO SV: %d", sate_id);
+                    #endif
+                }
+                if (sate_id >= 0 && sate_id < 450) {
+                    nmea_cash[sate_id].prn = sate_id;
+                    nmea_cash[sate_id].used_in_fix = 1;
+                }
+            }
+        }
+    }
+    // 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)) {
+        Token tok_num = nmea_tokenizer_get(tzer, 1);    // number of EPH
+        int num = str2int(tok_num.p, tok_num.end);
+        UNUSED(num);
+        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)) {
+        Token tok_num = nmea_tokenizer_get(tzer, 1);    // number of ALM
+        int num = str2int(tok_num.p, tok_num.end);
+        UNUSED(num);
+        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 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;
+                #if NEMA_DEBUG
+                LOGD("It is BDS SV: %d", sv_id);
+                #endif
+            } else if (sv_type == GALILEO_SV) {
+                sv_id += 400;
+                #if NEMA_DEBUG
+                LOGD("It is GALILEO SV: %d", sv_id);
+                #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);
+            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);
+        }
+        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)) {
+                    LOGD("MNL_AT_TEST_FLAG = %d, MNL_AT_SIGNAL_MODE = %d", MNL_AT_TEST_FLAG, MNL_AT_SIGNAL_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)) {
+#ifdef CONFIG_GPS_MT3303
+        if(!has_accuracy) {
+            has_accuracy = 1;
+        } else {
+            mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_ONCEPERSECOND);
+            gps_nmea_end_tag = 1;
+        }
+#endif
+        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);
+            #if NEMA_DEBUG
+            LOGD("GPS get accuracy from driver:%f\n", r->fix.h_accuracy);
+            #endif
+        }
+    } else if (!memcmp(mtok.p+2, "AG2", 3)) {
+        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);
+    } 
+#ifdef CONFIG_GPS_MT3303
+    else if (!memcmp(mtok.p, "PMTK001", 7) || !memcmp(mtok.p, "PMTK010", 7)) {
+    }else if (!memcmp(tok.p+2, "GRP", 3)) {
+        if(!has_accuracy) {
+            mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_ONCEPERSECOND);
+            gps_nmea_end_tag = 1;
+        }
+    }
+#endif
+    else {
+        tok.p -= 2;
+        LOGW("unknown sentence '%.*s", tok.end-tok.p, tok.p);
+    }
+    if (!LOC_FIXED(r)) {
+        #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
+        mnl2hal_location(r->fix);
+        mnld_gps_update_location(r->fix);
+        r->fix.flags = 0;
+    }
+
+    #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) {
+        mnl2hal_gps_sv(r->sv_status);
+#ifdef CONFIG_GPS_MT3303
+        if(mnld_is_gps_meas_enabled()){
+            extern gnss_sv_info cts_sv_data;
+            cts_sv_data = r->sv_status;
+        }
+#endif
+
+        r->sv_count = r->sv_status.num_svs = 0;
+        memset((void*)nmea_cash, 0x00, sizeof(nmea_cash));
+    }
+}
+
+static int mtk_mnld_nmea_paser_filter(char* const nmea_stnc, int length)
+{
+    char* buf;
+    int ret = 0;
+
+    if(nmea_stnc == NULL) {
+        LOGE("pointer fail!");
+        return 0;
+    }
+
+    if(length < 6) {
+        LOGE("length fail:%d", length);
+        return 0;
+    }
+
+    buf = nmea_stnc+3; //skip "$GP", "$GL", "$BD", "$GA"
+#ifdef CONFIG_GPS_MT3303
+if ((!memcmp(buf, "GGA", 3)) ||
+     (!memcmp(buf, "GSA", 3)) ||
+     (!memcmp(buf, "RMC", 3)) ||
+     (!memcmp(buf+3, "EPH", 3)) ||
+     (!memcmp(buf+3, "ALM", 3)) ||
+     (!memcmp(buf, "GSV", 3)) ||
+     (!memcmp(buf, "ACCURACY", 8)) ||
+     (!memcmp(buf+2, "001", 3)) ||
+     (!memcmp(buf+2, "010", 3)) ||
+     (!memcmp(buf+2, "AGC", 3)) ||
+     (!memcmp(buf+2, "CLK", 3)) ||
+     (!memcmp(buf+2, "SUPL", 4)) ||
+     (!memcmp(buf+2, "AG2", 3)) ||
+     (!memcmp(buf+2, "GRP", 3))
+#else
+    if ((!memcmp(buf, "GGA", 3)) ||
+        (!memcmp(buf, "GSA", 3)) ||
+        (!memcmp(buf, "RMC", 3)) ||
+        (!memcmp(buf+3, "EPH", 3)) ||
+        (!memcmp(buf+3, "ALM", 3)) ||
+        (!memcmp(buf, "GSV", 3)) ||
+        (!memcmp(buf, "ACCURACY", 8)) ||
+        (!memcmp(buf, "VTG", 3)) ||
+        (!memcmp(buf+2, "TIM", 3)) ||
+        (!memcmp(buf+2, "840", 3)) ||
+        (!memcmp(buf+2, "AGC", 3)) ||
+        (!memcmp(buf+2, "CLK", 3)) ||
+        (!memcmp(buf+2, "SUPL", 4)) ||
+        (!memcmp(buf+2, "AG2", 3))
+#endif
+    ) {
+        ret = 1;
+    } else {
+        ret = 0;
+    }
+
+    return ret;
+}
+
+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') {
+        if(mtk_mnld_nmea_paser_filter(r->in, r->pos)) {
+            nmea_reader_parse(r);
+        }
+        // LOGD("the structure include nmea_cb address is %p\n", r);
+#ifndef CONFIG_GPS_MT3303
+        mnl2hal_nmea(r->fix.timestamp, r->in, r->pos);
+#else
+        if(is_ygps_delete_data == 0){
+            mnl2hal_nmea(r->fix.timestamp, r->in, r->pos);
+        }
+#endif
+        // 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;
+#ifndef CONFIG_GPS_MT3303
+    NmeaReader  reader[1];
+#else
+    static NmeaReader  reader[1]={0};
+#endif
+
+#ifndef CONFIG_GPS_MT3303
+    nmea_reader_init(reader);
+    gps_nmea_end_tag = 0;
+#endif
+
+    for (nn = 0; nn < length; nn++) {
+#ifndef CONFIG_GPS_MT3303
+        if (nn == (length-1)) {
+            gps_nmea_end_tag = 1;
+        }
+#endif
+        nmea_reader_addc(reader, buffer[nn]);
+    }
+}
+
+int get_gps_nmea_parser_end_status() {
+    int ret = 0;
+
+    ret = gps_nmea_end_tag;
+    return ret;
+}
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/op01_log.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/op01_log.c
new file mode 100644
index 0000000..4884303
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/op01_log.c
@@ -0,0 +1,195 @@
+#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_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "op01"
+#endif
+
+typedef enum {
+    MAIN2OP01_EVENT_LOG_WRITE       = 0,
+} main2op01_event;
+
+static int g_fd_op01;
+
+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);
+    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;
+    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_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;
+}
+
+int op01_log_gps_start() {
+    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);
+}
+
+int op01_log_gps_stop() {
+    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);
+}
+
+int op01_log_gps_location(double lat, double lng, int ttff) {
+    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);
+}
+
+int op01_log_init() {
+    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);
+    return 0;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/qepo.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/qepo.c
new file mode 100644
index 0000000..86e0237
--- /dev/null
+++ b/src/connectivity/gps/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_auto_log.h"
+#ifdef CONFIG_GPS_MT3303
+#include "mt3333_controller.h"
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "qepo"
+#endif
+
+#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;
+#ifdef CONFIG_GPS_MT3303
+extern MNL_CONFIG_T mnl_config;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////
+// 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 = 1;
+
+#ifndef CONFIG_GPS_MT3303
+static CURLcode curl_easy_download_quarter_epo(void) {
+    int res_val;
+    CURLcode res;
+    char url[256]={0};
+
+    LOGD("curl_easy_download_quarter_epo");
+    getEpoUrl(quarter_epo_file_name, url);
+
+    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 = 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++;
+    }
+    return res;
+}
+#else
+static CURLcode curl_easy_download_quarter_epo(void) {
+    int res_val;
+    CURLcode res;
+    char url[256]={0};
+
+    LOGD("curl_easy_download_quarter_epo");
+    __getEpoUrl(quarter_epo_file_name, url);
+    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 = 1;
+        res_val = chmod(QUARTER_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;
+}
+
+#endif
+
+static CURLcode curl_easy_download_quarter_epo_bd(void) {
+    int res_val;
+    CURLcode res;
+    char url[256]={0};
+
+    LOGD("curl_easy_download_quarter_bdepo");
+    getEpoUrl(quarter_epo_bd_file_name, url);
+
+    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 = 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++;
+    }
+    return res;
+}
+
+static CURLcode curl_easy_download_quarter_epo_ga(void) {
+    int res_val;
+    CURLcode res;
+    char url[256]={0};
+
+    LOGD("curl_easy_download_quarter_gaepo");
+    getEpoUrl(quarter_epo_ga_file_name, url);
+
+    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 = 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++;
+    }
+    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) {
+        LOGE("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 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("gps_time.wn, tow %d, %d\n", gps_time.wn, gps_time.tow);
+        GpsToUtcTime(gps_time.wn, gps_time.tow, &current_rqst_time_utc_s);
+        LOGD("Request GPS time: %s", ctime(&current_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;
+
+            LOGE("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[0], &g_qepo_bd_has_epo);
+        mtk_gps_sys_qepo_bd_get_sv_cnt(bd_header_data[1], &sv_cnt);
+
+        //Check file size
+        file_size = gps_mnl_epo_get_file_size(fd);
+        LOGD("qepo bd file size:%d\n",file_size);
+        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, &current_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("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(&current_qbd_start_time_utc_s));
+            current_dl_time_utc_s = current_rqst_time_utc_s+(time((time_t *)NULL)-gps_time.sys_time);
+            LOGD("Time after download: %s\n", ctime(&current_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 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("gps_time.wn, tow %d, %d\n", gps_time.wn, gps_time.tow);
+        GpsToUtcTime(gps_time.wn, gps_time.tow, &current_rqst_time_utc_s);
+        LOGD("Request GPS time: %s", ctime(&current_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;
+
+            LOGE("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[0], &g_qepo_ga_has_epo);
+        mtk_gps_sys_qepo_ga_get_sv_cnt(ga_header_data[1], &sv_cnt);
+
+        //Check file size
+        file_size = gps_mnl_epo_get_file_size(fd);
+        LOGD("qepo ga file size:%d\n",file_size);
+        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, &current_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("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(&current_qga_start_time_utc_s));
+            current_dl_time_utc_s = current_rqst_time_utc_s+(time((time_t *)NULL)-gps_time.sys_time);
+            LOGD("Time after download: %s\n", ctime(&current_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;
+}
+
+/*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);
+    }
+}*/
+
+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("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("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\n",  qepo_bd_valid,g_qepo_bd_has_epo,g_qepo_bd_file_time_correct,g_qepo_bd_file_size_correct);
+    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("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\n",  qepo_ga_valid,g_qepo_ga_has_epo,g_qepo_ga_file_time_correct,g_qepo_ga_file_size_correct);
+    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;
+}
+#ifndef CONFIG_GPS_MT3303
+void qepo_update_quarter_epo_file(int qepo_valid) {
+    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");
+        }
+}
+#else
+void qepo_update_quarter_epo_file(int qepo_valid) {
+    if (qepo_valid == EPO_DOWNLOAD_RESULT_SUCCESS && (mnl_config.EPO_enabled == 1)) {
+        mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_REQUESTQEPO);
+    }
+}
+
+#endif
+
+void qepo_update_quarter_epo_bd_file(int qepo_bd_valid) {
+    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) {
+    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;
+    mnld_qepo_download_done(ret);
+    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, &current_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("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("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;
+    LOGD("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);
+    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("The qbd data on server is invalid, will download again when the requesting is come in in next hour!\n");
+    }
+
+    qepo_bd_dl_res = ret;
+
+    mnld_qepo_bd_download_done(ret);
+    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, &current_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("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("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;
+    LOGD("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);
+    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("The qga data on server is invalid, will download again when the requesting is come in in next hour!\n");
+    }
+
+    qepo_ga_dl_res = ret;
+
+    mnld_qepo_ga_download_done(ret);
+    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: {
+        LOGW("mnld_qepo_download() before");
+        // need to call mnld_qepo_download_done() when QEPO download is done
+        mnld_qepo_download();
+        LOGW("mnld_qepo_download() after");
+        break;
+    }
+    case MAIN2QEPO_BD_EVENT_START: {
+        LOGW("mnld_qepo_bd_download() before");
+        mnld_qepo_bd_download();
+        LOGW("mnld_qepo_bd_download() after");
+        break;
+    }
+    case MAIN2QEPO_GA_EVENT_START: {
+        LOGW("mnld_qepo_ga_download() before");
+        mnld_qepo_ga_download();
+        LOGW("mnld_qepo_ga_download() after");
+        break;
+    }
+
+    default: {
+        LOGE("qepo_event_hdlr() unknown cmd=%d", cmd);
+        return -1;
+    }
+    }
+    return 0;
+}
+
+/*static void qepo_downloader_thread_timeout() {
+    if (mnld_timeout_ne_enabled() == false) {
+        LOGE("qepo_downloader_thread_timeout() dump and exit.");
+        mnld_block_exit();
+    } else {
+        LOGE("qepo_downloader_thread_timeout() crash here for debugging");
+        CRASH_TO_DEBUG();
+    }
+}*/
+
+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];
+    memset(&events, 0, sizeof(events));
+    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("qepo_downloader_thread wait");
+        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;
+            }
+        }
+        //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);
+    }
+
+    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;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_mt33xx.service b/src/connectivity/gps/mtk_mnld/mnld_mt33xx.service
new file mode 100644
index 0000000..b8657c9
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_mt33xx.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=MNL Daemon
+Requires=mt33xx_drv_insmod.service
+After=mt33xx_drv_insmod.service
+
+[Service]
+ExecStart=/usr/bin/mnld0
+Restart=always
+#StandardOutput=kmsg+console
+
+[Install]
+WantedBy=basic.target
diff --git a/src/connectivity/gps/mtk_mnld/utility/inc/data_coder.h b/src/connectivity/gps/mtk_mnld/utility/inc/data_coder.h
new file mode 100644
index 0000000..fc66d2f
--- /dev/null
+++ b/src/connectivity/gps/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);
+void put_binary(char* buff, int* offset, const char* input, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/utility/inc/mtk_auto_log.h b/src/connectivity/gps/mtk_mnld/utility/inc/mtk_auto_log.h
new file mode 100644
index 0000000..0387cb0
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/inc/mtk_auto_log.h
@@ -0,0 +1,186 @@
+/*
+* 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_AUTO_LOG_H
+#define MTK_AUTO_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__)
+
+#define  ANDROID_MNLD_PROP_SUPPORT 1
+
+#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>
+#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
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/utility/inc/mtk_lbs_utility.h b/src/connectivity/gps/mtk_mnld/utility/inc/mtk_lbs_utility.h
new file mode 100644
index 0000000..1498859
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/inc/mtk_lbs_utility.h
@@ -0,0 +1,159 @@
+#ifndef __MTK_LBS_UTILITY_H__
+#define __MTK_LBS_UTILITY_H__
+
+#include <time.h>
+#include <stdint.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include "gps_dbg_log.h"
+#include "mtk_auto_log.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************
+* Basic Utilities
+**************************************************/
+#define  MTK_GPS_NVRAM  0
+    
+#if defined(__ANDROID_OS__)
+#define  ANDROID_MNLD_PROP_SUPPORT 1
+#elif defined(__LINUX_OS__)
+#define  ANDROID_MNLD_PROP_SUPPORT 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 CRASH_TO_DEBUG() \
+{\
+    int* crash = 0;\
+    gps_dbg_log_exit_flush(0);\
+    *crash = 100;\
+}
+
+#define MNLD_STRNCPY(dst,src,size)\
+    do{\
+        strncpy((char *)(dst), (src), (size - 1));\
+        (dst)[size - 1] = '\0';\
+    }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
+time_t 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);
+
+/*************************************************
+* 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(void* dest, 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);
+
+/*************************************************
+* 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(char* dest, char* msg, ...);
+
+int asc_str_to_usc2_str(char* output, const char* input);
+
+void raw_data_to_hex_string(char* output, 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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/utility/inc/mtk_socket_data_coder.h b/src/connectivity/gps/mtk_mnld/utility/inc/mtk_socket_data_coder.h
new file mode 100644
index 0000000..cc9d52e
--- /dev/null
+++ b/src/connectivity/gps/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, 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/mtk_mnld/utility/inc/mtk_socket_utils.h b/src/connectivity/gps/mtk_mnld/utility/inc/mtk_socket_utils.h
new file mode 100644
index 0000000..03e29c6
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/inc/mtk_socket_utils.h
@@ -0,0 +1,236 @@
+// 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_auto_log.h"
+#ifdef __cplusplus
+extern "C" {
+#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 ...) ALOGD("%s: " fmt, __FUNCTION__ , ##arg)
+#define SOCK_LOGW(fmt, arg ...) ALOGW("%s: " fmt, __FUNCTION__ , ##arg)
+#define SOCK_LOGE(fmt, arg ...) ALOGE("%s: " fmt, __FUNCTION__ , ##arg)
+
+//-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);
+
+#define ASSERT_EQUAL_INT(d1, d2) \
+{\
+    int _d1 = d1;\
+    int _d2 = d2;\
+    if(_d1 != _d2) {\
+        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)) {\
+        LOGE("%s():%d EXPECTED_STRUCT() %s_is_equal() fail", __func__, __LINE__, #struct_name);\
+        LOGE(" ============= read ===============");\
+        struct_name##_dump(&_tmp);\
+        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)) {\
+        LOGE("%s():%d expected_%s_array() fail", __func__, __LINE__, #type);\
+        LOGE(" ============= read ===============");\
+        mtk_socket_##type##_array_dump(_tmp, _tmp_num);\
+        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)) {\
+        LOGE("%s():%d expected_string_array() fail", __func__, __LINE__);\
+        LOGE(" ============= read ===============");\
+        mtk_socket_string_array_dump(_tmp, _tmp_num, max_size2);\
+        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)) {\
+        LOGE("%s():%d expected_%s_array() fail", __func__, __LINE__, #type);\
+        LOGE(" ============= read ===============");\
+        type##_array_dump(_tmp, _tmp_num);\
+        LOGE(" ============= expected ===============");\
+        type##_array_dump(expected_value, expected_num);\
+        return false;\
+    }\
+}
+
+#define ASSERT_LESS_EQUAL_THAN(d1, d2) \
+{\
+    if(d1 > d2) {\
+        LOGE("%s():%d ASSERT_LESS_EQUAL_THAN() fail, %s=[%d] > [%d]", __func__, __LINE__, #d1, d1, d2);\
+        return false;\
+    }\
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/utility/src/data_coder.c b/src/connectivity/gps/mtk_mnld/utility/src/data_coder.c
new file mode 100644
index 0000000..ab67b38
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/src/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/mtk_mnld/utility/src/mtk_auto_log.c b/src/connectivity/gps/mtk_mnld/utility/src/mtk_auto_log.c
new file mode 100644
index 0000000..1c16fa9
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/src/mtk_auto_log.c
@@ -0,0 +1,109 @@
+/*
+* 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_auto_log.h"
+
+#if defined(__LINUX_OS__)
+// -1 means failure
+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;
+}
+#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/mtk_mnld/utility/src/mtk_lbs_utility.c b/src/connectivity/gps/mtk_mnld/utility/src/mtk_lbs_utility.c
new file mode 100644
index 0000000..170b70a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/src/mtk_lbs_utility.c
@@ -0,0 +1,669 @@
+#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 "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mtk_lbs_utility"
+#endif
+
+#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;
+}
+
+
+#endif //__LINUX_OS__
+
+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, 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
+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);
+}
+
+
+sem_t g_mnld_exit_sem;
+// -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) {
+    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 (timer_t)-1;
+    }
+    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) {
+    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);
+}
+
+// -1 means failure
+int stop_timer(timer_t timerid) {
+    return start_timer(timerid, 0);
+}
+
+// -1 means failure
+int deinit_timer(timer_t timerid) {
+    if (timer_delete(timerid) == -1) {
+        // errno
+        return -1;
+    }
+    return 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_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;
+}
+
+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 ? (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) continue;
+        if (errno == EAGAIN) {
+            if (retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+        }
+        LOGE("sendto() failed path=[%s] ret=%d reason=[%s]%d",
+            path, ret, strerror(errno), errno);
+        break;
+    }
+
+    close(fd);
+    return ret;
+}
+
+int mnld_sendto_flp(void* dest, 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",
+            (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(char* dest, char* msg, ...) {
+    FILE* fp;
+    char buf[1024] = {0};
+    va_list ap;
+
+    if (dest == NULL || msg == NULL) {
+        return -1;
+    }
+
+    va_start(ap, msg);
+    vsnprintf(buf, sizeof(buf), msg, ap);
+    va_end(ap);
+
+    fp = fopen(dest, "a");
+    if (fp == NULL) {
+        LOGE("write_msg2file() fopen() fail reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+    fprintf(fp, "%s", buf);
+    fclose(fp);
+    return 0;
+}
+
+void init_condition(SYNC_LOCK_T *lock) {
+    int ret = 0;
+
+    ret = pthread_mutex_lock(&(lock->mutx));
+    lock->condtion = 0;
+    ret = pthread_mutex_unlock(&(lock->mutx));
+    LOGD("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("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("ret unlock= %d\n", ret);
+
+    return;
+}
diff --git a/src/connectivity/gps/mtk_mnld/utility/src/mtk_mnld_dump.cpp b/src/connectivity/gps/mtk_mnld/utility/src/mtk_mnld_dump.cpp
new file mode 100644
index 0000000..05e457b
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/src/mtk_mnld_dump.cpp
@@ -0,0 +1,147 @@
+#if defined(__ANDROID_OS__)
+#include <utils/CallStack.h>
+#include <utils/ProcessCallStack.h>
+#endif
+#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 "mtk_gps_type.h"
+#include "gps_dbg_log.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "MNLD_DUMP"
+#endif
+
+#define MNLD_DUMP_FILE_LEN 128
+
+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) {
+#if defined(__ANDROID_OS__)
+    android::ProcessCallStack pcs;
+    pcs.update();
+    if(dump_fd != -1) {
+        pcs.dump(dump_fd, 0, NULL);  //Dump to file
+    } else {
+        pcs.log(LOG_TAG, ANDROID_LOG_DEBUG, NULL);  //Dump to mainlog
+    }
+#endif
+}
+
+/*****************************************************************************
+ * 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
+#if defined(__ANDROID_OS__)
+    android::CallStack stack;
+    stack.update(0, tid);
+    if(dump_fd != -1) {
+        stack.dump(dump_fd, 0, NULL);  //Dump to file
+    } else {
+        stack.log(LOG_TAG, ANDROID_LOG_DEBUG, NULL);  //Dump to mainlog
+    }
+#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)
+{
+    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);
+    }
+    gps_dbg_log_exit_flush(0);
+    _exit(0);
+}
diff --git a/src/connectivity/gps/mtk_mnld/utility/src/mtk_socket_data_coder.c b/src/connectivity/gps/mtk_mnld/utility/src/mtk_socket_data_coder.c
new file mode 100644
index 0000000..c641f22
--- /dev/null
+++ b/src/connectivity/gps/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, 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/mtk_mnld/utility/src/mtk_socket_utils.c b/src/connectivity/gps/mtk_mnld/utility/src/mtk_socket_utils.c
new file mode 100644
index 0000000..30aee1e
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/src/mtk_socket_utils.c
@@ -0,0 +1,611 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#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>
+
+#include "mtk_socket_utils.h"
+#include "mtk_socket_data_coder.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mtk_socket"
+#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) {
+        LOGE("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) {
+        LOGE("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) {
+        LOGE("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) {
+        LOGE("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) {
+        LOGE("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) {
+        strcpy(addr.sun_path, path);
+        unlink(addr.sun_path);
+    } else {
+        LOGE("unknown namespace=[%d]", sock_namespace);
+        close(fd);
+        return -1;
+    }
+    if (bind(fd, (struct sockaddr *)&addr, size) == -1) {
+        LOGE("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);
+    strcpy(sock_fd->host, host);
+    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);
+    strcpy(sock_fd->path, path);
+    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) {
+        LOGE("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) {
+        strcpy(addr.sun_path, sock_fd->path);
+    } else {
+        LOGE("unknown namespace=[%d]", sock_fd->namesapce);
+        close(fd);
+        return false;
+    }
+    if (connect(fd, (struct sockaddr *)&addr, size) < 0) {
+        LOGE("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) {
+        LOGE("socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+    //LOGD("IPv4=[%s] port=[%d]", ip_str, port);
+    if (connect(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
+        LOGE("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) {
+        LOGE("socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+    //unsigned char* ipv6_addr = addr->sin6_addr.s6_addr;
+    //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("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) {
+        LOGE("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) {
+        LOGE("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:
+    LOGE("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) {
+        LOGE("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:
+    LOGE("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};
+    LOGD("len=%d", len);
+    for(i = 0; i < len; i++) {
+        if((i % 16 == 0) && (i != 0)) {
+            LOGD("  %s", tmp);
+            memset(tmp, 0, sizeof(tmp));
+        }
+        sprintf(tmp + ((i % 16) * 3), "%02x ", buff[i] & 0xff);
+    }
+    if(i > 0) {
+        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;
+    LOGD("size=%d", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%d]", i, input[i]);
+    }
+}
+
+void mtk_socket_char_array_dump(char input[], int size) {
+    int i = 0;
+    LOGD("size=%d", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%d]", i, input[i] & 0xff);
+    }
+}
+
+void mtk_socket_short_array_dump(short input[], int size) {
+    int i = 0;
+    LOGD("size=%d", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%d]", i, input[i] & 0xffff);
+    }
+}
+
+void mtk_socket_int_array_dump(int input[], int size) {
+    int i = 0;
+    LOGD("size=%d", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%d]", i, input[i]);
+    }
+}
+
+void mtk_socket_int64_t_array_dump(int64_t input[], int size) {
+    int i = 0;
+    LOGD("size=%d", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%lld]", i, (long long)input[i]);
+    }
+}
+
+void mtk_socket_float_array_dump(float input[], int size) {
+    int i = 0;
+    LOGD("size=%d", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%f]", i, input[i]);
+    }
+}
+
+void mtk_socket_double_array_dump(double input[], int size) {
+    int i = 0;
+    LOGD("size=%d", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%f]", i, input[i]);
+    }
+}
+
+void mtk_socket_string_array_dump(void* input, int size1, int size2) {
+    int i = 0;
+    LOGD("size1=%d size2=%d", size1, size2);
+    for(i = 0; i < size1; i++) {
+        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) {
+        LOGE("%s():%d 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) {
+        LOGE("%s():%d 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) {
+        LOGE("%s():%d 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) {
+        LOGE("%s():%d 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) {
+        LOGE("%s():%d 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) {
+        LOGE("%s():%d 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) {
+        LOGE("%s():%d 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) {
+        LOGE("%s():%d failed, read=[%s], expected=[%s]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}