[Feature] add GA346 baseline version

Change-Id: Ic62933698569507dcf98240cdf5d9931ae34348f
diff --git a/src/devtools/meta/NOTICE b/src/devtools/meta/NOTICE
new file mode 100644
index 0000000..17cd927
--- /dev/null
+++ b/src/devtools/meta/NOTICE
@@ -0,0 +1,23 @@
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other materials provided with the distribution.
+    * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
diff --git a/src/devtools/meta/files/meta_tst.init b/src/devtools/meta/files/meta_tst.init
new file mode 100644
index 0000000..a604ccf
--- /dev/null
+++ b/src/devtools/meta/files/meta_tst.init
@@ -0,0 +1,16 @@
+#!/bin/sh /etc/rc.common
+
+START=98
+
+USE_PROCD=1
+NAME=meta_tst
+PROG=/usr/bin/meta_tst
+
+start_service() {
+	echo "start meta_tst"
+	procd_open_instance
+	procd_set_param command /usr/bin/meta_tst
+	procd_set_param stdout 1
+	procd_set_param stderr 1
+	procd_close_instance
+}
diff --git a/src/devtools/meta/src/LICENSE b/src/devtools/meta/src/LICENSE
new file mode 100644
index 0000000..77f59ed
--- /dev/null
+++ b/src/devtools/meta/src/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/devtools/meta/src/Makefile b/src/devtools/meta/src/Makefile
new file mode 100644
index 0000000..f994290
--- /dev/null
+++ b/src/devtools/meta/src/Makefile
@@ -0,0 +1,61 @@
+TARGET := meta_tst
+
+FLAGS += -DFT_GPS_FEATURE
+FLAGS += -DFT_NVRAM_FEATURE
+
+INCLUDES += \
+            -I./common/inc \
+            -I./misc/snappy \
+            -I./adaptor/gps \
+            -I./adaptor/Meta_APEditor \
+            -I../../../libnvram/1.0.0-r0/libnvram-1.0.0/libfile_op \
+            -I../../../libnvram/1.0.0-r0/libnvram-1.0.0/libnvram \
+
+SRCS := \
+
+
+CXXSRCS := \
+            ./common/src/tst_main.cpp \
+            ./common/src/CmdTarget.cpp \
+            ./common/src/Context.cpp \
+            ./common/src/Device.cpp \
+            ./common/src/Frame.cpp \
+            ./common/src/FtModule.cpp \
+            ./common/src/MdRxWatcher.cpp \
+            ./common/src/Modem.cpp \
+            ./common/src/SerPort.cpp \
+            ./common/src/UsbRxWatcher.cpp \
+            ./common/src/PortHandle.cpp \
+            ./common/src/MSocket.cpp \
+            ./common/src/Meta_mipc.cpp \
+            ./misc/snappy/snappy-sinksource.cpp \
+            ./misc/snappy/snappy-stubs-internal.cpp \
+            ./misc/snappy/snappy.cpp \
+            ./misc/snappy/snappy-c.cpp \
+            ./adaptor/gps/meta_gps.cpp \
+            ./adaptor/Meta_APEditor/Meta_APEditor_Para.c \
+
+EXTRA_CXXFLAGS := -std=c++11
+
+OBJS := ${SRCS:%.c=%.o}
+
+CXXOBJS := ${CXXSRCS:%.cpp=%.o}
+
+LDFLAGS += -L. -lz -ldl -lpthread
+
+.PHONY: all
+all : $(TARGET)
+
+${TARGET}: $(OBJS) $(CXXOBJS)
+	$(CXX) $(OBJS) $(CXXOBJS) $(LDFLAGS) $(LIBS) $(CFLAGS) -o $@ $(INCLUDES)
+
+%.o: %.c
+	${CC} $(CFLAGS) -c $< -o $@ $(INCLUDES) $(FLAGS)
+	
+%.o: %.cpp
+	${CXX} $(CXXFLAGS) $(CFLAGS) -c $< -o $@ $(INCLUDES) $(FLAGS) $(EXTRA_CXXFLAGS)
+
+.PHONY: clean
+clean:
+	$(warning "makefile meta_tst clean")
+	rm -rf $(OBJS) $(CXXOBJS) $(TARGET)
diff --git a/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.c b/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.c
new file mode 100644
index 0000000..9544120
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.c
@@ -0,0 +1,206 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include "libnvram.h"
+#include "libnvram_log.h"
+#include "MetaPub.h"
+#include "Meta_APEditor_Para.h"
+#include "errno.h"
+
+
+//-----------------------------------------------------------------------------
+bool META_Editor_Init(void)
+{
+	return true;
+}
+//-----------------------------------------------------------------------------
+bool META_Editor_Deinit(void)
+{
+	return true;
+}
+//-----------------------------------------------------------------------------
+bool META_Editor_ReadFile_OP(FT_AP_Editor_read_req *pReq)
+{
+	FT_AP_Editor_read_cnf kCnf;
+	F_INFO kFileInfo;
+	int iNvmRecSize = 0, iReadSize;
+	F_ID iFD;
+	char* pBuffer = NULL;
+	bool IsRead =true;
+
+	memset(&kCnf, 0, sizeof(FT_AP_Editor_read_cnf));
+	kCnf.header.id 		= pReq->header.id + 1;
+	kCnf.header.token 	= pReq->header.token;
+	kCnf.file_idx 		= pReq->file_idx;
+	kCnf.para 			= pReq->para;
+	
+	iFD = NVM_GetFileDesc(pReq->file_idx,&(kFileInfo.i4RecSize),&(kFileInfo.i4RecNum),IsRead);
+	if (iFD.iFileDesc == -1) 
+    {
+		NVRAM_LOG("Error AP_Editor_ReadFile can't open file: file index-%d, %d\n", pReq->file_idx, iNvmRecSize);
+		kCnf.status = META_FAILED;
+		WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), NULL, 0);
+		return false;		
+	}
+	iNvmRecSize = kFileInfo.i4RecSize;
+    
+	if (pReq->para > kFileInfo.i4RecNum) 
+    {
+		NVRAM_LOG("Error AP_Editor_ReadFile para: %d, %d\n", pReq->file_idx, pReq->para);
+		NVM_CloseFileDesc(iFD);
+		kCnf.status = META_FAILED;
+		WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), NULL, 0);
+		return false;
+	}
+
+    /* Open NVRAM realted files */
+	pBuffer = (char*)malloc(iNvmRecSize);
+    if (pBuffer == NULL) {
+        NVRAM_LOG("Error AP_Editor_ReadFile:memory malloc error\r\n");
+        return false;
+    }
+	if (lseek(iFD.iFileDesc, (pReq->para - 1) * iNvmRecSize, SEEK_CUR) < 0) {
+		NVRAM_LOG("Error AP_Editor_ReadFile :seek fail,error:%s\n",strerror(errno));
+		NVM_CloseFileDesc(iFD);
+		kCnf.status = META_FAILED;
+		WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), NULL, 0);
+		free(pBuffer);
+		return false;
+	}
+
+	iReadSize=read(iFD.iFileDesc, pBuffer, iNvmRecSize);
+	if(iNvmRecSize != iReadSize){
+		NVRAM_LOG("Error AP_Editor_ReadFile :Read size not match:iReadSize(%d),iNvmRecSize(%d),error:%s\n",iReadSize,iNvmRecSize,strerror(errno));
+		NVM_CloseFileDesc(iFD);
+		kCnf.status = META_FAILED;
+		WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), NULL, 0);
+		free(pBuffer);
+		return false;
+	}
+		
+	NVM_CloseFileDesc(iFD);
+
+	kCnf.read_status = META_STATUS_SUCCESS;
+	kCnf.status = META_SUCCESS;
+
+	WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), pBuffer, iNvmRecSize);
+
+	NVRAM_LOG("AP_Editor_ReadFile result: file_idx ~ %d para ~ %d read ~ %d\n", pReq->file_idx, pReq->para, iReadSize);
+	free(pBuffer);
+
+	return true;
+}
+//-----------------------------------------------------------------------------
+FT_AP_Editor_write_cnf	META_Editor_WriteFile_OP(
+	FT_AP_Editor_write_req *pReq,
+    char *peer_buf,
+    unsigned short peer_len)
+{
+	FT_AP_Editor_write_cnf kCnf;
+	F_INFO kFileInfo;
+	int iNvmRecSize = 0, iWriteSize;
+	F_ID iFD;
+	bool IsRead = false;
+
+	memset(&kCnf, 0, sizeof(FT_AP_Editor_write_cnf));
+	kCnf.file_idx 		= pReq->file_idx;
+	kCnf.para 			= pReq->para;
+	
+	if ((peer_buf == NULL) || (peer_len == 0)) {
+		NVRAM_LOG("Error AP_Editor_WriteFile Peer Buffer Error\n");
+		kCnf.status = META_FAILED;
+		return kCnf;
+	}
+	
+	iFD = NVM_GetFileDesc(pReq->file_idx,&(kFileInfo.i4RecSize),&(kFileInfo.i4RecNum),IsRead);
+	if (iFD.iFileDesc == -1) {
+		NVRAM_LOG("Error AP_Editor_WriteFile can't open file: file index-%d, %d\n", 
+			pReq->file_idx, iNvmRecSize);
+		kCnf.status = META_FAILED;
+		return kCnf;
+	}
+	iNvmRecSize = kFileInfo.i4RecSize;
+	if ((pReq->para > kFileInfo.i4RecNum) || (peer_len > kFileInfo.i4RecSize)) {
+		NVRAM_LOG("Error AP_Editor_WriteFile para: %d, %d, %d\n", pReq->file_idx, pReq->para, peer_len);
+		NVM_CloseFileDesc(iFD);
+		kCnf.status = META_FAILED;
+		return kCnf;
+
+	}
+	if (lseek(iFD.iFileDesc, (pReq->para - 1) * iNvmRecSize, SEEK_CUR) < 0) {
+		NVRAM_LOG("Error AP_Editor_WriteFile :seek fail,error:%s\n",strerror(errno));
+		NVM_CloseFileDesc(iFD);
+		kCnf.status = META_FAILED;
+		return kCnf;
+	}
+
+	iWriteSize = write(iFD.iFileDesc, peer_buf, iNvmRecSize);
+	if(iNvmRecSize != iWriteSize){
+		NVRAM_LOG("Error AP_Editor_WriteFile :Write size not match:iWriteSize(%d),iNvmRecSize(%d),error:%s\n",iWriteSize,iNvmRecSize,strerror(errno));
+		NVM_CloseFileDesc(iFD);
+		kCnf.status = META_FAILED;
+		return kCnf;
+	}
+	NVM_CloseFileDesc(iFD);
+
+	kCnf.write_status = META_STATUS_SUCCESS;
+	kCnf.status = META_SUCCESS;
+
+	NVRAM_LOG("AP_Editor_WriteFile result: file_idx-%d para-%d write-%d\n", pReq->file_idx, pReq->para, iWriteSize);
+	NVRAM_LOG("AddBackupFileNum Begin");
+	NVM_AddBackupFileNum(pReq->file_idx);
+	NVRAM_LOG("AddBackupFileNum End");
+	return kCnf;
+}
+//-----------------------------------------------------------------------------
+FT_AP_Editor_reset_cnf	META_Editor_ResetFile_OP(FT_AP_Editor_reset_req *pReq)
+{
+	FT_AP_Editor_reset_cnf kCnf;
+
+	memset(&kCnf, 0, sizeof(FT_AP_Editor_reset_cnf));
+	if (!NVM_ResetFileToDefault(pReq->file_idx)) 
+    {
+		printf("Error AP_Editor_ResetFile\n");
+		kCnf.status = META_FAILED;
+		return kCnf;
+	}
+
+	kCnf.status = META_SUCCESS;
+	return kCnf;
+}
+//-----------------------------------------------------------------------------
+FT_AP_Editor_reset_cnf	META_Editor_ResetAllFile_OP(FT_AP_Editor_reset_req *pReq)
+{
+	int i;
+	FT_AP_Editor_reset_cnf kCnf;
+	FT_AP_Editor_reset_req kReq;
+	
+	F_INFO kFileInfo = NVM_ReadFileVerInfo(0);
+
+	memset(&kCnf, 0, sizeof(FT_AP_Editor_reset_cnf));
+	memset(&kReq, 0, sizeof(FT_AP_Editor_reset_req));
+    
+	if ((pReq->file_idx != 0xFCCF) || (pReq->reset_category != 0xFC)) 
+    {
+		kCnf.status = META_FAILED;
+		NVRAM_LOG("Error AP_Editor_ResetAllFile para is wrong - %d", pReq->file_idx);
+		return kCnf;
+	}
+
+	for (i = 0; i < kFileInfo.i4MaxFileLid; ++i) 
+    {
+		kReq.file_idx = i;
+		kCnf = META_Editor_ResetFile_OP(&kReq);
+		if (kCnf.status == META_FAILED) {
+			NVRAM_LOG("Error AP_Editor_ResetAllFile: file_idx-%d\n", kReq.file_idx);
+			return kCnf;			
+		}
+	}
+
+	return kCnf;
+}
+//-----------------------------------------------------------------------------
diff --git a/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.cpp b/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.cpp
new file mode 100644
index 0000000..4ba7079
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.cpp
@@ -0,0 +1,299 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include "libnvram.h"
+#include "libnvram_log.h"
+#include "MetaPub.h"
+#include "Meta_APEditor_Para.h"
+#include "errno.h"
+#if 1
+#include <vendor/mediatek/hardware/nvram/1.1/INvram.h>
+#include "cutils/log.h"
+#include <vector>
+#include <stdint.h>
+#include <android-base/logging.h>
+
+using std::string;
+
+
+static void covertArray2Vector(const char* in, int len, std::vector<uint8_t>& out) {
+    out.clear();
+    for(int i = 0; i < len; i++) {
+       out.push_back(in[i]);
+    }
+}
+static void covertVector2Array(std::vector<uint8_t> in, char* out) {
+	int size = in.size();
+	for(int i = 0; i < size; i++) {
+		out[i] = in.at(i);
+	}
+}
+#endif
+
+
+//-----------------------------------------------------------------------------
+bool META_Editor_Init(void)
+{
+	return true;
+}
+//-----------------------------------------------------------------------------
+bool META_Editor_Deinit(void)
+{
+	return true;
+}
+
+//readFileById(int32_t lid, uint16_t para)			generates (string data, int32_t readsize, int8_t retval);
+
+//-----------------------------------------------------------------------------
+bool META_Editor_ReadFile_OP(FT_AP_Editor_read_req *pReq)
+{
+#if 1
+	FT_AP_Editor_read_cnf kCnf;
+	F_INFO kFileInfo;
+	int iNvmRecSize = 0, iReadSize;
+	F_ID iFD;
+	char* pBuffer = NULL;
+	char* ptempbuf = NULL;
+	bool IsRead =true;
+    using ::vendor::mediatek::hardware::nvram::V1_1::INvram;
+    android::sp<INvram> client = INvram::getService();
+
+    if (client == NULL) {
+	 LOG(INFO) << "client is NULL";
+    }
+
+	char *nvrambuff=NULL;
+	std::vector<uint8_t> nvramvec;
+	int ret=0;
+    int Readsize = 0;
+	std::string readnvram;
+	int i =0;
+	memset(&kCnf, 0, sizeof(FT_AP_Editor_read_cnf));
+	kCnf.header.id 		= pReq->header.id + 1;
+	kCnf.header.token 	= pReq->header.token;
+	kCnf.file_idx 		= pReq->file_idx;
+	kCnf.para 			= pReq->para;
+
+	auto callback = [&] (const std::string& data, int32_t readsize, int8_t retval) {
+		 readnvram=data;
+		 ret=(int)retval;
+		 Readsize=(int)readsize;
+		//NVRAM_LOG("readnvram %s readsize %d retval%d\n", readnvram, readsize, retval);
+		LOG(INFO) << "readnvram@1:" << readnvram;
+		
+	};
+	client->readFileBylid(pReq->file_idx,pReq->para,callback);
+	NVRAM_LOG("ret=%d, Readsize=%d\n", ret, Readsize);
+#if 0	
+	iFD = NVM_GetFileDesc(pReq->file_idx,&(kFileInfo.i4RecSize),&(kFileInfo.i4RecNum),IsRead);
+	if (iFD.iFileDesc == -1) 
+    {
+		NVRAM_LOG("Error AP_Editor_ReadFile can't open file: file index-%d, %d\n", pReq->file_idx, iNvmRecSize);
+		kCnf.status = META_FAILED;
+		WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), NULL, 0);
+		return false;		
+	}
+	iNvmRecSize = kFileInfo.i4RecSize;
+    
+	if (pReq->para > kFileInfo.i4RecNum) 
+    {
+		NVRAM_LOG("Error AP_Editor_ReadFile para: %d, %d\n", pReq->file_idx, pReq->para);
+		NVM_CloseFileDesc(iFD);
+		kCnf.status = META_FAILED;
+		WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), NULL, 0);
+		return false;
+	}
+
+    /* Open NVRAM realted files */
+	pBuffer = (char*)malloc(iNvmRecSize);
+    if (pBuffer == NULL) {
+        NVRAM_LOG("Error AP_Editor_ReadFile:memory malloc error\r\n");
+        return false;
+    }
+	lseek(iFD.iFileDesc, (pReq->para - 1) * iNvmRecSize, SEEK_CUR);
+	iReadSize=read(iFD.iFileDesc, pBuffer, iNvmRecSize);
+	if(iNvmRecSize != iReadSize){
+		NVRAM_LOG("Error AP_Editor_ReadFile :Read size not match:iReadSize(%d),iNvmRecSize(%d),error:%s\n",iReadSize,iNvmRecSize,strerror(errno));
+		NVM_CloseFileDesc(iFD);
+		kCnf.status = META_FAILED;
+		WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), NULL, 0);
+		free(pBuffer);
+		return false;
+	}
+		
+	NVM_CloseFileDesc(iFD);
+	
+#endif
+	kCnf.read_status = META_STATUS_SUCCESS;
+	kCnf.status = META_SUCCESS;
+	pBuffer = (char*)malloc(Readsize);
+	ptempbuf = (char*)malloc(2*Readsize+1);
+	//char *cstr = new char[str.length() + 1];	
+	strncpy(ptempbuf, readnvram.c_str(), 2*Readsize);
+	ptempbuf[2*Readsize] = '\0';
+
+	NVRAM_LOG("ptempbuf[0]%x, ptempbuf[1]%x, ptempbuf[2]%x, ptempbuf[3]%x, ptempbuf[4]%x, ptempbuf[5]%x, ptempbuf[6]%x, ptempbuf[7]%x, ptempbuf[8]%x \n",
+		ptempbuf[0],ptempbuf[1],ptempbuf[2],ptempbuf[3],ptempbuf[4],ptempbuf[5],ptempbuf[6],ptempbuf[7],ptempbuf[8]);
+	
+	for(i=0;i<2*Readsize; i+=2)
+		{
+		sscanf(ptempbuf+i, "%02X", &pBuffer[i/2]);
+		}
+	NVRAM_LOG("pBuffer[0]%x, pBuffer[1]%x, pBuffer[2]%x, pBuffer[3]%x, pBuffer[4]%x, pBuffer[5]%x, pBuffer[6]%x, pBuffer[7]%x, pBuffer[8]%x \n",
+		pBuffer[0],pBuffer[1],pBuffer[2],pBuffer[3],pBuffer[4],pBuffer[5],pBuffer[6],pBuffer[7],pBuffer[8]);
+	
+
+	//covertVector2Array(readnvram,pBuffer);
+
+	//WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), pBuffer, iNvmRecSize);
+	WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), pBuffer, Readsize);
+
+	NVRAM_LOG("AP_Editor_ReadFile result: file_idx ~ %d para ~ %d read ~ %d\n", pReq->file_idx, pReq->para, Readsize);
+	free(pBuffer);
+#endif
+	return true;
+}
+//-----------------------------------------------------------------------------
+FT_AP_Editor_write_cnf	META_Editor_WriteFile_OP(
+	FT_AP_Editor_write_req *pReq,
+    char *peer_buf,
+    unsigned short peer_len)
+{
+	FT_AP_Editor_write_cnf kCnf;
+	F_INFO kFileInfo;
+	int iNvmRecSize = 0, iWriteSize;
+	F_ID iFD;
+	bool IsRead = false;
+    std::vector<uint8_t> nvramvec;
+    int ret=0;
+    using ::vendor::mediatek::hardware::nvram::V1_1::INvram;
+    android::sp<INvram> client = INvram::getService();
+
+	memset(&kCnf, 0, sizeof(FT_AP_Editor_write_cnf));
+	kCnf.file_idx 		= pReq->file_idx;
+	kCnf.para 			= pReq->para;
+	
+	if ((peer_buf == NULL) || (peer_len == 0)) {
+		NVRAM_LOG("Error AP_Editor_WriteFile Peer Buffer Error\n");
+		kCnf.status = META_FAILED;
+		return kCnf;
+	}
+	
+#if 0	
+	iFD = NVM_GetFileDesc(pReq->file_idx,&(kFileInfo.i4RecSize),&(kFileInfo.i4RecNum),IsRead);
+	if (iFD.iFileDesc == -1) {
+		NVRAM_LOG("Error AP_Editor_WriteFile can't open file: file index-%d, %d\n", 
+			pReq->file_idx, iNvmRecSize);
+		kCnf.status = META_FAILED;
+		return kCnf;
+	}
+	iNvmRecSize = kFileInfo.i4RecSize;
+	if ((pReq->para > kFileInfo.i4RecNum) || (peer_len > kFileInfo.i4RecSize)) {
+		NVRAM_LOG("Error AP_Editor_WriteFile para: %d, %d, %d\n", pReq->file_idx, pReq->para, peer_len);
+		NVM_CloseFileDesc(iFD);
+		kCnf.status = META_FAILED;
+		return kCnf;
+
+	}
+	lseek(iFD.iFileDesc, (pReq->para - 1) * iNvmRecSize, SEEK_CUR);
+	iWriteSize = write(iFD.iFileDesc, peer_buf, iNvmRecSize);
+	if(iNvmRecSize != iWriteSize){
+		NVRAM_LOG("Error AP_Editor_WriteFile :Write size not match:iWriteSize(%d),iNvmRecSize(%d),error:%s\n",iWriteSize,iNvmRecSize,strerror(errno));
+		NVM_CloseFileDesc(iFD);
+		kCnf.status = META_FAILED;
+		return kCnf;
+	}
+	NVM_CloseFileDesc(iFD);
+#else
+auto callback = [&] (int32_t writesize, int8_t retval) {
+	 ret=(int)retval;
+	 iWriteSize=(int)writesize;
+};
+covertArray2Vector(peer_buf,peer_len,nvramvec);
+
+
+client->writeFileBylid(pReq->file_idx,pReq->para,nvramvec,callback);
+NVRAM_LOG("ret=%d, iWriteSize=%d\n", ret, iWriteSize);
+
+
+#endif
+
+	kCnf.write_status = META_STATUS_SUCCESS;
+if(ret == 0)
+	kCnf.status = META_SUCCESS;
+else
+	kCnf.status = META_FAILED;
+
+	NVRAM_LOG("AP_Editor_WriteFile result: file_idx-%d para-%d write-%d\n", pReq->file_idx, pReq->para, iWriteSize);
+	NVRAM_LOG("AddBackupFileNum Begin");
+	//NVM_AddBackupFileNum(pReq->file_idx);
+	ret=client->AddBackupFileNum(pReq->file_idx);
+	NVRAM_LOG("AddBackupFileNum End ret=%d",ret);
+	return kCnf;
+}
+//-----------------------------------------------------------------------------
+FT_AP_Editor_reset_cnf	META_Editor_ResetFile_OP(FT_AP_Editor_reset_req *pReq)
+{
+	FT_AP_Editor_reset_cnf kCnf;
+    using ::vendor::mediatek::hardware::nvram::V1_1::INvram;
+    android::sp<INvram> client = INvram::getService();
+
+	memset(&kCnf, 0, sizeof(FT_AP_Editor_reset_cnf));
+	//if (!NVM_ResetFileToDefault(pReq->file_idx)) 
+	if (!client->ResetFileToDefault(pReq->file_idx))
+    {
+		printf("Error AP_Editor_ResetFile\n");
+		kCnf.status = META_FAILED;
+		return kCnf;
+	}
+
+	kCnf.status = META_SUCCESS;
+	return kCnf;
+}
+//-----------------------------------------------------------------------------
+FT_AP_Editor_reset_cnf	META_Editor_ResetAllFile_OP(FT_AP_Editor_reset_req *pReq)
+{
+	int i;
+	FT_AP_Editor_reset_cnf kCnf;
+	FT_AP_Editor_reset_req kReq;
+	#if 0
+	F_INFO kFileInfo = NVM_ReadFileVerInfo(0);
+	#else
+    using ::vendor::mediatek::hardware::nvram::V1_1::INvram;
+    android::sp<INvram> client = INvram::getService();
+    int FileInfoRecSize = 0, FileInfoRecNum= 0, FileInfoMaxFileLid = 0;
+	auto callback = [&] (int32_t i4RecSize, int32_t i4RecNum, int32_t i4MaxFileLid) {
+	 FileInfoRecSize=(int)i4RecSize;
+	 FileInfoRecNum=(int)i4RecNum;
+	 FileInfoMaxFileLid=(int)i4MaxFileLid;
+};
+    client->ReadFileVerInfo(0,callback);
+	NVRAM_LOG("FileInfoRecSize %d, FileInfoRecNum %d, FileInfoMaxFileLid %d", FileInfoRecSize,FileInfoRecNum,FileInfoMaxFileLid);
+    #endif
+	memset(&kCnf, 0, sizeof(FT_AP_Editor_reset_cnf));
+	memset(&kReq, 0, sizeof(FT_AP_Editor_reset_req));
+    
+	if ((pReq->file_idx != 0xFCCF) || (pReq->reset_category != 0xFC)) 
+    {
+		kCnf.status = META_FAILED;
+		NVRAM_LOG("Error AP_Editor_ResetAllFile para is wrong - %d", pReq->file_idx);
+		return kCnf;
+	}
+
+	//for (i = 0; i < kFileInfo.i4MaxFileLid; ++i) 
+	for (i = 0; i < FileInfoMaxFileLid; ++i) 
+    {
+		kReq.file_idx = i;
+		kCnf = META_Editor_ResetFile_OP(&kReq);
+		if (kCnf.status == META_FAILED) {
+			NVRAM_LOG("Error AP_Editor_ResetAllFile: file_idx-%d\n", kReq.file_idx);
+			return kCnf;			
+		}
+	}
+
+	return kCnf;
+}
+//-----------------------------------------------------------------------------
diff --git a/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.h b/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.h
new file mode 100644
index 0000000..c43e5b4
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.h
@@ -0,0 +1,246 @@
+/*****************************************************************************
+*  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).
+*
+*****************************************************************************/
+
+
+/*******************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   Meta_APEditor.h
+ *
+ * Project:
+ * --------
+ *   DUMA
+ *
+ * Description:
+ * ------------
+ *    header file of main function
+ *
+ * Author:
+ * -------
+ *   Nick Huang (mtk02183) 12/09/2009
+ *
+ *******************************************************************************/
+
+
+#ifndef __AP_EDITOR_PARA_H__
+#define __AP_EDITOR_PARA_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+    /********************************************
+    * Generic Primitives for AP_Editor READ/WRITE
+    ********************************************/
+
+    typedef struct
+    {
+        FT_H			header;         //the header of ft module
+        unsigned short  file_idx;       // file lid
+        unsigned short  para;           //record id
+    } FT_AP_Editor_read_req;
+
+    typedef struct
+    {
+        FT_H			header;         //the header of ft module
+        unsigned short  file_idx;       //file lid
+        unsigned short  para;           //record id
+        unsigned char   read_status;    //read nvram file status: 0 is fail
+        unsigned char	status;         //the status of ft module:  0 is success
+    } FT_AP_Editor_read_cnf;
+
+
+    typedef struct
+    {
+        FT_H			header;         //the header of ft module
+        unsigned short  file_idx;       //file lid
+        unsigned short  para;           //record id
+    } FT_AP_Editor_write_req;
+
+    typedef struct
+    {
+        FT_H			header;         //the header of ft module
+        unsigned short  file_idx;       //file lid
+        unsigned short  para;           //record id
+        unsigned char   write_status;   //the write status
+        unsigned char	status;         //the status of ft module:  0 is success
+    } FT_AP_Editor_write_cnf;
+
+
+    typedef struct
+    {
+        FT_H			header;         //the header of ft module
+        unsigned char	reset_category;	//0xff indicate reset all files
+        unsigned short	file_idx;   	//0xffff indicate reset all files
+    } FT_AP_Editor_reset_req;
+
+    typedef struct
+    {
+        FT_H			header;         //the header of ft module
+        unsigned char	reset_status;   //the status of reset file to default value
+        unsigned char	status;         //the status of ft module, 0 is success
+    } FT_AP_Editor_reset_cnf;
+
+
+    /* implement these functions in AP_Editor.LIB  */
+    /********************************************************************************
+    //FUNCTION:
+    //		META_Editor_Init
+    //DESCRIPTION:
+    //		this function is called to initial the meta_editor module.
+    //
+    //PARAMETERS:
+    //		None
+    //
+    //RETURN VALUE:
+    //		TRUE: is scuccess, otherwise is fail
+    //
+    //DEPENDENCY:
+    //		None
+    //
+    //GLOBALS AFFECTED
+    //		None
+    ********************************************************************************/
+    bool 					META_Editor_Init(void);
+
+
+    /********************************************************************************
+    //FUNCTION:
+    //		META_Editor_Deinit
+    //DESCRIPTION:
+    //		this function is called to de-initial the meta_editor module.
+    //
+    //PARAMETERS:
+    //		None
+    //
+    //RETURN VALUE:
+    //		TRUE: is scuccess, otherwise is fail
+    //
+    //DEPENDENCY:
+    //		META_Editor_Init must have been called
+    //
+    //GLOBALS AFFECTED
+    //		None
+    ********************************************************************************/
+    bool 					META_Editor_Deinit(void);
+
+    /********************************************************************************
+    //FUNCTION:
+    //		META_Editor_ReadFile_OP
+    //DESCRIPTION:
+    //		this function is called to Read a record of NvRam file from Target side to PC.
+    //
+    //PARAMETERS:
+    //		req:
+    //
+    //RETURN VALUE:
+    //		TRUE: is scuccess, otherwise is fail. the data will be send to PC in the function body
+    //
+    //DEPENDENCY:
+    //		META_Editor_Init must have been called
+    //
+    //GLOBALS AFFECTED
+    ********************************************************************************/
+    bool					META_Editor_ReadFile_OP(FT_AP_Editor_read_req *req);
+
+    /********************************************************************************
+    //FUNCTION:
+    //		META_Editor_WriteFile_OP
+    //DESCRIPTION:
+    //		this function is called to write a record of NvRam file from PC side to Target.
+    //
+    //PARAMETERS:
+    //		None
+    //
+    //RETURN VALUE:
+    //		refers to the definition of "FT_AP_Editor_write_cnf"
+    //
+    //DEPENDENCY:
+    //		META_Editor_Init must have been called
+    //
+    //GLOBALS AFFECTED
+    //		None
+    ********************************************************************************/
+    FT_AP_Editor_write_cnf	META_Editor_WriteFile_OP(FT_AP_Editor_write_req *req,
+            char *peer_buf,
+            unsigned short peer_len);
+
+    /********************************************************************************
+    //FUNCTION:
+    //		META_Editor_ResetFile_OP
+    //DESCRIPTION:
+    //		this function is called to reset a NvRam to default value.
+    //
+    //PARAMETERS:
+    //		None
+    //
+    //RETURN VALUE:
+    //		refers to the definition of "FT_AP_Editor_reset_cnf"
+    //
+    //DEPENDENCY:
+    //		META_Editor_Init must have been called
+    //
+    //GLOBALS AFFECTED
+    //		None
+    ********************************************************************************/
+    FT_AP_Editor_reset_cnf	META_Editor_ResetFile_OP(FT_AP_Editor_reset_req *req);
+
+    /********************************************************************************
+    //FUNCTION:
+    //		META_Editor_ResetAllFile_OP
+    //DESCRIPTION:
+    //		this function is called to Reset all of NvRam files to default value.
+    //
+    //PARAMETERS:
+    //		None
+    //
+    //RETURN VALUE:
+    //		refers to the definition of "FT_AP_Editor_reset_cnf"
+    //
+    //DEPENDENCY:
+    //		META_Editor_Init must have been called
+    //
+    //GLOBALS AFFECTED
+    //		None
+    ********************************************************************************/
+    FT_AP_Editor_reset_cnf	META_Editor_ResetAllFile_OP(FT_AP_Editor_reset_req *req);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/devtools/meta/src/adaptor/Meta_APEditor/README b/src/devtools/meta/src/adaptor/Meta_APEditor/README
new file mode 100644
index 0000000..782e903
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/Meta_APEditor/README
@@ -0,0 +1,19 @@
+
+
+
+WHAT IT DOES?
+=============
+libmeta_apeditor is a static library which offer a interface for meta tool to access nvram
+
+
+HOW IT WAS BUILT?
+==================
+depend on library libc libnvram libft
+need to include header file in  
+$(MTK_PATH_SOURCE)/external/meta/common/inc\
+$(MTK_PATH_SOURCE)/external/nvram/libnvram
+
+HOW TO USE IT?
+==============
+
+include this staic library by adding BUILD_STATIC_LIBRARY in your Android.mk
diff --git a/src/devtools/meta/src/adaptor/bluetooth/README b/src/devtools/meta/src/adaptor/bluetooth/README
new file mode 100644
index 0000000..8b558c1
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/bluetooth/README
@@ -0,0 +1,33 @@
+This directory contains BT Meta mode test library
+
+
+WHAT IT DOES?
+=============
+It provide BT test feature on meta mode, including BT power on/off, write/read and some other functions.
+
+HOW IT WAS BUILT?
+==================
+
+It needs the following libs from AOSP:
+1. libc.so
+2. libcutils
+3. libnetutils
+
+and the following libs from MediaTek:
+1. libft.a
+
+
+HOW TO USE IT?
+==============
+
+Files in this directory is used to
+generate a library which's name is 'libmeta_bluetooth'
+
+
+libmeta_bluetooth
+The lib  'libmeta_bluetooth' is loaded when target enter meta mode,
+Meta main thread will call META BT APIs, if meta gps tool is launched.
+
+
+All the source code of this library were written by MediaTek co..
+
diff --git a/src/devtools/meta/src/adaptor/bluetooth/meta_bt.c b/src/devtools/meta/src/adaptor/bluetooth/meta_bt.c
new file mode 100644
index 0000000..338b5ba
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/bluetooth/meta_bt.c
@@ -0,0 +1,583 @@
+/* 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) 2014. 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 <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <dlfcn.h>
+
+#include "meta_bt.h"
+
+
+/**************************************************************************
+ *                  G L O B A L   V A R I A B L E S                       *
+***************************************************************************/
+
+static int  bt_fd = -1;
+static BOOL bt_enabled = FALSE;
+static BT_CNF_CB cnf_cb = NULL;
+static BT_CNF bt_cnf;
+
+/* Used to read serial port */
+static pthread_t rxThread;
+static BOOL fgKillThread = FALSE;
+
+/* mtk bt library */
+static void *glib_handle = NULL;
+typedef int (*INIT)(void);
+typedef int (*DEINIT)(int fd);
+typedef int (*WRITE)(int fd, unsigned char *buf, unsigned int len);
+typedef int (*READ)(int fd, unsigned char *buf, unsigned int len);
+typedef int (*GETID)(unsigned int *pChipId, unsigned int *pAdieId);
+
+INIT    meta_bt_init = NULL;
+DEINIT  meta_bt_restore = NULL;
+WRITE   meta_bt_send_data = NULL;
+READ    meta_bt_receive_data = NULL;
+GETID   meta_bt_get_combo_id = NULL;
+
+/**************************************************************************
+ *              F U N C T I O N   D E C L A R A T I O N S                 *
+***************************************************************************/
+static unsigned int BT_Get_On_Off_State(void);
+static BOOL BT_Send_HciCmd(BT_HCI_CMD *pHciCmd);
+static BOOL BT_Recv_HciEvent(BT_HCI_EVENT *pHciEvent);
+static BOOL BT_Send_AclData(BT_HCI_BUFFER *pAclData);
+static BOOL BT_Recv_AclData(BT_HCI_BUFFER *pAclData);
+
+static void* BT_Meta_Thread(void* ptr);
+
+/**************************************************************************
+  *                         F U N C T I O N S                             *
+***************************************************************************/
+
+static void bt_send_resp(BT_CNF *cnf, unsigned short size, void *buf, unsigned short len)
+{
+    if (cnf_cb)
+        cnf_cb(cnf, buf, len);
+    else
+        WriteDataToPC(cnf, size, buf, len);
+}
+
+void META_BT_Register(BT_CNF_CB callback)
+{
+    cnf_cb = callback;
+}
+
+BOOL META_BT_init(void)
+{
+    const char *errstr;
+
+    TRC();
+
+    glib_handle = dlopen("libbluetooth_mtk_pure.so", RTLD_LAZY);
+    if (!glib_handle) {
+        ERR("%s\n", dlerror());
+        goto error;
+    }
+
+    dlerror(); /* Clear any existing error */
+
+    meta_bt_init = dlsym(glib_handle, "bt_init");
+    meta_bt_restore = dlsym(glib_handle, "bt_restore");
+    meta_bt_send_data = dlsym(glib_handle, "bt_send_data");
+    meta_bt_receive_data = dlsym(glib_handle, "bt_receive_data");
+    meta_bt_get_combo_id = dlsym(glib_handle, "wait_connsys_ready");
+
+    if ((errstr = dlerror()) != NULL) {
+        ERR("Can't find function symbols %s\n", errstr);
+        goto error;
+    }
+
+    bt_fd = meta_bt_init();
+    if (bt_fd < 0)
+        goto error;
+
+    DBG("BT is enabled success\n");
+
+    /* Create RX thread */
+    fgKillThread = FALSE;
+    pthread_create(&rxThread, NULL, BT_Meta_Thread, (void*)&bt_cnf);
+
+    bt_enabled = TRUE;
+    sched_yield();
+
+    return TRUE;
+
+error:
+    if (glib_handle) {
+        dlclose(glib_handle);
+        glib_handle = NULL;
+    }
+
+    return FALSE;
+}
+
+void META_BT_deinit(void)
+{
+    TRC();
+
+    /* Stop RX thread */
+    fgKillThread = TRUE;
+    /* Wait until thread exit */
+    pthread_join(rxThread, NULL);
+
+    if (!glib_handle) {
+        ERR("mtk bt library is unloaded!\n");
+    }
+    else {
+        if (bt_fd < 0) {
+            ERR("bt driver fd is invalid!\n");
+        }
+        else {
+            meta_bt_restore(bt_fd);
+            bt_fd = -1;
+        }
+        dlclose(glib_handle);
+        glib_handle = NULL;
+    }
+
+    bt_enabled = FALSE;
+    return;
+}
+
+void META_BT_OP(BT_REQ *req, UNUSED_ATTR char *buf, UNUSED_ATTR unsigned short len)
+{
+    TRC();
+
+    if (NULL == req) {
+        ERR("Invalid arguments or operation!\n");
+        return;
+    }
+
+    memset(&bt_cnf, 0, sizeof(BT_CNF));
+    bt_cnf.header.id = FT_BT_CNF_ID;
+    bt_cnf.header.token = req->header.token;
+    bt_cnf.op = req->op;
+
+    if (req->op == BT_OP_GET_ON_OFF_ST) {
+        DBG("run BT_Get_On_Off_State\n");
+        bt_cnf.result.bt_on_off_state = BT_Get_On_Off_State();
+        bt_cnf.bt_status = TRUE;
+        bt_cnf.status = META_SUCCESS;
+        bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+        return;
+    }
+
+    if (bt_enabled == FALSE) {
+        /*
+           Initialize BT module when it is called first time
+           to avoid the case that PC tool not send BT_OP_INIT
+        */
+        if (META_BT_init() == FALSE) {
+            bt_cnf.bt_status = FALSE;
+            bt_cnf.status = META_FAILED;
+            bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+            return;
+        }
+    }
+
+    switch (req->op)
+    {
+      case BT_OP_INIT:
+        if ((bt_enabled == FALSE) && (META_BT_init() == FALSE)){
+            bt_cnf.bt_status = FALSE;
+            bt_cnf.status = META_FAILED;
+        }
+        else{
+            bt_cnf.bt_status = TRUE;
+            bt_cnf.status = META_SUCCESS;
+        }
+
+        bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+        break;
+
+      case BT_OP_DEINIT:
+        if (bt_enabled == TRUE)
+            META_BT_deinit();
+
+        bt_cnf.bt_status = TRUE;
+        bt_cnf.status = META_SUCCESS;
+        bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+        break;
+
+      case BT_OP_GET_CHIP_ID:
+      {
+        UINT32 chipId, adieId;
+
+        DBG("BT_OP_GET_CHIP_ID\n");
+        if (meta_bt_get_combo_id(&chipId, &adieId) < 0) {
+            ERR("Get combo chip id fails\n");
+            bt_cnf.bt_status = FALSE;
+            bt_cnf.status = META_FAILED;
+            bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+            break;
+        }
+        bt_cnf.result.dummy = chipId;
+        bt_cnf.bt_status = TRUE;
+        bt_cnf.status = META_SUCCESS;
+        bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+        break;
+      }
+      case BT_OP_HCI_SEND_COMMAND:
+        DBG("BT_OP_HCI_SEND_COMMAND\n");
+        if (BT_Send_HciCmd(&req->cmd.hcicmd) == FALSE) {
+            bt_cnf.bt_status = FALSE;
+            bt_cnf.status = META_FAILED;
+            bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+        }
+        break;
+
+      case BT_OP_HCI_SEND_DATA:
+        DBG("BT_OP_HCI_SEND_DATA\n");
+        if (BT_Send_AclData(&req->cmd.hcibuf) == FALSE) {
+            bt_cnf.bt_status = FALSE;
+            bt_cnf.status = META_FAILED;
+            bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+        }
+        break;
+
+      case BT_OP_HCI_CLEAN_COMMAND:
+      case BT_OP_HCI_TX_PURE_TEST:
+      case BT_OP_HCI_RX_TEST_START:
+      case BT_OP_HCI_RX_TEST_END:
+      case BT_OP_HCI_TX_PURE_TEST_V2:
+      case BT_OP_HCI_RX_TEST_START_V2:
+      case BT_OP_ENABLE_NVRAM_ONLINE_UPDATE:
+      case BT_OP_DISABLE_NVRAM_ONLINE_UPDATE:
+
+      case BT_OP_ENABLE_PCM_CLK_SYNC_SIGNAL:
+      case BT_OP_DISABLE_PCM_CLK_SYNC_SIGNAL:
+        /* Need to confirm with CCCI driver buddy */
+        DBG("Not implemented command %d\n", req->op);
+        bt_cnf.status = META_FAILED;
+        bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+        break;
+
+      default:
+        DBG("Unknown command %d\n", req->op);
+        bt_cnf.status = META_FAILED;
+        bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+        break;
+    }
+
+    return;
+}
+
+unsigned int BT_Get_On_Off_State(void)
+{
+    #define BT_DRV_IF "/proc/driver/bt_dbg"
+    #define BT_DBG_NODE_ENABLE "4w2T8M65K5?2af+a ON"
+    #define BT_DBG_NODE_DISABLE "4w2T8M65K5?2af+a OFF"
+    #define LEN_10 10
+    int fd;
+    int retval = 0;
+    unsigned int ret = 2;
+    unsigned char buf[LEN_10];
+
+    fd = open(BT_DRV_IF, O_RDWR | O_NOCTTY);
+    if (fd < 0) {
+        DBG("%s: Can't open %s, errno[%d][%s]", __func__, BT_DRV_IF, errno, strerror(errno));
+        return ret;
+    } else {
+        write(fd, BT_DBG_NODE_ENABLE, strlen(BT_DBG_NODE_ENABLE)); // enable debug function
+        retval = write(fd, "0x0E 0x00 0x00", 14);
+        if (retval > 0) {
+            DBG("%s: write %s: retval[%d]", __func__, BT_DRV_IF, retval);
+        }
+        retval = read(fd, buf, LEN_10);
+        if (retval > 0 && retval < LEN_10) {
+            buf[retval] = '\0';
+            ret = buf[0];
+            DBG("%s: retval[%d], ret[%d]", __func__, retval, ret);
+        } else {
+            buf[0] = '\0';
+        }
+        write(fd, BT_DBG_NODE_DISABLE, strlen(BT_DBG_NODE_DISABLE)); // disable debug function
+    }
+    close(fd);
+
+    /* return value
+     * 0: bt off
+     * 1: bt on
+     * 2: unknown
+     */
+    return ret;
+}
+
+static BOOL BT_Send_HciCmd(BT_HCI_CMD *pHciCmd)
+{
+    UINT8 ucHciCmd[256+4];
+    UINT8 i = 0;
+    unsigned char str[100] = {""};
+    unsigned char buf_str[6] = {""};
+
+    if (!glib_handle) {
+        ERR("mtk bt library is unloaded!\n");
+        return FALSE;
+    }
+    if (bt_fd < 0) {
+        ERR("bt driver fd is invalid!\n");
+        return FALSE;
+    }
+
+    ucHciCmd[0] = 0x01;
+    ucHciCmd[1] = (pHciCmd->opcode) & 0xFF;
+    ucHciCmd[2] = (pHciCmd->opcode >> 8) & 0xFF;
+    ucHciCmd[3] = pHciCmd->len;
+
+    DBG("OpCode 0x%04x len %d\n", pHciCmd->opcode, (int)pHciCmd->len);
+
+    if (pHciCmd->len) {
+        memcpy(&ucHciCmd[4], pHciCmd->parms, pHciCmd->len);
+    }
+
+    if (meta_bt_send_data(bt_fd, ucHciCmd, pHciCmd->len + 4) < 0) {
+        ERR("Write HCI command fails errno %d\n", errno);
+        return FALSE;
+    }
+
+    /* Dump packet */
+    for (i = 0; i < pHciCmd->len + 4; i++) {
+        if ((i % 16 == 0) && (i != 0)) {
+            DBG("%s\n", str);
+            memset(str, 0, sizeof(str));
+        }
+        if(snprintf(buf_str, sizeof(buf_str), "0x%02x ", ucHciCmd[i]) < 0) {
+            ERR("snprintf error!\n");
+            break;
+        }
+        strncat(str, buf_str, strlen(buf_str));
+    }
+    DBG("%s\n", str);
+
+    return TRUE;
+}
+
+static BOOL BT_Recv_HciEvent(BT_HCI_EVENT *pHciEvent)
+{
+    UINT8 i = 0;
+    unsigned char str[100] = {""};
+    unsigned char buf_str[6] = {""};
+    pHciEvent->status = FALSE;
+
+    if (!glib_handle) {
+        ERR("mtk bt library is unloaded!\n");
+        return FALSE;
+    }
+    if (bt_fd < 0) {
+        ERR("bt driver fd is invalid!\n");
+        return FALSE;
+    }
+
+    if (meta_bt_receive_data(bt_fd, &pHciEvent->event, 1) < 0) {
+        ERR("Read event code fails errno %d\n", errno);
+        return FALSE;
+    }
+
+    DBG("Read event code: %02x\n", pHciEvent->event);
+
+    if (meta_bt_receive_data(bt_fd, &pHciEvent->len, 1) < 0) {
+        ERR("Read event length fails errno %d\n", errno);
+        return FALSE;
+    }
+
+    DBG("Read event length: %d\n", pHciEvent->len);
+
+    if (pHciEvent->len) {
+        if (meta_bt_receive_data(bt_fd, pHciEvent->parms, pHciEvent->len) < 0) {
+            ERR("Read event param fails errno %d\n", errno);
+            return FALSE;
+        }
+    }
+
+    pHciEvent->status = TRUE;
+
+    /* Dump packet */
+    for (i = 0; i < pHciEvent->len; i++) {
+        if ((i % 16 == 0) && (i != 0)) {
+            DBG("%s\n", str);
+            memset(str, 0, sizeof(str));
+        }
+        if(snprintf(buf_str, sizeof(buf_str), "0x%02x ", pHciEvent->parms[i]) < 0) {
+            ERR("snprintf error!\n");
+            break;
+        }
+        strncat(str, buf_str, strlen(buf_str));
+    }
+    DBG("%s\n", str);
+
+    return TRUE;
+}
+
+static BOOL BT_Send_AclData(BT_HCI_BUFFER *pAclData)
+{
+    UINT8 ucAclData[1029];
+
+    if (!glib_handle) {
+        ERR("mtk bt library is unloaded!\n");
+        return FALSE;
+    }
+    if (bt_fd < 0) {
+        ERR("bt driver fd is invalid!\n");
+        return FALSE;
+    }
+
+    ucAclData[0] = 0x02;
+    ucAclData[1] = (pAclData->con_hdl) & 0xFF;
+    ucAclData[2] = (pAclData->con_hdl >> 8) & 0xFF;
+    ucAclData[3] = (pAclData->len) & 0xFF;
+    ucAclData[4] = (pAclData->len >> 8) & 0xFF;
+
+    if (pAclData->len) {
+        memcpy(&ucAclData[5], pAclData->buffer, pAclData->len);
+    }
+
+    if (meta_bt_send_data(bt_fd, ucAclData, pAclData->len + 5) < 0) {
+        ERR("Write ACL data fails errno %d\n", errno);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static BOOL BT_Recv_AclData(BT_HCI_BUFFER *pAclData)
+{
+    if (!glib_handle) {
+        ERR("mtk bt library is unloaded!\n");
+        return FALSE;
+    }
+    if (bt_fd < 0) {
+        ERR("bt driver fd is invalid!\n");
+        return FALSE;
+    }
+
+    if (meta_bt_receive_data(bt_fd, (UINT8*)&pAclData->con_hdl, 2) < 0) {
+        ERR("Read connection handle fails errno %d\n", errno);
+        return FALSE;
+    }
+
+    pAclData->con_hdl = ((pAclData->con_hdl & 0xFF) << 8) | ((pAclData->con_hdl >> 8) & 0xFF);
+
+    if (meta_bt_receive_data(bt_fd, (UINT8*)&pAclData->len, 2) < 0) {
+        ERR("Read ACL data length fails errno %d\n", errno);
+        return FALSE;
+    }
+
+    pAclData->len = ((pAclData->len & 0xFF) << 8) | ((pAclData->len >> 8) & 0xFF);
+
+    if (pAclData->len) {
+        if (meta_bt_receive_data(bt_fd, pAclData->buffer, pAclData->len) < 0) {
+            ERR("Read ACL data fails errno %d\n", errno);
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+
+static void *BT_Meta_Thread(void *ptr)
+{
+    BT_CNF *pBtCnf = (BT_CNF*)ptr;
+    BT_HCI_EVENT hci_event;
+    BT_HCI_BUFFER acl_data;
+    UINT8  ucHeader = 0;
+
+    TRC();
+
+    while (!fgKillThread) {
+
+        if (!glib_handle) {
+            ERR("mtk bt library is unloaded!\n");
+            break;
+        }
+        if (bt_fd < 0) {
+            ERR("bt driver fd is invalid!\n");
+            break;
+        }
+
+        if (meta_bt_receive_data(bt_fd, &ucHeader, sizeof(ucHeader)) < 0) {
+            ERR("Zero byte read\n");
+            continue;
+        }
+
+        switch (ucHeader) {
+          case 0x04:
+            DBG("Receive HCI event\n");
+            if (BT_Recv_HciEvent(&hci_event)) {
+                pBtCnf->bt_status = TRUE;
+                pBtCnf->result_type = PKT_TYPE_EVENT;
+                memcpy(&pBtCnf->result.hcievent, &hci_event, sizeof(hci_event));
+                pBtCnf->status = META_SUCCESS;
+                bt_send_resp(pBtCnf, sizeof(BT_CNF), NULL, 0);
+            }
+            else {
+                pBtCnf->bt_status = FALSE;
+                pBtCnf->status = META_FAILED;
+                bt_send_resp(pBtCnf, sizeof(BT_CNF), NULL, 0);
+            }
+            break;
+
+          case 0x02:
+            DBG("Receive ACL data\n");
+            if (BT_Recv_AclData(&acl_data)) {
+                pBtCnf->bt_status = TRUE;
+                pBtCnf->result_type = PKT_TYPE_ACL;
+                memcpy(&pBtCnf->result.hcibuf, &acl_data, sizeof(acl_data));
+                pBtCnf->status = META_SUCCESS;
+                bt_send_resp(pBtCnf, sizeof(BT_CNF), NULL, 0);
+            }
+            else {
+                pBtCnf->bt_status = FALSE;
+                pBtCnf->status = META_FAILED;
+                bt_send_resp(pBtCnf, sizeof(BT_CNF), NULL, 0);
+            }
+            break;
+
+          default:
+            ERR("Unexpected BT packet header %02x\n", ucHeader);
+            goto CleanUp;
+        }
+    }
+
+CleanUp:
+    return NULL;
+}
diff --git a/src/devtools/meta/src/adaptor/bluetooth/meta_bt.h b/src/devtools/meta/src/adaptor/bluetooth/meta_bt.h
new file mode 100644
index 0000000..e656ca8
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/bluetooth/meta_bt.h
@@ -0,0 +1,64 @@
+/* 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) 2014. 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 __META_BT_H__
+#define __META_BT_H__
+
+#include "MetaPub.h"
+#include "meta_bt_para.h"
+
+
+#define LOG_TAG         "BT_META "
+#include <log/log.h>
+
+#define BT_META_DEBUG   1
+#define ERR(f, ...)     ALOGE("%s: " f, __FUNCTION__, ##__VA_ARGS__)
+#define WAN(f, ...)     ALOGW("%s: " f, __FUNCTION__, ##__VA_ARGS__)
+#if BT_META_DEBUG
+#define DBG(f, ...)     ALOGD("%s: " f, __FUNCTION__, ##__VA_ARGS__)
+#define TRC(f)          ALOGW("%s #%d", __FUNCTION__, __LINE__)
+#else
+#define DBG(...)        ((void)0)
+#define TRC(f)          ((void)0)
+#endif
+
+typedef void (*BT_CNF_CB)(BT_CNF *cnf, void *buf, unsigned short len);
+
+extern void META_BT_Register(BT_CNF_CB callback);
+
+#endif
+
diff --git a/src/devtools/meta/src/adaptor/bluetooth/meta_bt_para.h b/src/devtools/meta/src/adaptor/bluetooth/meta_bt_para.h
new file mode 100644
index 0000000..8ae49e0
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/bluetooth/meta_bt_para.h
@@ -0,0 +1,162 @@
+/* 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) 2014. 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 __META_BT_PARA_H__
+#define __META_BT_PARA_H__
+
+#include "MetaPub.h"
+
+#define UNUSED_ATTR __attribute__((unused))
+
+#define FT_CNF_OK     0
+#define FT_CNF_FAIL   1
+
+#include <stdbool.h>
+#ifndef FALSE
+#define FALSE    0
+#endif
+#ifndef TRUE
+#define TRUE     1
+#endif
+#ifndef BOOL
+#define BOOL     bool
+#endif
+
+typedef unsigned char UINT8;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PKT_TYPE_CMD        0
+#define PKT_TYPE_EVENT      1
+#define PKT_TYPE_SCO        2
+#define PKT_TYPE_ACL        3
+
+/*
+* Test case enum defination for BT_module
+*/
+typedef enum {
+  BT_OP_HCI_SEND_COMMAND = 0
+  ,BT_OP_HCI_CLEAN_COMMAND
+  ,BT_OP_HCI_SEND_DATA
+  ,BT_OP_HCI_TX_PURE_TEST
+  ,BT_OP_HCI_RX_TEST_START
+  ,BT_OP_HCI_RX_TEST_END
+  ,BT_OP_HCI_TX_PURE_TEST_V2
+  ,BT_OP_HCI_RX_TEST_START_V2
+  ,BT_OP_ENABLE_NVRAM_ONLINE_UPDATE
+  ,BT_OP_DISABLE_NVRAM_ONLINE_UPDATE
+  ,BT_OP_ENABLE_PCM_CLK_SYNC_SIGNAL
+  ,BT_OP_DISABLE_PCM_CLK_SYNC_SIGNAL
+  ,BT_OP_GET_CHIP_ID
+  ,BT_OP_INIT
+  ,BT_OP_DEINIT
+  ,BT_OP_GET_ON_OFF_ST
+  ,BT_OP_END
+} BT_OP;
+
+typedef enum {
+  BT_CHIP_ID_MT6611 = 0
+  ,BT_CHIP_ID_MT6612
+  ,BT_CHIP_ID_MT6616
+  ,BT_CHIP_ID_MT6620
+  ,BT_CHIP_ID_MT6622
+  ,BT_CHIP_ID_MT6626
+} BT_CHIP_ID;
+
+/*
+* Structure Defination
+*/
+typedef struct _BT_HCI_CMD {
+  UINT16 opcode;
+  UINT8  len;
+  UINT8  parms[256];
+} BT_HCI_CMD;
+
+typedef struct _BT_HCI_BUFFER {
+  UINT16 con_hdl;
+  UINT16 len;
+  UINT8  buffer[1024];
+} BT_HCI_BUFFER;
+
+typedef union _BT_CMD {
+  BT_HCI_CMD    hcicmd;
+  BT_HCI_BUFFER hcibuf;
+  UINT32        dummy;
+} BT_CMD;
+
+typedef struct _BT_HCI_EVENT {
+  UINT8  event;
+  UINT16 handle;
+  UINT8  len;
+  UINT8  status;
+  UINT8  parms[256];
+} BT_HCI_EVENT;
+
+typedef union _BT_RESULT {
+  BT_HCI_EVENT  hcievent;
+  BT_HCI_BUFFER hcibuf;
+  UINT8         bt_on_off_state;
+  UINT32        dummy;
+} BT_RESULT;
+
+typedef struct _BT_REQ {
+  FT_H        header;
+  BT_OP       op;
+  BT_CMD      cmd;
+} BT_REQ;
+
+typedef struct _BT_CNF {
+  FT_H        header;
+  BT_OP       op;
+  UINT32      bt_status;
+  UINT8       result_type; /* result type */
+  BT_RESULT   result; /* result */
+  META_RESULT status;
+} BT_CNF;
+
+BOOL META_BT_init(void);
+void META_BT_deinit(void);
+void META_BT_OP(BT_REQ *req, char *buf, unsigned short len);
+
+#ifdef __cplusplus
+};
+#endif
+#endif
diff --git a/src/devtools/meta/src/adaptor/bluetooth/meta_bt_test.c b/src/devtools/meta/src/adaptor/bluetooth/meta_bt_test.c
new file mode 100644
index 0000000..9082d45
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/bluetooth/meta_bt_test.c
@@ -0,0 +1,131 @@
+/* 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) 2014. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "meta_bt.h"
+
+static void bt_info_callback(BT_CNF *cnf, void *buf, unsigned short len)
+{
+    char *type[] = {
+        "BT_OP_HCI_SEND_COMMAND", "BT_OP_HCI_CLEAN_COMMAND", "BT_OP_HCI_SEND_DATA", "BT_OP_HCI_TX_PURE_TEST",
+        "BT_OP_HCI_RX_TEST_START", "BT_OP_HCI_RX_TEST_END", "BT_OP_HCI_TX_PURE_TEST_V2", "BT_OP_HCI_RX_TEST_START_V2",
+        "BT_OP_ENABLE_NVRAM_ONLINE_UPDATE", "BT_OP_DISABLE_NVRAM_ONLINE_UPDATE", "BT_OP_ENABLE_PCM_CLK_SYNC_SIGNAL", "BT_OP_DISABLE_PCM_CLK_SYNC_SIGNAL",
+        "BT_OP_GET_CHIP_ID", "BT_OP_INIT", "BT_OP_DEINIT", "BT_OP_GET_ON_OFF_ST"};
+
+    printf("[META_BT] <CNF> %s, bt_status: %d, result_type: %d, status: %d\n",
+        type[cnf->op],
+        cnf->bt_status, cnf->result_type, cnf->status);
+
+    if (cnf->result_type == PKT_TYPE_EVENT) {
+        printf("[META_BT] HCI event %02x, len %d\n", cnf->result.hcievent.event, (int)cnf->result.hcievent.len);
+        printf("[META_BT] HCI event %02x-%02x-%02x-%02x\n",
+            cnf->result.hcievent.parms[0], cnf->result.hcievent.parms[1],
+            cnf->result.hcievent.parms[2], cnf->result.hcievent.parms[3]);
+
+    }
+    else if (cnf->result_type == PKT_TYPE_ACL) {
+        printf("[META_BT] ACL con_hdl %d, len: %d\n", (int)cnf->result.hcibuffer.con_hdl, (int)cnf->result.hcibuffer.len);
+    }
+    else {
+        printf("[META_BT] Unexpected result type\n");
+    }
+}
+
+int main(int argc, const char** argv)
+{
+    BT_REQ req;
+
+    memset(&req, 0, sizeof(BT_REQ));
+
+    META_BT_Register(bt_info_callback);
+
+    if (META_BT_init() == FALSE) {
+        printf("BT init fails\n");
+        return -1;
+    }
+#if 0
+    req.op = BT_OP_HCI_SEND_COMMAND;
+    req.cmd.hcicmd.opcode = 0x0c03;
+    req.cmd.hcicmd.len = 0;
+    req.cmd.hcicmd.parms[0] = 0;
+    META_BT_OP(&req, NULL, 0);
+
+    sleep(1);
+
+    req.op = BT_OP_HCI_CLEAN_COMMAND;
+    META_BT_OP(&req, NULL, 0);
+
+    sleep(1);
+
+    req.op = BT_OP_HCI_SEND_COMMAND;
+    req.cmd.hcicmd.opcode = 0xfc72;
+    req.cmd.hcicmd.len = 1;
+    req.cmd.hcicmd.parms[0] = 0x23;
+    META_BT_OP(&req, NULL, 0);
+
+    sleep(1);
+
+    req.op = BT_OP_HCI_CLEAN_COMMAND;
+    META_BT_OP(&req, NULL, 0);
+#endif
+    sleep(1);
+    /* 01,04,05,33,8B,9E,05,0A */
+    req.op = BT_OP_HCI_SEND_COMMAND;
+    req.cmd.hcicmd.opcode = 0x0401;
+    req.cmd.hcicmd.len = 5;
+    req.cmd.hcicmd.parms[0] = 0x33;
+    req.cmd.hcicmd.parms[1] = 0x8B;
+    req.cmd.hcicmd.parms[2] = 0x9E;
+    req.cmd.hcicmd.parms[3] = 0x05;
+    req.cmd.hcicmd.parms[4] = 0x0A;
+    META_BT_OP(&req, NULL, 0);
+
+    sleep(20);
+
+    req.op = BT_OP_HCI_CLEAN_COMMAND;
+    META_BT_OP(&req, NULL, 0);
+
+    sleep(1);
+
+    META_BT_deinit();
+    META_BT_Register(NULL);
+
+    return 0;
+}
+
diff --git a/src/devtools/meta/src/adaptor/gps/meta_gps.cpp b/src/devtools/meta/src/adaptor/gps/meta_gps.cpp
new file mode 100644
index 0000000..0a029ce
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/gps/meta_gps.cpp
@@ -0,0 +1,546 @@
+/*****************************************************************************
+*  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).
+*
+*****************************************************************************/
+
+//
+// Copyright (c) Microsoft Corporation.  All rights reserved.
+//
+//
+// Use of this source code is subject to the terms of the Microsoft end-user
+// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
+// If you did not accept the terms of the EULA, you are not authorized to use
+// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
+// install media.
+//
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   meta_gps.cpp
+ *
+ * Project:
+ * --------
+ *   DUMA
+ *
+ * Description:
+ * ------------
+ *   Implement GPS interface for META mode.
+ *
+ * Author:
+ * -------
+ *  LiChunhui (MTK80143)
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by CC/CQ. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * $Revision:$
+ * $Modtime:$
+ * $Log:$
+ *
+ * Mar 20 2009 mtk80143
+ * [DUMA00111323] [GPS] modify for GPS META
+ * Add for GPS meta
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+#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 <time.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/epoll.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <strings.h>
+#include <sys/un.h>  // struct sockaddr_un
+#include "LogDefine.h"
+
+#ifdef IS_SUPPORT_SP
+#include <cutils/properties.h>
+#include <cutils/log.h>
+//for read 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
+#ifdef GPS_PROPERTY
+#undef GPS_PROPERTY
+#endif
+#define GPS_DATA_PATH "/etc/gnss/"
+#define GPS_PROPERTY GPS_DATA_PATH"GPS_CHIP_FTM.cfg"
+//static  ap_nvram_gps_config_struct stGPSReadback;
+#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 BUF_TAIL_LENGTH   3
+#define ACK_BUF_SIZE      1024
+static int mnld_terminated = 0;
+
+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,
+};
+
+#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 MND_ERR META_LOG
+#define MND_MSG META_LOG
+#ifndef META_LOG
+#define META_LOG ALOGD
+#endif
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+//// meta test
+#define META_TO_MNLD_SOCKET        "mtk_meta2mnld"
+#ifdef IS_SUPPORT_SP
+#include <hidl/LegacySupport.h>
+#include <vendor/mediatek/hardware/lbs/1.0/ILbs.h>
+#endif
+#include "meta_gps_para.h"
+//#include "Meta2MnldInterface.h"
+#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;
+
+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);
+}
+
+// -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) {
+        META_LOG("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){
+        META_LOG("fcntl failed reason=[%s]%d",
+                    strerror(errno), errno);
+
+        close(fd);
+        return -1;
+    }
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_path[0] = 0;
+    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;
+            }
+        }
+        META_LOG("safe_sendto() sendto() failed path=[%s] ret=%d reason=[%s]%d",
+            path, ret, strerror(errno), errno);
+        break;
+    }
+
+    close(fd);
+    return ret;
+}
+
+void hidl_request_gps(bool turnOn) {
+    char _buff[META2MNLD_INTERFACE_BUFF_SIZE] = {0};
+    int _offset = 0;
+    int src = 0;
+    int msg = turnOn ? META2MNLD_INTERFACE_REQ_GNSS_LOCATION: META2MNLD_INTERFACE_CANCEL_GNSS_LOCATION;
+
+    mtk_socket_put_int(_buff, &_offset, META2MNLD_INTERFACE_PROTOCOL_TYPE);
+    mtk_socket_put_int(_buff, &_offset, msg);
+    mtk_socket_put_int(_buff, &_offset, src);
+    int size = (_offset < (int)(sizeof(_buff)/sizeof(_buff[0])))? _offset : sizeof(_buff)/sizeof(_buff[0]);
+    META_LOG("Send req gnss location to LBS service offset: %d size: %d", _offset, size);
+    if(safe_sendto(META_TO_MNLD_SOCKET, _buff, size) == -1) {
+        META_LOG("safe_sendto fail!!!");
+    }
+}
+//// end
+
+static GPS_CNF gps_cnf1;
+static GPS_CNF gps_cnf2;
+
+pid_t mnl_pid = C_INVALID_PID;
+int sockfd = C_INVALID_SOCKET;
+pthread_t gps_meta_thread_handle = C_INVALID_TID;
+
+/*****************************************************************************/
+static void sighlr(int signo)
+{
+    //pthread_t self = pthread_self();
+
+    META_LOG("Wait MNLD terminated");
+    if (signo == SIGCHLD) {
+        META_LOG("MNLD terminated");
+        mnld_terminated = 1;
+    }
+}
+/*****************************************************************************/
+int 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 = sighlr;
+
+    if ((err = sigaction(SIGALRM, &actions, NULL))) {
+        META_LOG("register signal handler for SIGALRM: %s\n", strerror(errno));
+        return -1;
+    }
+    if ((err = sigaction(SIGCHLD, &actions, NULL))) {
+        META_LOG("register signal handler for SIGALRM: %s\n", strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+/*****************************************************************************/
+int META_GPS_Open(int ATM_test)
+{
+    //int err;
+    pid_t pid;
+    int portno;
+    struct sockaddr_in serv_addr;
+    META_LOG("META_GPS_Open() 1\n");
+    if (setup_signal_handler()) {
+        META_LOG("setup_signal_handler: %d (%s)\n", errno, strerror(errno));
+        exit(1);
+    }
+    // power on GPS chip
+    //err = mnl_write_attr("/sys/class/gpsdrv/gps/pwrctl", 4);
+    //if (err != 0) {
+    //    META_LOG("META_GPS_Open: GPS power-on error: %d\n", err);
+    //}
+
+    if(0 != ATM_test) {
+        META_LOG("ATM test, hidl start gps\n");
+        hidl_request_gps(true);
+    } else {
+        // run gps driver
+        if ((pid = fork()) < 0) {
+            META_LOG("META_GPS_Open: fork fails: %d (%s)\n", errno, strerror(errno));
+            return (-2);
+        }
+        else if (pid == 0) {  /*child process*/
+            int err;
+            err = execl("vendor/bin/mnld", "mnld", "1Hz=y", "meta", NULL);
+            if (err == -1) {
+                MND_MSG("execl error: %s\n", strerror(errno));
+                return -1;
+            }
+            return 0;
+        } else {  /*parent process*/
+            mnl_pid = pid;
+            META_LOG("META_GPS_Open: mnl_pid = %d\n", pid);
+        }
+    }
+    // create socket connection to gps driver
+    portno = 7000;
+    /* Create a socket point */
+    sockfd = socket(AF_INET, SOCK_STREAM, 0);
+    if (sockfd < 0) {
+        META_LOG("META_GPS_Open: ERROR opening socket");
+        return (-4);
+    }
+    bzero((char *) &serv_addr, sizeof(serv_addr));
+    serv_addr.sin_family = AF_INET;
+    serv_addr.sin_addr.s_addr = htons(INADDR_ANY);
+    serv_addr.sin_port = htons(portno);
+
+    int try_time = 10;
+    do {
+      META_LOG("META_GPS_Open: try connecting,try_time = %d, %s(%d)",try_time, strerror(errno), errno);
+      sleep(1);  // sleep 10 sec for libmnl to finish initialization
+    } while (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0 && --try_time);
+    if (try_time == 0) {
+      META_LOG("META_GPS_Open: ERROR connecting");
+      return (-6);
+    }
+
+    // run GPS_MetaThread
+    if (pthread_create(&gps_meta_thread_handle, NULL, GPS_MetaThread, NULL)) {
+      META_LOG("META_GPS_Open: error creating dsp thread \n");
+      return (-7);
+    }
+    META_LOG("META_GPS_Open() 2\n");
+
+    return 0;
+}
+
+void META_GPS_Close(int ATM_test) {
+    int err;
+    int cnt = 0, max = 10;
+
+    META_LOG("META_GPS_Close() 1\n");
+    // disconnect to gps driver
+    if (sockfd != C_INVALID_SOCKET) {
+        close(sockfd);
+        sockfd = C_INVALID_SOCKET;
+    }
+    META_LOG("META_GPS_Close() 4\n");
+
+    if(0 != ATM_test) {
+        META_LOG("ATM test, hidl stop gps\n");
+        hidl_request_gps(false);
+    } else {
+        if (mnl_pid != C_INVALID_PID) {
+            META_LOG("GPS_Close() 5\n");
+            // kill(mnl_pid, SIGKILL);
+            // usleep(500000);
+
+            kill(mnl_pid, SIGTERM);
+            while (!mnld_terminated) {
+                if (cnt++ < max) {
+                /*timeout: 1 sec;
+                notice that libmnlp needs
+                some sleep time after MTK_PARAM_CMD_RESET_DSP*/
+                    usleep(100000);
+                    continue;
+                } else {
+                    kill(mnl_pid, SIGKILL);
+                    usleep(100000);
+                }
+            }
+            META_LOG("waiting counts: %d\n", cnt);
+            mnl_pid = wait(&err);
+
+            if (mnl_pid == -1)
+                MND_MSG("wait error: %s\n",strerror(errno));
+            MND_MSG("mnld process : %d is killed\n", mnl_pid);
+            mnld_terminated = 1;
+        }
+    }
+    unlink(GPS_DATA_PATH"mtkgps.dat");
+    // power off GPS chip
+    //err = mnl_write_attr("/sys/class/gpsdrv/gps/pwrctl", 0);
+    //if (err != 0) {
+    //    META_LOG("GPS power-off error: %d\n", err);
+    //}
+    META_LOG("META_GPS_Close() 6\n");
+
+    unlink(GPS_PROPERTY);
+    META_LOG("META_GPS_Close() 7\n");
+    return;
+}
+
+
+void META_GPS_OP(GPS_REQ *req, char *peer_buff, unsigned short peer_len, int ATM_test)
+{
+    memset(&gps_cnf1, 0, sizeof(GPS_CNF));
+    gps_cnf1.header.id = FT_GPS_CNF_ID;
+    gps_cnf1.header.token = req->header.token;
+    gps_cnf1.op = req->op;
+    memset(&gps_cnf2, 0, sizeof(GPS_CNF));
+    gps_cnf2.header.id = FT_GPS_CNF_ID;
+    gps_cnf2.header.token = req->header.token;
+    gps_cnf2.op = req->op;
+
+    META_LOG("META_GPS_OP() 1, (%d),(%s),(%u)\n", req->op, peer_buff, peer_len);
+    switch (req->op) {
+        case GPS_OP_OPEN:
+            META_LOG("META_GPS_OP(), GPS_OP_OPEN 1\n");
+            if (META_GPS_Open(ATM_test) != 0) {   // open fail
+                META_LOG("META_GPS_OP(), GPS_OP_OPEN fail\n");
+                META_GPS_Close(ATM_test);
+                META_LOG("Can't open gps driver \r\n");
+                gps_cnf1.gps_status = FALSE;
+                gps_cnf1.status = META_FAILED;
+            }
+            else {
+                META_LOG("META_GPS_OP(), GPS_OP_OPEN OK\n");
+                gps_cnf1.gps_status = TRUE;
+                gps_cnf1.status = META_SUCCESS;
+            }
+            WriteDataToPC(&gps_cnf1, sizeof(GPS_CNF), NULL, 0);
+            META_LOG("META_GPS_OP(), GPS_OP_OPEN 2\n");
+            break;
+
+        case GPS_OP_CLOSE:
+            META_LOG("META_GPS_OP(), GPS_OP_CLOSE 1\n");
+            META_GPS_Close(ATM_test);
+            gps_cnf1.gps_status = TRUE;
+            gps_cnf1.status = META_SUCCESS;
+            WriteDataToPC(&gps_cnf1, sizeof(GPS_CNF), NULL, 0);
+            META_LOG("META_GPS_OP(), GPS_OP_CLOSE 2\n");
+            break;
+
+        case GPS_OP_SEND_CMD:
+            META_LOG("META_GPS_OP(), GPS_OP_SEND_CMD\n");
+            if (sockfd != C_INVALID_SOCKET) {
+                int n = write(sockfd, req->cmd.buff, req->cmd.len);
+                if (n < 0) {
+                     META_LOG("ERROR writing to socket\r\n");
+                }
+                META_LOG("META_GPS_OP(), GPS_OP_SEND_CMD: %s\r\n", req->cmd.buff);
+            }
+
+            gps_cnf1.gps_status = TRUE;
+            gps_cnf1.status = META_SUCCESS;
+            META_LOG("GPS_OP_SEND_CMD, gps_cnf.status:%d\r\n", gps_cnf1.status);
+            WriteDataToPC(&gps_cnf1, sizeof(GPS_CNF), NULL, 0);
+
+            break;
+
+        default:
+            META_LOG("META_GPS_OP(), default 1\n");
+            gps_cnf1.gps_status = FALSE;
+            gps_cnf1.status = META_FAILED;
+            WriteDataToPC(&gps_cnf1, sizeof(GPS_CNF), NULL, 0);
+            META_LOG("META_GPS_OP(), default 2\n");
+            break;
+    }
+    META_LOG("META_GPS_OP() 2\n");
+}
+
+void *GPS_MetaThread(void *arg)
+{
+    int read_leng = 0;
+    int cnt = 0;
+    int cnt_tmp = 0;
+    char *ptr;
+    char buf[ACK_BUF_SIZE*10];
+    UNUSED(arg);
+
+    cnt = 0;
+
+    while (1) {
+        memset(buf, 0, sizeof(buf));
+        read_leng = 0;
+        read_leng = read(sockfd, buf, sizeof(buf) - 1);
+        if (read_leng < 0) {
+            META_LOG("ERROR reading from socket");
+            return (void *)(-1);
+        } else if (read_leng > 0) {
+            buf[ACK_BUF_SIZE*10-1] = '\0';
+            ptr=strtok(buf, "\r\n");
+            if (ptr == NULL) {
+                continue;
+            }
+
+            do {
+                cnt_tmp = strlen(ptr);
+                if (cnt_tmp + BUF_TAIL_LENGTH > ACK_BUF_SIZE || ptr[0] == '#') {
+                    continue;
+                }
+                META_LOG("GPS_MetaThread: [%d]/[%d]\n", cnt_tmp, cnt);
+                if ((cnt != 0) && ((cnt + cnt_tmp + BUF_TAIL_LENGTH) >= ACK_BUF_SIZE)) {
+                    gps_cnf2.gps_ack.len = cnt;
+                    gps_cnf2.gps_status = TRUE;
+                    gps_cnf2.status = META_SUCCESS;
+                    META_LOG("GPS_MetaThread, status:%d, gps_cnf.gps_ack.len:%d\r\n",
+                    gps_cnf2.status, gps_cnf2.gps_ack.len);
+                    WriteDataToPC(&gps_cnf2, sizeof(GPS_CNF), NULL, 0);
+                    cnt = 0;
+                }
+                META_LOG("GPS_MetaThread: %s", ptr);
+                strncpy((char*)&gps_cnf2.gps_ack.buff[cnt], ptr, (sizeof(gps_cnf2.gps_ack.buff) - cnt));
+                cnt += cnt_tmp;
+                if(cnt > 0 && cnt < (sizeof(gps_cnf2.gps_ack.buff) - 3)) {
+                    gps_cnf2.gps_ack.buff[cnt++] = '\r';
+                    gps_cnf2.gps_ack.buff[cnt++] = '\n';
+                } else {
+                    META_LOG("gps_ack buffer full(%d)", cnt);
+                }
+            } while ((ptr = strtok(NULL, "\r\n")) != NULL);
+            if (cnt > 0) {
+                gps_cnf2.gps_ack.len = cnt;
+                gps_cnf2.gps_status = TRUE;
+                gps_cnf2.status = META_SUCCESS;
+                META_LOG("GPS_MetaThread, status:%d, last gps_cnf.gps_ack.len:%d\r\n",
+                gps_cnf2.status, gps_cnf2.gps_ack.len);
+                WriteDataToPC(&gps_cnf2, sizeof(GPS_CNF), NULL, 0);
+                cnt = 0;
+            }
+        }
+    }
+
+    return (void *)0;
+}
diff --git a/src/devtools/meta/src/adaptor/gps/meta_gps_para.h b/src/devtools/meta/src/adaptor/gps/meta_gps_para.h
new file mode 100644
index 0000000..925bb29
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/gps/meta_gps_para.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) 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).
+*
+*****************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   meta_gps_para.h
+ *
+ * Project:
+ * --------
+ *   DUMA
+ *
+ * Description:
+ * ------------
+ *   define the struct for Meta
+ *
+ * Author:
+ * -------
+ *  LiChunhui (MTK80143)
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by CC/CQ. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * $Revision:$
+ * $Modtime:$
+ * $Log:$
+ *
+ * Mar 20 2009 mtk80143
+ * [DUMA00111323] [GPS] modify for GPS META
+ * Add for GPS META
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+#ifndef __META_GPS_PARA_H_
+#define __META_GPS_PARA_H_
+
+#include "MetaPub.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The TestCase Enum define of GPS_module */
+typedef enum {
+    GPS_OP_OPEN = 0,
+    GPS_OP_CLOSE,
+    GPS_OP_SEND_CMD,
+    GPS_OP_END
+} GPS_OP;
+
+/* The PMTK command struct */
+typedef struct {
+    unsigned int len;
+    unsigned char buff[1024];
+} GPS_CMD;
+
+/* The PMTK command ACK struct */
+typedef struct {
+    unsigned int len;
+    unsigned char buff[1024];
+} GPS_ACK_BUF;
+
+typedef struct {
+    FT_H        header;  // module do not need care it
+    GPS_OP      op;
+    GPS_CMD     cmd;
+} GPS_REQ;
+
+typedef struct {
+    FT_H        header;  // module do not need care it
+    GPS_OP      op;
+    unsigned int    gps_status;  // gps->FT
+    GPS_ACK_BUF     gps_ack;
+    unsigned char   status;
+} GPS_CNF;
+
+
+void META_GPS_OP(GPS_REQ *req, char *peer_buff, unsigned short peer_len, int ATM_test);
+void *GPS_MetaThread(void *arg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/devtools/meta/src/adaptor/gps/type.h b/src/devtools/meta/src/adaptor/gps/type.h
new file mode 100644
index 0000000..4d6a885
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/gps/type.h
@@ -0,0 +1,83 @@
+/*******************************************************************************
+** Copyright (c) 2005 MediaTek Inc.
+**
+** All rights reserved. Copying, compilation, modification, distribution
+** or any other use whatsoever of this material is strictly prohibited
+** except in accordance with a Software License Agreement with
+** MediaTek Inc.
+********************************************************************************
+*/
+#ifndef _TYPE_H
+#define _TYPE_H
+
+#define ULONG unsigned long
+#define UINT  unsigned int
+#define USHORT unsigned short
+#define UCHAR unsigned char
+
+#define LONG long
+#define INT  int
+#define SHORT short
+#define CHAR char
+
+#define UINT32 unsigned long
+#define UINT16 unsigned short
+#define UINT8 unsigned char
+
+#define PUINT32 unsigned long*
+#define PUINT16 unsigned short*
+#define PUINT8 unsigned char*
+
+#define UINT_64 unsigned long long
+#define UINT_32 unsigned long
+#define UINT_16 unsigned short
+#define UINT_8 unsigned char
+
+#define INT32  long
+#define INT16  short
+#define INT8  char
+
+#define PINT32  long*
+#define PINT16  short*
+#define PINT8  char*
+#define PVOID  void*
+
+#define INT_32  long
+#define INT_16  short
+#define INT_8  char
+
+#define PULONG ULONG*
+#define PUCHAR UCHAR*
+
+#define DWORD ULONG
+
+#ifndef NULL
+#define NULL  0
+#endif
+
+#define BOOL  bool
+#define BOOLEAN bool
+
+
+#define TRUE true
+#define FALSE false
+
+#define IN
+#define OUT
+
+#define TCHAR char
+
+#define CString char*
+
+#define LPSTR   char*
+#define LPCTSTR char*
+
+#define DLL_FUNC
+
+#define TEXT
+
+#define BIT(n)                          ((UINT_32) 1 << (n))
+#define BITS(m,n)                       (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n)))
+
+
+#endif
diff --git a/src/devtools/meta/src/adaptor/wifi/README b/src/devtools/meta/src/adaptor/wifi/README
new file mode 100644
index 0000000..dbbea42
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/README
@@ -0,0 +1,33 @@
+This directory contains WIFI Tool library
+
+
+WHAT IT DOES?
+=============
+It provide WIFI editing feature on PC side, which allow read and modify WIFI items as GUI.
+
+
+HOW IT WAS BUILT?
+==================
+It needs the following libs from AOSP:
+1.  libc.so
+
+and the following libs from MediaTek:
+1. libmeta_wifi.a
+2. libft.so
+
+All source/dependency modules of this module are already put in
+'vendor/mediatek/proprietary/platform/${CHIP_NAME}/external/meta/wifi' folder.
+
+
+HOW TO USE IT?
+==============
+Files in this directory is used to generate a library which's name is 'libmeta_wifi'
+
+
+WIFI Tool
+The lib  'libmeta_wifi' is loaded when SP WIFI tool and related libs,
+all WIFI GUI opertations will call META_WIFI_xxx API, then it calls WIFI native API to access WIFI driver data.
+
+
+All the source code of this library were written by MediaTek co..
+
diff --git a/src/devtools/meta/src/adaptor/wifi/iwlibstub.c b/src/devtools/meta/src/adaptor/wifi/iwlibstub.c
new file mode 100644
index 0000000..648db21
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/iwlibstub.c
@@ -0,0 +1,338 @@
+/*******************************************************************************
+** Copyright (c) 2006 MediaTek Inc.
+**
+** All rights reserved. Copying, compilation, modification, distribution
+** or any other use whatsoever of this material is strictly prohibited
+** except in accordance with a Software License Agreement with
+** MediaTek Inc.
+********************************************************************************
+*/
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <math.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+//#include <net/ethernet.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <linux/socket.h>
+#include <linux/if.h>
+#include <net/if_arp.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <linux/types.h>
+#ifndef __user
+#define __user
+#endif
+#include <linux/wireless.h>
+#include "iwlibstub.h"
+#include "meta_wifi_para.h"
+
+int openNetHandle(void)
+{
+    int sock; /* generic raw socket desc. */
+
+
+    /* Try to open the socket, if success returns it */
+    sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+    if (sock >= 0)
+        return sock;
+    else
+        return -1;
+}
+
+void closeNetHandle(int skfd)
+{
+    /* Close the socket. */
+    close(skfd);
+}
+
+int enumNetIf(int skfd, _enum_handler fn, void* argc)
+{
+    struct  ifconf ifc;
+    char    buff[1024];
+    struct  ifreq *ifr;
+    int     i, num = 0;
+
+    ifc.ifc_len = sizeof(buff);
+    ifc.ifc_buf = buff;
+
+    if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
+    {
+        fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
+        return num;
+    }
+
+    ifr = ifc.ifc_req;
+
+    for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
+    {
+        (*fn)(skfd, ifr->ifr_name, argc);
+        num ++;
+    }
+
+    return num;
+}
+
+
+int setIWreq(int skfd, char* if_name,
+             unsigned int ndisOid,
+             unsigned char* ndisData,
+             unsigned int bufLen,
+             unsigned int* outputBufLen)
+{
+    struct iwreq wrq;
+    unsigned char *buffer = NULL;
+    unsigned int    reqBufLen = 0;
+    NDIS_TRANSPORT_STRUCT*   reqStruct_p = NULL;
+    int     result;
+
+    reqBufLen = bufLen + sizeof(*reqStruct_p) -
+                sizeof(reqStruct_p->ndisOidContent);
+
+    if (reqBufLen >= 0)
+    {
+        buffer = (unsigned char *)malloc(reqBufLen);
+    }
+
+    if (buffer == NULL)
+    {
+        printf("%s malloc(%d) fail\n", __func__, reqBufLen);
+        return -1;
+    }
+
+    reqStruct_p = (NDIS_TRANSPORT_STRUCT*)buffer;
+
+    reqStruct_p->ndisOidCmd = ndisOid;
+    reqStruct_p->inNdisOidlength = bufLen;
+
+    if (bufLen != 0)
+    {
+        memcpy(reqStruct_p->ndisOidContent, ndisData, bufLen);
+    }
+
+    /* Try to read the results */
+    wrq.u.data.pointer = buffer;
+    wrq.u.data.flags = PRIV_CMD_OID;
+    wrq.u.data.length = reqBufLen;
+
+#if 0
+    printf("%s: buffer(0x%p), flags(%d), length(%d)\n",
+           __FUNCTION__,
+           buffer, PRIV_CMD_OID, reqBufLen
+          );
+#endif
+
+    /* Set device name */
+    strncpy(wrq.ifr_name, if_name, IFNAMSIZ - 1);
+    /* Do the request */
+    result = ioctl(skfd, IOCTL_SET_STRUCT, &wrq);
+
+    if (result < 0)
+    {
+        if(fprintf(stderr, "result %d %s\n", result, strerror(errno)) < 0)
+            return -1;
+    }
+
+    *outputBufLen = reqStruct_p->outNdisOidLength;
+
+    free(buffer);
+
+    if (result == 0)
+        return 0;
+
+    return -1;
+}
+
+int getIWreq(int skfd, char* if_name,
+             unsigned int ndisOid,
+             unsigned char* ndisData,
+             unsigned int bufLen,
+             unsigned int* outputBufLen)
+{
+    struct iwreq wrq;
+    unsigned char *buffer = NULL;
+    unsigned int   reqBufLen = 0;
+    NDIS_TRANSPORT_STRUCT*   reqStruct_p = NULL;
+    int     result;
+
+    //printf("%s\n", __FUNCTION__);
+
+    reqBufLen = bufLen + sizeof(*reqStruct_p) -
+                sizeof(reqStruct_p->ndisOidContent);
+
+    if (reqBufLen >= 0)
+    {
+        buffer = (unsigned char *)malloc(reqBufLen);
+    }
+
+    if (buffer == NULL)
+    {
+        printf("%s malloc(%d) fail\n", __func__, reqBufLen);
+        return -1;
+    }
+
+    reqStruct_p = (NDIS_TRANSPORT_STRUCT*)buffer;
+
+    reqStruct_p->ndisOidCmd = ndisOid;
+    reqStruct_p->inNdisOidlength = bufLen;
+
+    /* IMPORTANT!! copy input data to buffer (ex. mcr index) */
+    memcpy(reqStruct_p->ndisOidContent, ndisData, bufLen);
+
+    /* Try to read the results */
+    wrq.u.data.pointer = buffer;
+    wrq.u.data.flags = PRIV_CMD_OID;
+    wrq.u.data.length = reqBufLen;
+
+    /* Set device name */
+    strncpy(wrq.ifr_name, if_name, IFNAMSIZ - 1);
+    /* Do the request */
+    result = ioctl(skfd, IOCTL_GET_STRUCT, &wrq);
+
+    if (result < 0)
+        if(fprintf(stderr, "getIWreq result %s %d %s\n", if_name, result, strerror(errno)) < 0)
+            return -1;
+
+    if (result == 0)
+    {
+        memcpy(ndisData, reqStruct_p->ndisOidContent, reqStruct_p->outNdisOidLength);
+    }
+
+    *outputBufLen = reqStruct_p->outNdisOidLength;
+
+    free(buffer);
+
+    if (result == 0)
+        return 0;
+
+    return -1;
+}
+
+/**
+ * Function:
+ * Send the parsed command to driver
+ * for example : set_mcr 0x820F4020 0x14141414
+ *
+ * Parameters:
+ * IN  int    skfd: socket handle
+ * IN  char*  if_name: network device name, wlan0
+ * IN  char*  pDataCmd: command string from script file
+ * IN  int    bufLen: strlen of command string
+ * OUT int    outputBufLen: length of output buffer
+ *
+ * Return:
+ *  -1 means error, 0 is success
+ */
+int driverIWreq(int skfd, char* if_name,
+                char* pDataCmd,
+                unsigned int bufLen,
+                unsigned int* outputBufLen)
+{
+    struct iwreq wrq;
+    char *buffer = NULL;
+
+    int     result;
+
+
+    buffer = (char *)malloc(WIFI_SCRIPT_TOTAL_BUF_LEN);
+
+    if (buffer == NULL)
+        return -1;
+
+    /*copy driver command*/
+    memcpy(buffer, pDataCmd, bufLen);
+    buffer[bufLen] = '\0';
+
+    /* Try to read the results */
+    wrq.u.data.pointer = buffer;
+    wrq.u.data.length = bufLen; /*available data length*/
+
+    DBG("input (%d) >> %s\n", wrq.u.data.length, wrq.u.data.pointer);
+
+    /* Set device name */
+    strncpy(wrq.ifr_name, if_name, IFNAMSIZ - 1);
+    /* Do the request */
+    result = ioctl(skfd, IOCTL_GET_DRIVER, &wrq);
+
+    if (wrq.u.data.length > WIFI_SCRIPT_TOTAL_BUF_LEN)
+        wrq.u.data.length = WIFI_SCRIPT_TOTAL_BUF_LEN;
+
+    if (result < 0)
+        DBG("driverIWreq result %s %d %s\n", if_name, result, strerror(errno));
+    else if (result == 0)
+    {
+        memcpy(pDataCmd, buffer, wrq.u.data.length);
+        pDataCmd[wrq.u.data.length] = '\0';
+
+        DBG("output (%d) >> %s\n", wrq.u.data.length, pDataCmd);
+        *outputBufLen = wrq.u.data.length;
+    }
+
+    free(buffer);
+
+    if (result == 0)
+        return 0;
+
+    return -1;
+}
+
+int HQAIWreq(int skfd, char* if_name,
+             char* pDataCmd,
+             unsigned int bufLen,
+             unsigned int* outputBufLen)
+{
+    struct iwreq wrq;
+    int     result, intI, dataLen;
+
+    /* Try to read the results */
+    wrq.u.data.pointer = pDataCmd;
+    wrq.u.data.length = bufLen; /*available data length*/
+
+    dataLen = (pDataCmd[8] << 8) + pDataCmd[9];
+    DBG("Cmd Type: %02x%02x, Cmd ID: %02x%02x Length: %d\n", pDataCmd[4], pDataCmd[5], pDataCmd[6], pDataCmd[7], dataLen);
+
+    for (intI = 0; intI < dataLen;)
+    {
+        DBG("Content [%d~%d]: %x %x %x %x ", intI, intI + 3, pDataCmd[12 + intI], pDataCmd[13 + intI], pDataCmd[14 + intI], pDataCmd[15 + intI]);  /* content start index in pDataCmd[8], pDataCmd[6,7] is Seq */
+        intI = intI + 4;
+    }
+
+    /* Set device name */
+    strncpy(wrq.ifr_name, if_name, IFNAMSIZ - 1);
+    /* Do the request */
+#ifdef PETRUS_META_WORKAROUND
+    result = ioctl(skfd, IOCTL_QA_TOOL_DAEMON_NEW, &wrq);
+#else
+    result = ioctl(skfd, IOCTL_QA_TOOL_DAEMON, &wrq);
+#endif
+
+    if (wrq.u.data.length > bufLen)
+        wrq.u.data.length = bufLen;
+
+    if (result < 0)
+        DBG("HQAIWreq result %s %d %s\n", if_name, result, strerror(errno));
+    else if (result == 0)
+    {
+        for (intI = 0; intI < wrq.u.data.length;)
+        {
+            DBG("Content [%d~%d]: %x %x %x %x ", intI, intI + 3, pDataCmd[intI], pDataCmd[1 + intI], pDataCmd[2 + intI], pDataCmd[3 + intI]);
+            intI = intI + 4;
+        }
+        *outputBufLen = wrq.u.data.length;
+    }
+
+    if (result == 0)
+        return 0;
+
+    return -1;
+}
\ No newline at end of file
diff --git a/src/devtools/meta/src/adaptor/wifi/iwlibstub.h b/src/devtools/meta/src/adaptor/wifi/iwlibstub.h
new file mode 100644
index 0000000..51a2b1c
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/iwlibstub.h
@@ -0,0 +1,134 @@
+#ifndef _IWLIB_STUB_H
+#define _IWLIB_STUB_H
+
+/*******************************************************************************
+** Copyright (c) 2005 MediaTek Inc.
+**
+** All rights reserved. Copying, compilation, modification, distribution
+** or any other use whatsoever of this material is strictly prohibited
+** except in accordance with a Software License Agreement with
+** MediaTek Inc.
+********************************************************************************
+*/
+
+#include "type.h"
+
+#define PETRUS_META_WORKAROUND    1
+
+#if WIRELESS_EXT >= 12
+/* New wireless extensions API - SET/GET convention (even ioctl numbers are
+ * root only)
+ */
+#define IOCTL_SET_INT       (SIOCIWFIRSTPRIV + 0)
+#define IOCTL_GET_INT       (SIOCIWFIRSTPRIV + 1)
+#define IOCTL_SET_ADDRESS   (SIOCIWFIRSTPRIV + 2)
+#define IOCTL_GET_ADDRESS   (SIOCIWFIRSTPRIV + 3)
+#define IOCTL_SET_STR       (SIOCIWFIRSTPRIV + 4)
+#define IOCTL_GET_STR       (SIOCIWFIRSTPRIV + 5)
+#define IOCTL_SET_KEY       (SIOCIWFIRSTPRIV + 6)
+#define IOCTL_GET_KEY       (SIOCIWFIRSTPRIV + 7)
+#define IOCTL_SET_STRUCT    (SIOCIWFIRSTPRIV + 8)
+#define IOCTL_GET_STRUCT    (SIOCIWFIRSTPRIV + 9)
+#define IOCTL_GET_DRIVER    (SIOCIWFIRSTPRIV + 15)
+#define IOCTL_QA_TOOL_DAEMON    (SIOCIWFIRSTPRIV + 16)
+#define IOCTL_QA_TOOL_DAEMON_NEW    (SIOCDEVPRIVATE + 2)
+#endif /* WIRELESS_EXT >= 12 */
+
+#if 1
+/* MT5921 Glue Layer Private IOCTL IDs */
+#define PRIV_CMD_REG_DOMAIN             0
+#define PRIV_CMD_BEACON_PERIOD          1
+#define PRIV_CMD_ADHOC_MODE             2
+
+#define PRIV_CMD_CSUM_OFFLOAD       3
+
+#define PRIV_CMD_ROAMING                4
+#define PRIV_CMD_VOIP_DELAY             5
+#define PRIV_CMD_POWER_MODE             6
+
+#define PRIV_CMD_WMM_PS                 7
+#define PRIV_CMD_BT_COEXIST             8
+#define PRIV_GPIO2_MODE                 9
+
+#define PRIV_CUSTOM_SET_PTA         10
+#define PRIV_CUSTOM_CONTINUOUS_POLL     11
+#define PRIV_CUSTOM_SINGLE_ANTENNA  12
+#define PRIV_CUSTOM_BWCS_CMD        13
+#define PRIV_CUSTOM_DISABLE_BEACON_DETECTION    14 // later
+#define PRIV_CMD_OID                15
+#define PRIV_CMD_MAX                16
+
+#else
+/* MT5911/12 Glue Layer Private IOCTL IDs */
+#define PRIV_CMD_OID                0
+#define PRIV_CMD_CHIPID             1
+#define PRIV_CMD_MCR                2
+#define PRIV_CMD_BBCR               3
+#define PRIV_CMD_EEPROM             4
+#define PRIV_CMD_EEPROM_SIZE        5
+#define PRIV_CMD_EEPROM_MAC         6
+#define PRIV_CMD_EEPROM_CHKSUM      7
+#define PRIV_CMD_EEPROM_COUNTRY     8
+#define PRIV_CMD_EEPROM_SET_POWER   9
+#define PRIV_CMD_RFTEST_MODE        10
+#define PRIV_CMD_RFTEST_TX          11
+#define PRIV_CMD_RFTEST_RX          12
+#define PRIV_CMD_RFTEST_RST_RX_CNT  13
+#define PRIV_CMD_RFTEST_CNT_POWER   14
+#define PRIV_CMD_RFTEST_LOCAL_FREQ  15
+#define PRIV_CMD_RFTEST_CAR_SUP     16
+#define PRIV_CMD_RFTEST_LOW_POWER   17
+#define PRIV_CMD_QOS_UAPSD          18
+#define PRIV_CMD_QOS_UAPSD_TEST     19
+#define PRIV_CMD_PSP_PROFILE        20
+#define PRIV_CMD_PM_TX_TIMEOUT      21
+#define PRIV_CMD_PM_ASSOC_TIMEOUT   22
+#define PRIV_CMD_PM_DTIM_PERIOD     23
+#define PRIV_CMD_CONN_KEEP_PERIOD   24
+#define PRIV_CMD_CONN_TX_NULL     25
+#define PRIV_CMD_MAX                26
+#endif
+
+#define WIFI_SCRIPT_TOTAL_BUF_LEN   2000
+#define RA_CFG_HLEN     14  /* Length of Racfg header*/
+
+typedef int (*_enum_handler)(int skfd,
+                             char *ifname,
+                             void *arg);
+
+typedef struct _NDIS_TRANSPORT_STRUCT
+{
+    unsigned int    ndisOidCmd;
+    unsigned int    inNdisOidlength;
+    unsigned int    outNdisOidLength;
+    unsigned char ndisOidContent[16];
+} NDIS_TRANSPORT_STRUCT;
+
+
+int openNetHandle(void);
+void closeNetHandle(int skfd);
+int enumNetIf(int skfd, _enum_handler fn, void* argc);
+
+int setIWreq(int skfd, char* if_name,
+             unsigned int ndisOid,
+             unsigned char* ndisData,
+             unsigned int bufLen,
+             unsigned int* outputBufLen);
+
+int getIWreq(int skfd, char* if_name,
+             unsigned int ndisOid,
+             unsigned char* ndisData,
+             unsigned int bufLen,
+             unsigned int* outputBufLen);
+
+int driverIWreq(int skfd, char* if_name,
+                char* pDataCmd,
+                unsigned int bufLen,
+                unsigned int* outputBufLen);
+
+int HQAIWreq(int skfd, char* if_name,
+             char* pDataCmd,
+             unsigned int bufLen,
+             unsigned int* outputBufLen);
+
+#endif
diff --git a/src/devtools/meta/src/adaptor/wifi/meta_wifi.c b/src/devtools/meta/src/adaptor/wifi/meta_wifi.c
new file mode 100644
index 0000000..aed7c1d
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/meta_wifi.c
@@ -0,0 +1,3083 @@
+#include "meta_wifi.h"
+
+#include <cutils/properties.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <net/if_arp.h>         /* For ARPHRD_ETHER */
+#include <sys/socket.h>         /* For AF_INET & struct sockaddr */
+#include <netinet/in.h>         /* For struct sockaddr_in */
+#include <netinet/if_ether.h>
+#include <linux/wireless.h>
+
+#include "cutils/misc.h"
+#include "iwlibstub.h"
+
+
+#include "libnvram.h"
+#include <Custom_NvRam_LID.h>
+
+#include "type.h"
+
+#ifndef WIFI_DRV_MOD_PATH
+#define WIFI_DRV_MOD_PATH         "/system/lib/modules/wlan.ko"
+#endif
+#ifndef WIFI_DRV_MOD_NAME
+#define WIFI_DRV_MOD_NAME         "wlan"
+#endif
+#ifndef WIFI_DRV_MOD_ARG
+#define WIFI_DRV_MOD_ARG          ""
+#endif
+#ifndef WIFI_TYPE_NAME
+#define WIFI_TYPE_NAME            "wlan"
+#endif
+
+#define WIFI_POWER_PATH     "/dev/wmtWifi"
+
+#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+#define MAX_NVRAM_ACCESS_SIZE           256
+#define NVRAM_G_BAND_TSSI_CH_GROUP_NUM     14
+#define NVRAM_A_BAND_TSSI_CH_GROUP_NUM     32
+#define NVRAM_G_BAND_TSSI_CH_OFS_SIZE   (sizeof(WIFI_NVRAM_TSSI_CH_OFS_T)*NVRAM_G_BAND_TSSI_CH_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_A_BAND_TSSI_CH_OFS_SIZE   (sizeof(WIFI_NVRAM_TSSI_CH_OFS_T)*NVRAM_A_BAND_TSSI_CH_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF0    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF0path.rTssiChOfs[0].ucTssiChOfsGT2))
+#define NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF1    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF1path.rTssiChOfs[0].ucTssiChOfsGT2))
+#define NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF0path.rTssiChOfs[0].ucTssiChOfsGT2))
+#define NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF1path.rTssiChOfs[0].ucTssiChOfsGT2))
+
+#if (CFG_DNL_CAL == 1)
+#define NVRAM_G_BAND_TSSI_DNL_GROUP_NUM     14
+#define NVRAM_A_BAND_TSSI_DNL_GROUP_NUM     8
+#define NVRAM_G_BAND_TSSI_DNL_OFS_SIZE   (sizeof(WIFI_NVRAM_TX_DNL_T)*NVRAM_G_BAND_TSSI_DNL_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_A_BAND_TSSI_DNL_OFS_SIZE   (sizeof(WIFI_NVRAM_TX_DNL_T)*NVRAM_A_BAND_TSSI_DNL_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_G_BAND_TSSI_DNL_OFS_OFSETOF_WF0    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF0path.rTxDnl[0].ucTxDnlCckGT0))
+#define NVRAM_G_BAND_TSSI_DNL_OFS_OFSETOF_WF1    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF1path.rTxDnl[0].ucTxDnlCckGT0))
+#define NVRAM_A_BAND_TSSI_DNL_OFS_OFSETOF_WF0    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF0path.rTxDnl[0].ucTxDnlCckGT0))
+#define NVRAM_A_BAND_TSSI_DNL_OFS_OFSETOF_WF1    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF1path.rTxDnl[0].ucTxDnlCckGT0))
+#endif
+
+#define NVRAM_G_BAND_LNA_GAIN_CAL_GROUP_NUM     1
+#define NVRAM_A_BAND_LNA_GAIN_CAL_GROUP_NUM     8
+#define NVRAM_G_BAND_LNA_GAIN_CAL_OFS_SIZE   (sizeof(WIFI_NVRAM_LNA_GAIN_CAL_T)*NVRAM_G_BAND_LNA_GAIN_CAL_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_A_BAND_LNA_GAIN_CAL_OFS_SIZE   (sizeof(WIFI_NVRAM_LNA_GAIN_CAL_T)*NVRAM_A_BAND_LNA_GAIN_CAL_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_G_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF0    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF0path.rLnaGainCal[0].ucRxCal1))
+#define NVRAM_G_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF1    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF1path.rLnaGainCal[0].ucRxCal1))
+#define NVRAM_A_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF0    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF0path.rLnaGainCal[0].ucRxCal1))
+#define NVRAM_A_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF1    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF1path.rLnaGainCal[0].ucRxCal1))
+#else
+#define MAX_NVRAM_ACCESS_SIZE           256
+#define NVRAM_G_BAND_TSSI_CH_GROUP_NUM     14
+#define NVRAM_A_BAND_TSSI_CH_GROUP_NUM     32
+#define NVRAM_G_BAND_TSSI_CH_OFS_SIZE   (sizeof(UINT_8)*NVRAM_G_BAND_TSSI_CH_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_A_BAND_TSSI_CH_OFS_SIZE   (sizeof(UINT_8)*NVRAM_A_BAND_TSSI_CH_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF0    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF0path.aucTx2G4TssiChannelOffsetLowCh[0]))
+#define NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF1    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF1path.aucTx2G4TssiChannelOffsetLowCh[0]))
+#define NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF0path.rTxTssiChannelOffset[0].ucTxPowerOffsetLow))
+#define NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF1path.rTxTssiChannelOffset[0].ucTxPowerOffsetLow))
+
+#define NVRAM_TSSI_STEP_OFSET    (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, rSys.u1TssiStep))
+#endif /*#if (WIFI_GEN_VER == CONNAC_SOC3_0)*/
+#endif /*#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)*/
+
+#define MAX_PL_INPUT_ARG_NUM 32
+#define POLLING_RECAL_RETRY_CNT 10
+#define QUERY_RECAL_RETRY_CNT 3
+
+#define GET_A_BAND_RF_GROUP(group) (((group % 2) == 0) ? (group / 2) : ((group - 1) / 2))
+
+//static const char DRIVER_MODULE_NAME[]  = WIFI_DRV_MOD_NAME;
+//static const char DRIVER_MODULE_TAG[]   = WIFI_DRV_MOD_NAME " ";
+//static const char DRIVER_MODULE_ARG[]   = WIFI_DRV_MOD_ARG;
+//static const char DRIVER_MODULE_PATH[]  = WIFI_DRV_MOD_PATH;
+//static const char MODULE_FILE[]         = "/proc/modules";
+
+static int   wifi_init = 0;
+static int   wifi_skfd = -1;
+//static int   wifi_rfkill_id = -1;
+//static char *wifi_rfkill_state_path = NULL;
+static WIFI_CNF_CB cnf_cb = NULL;
+
+//extern int init_module(void *, unsigned long, const char *);
+//extern int delete_module(const char *, unsigned int);
+extern int sched_yield(void);
+extern int ifc_init();
+extern int ifc_up(const char *name);
+extern int ifc_down(const char *name);
+extern void ifc_close();
+
+static F_INFO  gNvInfo;
+#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)
+static HQA_PARA_INFO gHqaParaInfo;
+static CH_GROUP_CLASS _arChGroupTbl[][BAND_NUM] =
+{
+    {   /* 2G channel group (COMMON) */
+        {
+            CH_GROUP_ITEM_COMMON,
+            NVRAM_COMMON_CATEGORY_G_BAND_CH_GROUP_NUM,
+            {
+                CH_GROUP_COMMON_G_BAND_BOUNDARY_00, CH_GROUP_COMMON_G_BAND_BOUNDARY_01, CH_GROUP_COMMON_G_BAND_BOUNDARY_02, CH_GROUP_COMMON_G_BAND_BOUNDARY_03,
+                CH_GROUP_COMMON_G_BAND_BOUNDARY_04, CH_GROUP_COMMON_G_BAND_BOUNDARY_05, CH_GROUP_COMMON_G_BAND_BOUNDARY_06, CH_GROUP_COMMON_G_BAND_BOUNDARY_07,
+                CH_GROUP_COMMON_G_BAND_BOUNDARY_08, CH_GROUP_COMMON_G_BAND_BOUNDARY_09, CH_GROUP_COMMON_G_BAND_BOUNDARY_10, CH_GROUP_COMMON_G_BAND_BOUNDARY_11,
+                CH_GROUP_COMMON_G_BAND_BOUNDARY_12, CH_GROUP_COMMON_G_BAND_BOUNDARY_13, CH_GROUP_COMMON_G_BAND_BOUNDARY_14, CH_GROUP_COMMON_G_BAND_BOUNDARY_15
+            }
+        },
+        /* 5G channel group (COMMON) */
+        {
+            CH_GROUP_ITEM_COMMON,
+            NVRAM_COMMON_CATEGORY_A_BAND_CH_GROUP_NUM,
+            {
+                CH_GROUP_COMMON_A_BAND_BOUNDARY_00, CH_GROUP_COMMON_A_BAND_BOUNDARY_01, CH_GROUP_COMMON_A_BAND_BOUNDARY_02, CH_GROUP_COMMON_A_BAND_BOUNDARY_03,
+                CH_GROUP_COMMON_A_BAND_BOUNDARY_04, CH_GROUP_COMMON_A_BAND_BOUNDARY_05, CH_GROUP_COMMON_A_BAND_BOUNDARY_06, CH_GROUP_COMMON_A_BAND_BOUNDARY_07,
+                CH_GROUP_COMMON_A_BAND_BOUNDARY_08, CH_GROUP_COMMON_A_BAND_BOUNDARY_09, CH_GROUP_COMMON_A_BAND_BOUNDARY_10, CH_GROUP_COMMON_A_BAND_BOUNDARY_11,
+                CH_GROUP_COMMON_A_BAND_BOUNDARY_12, CH_GROUP_COMMON_A_BAND_BOUNDARY_13, CH_GROUP_COMMON_A_BAND_BOUNDARY_14, CH_GROUP_COMMON_A_BAND_BOUNDARY_15
+            }
+        }
+    },
+    {   /* 2G channel group (TSSI_CH) */
+        {
+            CH_GROUP_ITEM_TSSI_CH,
+            NVRAM_TSSI_CH_OFFSET_G_BAND_CH_GROUP_NUM,
+            {
+                CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_00, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_01, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_02, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_03,
+                CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_04, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_05, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_06, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_07,
+                CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_08, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_09, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_10, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_11,
+                CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_12, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_13, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_14, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_15
+            }
+        },
+        /* 5G channel group (TSSI_CH) */
+        {
+            CH_GROUP_ITEM_TSSI_CH,
+            NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM,
+            {
+                CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_00, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_01, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_02, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_03,
+                CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_04, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_05, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_06, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_07,
+                CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_08, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_09, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_10, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_11,
+                CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_12, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_13, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_14, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_15
+            }
+        }
+    },
+};
+static CH_SUB_GROUP_CLASS _arSubGroupTbl[][BAND_NUM] =
+{
+    {   /* 2G channel group (TX) */
+        {
+            CH_SUB_GROUP_TSSI_CH,
+            CH_SUB_GROUP_2G4_ITEM_NUM, CH_SUB_GROUP_G_BAND_NOT_ORDERED_NUM,
+            {
+                CH_SUB_GROUP_G_BAND_BOUNDARY_00, CH_SUB_GROUP_G_BAND_BOUNDARY_01, CH_SUB_GROUP_G_BAND_BOUNDARY_02, CH_SUB_GROUP_G_BAND_BOUNDARY_03,
+                CH_SUB_GROUP_G_BAND_BOUNDARY_04, CH_SUB_GROUP_G_BAND_BOUNDARY_05, CH_SUB_GROUP_G_BAND_BOUNDARY_06, CH_SUB_GROUP_G_BAND_BOUNDARY_07,
+                CH_SUB_GROUP_G_BAND_BOUNDARY_08, CH_SUB_GROUP_G_BAND_BOUNDARY_09, CH_SUB_GROUP_G_BAND_BOUNDARY_10, CH_SUB_GROUP_G_BAND_BOUNDARY_11,
+                CH_SUB_GROUP_G_BAND_BOUNDARY_12, CH_SUB_GROUP_G_BAND_BOUNDARY_13, CH_SUB_GROUP_G_BAND_BOUNDARY_14, CH_SUB_GROUP_G_BAND_BOUNDARY_15
+            }
+        },
+        /* 5G channel group (TX) */
+        {
+            CH_SUB_GROUP_TSSI_CH,
+            CH_SUB_GROUP_5G_ITEM_NUM, CH_SUB_GROUP_A_BAND_NOT_ORDERED_NUM,
+            {
+                CH_SUB_GROUP_A_BAND_BOUNDARY_00, CH_SUB_GROUP_A_BAND_BOUNDARY_01, CH_SUB_GROUP_A_BAND_BOUNDARY_02, CH_SUB_GROUP_A_BAND_BOUNDARY_03,
+                CH_SUB_GROUP_A_BAND_BOUNDARY_04, CH_SUB_GROUP_A_BAND_BOUNDARY_05, CH_SUB_GROUP_A_BAND_BOUNDARY_06, CH_SUB_GROUP_A_BAND_BOUNDARY_07,
+                CH_SUB_GROUP_A_BAND_BOUNDARY_08, CH_SUB_GROUP_A_BAND_BOUNDARY_09, CH_SUB_GROUP_A_BAND_BOUNDARY_10, CH_SUB_GROUP_A_BAND_BOUNDARY_11,
+                CH_SUB_GROUP_A_BAND_BOUNDARY_12, CH_SUB_GROUP_A_BAND_BOUNDARY_13, CH_SUB_GROUP_A_BAND_BOUNDARY_14, CH_SUB_GROUP_A_BAND_BOUNDARY_15
+            }
+        }
+    }
+};
+
+#define CH_GROUP_CLASS_TBL_ITEM_NUM (sizeof(_arChGroupTbl)) / (sizeof(CH_GROUP_CLASS)) / (BAND_NUM)
+#define CH_SUB_GROUP_CLASS_TBL_ITEM_NUM (sizeof(_arSubGroupTbl)) / (sizeof(CH_SUB_GROUP_CLASS)) / (BAND_NUM)
+#endif /*#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)*/
+static void wifi_send_resp(FT_WM_WIFI_CNF *cnf, void *buf, unsigned int size)
+{
+    if (cnf_cb)
+        cnf_cb(cnf, buf, size);
+    else
+        WriteDataToPC(cnf, sizeof(FT_WM_WIFI_CNF), buf, size);
+}
+
+int write_data_to_driver(char *data, size_t length)
+{
+    int sz;
+    int fd = -1;
+    int ret = -1;
+    int retry_cont;
+
+    if (!data || !length)
+        return ret;
+
+    for (retry_cont = 0; retry_cont < 5; retry_cont++)
+    {
+        DBG("open retry_cont = (%d)", retry_cont);
+        fd = open(WIFI_POWER_PATH, O_WRONLY);
+
+        if (fd < 0)
+        {
+            usleep(1000000);
+        }
+        else
+            break;
+    }
+
+    if (fd < 0)
+    {
+        DBG("open(%s) for write failed: %s (%d)", WIFI_POWER_PATH,
+            strerror(errno), errno);
+        goto out;
+    }
+
+    for (retry_cont = 0; retry_cont < 5; retry_cont++)
+    {
+        DBG("write retry_cont = (%d)", retry_cont);
+        sz = write(fd, data, length);
+
+        if (sz < 0)
+        {
+#if 0
+            DBG("write(%s) failed: %s (%d)", WIFI_POWER_PATH, strerror(errno),
+                errno);
+            goto out;
+#endif
+
+            usleep(1000000);
+        }
+        else
+            break;
+    }
+
+    if (sz > 0)
+        ret = 0;
+    else
+    {
+        DBG("write(%s) failed: %s (%d)", WIFI_POWER_PATH, strerror(errno),
+            errno);
+    }
+
+out:
+
+    if (fd >= 0)
+        close(fd);
+
+    return ret;
+}
+/*----------------------------------------------------------------------------*/
+/**
+* @brief wifi nvram control: read nvram and wirte nvram
+*
+* @param[in] fgSet, (true:write, false:read)
+*
+* @return new command size
+*/
+/*----------------------------------------------------------------------------*/
+int wifiNVRAMCtrl(bool fgSet, PNVRAM_ACCESS_STRUCT pnvram)
+{
+
+    int ret = -1;
+    int iFD;
+    int readByteLen = -1;
+
+    if (pnvram == NULL)
+    {
+
+        return -1;
+    }
+
+    DBG("[META_WIFI] NVRAMCtrl fg(%d) len(%d)\n", fgSet, pnvram->dataLen);
+
+
+    if (fgSet)
+    {
+        DBG("[META_WIFI] write offset:%d (0x%04X)\n", pnvram->dataOffset, pnvram->dataOffset);
+        iFD = open(gNvInfo.cFileName, O_WRONLY | O_CREAT, S_IRUSR | S_IRGRP);
+
+        if (iFD >= 0)
+        {
+            if (lseek(iFD, pnvram->dataOffset, SEEK_SET) < 0)
+            {
+                ERR("[META_WIFI] read fail!");
+                close(iFD);
+                return -1;
+            }
+
+            write(iFD, pnvram->data, pnvram->dataLen);
+            close(iFD);
+
+            /* invoke protect data file mechanism */
+            if (NVM_ProtectDataFile(AP_CFG_RDEB_FILE_WIFI_LID, 1) != 1)
+            {
+                ERR("[META_WIFI] NVM_ProtectDataFile(): set failed\n");
+                ret = -1;
+            }
+            else
+            {
+                // invoke auto backup mechanism
+                NVM_AddBackupFileNum(AP_CFG_RDEB_FILE_WIFI_LID);
+                ret = 0;
+            }
+        }
+        else
+        {
+            ERR("[META_WIFI] open file :%s fail!, iFD=%d", gNvInfo.cFileName, iFD);
+            return -1;
+        }
+
+
+    }
+    else
+    {
+        /* post-check for read access */
+        DBG("[META_WIFI] read offset:%d (0x%04X)\n", pnvram->dataOffset, pnvram->dataOffset);
+
+        if (NVM_ProtectDataFile(AP_CFG_RDEB_FILE_WIFI_LID, 0) != 1)
+        {
+            ERR("[META_WIFI] NVM_ProtectDataFile(): get failed\n");
+            return -1;
+        }
+
+        iFD = open(gNvInfo.cFileName, O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP);
+
+        if (iFD >= 0)
+        {
+            if (lseek(iFD, pnvram->dataOffset, SEEK_SET) < 0)
+            {
+                ERR("[META_WIFI] lseek fail!");
+                close(iFD);
+                return -1;
+            }
+
+            readByteLen = read(iFD, pnvram->data, pnvram->dataLen);
+
+            if (readByteLen <= 0)
+            {
+                ERR("[META_WIFI] read fail! ,readByteLen :%d", readByteLen);
+                close(iFD);
+                return -1;
+            }
+
+            close(iFD);
+
+            ret = readByteLen;
+        }
+        else
+        {
+            ERR("[META_WIFI] open file :%s fail!", gNvInfo.cFileName);
+            return -1;
+        }
+
+
+    }
+
+    return ret;
+}
+
+void wifwNVRAMWriteDataToDriver(void)
+{
+    char *pCmdNvram;
+    int ret = -1;
+    PNVRAM_ACCESS_STRUCT pQueryNv = NULL;
+    int readLen = -1;
+    int cmdLen = -1;
+    char *pBuf = NULL;
+
+    pQueryNv = (PNVRAM_ACCESS_STRUCT)malloc(gNvInfo.i4RecSize + sizeof(NVRAM_ACCESS_STRUCT));
+
+    if (!pQueryNv)
+    {
+        DBG("out of memory in allocating pQueryNv\n");
+        return ;
+    }
+
+    /*read NVRAM contant*/
+    pQueryNv->dataLen = gNvInfo.i4RecSize;
+    pQueryNv->dataOffset = 0; /*read NVRAM range[0~ dataLen]*/
+    readLen = wifiNVRAMCtrl(NVRAM_READ, pQueryNv);
+    pBuf = (char *)&pQueryNv->data[0];
+
+
+    /*Fill wmtWifi command buffer*/
+    cmdLen = gNvInfo.i4RecSize + 12;
+    pCmdNvram = (char *)malloc(cmdLen);
+
+    if (!pCmdNvram)
+    {
+        DBG("out of memory in allocating acnvram\n");
+        goto exit;
+    }
+
+    memset(pCmdNvram, 0, cmdLen);
+    strncpy(pCmdNvram, "WR-BUF:NVRAM", 12);
+    memcpy(pCmdNvram + 12, pBuf, gNvInfo.i4RecSize);
+
+    /*write cmd to wifi driver*/
+    ret = write_data_to_driver(pCmdNvram, cmdLen);
+
+    DBG("[META_WIFI] write NVRAM[%d] to driver done! ret =%d \n", readLen, ret);
+
+exit:
+    FREEIF(pCmdNvram);
+    FREEIF(pQueryNv);
+
+}
+
+/*
+* Control Wi-Fi power by RFKILL interface is deprecated.
+* Use character device to control instead.
+*/
+#if 0
+static int wifi_init_rfkill(void)
+{
+    char path[128];
+    char buf[32];
+    int fd, id;
+    ssize_t sz;
+
+    for (id = 0; id < 10 ; id++)
+    {
+        snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id);
+        fd = open(path, O_RDONLY);
+
+        if (fd < 0)
+        {
+            printf("open(%s) failed: %s (%d)\n", path, strerror(errno), errno);
+            return -1;
+        }
+
+        sz = read(fd, &buf, sizeof(buf));
+        close(fd);
+
+        if (sz >= (ssize_t)strlen(WIFI_TYPE_NAME) &&
+                memcmp(buf, WIFI_TYPE_NAME, strlen(WIFI_TYPE_NAME)) == 0)
+        {
+            wifi_rfkill_id = id;
+            break;
+        }
+    }
+
+    if (id == 10)
+        return -1;
+
+    asprintf(&wifi_rfkill_state_path, "/sys/class/rfkill/rfkill%d/state",
+             wifi_rfkill_id);
+
+    return 0;
+}
+
+static int wifi_check_power(void)
+{
+    int sz;
+    int fd = -1;
+    int ret = -1;
+    char buf;
+    char *path = wifi_rfkill_state_path;
+
+    if ((wifi_rfkill_id == -1) && wifi_init_rfkill())
+        goto out;
+
+    fd = open(path, O_RDONLY);
+
+    if (fd < 0)
+    {
+        printf("open(%s) failed: %s (%d)", path, strerror(errno),
+               errno);
+        goto out;
+    }
+
+    sz = read(fd, &buf, 1);
+
+    if (sz != 1)
+    {
+        printf("read(%s) failed: %s (%d)", path, strerror(errno),
+               errno);
+        goto out;
+    }
+
+    switch (buf)
+    {
+        case '1':
+            ret = 1;
+            break;
+
+        case '0':
+            ret = 0;
+            break;
+    }
+
+out:
+
+    if (fd >= 0)
+        close(fd);
+
+    return ret;
+}
+
+static int wifi_set_power(int on)
+{
+    int sz;
+    int fd = -1;
+    int ret = -1;
+    const char buf = (on ? '1' : '0');
+
+    if (wifi_rfkill_id == -1)
+    {
+        if (wifi_init_rfkill()) goto out;
+    }
+
+    fd = open(wifi_rfkill_state_path, O_WRONLY);
+
+    if (fd < 0)
+    {
+        printf("open(%s) for write failed: %s (%d)", wifi_rfkill_state_path,
+               strerror(errno), errno);
+        goto out;
+    }
+
+    sz = write(fd, &buf, 1);
+
+    if (sz < 0)
+    {
+        printf("write(%s) failed: %s (%d)", wifi_rfkill_state_path, strerror(errno),
+               errno);
+        goto out;
+    }
+
+    ret = 0;
+
+out:
+
+    if (fd >= 0) close(fd);
+
+    return ret;
+}
+#else
+
+
+static int wifi_set_power(int on)
+{
+    int ret = -1;
+    const char buf = (on ? '1' : '0');
+
+    if (on)
+        wifwNVRAMWriteDataToDriver();
+
+    ret = write_data_to_driver((char *)&buf, sizeof(buf));
+
+    return ret;
+}
+#endif
+
+#if 0
+static int wifi_insmod(const char *filename, const char *args)
+{
+    void *module;
+    unsigned int size;
+    int ret;
+
+    module = load_file(filename, &size);
+
+    if (!module)
+        return -1;
+
+    ret = init_module(module, size, args);
+
+    free(module);
+
+    return ret;
+}
+
+static int wifi_rmmod(const char *modname)
+{
+    int ret = -1;
+    int maxtry = 10;
+
+    while (maxtry-- > 0)
+    {
+        ret = delete_module(modname, O_NONBLOCK | O_EXCL);
+
+        if (ret < 0 && errno == EAGAIN)
+            usleep(500000);
+        else
+            break;
+    }
+
+    if (ret != 0)
+        ERR("Unable to unload driver \"%s\": %s\n", modname, strerror(errno));
+
+    return ret;
+}
+
+static int wifi_is_loaded(void)
+{
+    FILE *proc;
+    char line[sizeof(DRIVER_MODULE_TAG) + 10];
+
+    if ((proc = fopen(MODULE_FILE, "r")) == NULL)
+    {
+        ERR("Could not open %s: %s", MODULE_FILE, strerror(errno));
+        return 0;
+    }
+
+    while ((fgets(line, sizeof(line), proc)) != NULL)
+    {
+        if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0)
+        {
+            fclose(proc);
+            return 1;
+        }
+    }
+
+    fclose(proc);
+    return 0;
+}
+#endif
+
+void removeSubstring(char *s, const char *toremove)
+{
+    while ((s = strstr(s, toremove)) != NULL)
+        memmove(s, s + strlen(toremove), 1 + strlen(s + strlen(toremove)));
+
+}
+/*----------------------------------------------------------------------------*/
+/**
+* @brief remove Script's head command, inclue: adb, shell, iwpriv,wlan0,driver
+*
+* @param[in] pStr, input string
+*
+* @return new command size
+*/
+/*----------------------------------------------------------------------------*/
+
+#define WIFI_REMOVE_HEAD_SIZE 5
+int wifiScriptRemoveHead(char *pStr)
+{
+    int strIndex = 0;
+    char *removeStrArray[WIFI_REMOVE_HEAD_SIZE] =
+    {
+        "adb ",
+        "shell ",
+        "iwpriv ",
+        "wlan0 ",
+        "driver ",
+    };
+
+    if (!pStr)
+        return FALSE;
+
+    for (strIndex = 0 ; strIndex < WIFI_REMOVE_HEAD_SIZE ; strIndex++)
+    {
+        if (strncmp(pStr, removeStrArray[strIndex], strlen(removeStrArray[strIndex])) == 0)
+            removeSubstring(pStr, removeStrArray[strIndex]);
+    }
+
+    return strlen(pStr);
+}
+
+WLAN_STATUS wifiNVRAMWirteByte(unsigned int offset, unsigned char value)
+{
+    PNVRAM_ACCESS_STRUCT pSetNv = NULL;
+    pSetNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + sizeof(unsigned char));
+    if (!pSetNv)
+    {
+        DBG("out of memory in allocating pSetNv\n");
+        return META_WIFI_STATUS_FAIL;
+    }
+    pSetNv->dataLen = sizeof(unsigned char);
+    pSetNv->dataOffset = offset;
+    memcpy(&pSetNv->data[0], &value, sizeof(value));
+    wifiNVRAMCtrl(NVRAM_WRITE, pSetNv);
+    FREEIF(pSetNv);
+
+    return META_WIFI_STATUS_SUCCESS;
+}
+
+#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)
+unsigned char wifiNVRAMGetSubChGroup(
+    ENUM_BAND_T eBand,
+    unsigned char u1CenterCh,
+    unsigned char u1ChGroupIdx,
+    ENUM_CH_SUB_GROUP_ITEM eChSubGroupItem
+)
+{
+    unsigned char u1Idx = 0;
+    unsigned char u1ChBand;
+    unsigned char u1SubGroupIdx = 0;
+    unsigned char u1GroupIdx = 0;
+    unsigned char u1BoundaryNum = 0;
+    P_CH_SUB_GROUP_CLASS prChSubGroup = NULL;
+
+    /* get channel band */
+    u1ChBand = (BAND_2G4 == eBand) ? (G_BAND) : (A_BAND);
+
+    /* get pointer of channel power offset sub-group table entry */
+    for (u1Idx = 0 ; u1Idx < CH_SUB_GROUP_CLASS_TBL_ITEM_NUM ; u1Idx++)
+    {
+        if (_arSubGroupTbl[u1Idx][u1ChBand].eGroupId == eChSubGroupItem)
+        {
+            prChSubGroup = &(_arSubGroupTbl[u1Idx][u1ChBand]);
+            break;
+        }
+    }
+
+    if (prChSubGroup == NULL)
+    {
+        DBG("Can't find Channel Sub Group mapping Band:%d,item:%d\n", eBand, eChSubGroupItem);
+        return META_WIFI_STATUS_INVALID_PARA;
+    }
+
+
+    /* get boundary number for each group */
+    u1BoundaryNum = prChSubGroup->u1ChSubGroupCategoryNum - 1;
+
+    /* search channel power offset sub-group index for specific channel */
+    for (u1GroupIdx = (u1ChGroupIdx * u1BoundaryNum); u1GroupIdx < ((u1ChGroupIdx + 1) * u1BoundaryNum); u1GroupIdx++)
+    {
+        /* increment channel group index when exceed channel group boundary */
+        if (u1CenterCh > prChSubGroup->u1ChSubGroupBoundary[u1GroupIdx])
+            u1SubGroupIdx++;
+    }
+
+    /* special case (channel number not in order) handler for 5G band channel group 0 */
+    if ((0 == u1ChGroupIdx) && (BAND_5G == eBand))
+    {
+        /* cyclic left shift sub-group index by Non-ordered subgroup number */
+        u1SubGroupIdx += prChSubGroup->u1ChSubGroupNotOrderedNum;
+        u1SubGroupIdx %= prChSubGroup->u1ChSubGroupCategoryNum;
+    }
+
+    return u1SubGroupIdx;
+}
+unsigned char wifiNVRAMGetChGroup(ENUM_BAND_T eBand, unsigned char u1CenterCh, ENUM_CH_GROUP_ITEM eChGroupItem)
+{
+    unsigned char u1Idx;
+    unsigned char u1ChGroupIdx = 0;
+    unsigned char u1GroupIdx = 0;
+    P_CH_GROUP_CLASS prChGroup = NULL;
+    unsigned char u1ChBand;
+
+    /* get channel band */
+    u1ChBand = (BAND_2G4 == eBand) ? (G_BAND) : (A_BAND);
+
+    /* search Channel group class table entry */
+    for (u1Idx = 0 ; u1Idx < CH_GROUP_CLASS_TBL_ITEM_NUM ; u1Idx++)
+    {
+        if (_arChGroupTbl[u1Idx][u1ChBand].eGroupId == eChGroupItem)
+        {
+            prChGroup = &(_arChGroupTbl[u1Idx][u1ChBand]);
+            break;
+        }
+    }
+
+    if (prChGroup == NULL)
+    {
+        DBG("Can't find Channel Group mapping Band:%d,item:%d\n", eBand, eChGroupItem);
+        return META_WIFI_STATUS_INVALID_PARA;
+    }
+
+    /* search class index for specific channel */
+    for (u1GroupIdx = 0; u1GroupIdx < prChGroup->u1ChGroupSupportNum; u1GroupIdx++)
+    {
+        /* increment channel group index when exceed channel group boundary */
+        if (u1CenterCh > prChGroup->u1ChGroupBoundary[u1GroupIdx])
+            u1ChGroupIdx++;
+    }
+
+    /* cyclic channel group process for high channel number in group 0 */
+    if (prChGroup->u1ChGroupSupportNum != 1)
+        u1ChGroupIdx %= prChGroup->u1ChGroupSupportNum;
+
+    DBG("GetCh:%d ,ID:%d ,Group Idx:%d\n", u1CenterCh, eChGroupItem, u1ChGroupIdx);
+
+    return u1ChGroupIdx;
+
+
+}
+
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+/*Thrshold bound is defined */
+unsigned char wifiNVRAMTssiChGainTableSelect(int pwr)
+{
+    unsigned char table_ofs = 0;
+
+    if (pwr >= TSSI_CH_OFFSET_TH_GT7)
+        table_ofs = NVRAM_GT7_OFFSET;
+    else if ((TSSI_CH_OFFSET_TH_GT7 > pwr) && (pwr >= TSSI_CH_OFFSET_TH_GT6))
+        table_ofs = NVRAM_GT6_OFFSET;
+    else if ((TSSI_CH_OFFSET_TH_GT6 > pwr) && (pwr >= TSSI_CH_OFFSET_TH_GT5))
+        table_ofs = NVRAM_GT5_OFFSET;
+    else if ((TSSI_CH_OFFSET_TH_GT5 > pwr) && (pwr >= TSSI_CH_OFFSET_TH_GT4))
+        table_ofs = NVRAM_GT4_OFFSET;
+    else if ((TSSI_CH_OFFSET_TH_GT4 > pwr) && (pwr >= TSSI_CH_OFFSET_TH_GT3))
+        table_ofs = NVRAM_GT3_OFFSET;
+    else if ((TSSI_CH_OFFSET_TH_GT3 > pwr) && (pwr >= TSSI_CH_OFFSET_TH_GT2))
+        table_ofs = NVRAM_GT2_OFFSET;
+    else
+        DBG("out of Gain Table thrshold :%d\n", pwr);
+
+    /* Low Bound <= pwr < Upper Bound*/
+    DBG("GT7[%d ~ %d]\n", TSSI_CH_OFFSET_TH_GT7, 127);
+    DBG("GT6[%d ~ %d]\n", TSSI_CH_OFFSET_TH_GT6, TSSI_CH_OFFSET_TH_GT7);
+    DBG("GT5[%d ~ %d]\n", TSSI_CH_OFFSET_TH_GT5, TSSI_CH_OFFSET_TH_GT6);
+    DBG("GT4[%d ~ %d]\n", TSSI_CH_OFFSET_TH_GT4, TSSI_CH_OFFSET_TH_GT5);
+    DBG("GT3[%d ~ %d]\n", TSSI_CH_OFFSET_TH_GT3, TSSI_CH_OFFSET_TH_GT4);
+    DBG("GT2[%d ~ %d]\n", TSSI_CH_OFFSET_TH_GT2, TSSI_CH_OFFSET_TH_GT3);
+    DBG("Pwr:%d is filled in GT%d\n", pwr, (table_ofs + 2));
+
+    return table_ofs;
+}
+#endif
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+WLAN_STATUS wifiNVRAMTssiChGainTableAllTheSame(unsigned int nvOfs, unsigned char value)
+{
+    unsigned int gtOfsArray[TSSI_CH_OFS_GT_NUM] = {NVRAM_GT2_OFFSET, NVRAM_GT3_OFFSET,
+                                                   NVRAM_GT4_OFFSET, NVRAM_GT5_OFFSET, NVRAM_GT6_OFFSET, NVRAM_GT7_OFFSET
+                                                  };
+    int idx = 0;
+
+    unsigned int gtNvOfs = 0;
+
+    for (idx = 0 ; idx < TSSI_CH_OFS_GT_NUM ; idx++)
+    {
+        gtNvOfs = nvOfs + gtOfsArray[idx];
+        wifiNVRAMWirteByte(gtNvOfs, value);
+        DBG("GT%d [0x%x]=0x%x\n", (idx + 2), gtNvOfs, value);
+    }
+
+    return META_WIFI_STATUS_SUCCESS;
+}
+#endif
+
+unsigned int wifiNVRAMTssiChGetNVRAMOfs(unsigned int wf,
+                                        ENUM_BAND_T eBand, unsigned int ch, unsigned int *pOfs)
+{
+
+    unsigned int u4NvramOffset = 0;
+
+    unsigned char groupId = wifiNVRAMGetChGroup(eBand, ch, CH_GROUP_ITEM_TSSI_CH);
+    unsigned char subGroupId = wifiNVRAMGetSubChGroup(eBand, ch, groupId, CH_SUB_GROUP_TSSI_CH);
+
+    if (ch <= 0)
+    {
+        DBG("Tssi Ch error:%d\n", ch);
+        return META_WIFI_STATUS_INVALID_PARA;
+    }
+
+    if (wf >= WF_NUM)
+    {
+        DBG("Tssi wf error:%d\n", wf);
+        return META_WIFI_STATUS_INVALID_PARA;
+    }
+
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+
+    if (eBand == BAND_2G4)
+    {
+        u4NvramOffset = (wf == WF0) ? (NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF0) : (NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF1);
+        u4NvramOffset += sizeof(WIFI_NVRAM_TSSI_CH_OFS_T) * groupId;
+
+    }
+    else
+    {
+        u4NvramOffset = (wf == WF0) ? (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0) : (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1);
+        u4NvramOffset += (groupId * (CH_SUB_GROUP_5G_ITEM_NUM) + subGroupId) * sizeof(WIFI_NVRAM_TSSI_CH_OFS_T);
+    }
+
+#else
+
+    if (eBand == BAND_2G4)
+    {
+        u4NvramOffset = (wf == WF0) ? (NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF0) : (NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF1);
+        u4NvramOffset += sizeof(UINT_8) * groupId;
+
+    }
+    else
+    {
+        u4NvramOffset = (wf == WF0) ? (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0) : (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1);
+        u4NvramOffset += (groupId * (CH_SUB_GROUP_5G_ITEM_NUM) + subGroupId) * sizeof(UINT_8);
+    }
+
+#endif
+    *pOfs = u4NvramOffset;
+
+    return META_WIFI_STATUS_SUCCESS;
+
+}
+WLAN_STATUS wifiNVRAMTssiChOfsRfGroupTheSame(unsigned int wf, ENUM_BAND_T eBand,
+        unsigned int ch, unsigned int chGroup, char nvCompVal)
+{
+
+    unsigned char rfGroup = 0, subGroup = 0;
+    unsigned int u4NvramOffset = 0;
+    unsigned int chInter = 0;
+
+    if (eBand != BAND_5G)
+    {
+        DBG("only Support 5G Channel\n");
+        return META_WIFI_STATUS_INVALID_PARA;
+    }
+
+    rfGroup = GET_A_BAND_RF_GROUP(chGroup);
+    subGroup = wifiNVRAMGetSubChGroup(eBand, ch, chGroup, CH_SUB_GROUP_TSSI_CH);
+
+    DBG("group the same: ch[%d],tssiChGroup=%d,subGroup=%d,RfGroup=%d,nvCompVal=0x%02X\n",
+        ch, chGroup, subGroup, rfGroup, nvCompVal);
+
+    /*update (n) ~ (n+3) Tssi ch group in one RF Group*/
+    for (chInter = (rfGroup * PER_CH_GROUP_IN_RF_GROUP) ; chInter < ((rfGroup * PER_CH_GROUP_IN_RF_GROUP) + PER_CH_GROUP_IN_RF_GROUP); chInter++)
+    {
+        u4NvramOffset = (wf == WF0) ? (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0) : (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1);
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+        u4NvramOffset += (chInter * sizeof(WIFI_NVRAM_TSSI_CH_OFS_T));
+#else
+        u4NvramOffset += (chInter * sizeof(UINT_8));
+#endif
+#if (CFG_TSSI_CH_GT_SAME == 1)
+        DBG("update TssiChGroup[%d][%c],NvOfs=0x%08X,NvVal=0x%02X\n",
+            chInter / 2,
+            ((chInter % 2) == 0) ? ('L') : ('H'),
+            u4NvramOffset,
+            nvCompVal);
+
+        wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, nvCompVal);
+#else
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+        u4NvramOffset += OFFSET_OF(WIFI_NVRAM_TSSI_CH_OFS_T, ucTssiChOfsGT7);
+#endif
+        wifiNVRAMWirteByte(u4NvramOffset, nvCompVal);
+        DBG("update TssiChGroup[%d][%c] nvOfs=0x%X,nvCompVal=0x%02X\n",
+            chInter / 2,
+            ((chInter % 2) == 0) ? ('L') : ('H'),
+            u4NvramOffset,
+            nvCompVal);
+#endif
+    }
+
+    return META_WIFI_STATUS_SUCCESS;
+
+}
+
+
+/*clear tssi channel offset*/
+WLAN_STATUS wifiNVRAMTssiChOfsClear(void)
+{
+    NVRAM_ACCESS_STRUCT raNvram[] =
+    {
+        /*2.4G WF0 Tssi Ch*/
+        {NVRAM_G_BAND_TSSI_CH_OFS_SIZE, NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF0, {0}},
+        /*2.4G WF1 Tssi Ch*/
+        {NVRAM_G_BAND_TSSI_CH_OFS_SIZE, NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF1, {0}},
+        /*5G WF0 Tssi Ch*/
+        {NVRAM_A_BAND_TSSI_CH_OFS_SIZE, NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0, {0}},
+        /*5G WF1 Tssi Ch*/
+        {NVRAM_A_BAND_TSSI_CH_OFS_SIZE, NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1, {0}},
+
+    };
+    PNVRAM_ACCESS_STRUCT pQueryNv = NULL;
+    char *pBuf = NULL;
+
+#if 0
+    int readLen = 0, j = 0;
+#endif
+    int i = 0;
+
+    pQueryNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE);
+
+    if (pQueryNv == NULL)
+    {
+        ERR("[META_WIFI] No memory nvram\n");
+        goto error;
+    }
+
+    for (i = 0 ; i < (sizeof(raNvram) / sizeof(NVRAM_ACCESS_STRUCT)) ; i++)
+    {
+        pQueryNv->dataLen = raNvram[i].dataLen;
+        pQueryNv->dataOffset = raNvram[i].dataOffset;
+        pBuf = (char *)&pQueryNv->data[0];
+#if 0
+        /*read before clean*/
+        readLen = wifiNVRAMCtrl(NVRAM_READ, pQueryNv);
+        DBG("[META_WIFI] 1st read len= %d\n", readLen);
+
+        for (j = 0; j < readLen; j++)
+            DBG("[META_WIFI] NVofs(0x%08X)[%p] = 0x%02X\n", (pQueryNv->dataOffset + j), (pBuf + j), *(pBuf + j));
+
+#endif
+        /*clear NVRAM content*/
+        memset(pBuf, 0, MAX_NVRAM_ACCESS_SIZE);
+        wifiNVRAMCtrl(NVRAM_WRITE, pQueryNv);
+
+#if 0
+        /*read again*/
+        readLen = wifiNVRAMCtrl(NVRAM_READ, pQueryNv);
+        DBG("[META_WIFI] 2st read len= %d\n", readLen);
+
+        for (j = 0; j < readLen; j++)
+            DBG("[META_WIFI] NVofs(0x%08X)[%p] = 0x%02X\n", (pQueryNv->dataOffset + j), (pBuf + j), *(pBuf + j));
+
+#endif
+    }
+
+    DBG("Finish!\n");
+error:
+    FREEIF(pQueryNv);
+
+    return META_WIFI_STATUS_SUCCESS;
+
+}
+
+WLAN_STATUS wifiNVRAMTssiContentDumpToPC(ENUM_BAND_T eBand, P_CMD_PL_CAL pCmdPLcal, WLAN_STATUS kResult)
+{
+
+    PNVRAM_ACCESS_STRUCT pQueryNv = NULL;
+    int readLen = 0, buffIdx = 0;
+
+    pQueryNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(PNVRAM_ACCESS_STRUCT));
+
+    if (!pQueryNv)
+    {
+        DBG("out of memory in allocating pQueryNv\n");
+        return META_WIFI_STATUS_FAIL;
+    }
+    memset(pQueryNv, 0, sizeof(PNVRAM_ACCESS_STRUCT));
+
+    /*debug flow:add response data to PC*/
+    pCmdPLcal->au4Buffer[buffIdx++] = kResult;
+
+    if (eBand == BAND_2G4)
+    {
+        pCmdPLcal->au4Buffer[buffIdx++] = (NVRAM_G_BAND_TSSI_CH_OFS_SIZE << 16) | NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF0;
+
+        /*read 2.4G WF0 TSSI CH OFS*/
+        pQueryNv->dataLen = NVRAM_G_BAND_TSSI_CH_OFS_SIZE;
+        pQueryNv->dataOffset = NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF0;
+        readLen = wifiNVRAMCtrl(NVRAM_READ, pQueryNv);
+        memcpy(&pCmdPLcal->au4Buffer[buffIdx], &pQueryNv->data[0], readLen);
+        buffIdx += readLen / sizeof(unsigned int);
+
+        /*clear buffer*/
+        memset(pQueryNv, 0, MAX_NVRAM_ACCESS_SIZE);
+
+        pCmdPLcal->au4Buffer[buffIdx++] = (NVRAM_G_BAND_TSSI_CH_OFS_SIZE << 16) | NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF1;
+
+        /*read 2.4G WF1 TSSI CH OFS*/
+        pQueryNv->dataLen = NVRAM_G_BAND_TSSI_CH_OFS_SIZE;
+        pQueryNv->dataOffset = NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF1;
+
+        readLen = wifiNVRAMCtrl(NVRAM_READ, pQueryNv);
+        memcpy(&pCmdPLcal->au4Buffer[buffIdx], &pQueryNv->data[0], readLen);
+        buffIdx += readLen / sizeof(unsigned int);
+
+        memset(pQueryNv, 0, MAX_NVRAM_ACCESS_SIZE);
+
+        /*update data length*/
+        pCmdPLcal->inputLen = buffIdx;
+
+    }
+    else
+    {
+        pCmdPLcal->au4Buffer[buffIdx++] = (NVRAM_A_BAND_TSSI_CH_OFS_SIZE << 16) | NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0;
+
+        /*read 5G WF0 TSSI CH OFS*/
+        pQueryNv->dataLen = NVRAM_A_BAND_TSSI_CH_OFS_SIZE;
+        pQueryNv->dataOffset = NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0;
+        readLen = wifiNVRAMCtrl(NVRAM_READ, pQueryNv);
+        memcpy(&pCmdPLcal->au4Buffer[buffIdx], &pQueryNv->data[0], readLen);
+        buffIdx += readLen / sizeof(unsigned int);
+
+        memset(pQueryNv, 0, MAX_NVRAM_ACCESS_SIZE);
+
+        pCmdPLcal->au4Buffer[buffIdx++] = (NVRAM_A_BAND_TSSI_CH_OFS_SIZE << 16) | NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1;
+
+        /*read 5G WF1 TSSI CH OFS*/
+        pQueryNv->dataLen = NVRAM_A_BAND_TSSI_CH_OFS_SIZE;
+        pQueryNv->dataOffset = NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1;
+
+        readLen = wifiNVRAMCtrl(NVRAM_READ, pQueryNv);
+        memcpy(&pCmdPLcal->au4Buffer[buffIdx], &pQueryNv->data[0], readLen);
+        buffIdx += readLen / sizeof(unsigned int);
+
+        memset(pQueryNv, 0, MAX_NVRAM_ACCESS_SIZE);
+
+        /*update data length*/
+        pCmdPLcal->inputLen = buffIdx;
+
+    }
+
+    FREEIF(pQueryNv);
+    DBG("Band[%d] Calibration Result:%d dump done!\n", eBand, kResult);
+
+    return kResult;
+}
+
+#if (WIFI_GEN_VER != CONNAC_SOC3_0)
+unsigned int wifiNVRAMCalculateShift()
+{
+    unsigned int ret = 7;
+    UINT_8 tssiStep;
+    unsigned int readLine = 0;
+    PNVRAM_ACCESS_STRUCT pSetNv = NULL;
+
+    /* read from NVram calculateShift */
+    pSetNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + sizeof(UINT_8));
+
+    if (!pSetNv)
+    {
+        DBG("out of memory in allocating pSetNv\n");
+        return ret;
+    }
+
+    pSetNv->dataLen = sizeof(UINT_8);
+    pSetNv->dataOffset = NVRAM_TSSI_STEP_OFSET;
+    readLine = wifiNVRAMCtrl(NVRAM_READ, pSetNv);
+    memcpy(&tssiStep, &pSetNv->data[0], sizeof(UINT_8));
+
+    DBG("calculate Shift tssiStep=[0x%X] readLen=%d\n", tssiStep, readLine);
+
+    switch (tssiStep)
+    {
+        case 0x83:
+            /* precision 0.125 translate q-format from .8 to .3 */
+            ret = 5;
+            break;
+
+        case 0x82:
+            /* precision 0.25 translate q-format from .8 to .2 */
+            ret = 6;
+            break;
+        case 0x81:
+        case 0x80:
+        default:
+            /* precision 0.5 translate q-format from .8 to .1 */
+            ret = 7;
+    }
+
+    FREEIF(pSetNv);
+    return ret;
+
+}
+#endif
+
+WLAN_STATUS wifiNVRAMTssiChOfsAdjust(unsigned int wf, ENUM_BAND_T eBand, unsigned int ch, unsigned int targetPwr, unsigned int MeanPwr)
+{
+
+    unsigned int u4NvramOffset = 0;
+    unsigned char GTofs = 0;
+    char tssiChofsValue = 0;
+    unsigned int shift = 5;
+
+    if (wifiNVRAMTssiChGetNVRAMOfs(wf, eBand, ch, &u4NvramOffset) != META_WIFI_STATUS_SUCCESS)
+    {
+        DBG("Get Ch offset fial!\n");
+        return META_WIFI_STATUS_FAIL;
+    }
+
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+    /*decided to gain table compensation offset*/
+    GTofs = wifiNVRAMTssiChGainTableSelect(targetPwr);
+#else
+    shift = wifiNVRAMCalculateShift();
+#endif
+
+    /*decided to tssi channel offset compensation*/
+    /*TODO*/
+    /*targetpwr = 8 bit format ,2's complement*/
+    /*MeanPwr = s23.8 format*/
+    /*tssiChofsValue format = s4.3,nvram use 2's complement firmware will covert 20 s4.3*/
+
+    tssiChofsValue = (((targetPwr << 7) - MeanPwr) >> shift) & 0xFF;
+    DBG("TargetPwr:0x%08X (%6.1fdBm), MeaPwr:0x%08X(%6.8fdBm),tssiChofsValue=0x%02X\n",
+        targetPwr,
+        ((float)targetPwr) / (2.0),
+        MeanPwr,
+        ((float)MeanPwr / (256.0)),
+        tssiChofsValue);
+
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+    DBG("Tssi ch wf[%d]Band[%d]Ch[%d] GT the same\n"
+        , wf
+        , eBand
+        , ch);
+    wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, tssiChofsValue);
+#else
+    u4NvramOffset += GTofs;
+
+    wifiNVRAMWirteByte(u4NvramOffset, tssiChofsValue);
+
+    DBG("Tssi ch wf[%d]Band[%d]Ch[%d]GT[%d] ofs:0x%08X = 0x%x\n"
+        , wf
+        , eBand
+        , ch
+        , (GTofs + 2)
+        , u4NvramOffset
+        , tssiChofsValue);
+#endif
+
+
+
+    return META_WIFI_STATUS_SUCCESS;
+}
+
+
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+
+WLAN_STATUS wifiNVRAMTssiChOfsInterpolation(TX_PWR_INTERPOLATION_TYPE type,
+        ENUM_BAND_T eBand, unsigned int chNum, unsigned int *pchArray)
+{
+
+    int wf = WF0;
+    unsigned int u4NvramOffset;
+    unsigned int chIdx = 0, rfIdx = 0;
+    int ch0 = 0, ch1 = 0, chInter = 0;
+    unsigned int readLine = 0;
+    int devStep = 0;
+    char nvCompVal = 0;
+    WIFI_NVRAM_TSSI_CH_OFS_T rNvVal[NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2];
+    PNVRAM_ACCESS_STRUCT pSetNv = NULL;
+    int chOfs0 = 0, chOfs1 = 0;
+    unsigned char chGroup[NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2];
+    unsigned char rfGroup = 0;
+    INTER_ACT interAct = INTER_ACT_NOT_SUPPORT;
+    INTERPOLATION_CH_BOUND_A_BAND rfInterList[NVRAM_TSSI_CH_OFFSET_A_BAND_RF_GROUP_NUM] =
+    {
+        {0xFF, 0}, //RF Group 0, not support 5G Interpolation
+        {36, 48}, //RF Group 1
+        {52, 64}, //RF Group 2
+        {0xFF, 0}, //RF Group 3, not support 5G Interpolation
+        {100, 112}, //RF Group 4
+        {116, 128}, //RF Group 5
+        {132, 144}, //RF Group 6
+        {149, 165}, //RF Group 7
+    };
+
+
+
+    /*init */
+    pSetNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + sizeof(WIFI_NVRAM_TSSI_CH_OFS_T));
+    DBG("Band[%d] chNum[%d] Type[%d] Enter\n", eBand, chNum, type);
+    memset(&rNvVal[0], 0, sizeof(WIFI_NVRAM_TSSI_CH_OFS_T) * (NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2));
+    memset(&chGroup[0], 0, sizeof(unsigned char) * (NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2));
+
+    for (wf = WF0; wf < WF_NUM; wf++)
+    {
+
+        //read GT table by channel range
+        for (chIdx = 0; chIdx < chNum; chIdx++)
+        {
+            ch0 = pchArray[chIdx];
+            chGroup[chIdx] = wifiNVRAMGetChGroup(eBand, ch0, CH_GROUP_ITEM_TSSI_CH);
+
+            if (wifiNVRAMTssiChGetNVRAMOfs(wf, eBand, ch0, &u4NvramOffset) != META_WIFI_STATUS_SUCCESS)
+            {
+                DBG("Get Ch offset fial!\n");
+                return META_WIFI_STATUS_FAIL;
+            }
+
+            pSetNv->dataLen = sizeof(WIFI_NVRAM_TSSI_CH_OFS_T);
+            pSetNv->dataOffset = u4NvramOffset;
+            readLine = wifiNVRAMCtrl(NVRAM_READ, pSetNv);
+            memcpy(&rNvVal[chIdx], &pSetNv->data[0], sizeof(WIFI_NVRAM_TSSI_CH_OFS_T));
+            DBG("Read WF[%d]chIdx[%d] = %d,Group=%d,GT=[0x%X,0x%X,0x%X,0x%X,0x%X,0x%X] readLen=%d\n",
+                wf,
+                chIdx,
+                ch0,
+                chGroup[chIdx],
+                rNvVal[chIdx].ucTssiChOfsGT2,
+                rNvVal[chIdx].ucTssiChOfsGT3,
+                rNvVal[chIdx].ucTssiChOfsGT4,
+                rNvVal[chIdx].ucTssiChOfsGT5,
+                rNvVal[chIdx].ucTssiChOfsGT6,
+                rNvVal[chIdx].ucTssiChOfsGT7,
+                readLine);
+        }
+
+
+
+        /*only 2.4G support interpolation -- start*/
+        if ((type == TYPE_INTERPOLATION) && (eBand == BAND_2G4))
+        {
+            //calcaute each step ch=0 ~ pchArray(chNum-1)
+            for (chIdx = 0; chIdx < chNum - 1; chIdx++)
+            {
+
+                ch0 = pchArray[chIdx];
+                chOfs0 =  SIGNED_CONVERT_EXTEND_BITS(rNvVal[chIdx].ucTssiChOfsGT7, 8);
+
+
+                ch1 = pchArray[(chIdx + 1)];
+                chOfs1 = SIGNED_CONVERT_EXTEND_BITS(rNvVal[(chIdx + 1)].ucTssiChOfsGT7, 8);
+
+                for (chInter = ch0 + 1 ; chInter < ch1; chInter++)
+                {
+                    u4NvramOffset = 0;
+
+                    if (wifiNVRAMTssiChGetNVRAMOfs(wf, eBand, chInter, &u4NvramOffset)
+                            != META_WIFI_STATUS_SUCCESS)
+                    {
+                        DBG("Get Ch offset fial!\n");
+                        return META_WIFI_STATUS_FAIL;
+                    }
+
+                    devStep = ((chOfs1 - chOfs0) * (chInter - ch0)) / (ch1 - ch0);
+
+                    DBG("Interpolation ch[%d ~ %d] tssiChVal=[%d ~ %d],ch[%d] + devStep=%d\n",
+                        ch0, ch1, chOfs0, chOfs1, chInter, devStep);
+
+                    nvCompVal = (chOfs0 + devStep) & 0x000000FF;
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+                    wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, nvCompVal);
+#else
+                    u4NvramOffset += OFFSET_OF(WIFI_NVRAM_TSSI_CH_OFS_T, ucTssiChOfsGT7);
+                    wifiNVRAMWirteByte(u4NvramOffset, nvCompVal);
+                    DBG("ch[%d] nvOfs=0x%X,nvCompVal=0x%02X\n",
+                        chInter, u4NvramOffset, nvCompVal);
+#endif
+                }
+            }
+
+            //calcaute each step pchArray(n+1) ~ ch=14
+            for (chInter = ch1 + 1 ; chInter <= 14; chInter++)
+            {
+                u4NvramOffset = 0;
+
+                if (wifiNVRAMTssiChGetNVRAMOfs(wf, eBand, chInter, &u4NvramOffset) != META_WIFI_STATUS_SUCCESS)
+                {
+                    DBG("Get Ch offset fial!\n");
+                    return META_WIFI_STATUS_FAIL;
+                }
+
+                devStep = ((chOfs1 - chOfs0) * (chInter - ch1)) / (ch1 - ch0);
+
+                DBG("Extrapolation ch[%d ~ %d] tssiChVal=[%d ~ %d],ch[%d] + devStep=%d\n",
+                    ch1 + 1, 14, chOfs0, chOfs1, chInter, devStep);
+                nvCompVal = chOfs0 + (chInter - ch0) * devStep;
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+                wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, nvCompVal);
+#else
+                u4NvramOffset += OFFSET_OF(WIFI_NVRAM_TSSI_CH_OFS_T, ucTssiChOfsGT7);
+                wifiNVRAMWirteByte(u4NvramOffset, nvCompVal);
+                DBG("ch[%d] nvOfs=0x%X,nvCompVal=0x%02X\n",
+                    chInter, u4NvramOffset, nvCompVal);
+#endif
+
+            }
+        }
+        else if ((type == TYPE_GROUP_THE_SAME) && (eBand == BAND_5G))
+        {
+            /* "group the same" means using meanuse tx power value to apply tssi ch ofs group
+                         *   in RF defined group
+                         */
+            //calcaute each step ch=0 ~ pchArray(chNum)
+            for (chIdx = 0; chIdx < chNum ; chIdx++)
+            {
+                nvCompVal = rNvVal[chIdx].ucTssiChOfsGT7;
+                wifiNVRAMTssiChOfsRfGroupTheSame(wf, eBand, pchArray[chIdx], chGroup[chIdx], nvCompVal);
+            }
+        }
+        else if ((type == TYPE_INTERPOLATION) && (eBand == BAND_5G))
+        {
+            //calcaute each step ch=0 ~ pchArray(chNum-1)
+            for (chIdx = 0; chIdx < chNum; chIdx++)
+            {
+                interAct = INTER_ACT_NOT_SUPPORT;
+
+                //Check 5G interpolation support RF group channel bound
+                for (rfIdx = 0; rfIdx < NVRAM_TSSI_CH_OFFSET_A_BAND_RF_GROUP_NUM; rfIdx++)
+                {
+                    DBG("ch=%d Check RFGroup[%d] bound[%d ~ %d]\n",
+                        pchArray[chIdx],
+                        rfIdx,
+                        rfInterList[rfIdx].lowBoundCh,
+                        rfInterList[rfIdx].upperBoundCh);
+
+                    //if chIdx = low bound  and chIdx+1 = upper bound
+                    if (pchArray[chIdx] == rfInterList[rfIdx].lowBoundCh)
+                    {
+                        if ((chIdx < (chNum - 1)) &&
+                                pchArray[chIdx + 1] == rfInterList[rfIdx].upperBoundCh)
+                        {
+                            interAct = INTER_ACT_INTERPOLATION;
+
+                            rfGroup = GET_A_BAND_RF_GROUP(chGroup[chIdx]);
+
+                            ch0 = pchArray[chIdx];
+                            ch1 = pchArray[(chIdx + 1)];
+
+                            chOfs0 =  SIGNED_CONVERT_EXTEND_BITS(rNvVal[chIdx].ucTssiChOfsGT7, 8);
+                            chOfs1 = SIGNED_CONVERT_EXTEND_BITS(rNvVal[(chIdx + 1)].ucTssiChOfsGT7, 8);
+
+                            DBG("5G do Interpolation WF[%d] RF[%d] ch[%d ~ %d] Rang[%d ~ %d]\n",
+                                wf,
+                                rfGroup,
+                                ch0,
+                                ch1,
+                                chOfs0,
+                                chOfs1);
+
+                            //Query the next RF group
+                            chIdx++;
+                            break;
+                        }
+                        else
+                        {
+                            interAct = INTER_ACT_GROUP_THE_SAME;
+                            break;
+                        }
+                    }
+                    else if ((pchArray[chIdx] > rfInterList[rfIdx].lowBoundCh) &&
+                             (pchArray[chIdx] < rfInterList[rfIdx].upperBoundCh))
+                    {
+                        interAct = INTER_ACT_GROUP_THE_SAME;
+                        break;
+                    }
+                    else
+                        interAct = INTER_ACT_GROUP_THE_SAME;
+
+                }
+
+                if (interAct == INTER_ACT_GROUP_THE_SAME)
+                {
+                    nvCompVal = rNvVal[chIdx].ucTssiChOfsGT7;
+                    wifiNVRAMTssiChOfsRfGroupTheSame(wf, eBand, pchArray[chIdx], chGroup[chIdx], nvCompVal);
+                }
+                else if (interAct == INTER_ACT_INTERPOLATION)
+                {
+
+                    /*update (n) ~ (n+3) Tssi ch group in one RF Group*/
+                    for (chInter = (rfGroup * PER_CH_GROUP_IN_RF_GROUP) ; chInter < ((rfGroup * PER_CH_GROUP_IN_RF_GROUP) + PER_CH_GROUP_IN_RF_GROUP); chInter++)
+                    {
+                        u4NvramOffset = (wf == WF0) ? (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0) : (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1);
+                        u4NvramOffset += (chInter * sizeof(WIFI_NVRAM_TSSI_CH_OFS_T));
+
+                        devStep = ((chOfs1 - chOfs0) * (chInter - (rfGroup * PER_CH_GROUP_IN_RF_GROUP))) / (PER_CH_GROUP_IN_RF_GROUP - 1);
+
+                        nvCompVal = (chOfs0 + devStep) & 0x000000FF;
+
+                        DBG("Interpolation:TssiChGroup[%d][%c] + devStep=%d,NvOfs=0x%08X,NvVal=0x%02X\n",
+                            chInter / 2,
+                            ((chInter % 2) == 0) ? ('L') : ('H'),
+                            devStep,
+                            u4NvramOffset,
+                            nvCompVal);
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+                        wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, nvCompVal);
+#else
+                        u4NvramOffset += OFFSET_OF(WIFI_NVRAM_TSSI_CH_OFS_T, ucTssiChOfsGT7);
+
+                        wifiNVRAMWirteByte(u4NvramOffset, nvCompVal);
+#endif
+
+                    }
+
+                }
+                else
+                    DBG("Not Support ch[%d]!\n", pchArray[chIdx + 1]);
+
+            }
+        }
+    }
+
+    FREEIF(pSetNv);
+
+    return META_WIFI_STATUS_SUCCESS;
+}
+
+
+WLAN_STATUS wifiNVRAMTssiNDLOfsClear(void)
+{
+#if (CFG_DNL_CAL == 1)
+    NVRAM_ACCESS_STRUCT raNvram[] =
+    {
+        /*2.4G WF0 Tssi DNL*/
+        {NVRAM_G_BAND_TSSI_DNL_OFS_SIZE, NVRAM_G_BAND_TSSI_DNL_OFS_OFSETOF_WF0, {0}},
+        /*2.4G WF1 Tssi DNL*/
+        {NVRAM_G_BAND_TSSI_DNL_OFS_SIZE, NVRAM_G_BAND_TSSI_DNL_OFS_OFSETOF_WF1, {0}},
+        /*5G WF0 Tssi DNL*/
+        {NVRAM_A_BAND_TSSI_DNL_OFS_SIZE, NVRAM_A_BAND_TSSI_DNL_OFS_OFSETOF_WF0, {0}},
+        /*5G WF1 Tssi DNL*/
+        {NVRAM_A_BAND_TSSI_DNL_OFS_SIZE, NVRAM_A_BAND_TSSI_DNL_OFS_OFSETOF_WF1, {0}},
+
+    };
+    PNVRAM_ACCESS_STRUCT pQueryNv = NULL;
+    char *pBuf = NULL;
+    int i = 0;
+
+    pQueryNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE);
+
+    if (pQueryNv == NULL)
+    {
+        ERR("[META_WIFI] No memory nvram\n");
+        goto error;
+    }
+
+    for (i = 0 ; i < (sizeof(raNvram) / sizeof(NVRAM_ACCESS_STRUCT)) ; i++)
+    {
+        pQueryNv->dataLen = raNvram[i].dataLen;
+        pQueryNv->dataOffset = raNvram[i].dataOffset;
+        pBuf = (char *)&pQueryNv->data[0];
+
+        /*clear NVRAM content*/
+        memset(pBuf, 0, MAX_NVRAM_ACCESS_SIZE);
+        wifiNVRAMCtrl(NVRAM_WRITE, pQueryNv);
+
+    }
+
+    DBG("Finish!\n");
+error:
+    FREEIF(pQueryNv);
+#endif
+    return META_WIFI_STATUS_SUCCESS;
+
+}
+
+WLAN_STATUS wifiNVRAMTssiDnlOfsAdjust(unsigned int dbdcbandIdx,
+                                      ENUM_BAND_T eBand, unsigned char inputCh)
+{
+    WLAN_STATUS ret = META_WIFI_STATUS_FAIL;
+
+#if (CFG_DNL_CAL == 1)
+    unsigned char chGroup = 0;
+    unsigned int data_cnt = 0;
+    char crOfsetIdx = 0;
+    char chIdx = 0;
+    int i = 0;
+    RECAL_INFO_T rReCalInfo;
+    WIFI_NVRAM_TX_DNL_T rDnl;
+
+    unsigned int nvramOfs = 0;
+    PNVRAM_ACCESS_STRUCT pQueryNv = NULL;
+
+    pQueryNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE);
+    memset(&rReCalInfo, 0, sizeof(RECAL_INFO_T));
+
+    //get ch group
+    chGroup = wifiNVRAMGetChGroup(eBand, inputCh, CH_GROUP_ITEM_COMMON);
+
+    DBG("DbdcIdx=%d,Band=%d,ch=%d,Group=%d\n", dbdcbandIdx, eBand, inputCh, chGroup);
+
+    for (i = 0 ; i < QUERY_RECAL_RETRY_CNT ; i++)
+    {
+
+        //set NDL CAL by HQA CMD
+        if (wifiHqaDoCalibrationTestItem(HQA_CAL_ITEM_DNL, dbdcbandIdx) != META_WIFI_STATUS_SUCCESS)
+            DBG("Cal test item fail!\n");
+
+
+        //query NDL CAL RESULT
+        if (wifiHqaGetDumpReCal(HQA_CAL_ITEM_DNL, dbdcbandIdx, &rReCalInfo) != META_WIFI_STATUS_SUCCESS)
+            DBG("Cal query item fail!\n");
+
+
+        data_cnt = rReCalInfo.u4Count;
+
+        if (data_cnt != (DNL_WF_PATH_CR_NUM * WF_NUM))
+        {
+            DBG("Result Num dismatch!,Expect:%d Total:%d do-try(%d)!\n",
+                (DNL_WF_PATH_CR_NUM * WF_NUM),
+                data_cnt, i);
+            continue;
+        }
+        else
+            break;
+    }
+
+    if (data_cnt != (DNL_WF_PATH_CR_NUM * WF_NUM))
+    {
+        DBG("Over retry(%d)! DNL Cal Result Fail\n", QUERY_RECAL_RETRY_CNT);
+        ret = META_WIFI_STATUS_FAIL;
+        goto error;
+    }
+
+
+
+    for (i = 0 ; i < data_cnt ; i++)
+    {
+        DBG("(%d)ID=0x%X,Addr=0x%X,Val=0x%X\n", i, rReCalInfo.u4CalId[i], rReCalInfo.u4CalAddr[i], rReCalInfo.u4CalValue[i]);
+    }
+
+    for (i = 0; i < WF_NUM; i++)
+    {
+
+        crOfsetIdx = DNL_WF_PATH_CR_NUM * i;
+        memset(&rDnl, 0, sizeof(WIFI_NVRAM_TX_DNL_T));
+
+        rDnl.ucTxDnlCckGT0 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+        rDnl.ucTxDnlLowGT0 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+        rDnl.ucTxDnlMidGT0 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+        rDnl.ucTxDnlHighGT0 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+        rDnl.ucTxDnlUltraGT0 = (rReCalInfo.u4CalValue[crOfsetIdx + 1] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+        rDnl.ucTxDnlCckGT1 = (rReCalInfo.u4CalValue[crOfsetIdx + 2] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+        rDnl.ucTxDnlLowGT1 = (rReCalInfo.u4CalValue[crOfsetIdx + 2] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+        rDnl.ucTxDnlMidGT1 = (rReCalInfo.u4CalValue[crOfsetIdx + 2] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+        rDnl.ucTxDnlHighGT1 = (rReCalInfo.u4CalValue[crOfsetIdx + 2] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+        rDnl.ucTxDnlUltraGT1 = (rReCalInfo.u4CalValue[crOfsetIdx + 3] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+        rDnl.ucTxDnlCckGT2 = (rReCalInfo.u4CalValue[crOfsetIdx + 4] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+        rDnl.ucTxDnlLowGT2 = (rReCalInfo.u4CalValue[crOfsetIdx + 4] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+        rDnl.ucTxDnlMidGT2 = (rReCalInfo.u4CalValue[crOfsetIdx + 4] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+        rDnl.ucTxDnlHighGT2 = (rReCalInfo.u4CalValue[crOfsetIdx + 4] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+        rDnl.ucTxDnlUltraGT2 = (rReCalInfo.u4CalValue[crOfsetIdx + 5] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+        rDnl.ucTxDnlCckGT3 = (rReCalInfo.u4CalValue[crOfsetIdx + 6] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+        rDnl.ucTxDnlLowGT3 = (rReCalInfo.u4CalValue[crOfsetIdx + 6] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+        rDnl.ucTxDnlMidGT3 = (rReCalInfo.u4CalValue[crOfsetIdx + 6] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+        rDnl.ucTxDnlHighGT3 = (rReCalInfo.u4CalValue[crOfsetIdx + 6] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+        rDnl.ucTxDnlUltraGT3 = (rReCalInfo.u4CalValue[crOfsetIdx + 7] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+        rDnl.ucTxDnlCckGT4 = (rReCalInfo.u4CalValue[crOfsetIdx + 8] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+        rDnl.ucTxDnlLowGT4 = (rReCalInfo.u4CalValue[crOfsetIdx + 8] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+        rDnl.ucTxDnlMidGT4 = (rReCalInfo.u4CalValue[crOfsetIdx + 8] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+        rDnl.ucTxDnlHighGT4 = (rReCalInfo.u4CalValue[crOfsetIdx + 8] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+        rDnl.ucTxDnlUltraGT4 = (rReCalInfo.u4CalValue[crOfsetIdx + 9] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+        rDnl.ucTxDnlCckGT5 = (rReCalInfo.u4CalValue[crOfsetIdx + 10] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+        rDnl.ucTxDnlLowGT5 = (rReCalInfo.u4CalValue[crOfsetIdx + 10] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+        rDnl.ucTxDnlMidGT5 = (rReCalInfo.u4CalValue[crOfsetIdx + 10] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+        rDnl.ucTxDnlHighGT5 = (rReCalInfo.u4CalValue[crOfsetIdx + 10] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+        rDnl.ucTxDnlUltraGT5 = (rReCalInfo.u4CalValue[crOfsetIdx + 11] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+        rDnl.ucTxDnlCckGT6 = (rReCalInfo.u4CalValue[crOfsetIdx + 12] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+        rDnl.ucTxDnlLowGT6 = (rReCalInfo.u4CalValue[crOfsetIdx + 12] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+        rDnl.ucTxDnlMidGT6 = (rReCalInfo.u4CalValue[crOfsetIdx + 12] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+        rDnl.ucTxDnlHighGT6 = (rReCalInfo.u4CalValue[crOfsetIdx + 12] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+        rDnl.ucTxDnlUltraGT6 = (rReCalInfo.u4CalValue[crOfsetIdx + 13] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+        rDnl.ucTxDnlCckGT7 = (rReCalInfo.u4CalValue[crOfsetIdx + 14] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+        rDnl.ucTxDnlLowGT7 = (rReCalInfo.u4CalValue[crOfsetIdx + 14] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+        rDnl.ucTxDnlMidGT7 = (rReCalInfo.u4CalValue[crOfsetIdx + 14] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+        rDnl.ucTxDnlHighGT7 = (rReCalInfo.u4CalValue[crOfsetIdx + 14] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+        rDnl.ucTxDnlUltraGT7 = (rReCalInfo.u4CalValue[crOfsetIdx + 15] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+
+        if (eBand == BAND_2G4)
+        {
+            //2.4G channel all the same DNL value;
+            for (chIdx = 0 ; chIdx < 14 ; chIdx++)
+            {
+                nvramOfs = (i == WF0) ? (NVRAM_G_BAND_TSSI_DNL_OFS_OFSETOF_WF0) : (NVRAM_G_BAND_TSSI_DNL_OFS_OFSETOF_WF1);
+                //get nvram by ch group offset
+                nvramOfs += sizeof(WIFI_NVRAM_TX_DNL_T) * chIdx;
+                memset(pQueryNv, 0, sizeof(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE));
+
+                pQueryNv->dataLen = sizeof(WIFI_NVRAM_TX_DNL_T);
+                pQueryNv->dataOffset = nvramOfs;
+                memcpy(&pQueryNv->data[0], &rDnl, sizeof(WIFI_NVRAM_TX_DNL_T));
+                wifiNVRAMCtrl(NVRAM_WRITE, pQueryNv);
+
+                DBG("WF%d update B[%d] Ch=%d nvramOfs=0x%08X done!\n", i, eBand, chIdx, nvramOfs);
+            }
+        }
+        else
+        {
+            //get 5G DNL offset
+            nvramOfs = (i == WF0) ? (NVRAM_A_BAND_TSSI_DNL_OFS_OFSETOF_WF0) : (NVRAM_A_BAND_TSSI_DNL_OFS_OFSETOF_WF1);
+
+            //get nvram by ch group offset
+            nvramOfs += sizeof(WIFI_NVRAM_TX_DNL_T) * chGroup;
+            memset(pQueryNv, 0, sizeof(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE));
+
+            pQueryNv->dataLen = sizeof(WIFI_NVRAM_TX_DNL_T);
+            pQueryNv->dataOffset = nvramOfs;
+            memcpy(&pQueryNv->data[0], &rDnl, sizeof(WIFI_NVRAM_TX_DNL_T));
+            wifiNVRAMCtrl(NVRAM_WRITE, pQueryNv);
+
+            DBG("WF%d update B[%d] Ch=%d Group =%d nvramOfs=0x%08X done!\n", i, eBand, inputCh, chGroup, nvramOfs);
+
+        }
+
+
+    }
+
+    ret = META_WIFI_STATUS_SUCCESS;
+
+    DBG("DNL Adjust success!\n");
+error:
+    FREEIF(pQueryNv);
+
+#else
+    DBG("[WARNING] Adjust not-support!\n");
+#endif
+
+    return ret;
+}
+
+
+/*LNA(Rssi) Gain Calibration clear*/
+WLAN_STATUS wifiNVRAMLnaGainCalClear(void)
+{
+    NVRAM_ACCESS_STRUCT raNvram[] =
+    {
+        /*2.4G WF0 LNA(Rssi) Gain Calibration*/
+        {NVRAM_G_BAND_LNA_GAIN_CAL_OFS_SIZE, NVRAM_G_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF0, {0}},
+        /*2.4G WF1 LNA(Rssi) Gain Calibration*/
+        {NVRAM_G_BAND_LNA_GAIN_CAL_OFS_SIZE, NVRAM_G_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF1, {0}},
+        /*5G WF0 LNA(Rssi) Gain Calibration*/
+        {NVRAM_A_BAND_LNA_GAIN_CAL_OFS_SIZE, NVRAM_A_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF0, {0}},
+        /*5G WF1 LNA(Rssi) Gain Calibration*/
+        {NVRAM_A_BAND_LNA_GAIN_CAL_OFS_SIZE, NVRAM_A_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF1, {0}},
+
+    };
+    PNVRAM_ACCESS_STRUCT pQueryNv = NULL;
+    char *pBuf = NULL;
+    int i = 0;
+
+    pQueryNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE);
+
+    if (pQueryNv == NULL)
+    {
+        ERR("[META_WIFI] No memory nvram\n");
+        goto error;
+    }
+
+    for (i = 0 ; i < (sizeof(raNvram) / sizeof(NVRAM_ACCESS_STRUCT)) ; i++)
+    {
+        pQueryNv->dataLen = raNvram[i].dataLen;
+        pQueryNv->dataOffset = raNvram[i].dataOffset;
+        pBuf = (char *)&pQueryNv->data[0];
+
+        /*clear NVRAM content*/
+        memset(pBuf, 0, MAX_NVRAM_ACCESS_SIZE);
+        wifiNVRAMCtrl(NVRAM_WRITE, pQueryNv);
+
+    }
+
+    DBG("Finish!\n");
+error:
+    FREEIF(pQueryNv);
+
+    return META_WIFI_STATUS_SUCCESS;
+
+}
+/*LNA(Rssi) Gain Calibration Adjust*/
+WLAN_STATUS wifiNVRAMLnaGainCalAdjust(unsigned int dbdcbandIdx,
+                                      ENUM_BAND_T eBand, unsigned char inputCh)
+{
+
+    unsigned char chGroup = 0;
+    unsigned int data_cnt = 0;
+    char crOfsetIdx = 0;
+    int i = 0;
+    RECAL_INFO_T rReCalInfo;
+    WIFI_NVRAM_LNA_GAIN_CAL_T rLnaGain;
+    unsigned int nvramOfs = 0;
+    PNVRAM_ACCESS_STRUCT pQueryNv = NULL;
+    WLAN_STATUS ret = META_WIFI_STATUS_FAIL;
+
+    memset(&rReCalInfo, 0, sizeof(RECAL_INFO_T));
+    memset(&rLnaGain, 0, sizeof(WIFI_NVRAM_LNA_GAIN_CAL_T));
+
+    pQueryNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE);
+
+    //get ch group
+    chGroup = wifiNVRAMGetChGroup(eBand, inputCh, CH_GROUP_ITEM_COMMON);
+
+    DBG("DbdcIdx=%d,Band=%d,ch=%d,Group=%d\n", dbdcbandIdx, eBand, inputCh, chGroup);
+
+    for (i = 0 ; i < QUERY_RECAL_RETRY_CNT ; i++)
+    {
+
+        //set Lna/Rssi Gain Cal by HQA CMD
+        if (wifiHqaDoCalibrationTestItem(HQA_CAL_ITEM_LNA_GIAN_CAL, dbdcbandIdx) != META_WIFI_STATUS_SUCCESS)
+            DBG("Cal test item fail!\n");
+
+
+        //query  Lna/Rssi Gain Cal RESULT
+        if (wifiHqaGetDumpReCal(HQA_CAL_ITEM_LNA_GIAN_CAL, dbdcbandIdx, &rReCalInfo) != META_WIFI_STATUS_SUCCESS)
+            DBG("Cal test item fail!\n");
+
+
+        data_cnt = rReCalInfo.u4Count;
+
+        if (data_cnt != (LNA_GIAN_CAL_WF_PATH_CR_NUM * WF_NUM))
+        {
+            DBG("Result Num dismatch!,Expect:%d Total:%d do-try(%d)!\n",
+                (LNA_GIAN_CAL_WF_PATH_CR_NUM * WF_NUM),
+                data_cnt, i);
+            continue;
+        }
+        else
+            break;
+    }
+
+    if (data_cnt != (LNA_GIAN_CAL_WF_PATH_CR_NUM * WF_NUM))
+    {
+        DBG("Over retry(%d)! DNL Cal Result Fail\n", QUERY_RECAL_RETRY_CNT);
+        ret = META_WIFI_STATUS_FAIL;
+        goto error;
+    }
+
+    for (i = 0 ; i < data_cnt ; i++)
+    {
+        DBG("(%d)ID=0x%X,Addr=0x%X,Val=0x%X\n", i, rReCalInfo.u4CalId[i], rReCalInfo.u4CalAddr[i], rReCalInfo.u4CalValue[i]);
+    }
+
+    for (i = 0; i < WF_NUM; i++)
+    {
+
+        crOfsetIdx = LNA_GIAN_CAL_WF_PATH_CR_NUM * i;
+
+        //get Cal value
+        rLnaGain.ucRxCal1 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & LNA_GAIN_TAB0_MASK) >> LNA_GAIN_TAB0_SHFT;
+        rLnaGain.ucRxCal2 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & LNA_GAIN_TAB1_MASK) >> LNA_GAIN_TAB1_SHFT;
+        rLnaGain.ucRxCal3 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & LNA_GAIN_TAB2_MASK) >> LNA_GAIN_TAB2_SHFT;
+        rLnaGain.ucRxCal4 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & LNA_GAIN_TAB3_MASK) >> LNA_GAIN_TAB3_SHFT;
+        rLnaGain.ucRxCal5 = (rReCalInfo.u4CalValue[crOfsetIdx + 1] & LNA_GAIN_TAB4_MASK) >> LNA_GAIN_TAB4_SHFT;
+        rLnaGain.ucRxCal6 = 0; /*reserved*/
+
+        //calculate nvram offset
+        if (eBand == BAND_2G4)
+        {
+            nvramOfs = (i == WF0) ? (NVRAM_G_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF0) : (NVRAM_G_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF1);
+        }
+        else
+        {
+            nvramOfs = (i == WF0) ? (NVRAM_A_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF0) : (NVRAM_A_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF1);
+            //get nvram by ch group offset
+            nvramOfs += sizeof(WIFI_NVRAM_LNA_GAIN_CAL_T) * chGroup;
+        }
+
+
+        memset(pQueryNv, 0, sizeof(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE));
+
+        pQueryNv->dataLen = sizeof(WIFI_NVRAM_LNA_GAIN_CAL_T);
+        pQueryNv->dataOffset = nvramOfs;
+        memcpy(&pQueryNv->data[0], &rLnaGain, sizeof(WIFI_NVRAM_LNA_GAIN_CAL_T));
+        wifiNVRAMCtrl(NVRAM_WRITE, pQueryNv);
+
+        DBG("WF%d update B[%d] Ch=%d GP=%d nvramOfs=0x%08X done!\n", i, eBand, inputCh, chGroup, nvramOfs);
+    }
+
+    ret = META_WIFI_STATUS_SUCCESS;
+
+    DBG("Success!\n");
+error:
+    FREEIF(pQueryNv);
+
+    return ret;
+}
+
+#else
+
+WLAN_STATUS wifiNVRAMTssiChOfsInterpolation(TX_PWR_INTERPOLATION_TYPE type,
+        ENUM_BAND_T eBand, unsigned int chNum, unsigned int *pchArray)
+{
+
+    int wf = WF0;
+    unsigned int u4NvramOffset;
+    unsigned int chIdx = 0, rfIdx = 0;
+    int ch0 = 0, ch1 = 0, chInter = 0;
+    unsigned int readLine = 0;
+    int devStep = 0;
+    char nvCompVal = 0;
+    UINT_8 rNvVal[NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2];
+    PNVRAM_ACCESS_STRUCT pSetNv = NULL;
+    int chOfs0 = 0, chOfs1 = 0;
+    unsigned char chGroup[NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2];
+    unsigned char rfGroup = 0;
+    INTER_ACT interAct = INTER_ACT_NOT_SUPPORT;
+    INTERPOLATION_CH_BOUND_A_BAND rfInterList[NVRAM_TSSI_CH_OFFSET_A_BAND_RF_GROUP_NUM] =
+    {
+        {0xFF, 0}, //RF Group 0, not support 5G Interpolation
+        {36, 48}, //RF Group 1
+        {52, 64}, //RF Group 2
+        {0xFF, 0}, //RF Group 3, not support 5G Interpolation
+        {100, 112}, //RF Group 4
+        {116, 128}, //RF Group 5
+        {132, 144}, //RF Group 6
+        {149, 165}, //RF Group 7
+    };
+
+    /*init */
+    pSetNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + sizeof(UINT_8));
+    DBG("Band[%d] chNum[%d] Type[%d] Enter\n", eBand, chNum, type);
+    memset(&rNvVal[0], 0, sizeof(UINT_8) * (NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2));
+    memset(&chGroup[0], 0, sizeof(unsigned char) * (NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2));
+
+    for (wf = WF0; wf < WF_NUM; wf++)
+    {
+
+        //read GT table by channel range
+        for (chIdx = 0; chIdx < chNum; chIdx++)
+        {
+            ch0 = pchArray[chIdx];
+            chGroup[chIdx] = wifiNVRAMGetChGroup(eBand, ch0, CH_GROUP_ITEM_TSSI_CH);
+
+            if (wifiNVRAMTssiChGetNVRAMOfs(wf, eBand, ch0, &u4NvramOffset) != META_WIFI_STATUS_SUCCESS)
+            {
+                DBG("Get Ch offset fial!\n");
+                return META_WIFI_STATUS_FAIL;
+            }
+
+            pSetNv->dataLen = sizeof(UINT_8);
+            pSetNv->dataOffset = u4NvramOffset;
+            readLine = wifiNVRAMCtrl(NVRAM_READ, pSetNv);
+            memcpy(&rNvVal[chIdx], &pSetNv->data[0], sizeof(UINT_8));
+            DBG("Read WF[%d]chIdx[%d] = %d,Group=%d, Ofs=[0x%X] readLen=%d\n",
+                wf,
+                chIdx,
+                ch0,
+                chGroup[chIdx],
+                rNvVal[chIdx],
+                readLine);
+        }
+
+
+
+        /*only 2.4G support interpolation -- start*/
+        if ((type == TYPE_INTERPOLATION) && (eBand == BAND_2G4))
+        {
+            //calcaute each step ch=0 ~ pchArray(chNum-1)
+            for (chIdx = 0; chIdx < chNum - 1; chIdx++)
+            {
+
+                ch0 = pchArray[chIdx];
+                chOfs0 =  SIGNED_CONVERT_EXTEND_BITS(rNvVal[chIdx], 8);
+
+
+                ch1 = pchArray[(chIdx + 1)];
+                chOfs1 = SIGNED_CONVERT_EXTEND_BITS(rNvVal[(chIdx + 1)], 8);
+
+                for (chInter = ch0 + 1 ; chInter < ch1; chInter++)
+                {
+                    u4NvramOffset = 0;
+
+                    if (wifiNVRAMTssiChGetNVRAMOfs(wf, eBand, chInter, &u4NvramOffset)
+                            != META_WIFI_STATUS_SUCCESS)
+                    {
+                        DBG("Get Ch offset fial!\n");
+                        return META_WIFI_STATUS_FAIL;
+                    }
+
+                    devStep = ((chOfs1 - chOfs0) * (chInter - ch0)) / (ch1 - ch0);
+
+                    DBG("Interpolation ch[%d ~ %d] tssiChVal=[%d ~ %d],ch[%d] + devStep=%d\n",
+                        ch0, ch1, chOfs0, chOfs1, chInter, devStep);
+
+                    nvCompVal = (chOfs0 + devStep) & 0x000000FF;
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+                    wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, nvCompVal);
+#else
+                    wifiNVRAMWirteByte(u4NvramOffset, nvCompVal);
+                    DBG("ch[%d] nvOfs=0x%X,nvCompVal=0x%02X\n",
+                        chInter, u4NvramOffset, nvCompVal);
+#endif
+                }
+            }
+
+            //calcaute each step pchArray(n+1) ~ ch=14
+            for (chInter = ch1 + 1 ; chInter <= 14; chInter++)
+            {
+                u4NvramOffset = 0;
+
+                if (wifiNVRAMTssiChGetNVRAMOfs(wf, eBand, chInter, &u4NvramOffset) != META_WIFI_STATUS_SUCCESS)
+                {
+                    DBG("Get Ch offset fial!\n");
+                    return META_WIFI_STATUS_FAIL;
+                }
+
+                devStep = ((chOfs1 - chOfs0) * (chInter - ch1)) / (ch1 - ch0);
+
+                DBG("Extrapolation ch[%d ~ %d] tssiChVal=[%d ~ %d],ch[%d] + devStep=%d\n",
+                    ch1 + 1, 14, chOfs0, chOfs1, chInter, devStep);
+                nvCompVal = chOfs0 + (chInter - ch0) * devStep;
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+                wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, nvCompVal);
+#else
+                wifiNVRAMWirteByte(u4NvramOffset, nvCompVal);
+                DBG("ch[%d] nvOfs=0x%X,nvCompVal=0x%02X\n",
+                    chInter, u4NvramOffset, nvCompVal);
+#endif
+
+            }
+        }
+        else if ((type == TYPE_GROUP_THE_SAME) && (eBand == BAND_5G))
+        {
+            /* "group the same" means using meanuse tx power value to apply tssi ch ofs group
+                         *   in RF defined group
+                         */
+            //calcaute each step ch=0 ~ pchArray(chNum)
+            for (chIdx = 0; chIdx < chNum ; chIdx++)
+            {
+                nvCompVal = rNvVal[chIdx];
+                wifiNVRAMTssiChOfsRfGroupTheSame(wf, eBand, pchArray[chIdx], chGroup[chIdx], nvCompVal);
+            }
+        }
+        else if ((type == TYPE_INTERPOLATION) && (eBand == BAND_5G))
+        {
+            //calcaute each step ch=0 ~ pchArray(chNum-1)
+            for (chIdx = 0; chIdx < chNum; chIdx++)
+            {
+                interAct = INTER_ACT_NOT_SUPPORT;
+
+                //Check 5G interpolation support RF group channel bound
+                for (rfIdx = 0; rfIdx < NVRAM_TSSI_CH_OFFSET_A_BAND_RF_GROUP_NUM; rfIdx++)
+                {
+                    DBG("ch=%d Check RFGroup[%d] bound[%d ~ %d]\n",
+                        pchArray[chIdx],
+                        rfIdx,
+                        rfInterList[rfIdx].lowBoundCh,
+                        rfInterList[rfIdx].upperBoundCh);
+
+                    //if chIdx = low bound  and chIdx+1 = upper bound
+                    if (pchArray[chIdx] == rfInterList[rfIdx].lowBoundCh)
+                    {
+                        if ((chIdx < (chNum - 1)) &&
+                                pchArray[chIdx + 1] == rfInterList[rfIdx].upperBoundCh)
+                        {
+                            interAct = INTER_ACT_INTERPOLATION;
+
+                            rfGroup = GET_A_BAND_RF_GROUP(chGroup[chIdx]);
+
+                            ch0 = pchArray[chIdx];
+                            ch1 = pchArray[(chIdx + 1)];
+
+                            chOfs0 =  SIGNED_CONVERT_EXTEND_BITS(rNvVal[chIdx], 8);
+                            chOfs1 = SIGNED_CONVERT_EXTEND_BITS(rNvVal[(chIdx + 1)], 8);
+
+                            DBG("5G do Interpolation WF[%d] RF[%d] ch[%d ~ %d] Rang[%d ~ %d]\n",
+                                wf,
+                                rfGroup,
+                                ch0,
+                                ch1,
+                                chOfs0,
+                                chOfs1);
+
+                            //Query the next RF group
+                            chIdx++;
+                            break;
+                        }
+                        else
+                        {
+                            interAct = INTER_ACT_GROUP_THE_SAME;
+                            break;
+                        }
+                    }
+                    else if ((pchArray[chIdx] > rfInterList[rfIdx].lowBoundCh) &&
+                             (pchArray[chIdx] < rfInterList[rfIdx].upperBoundCh))
+                    {
+                        interAct = INTER_ACT_GROUP_THE_SAME;
+                        break;
+                    }
+                    else
+                        interAct = INTER_ACT_GROUP_THE_SAME;
+
+                }
+
+                if (interAct == INTER_ACT_GROUP_THE_SAME)
+                {
+                    nvCompVal = rNvVal[chIdx];
+                    wifiNVRAMTssiChOfsRfGroupTheSame(wf, eBand, pchArray[chIdx], chGroup[chIdx], nvCompVal);
+                }
+                else if (interAct == INTER_ACT_INTERPOLATION)
+                {
+
+                    /*update (n) ~ (n+3) Tssi ch group in one RF Group*/
+                    for (chInter = (rfGroup * PER_CH_GROUP_IN_RF_GROUP) ; chInter < ((rfGroup * PER_CH_GROUP_IN_RF_GROUP) + PER_CH_GROUP_IN_RF_GROUP); chInter++)
+                    {
+                        u4NvramOffset = (wf == WF0) ? (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0) : (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1);
+                        u4NvramOffset += (chInter * sizeof(UINT_8));
+
+                        devStep = ((chOfs1 - chOfs0) * (chInter - (rfGroup * PER_CH_GROUP_IN_RF_GROUP))) / (PER_CH_GROUP_IN_RF_GROUP - 1);
+
+                        nvCompVal = (chOfs0 + devStep) & 0x000000FF;
+
+                        DBG("Interpolation:TssiChGroup[%d][%c] + devStep=%d,NvOfs=0x%08X,NvVal=0x%02X\n",
+                            chInter / 2,
+                            ((chInter % 2) == 0) ? ('L') : ('H'),
+                            devStep,
+                            u4NvramOffset,
+                            nvCompVal);
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+                        wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, nvCompVal);
+#else
+                        wifiNVRAMWirteByte(u4NvramOffset, nvCompVal);
+#endif
+
+                    }
+
+                }
+                else
+                    DBG("Not Support ch[%d]!\n", pchArray[chIdx + 1]);
+
+            }
+        }
+    }
+
+    FREEIF(pSetNv);
+
+    return META_WIFI_STATUS_SUCCESS;
+}
+
+WLAN_STATUS wifiNVRAMLnaGainCalClear(void)
+{
+    return META_WIFI_STATUS_FAIL;
+}
+WLAN_STATUS wifiNVRAMLnaGainCalAdjust(unsigned int dbdcbandIdx,
+                                      ENUM_BAND_T eBand, unsigned char inputCh)
+{
+    return META_WIFI_STATUS_FAIL;
+}
+WLAN_STATUS wifiNVRAMTssiNDLOfsClear(void)
+{
+    return META_WIFI_STATUS_FAIL;
+}
+WLAN_STATUS wifiNVRAMTssiDnlOfsAdjust(unsigned int dbdcbandIdx,
+                                      ENUM_BAND_T eBand, unsigned char inputCh)
+{
+    return META_WIFI_STATUS_FAIL;
+}
+#endif /*#if (WIFI_GEN_VER == CONNAC_SOC3_0)*/
+
+WLAN_STATUS wifiProductLineCalProcess(P_CMD_PL_CAL pCmdPLcal)
+{
+    WLAN_STATUS ret = META_WIFI_STATUS_FAIL;
+    unsigned char i = 0;
+    unsigned int arg[MAX_PL_INPUT_ARG_NUM] = {0};
+    unsigned int CalStatus = META_WIFI_STATUS_FAIL;
+    unsigned int targetPwr = gHqaParaInfo.power;
+    int meanPwr = 0;
+    unsigned int ch = 0;
+    unsigned int wf_idx = -1;
+    unsigned int dbdcBandIdx = -1;
+    ENUM_BAND_T eBand = (gHqaParaInfo.chBand == 0) ? (BAND_2G4) : (BAND_5G);
+
+    unsigned int band_chNum = 0;
+    unsigned int interpolat_type = 0;
+
+
+    memset(&arg[0], 0, sizeof(unsigned int)*MAX_PL_INPUT_ARG_NUM);
+
+    if (gHqaParaInfo.eCbw == CDBW_80P80)
+        ch = gHqaParaInfo.chS2;
+    else
+        ch = gHqaParaInfo.chS1;
+
+    wf_idx = gHqaParaInfo.wf_idx;
+
+    dbdcBandIdx = gHqaParaInfo.dbdcBandIdx;
+
+    if (pCmdPLcal == NULL)
+    {
+        ERR("pCmdPLcal is null\n");
+        ret = META_WIFI_STATUS_INVALID_PARA;
+        goto error;
+    }
+
+    DBG("ID=%d Act=%d ParaNum= %d wf_idx=%d\n", pCmdPLcal->calId, pCmdPLcal->action, pCmdPLcal->inputLen, wf_idx);
+
+    for (i = 0; i < pCmdPLcal->inputLen ; i++)
+    {
+        arg[i] = pCmdPLcal->au4Buffer[i];
+        DBG("Para (%d)=%d\n", i, arg[i]);
+    }
+
+    switch (pCmdPLcal->calId)
+    {
+
+        case WIFI_PL_CAL_TX_PWR:
+            {
+                switch (pCmdPLcal->action)
+                {
+                    case TX_PWR_CAL_ACT_START:
+                        ret = wifiNVRAMTssiChOfsClear();
+
+                        if (ret == META_WIFI_STATUS_SUCCESS)
+                        {
+                            wifwNVRAMWriteDataToDriver();
+                            usleep(500000);
+                        }
+
+                        break;
+
+                    case TX_PWR_CAL_ACT_ADJUST:
+                        meanPwr = arg[0];
+
+                        if (wf_idx & BIT(WF0))
+                            ret = wifiNVRAMTssiChOfsAdjust(WF0, eBand, ch, targetPwr, meanPwr);
+
+                        if (wf_idx & BIT(WF1))
+                            ret = wifiNVRAMTssiChOfsAdjust(WF1, eBand, ch, targetPwr, meanPwr);
+
+                        if (ret == META_WIFI_STATUS_SUCCESS)
+                        {
+                            wifwNVRAMWriteDataToDriver();
+                            usleep(500000);
+                        }
+
+                        break;
+
+                    case TX_PWR_CAL_ACT_END:
+                        CalStatus = arg[0];
+
+                        if (CalStatus == META_WIFI_STATUS_SUCCESS)
+                        {
+                            DBG("[META_WIFI] TX POWER CALIBRATION PASS!\n");
+                            ret = META_WIFI_STATUS_SUCCESS;
+                        }
+                        else
+                        {
+                            DBG("[META_WIFI] TX POWER CALIBRATION Fail! Clear Result!\n");
+                            ret = wifiNVRAMTssiChOfsClear();
+                        }
+
+                        break;
+
+                    case TX_PWR_CAL_ACT_INTERPOLAT:
+                        if (arg[0] & BIT(0)) //BIT[0]:2.4G
+                            eBand = BAND_2G4;
+                        else if (arg[0] & BIT(1))//BIT[1]:5G
+                            eBand = BAND_5G;
+
+                        DBG("[META_WIFI] TX_PWR_CAL_ACT_INTERPOLAT Band(%d)\n", eBand);
+                        interpolat_type = arg[1];
+                        band_chNum = arg[2];
+                        ret = wifiNVRAMTssiChOfsInterpolation(interpolat_type, eBand, band_chNum, &arg[3]);
+
+                        if (ret == META_WIFI_STATUS_SUCCESS)
+                        {
+                            wifwNVRAMWriteDataToDriver();
+                            usleep(500000);
+                        }
+
+                        return wifiNVRAMTssiContentDumpToPC(eBand, pCmdPLcal, ret);
+
+                    default:
+                        DBG("[META_WIFI] un-support act(%d)\n", pCmdPLcal->action);
+                        ret = META_WIFI_STATUS_FAIL;
+                        goto error;
+                }
+            }
+            break;
+
+        case WIFI_PL_CAL_EPA_FE_GAIN:
+            break;
+
+        case WIFI_PL_CAL_LNA_GAIN_CAL:
+            switch (pCmdPLcal->action)
+            {
+                case TX_PWR_CAL_ACT_START:
+                    ret = wifiNVRAMLnaGainCalClear();
+
+                    if (ret == META_WIFI_STATUS_SUCCESS)
+                    {
+                        wifwNVRAMWriteDataToDriver();
+                        usleep(500000);
+                    }
+
+                    break;
+
+                case TX_PWR_CAL_ACT_ADJUST:
+                    ret = wifiNVRAMLnaGainCalAdjust(dbdcBandIdx, eBand, ch);
+
+                    if (ret == META_WIFI_STATUS_SUCCESS)
+                    {
+                        wifwNVRAMWriteDataToDriver();
+                        usleep(500000);
+                    }
+
+                    break;
+
+                case TX_PWR_CAL_ACT_END:
+                    CalStatus = arg[0];
+
+                    if (CalStatus == META_WIFI_STATUS_SUCCESS)
+                    {
+                        DBG("[META_WIFI] LNA GAIN CALIBRATION PASS!\n");
+                        ret = META_WIFI_STATUS_SUCCESS;
+                    }
+                    else
+                    {
+                        DBG("[META_WIFI] LNA GAIN CALIBRATION Fail! Clear Result!\n");
+                        ret = wifiNVRAMLnaGainCalClear();
+                    }
+
+                    break;
+
+                default:
+                    DBG("[META_WIFI] un-support act(%d)\n", pCmdPLcal->action);
+                    ret = META_WIFI_STATUS_FAIL;
+                    goto error;
+
+            }
+
+            break;
+
+        case WIFI_PL_CAL_DNL_CAL:
+            switch (pCmdPLcal->action)
+            {
+                case TX_PWR_CAL_ACT_START:
+                    ret = wifiNVRAMTssiNDLOfsClear();
+
+                    if (ret == META_WIFI_STATUS_SUCCESS)
+                    {
+                        wifwNVRAMWriteDataToDriver();
+                        usleep(500000);
+                    }
+
+                    break;
+
+                case TX_PWR_CAL_ACT_ADJUST:
+                    ret = wifiNVRAMTssiDnlOfsAdjust(dbdcBandIdx, eBand, ch);
+
+                    if (ret == META_WIFI_STATUS_SUCCESS)
+                    {
+                        wifwNVRAMWriteDataToDriver();
+                        usleep(500000);
+                    }
+
+                    break;
+
+                case TX_PWR_CAL_ACT_END:
+                    CalStatus = arg[0];
+
+                    if (CalStatus == META_WIFI_STATUS_SUCCESS)
+                    {
+                        DBG("[META_WIFI] DNL CALIBRATION PASS!\n");
+                        ret = META_WIFI_STATUS_SUCCESS;
+                    }
+                    else
+                    {
+                        DBG("[META_WIFI] DNL CALIBRATION Fail! Clear Result!\n");
+                        ret = wifiNVRAMTssiNDLOfsClear();
+                    }
+
+                    break;
+
+                default:
+                    DBG("[META_WIFI] un-support act(%d)\n", pCmdPLcal->action);
+                    ret = META_WIFI_STATUS_FAIL;
+                    goto error;
+
+            }
+
+            break;
+
+        default:
+            ERR("Not Support Cal ID :%d\n", pCmdPLcal->calId);
+            ret = META_WIFI_STATUS_FAIL;
+            goto error;
+    }
+
+error:
+
+    //reponse Product Line calibration result
+    pCmdPLcal->inputLen = sizeof(ret);
+    pCmdPLcal->au4Buffer[0] = ret;
+
+    return ret;
+
+}
+
+WLAN_STATUS wifiProductLineScript(char* pCmd, unsigned short pCmdlen)
+{
+    CMD_PL_CAL rCmdPlCal;
+    char head[20];
+    unsigned int act;
+    unsigned int val;
+    unsigned int calId;
+
+    DBG("do Product line cmd: %s len:%d\n", pCmd, pCmdlen);
+    sscanf(pCmd, "%s %d %d %d", head, &calId, &act, &val);
+    DBG("HEAD:%s,CAL ID%d,ACT:%d,VAL:%d\n", head, calId, act, val);
+
+    rCmdPlCal.calId = calId;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.action = act;
+    rCmdPlCal.inputLen = 1;
+    rCmdPlCal.au4Buffer[0] = val;
+
+    return wifiProductLineCalProcess(&rCmdPlCal);
+
+}
+
+WLAN_STATUS wifiProductInit(void)
+{
+    memset(&gHqaParaInfo, 0, sizeof(gHqaParaInfo));
+
+    return META_WIFI_STATUS_SUCCESS;
+
+}
+
+unsigned int wifiHqaGetParaAndShiftBuf(
+    bool convert, unsigned int size, unsigned char **buf, unsigned char *out)
+{
+    if (!(*buf))
+    {
+        DBG("*buf NULL pointer with size=%u\n", size);
+        return META_WIFI_STATUS_INVALID_PARA;
+    }
+
+    if (!out)
+    {
+        DBG("out NULL pointer with size=%u\n", size);
+        return META_WIFI_STATUS_INVALID_PARA;
+    }
+
+    memcpy(out, *buf, size);
+    *buf = *buf + size;
+
+    if (!convert)
+    {
+        DBG("size=%u", size);
+        return META_WIFI_STATUS_SUCCESS;
+    }
+
+    if (size == sizeof(unsigned int))
+    {
+        unsigned int *tmp = (unsigned int *) out;
+
+        *tmp = ntohl(*tmp);
+        DBG("size=%u, val=%u\n", size, *tmp);
+    }
+    else if (size == sizeof(unsigned short))
+    {
+        unsigned short *tmp = (unsigned short *) out;
+
+        *tmp = ntohs(*tmp);
+        DBG("size=%u, val=%u\n", size, *tmp);
+    }
+    else
+    {
+        DBG("size %u not supported\n", size);
+        return META_WIFI_STATUS_NOT_SUPPORT;
+    }
+
+    return META_WIFI_STATUS_SUCCESS;
+}
+
+WLAN_STATUS wifiHqaGetDumpReCal(unsigned int item, unsigned int dbdcBandIdx, P_RECAL_INFO_T prReCalInfo)
+{
+    P_HQA_CMD_FRAME prHqaCmd = NULL;
+    WLAN_STATUS ret = META_WIFI_STATUS_FAIL;
+    unsigned char* pData = NULL;
+
+
+    unsigned int avail_sz = 0;
+    int i = 0, j = 0;
+    int u4hqaCmdLen = 0;
+
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(RECAL_INFO_T) + sizeof(RECAL_INFO_T);
+    prHqaCmd = (P_HQA_CMD_FRAME)malloc(u4hqaCmdLen);
+    if (!prHqaCmd)
+    {
+        DBG("out of memory in allocating prHqaCmd\n");
+        return META_WIFI_STATUS_FAIL;
+    }
+    memset(prHqaCmd, 0, u4hqaCmdLen);
+
+
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_GetDumpRecal);
+    prHqaCmd->length = htons(sizeof(unsigned int));
+    prHqaCmd->sequence = 1;
+    dbdcBandIdx = htonl(dbdcBandIdx);
+
+    memcpy(&prHqaCmd->data[0], &dbdcBandIdx, sizeof(unsigned int));
+
+    for (i = 0; i < POLLING_RECAL_RETRY_CNT; i++)
+    {
+        ret = HQAIWreq(wifi_skfd, "wlan0", (char *)prHqaCmd, u4hqaCmdLen, &avail_sz);
+
+        DBG("[HQA_CMD] dump Item:%d,BandIdx:%d,CMD:%p,len:%d,ret:%d,avail_sz:%d\n",
+            item,
+            dbdcBandIdx,
+            prHqaCmd,
+            u4hqaCmdLen,
+            ret,
+            avail_sz);
+
+        if (ret != META_WIFI_STATUS_SUCCESS)
+        {
+            DBG("[HQA_CMD] dump Item:%d fail!ret(%d)\n", item, ret);
+            break;
+        }
+
+        if (avail_sz > 0)
+        {
+            pData = (unsigned char*)&prHqaCmd->data[0];
+
+            //status 2Byte
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned short), &pData, (unsigned char *)&prReCalInfo->status);
+
+            //Count 4Byte
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&prReCalInfo->u4Count);
+
+            DBG("[HQA_CMD] dump Cal Item:%d,retry:%d,status:%d,Count:%d\n", item, i, prReCalInfo->status, prReCalInfo->u4Count);
+
+
+            if (prReCalInfo->u4Count == 0)
+            {
+                usleep(1 * 1000 * 1000);
+                DBG("[HQA_CMD] dump Item Sleep 1s do next query\n");
+            }
+            else if (prReCalInfo->u4Count > MAX_RECAL_DATA_NUM)
+            {
+                DBG("[HQA_CMD] prReCalInfo->u4Count out of bound!\n");
+                ret = META_WIFI_STATUS_FAIL;
+                goto error;
+            }
+            else
+            {
+
+                for (j = 0 ; j < prReCalInfo->u4Count ; j++)
+                {
+                    //Recal ID 4Byte
+                    wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&prReCalInfo->u4CalId[j]);
+                    //Offset 4Byte
+                    wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&prReCalInfo->u4CalAddr[j]);
+                    //Value 4Byte
+                    wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&prReCalInfo->u4CalValue[j]);
+
+                    DBG("[HQA_CMD] (%d)ID=0x%08X,CR=0x%08X,Value=0x%08X\n"
+                        , j, prReCalInfo->u4CalId[j], prReCalInfo->u4CalAddr[j], prReCalInfo->u4CalValue[j]);
+                }
+
+                ret = META_WIFI_STATUS_SUCCESS;
+
+                break;
+            }
+        }
+
+    }
+
+error:
+    FREEIF(prHqaCmd);
+
+    DBG("finish\n");
+
+    return ret;
+}
+WLAN_STATUS wifiHqaDoCalibrationTestItem(unsigned int item, unsigned int dbdcBandIdx)
+{
+    P_HQA_CMD_FRAME prHqaCmd;
+    WLAN_STATUS ret = META_WIFI_STATUS_FAIL;
+    HQA_DO_CAL_TEST_ITEM rCalItem;
+
+    unsigned int avail_sz = 0;
+    int u4hqaCmdLen = 0;
+
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(HQA_DO_CAL_TEST_ITEM);
+    prHqaCmd = (P_HQA_CMD_FRAME)malloc(u4hqaCmdLen);
+    if (!prHqaCmd)
+    {
+        DBG("out of memory in allocating prHqaCmd\n");
+        return META_WIFI_STATUS_FAIL;
+    }
+    memset(prHqaCmd, 0, u4hqaCmdLen);
+
+
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_DoCalibrationTestItem);
+    prHqaCmd->length = htons(sizeof(rCalItem));
+    prHqaCmd->sequence = 1;
+    rCalItem.item = htonl(item);
+    rCalItem.band_idx = htonl(dbdcBandIdx);
+
+    memcpy(&prHqaCmd->data[0], &rCalItem, sizeof(HQA_DO_CAL_TEST_ITEM));
+
+    ret = HQAIWreq(wifi_skfd, "wlan0", (char *)prHqaCmd, u4hqaCmdLen, &avail_sz);
+
+    DBG("[HQA_CMD] Do Cal Item:0x%08X,BandIdx:%d,CMD:%p,len:%d,ret:%d,avail_sz:%d\n",
+        item,
+        dbdcBandIdx,
+        prHqaCmd,
+        u4hqaCmdLen,
+        ret,
+        avail_sz);
+
+
+    FREEIF(prHqaCmd);
+    return ret;
+}
+
+WLAN_STATUS wifiHqaCmdParaMonitor(char* peer_buf, unsigned short peer_len)
+{
+    P_HQA_CMD_FRAME prHqaCmd = NULL;
+    unsigned short u2HqaCmdId = 0;
+    unsigned int u4HqaCmdExtId = 0;
+    unsigned int u4ParaNum = 0;
+    unsigned int    value = 0;
+    unsigned char* pData = NULL;
+
+    if (peer_buf == NULL)
+        return META_WIFI_STATUS_INVALID_PARA;
+
+    if (peer_len <= 0)
+        return META_WIFI_STATUS_INVALID_PARA;
+
+
+    prHqaCmd = (P_HQA_CMD_FRAME)peer_buf;
+
+    if (ntohl(prHqaCmd->magicNo) != HQA_CMD_MAGIC_NO)
+    {
+        DBG("MagicNo is Not Support\n");
+        return META_WIFI_STATUS_NOT_SUPPORT;
+    }
+
+    u2HqaCmdId = ntohs(prHqaCmd->id);
+
+    pData = &prHqaCmd->data[0];
+
+    switch (u2HqaCmdId)
+    {
+        case HQA_CMD_OPEN_ADAPTER:
+        case HQA_CMD_CLOSE_ADAPTER:
+            memset(&gHqaParaInfo, 0, sizeof(gHqaParaInfo));
+            break;
+
+        case HQA_CMD_SetTxPath:
+            //tx path in bitwith
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+            gHqaParaInfo.wf_idx = value;
+            //band index
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+            gHqaParaInfo.dbdcBandIdx = value;
+            break;
+
+        case HQA_CMD_SetTxPowerExt:
+            //Power
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+            gHqaParaInfo.power = value;
+            break;
+
+        case HQA_CMD_EXTEND:
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&u4HqaCmdExtId);
+            break;
+    }
+
+    switch (u4HqaCmdExtId)
+    {
+        case HQA_CMD_DBDCSetChannel:
+            //PARA NUM
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&u4ParaNum);
+            //DBDC IDX
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+            //Center Channel Freq 0
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+            gHqaParaInfo.chS1 = value;
+            //Center Channel Freq 1
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+            gHqaParaInfo.chS2 = value;
+            //SystemBW
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+            gHqaParaInfo.eCbw = value;
+            //PrePketBW
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+            //primary select
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+            //reason
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+            //channel band
+            wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+            gHqaParaInfo.chBand = value;
+            break;
+
+        case HQA_CMD_DBDCStartTx:
+            DBG("Start Tx: wf_idx[0x%x]dbdcIdx[%d]chBand[%d]pwr[%d]chS1[%d]chS2[%d]cbw[%d]\n",
+                gHqaParaInfo.wf_idx,
+                gHqaParaInfo.dbdcBandIdx,
+                gHqaParaInfo.chBand,
+                gHqaParaInfo.power,
+                gHqaParaInfo.chS1,
+                gHqaParaInfo.chS2,
+                gHqaParaInfo.eCbw);
+            break;
+
+        case HQA_CMD_DBDCStopTx:
+            break;
+
+    }
+
+    DBG("Handle cmdId = 0x%08X extId = 0x%08X\n", u2HqaCmdId, u4HqaCmdExtId);
+
+    return META_WIFI_STATUS_SUCCESS;
+
+}
+#endif /*#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)*/
+
+void META_WIFI_Register(WIFI_CNF_CB callback)
+{
+    cnf_cb = callback;
+}
+
+int META_WIFI_init(void)
+{
+    int count = 100;
+
+    if (1 == wifi_init)
+    {
+        ERR("wifi is already initilized.\n");
+        return true;
+    }
+
+#if 0
+
+    if (!wifi_is_loaded())
+    {
+        ERR("[META_WIFI] loading wifi driver ... ...\n");
+
+        if (wifi_insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
+        {
+            ERR("[META_WIFI] failed to load wifi driver!!!\n");
+            goto error;
+        }
+    }
+
+#endif
+    usleep(200000);
+    /*get wifi nvram profile before wifi on */
+    gNvInfo = NVM_ReadFileVerInfo(AP_CFG_RDEB_FILE_WIFI_LID);
+    DBG("[META_WIFI] NVRAM FileVer:%s\n", gNvInfo.cFileVer);
+    DBG("[META_WIFI] NVRAM FileName:%s\n", gNvInfo.cFileName);
+    DBG("[META_WIFI] NVRAM RecSize:%d\n", gNvInfo.i4RecSize);
+    DBG("[META_WIFI] NVRAM RecNum:%d\n", gNvInfo.i4RecNum);
+    DBG("[META_WIFI] NVRAM MaxFileLid:%d\n", gNvInfo.i4MaxFileLid);
+
+    DBG("[META_WIFI] WIFI_META_VER:%s\n", WIFI_META_VER);
+
+    wifi_set_power(1);
+
+
+    sched_yield();
+
+    while (count-- > 0)
+    {
+        if (ifc_init() == 0)
+        {
+            if (ifc_up("wlan0") == 0)
+            {
+                ifc_close();
+                break;
+            }
+
+            ERR("[META_WIFI] ifc_up(wlan0) failed\n");
+            ifc_close();
+        }
+        else
+        {
+            ERR("[META_WIFI] ifc_init() failed\n");
+        }
+
+        usleep(100000);
+    }
+
+    if (count == 0)
+        goto error;
+
+    if (wifi_skfd == -1)
+        wifi_skfd = openNetHandle();
+
+    if (wifi_skfd < 0)
+    {
+        META_WIFI_deinit();
+        goto error;
+    }
+
+    wifi_init = 1;
+#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)
+    wifiProductInit();
+#endif /*#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)*/
+
+    return true;
+
+error:
+    wifi_set_power(0);
+    return false;
+}
+
+void META_WIFI_deinit(void)
+{
+    //int count = 20; /* wait at most 10 seconds for completion */
+
+    DBG("[META_WIFI] WIFI_META_VER:%s\n", WIFI_META_VER);
+
+    if (0 == wifi_init)
+    {
+        ERR("wifi is already deinitilized.\n");
+        return;
+    }
+
+    if (wifi_skfd > 0)
+    {
+        closeNetHandle(wifi_skfd);
+        wifi_skfd = -1;
+    }
+
+    /*    if (wifi_rmmod(DRIVER_MODULE_NAME) == 0) {
+            while (count-- > 0) {
+                if (!wifi_is_loaded())
+                    break;
+                usleep(500000);
+            }
+            sched_yield();*/
+    wifi_set_power(0);
+    /*    }*/
+    wifi_init = 0;
+    return;
+}
+
+void META_WIFI_OP(FT_WM_WIFI_REQ *req, char *peer_buf, unsigned short peer_len)
+{
+    unsigned int i;
+    int ret = -1;
+    FT_WM_WIFI_CNF cnf;
+    OID_STRUC *poid = NULL;
+    unsigned int avail_sz = 0;
+    NVRAM_ACCESS_STRUCT *pnvram = NULL;
+    P_CMD_PL_CAL prCmdPlCal = NULL;
+    char *pCmd = NULL;
+    int cmdLen = 0;
+    void *ret_buf = NULL, *allocated_buf = NULL;
+    unsigned int ret_size = 0;
+    int readByteLen = -1;
+
+
+//modify for wifi init/deinit flow
+//     if (NULL == req || NULL == peer_buf || wifi_skfd < 0 || !wifi_init) {
+//         printf("[META_WIFI] Invalid arguments or operation\n");
+//         goto exit;
+//     }
+
+    DBG("META_WIFI_OP OP is %d,peer_len=%d\n", req->type, peer_len);
+
+    //for the compaliance of the former meta tool
+    if (!wifi_init && WIFI_CMD_INIT != req->type)
+    {
+        if (true != META_WIFI_init())
+        {
+            ERR("!wifi_init & META_WIFI_init fail\n");
+            ret = -1;
+            goto exit;
+        }
+        else
+            DBG("Init for the compaliance of the former meta tool.\n");
+    }
+
+
+    // OID operation
+    if (WIFI_CMD_SET_OID == req->type
+            || WIFI_CMD_QUERY_OID == req->type)
+    {
+        if ((peer_len <= 0) || NULL == (poid = (OID_STRUC *)malloc(peer_len)))
+        {
+            ERR("[META_WIFI] No memory, %d\n", peer_len);
+            goto exit;
+        }
+
+        // for later freeing
+        allocated_buf = (void *)poid;
+        memcpy(poid, peer_buf, peer_len);
+
+        if (WIFI_CMD_SET_OID == req->type)
+        {
+            for (i = 0; i < poid->SetOidPara.dataLen; i++)
+            {
+                DBG("[META_WIFI] OIDReq : data[%d] = 0x%x\n",
+                    i, poid->SetOidPara.data[i]);
+            }
+
+            ret = setIWreq(wifi_skfd, "wlan0", poid->SetOidPara.oid,
+                           poid->SetOidPara.data, poid->SetOidPara.dataLen, &avail_sz);
+            DBG("[META_WIFI] SET_OID, OID: 0x%x, len: %d, ret: %d\n",
+                poid->SetOidPara.oid, poid->SetOidPara.dataLen, ret);
+        }
+        else if (WIFI_CMD_QUERY_OID == req->type)
+        {
+            ret = getIWreq(wifi_skfd, "wlan0", poid->QueryOidPara.oid,
+                           poid->QueryOidPara.data, poid->QueryOidPara.dataLen, &avail_sz);
+            DBG("[META_WIFI] QUERY_OID, OID: 0x%x, len: %d, ret: %d\n",
+                poid->QueryOidPara.oid, poid->QueryOidPara.dataLen, ret);
+        }
+
+        if (ret == 0 && WIFI_CMD_QUERY_OID == req->type)
+        {
+            ret_buf = (void *)poid;
+            ret_size = avail_sz + 8;
+        }
+    }
+    // NVRAM access
+    else if (WIFI_CMD_NVRAM_WRITE_ACCESS == req->type
+             || WIFI_CMD_NVRAM_READ_ACCESS == req->type)
+    {
+
+        if ((peer_len <= 0) || NULL == (pnvram = (NVRAM_ACCESS_STRUCT *)malloc(peer_len)))
+        {
+            ERR("[META_WIFI] No memory, %d\n", peer_len);
+            goto exit;
+        }
+
+        // for later freeing
+        allocated_buf = (void *)pnvram;
+        memcpy(pnvram, peer_buf, peer_len);
+
+        if (peer_len < (offsetof(NVRAM_ACCESS_STRUCT, data) + pnvram->dataLen))
+        {
+            ERR("[META_WIFI] Mimatched NVRAM content length: (%d / %u)\n", peer_len,
+                (unsigned int)(offsetof(NVRAM_ACCESS_STRUCT, data) + pnvram->dataLen));
+            goto exit;
+        }
+
+        if (WIFI_CMD_NVRAM_READ_ACCESS == req->type)
+        {
+            readByteLen = wifiNVRAMCtrl(NVRAM_READ, pnvram);
+
+            if (readByteLen > 0)
+            {
+                ret_buf = (void *)pnvram;
+                ret_size = offsetof(NVRAM_ACCESS_STRUCT, data) + ret;
+                ret = 0;
+            }
+            else
+                ret = -1;
+        }
+        else if (WIFI_CMD_NVRAM_WRITE_ACCESS == req->type)
+        {
+            ret = wifiNVRAMCtrl(NVRAM_WRITE, pnvram);
+        }
+    }
+    else if (WIFI_CMD_INIT == req->type)
+    {
+        if (true != META_WIFI_init())
+            ret = -1;
+        else
+            ret = 0;
+    }
+
+    else if (WIFI_CMD_DEINIT == req->type)
+    {
+        META_WIFI_deinit();
+        ret = 0;
+    }
+
+    else if (WIFI_CMD_SCRIPT == req->type)
+    {
+
+        /*Do sanity check*/
+        if (peer_len <= 0)
+            goto exit;
+
+        /*memory allocate for saving driver's command result*/
+        if (NULL == (pCmd = (char *)malloc(WIFI_SCRIPT_TOTAL_BUF_LEN)))
+        {
+            goto exit;
+        }
+
+        memcpy(pCmd, peer_buf, peer_len);
+        pCmd[peer_len] = '\0';
+
+        /*parse User command and remove iwpriv driver command head, for example : adb shell ipwriv driver*/
+        cmdLen = wifiScriptRemoveHead(pCmd);
+
+        if (cmdLen > 0)
+        {
+#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)
+
+            /*Support Product Line Calibration script*/
+            /*format : PL <ID> <ACT> <VALUE>*/
+            if (pCmd[0] == 'P' && pCmd[1] == 'L')
+            {
+                ret = wifiProductLineScript(pCmd, cmdLen);
+            }
+            else
+#endif /*#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)*/
+            {
+                ret = driverIWreq(wifi_skfd, "wlan0", pCmd, cmdLen, &avail_sz);
+                DBG("[META_WIFI] DRIVER CMD:%s,len:%d,ret:%d,avail_sz:%d\n", peer_buf, peer_len, ret, avail_sz);
+            }
+
+            if (ret == 0 && WIFI_CMD_SCRIPT == req->type)
+            {
+                ret_buf = (void *)pCmd;
+                ret_size = avail_sz;
+            }
+
+        }
+
+    }
+
+    else if (WIFI_CMD_HQA == req->type)
+    {
+
+        if ((peer_len <= 0) || NULL == (pCmd = (char *)malloc(WIFI_SCRIPT_TOTAL_BUF_LEN)))
+        {
+            ERR("[HQA_CMD] No memory, %d\n", peer_len);
+            goto exit;
+        }
+
+        memcpy(pCmd, peer_buf, peer_len);
+        pCmd[peer_len] = '\0';
+        cmdLen = peer_len; // +  RA_CFG_HLEN
+
+        ret = HQAIWreq(wifi_skfd, "wlan0", pCmd, cmdLen, &avail_sz);
+
+        DBG("[HQA_CMD] CMD:%p,len:%d,ret:%d,avail_sz:%d\n", peer_buf, peer_len, ret, avail_sz);
+
+        if (ret == 0 && WIFI_CMD_HQA == req->type)
+        {
+#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)
+            wifiHqaCmdParaMonitor(peer_buf, peer_len);
+#endif /*#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)*/
+            ret_buf = (void *)pCmd;
+            ret_size = avail_sz;
+        }
+    }
+
+#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)
+
+    else if (WIFI_CMD_PL_CALIBRATION == req->type)
+    {
+        if ((peer_len <= 0) || NULL == (prCmdPlCal = (P_CMD_PL_CAL)malloc(sizeof(CMD_PL_CAL))))
+        {
+            ERR("[META_WIFI] No memory, %d\n", peer_len);
+            goto exit;
+        }
+
+        //init
+        memset(prCmdPlCal, 0, sizeof(CMD_PL_CAL));
+
+        // for later freeing
+        memcpy(prCmdPlCal, peer_buf, peer_len);
+        ret = wifiProductLineCalProcess(prCmdPlCal);
+
+        ret_buf = (void *)prCmdPlCal;
+        ret_size = sizeof(CMD_PL_CAL);
+
+        DBG("[PL_CAL] ID:%d,ACT:%d,ret:%d,ret_size:%d done!\n", prCmdPlCal->calId, prCmdPlCal->action, ret, ret_size);
+    }
+
+#endif /*#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)*/
+
+exit:
+    memset(&cnf, 0, sizeof(FT_WM_WIFI_CNF));
+    cnf.header.token = req->header.token;
+    cnf.header.id    = FT_WIFI_CNF_ID;
+    cnf.type         = req->type;
+    cnf.status       = META_SUCCESS;
+
+    /* CHECKME!! Need to confirm the value of drv_status */
+    cnf.drv_status   = (ret == 0) ? (int)true : (int)false;
+
+    wifi_send_resp(&cnf, ret_buf, ret_size);
+
+    FREEIF(poid);
+    FREEIF(pnvram);
+    FREEIF(pCmd);
+    FREEIF(prCmdPlCal);
+    return;
+}
+
diff --git a/src/devtools/meta/src/adaptor/wifi/meta_wifi.h b/src/devtools/meta/src/adaptor/wifi/meta_wifi.h
new file mode 100644
index 0000000..2aa5dc6
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/meta_wifi.h
@@ -0,0 +1,10 @@
+#ifndef __META_WIFI_H__
+#define __META_WIFI_H__
+#include "meta_wifi_para.h"
+
+typedef void (*WIFI_CNF_CB)(FT_WM_WIFI_CNF *cnf, void *buf, unsigned int size);
+
+extern void META_WIFI_Register(WIFI_CNF_CB callback);
+
+#endif
+
diff --git a/src/devtools/meta/src/adaptor/wifi/meta_wifi_para.h b/src/devtools/meta/src/adaptor/wifi/meta_wifi_para.h
new file mode 100644
index 0000000..83ecd12
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/meta_wifi_para.h
@@ -0,0 +1,675 @@
+/*****************************************************************************
+*  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).
+*
+*****************************************************************************/
+
+//
+// Copyright (c) Microsoft Corporation.  All rights reserved.
+//
+//
+// Use of this source code is subject to the terms of the Microsoft end-user
+// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
+// If you did not accept the terms of the EULA, you are not authorized to use
+// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
+// install media.
+//
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   meta_wifi_para.h
+ *
+ * Project:
+ * --------
+ *   DUMA
+ *
+ * Description:
+ * ------------
+ *   the defination of Wi-Fi wrapper interface for META FT task.
+ *
+ * Author:
+ * -------
+ *  Renbang Jiang (MTK80150)
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by CC/CQ. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * $Revision:$
+ * $Modtime:$
+ * $Log:$
+ *
+ * Mar 6 2009 mtk80150
+ * [DUMA00110922] [Wi-Fi] Wi-Fi driver for META initial timeout
+ * Add Timeout for driver initializing
+ *
+ * Mar 6 2009 mtk80150
+ * [DUMA00110922] [Wi-Fi] Wi-Fi driver for META initial timeout
+ * Add timeout for Wi-Fi driver initialize
+ *
+ * Feb 22 2009 mtk80150
+ * [DUMA00109732] [Wi-Fi] Driver version update to 1.13
+ *
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+#ifndef _META_WIFI_PARA_H_
+#define _META_WIFI_PARA_H_
+
+#include <sys/types.h>
+#include "MetaPub.h"
+#include <cutils/log.h>
+#include <type.h>
+
+#include "CFG_Wifi_File.h"
+
+#define WIFI_GEN_VER (WIFI_NVRAM_VERSION & 0xF000)
+#define CONNAC_SOC3_0                   0x3000
+#define CONNAC_SOC2_0                   0x2000
+#define SUPPORT_SOC3_0_DNL_VER          0x3030
+
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+#define CFG_TSSI_CH_GT_SAME 1 // all gt table apply the same value
+#else
+#define CFG_TSSI_CH_GT_SAME 0 // all gt table apply the same value
+#endif
+
+#if (WIFI_NVRAM_VERSION >= SUPPORT_SOC3_0_DNL_VER)
+#define CFG_DNL_CAL 1
+#else
+#define CFG_DNL_CAL 0
+#endif
+
+#define DRIVER_INIT_TIMEOUT 1000
+
+#define ZONE_ERROR 1
+#define ZONE_FUNC 0
+
+
+#define FUNCTION_CODE_QUERY_OID_VALUE           0x201
+#define FUNCTION_CODE_SET_OID_VALUE             0x205
+#define FUNCTION_CODE_POSTINIT_VALUE            0x209
+#define NVRAM_READ  FALSE
+#define NVRAM_WRITE TRUE
+#define G_BAND 0
+#define A_BAND 1
+#define BAND_NUM 2
+
+#define WF0           0
+#define WF1           1
+#define WF_NUM        2
+
+#define META_WIFI_STATUS_SUCCESS         0
+#define META_WIFI_STATUS_FAIL           -1
+#define META_WIFI_STATUS_INVALID_PARA   -2
+#define META_WIFI_STATUS_NOT_SUPPORT    -3
+
+
+#define _META_CTL_CODE(_Function, _Method, _Access)                \
+            CTL_CODE(FILE_DEVICE_NETWORK, _Function, _Method, _Access)
+
+#define IOCTL_META_SET_OID_VALUE                                   \
+            _META_CTL_CODE(FUNCTION_CODE_SET_OID_VALUE,            \
+                           METHOD_BUFFERED,                        \
+                           FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_META_QUERY_OID_VALUE                                 \
+            _META_CTL_CODE(FUNCTION_CODE_QUERY_OID_VALUE,          \
+                           METHOD_BUFFERED,                        \
+                           FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+
+#define IOCTL_META_WIFI_POSTINIT                                        \
+            _META_CTL_CODE(FUNCTION_CODE_POSTINIT_VALUE,           \
+                           METHOD_BUFFERED,                        \
+                           FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define FREEIF(p)   do { if(p) free(p); p = NULL; } while(0)
+
+
+
+#define WIFI_DEV_NAME (L"NDL1:")
+#define WIFI_READY_EVENT_NAME (L"OEM/WiFiDriverReady")
+
+
+#define HQA_CMD_MAGIC_NO 0x18142880
+#define HQA_CMD_OPEN_ADAPTER 0x1000
+#define HQA_CMD_CLOSE_ADAPTER 0x1001
+#define HQA_CMD_SetTxPath     0x100B
+#define HQA_CMD_DoCalibrationTestItem  0x150A
+#define HQA_CMD_GetDumpRecal           0x1581
+
+#define HQA_CMD_SetTxPowerExt 0x1011
+#define HQA_CMD_EXTEND  0x1600
+#define HQA_CMD_DBDCSetChannel  0x01
+#define HQA_CMD_DBDCStartTx 0x03
+#define HQA_CMD_DBDCStopTx 0x05
+
+#define HQA_CAL_ITEM_DNL            0x00004000
+#define DNL_WF_PATH_CR_NUM          16 /* CR:32*(WF0+WF1)*/
+
+#define HQA_CAL_ITEM_LNA_GIAN_CAL   0x00008000
+#define LNA_GIAN_CAL_WF_PATH_CR_NUM          2 /*CR:2 *(WF0+WF1)*/
+
+#define TSSI_CH_OFS_GT_NUM 6
+#define PER_CH_GROUP_IN_RF_GROUP 4 /* 2x(low channel+high channel) */
+
+#define MAX_RECAL_DATA_NUM              64
+
+/** chanle group support max num */
+#define CH_GROUP_SUPPORT_MAX_NUM        16
+#define CH_SUB_GROUP_SUPPORT_MAX_NUM    16
+
+/** common category channel group info */
+#define NVRAM_COMMON_CATEGORY_G_BAND_CH_GROUP_NUM        14
+#define NVRAM_COMMON_CATEGORY_A_BAND_CH_GROUP_NUM         8
+
+/** wf path module channel group info (Tssi Ch offset) */
+#define NVRAM_TSSI_CH_OFFSET_G_BAND_CH_GROUP_NUM         14
+#define NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM         16
+#define NVRAM_TSSI_CH_OFFSET_A_BAND_RF_GROUP_NUM          8
+
+
+/** channel group boundary (common category) */
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_00                1
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_01                2
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_02                3
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_03                4
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_04                5
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_05                6
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_06                7
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_07                8
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_08                9
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_09               10
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_10               11
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_11               12
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_12               13
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_13               14
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_14              255
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_15              255
+
+
+/** channel group boundary (common category) */
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_00               34
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_01               50
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_02               66
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_03               98
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_04              114
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_05              130
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_06              147
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_07              182
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_08              255
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_09              255
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_10              255
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_11              255
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_12              255
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_13              255
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_14              255
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_15              255
+
+/** channel group boundary (Tssi Ch offset for G-Band) */
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_00                       1
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_01                       2
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_02                       3
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_03                       4
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_04                       5
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_05                       6
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_06                       7
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_07                       8
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_08                       9
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_09                      10
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_10                      11
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_11                      12
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_12                      13
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_13                      14
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_14                     255
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_15                     255
+
+/** channel group boundary (Tssi Ch offset for A-Band) */
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_00                       5
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_01                      34
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_02                      40
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_03                      50
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_04                      56
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_05                      66
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_06                      80
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_07                      98
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_08                     104
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_09                     114
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_10                     120
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_11                     130
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_12                     136
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_13                     144
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_14                     157
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_15                     182
+
+
+/** sub-group boundary (TX for G-Band) */
+#define CH_SUB_GROUP_G_BAND_NOT_ORDERED_NUM     0
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_00       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_01       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_02       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_03       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_04       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_05       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_06       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_07       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_08       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_09       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_10       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_11       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_12       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_13       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_14       255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_15       255
+
+/** channel power offset sub-group boundary (TX for A-Band) */
+#define CH_SUB_GROUP_A_BAND_NOT_ORDERED_NUM    0
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_00        190
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_01        17
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_02        37
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_03        45
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_04        53
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_05        61
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_06        75
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_07        89
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_08       102
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_09       110
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_10       118
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_11       125
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_12       134
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_13       142
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_14       153
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_15       163
+
+
+#define NVRAM_GT2_OFFSET    0x00
+#define NVRAM_GT3_OFFSET    0x01
+#define NVRAM_GT4_OFFSET    0x02
+#define NVRAM_GT5_OFFSET    0x03
+#define NVRAM_GT6_OFFSET    0x04
+#define NVRAM_GT7_OFFSET    0x05
+
+#define NDL_OFFSET_BIAS0_MASK 0xFF000000
+#define NDL_OFFSET_BIAS0_SHFT 24
+
+#define NDL_OFFSET_BIAS1_MASK 0x00FF0000
+#define NDL_OFFSET_BIAS1_SHFT 16
+
+#define NDL_OFFSET_BIAS2_MASK 0x0000FF00
+#define NDL_OFFSET_BIAS2_SHFT 8
+
+#define NDL_OFFSET_BIAS3_MASK 0x000000FF
+#define NDL_OFFSET_BIAS3_SHFT 0
+
+#define NDL_OFFSET_BIAS4_MASK 0xFF000000
+#define NDL_OFFSET_BIAS4_SHFT 24
+
+#define NDL_OFFSET_BIAS5_MASK 0x00FF0000
+#define NDL_OFFSET_BIAS5_SHFT 16
+
+
+#define LNA_GAIN_TAB0_MASK 0x7F000000  //[30..24]
+#define LNA_GAIN_TAB0_SHFT 24
+
+#define LNA_GAIN_TAB1_MASK 0x007F0000  //[22..16]
+#define LNA_GAIN_TAB1_SHFT 16
+
+#define LNA_GAIN_TAB2_MASK 0x00007F00  //[14..8]
+#define LNA_GAIN_TAB2_SHFT 8
+
+#define LNA_GAIN_TAB3_MASK 0x0000007F  //[6..0]
+#define LNA_GAIN_TAB3_SHFT 0
+
+#define LNA_GAIN_TAB4_MASK 0x7F000000  //[30..24]
+#define LNA_GAIN_TAB4_SHFT 24
+
+
+/* This macro returns the byte offset of a named field in a known structure
+ *   type.
+ *   _type - structure name,
+ *   _field - field name of the structure
+ */
+#ifndef OFFSET_OF
+#define OFFSET_OF(_type, _field)    offsetof(_type, _field)
+#endif /* OFFSET_OF */
+#define SIGNED_CONVERT_EXTEND_BITS(data,ori_res) ((unsigned)(data) >= (unsigned)BIT((ori_res) - 1) ? (signed)((data)- BIT((ori_res))) : (signed)(data))
+
+
+#ifdef LOG_TAG
+#undef  LOG_TAG
+#endif
+#define LOG_TAG         "WIFI_META "
+#define WIFI_META_VER   "20191021_0"
+
+#define WIFI_META_TEST_DEBUG 0
+#if (WIFI_META_TEST_DEBUG == 1)
+#define DBG(f, ...)     printf(f, ##__VA_ARGS__)
+#define TRC(f, ...)     printf(f, ##__VA_ARGS__)
+#define ERR(f, ...)     printf(f, ##__VA_ARGS__)
+#define WAN(f, ...)     printf(f, ##__VA_ARGS__)
+#else
+#define DBG(f, ...)     ALOGD("%s: " f, __func__, ##__VA_ARGS__)
+#define TRC(f)          ALOGW("%s #%d", __func__, __LINE__)
+#define ERR(f, ...)     ALOGE("%s: " f, __func__, ##__VA_ARGS__)
+#define WAN(f, ...)     ALOGW("%s: " f, __func__, ##__VA_ARGS__)
+#endif
+
+
+typedef enum
+{
+    WIFI_CMD_SET_OID = 0,
+    WIFI_CMD_QUERY_OID = 1,
+    WIFI_CMD_NVRAM_WRITE_ACCESS = 2,
+    WIFI_CMD_NVRAM_READ_ACCESS = 3,
+    WIFI_CMD_INIT = 4,
+    WIFI_CMD_DEINIT = 5,
+    WIFI_CMD_SCRIPT = 6,
+    WIFI_CMD_HQA = 7,
+    WIFI_CMD_PL_CALIBRATION = 8,
+    WIFI_CMD_NUM
+} WIFI_CMD_TYPE;
+
+typedef enum
+{
+    WIFI_PL_CAL_TX_PWR = 1,
+    WIFI_PL_CAL_EPA_FE_GAIN = 2,
+    WIFI_PL_CAL_LNA_GAIN_CAL = 3, /*RSSI GAIN CAL*/
+    WIFI_PL_CAL_DNL_CAL = 4,
+    WIFI_PL_CAL_NUM
+} WIFI_PL_CAL_TYPE;
+
+typedef enum
+{
+    TX_PWR_CAL_ACT_START = 0,
+    TX_PWR_CAL_ACT_ADJUST = 1,
+    TX_PWR_CAL_ACT_END = 2,
+    TX_PWR_CAL_ACT_INTERPOLAT = 3, //Interpolation
+    TX_PWR_CAL_ACT_NUM
+} TX_PWR_CAL_ACT;
+
+
+typedef enum
+{
+    TYPE_INTERPOLATION = 0,
+    TYPE_GROUP_THE_SAME = 1,
+    TX_PWR_INTERPOLATION_NUM
+} TX_PWR_INTERPOLATION_TYPE;
+
+typedef enum
+{
+    INTER_ACT_INTERPOLATION = 0,
+    INTER_ACT_GROUP_THE_SAME = 1,
+    INTER_ACT_NOT_SUPPORT = 2,
+    INTER_ACT_NUM
+} INTER_ACT;
+
+
+/* This starting freq of the band is unit of kHz */
+typedef enum _ENUM_BAND_T
+{
+    BAND_NULL   = 0000000,
+    BAND_2G4    = 2407000,
+    BAND_5G     = 5000000,
+    BAND_4G9375 = 4937500,
+    BAND_4G89   = 4890000,
+    BAND_4G85   = 4850000,
+    BAND_4G     = 4000000,
+    BAND_5G0025 = 5002500,
+    BAND_4G0025 = 4002500
+} ENUM_BAND_T, *P_ENUM_BAND_T;
+
+/* The following macro to translate channel number to its center freq
+ * in unit of kHz
+ */
+#define CHNL_FREQ_2G(n)         (((n) == 14) ? 2484000 : \
+                                     (BAND_2G4 + 5000 * (n)))
+#define CHNL_FREQ_5G(n)         (BAND_5G + 5000 * (n))
+#define CHNL_FREQ_4G9375(n)     (BAND_4G9375 + 5000 * (n))
+#define CHNL_FREQ_4G89(n)       (BAND_4G89 + 5000 * (n))
+#define CHNL_FREQ_4G85(n)       (BAND_4G85 + 5000 * (n))
+#define CHNL_FREQ_4G(n)         (BAND_4G + 5000 * (n))
+#define CHNL_FREQ_5G0025(n)     (BAND_5G0025 + 5000 * (n))
+#define CHNL_FREQ_4G0025(n)     (BAND_4G0025 + 5000 * (n))
+
+#define CHNL_FREQ(_eBand, _u1Chnl) \
+        (((_eBand) == BAND_2G4 && (_u1Chnl) == 14) ? 2484000 : \
+         ((_eBand) + 5000 * (_u1Chnl)))
+
+#define FREQ_BAND(_u4Freq) \
+        ((_u4Freq) < BAND_4G ? BAND_2G4 : BAND_5G) /* To do: support more bands */
+
+#define FREQ_CHNL(_eBand, _u4Freq) \
+        ((unsigned char)(((_eBand) == BAND_2G4 && (_u4Freq) == 2484000) ? 14 : \
+                  (((_u4Freq) - (_eBand)) / 5000)))
+
+/** channel group category item */
+typedef enum _ENUM_CH_GROUP_ITEM
+{
+    CH_GROUP_ITEM_COMMON = 0x00,
+    CH_GROUP_ITEM_TSSI_CH = 0x01,
+    CH_GROUP_ITEM_NUM
+} ENUM_CH_GROUP_ITEM, *P_ENUM_CH_GROUP_ITEM;
+
+/** channel sub-group category item */
+typedef enum _ENUM_CH_SUB_GROUP_ITEM
+{
+    CH_SUB_GROUP_TSSI_CH = 0,
+    CH_SUB_GROUP_ITEM_NUM
+} ENUM_CH_SUB_GROUP_ITEM, *P_ENUM_CH_SUB_GROUP_ITEM;
+
+
+typedef enum _ENUM_CH_SUB_GROUP_2G4_ITEM
+{
+    CH_SUB_GROUP_2G4_LOW = 0,
+    CH_SUB_GROUP_2G4_MID,
+    CH_SUB_GROUP_2G4_HIGH,
+    CH_SUB_GROUP_2G4_ITEM_NUM
+} ENUM_CH_SUB_GROUP_2G4_ITEM, *P_ENUM_CH_SUB_GROUP_2G4_ITEM;
+
+typedef enum _ENUM_CH_SUB_GROUP_5G_ITEM
+{
+    CH_SUB_GROUP_5G_LOW = 0,
+    CH_SUB_GROUP_5G_HIGH,
+    CH_SUB_GROUP_5G_ITEM_NUM
+} ENUM_CH_SUB_GROUP_5G_ITEM, *P_ENUM_CH_SUB_GROUP_5G_ITEM;
+
+typedef enum _ENUM_CBW_DBW_T
+{
+    CDBW_20,
+    CDBW_40,
+    CDBW_80,
+    CDBW_160,
+    CDBW_80P80,
+    CDBW_5,
+    CDBW_10,
+    CDBW_NUM
+} ENUM_CBW_DBW_T, *P_ENUM_CBW_DBW_T;
+
+/** channel group info structure */
+typedef struct _CH_GROUP_CLASS
+{
+    ENUM_CH_GROUP_ITEM eGroupId;
+    unsigned char u1ChGroupSupportNum;
+    unsigned char u1ChGroupBoundary[CH_GROUP_SUPPORT_MAX_NUM];
+} CH_GROUP_CLASS, *P_CH_GROUP_CLASS;
+
+/** channel power offset group info structure */
+typedef struct _CH_SUB_GROUP_CLASS
+{
+    ENUM_CH_SUB_GROUP_ITEM eGroupId;
+    unsigned char u1ChSubGroupCategoryNum;
+    unsigned char u1ChSubGroupNotOrderedNum;
+    unsigned char u1ChSubGroupBoundary[CH_SUB_GROUP_SUPPORT_MAX_NUM];
+} CH_SUB_GROUP_CLASS, *P_CH_SUB_GROUP_CLASS;
+
+typedef struct
+{
+    FT_H            header;
+    WIFI_CMD_TYPE   type;
+    int             dummy;
+} FT_WM_WIFI_REQ;
+
+typedef struct
+{
+    FT_H            header;
+    WIFI_CMD_TYPE   type;
+    int            drv_status;
+    unsigned char   status;
+} FT_WM_WIFI_CNF;
+typedef struct _INTERPOLATION_CH_BOUND_A_BAND
+{
+    unsigned char lowBoundCh;
+    unsigned char upperBoundCh;
+} INTERPOLATION_CH_BOUND_A_BAND, *P_INTERPOLATION_CH_BOUND_A_BAND;
+
+
+typedef struct _CMD_PL_CAL
+{
+    unsigned int calId;
+    unsigned int action;
+    unsigned int flags;
+    unsigned int inputLen;
+    unsigned int au4Buffer[100];
+} CMD_PL_CAL, *P_CMD_PL_CAL;
+
+typedef struct _SET_OID_STRUC
+{
+    unsigned int  oid;
+    unsigned int  dataLen;
+    unsigned char data[1];
+
+} SET_OID_STRUC, *PSET_OID_STRUC;
+
+
+typedef struct _QUERY_OID_STRUC
+{
+    unsigned int  oid;
+    unsigned int  dataLen;
+    unsigned char data[1];
+
+} QUERY_OID_STRUC, *PQUERY_OID_STRUC;
+
+typedef struct _NVRAM_ACCESS_STRUCT
+{
+    unsigned int  dataLen;
+    unsigned int  dataOffset;
+    unsigned char data[1];
+} NVRAM_ACCESS_STRUCT, *PNVRAM_ACCESS_STRUCT;
+
+typedef union
+{
+    SET_OID_STRUC   SetOidPara;
+    QUERY_OID_STRUC QueryOidPara;
+} OID_STRUC, *POID_STRUC;
+
+typedef struct _HQA_CMD_FRAME
+{
+    unsigned int magicNo;
+    unsigned short type;
+    unsigned short id;
+    unsigned short length;
+    unsigned short sequence;
+    unsigned char data[1];
+} HQA_CMD_FRAME, *P_HQA_CMD_FRAME;
+
+typedef struct _HQA_SET_TX_PATH
+{
+    unsigned int tx_path;
+    unsigned int band_idx;
+} HQA_SET_TX_PATH, *P_HQA_SET_TX_PATH;
+
+typedef struct _HQA_SET_TX_POWER
+{
+    unsigned int power;
+    unsigned int band_idx;
+    unsigned int channel;
+    unsigned int channel_band;
+    unsigned int ant_idx;
+} HQA_SET_TX_POWER, *P_HQA_SET_TX_POWER;
+
+
+typedef struct _HQA_DO_CAL_TEST_ITEM
+{
+    unsigned int item;
+    unsigned int band_idx;
+} HQA_DO_CAL_TEST_ITEM, *P_HQA_DO_CAL_TEST_ITEM;
+
+typedef struct _RECAL_INFO_T
+{
+    unsigned short status;
+    unsigned int u4Count;
+    unsigned int u4CalId[MAX_RECAL_DATA_NUM];
+    unsigned int u4CalAddr[MAX_RECAL_DATA_NUM];
+    unsigned int u4CalValue[MAX_RECAL_DATA_NUM];
+} RECAL_INFO_T, *P_RECAL_INFO_T;
+
+typedef struct _HQA_SET_CH
+{
+    unsigned int ext_id;
+    unsigned int num_param;
+    unsigned int band_idx;
+    unsigned int central_ch0;
+    unsigned int central_ch1;
+    unsigned int sys_bw;
+    unsigned int perpkt_bw;
+    unsigned int pri_sel;
+    unsigned int reason;
+    unsigned int ch_band;
+    unsigned int out_band_freq;
+} HQA_SET_CH, *P_HQA_SET_CH;
+
+
+typedef struct _HQA_PARA_INFO
+{
+    unsigned int wf_idx; /* bit[0]:WF0,bit[1]:WF1,bit[2]:WF0/WF1 */
+    unsigned int dbdcBandIdx;
+    unsigned int chBand; /*0:2,4G , 1:5G*/
+    unsigned int chS1; /* Channel Number in unit of kHz - 20/40/80/160 */
+    unsigned int chS2; /* Channel Number in unit of kHz - 80+80*/
+    ENUM_CBW_DBW_T eCbw;
+    unsigned int power; /* In unit of 0.5 dBm */
+} HQA_PARA_INFO, *P_HQA_PARA_INFO;
+
+WLAN_STATUS wifiNVRAMTssiChOfsAdjust(unsigned int wf, ENUM_BAND_T eBand, unsigned int ch, unsigned int targetPwr, unsigned int MeanPwr);
+int META_WIFI_init(void);
+void META_WIFI_deinit(void);
+void META_WIFI_OP(FT_WM_WIFI_REQ *req, char *peer_buf, unsigned short peer_len);
+WLAN_STATUS wifiHqaGetDumpReCal(unsigned int item, unsigned int dbdcBandIdx, P_RECAL_INFO_T prReCalInfo);
+WLAN_STATUS wifiHqaDoCalibrationTestItem(unsigned int item, unsigned int dbdcBandIdx);
+#endif
diff --git a/src/devtools/meta/src/adaptor/wifi/meta_wifi_test.c b/src/devtools/meta/src/adaptor/wifi/meta_wifi_test.c
new file mode 100644
index 0000000..0c1c47c
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/meta_wifi_test.c
@@ -0,0 +1,759 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include "meta_wifi.h"
+#include <cutils/log.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#ifdef LOG_TAG
+#undef  LOG_TAG
+#endif
+#define LOG_TAG         "WIFI_META "
+
+static void wifi_info_callback(FT_WM_WIFI_CNF *cnf, void *buf, unsigned int size)
+{
+    unsigned int i;
+    char *type[] = { "WIFI_CMD_SET_OID", "WIFI_CMD_QUERY_OID", "WIFI_CMD_NVRAM_WRITE_ACCESS", "WIFI_CMD_NVRAM_READ_ACCESS"
+                     , "WIFI_CMD_INIT", "WIFI_CMD_DEINIT", "WIFI_CMD_SCRIPT", "WIFI_CMD_HQA", "WIFI_CMD_PL_CALIBRATION"
+                   };
+    OID_STRUC *poid;
+
+    P_CMD_PL_CAL prCmdPlCal;
+
+    if (buf == NULL)
+    {
+        printf("[META_WIFI] %s is Null!\n", __func__);
+        return;
+    }
+
+    printf("[META_WIFI] <CNF> %s, Drv Status: %d, Status: %d\n", type[cnf->type],
+           cnf->drv_status, cnf->status);
+
+    switch (cnf->type)
+    {
+        case WIFI_CMD_SET_OID:
+        case WIFI_CMD_QUERY_OID:
+            {
+                poid = (OID_STRUC *)buf;
+                printf("META_WIFI] <CNF> OID: %d, data len: %d\n",
+                       poid->QueryOidPara.oid, poid->QueryOidPara.dataLen);
+
+                for (i = 0; i < poid->QueryOidPara.dataLen; i++)
+                {
+                    printf("META_WIFI] <CNF> Data[%d] = 0x%x\n",
+                           i, poid->QueryOidPara.data[i]);
+                }
+
+                break;
+            }
+
+        case WIFI_CMD_SCRIPT:
+            {
+                printf("[META_WIFI] <CNF> DataBuf(%d)= %s\n", size, buf);
+                break;
+            }
+
+        case WIFI_CMD_PL_CALIBRATION:
+            {
+                prCmdPlCal = (P_CMD_PL_CAL)buf;
+                printf("[META_WIFI] <WIFI_CMD_PL_CALIBRATION> id=%d,act=%d,Len=%d\n",
+                       prCmdPlCal->calId,
+                       prCmdPlCal->action,
+                       prCmdPlCal->inputLen);
+
+                for (i = 0; i < prCmdPlCal->inputLen; i++)
+                {
+                    printf("META_WIFI] Data[%d] = 0x%08x\n",
+                           i, prCmdPlCal->au4Buffer[i]);
+                }
+
+                break;
+            }
+
+        default:
+            {
+                printf("[META_WIFI] %s is Null!\n", __func__);
+                return;
+            }
+    }
+}
+
+void DoTestTssiChOffset()
+{
+    FT_WM_WIFI_REQ req;
+
+    CMD_PL_CAL rCmdPlCal;
+    P_HQA_CMD_FRAME prHqaCmd;
+    HQA_SET_TX_PATH rSetTxPath;
+    HQA_SET_TX_POWER rSetTxPower;
+    HQA_SET_CH rSetCh;
+    int u4hqaCmdLen = 0;
+    int ext_id = 0;
+
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(HQA_SET_CH);
+    prHqaCmd = (P_HQA_CMD_FRAME)malloc(u4hqaCmdLen);
+
+    memset(&req, 0, sizeof(FT_WM_WIFI_REQ));
+    memset(prHqaCmd, 0, u4hqaCmdLen);
+
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_OPEN_ADAPTER); //OPEN ADAPTER
+    prHqaCmd->length = 0;
+    prHqaCmd->sequence = 1;
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================HQA OPEN ADAPTER DONE====================\n");
+
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_TX_PWR;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_START;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = 0;
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================PL TXPWR -START DONE====================\n");
+
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_SetTxPath);
+    prHqaCmd->length = htons(sizeof(rSetTxPath));
+    prHqaCmd->sequence = 1;
+    rSetTxPath.tx_path = htonl(0x01);
+    rSetTxPath.band_idx = htonl(0x00);
+    memcpy(&prHqaCmd->data[0], &rSetTxPath, sizeof(rSetTxPath));
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetTxPath);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R1:HQA Set Tx Path DONE====================\n");
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_SetTxPowerExt);
+    prHqaCmd->length = htons(sizeof(rSetTxPath));
+    prHqaCmd->sequence = 2;
+    rSetTxPower.power = htonl(0x1E);
+    rSetTxPower.band_idx = htonl(0x00);
+    rSetTxPower.channel = htonl(0x00);
+    rSetTxPower.channel_band = htonl(0x00);
+    rSetTxPower.ant_idx = htonl(0x00);
+    memcpy(&prHqaCmd->data[0], &rSetTxPower, sizeof(rSetTxPower));
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetTxPower);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R1:HQA Set Tx Power DONE====================\n");
+
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_EXTEND);
+    prHqaCmd->length = htons(sizeof(rSetCh));
+    prHqaCmd->sequence = 3;
+    rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+    rSetCh.num_param = htonl(0x06);
+    rSetCh.band_idx = htonl(0x00);
+    rSetCh.central_ch0 = htonl(7); //channel 7
+    rSetCh.central_ch1 = htonl(0x00);
+    rSetCh.sys_bw = htonl(0);
+    rSetCh.perpkt_bw = htonl(0);
+    rSetCh.ch_band = htonl(0); //0:2.4G,1:5G
+    memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R1:HQA DBDC Set Channel DONE====================\n");
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_EXTEND); //OPEN ADAPTER
+    prHqaCmd->length = htons(sizeof(unsigned int));
+    prHqaCmd->sequence = 4;
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME);
+    ext_id = htonl(HQA_CMD_DBDCStartTx); //HQA_DBDCSetChannel
+    memcpy(&prHqaCmd->data[0], &ext_id, sizeof(ext_id));
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R1:HQA START TX DONE====================\n");
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_EXTEND); //OPEN ADAPTER
+    prHqaCmd->length = htons(sizeof(unsigned int));
+    prHqaCmd->sequence = 4;
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME);
+    ext_id = htonl(HQA_CMD_DBDCStopTx); //HQA_DBDCSetChannel
+    memcpy(&prHqaCmd->data[0], &ext_id, sizeof(ext_id));
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R1:HQA STOP TX DONE====================\n");
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_TX_PWR;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_ADJUST;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = 1;
+    rCmdPlCal.au4Buffer[0] = 0x1000; //Tool Measurement(S23.8)
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================PL ADJUST DONE====================\n");
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_SetTxPath);
+    prHqaCmd->length = htons(sizeof(rSetTxPath));
+    prHqaCmd->sequence = 1;
+    rSetTxPath.tx_path = htonl(0x01);
+    rSetTxPath.band_idx = htonl(0x00);
+    memcpy(&prHqaCmd->data[0], &rSetTxPath, sizeof(rSetTxPath));
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetTxPath);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R2:HQA Set Tx Path DONE====================\n");
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_SetTxPowerExt);
+    prHqaCmd->length = htons(sizeof(rSetTxPath));
+    prHqaCmd->sequence = 2;
+    rSetTxPower.power = htonl(0x16);
+    rSetTxPower.band_idx = htonl(0x00);
+    rSetTxPower.channel = htonl(0x00);
+    rSetTxPower.channel_band = htonl(0x00);
+    rSetTxPower.ant_idx = htonl(0x00);
+    memcpy(&prHqaCmd->data[0], &rSetTxPower, sizeof(rSetTxPower));
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetTxPower);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R2:HQA Set Tx Power DONE====================\n");
+
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_EXTEND);
+    prHqaCmd->length = htons(sizeof(rSetCh));
+    prHqaCmd->sequence = 3;
+    rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+    rSetCh.num_param = htonl(0x06);
+    rSetCh.band_idx = htonl(0x00);
+    rSetCh.central_ch0 = htonl(6); //channel 6
+    rSetCh.central_ch1 = htonl(0x00);
+    rSetCh.sys_bw = htonl(0);
+    rSetCh.perpkt_bw = htonl(0);
+    rSetCh.ch_band = htonl(0); //0:2.4G,1:5G
+    memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R2:HQA DBDC Set Channel DONE====================\n");
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_EXTEND); //OPEN ADAPTER
+    prHqaCmd->length = htons(sizeof(unsigned int));
+    prHqaCmd->sequence = 4;
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME);
+    ext_id = htonl(HQA_CMD_DBDCStartTx); //HQA_DBDCSetChannel
+    memcpy(&prHqaCmd->data[0], &ext_id, sizeof(ext_id));
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R2:HQA START TX DONE====================\n");
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_EXTEND); //OPEN ADAPTER
+    prHqaCmd->length = htons(sizeof(unsigned int));
+    prHqaCmd->sequence = 4;
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME);
+    ext_id = htonl(HQA_CMD_DBDCStopTx); //HQA_DBDCSetChannel
+    memcpy(&prHqaCmd->data[0], &ext_id, sizeof(ext_id));
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R2:HQA STOP TX DONE====================\n");
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_TX_PWR;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_END;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = 1;
+    rCmdPlCal.au4Buffer[0] = 0; /*success*/
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================PL TXPWR -FINISH DONE====================\n");
+
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_CLOSE_ADAPTER); //CLOSE  ADAPTER
+    prHqaCmd->length = 0;
+    prHqaCmd->sequence = 2;
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================CLOSE ADAPTER Done====================\n");
+
+
+#if 1
+    int inputCh[] = {3, 0, 4, 1, 4, 7, 13};
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_TX_PWR;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_INTERPOLAT;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = sizeof(inputCh) / sizeof(int);
+    rCmdPlCal.au4Buffer[0] = 0; /*success*/
+    memcpy(&rCmdPlCal.au4Buffer[0], &inputCh[0], sizeof(inputCh));
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================PL TXPWR - Interpolation ====================\n");
+#endif
+
+    FREEIF(prHqaCmd);
+
+}
+void DoTest2G4Interpolation()
+{
+
+    FT_WM_WIFI_REQ req;
+
+    CMD_PL_CAL rCmdPlCal;
+    memset(&rCmdPlCal, 0, sizeof(rCmdPlCal));
+
+    int inputCh[] = {3, 0, 4, 1, 4, 7, 13};
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_TX_PWR;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_INTERPOLAT;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = sizeof(inputCh) / sizeof(int);
+    rCmdPlCal.au4Buffer[0] = 0; /*success*/
+    memcpy(&rCmdPlCal.au4Buffer[0], &inputCh[0], sizeof(inputCh));
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================PL TXPWR - 2.4G Interpolation ====================\n");
+
+}
+void DoTest5GInterpolation()
+{
+
+    FT_WM_WIFI_REQ req;
+
+    CMD_PL_CAL rCmdPlCal;
+    memset(&rCmdPlCal, 0, sizeof(rCmdPlCal));
+
+    int inputCh[] = {2, 0, 14, 36, 48, 52, 64, 100, 112, 116, 128, 132, 144, 149, 165, 184, 192};
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_TX_PWR;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_INTERPOLAT;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = sizeof(inputCh) / sizeof(int);
+    rCmdPlCal.au4Buffer[0] = 0; /*success*/
+    memcpy(&rCmdPlCal.au4Buffer[0], &inputCh[0], sizeof(inputCh));
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================PL TXPWR - 5G Interpolation ====================\n");
+}
+void DoTestDNLCal()
+{
+
+    FT_WM_WIFI_REQ req;
+    P_HQA_CMD_FRAME prHqaCmd;
+    HQA_SET_CH rSetCh;
+    HQA_SET_TX_PATH rSetTxPath;
+    CMD_PL_CAL rCmdPlCal;
+
+    int u4hqaCmdLen = 0;
+
+    printf("====================DoTestDNLCal====================\n");
+
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(HQA_SET_CH);
+    prHqaCmd = (P_HQA_CMD_FRAME)malloc(u4hqaCmdLen);
+
+
+    memset(&req, 0, sizeof(FT_WM_WIFI_REQ));
+    memset(prHqaCmd, 0, u4hqaCmdLen);
+
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_OPEN_ADAPTER); //OPEN ADAPTER
+    prHqaCmd->length = 0;
+    prHqaCmd->sequence = 1;
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================HQA OPEN ADAPTER DONE====================\n");
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_DNL_CAL;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_START;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = 0;
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================PL DNL -START DONE====================\n");
+
+
+#if 1
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_SetTxPath);
+    prHqaCmd->length = htons(sizeof(rSetTxPath));
+    prHqaCmd->sequence = 1;
+    rSetTxPath.tx_path = htonl(0x01);
+    rSetTxPath.band_idx = htonl(0x00);
+    memcpy(&prHqaCmd->data[0], &rSetTxPath, sizeof(rSetTxPath));
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetTxPath);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R1:HQA Set Tx Path DONE====================\n");
+
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_EXTEND);
+    prHqaCmd->length = htons(sizeof(rSetCh));
+    prHqaCmd->sequence = 3;
+    rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+    rSetCh.num_param = htonl(0x06);
+    rSetCh.band_idx = htonl(0x00);
+    rSetCh.central_ch0 = htonl(7); //channel 6
+    rSetCh.central_ch1 = htonl(0x00);
+    rSetCh.sys_bw = htonl(0);
+    rSetCh.perpkt_bw = htonl(0);
+    rSetCh.ch_band = htonl(0); //0:2.4G,1:5G
+    memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R1:HQA DBDC Set Channel DONE====================\n");
+
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_DNL_CAL;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_ADJUST;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = 0;
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================DNL adjust done!====================\n");
+
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_EXTEND);
+    prHqaCmd->length = htons(sizeof(rSetCh));
+    prHqaCmd->sequence = 3;
+    rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+    rSetCh.num_param = htonl(0x06);
+    rSetCh.band_idx = htonl(0x00);
+    rSetCh.central_ch0 = htonl(192); //channel 8
+    rSetCh.central_ch1 = htonl(0x00);
+    rSetCh.sys_bw = htonl(0);
+    rSetCh.perpkt_bw = htonl(0);
+    rSetCh.ch_band = htonl(1); //0:2.4G,1:5G
+    memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R1:HQA DBDC Set Channel DONE====================\n");
+
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_DNL_CAL;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_ADJUST;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = 0;
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================DNL adjust done!====================\n");
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_EXTEND);
+    prHqaCmd->length = htons(sizeof(rSetCh));
+    prHqaCmd->sequence = 3;
+    rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+    rSetCh.num_param = htonl(0x06);
+    rSetCh.band_idx = htonl(0x00);
+    rSetCh.central_ch0 = htonl(100); //channel 100
+    rSetCh.central_ch1 = htonl(0x00);
+    rSetCh.sys_bw = htonl(0);
+    rSetCh.perpkt_bw = htonl(0);
+    rSetCh.ch_band = htonl(1); //0:2.4G,1:5G
+    memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R1:HQA DBDC Set Channel DONE====================\n");
+
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_DNL_CAL;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_ADJUST;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = 0;
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================DNL adjust done!====================\n");
+
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_DNL_CAL;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_END;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = 0;
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================DNL END done!====================\n");
+
+
+#endif
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_CLOSE_ADAPTER); //CLOSE  ADAPTER
+    prHqaCmd->length = 0;
+    prHqaCmd->sequence = 2;
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================CLOSE ADAPTER Done====================\n");
+
+
+    FREEIF(prHqaCmd);
+
+}
+void DoTestLnaGainCal()
+{
+
+    FT_WM_WIFI_REQ req;
+    P_HQA_CMD_FRAME prHqaCmd;
+    HQA_SET_CH rSetCh;
+    HQA_SET_TX_PATH rSetTxPath;
+    CMD_PL_CAL rCmdPlCal;
+
+    int u4hqaCmdLen = 0;
+
+    printf("====================DoTestLnaGainCal====================\n");
+
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(HQA_SET_CH);
+    prHqaCmd = (P_HQA_CMD_FRAME)malloc(u4hqaCmdLen);
+
+
+    memset(&req, 0, sizeof(FT_WM_WIFI_REQ));
+    memset(prHqaCmd, 0, u4hqaCmdLen);
+
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_OPEN_ADAPTER); //OPEN ADAPTER
+    prHqaCmd->length = 0;
+    prHqaCmd->sequence = 1;
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================HQA OPEN ADAPTER DONE====================\n");
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_LNA_GAIN_CAL;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_START;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = 0;
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================PL LNA GAIN CAL -START DONE====================\n");
+
+
+#if 1
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_SetTxPath);
+    prHqaCmd->length = htons(sizeof(rSetTxPath));
+    prHqaCmd->sequence = 1;
+    rSetTxPath.tx_path = htonl(0x01);
+    rSetTxPath.band_idx = htonl(0x00);
+    memcpy(&prHqaCmd->data[0], &rSetTxPath, sizeof(rSetTxPath));
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetTxPath);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R1:HQA Set Tx Path DONE====================\n");
+
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_EXTEND);
+    prHqaCmd->length = htons(sizeof(rSetCh));
+    prHqaCmd->sequence = 3;
+    rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+    rSetCh.num_param = htonl(0x06);
+    rSetCh.band_idx = htonl(0x00);
+    rSetCh.central_ch0 = htonl(7); //channel 6
+    rSetCh.central_ch1 = htonl(0x00);
+    rSetCh.sys_bw = htonl(0);
+    rSetCh.perpkt_bw = htonl(0);
+    rSetCh.ch_band = htonl(0); //0:2.4G,1:5G
+    memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R1:HQA DBDC Set Channel DONE====================\n");
+
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_LNA_GAIN_CAL;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_ADJUST;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = 0;
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================LNA GAIN CAL adjust done!====================\n");
+
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_EXTEND);
+    prHqaCmd->length = htons(sizeof(rSetCh));
+    prHqaCmd->sequence = 3;
+    rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+    rSetCh.num_param = htonl(0x06);
+    rSetCh.band_idx = htonl(0x00);
+    rSetCh.central_ch0 = htonl(192); //channel 8
+    rSetCh.central_ch1 = htonl(0x00);
+    rSetCh.sys_bw = htonl(0);
+    rSetCh.perpkt_bw = htonl(0);
+    rSetCh.ch_band = htonl(1); //0:2.4G,1:5G
+    memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R1:HQA DBDC Set Channel DONE====================\n");
+
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_LNA_GAIN_CAL;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_ADJUST;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = 0;
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================LNA GAIN CAL adjust done!====================\n");
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_EXTEND);
+    prHqaCmd->length = htons(sizeof(rSetCh));
+    prHqaCmd->sequence = 3;
+    rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+    rSetCh.num_param = htonl(0x06);
+    rSetCh.band_idx = htonl(0x00);
+    rSetCh.central_ch0 = htonl(100); //channel 100
+    rSetCh.central_ch1 = htonl(0x00);
+    rSetCh.sys_bw = htonl(0);
+    rSetCh.perpkt_bw = htonl(0);
+    rSetCh.ch_band = htonl(1); //0:2.4G,1:5G
+    memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+    u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================R1:HQA DBDC Set Channel DONE====================\n");
+
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_LNA_GAIN_CAL;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_ADJUST;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = 0;
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================LNA GAIN CAL adjust done!====================\n");
+
+
+    req.type = WIFI_CMD_PL_CALIBRATION;
+    rCmdPlCal.calId =  WIFI_PL_CAL_LNA_GAIN_CAL;
+    rCmdPlCal.action = TX_PWR_CAL_ACT_END;
+    rCmdPlCal.flags = FALSE;
+    rCmdPlCal.inputLen = 0;
+    META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+    printf("====================LNA GAIN CAL END done!====================\n");
+
+
+#endif
+
+    req.type = WIFI_CMD_HQA;
+    prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+    prHqaCmd->type = 0;
+    prHqaCmd->id = htons(HQA_CMD_CLOSE_ADAPTER); //CLOSE  ADAPTER
+    prHqaCmd->length = 0;
+    prHqaCmd->sequence = 2;
+    META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+    printf("====================CLOSE ADAPTER Done====================\n");
+
+
+    FREEIF(prHqaCmd);
+
+}
+
+
+void doScript(void)
+{
+    FT_WM_WIFI_REQ req;
+
+    memset(&req, 0, sizeof(FT_WM_WIFI_REQ));
+
+    req.type = WIFI_CMD_SCRIPT;
+
+    char *cmd2 = "adb shell iwpriv driver set_mcr 2011 2011";
+    printf("[META_WIFI]  WIFI_CMD_SCRIPT execute:%s sizeof(%lu)\n", cmd2, strlen(cmd2));
+    META_WIFI_OP(&req, cmd2, strlen(cmd2));
+
+    char *cmd3 = "adb shell iwpriv driver get_mcr 0x820F4020";
+    printf("[META_WIFI]  WIFI_CMD_SCRIPT execute:%s sizeof(%lu)\n", cmd3, strlen(cmd3));
+    META_WIFI_OP(&req, cmd3, strlen(cmd3));
+
+
+    char *cmd4 = "adb shell iwpriv driver set_mcr 0x820F4020 0x14141414";
+    printf("[META_WIFI]  WIFI_CMD_SCRIPT execute:%s sizeof(%lu)\n", cmd4, strlen(cmd4));
+    META_WIFI_OP(&req, cmd4, strlen(cmd4));
+
+
+    char *cmd5 = "adb shell iwpriv driver get_mcr 0x820F4020";
+    printf("[META_WIFI]  WIFI_CMD_SCRIPT execute:%s sizeof(%lu)\n", cmd5, strlen(cmd5));
+    META_WIFI_OP(&req, cmd5, strlen(cmd5));
+
+    //GET_NOISE
+    char *cmd6 = "adb shell iwpriv driver get_noise";
+    printf("[META_WIFI]  WIFI_CMD_SCRIPT execute:%s sizeof(%lu)\n", cmd6, strlen(cmd6));
+    META_WIFI_OP(&req, cmd6, strlen(cmd6));
+
+    //GET_NOISE
+    char *cmd7 = "adb shell iwpriv get_noise";
+    printf("[META_WIFI]  WIFI_CMD_SCRIPT execute:%s sizeof(%lu)\n", cmd7, strlen(cmd7));
+    META_WIFI_OP(&req, cmd7, strlen(cmd7));
+
+
+}
+int main()
+{
+
+    META_WIFI_Register(wifi_info_callback);
+
+    if (META_WIFI_init() == false)
+    {
+        printf("WLAN init failed\n");
+        return -1;
+    }
+
+    /*Test Case: TSSI DNL OFFSET CALIBRATION*/
+    //DoTestDNLCal();
+
+    /*Test Case: TSSI Channel offset compensation*/
+    //DoTestTssiChOffset();
+
+    /*Test Case: LNA GAIN CAL*/
+    //DoTestLnaGainCal();
+
+    DoTest2G4Interpolation();
+
+
+    /*Test Case: Tssi 5G RF Group Interpolation*/
+    DoTest5GInterpolation();
+
+    printf("Sleep 1s\n");
+    usleep(1 * 1000 * 1000);
+
+    META_WIFI_deinit();
+    META_WIFI_Register(NULL);
+
+    return 0;
+}
+
diff --git a/src/devtools/meta/src/adaptor/wifi/type.h b/src/devtools/meta/src/adaptor/wifi/type.h
new file mode 100644
index 0000000..3b34a44
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/type.h
@@ -0,0 +1,52 @@
+/*******************************************************************************
+** Copyright (c) 2005 MediaTek Inc.
+**
+** All rights reserved. Copying, compilation, modification, distribution
+** or any other use whatsoever of this material is strictly prohibited
+** except in accordance with a Software License Agreement with
+** MediaTek Inc.
+********************************************************************************
+*/
+#ifndef _TYPE_H
+#define _TYPE_H
+
+
+#ifndef NULL
+#define NULL  0
+#endif
+
+
+#if !defined(TRUE)
+#define TRUE true
+#endif
+
+#if !defined(FALSE)
+#define FALSE false
+#endif
+
+#define IN
+#define OUT
+
+#define DLL_FUNC
+
+#define TEXT
+
+#define BIT(n)                          ((unsigned int) 1 << (n))
+#define BITS(m,n)                       (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n)))
+
+/* Type definition for WLAN STATUS */
+#define WLAN_STATUS                 unsigned int
+#define P_WLAN_STATUS               unsigned int*
+
+#ifndef RX_ANT_
+#define RX_ANT_
+typedef enum
+{
+    AGC_RX_ANT_SEL,
+    MPDU_RX_ANT_SEL,
+    FIXED_0,
+    FIXED_1
+} RX_ANT_SEL;
+#endif
+
+#endif
diff --git a/src/devtools/meta/src/common/inc/CmdTarget.h b/src/devtools/meta/src/common/inc/CmdTarget.h
new file mode 100644
index 0000000..d0549be
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/CmdTarget.h
@@ -0,0 +1,51 @@
+#ifndef _CMD_TARGET_H_
+#define _CMD_TARGET_H_
+
+#include "Frame.h"
+
+class CmdTarget
+{
+public:
+	CmdTarget(unsigned short);
+	virtual ~CmdTarget(void);
+
+public:
+	virtual void exec(Frame*);
+	
+	unsigned short getId() const
+	{
+		return m_myId;
+	}
+
+	unsigned short getToken() const
+	{
+		return m_token;
+	}
+
+	void setToken(unsigned short token) 
+	{
+		m_token = token;
+	}
+
+	int getInitState() const
+	{
+		return m_isInited;
+	}
+protected:
+	virtual int init(Frame*);
+	virtual void deinit();
+
+private:
+	unsigned short	m_myId;
+	int	m_isInited;
+	unsigned short  m_token;
+};
+/*
+template <typename _Tx>
+_Tx *getInstance()
+{
+	static _Tx _inst;
+	return &_inst;
+}
+*/
+#endif	// _CMD_TARGET_H_
diff --git a/src/devtools/meta/src/common/inc/Context.h b/src/devtools/meta/src/common/inc/Context.h
new file mode 100644
index 0000000..de56af9
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/Context.h
@@ -0,0 +1,135 @@
+#ifndef _CONETXT_H_
+#define _CONETXT_H_
+
+#include "MetaPub.h"
+
+
+#define MD1_INDEX 0x01
+#define MD2_INDEX 0x02
+#define MD3_INDEX 0x04
+#define MD5_INDEX 0x10
+
+
+typedef enum
+{
+	MODEM_AP_TST = 0,
+	MODEM_DHL = 1,
+	MODEM_6292 = 2,
+	MODEM_6293 = 3,
+	MODEM_6295 = 4,
+	MODEM_END = 5,	
+}Modem_Hw_Version;
+
+
+//#define BOOTMODE_PATH "/sys/class/BOOT/BOOT/boot/boot_mode"
+#define BOOTMODE_PATH "/proc/device-tree/chosen/atag,boot"    //for common kernel
+//struct tag_bootmode {
+//u32 size;
+//u32 tag;
+//u32 bootmode;
+//u32 boottype;
+//}; 
+
+#define UNKNOWN_BOOT -1
+#define NORMAL_BOOT 0
+#define META_BOOT 1
+
+//Jade
+//#define FLAG_PATH "/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/proinfo" 
+//Bianco
+#define FLAG_PATH "/dev/block/platform/bootdevice/by-name/proinfo"
+#define OFFSET_ATM (64+4*10+170+64+4+8)
+#define OFFSET_METALOG (349)
+#define KEY1 12345678
+#define KEY2 23131123
+#define ENCRYPT_LENTH 8
+
+#define USBONLINE_STATUS_PATH  "/sys/class/power_supply/usb/online"
+
+class Modem;
+class CmdTarget;
+class UsbRxWatcher;
+class MSocket;
+
+Modem * createModem(const char *ccci, unsigned short id);
+Modem * createModem(unsigned short id);
+void destroyModem(Modem *p);
+
+Modem * getModem(unsigned short id);
+CmdTarget * getModule(unsigned short id);
+unsigned int getMdmType();
+unsigned int getActiveMdmId();
+unsigned int getMdmNumber();
+signed int getModemHandle(unsigned short id); 
+
+unsigned int dumpData(const unsigned char* con, int length);
+unsigned int dumpDataInHexString(const unsigned char* con, int length, unsigned int bytesPerRow=16);
+unsigned int getFileSize(int fd);
+const char* makepath(unsigned char file_ID);
+void createModemThread(unsigned short modemIndex,int usbUsb);
+void destroyModemThread(unsigned short modemIndex);
+void createSerPortThread();
+void destroySerPortThread();
+void createAllModemThread();
+void destroyAllModemThread();
+
+void setLogLevel(unsigned int level);
+unsigned int getLogLevel();
+
+int getModemProtocol(unsigned short modemIndex, void* modem_capa);
+int getMDChType(unsigned short modemIndex);
+
+unsigned int getMDMode(void);
+void setMDMode(unsigned int modem_boot_mode);
+
+void setActiveATModem(unsigned int activeATModemId);
+unsigned int getActiveATModem();
+int getIOCPort(unsigned int nModemIndex,int & bDataDevice);
+int getBootMode();
+void queryNormalModeTestFlag();
+int getNormalModeTestFlag();
+int setNormalModeTestFlag(int flag);
+
+int setProductInfo(int type, int flag, int offset);
+int getProductInfo(int type, int offset);
+
+
+int getPropValue(const char *key);
+int getDataChannelType();
+
+void queryWifiPara(int argc, char** argv);
+WIFI_PARA getWifiPara();
+
+void destroyVirtualRxThread();
+void createVirtualRxThread();
+void setVirtualRxWatcher(UsbRxWatcher * virtualRxWatcher);
+
+MSocket * createSocket(unsigned int type);
+MSocket * getSocket(unsigned int type);
+void delSocket(unsigned int type);
+
+void destroyContext();
+
+int getLoadType();
+int getModemHwVersion(unsigned short modemIndex);
+
+void setATRespFlag(int atFlag);
+int getATRespFlag();
+
+int notifyModemDoRFByATCI();
+int ChangeModemMode(int mode);
+
+void writeBootprof(char * str);
+int writePortIndex();
+
+int readSys_int(char const * path);
+unsigned int checkMdStatus();
+
+void SetDataCompressStatus(unsigned int enable);
+unsigned int GetDataCompressStatus();
+
+void HandleSocketCmd(char* socket_cmd);
+void setCurrentMdMode(int mdMode);
+
+
+#endif	// _CONETXT_H_
diff --git a/src/devtools/meta/src/common/inc/Device.h b/src/devtools/meta/src/common/inc/Device.h
new file mode 100644
index 0000000..1590c5e
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/Device.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <pthread.h>
+#include "MetaPub.h"
+
+
+#define NULL_FILE_DESCRIPTOR (-1)	// 0 or -1 ???
+
+class IDevWatcher
+{
+public:
+	virtual signed int onReceived(
+		 unsigned char*, unsigned int) = 0;
+	virtual ~IDevWatcher(void) = 0;
+};
+
+class Device
+{
+public:
+	Device(void);
+	virtual ~Device(void);
+
+public:
+	virtual signed int read(unsigned char*, unsigned int);
+	virtual signed int write(const unsigned char*, unsigned int);
+	virtual void update();
+	virtual void close();
+    void waitForThreadExit();
+	void setExitFlag(unsigned int exitFlag);
+
+	signed int pump(IDevWatcher*);
+	signed int pumpAsync(IDevWatcher*);
+	signed int getDevHandle() const
+	{
+		return m_fd;
+	}
+	
+
+private:
+	static void *ThreadProc(void*);
+	unsigned int m_exitFlag;
+	unsigned char *m_buf;
+
+protected:
+	signed int m_fd;
+	pthread_t m_thread;
+	IDevWatcher *m_pWatcher;
+	pthread_mutex_t m_wMutex;
+	
+};
diff --git a/src/devtools/meta/src/common/inc/DriverInterface.h b/src/devtools/meta/src/common/inc/DriverInterface.h
new file mode 100644
index 0000000..9c093fe
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/DriverInterface.h
@@ -0,0 +1,1439 @@
+
+#ifndef _FT_DRIVERINTERFACE_H_
+#define _FT_DRIVERINTERFACE_H_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include "MetaPub.h"
+
+//WCN
+
+#ifdef FT_WIFI_FEATURE
+#include "meta_wifi_para.h"
+#endif
+
+#ifdef FT_GPS_FEATURE
+#include "meta_gps_para.h"
+#endif
+
+#ifdef FT_NFC_FEATURE
+#include "meta_nfc_para.h"
+#endif
+
+#ifdef FT_BT_FEATURE
+#include "meta_bt_para.h"
+#endif
+#ifdef FT_FM_FEATURE
+#include "meta_fm_para.h"
+#endif
+
+#ifdef FT_RAT_FEATURE
+#include "meta_rat_para.h"
+#endif
+
+#ifdef FT_MSIM_FEATURE
+#include "meta_msim_para.h"
+#endif
+
+//MM
+#ifdef FT_AUDIO_FEATURE
+#include "meta_audio_para.h"
+#endif
+
+#ifdef FT_MATV_FEATURE
+#include "meta_matv_para.h"
+#endif
+
+#ifdef FT_DRM_KEY_MNG_FEATURE
+#include "meta_drmkey_install_para.h"
+#endif
+
+#ifdef FT_GAMMA_FEATURE
+#include "meta_gamma_para.h"
+#endif
+
+#ifdef FT_ATTESTATION_KEY_FEATURE
+#include "kmsetkey.h"
+#endif
+
+#ifdef IS_SUPPORT_SP
+//NVRAM
+#include "libfile_op.h"
+#endif
+
+#ifdef FT_NVRAM_FEATURE
+#include "libfile_op.h"
+#include "Meta_APEditor_Para.h"
+#endif
+
+#ifdef FT_SYSENV_SUPPORT
+#include "sysenv_utils.h"
+#endif
+	
+typedef struct
+{
+	unsigned int	file_size;
+	unsigned char	file_ID;
+	unsigned char	stage;
+} FT_STREAM_BLOCK;
+
+typedef struct
+{
+    FT_H    header;
+    char    buffer[1024];
+    int     count;
+    int     mode;
+} FT_NVRAM_BACKUP_REQ;
+
+typedef struct
+{
+    FT_H            header;
+    FT_STREAM_BLOCK block;
+    unsigned char   status;
+} FT_NVRAM_BACKUP_CNF;
+
+typedef struct
+{
+    FT_H            header;
+    FT_STREAM_BLOCK block;
+} FT_NVRAM_RESTORE_REQ;
+
+typedef struct
+{
+	FT_H		header;
+	unsigned char	status;
+} FT_NVRAM_RESTORE_CNF;
+
+
+//Basic
+typedef struct
+{
+    FT_H			header;					
+    unsigned int	dummy;						
+} FT_IS_ALIVE_REQ;
+
+typedef struct
+{
+    FT_H			header;						
+    unsigned int	dummy;						
+} FT_IS_ALIVE_CNF;
+
+typedef struct
+{
+    FT_H    header;
+} FT_VER_INFO_REQ;
+
+typedef struct
+{
+    FT_H    header;			
+    unsigned char   bb_chip[64];
+    unsigned char   eco_ver[4];
+    unsigned char   sw_time[64];
+    unsigned char   dsp_fw[64];
+    unsigned char   rsc_ver[64];
+    unsigned char   sw_ver[64];
+    unsigned char   hw_ver[64];
+    unsigned char   melody_ver[64];
+    unsigned char	status;	
+} FT_VER_INFO_CNF;
+
+typedef struct
+{
+    FT_H		 header;		//ft header
+} FT_VER_INFO_V2_REQ;
+
+typedef struct
+{
+    FT_H		header;			//ft header
+    unsigned char	bb_chip[64];
+    unsigned char	eco_ver[4];
+    unsigned char	sw_time[64];
+    unsigned char	dsp_fw[64];
+    unsigned char	dsp_patch[64];
+    unsigned char	sw_ver[64];
+    unsigned char	hw_ver[64];
+    unsigned char	melody_ver[64];
+    unsigned char    build_disp_id[64];
+    unsigned char	 status;	//ft status: 0 is success
+} FT_VER_INFO_V2_CNF;
+
+
+typedef enum {
+    FT_SHUTDOWN_OP_POWEROFF = 0,
+    FT_SHUTDOWN_OP_REBOOT,
+    FT_SHUTDOWN_OP_ATMDISCONNECT,
+    FT_SHUTDOWN_OP_WAITUSB,
+    FT_SHUTDOWN_OP_END = 0x0fffffff
+} FT_SHUTDOWN_OP;
+
+
+typedef struct
+{
+	FT_H header;
+	unsigned int dummy; 
+}FT_POWER_OFF_REQ;
+
+typedef struct
+{
+    FT_H            header;
+    unsigned int    delay;
+    unsigned int    dummy;
+} FT_META_REBOOT_REQ;
+
+typedef struct
+{
+	FT_H header;
+	unsigned char tag[64];
+}FT_BUILD_PROP_REQ;
+
+typedef struct
+{
+	FT_H header;
+	unsigned char content[128];
+	int		status;
+}FT_BUILD_PROP_CNF;
+
+typedef struct
+{
+    FT_H            header;
+    unsigned int    dummy;               
+} FT_GET_CHIPID_REQ;
+
+typedef struct
+{
+    FT_H            header;
+    unsigned char   chipId[17];
+    unsigned char   status;
+} FT_GET_CHIPID_CNF;
+
+//Sensor
+#ifdef FT_GSENSOR_FEATURE
+#include "meta_gsensor_para.h"
+#endif
+#ifdef FT_MSENSOR_FEATURE
+#include "meta_msensor_para.h"
+#endif
+#ifdef FT_ALSPS_FEATURE
+#include "meta_alsps_para.h"
+#endif
+#ifdef FT_GYROSCOPE_FEATURE
+#include "meta_gyroscope_para.h"
+#endif
+
+
+typedef struct
+{
+    FT_H            header;
+    unsigned int    dummy;               
+} FT_MSENSOR_REQ;
+
+typedef struct
+{
+    FT_H            header;
+    unsigned char   status;
+} FT_MSENSOR_CNF;
+
+typedef struct
+{
+    FT_H            header;
+    unsigned int    dummy;               
+} FT_ALSPS_REQ;
+
+typedef struct
+{
+    FT_H            header;
+    unsigned char   status;
+} FT_ALSPS_CNF;
+
+//Modem
+typedef enum 
+{
+	FT_MODEM_OP_QUERY_INFO = 0,
+	FT_MODEM_OP_CAPABILITY_LIST = 1,
+	FT_MODEM_OP_SET_MODEMTYPE = 2,
+	FT_MODEM_OP_GET_CURENTMODEMTYPE = 3,
+	FT_MODEM_OP_QUERY_MDIMGTYPE = 4,
+	FT_MODEM_OP_QUERY_MDDOWNLOADSTATUS = 5,
+	FT_MODEM_OP_TRIGGER_NATIVE_DOWNLOAD = 6,
+	FT_MODEM_OP_REBOOT_MODEM = 7,
+	FT_MODEM_OP_GET_MODEMMODE = 8,
+	FT_MODEM_OP_QUERY_MDDBPATH = 9,
+	FT_MODEM_OP_SUPPORT_COMPRESS = 10,
+	FT_MODEM_END = 0x0fffffff
+}FT_MODEM_OP;
+
+typedef struct
+{
+    unsigned int modem_id;  //no use
+}MODEM_QUERY_MDDBPATH_REQ;
+
+typedef struct
+{
+    unsigned char mddb_path[64];
+}MODEM_QUERY_MDDBPATH_CNF;
+
+typedef struct
+{
+	unsigned char modem_index;
+	unsigned char mode;
+}MODEM_REBOOT_REQ;
+
+typedef struct
+{
+	unsigned int reserved;
+}MODEM_REBOOT_CNF;
+
+
+typedef struct
+{
+	unsigned char modem_index;
+}MODEM_GET_MODEMMODE_REQ;
+
+typedef struct
+{
+	unsigned char mode;
+}MODEM_GET_MODEMMODE_CNF;
+
+typedef struct 
+{
+	unsigned char reserved;
+}MODEM_QUERY_DOWNLOAD_STATUS_REQ;
+
+typedef struct 
+{
+	unsigned int percentage;
+	unsigned int status_code;
+}MODEM_QUERY_DOWNLOAD_STATUS_CNF;
+
+typedef struct 
+{
+	unsigned char reserved;
+}MODEM_QUERY_INFO_REQ;
+	
+typedef struct 
+{
+	unsigned int modem_number;
+	unsigned int modem_id;
+}MODEM_QUERY_INFO_CNF;
+
+typedef enum 
+{
+	FT_MODEM_SRV_INVALID = 0,
+	FT_MODEM_SRV_TST = 1,
+	FT_MODEM_SRV_DHL = 2,
+	FT_MODEM_SRV_ETS = 3,
+	FT_MODEM_SRV_END = 0x0fffffff
+}FT_MODEM_SRV;
+	
+typedef enum 
+{
+	FT_MODEM_CH_NATIVE_INVALID = 0,
+	FT_MODEM_CH_NATIVE_TST = 1,
+	FT_MODEM_CH_TUNNELING = 2,
+	FT_MODEM_CH_TUNNELING_IGNORE_CKSM = 3,
+	FT_MODEM_CH_NATIVE_ETS = 4,
+	FT_MODEM_CH_END = 0x0fffffff
+}FT_MODEM_CH_TYPE;
+	
+typedef struct 
+{
+	FT_MODEM_SRV md_service;
+	FT_MODEM_CH_TYPE ch_type;
+	unsigned char reserved;
+}MODEM_CAPABILITY; 
+
+typedef struct 
+{
+    unsigned char reserved;
+}MODEM_CAPABILITY_LIST_REQ;
+
+typedef struct 
+{
+	MODEM_CAPABILITY modem_cap[8];
+}MODEM_CAPABILITY_LIST_CNF; 
+
+typedef struct 
+{
+	unsigned int modem_id;
+	unsigned int modem_type;
+}MODEM_SET_MODEMTYPE_REQ;
+
+typedef struct 
+{
+	unsigned char reserved;	
+}MODEM_SET_MODEMTYPE_CNF;
+
+typedef struct 
+{
+	unsigned int modem_id;
+}MODEM_GET_CURRENTMODEMTYPE_REQ;
+
+typedef struct 
+{
+	unsigned int current_modem_type;
+}MODEM_GET_CURENTMODEMTYPE_CNF;
+
+typedef struct 
+{
+	unsigned int modem_id;	
+}MODEM_QUERY_MDIMGTYPE_REQ;
+
+typedef struct 
+{
+	unsigned int mdimg_type[16];
+}MODEM_QUERY_MDIMGTYPE_CNF;
+	
+typedef struct
+{       
+   unsigned int action;   //0:disable; 1:enable 
+} MODEM_SUPPORT_COMPRESS_REQ;
+
+typedef struct 
+{
+   unsigned int result;  //0:fail; 1:success
+} MODEM_SUPPORT_COMPRESS_CNF;
+
+typedef union 
+{
+	MODEM_QUERY_INFO_REQ query_modem_info_req; 
+	MODEM_CAPABILITY_LIST_REQ query_modem_cap_req;
+	MODEM_SET_MODEMTYPE_REQ set_modem_type_req;
+	MODEM_GET_CURRENTMODEMTYPE_REQ get_currentmodem_type_req; 
+	MODEM_QUERY_MDIMGTYPE_REQ query_modem_imgtype_req;
+    MODEM_QUERY_DOWNLOAD_STATUS_REQ query_modem_download_status_req;
+	MODEM_REBOOT_REQ reboot_modem_req;
+	MODEM_GET_MODEMMODE_REQ get_modem_mode_req;
+	MODEM_QUERY_MDDBPATH_REQ query_mddbpath_req;
+	MODEM_SUPPORT_COMPRESS_REQ set_compress_req;
+}FT_MODEM_CMD;
+	
+typedef union 
+{
+	MODEM_QUERY_INFO_CNF query_modem_info_cnf;
+	MODEM_CAPABILITY_LIST_CNF query_modem_cap_cnf;
+	MODEM_SET_MODEMTYPE_CNF set_modem_type_cnf;
+	MODEM_GET_CURENTMODEMTYPE_CNF get_currentmodem_type_cnf;
+	MODEM_QUERY_MDIMGTYPE_CNF query_modem_imgtype_cnf;
+	MODEM_QUERY_DOWNLOAD_STATUS_CNF query_modem_download_status_cnf;
+	MODEM_REBOOT_CNF reboot_modem_cnf;
+	MODEM_GET_MODEMMODE_CNF get_modem_mode_cnf;
+	MODEM_QUERY_MDDBPATH_CNF query_mddbpath_cnf;
+	MODEM_SUPPORT_COMPRESS_CNF set_compress_cnf;
+}FT_MODEM_RESULT;
+		
+typedef struct 
+{
+	FT_H header;
+	FT_MODEM_OP	type;
+	FT_MODEM_CMD cmd;
+}FT_MODEM_REQ;
+		
+typedef struct 
+{
+	FT_H header;
+	FT_MODEM_OP type;
+	unsigned char status;
+	FT_MODEM_RESULT result;
+}FT_MODEM_CNF;
+
+typedef enum 
+{
+     FT_GET_SIM_NUM = 0,
+     FT_MISC_WCN_END = 0x0fffffff
+}FT_GET_SIM_OP;
+
+
+typedef struct 
+{
+    FT_H    header;
+    FT_GET_SIM_OP    type;   
+}FT_GET_SIM_REQ;
+
+typedef struct 
+{
+    FT_H                  header;
+    FT_GET_SIM_OP             type;	
+   	unsigned char  status;
+	unsigned int   number;
+}FT_GET_SIM_CNF;
+
+//Baseband
+#ifdef FT_LCDBK_FEATURE
+#include "meta_lcdbk_para.h"
+#endif
+
+#ifdef FT_KEYPADBK_FEATURE
+#include "meta_keypadbk_para.h"
+#endif
+
+#ifdef FT_LCD_FEATURE
+#include "meta_lcdft_para.h"
+#endif
+
+#ifdef FT_VIBRATOR_FEATURE
+#include "meta_vibrator_para.h"
+#endif
+
+typedef enum
+{
+	 FT_UTILCMD_CHECK_IF_FUNC_EXIST = 0
+	,FT_UTILCMD_CHECK_IF_ISP_SUPPORT
+	,FT_UTILCMD_QUERY_BT_MODULE_ID
+	,FT_UTILCMD_ENABLE_WATCHDOG_TIMER
+	,FT_UTILCMD_CHECK_IF_ACOUSTIC16_SUPPORT
+	,FT_UTILCMD_CHECK_IF_AUDIOPARAM45_SUPPORT
+	,FT_UTILCMD_CHECK_IF_LOW_COST_SINGLE_BANK_FLASH
+	,FT_UTILCMD_QUERY_PMIC_ID
+	,FT_UTILCMD_BT_POWER_ON
+	,FT_UTILCMD_KEYPAD_LED_ONOFF
+	,FT_UTILCMD_VIBRATOR_ONOFF					//10
+	,FT_UTILCMD_QUERY_LOCAL_TIME
+	,FT_UTILCMD_CHECK_IF_WIFI_ALC_SUPPORT
+	,FT_UTILCMD_RF_ITC_PCL
+	,FT_UTILCMD_CHECK_IF_DRC_SUPPORT
+	,FT_UTILCMD_CHECK_IF_BT_POWERON
+	,FT_UTILCMD_MAIN_SUB_LCD_LIGHT_LEVEL
+	,FT_UTILCMD_SIGNAL_INDICATOR_ONOFF
+	,FT_UTILCMD_SET_CLEAN_BOOT_FLAG
+	,FT_UTILCMD_LCD_COLOR_TEST
+	,FT_UTILCMD_SAVE_MOBILE_LOG					//20
+	,FT_UTILCMD_GET_EXTERNAL_SD_CARD_PATH
+	,FT_UTILCMD_SET_LOG_LEVEL
+	,FT_UTILCMD_SDIO_AUTO_CALIBRATION
+	,FT_UTILCMD_QUERY_WCNDRIVER_READY
+	,FT_UTILCMD_SDIO_CHECK_CALIBRATION
+	,FT_UTILCMD_SWITCH_WIFI_USB
+	,FT_UTILCMD_SET_ATM_FLAG
+	,FT_UTILCMD_SET_PRODUCT_INFO
+	,FT_UTILCMD_PRINTF_CUSLOG 
+	,FT_UTILCMD_END								//30
+} FtUtilCmdType;
+
+typedef struct
+{
+	unsigned int		query_ft_msg_id;
+	unsigned int		query_op_code;
+}FtUtilCheckIfFuncExist;
+
+typedef struct
+{
+    int		Notused;
+    unsigned char BackupTime[64];
+} SetCleanBootFlag_REQ;
+
+typedef struct
+{
+    BOOL	drv_statsu;							//inidicate the result of setting clean boot
+} SetCleanBootFlag_CNF;
+
+typedef struct
+{
+    int		reserved;
+} SAVE_MOBILE_LOG_REQ;
+
+typedef struct
+{
+    BOOL	drv_status;							
+} SAVE_MOBILE_LOG_CNF;
+
+typedef struct
+{
+    unsigned int level;
+}SET_LOG_LEVEL_REQ;
+
+typedef struct
+{
+    int reserved;
+}SET_LOG_LEVEL_CNF;
+
+typedef struct
+{
+    unsigned int result;
+}QUERY_WCNDRIVER_READY_CNF;
+
+typedef struct
+{
+	unsigned short	   interval;
+} WatchDog_REQ;
+
+typedef struct
+{
+	unsigned short	   rtc_sec;
+	unsigned short	   rtc_min;
+	unsigned short	   rtc_hour;
+	unsigned short	   rtc_day;
+	unsigned short	   rtc_mon;
+	unsigned short	   rtc_wday;
+	unsigned short	   rtc_year;
+	unsigned short	   status;
+} WatchDog_CNF;
+
+typedef struct
+{
+    unsigned int flag; //0: wifi to usb, 1: usb to wifi
+}SWITCH_WIFI_USB_REQ;
+
+typedef struct
+{
+    unsigned int result;
+}SWITCH_WIFI_USB_CNF;
+
+typedef struct
+{
+	unsigned int flag;	
+}SET_ATM_FLAG_REQ;
+
+typedef struct 
+{
+	int	reserved;	
+}SET_ATM_FLAG_CNF;
+
+typedef struct
+{
+	unsigned int type; //0: ATM flag  1: meta log flag
+	unsigned int flag;	
+}SET_PRODUCT_INFO_REQ;
+
+typedef struct 
+{
+	int	reserved;	
+}SET_PRODUCT_INFO_CNF;
+
+typedef struct
+{	 
+    unsigned char log[256];
+}PRINTF_LOG_REQ;
+
+typedef struct
+{	
+    int reserved;
+}PRINTF_LOG_CNF;
+
+
+typedef union
+{
+    FtUtilCheckIfFuncExist	CheckIfFuncExist;
+    WatchDog_REQ			m_WatchDogReq;   // whether use
+#ifdef IS_SUPPORT_SP
+	KeypadBK_REQ			m_KeypadBKReq;
+    LCDLevel_REQ			m_LCDReq;
+    NLED_REQ				m_NLEDReq;
+	LCDFt_REQ         		m_LCDColorTestReq;
+#endif
+    SetCleanBootFlag_REQ	m_SetCleanBootFlagReq;
+    SAVE_MOBILE_LOG_REQ     m_SaveMobileLogReq;
+	SET_LOG_LEVEL_REQ       m_SetLogLevelReq;
+	SWITCH_WIFI_USB_REQ     m_SwitchWiFiUSBReq;
+	SET_ATM_FLAG_REQ		m_SetATMFlagReq;
+	SET_PRODUCT_INFO_REQ	m_SetProductInfo;
+	PRINTF_LOG_REQ			m_PrintCusLogReq;
+    unsigned int			dummy;
+} FtUtilCmdReq_U;
+
+typedef union
+{
+    FtUtilCheckIfFuncExist	CheckIfFuncExist;
+    WatchDog_CNF			m_WatchDogCnf;
+#ifdef IS_SUPPORT_SP
+    KeypadBK_CNF			m_KeypadBKCnf;
+    LCDLevel_CNF			m_LCDCnf;
+    NLED_CNF     			m_NLEDCnf;
+	LCDFt_CNF         		m_LCDColorTestCNF;
+#endif
+    SetCleanBootFlag_CNF	m_SetCleanBootFlagCnf;
+    SAVE_MOBILE_LOG_CNF     m_SaveMobileLogCnf;
+	SET_LOG_LEVEL_CNF		m_SetLogLevelCnf;
+	QUERY_WCNDRIVER_READY_CNF m_QueryWCNDriverReadyCnf;
+	SWITCH_WIFI_USB_CNF     m_SwitchWiFiUSBCnf;
+	SET_ATM_FLAG_CNF        m_SetATMFlagCnf;
+	SET_PRODUCT_INFO_CNF    m_SetProductInfoCnf;
+	PRINTF_LOG_CNF			m_PrintCusLogCnf;
+    unsigned int			dummy;
+} FtUtilCmdCnf_U;
+
+
+typedef struct
+{
+    FT_H            header;	//ft header
+    FtUtilCmdType   type;	//cmd type
+    FtUtilCmdReq_U  cmd;	//cmd parameter
+} FT_UTILITY_COMMAND_REQ;
+
+typedef struct
+{
+    FT_H            header;	//ft header
+    FtUtilCmdType   type;	//cmd type
+    FtUtilCmdCnf_U  result;	//module cmd result
+    unsigned char   status;	//ft status: 0 is success
+} FT_UTILITY_COMMAND_CNF;
+
+//File system
+#ifdef FT_EMMC_FEATURE
+#include "meta_clr_emmc_para.h"
+#endif
+#ifdef FT_NAND_FEATURE
+#include "meta_clr_emmc_para.h"
+#endif
+#ifdef FT_CRYPTFS_FEATURE
+#include "meta_cryptfs_para.h"
+#endif
+
+//Misc
+#ifdef FT_ADC_FEATURE
+#include "meta_adc_para.h"
+#endif
+
+
+#ifdef FT_TOUCH_FEATURE
+#include "meta_touch_para.h"
+#endif
+
+
+#ifdef FT_GPIO_FEATURE
+#include "Meta_GPIO_Para.h"
+#endif
+
+
+
+typedef enum
+{
+    FT_CUSTOMER_OP_BASIC = 0
+    ,FT_CUSTOMER_OP_END
+
+} META_CUSTOMER_CMD_TYPE;
+
+typedef union
+{
+    unsigned char	m_u1Dummy;
+} META_CUSTOMER_CMD_U;
+
+typedef union
+{
+    unsigned char  m_u1Dummy; 
+} META_CUSTOMER_CNF_U;
+
+typedef struct
+{
+    FT_H                    header;
+    META_CUSTOMER_CMD_TYPE  type;
+    META_CUSTOMER_CMD_U     cmd;	
+} FT_CUSTOMER_REQ;
+
+typedef struct
+{
+    FT_H                    header;
+    META_CUSTOMER_CMD_TYPE  type;
+    unsigned char           status;
+    META_CUSTOMER_CNF_U     result;			
+} FT_CUSTOMER_CNF;
+
+typedef enum 
+{
+     FT_SPECIALTEST_OP_HUGEDATA = 0,
+     FT_SPECIALTEST_END = 0x0fffffff
+}SPECIALTEST_OP;
+
+typedef struct
+{
+    int reserved;
+}SPECIALTEST_HUGEDATA_REQ;
+
+typedef struct 
+{
+    unsigned char result;
+}SPECIALTEST_HUGEDATA_CNF;
+
+
+typedef union 
+{
+    SPECIALTEST_HUGEDATA_REQ  specialtest_hugedata_req; 
+}FT_SPECIALTEST_CMD;
+
+typedef union 
+{
+    SPECIALTEST_HUGEDATA_CNF  specialtest_hugedata_cnf;
+}FT_SPECIALTEST_RESULT;
+
+typedef struct 
+{
+    FT_H                  header;
+    SPECIALTEST_OP       type;
+    FT_SPECIALTEST_CMD     cmd;
+}FT_SPECIALTEST_REQ;
+
+
+typedef struct 
+{
+    FT_H                         header;
+    SPECIALTEST_OP            type;
+    unsigned char                status;
+    FT_SPECIALTEST_RESULT        result;
+}FT_SPECIALTEST_CNF;
+
+
+struct FT_RAWDATATEST_REQ
+{
+      FT_H                  header;
+};
+
+struct FT_RAWDATATEST_CNF
+{
+      FT_H                        header;
+      unsigned char                      status;
+};
+
+typedef struct
+{
+    FT_H    header;
+} FT_CHIP_INFO_REQ;
+
+typedef struct
+{
+    FT_H    header;			
+    unsigned char   code_func[64];
+    unsigned char   code_proj[64];
+	unsigned char   code_date[64];
+	unsigned char   code_fab[64];
+    unsigned char	status;
+} FT_CHIP_INFO_CNF;
+
+//////////////////////////////////////////////////////////////////////
+
+typedef enum{
+	FT_SIM_DETECT_OP_EXTMOD = 0,
+	FT_SIM_DETECT_OP_PRJTYPE,
+	FT_SIM_DETECT_OP_MDIDXSET,
+	FT_SIM_DETECT_OP_SWITCH,	
+	FT_SIM_DETECT_OP_GETSSW,	
+	FT_SIM_DETECT_END = 0x0fffffff
+}FT_SIM_DETECT_OP;
+
+typedef struct  
+{
+	unsigned int reserved;
+}SIM_QUERY_MDTYPE_REQ;
+
+typedef struct  
+{
+	unsigned int md_type;
+}SIM_QUERY_MDTYPE_CNF;
+
+typedef struct  
+{
+	unsigned int reserved;
+}SIM_QUERY_PRJTYPE_REQ;
+
+typedef struct  
+{
+	unsigned int prj_type;
+}SIM_QUERY_PRJTYPE_CNF;
+
+typedef struct  
+{
+	unsigned int mode_cmd;
+}SIM_SET_SWITCHER_REQ;
+
+typedef struct  
+{
+	unsigned int reserved;
+}SIM_SET_SWITCHER_CNF;
+
+typedef struct  
+{
+	unsigned int reserved;
+}SIM_QUERY_MDIDXSET_REQ;
+
+typedef struct  
+{
+	unsigned int md_idxset;
+}SIM_QUERY_MDIDXSET_CNF;
+
+typedef struct  
+{
+	unsigned int reserved;
+}SIM_QUERY_SSW_REQ;
+
+typedef struct  
+{
+	unsigned int ssw_val;
+}SIM_QUERY_SSW_CNF;
+
+typedef union 
+{
+	SIM_QUERY_MDTYPE_CNF   sim_query_mdtype_cnf;
+	SIM_QUERY_PRJTYPE_CNF  sim_query_prjtype_cnf;
+	SIM_QUERY_MDIDXSET_CNF sim_query_mdidxset_cnf;
+	SIM_SET_SWITCHER_CNF   sim_set_switcher_cnf;
+	SIM_QUERY_SSW_CNF	   sim_query_ssw_cnf;
+
+} FT_SIM_DETECT_RESULT;
+
+
+typedef union
+{
+	SIM_QUERY_MDTYPE_REQ   sim_query_mdtype_req;
+	SIM_QUERY_PRJTYPE_REQ  sim_query_prjtype_req;
+	SIM_QUERY_MDIDXSET_REQ sim_query_mdidxset_req;
+	SIM_SET_SWITCHER_REQ   sim_set_switcher_req;
+	SIM_QUERY_SSW_REQ	   sim_query_ssw_req;
+
+} FT_SIM_DETECT_CMD;
+
+
+typedef struct 
+{
+	FT_H header;
+	FT_SIM_DETECT_OP	 type;
+	FT_SIM_DETECT_CMD   cmd;
+}FT_SIM_DETECT_REQ;
+		
+typedef struct 
+{
+	FT_H header;
+	FT_SIM_DETECT_OP  type;
+	FT_SIM_DETECT_RESULT result;
+	unsigned char status;
+}FT_SIM_DETECT_CNF;
+
+
+typedef enum{
+	FT_FILE_OP_PARSE = 0,
+	FT_FILE_OP_GETFILEINFO,
+	FT_FILE_OP_SENDFILE,
+	FT_FILE_OP_RECEIVEFILE,	
+	FT_FILE_OP_END = 0x0fffffff
+}FT_FILE_OPERATION_OP;
+
+typedef struct  
+{
+	unsigned char path_name[256];
+	unsigned char filename_substr[256];
+}FILE_OPERATION_PARSE_REQ;
+
+typedef enum 
+{
+	FT_FILE_TYPE_INVALID = 0,
+	FT_FILE_TYPE_FILE = 1,
+	FT_FILE_TYPE_FOLDER = 2,
+	FT_FILE_TYPE_END = 0x0fffffff
+}FT_FILE_TYPE;
+
+typedef struct 
+{
+	FT_FILE_TYPE file_type;
+	unsigned int file_size;
+	unsigned char file_name[256];
+}FT_FILE_INFO;  
+
+typedef struct  
+{
+	unsigned int file_count;
+}FILE_OPERATION_PARSE_CNF;
+
+typedef struct  
+{
+	unsigned int index;   // [ 0, file_count )
+}FILE_OPERATION_GETFILEINFO_REQ;
+
+
+typedef struct  
+{
+	FT_FILE_INFO file_info;
+}FILE_OPERATION_GETFILEINFO_CNF;
+
+typedef struct
+{
+	unsigned int   file_size;	// Total size of the current file. Only available on EOF
+	unsigned char	stage;		// CREATE, WRITE, EOF
+}FILEOPERATION_STREAM_BLOCK;
+
+typedef struct
+{
+    unsigned char dest_file_name[256];
+	FILEOPERATION_STREAM_BLOCK stream_block;
+}FILE_OPERATION_SENDFILE_REQ;
+
+typedef struct  
+{
+	unsigned int send_result;
+}FILE_OPERATION_SENDFILE_CNF;
+
+typedef struct  
+{
+    unsigned char source_file_name[256];
+}FILE_OPERATION_RECEIVEFILE_REQ;
+
+typedef struct  
+{
+    FILEOPERATION_STREAM_BLOCK stream_block;
+	unsigned int receive_result;
+}FILE_OPERATION_RECEIVEFILE_CNF;
+
+typedef union 
+{
+	FILE_OPERATION_PARSE_CNF   parse_cnf;
+	FILE_OPERATION_GETFILEINFO_CNF  getfileinfo_cnf;
+	FILE_OPERATION_SENDFILE_CNF  sendfile_cnf;
+	FILE_OPERATION_RECEIVEFILE_CNF receivefile_cnf;
+
+}FT_FILE_OPERATION_RESULT;
+
+
+typedef union
+{
+	FILE_OPERATION_PARSE_REQ   parse_req;
+	FILE_OPERATION_GETFILEINFO_REQ  getfileinfo_req;
+	FILE_OPERATION_SENDFILE_REQ  sendfile_req;
+	FILE_OPERATION_RECEIVEFILE_REQ receivefile_req;
+
+}FT_FILE_OPERATION_CMD;
+
+
+typedef struct
+{
+	FT_H header;
+	FT_FILE_OPERATION_OP	 type;
+	FT_FILE_OPERATION_CMD   cmd;
+}FT_FILE_OPERATION_REQ;
+		
+typedef struct 
+{
+	FT_H header;
+	FT_FILE_OPERATION_OP  type;
+	FT_FILE_OPERATION_RESULT result;
+	unsigned char status;
+}FT_FILE_OPERATION_CNF;
+
+
+#ifdef FT_SDCARD_FEATURE
+#include "meta_sdcard_para.h"
+#endif
+
+////////////////////Target log ctrl///////////////////////////
+typedef enum{
+	FT_MDLOGGER_OP_SWITCH_TYPE           = 0,
+	FT_MDLOGGER_OP_QUERY_STATUS          = 1,
+	FT_MDLOGGER_OP_QUERY_NORMALLOG_PATH  = 2,
+	FT_MDLOGGER_OP_QUERY_EELOG_PATH		 = 3,
+	FT_MOBILELOG_OP_SWITCH_TYPE			 = 4,
+	FT_MOBILELOG_OP_QUERY_LOG_PATH		 = 5,
+	FT_TARGETLOG_OP_PULL                 = 6,
+	FT_TARGETLOG_OP_PULLING_STATUS       = 7,
+	FT_MDLOGGER_OP_SET_FILTER		     = 8,
+	FT_CONNSYSLOG_OP_SWITCH_TYPE		 = 9,
+	FT_TARGET_OP_CONNSYSLOG_LEVEL		 = 10,
+	FT_GPSLOGGER_OP_SWITCH_TYPE 		 = 11,
+	FT_TARGETLOG_CTRL_OP_END = 0x0fffffff
+}FT_TARGETLOG_CTRL_OP;
+
+typedef struct
+{
+	unsigned int mode;     //1: usb, 2:SD
+	unsigned int action;   //0: stop, 1: start
+}MDLOGGER_CTRL_REQ;
+
+typedef struct
+{
+	unsigned int reserved;
+}MDLOGGER_CTRL_CNF;
+
+typedef struct
+{
+	unsigned int reserved;
+}MDLOGGER_QUERY_STATUS_REQ;
+
+typedef struct
+{
+	unsigned int status;  //0: stop 1:logging
+}MDLOGGER_QUERY_STATUS_CNF;
+
+typedef struct
+{
+	unsigned int reserved;
+}MDLOGGER_QUERY_LOGPATH_REQ;
+
+typedef struct
+{
+	unsigned char path[256];
+}MDLOGGER_QUERY_LOGPATH_CNF;
+
+typedef struct 
+{
+	unsigned int type;      //0:default filter 1:customization filter
+}MDLOGGER_SET_FILTER_REQ;
+
+
+// for mobilelog ctrl
+typedef struct
+{
+	unsigned int mode;     //reserved, in the future maybe->1: usb, 2:SD
+	unsigned int action;   //0: stop, 1: start
+}MOBILELOG_SWITCH_MODE_REQ;
+
+typedef struct
+{
+	unsigned int reserved;
+}MOBILELOG_SWITCH_MODE_CNF;
+
+typedef struct
+{
+	unsigned int reserved;
+}MOBILELOG_QUERY_LOGPATH_REQ;
+
+typedef struct
+{
+	unsigned char path[256];
+}MOBILELOG_QUERY_LOGPATH_CNF;
+
+typedef struct
+{
+	unsigned int type;      //0:modemlog 1:mobilelog 2:connsysLog 3:mddb 4:gpslog
+	unsigned int action;    //0:stop  1:start
+}TARGET_LOG_PULL_REQ;
+
+typedef struct
+{
+	unsigned int reserved;
+}TARGET_LOG_PULL_CNF;
+
+typedef struct
+{
+	unsigned int type;	//0:modemlog 1:mobilelog 2:modem EE log 3:connsyslog 4:mddb 5:gpslog
+}TARGET_LOG_PULL_STATUS_REQ;
+
+typedef struct
+{
+	unsigned int status;  //0:pulling 1:done
+}TARGET_LOG_PULL_STATUS_CNF;
+
+
+typedef enum{
+	CONSYS_WIFI = 0,
+	CONSYS_BT  = 1,
+	CONSYS_GPS = 2,
+	CONSYS_MCU = 3, // reserved
+	CONSYS_END = 4,
+}CONSYS_TYPE;
+
+typedef struct
+{
+	CONSYS_TYPE  type;	
+	unsigned int level; 
+}CONNSYS_SET_LOG_LEVEL_REQ;
+
+typedef struct
+{
+	unsigned int reserved;
+}CONNSYS_SET_LOG_LEVEL_CNF;
+
+// for connsyslog ctrl
+typedef struct
+{
+	unsigned int mode;     //reserved, in the future maybe->1: usb, 2:SD
+	unsigned int action;   //0: stop, 1: start
+}CONNSYSLOG_SWITCH_MODE_REQ, GPSLOG_SWITCH_MODE_REQ;
+
+typedef struct
+{
+	unsigned int reserved;
+}CONNSYSLOG_SWITCH_MODE_CNF, GPSLOG_SWITCH_MODE_CNF;
+
+
+typedef union
+{
+	MDLOGGER_CTRL_CNF           mdlogger_ctrl_cnf;
+	MDLOGGER_QUERY_STATUS_CNF   mdlogger_status_cnf;
+	MDLOGGER_QUERY_LOGPATH_CNF  mdlogger_logpath_cnf;
+	MOBILELOG_SWITCH_MODE_CNF   mobilelog_ctrl_cnf;
+	MOBILELOG_QUERY_LOGPATH_CNF mobilelog_logpath_cnf;
+	CONNSYSLOG_SWITCH_MODE_CNF  connsyslog_ctrl_cnf;
+	TARGET_LOG_PULL_CNF         targetlog_pull_cnf;
+	TARGET_LOG_PULL_STATUS_CNF  targetlog_pulling_status_cnf;
+	GPSLOG_SWITCH_MODE_CNF      gpslog_ctrl_cnf;
+	CONNSYS_SET_LOG_LEVEL_CNF   connsyslog_set_level_cnf;
+} FT_TARGETLOG_CTRL_RESULT;
+
+
+typedef union
+{
+	MDLOGGER_CTRL_REQ           mdlogger_ctrl_req;
+	MDLOGGER_QUERY_STATUS_REQ   mdlogger_status_req;
+	MDLOGGER_QUERY_LOGPATH_REQ  mdlogger_logpath_req;
+	MDLOGGER_SET_FILTER_REQ		mdlogger_setfilter_req;
+	MOBILELOG_SWITCH_MODE_REQ   mobilelog_ctrl_req;
+	MOBILELOG_QUERY_LOGPATH_REQ mobilelog_logpath_req;
+	CONNSYSLOG_SWITCH_MODE_REQ  connsyslog_ctrl_req;
+	TARGET_LOG_PULL_REQ         targetlog_pull_req;
+	TARGET_LOG_PULL_STATUS_REQ  targetlog_pulling_status_req;
+	GPSLOG_SWITCH_MODE_REQ      gpslog_ctrl_req;
+	CONNSYS_SET_LOG_LEVEL_REQ   connsyslog_set_level_req;
+} FT_TARGETLOG_CTRL_CMD;
+
+typedef struct
+{
+	FT_H header;
+	FT_TARGETLOG_CTRL_OP	type;
+	FT_TARGETLOG_CTRL_CMD   cmd;
+}FT_TARGETLOG_CTRL_REQ;
+
+typedef struct
+{
+	FT_H header;
+	FT_TARGETLOG_CTRL_OP     type;
+	FT_TARGETLOG_CTRL_RESULT result;
+	unsigned char status;
+}FT_TARGETLOG_CTRL_CNF;
+
+
+////////////////////APDB function///////////////////////////
+typedef enum
+{
+    FT_APDB_OP_QUERYPATH = 0,
+    FT_APDB_OP_END = 0x0fffffff
+}FT_APDB_OP;
+
+typedef struct
+{
+    unsigned int reserved; //reserved, no use
+}QUERY_APDBPATH_REQ;
+
+typedef struct
+{
+    unsigned char apdb_path[128];
+}QUERY_APDBPATH_CNF;
+
+typedef union
+{
+    QUERY_APDBPATH_CNF   query_apdbpath_cnf;
+} FT_APDB_RESULT;
+
+
+typedef union
+{
+    QUERY_APDBPATH_REQ   query_apdbpath_req;
+} FT_APDB_CMD;
+
+typedef struct
+{
+    FT_H header;
+    FT_APDB_OP  type;
+    FT_APDB_CMD   cmd;
+}FT_APDB_REQ;
+
+typedef struct
+{
+    FT_H header;
+    FT_APDB_OP     type;
+    FT_APDB_RESULT result;
+    unsigned int status;
+}FT_APDB_CNF;
+
+
+////////////////////Attestation Key///////////////////////////
+typedef enum 
+{
+    FT_ATTESTATIONKEY_INSTALL_SET = 0,
+	FT_ATTESTATIONKEY_INSTALL_END = 0x0fffffff
+}FT_ATTESTATIONKEY_INSTALL_OP;
+
+typedef struct
+{
+    unsigned int    file_size;
+    unsigned char   stage;
+}ATTESTATIONKEY_INSTALL_SET_REQ;
+
+typedef struct
+{
+    unsigned int result;
+}ATTESTATIONKEY_INSTALL_SET_CNF;
+
+typedef union
+{
+    ATTESTATIONKEY_INSTALL_SET_REQ   set_req;
+}FT_ATTESTATIONKEY_INSTALL_CMD;
+
+typedef union
+{
+    ATTESTATIONKEY_INSTALL_SET_CNF    set_cnf;
+}FT_ATTESTATIONKEY_INSTALL_RESULT;
+
+typedef struct
+{
+	FT_H						   header;
+	FT_ATTESTATIONKEY_INSTALL_OP   type;
+	FT_ATTESTATIONKEY_INSTALL_CMD  cmd;
+}FT_ATTESTATIONKEY_INSTALL_REQ;
+
+typedef struct
+{
+	FT_H							 header;
+	FT_ATTESTATIONKEY_INSTALL_OP     type;
+	FT_ATTESTATIONKEY_INSTALL_RESULT result;
+	unsigned char					 status;
+}FT_ATTESTATIONKEY_INSTALL_CNF;
+
+////////////////////SysEnv///////////////////////////
+typedef enum{
+	FT_SYSENV_SET = 0,
+	FT_SYSENV_GET = 1,
+	FT_SYSENV_END = 0x0fffffff
+}FT_SYSENV_OP;
+
+typedef struct 
+{
+	unsigned char name[256];
+	unsigned char value[256];	
+}SYS_ENV_SET_REQ;
+
+typedef struct 
+{
+	unsigned int reserved;
+}SYS_ENV_SET_CNF;
+
+typedef struct 
+{
+	unsigned char name[256];
+}SYS_ENV_GET_REQ;
+
+typedef struct 
+{
+	unsigned char value[256];
+}SYS_ENV_GET_CNF;
+
+
+typedef union 
+{
+	SYS_ENV_SET_CNF     sysenv_set_cnf;
+	SYS_ENV_GET_CNF     sysenv_get_cnf;	
+} FT_SYS_ENV_RESULT;
+
+
+typedef union
+{
+	SYS_ENV_SET_REQ     sysenv_set_req;
+	SYS_ENV_GET_REQ     sysenv_get_req;	
+} FT_SYS_ENV_CMD;
+
+typedef struct
+{
+	FT_H			header;
+	FT_SYSENV_OP    type;
+	FT_SYS_ENV_CMD  cmd;
+}FT_SYS_ENV_REQ;
+
+typedef struct
+{
+	FT_H		  		header;
+	FT_SYSENV_OP  		type;
+	FT_SYS_ENV_RESULT 	result;
+	unsigned int		status;
+}FT_SYS_ENV_CNF;
+
+
+typedef enum
+{
+	FT_CLOCK_SET = 0,
+	FT_CLOCK_GET = 1,
+	FT_CLOCK_END = 0x0fffffff
+}FT_TARGETCLOCK_OP;
+
+typedef struct
+{
+	unsigned int year;
+	unsigned int mon;
+	unsigned int day;
+	unsigned int hour;
+	unsigned int min;
+	unsigned int sec;
+	unsigned int ms;
+}SET_TARGET_CLOCK_REQ;
+
+typedef struct
+{
+	unsigned int reserved;
+}SET_TARGET_CLOCK_CNF;
+
+typedef union
+{
+	SET_TARGET_CLOCK_REQ     set_clock_req;
+}FT_TARGET_CLOCK_CMD;
+
+typedef union
+{
+	SET_TARGET_CLOCK_CNF     set_clock_cnf;	
+}FT_TARGET_CLOCK_RESULT;
+
+typedef struct
+{
+	FT_H				header;
+	FT_TARGETCLOCK_OP	type;
+	FT_TARGET_CLOCK_CMD	cmd;
+}FT_TARGETCLOCK_REQ;
+		
+typedef struct
+{
+	FT_H					header;
+	FT_TARGETCLOCK_OP		type;
+	FT_TARGET_CLOCK_RESULT	result;
+	unsigned int			status;
+}FT_TARGETCLOCK_CNF;
+
+typedef enum
+{
+	FT_CTRL_POWEROFF,
+	FT_CTRL_REBOOT,
+	FT_CTRL_REBOOT_RECOVERY,
+	FT_CTRL_REBOOT_BYDELAY,
+	FT_CTRL_DISCONN_ATM,
+	FT_CTRL_CHECKUSB_POWEROFF,
+	FT_CTRL_DONOTHING,
+	FT_CTRL_TARGET_OP_END = 0x0fffffff
+}FT_DISCONN_TARGET_OP;
+
+typedef struct
+{
+	unsigned int    delay;
+	unsigned int    reserved; 
+}FT_TARGET_DISCONNECT_REQ;
+
+typedef struct
+{
+	unsigned int    reserved; 
+}FT_TARGET_DISCONNECT_CNF;
+
+typedef union
+{
+	FT_TARGET_DISCONNECT_REQ   disconnect_req;
+}FT_DISCONNECT_CMD;
+
+typedef union
+{
+	FT_TARGET_DISCONNECT_CNF   disconnect_cnf;	
+}FT_DISCONNECT_RESULT;
+
+typedef struct
+{
+	FT_H				    header;
+	FT_DISCONN_TARGET_OP	type;
+	FT_DISCONNECT_CMD	    cmd;
+}FT_DISCONNECT_REQ;
+
+typedef struct
+{
+	FT_H					header;
+	FT_DISCONN_TARGET_OP	type;
+	FT_DISCONNECT_RESULT	result;
+	unsigned int			status;
+}FT_DISCONNECT_CNF;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+
diff --git a/src/devtools/meta/src/common/inc/Frame.h b/src/devtools/meta/src/common/inc/Frame.h
new file mode 100644
index 0000000..2af9b95
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/Frame.h
@@ -0,0 +1,74 @@
+#ifndef _FRAME_H_
+#define _FRAME_H_
+
+#include <stdlib.h>
+#include "MetaPub.h"
+
+class CmdTarget;
+
+class Frame
+{
+public:
+	Frame(const META_RX_DATA&, CmdTarget*);
+	Frame();
+	~Frame(void);
+
+public:
+	void exec();
+
+	META_FRAME_TYPE type() const
+	{
+		return m_frmData.eFrameType;
+	}
+
+	unsigned char *localBuf() const
+	{
+		return m_frmData.pData;
+	}
+	unsigned char *peerBuf() const
+	{
+		if (m_frmData.PeerLen > 8)
+		{
+		    return m_frmData.pData + m_frmData.LocalLen + 8; //skip the header of peer buffer
+	    }
+		else
+		{
+			return NULL;
+		}
+	}
+
+	unsigned short localLen() const
+	{
+		return m_frmData.LocalLen;
+	}
+	unsigned short peerLen() const
+	{
+		if (m_frmData.PeerLen > 8)
+		{
+		    return m_frmData.PeerLen - 8;//skip the header of peer buffer
+	    }
+		else
+		{
+			return 0;
+		}
+	}
+	unsigned char getIsValid()
+	{
+		return 	m_isValid;
+	}
+
+	CmdTarget * getCmdTarget() const
+	{
+		return m_myMod;
+	}
+
+protected:
+	void decode();
+
+private:
+	CmdTarget *m_myMod;
+	META_RX_DATA m_frmData;
+	unsigned char m_isValid;
+};
+
+#endif	// _FRAME_H_
\ No newline at end of file
diff --git a/src/devtools/meta/src/common/inc/FtModule.h b/src/devtools/meta/src/common/inc/FtModule.h
new file mode 100644
index 0000000..76cd47e
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/FtModule.h
@@ -0,0 +1,643 @@
+#ifndef _FT_MODULE_H_
+#define _FT_MODULE_H_
+#include "DriverInterface.h"
+#include "CmdTarget.h"
+#include "mlist.h"
+#include <vector>
+
+
+class FtModWifi : public CmdTarget
+{
+public:
+	FtModWifi(void);
+	virtual ~FtModWifi(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+class FtModGPS : public CmdTarget
+{
+public:
+	FtModGPS(void);
+	virtual ~FtModGPS(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+
+class FtModNFC : public CmdTarget
+{
+public:
+	FtModNFC(void);
+	virtual ~FtModNFC(void);
+
+public:
+	virtual void exec(Frame*);
+
+protected:
+	 int init(Frame*);
+};
+
+
+class FtModBT : public CmdTarget
+{
+public:
+	FtModBT(void);
+	virtual ~FtModBT(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+class FtModFM : public CmdTarget
+{
+public:
+	FtModFM(void);
+	virtual ~FtModFM(void);
+
+public:
+	virtual void exec(Frame*);
+
+protected:
+	 int init(Frame*);
+};
+
+class FtModAudio : public CmdTarget
+{
+public:
+	FtModAudio(void);
+	virtual ~FtModAudio(void);
+
+public:
+	virtual void exec(Frame*);
+
+protected:
+	 int init(Frame*);
+};
+
+class FtModCCAP : public CmdTarget
+{
+public:
+	FtModCCAP(void);
+	virtual ~FtModCCAP(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+
+class FtModDRM : public CmdTarget
+{
+public:
+	FtModDRM(void);
+	virtual ~FtModDRM(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+class FtModGAMMA : public CmdTarget
+{
+public:
+	FtModGAMMA(void);
+	virtual ~FtModGAMMA(void);
+public:
+	virtual void exec(Frame*);
+};
+
+class FtModAttestationKey : public CmdTarget
+{
+public:
+	FtModAttestationKey(void);
+	virtual ~FtModAttestationKey(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+
+#ifdef FT_NVRAM_FEATURE
+class FtModNvramBackup : public CmdTarget
+{
+public:
+	FtModNvramBackup(void);
+	virtual ~FtModNvramBackup(void);
+	void covertArray2Vector(const char* in, int len, std::vector<uint8_t>& out);
+	void covertVector2Array(std::vector<uint8_t> in, char* out);
+
+private:	
+	bool SendNVRAMFile(unsigned char file_ID, FT_NVRAM_BACKUP_CNF* pft_cnf);
+	
+public:
+	virtual void exec(Frame*);
+};
+
+class FtModNvramRestore : public CmdTarget
+{
+public:
+	FtModNvramRestore(void);
+	virtual ~FtModNvramRestore(void);
+
+public:
+	virtual void exec(Frame*);
+
+};
+
+class FtModNvramReset : public CmdTarget
+{
+public:
+	FtModNvramReset(void);
+	virtual ~FtModNvramReset(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+class FtModNvramRead : public CmdTarget
+{
+public:
+	FtModNvramRead(void);
+	virtual ~FtModNvramRead(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+
+class FtModNvramWrite : public CmdTarget
+{
+public:
+	FtModNvramWrite(void);
+	virtual ~FtModNvramWrite(void);
+
+public:
+	virtual void exec(Frame*);
+};
+#endif
+
+class FtModTestAlive : public CmdTarget
+{
+public:
+	FtModTestAlive(void);
+	virtual ~FtModTestAlive(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+class FtModVersionInfo : public CmdTarget
+{
+public:
+	FtModVersionInfo(void);
+	virtual ~FtModVersionInfo(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+
+
+class FtModVersionInfo2 : public CmdTarget
+{
+public:
+	FtModVersionInfo2(void);
+	virtual ~FtModVersionInfo2(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+
+class FtModChipInfo : public CmdTarget
+{
+public:
+	FtModChipInfo(void);
+	virtual ~FtModChipInfo(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+
+class FtModPowerOff : public CmdTarget
+{
+public:
+	FtModPowerOff(void);
+	virtual ~FtModPowerOff(void);
+
+public:
+	virtual void exec(Frame*);
+	void checkUSBOnline();
+	void rebootToRecovery();
+	void closeUSB();
+
+};
+
+
+class FtModReboot : public CmdTarget
+{
+public:
+	FtModReboot(void);
+	virtual ~FtModReboot(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+class FtModMetaDisconnect : public CmdTarget
+{
+public:
+	FtModMetaDisconnect(void);
+	virtual ~FtModMetaDisconnect(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+
+class FtModBuildProp : public CmdTarget
+{
+public:
+	FtModBuildProp(void);
+	virtual ~FtModBuildProp(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+
+
+class FtModGSensor : public CmdTarget
+{
+public:
+	FtModGSensor(void);
+	virtual ~FtModGSensor(void);
+
+public:
+	virtual void exec(Frame*);
+
+protected:
+	int init(Frame*);
+
+};
+
+class FtModMSensor : public CmdTarget
+{
+public:
+	FtModMSensor(void);
+	virtual ~FtModMSensor(void);
+
+public:
+	virtual void exec(Frame*);
+
+protected:
+	int init(Frame*);
+
+private:
+	FT_MSENSOR_CNF m_ft_cnf;
+};
+
+class FtModALSPS : public CmdTarget
+{
+public:
+	FtModALSPS(void);
+	virtual ~FtModALSPS(void);
+
+public:
+	virtual void exec(Frame*);
+
+protected:
+	int init(Frame*);
+
+private:
+	FT_ALSPS_CNF m_ft_cnf;
+};
+
+class FtModGyroSensor : public CmdTarget
+{
+public:
+	FtModGyroSensor(void);
+	virtual ~FtModGyroSensor(void);
+
+public:
+	virtual void exec(Frame*);
+
+protected:
+	int init(Frame*);
+
+};
+
+
+class FtModModemInfo : public CmdTarget
+{
+public:
+	FtModModemInfo(void);
+	virtual ~FtModModemInfo(void);
+	int getModemCapability(MODEM_CAPABILITY_LIST_CNF* modem_capa);
+	void rebootModem(FT_MODEM_REQ *req, FT_MODEM_CNF & ft_cnf, int fd);
+	int getModemMode(FT_MODEM_REQ *req, FT_MODEM_CNF & ft_cnf, int fd);
+	int getModemIndex(FT_MODEM_REQ *req);
+	int getModemState(int *modem_state, int fd);
+	int getModemType(int *modem_type, int fd);
+	int setModemType(int modem_type, int fd);
+#ifdef MTK_SINGLE_BIN_MODEM_SUPPORT
+        int CopyMDDBFile(unsigned int nModemId);
+#endif
+
+public:
+	virtual void exec(Frame*);
+
+};
+
+
+class FtModSIMNum : public CmdTarget
+{
+public:
+	FtModSIMNum(void);
+	virtual ~FtModSIMNum(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+class FtModSDcard : public CmdTarget
+{
+public:
+	FtModSDcard(void);
+	virtual ~FtModSDcard(void);
+
+public:
+	virtual void exec(Frame*);
+
+protected:
+	int init(Frame*);
+
+};
+
+class FtModEMMC : public CmdTarget
+{
+public:
+	FtModEMMC(void);
+	virtual ~FtModEMMC(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+class FtModCRYPTFS : public CmdTarget
+{
+public:
+	FtModCRYPTFS(void);
+	virtual ~FtModCRYPTFS(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+class FtModADC : public CmdTarget
+{
+public:
+	FtModADC(void);
+	virtual ~FtModADC(void);
+
+public:
+	virtual void exec(Frame*);
+};
+#if 0
+class FtModAUXADC : public CmdTarget
+{
+public:
+	FtModAUXADC(void);
+	virtual ~FtModAUXADC(void);
+
+public:
+	virtual void exec(Frame*);
+
+protected:
+	virtual void init();
+	virtual void deinit();
+};
+
+
+
+class FtModCPURegR : public CmdTarget
+{
+public:
+	FtModCPURegR(void);
+	virtual ~FtModCPURegR(void);
+
+public:
+	virtual void exec(Frame*);
+
+protected:
+	virtual void init();
+	virtual void deinit();
+};
+
+class FtModCPURegW : public CmdTarget
+{
+public:
+	FtModCPURegW(void);
+	virtual ~FtModCPURegW(void);
+
+public:
+	virtual void exec(Frame*);
+
+protected:
+	virtual void init();
+	virtual void deinit();
+};
+
+#endif
+
+
+class FtModChipID : public CmdTarget
+{
+public:
+	FtModChipID(void);
+	virtual ~FtModChipID(void);
+
+public:
+	virtual void exec(Frame*);
+
+};
+
+#ifdef FT_TOUCH_FEATURE
+class FtModCTP : public CmdTarget
+{
+public:
+	FtModCTP(void);
+	virtual ~FtModCTP(void);
+
+public:
+	virtual void exec(Frame*);
+
+protected:
+	int init(Frame*);
+
+private:
+	Touch_CNF m_ft_cnf;
+};
+#endif
+
+class FtModGPIO : public CmdTarget
+{
+public:
+	FtModGPIO(void);
+	virtual ~FtModGPIO(void);
+
+public:
+	virtual void exec(Frame*);
+
+protected:
+	int init(Frame*);
+};
+
+class FtModFileOperation : public CmdTarget
+{
+public:
+	FtModFileOperation(void);
+	virtual ~FtModFileOperation(void);
+
+public:
+	virtual void exec(Frame*);
+
+private:
+    mlist<FT_FILE_INFO*>		m_fileInfoList;
+	unsigned m_nFileCount;
+	unsigned int GetFileLen(char *pFilePath);
+	int ListPath(unsigned char *pPath,unsigned char *pFileNameSubStr);
+	void ClearFileInfoList(void);
+	FT_FILE_INFO* GetFileInfo(unsigned int id);
+	int SaveSendData(FILE_OPERATION_SENDFILE_REQ *req, char *peer_buff, unsigned short peer_len);
+	int SetReceiveData(FILE_OPERATION_RECEIVEFILE_REQ *req, FT_FILE_OPERATION_CNF* pft_cnf);
+};
+
+class FtModRAT : public CmdTarget
+{
+public:
+	FtModRAT(void);
+	virtual ~FtModRAT(void);
+
+public:
+	void exec(Frame*);
+protected:
+	int init(Frame*);
+
+};
+
+class FtModMSIM : public CmdTarget
+{
+public:
+	FtModMSIM(void);
+	virtual ~FtModMSIM(void);
+
+public:
+	void exec(Frame*);
+protected:
+	int init(Frame*);
+
+};
+
+
+class FtModUtility : public CmdTarget
+{
+public:
+	FtModUtility(void);
+	virtual ~FtModUtility(void);
+#ifdef FT_NVRAM_FEATURE
+	void covertArray2Vector(unsigned char* in, int len, std::vector<uint8_t>& out);
+	void covertVector2Array(std::vector<uint8_t> in, char* out);
+#endif
+public:
+	void exec(Frame*);
+	
+};
+
+
+class FtModCustomer : public CmdTarget
+{
+public:
+	FtModCustomer(void);
+	virtual ~FtModCustomer(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+class FtModSpecialTest : public CmdTarget
+{
+public:
+	FtModSpecialTest(void);
+	virtual ~FtModSpecialTest(void);
+
+public:
+	virtual void exec(Frame*);
+};
+
+class FtModTargetloggerCtrl : public CmdTarget
+{
+public:
+	FtModTargetloggerCtrl(void);
+	virtual ~FtModTargetloggerCtrl(void);
+
+public:
+	virtual void exec(Frame*);
+
+private:
+	unsigned int SwitchMdloggerMode(FT_TARGETLOG_CTRL_REQ *req);
+	unsigned int	SwitchMobilelogMode(FT_TARGETLOG_CTRL_REQ *req);
+	unsigned int SwitchConnsyslogMode(FT_TARGETLOG_CTRL_REQ *req);
+	unsigned int TargetLogPulling(FT_TARGETLOG_CTRL_REQ *req);
+	unsigned int GetTargetLogPullingStatus(FT_TARGETLOG_CTRL_REQ *req, FT_TARGETLOG_CTRL_CNF &cnf);
+	unsigned int QueryMdloggerStatus(FT_TARGETLOG_CTRL_CNF &cnf);
+	unsigned int GetLogPropValue(char *key);
+	unsigned int SetModemLogFilter(FT_TARGETLOG_CTRL_REQ *req);
+	void* GetLoggerSocket(unsigned int type, const char * service);
+	unsigned int	QueryMdNormalLogPath(FT_TARGETLOG_CTRL_CNF &cnf);
+	unsigned int QueryMdEELogPath(FT_TARGETLOG_CTRL_CNF &cnf);
+    unsigned int	QueryMBLogPath(FT_TARGETLOG_CTRL_CNF &cnf);
+	unsigned int SwitchGPSlogMode(FT_TARGETLOG_CTRL_REQ *req);
+	unsigned int SetConnsysLogLevel(FT_TARGETLOG_CTRL_REQ *req);
+
+};
+
+class FtModAPDB : public CmdTarget
+{
+public:
+    FtModAPDB(void);
+    virtual ~FtModAPDB(void);
+
+public:
+    virtual void exec(Frame*);
+};
+
+class FtModSysEnv : public CmdTarget
+{
+public:
+    FtModSysEnv(void);
+    virtual ~FtModSysEnv(void);
+
+public:
+    virtual void exec(Frame*);
+};
+
+class FtModTargetClock : public CmdTarget
+{
+public:
+    FtModTargetClock(void);
+    virtual ~FtModTargetClock(void);
+
+public:
+    virtual void exec(Frame*);
+
+private:
+	unsigned int SetSysClock(SET_TARGET_CLOCK_REQ *req);
+	unsigned int IsValidDate(SET_TARGET_CLOCK_REQ *req);
+
+};
+
+
+#endif	// _FT_MODULE_H_
diff --git a/src/devtools/meta/src/common/inc/LogDefine.h b/src/devtools/meta/src/common/inc/LogDefine.h
new file mode 100644
index 0000000..120e08e
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/LogDefine.h
@@ -0,0 +1,31 @@
+#ifndef _LOG_DEFINE_H_
+#define _LOG_DEFINE_H_
+
+
+#undef LOG_TAG
+#define LOG_TAG "META"
+
+#ifdef IS_SUPPORT_SP
+#include <log/log.h>
+
+#define META_LOG(...) \
+        do { \
+            ALOGD(__VA_ARGS__); \
+        } while (0)
+
+#else
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#define META_LOG(...) {\
+        syslog(LOG_DEBUG, ## __VA_ARGS__);}
+#endif
+
+//#define LOGD(...) {\
+//        syslog(LOG_DEBUG, ## __VA_ARGS__);}
+
+#define TEXT(__a)  __a
+
+
+
+#endif /* _LOG_DEFINE_H__ */
diff --git a/src/devtools/meta/src/common/inc/MSocket.h b/src/devtools/meta/src/common/inc/MSocket.h
new file mode 100644
index 0000000..ec62ad0
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/MSocket.h
@@ -0,0 +1,127 @@
+#ifndef _METASOCKET_H_

+#define _METASOCKET_H_

+

+#include <string>

+using namespace std;

+

+typedef enum

+{

+	SOCKET_MDLOGGER    = 0,

+	SOCKET_MOBILELOG   = 1,

+	SOCKET_ATCI_CLIENT = 2,

+	SOCKET_ATCI_SERVER = 3,

+	SOCKET_ATM_COMM    = 4,

+	SOCKET_CONNSYSLOG  = 5,

+	SOCKET_GPSLOGGER   = 6,

+	SOCKET_END         = 7

+}SOCKET_TYPE;

+

+

+class MSocket

+{

+

+public:

+	MSocket();

+	virtual ~MSocket(void);

+	int initClient(const char * socket_name, int namespaceId, int bListen=1);

+	int initServer(const char * socket_name, int namespaceId, int bListen=1);

+	void deinit();

+	int connect();

+	void disconnect();

+	int getClientSocketID() const

+	{

+	   return m_clientID;

+	}

+	int getServerSocketID() const

+	{

+	   return m_serverID;

+	}

+	virtual void send_msg(const char *msg);

+

+private:

+	static void* ThreadFunc(void*);

+	virtual void wait_msg() = 0;

+

+public:

+	SOCKET_TYPE m_type;

+	bool m_bClientConnected;

+	

+protected:	

+	int m_clientID;

+	int m_serverID;

+	int m_threadID;

+	int m_stop;

+	pthread_t  m_thread;

+};

+

+//////////////////////////////////////////////MATCIClientSocket////////////////////////////////////////////////////

+//ATCI is socket client

+class MATCIClientSocket : public MSocket

+{

+public:

+	MATCIClientSocket();

+	MATCIClientSocket(SOCKET_TYPE type);

+	virtual ~MATCIClientSocket();

+

+private:	

+	virtual void wait_msg();

+};

+

+//////////////////////////////////////////////MATCIServerSocket////////////////////////////////////////////////////

+//ATCI is socket server

+class MATCIServerSocket : public MSocket

+{

+public:

+	MATCIServerSocket();

+	MATCIServerSocket(SOCKET_TYPE type);

+	virtual ~MATCIServerSocket();

+

+private:	

+	virtual void wait_msg();

+};

+

+

+//////////////////////////////////////////////MLogSocket////////////////////////////////////////////////////

+

+class MLogSocket : public MSocket

+{

+public:

+	MLogSocket();

+	MLogSocket(SOCKET_TYPE type);

+	virtual ~MLogSocket();

+	int recv_rsp(char *buf);

+	void send_msg(const char *msg, bool ignore);

+	int getLogPullingStatus(int type);

+	void setLogPullingStatus(int type, int value);

+

+private:

+	string m_strCmd;

+	string m_strRsp;

+	int    m_mdlogpulling;

+	int    m_mblogpulling;

+	int    m_connsyslogpulling;

+	int    m_mddbpulling;

+	int    m_gpslogpulling;

+	pthread_mutex_t m_Mutex;

+	

+private:	

+	virtual void wait_msg();

+};

+

+

+//////////////////////////////////////////////MATMSocket////////////////////////////////////////////////////

+

+class MATMSocket : public MSocket

+{

+public:

+	MATMSocket();

+	MATMSocket(SOCKET_TYPE type);

+	virtual ~MATMSocket();

+

+private:	

+	virtual void wait_msg();

+};

+

+#endif

+

+

diff --git a/src/devtools/meta/src/common/inc/MdRxWatcher.h b/src/devtools/meta/src/common/inc/MdRxWatcher.h
new file mode 100644
index 0000000..f860210
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/MdRxWatcher.h
@@ -0,0 +1,55 @@
+#ifndef _MD_RX_WATCHER_H_
+#define _MD_RX_WATCHER_H_
+
+#include "Frame.h"
+#include "Device.h"
+#include "MetaPub.h"
+#include "DriverInterface.h"
+
+typedef struct 
+{
+	unsigned int	data_len;
+	char			preserve_head_buf[MD_FRAME_HREADER_LENGTH*2]; // Double the buffer space to preserve extension for escape translation
+	char			data[MAX_TST_RECEIVE_BUFFER_LENGTH];
+	char			preserve_tail_buf[TST_CHECKSUM_SIZE*2];// Double the buffer space to preserve extension for escape translation
+} TST_MD_RECV_BUF;
+
+
+class MdRxWatcher : public IDevWatcher
+{
+public:
+	MdRxWatcher(int index);
+	virtual ~MdRxWatcher(void);
+
+public:
+	virtual signed int onReceived(
+		unsigned char*, unsigned int);
+
+private:
+	void process(
+		const unsigned char *buf,
+		unsigned int len);
+
+	void processMDConfirm(
+		char *pdata, unsigned short len);
+
+	
+	int fillDataToTSTBufferReverse(unsigned char data, char **buffer_ptr);	
+	int fillDataToTSTBuffer(unsigned char data, char **buffer_ptr);	
+	void processTunnelData(unsigned char *pdata, unsigned int len);
+    bool compress(char *pdata, unsigned short len, char *compressed, size_t *compressed_len);
+
+private:
+	unsigned short m_bufLen;
+	unsigned short m_frmLen;
+	unsigned char  m_frmBuf[FRAME_MAX_LEN];
+	unsigned char  m_frmStat;
+	unsigned char  m_frmStat0;
+	unsigned char  m_chkSum;
+	int	   m_bL1Header;  //0:PS dta 1:L1 Data
+	TST_MD_RECV_BUF *m_recv_buf;
+	
+	int nModemIndex;
+};
+
+#endif	// _MD_RX_WATCHER_H_
diff --git a/src/devtools/meta/src/common/inc/MetaPub.h b/src/devtools/meta/src/common/inc/MetaPub.h
new file mode 100644
index 0000000..85fd982
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/MetaPub.h
@@ -0,0 +1,466 @@
+#ifndef _META_PUB_H_
+#define _META_PUB_H_
+
+#include <stdbool.h>
+#include "PortHandle.h"
+#define	MAX_PATH				1024
+
+typedef enum
+{
+	META_SUCCESS = 0,
+	META_FAILED
+} META_RESULT;
+
+
+typedef enum
+{
+	META_STATUS_FAILED = 0,
+    META_STATUS_SUCCESS
+} META_STATUS;
+
+
+//////////////////////////////////////////////////////////////////////////
+//define the MD frame
+#define MD_FRAME_TREACE_OFFSITE 3
+#define MD_FRAME_HREADER_LENGTH 4
+#define MAX_TST_RECEIVE_BUFFER_LENGTH       (4096*16)//2048
+#define TST_CHECKSUM_SIZE					(1)
+#define MD_FRAME_TST_INJECT_PRIMITIVE_LENGTH 10
+#define MD_FRAME_FAILED_TST_LOG_PRIMITIVE_LENGTH  20
+#define MD_FRAME_SUCCESS_TST_LOG_PRIMITIVE_LENGTH 102
+#define MD_FRAME_REF_LENGTH 2
+#define MD_FRAME_MSG_LEN_LENGTH 2
+#define MD_FRAME_MAX_LENGTH 256
+#define MD_FRAME_FAILED_CHECEK_SIM_OFFISTE 76
+#define MD_FRAME_SUCCESS_CHECEK_SIM_OFFISTE 116
+#define MD_FRAME_DS269_OFFSITE 8
+
+//the define of the type of meta frame
+#define  RS232_LOGGED_PRIMITIVE_TYPE   		0x60
+#define  RS232_PS_TRACE_TYPE           		0x61
+#define  RS232_PS_PROMPT_TRACE_TYPE    		0x62
+#define  RS232_COMMAND_TYPE_OCTET      		0x63
+#define  RS232_INJECT_PRIMITIVE_OCTET  		0x64
+#define  RS232_INJECT_UT_PRIMITIVE     		0x65
+#define  RS232_INJECT_APPRIMITIVE_OCTET     0x66
+
+#define  RS232_INJECT_PRIMITIVE_OCTETMODEM2  		0xA0
+#define  RS232_INJECT_PRIMITIVE_OCTETMODEM2_END		0xA7
+#define  RS232_COMMAND_TYPE_MD2_MEMORY_DUMP      	0xC0
+#define  RS232_COMMAND_TYPE_MD2_MEMORY_DUMP_END     0xC7
+
+//TST tunneling
+#define  RS232_COMMAND_TYPE_MD_DATA_TUNNEL_START   0xD0
+#define  RS232_COMMAND_TYPE_MD_DATA_TUNNEL_END 0xD7
+#define  RS232_RESPONSE_MD_DATA_TUNNEL_START   0xD8
+#define  RS232_RESPONSE_MD_DATA_TUNNEL_END  0xDF
+//TST tunneling + compression
+#define  RS232_COMMAND_TYPE_MD_DATA_TUNNEL_COMP_START 0xF0
+#define  RS232_COMMAND_TYPE_MD_DATA_TUNNEL_COMP_END   0xF7
+#define  RS232_RESPONSE_MD_DATA_TUNNEL_COMP_START     0xF8   
+#define  RS232_RESPONSE_MD_DATA_TUNNEL_COMP_END       0xFF
+
+
+//the maximum size of frame
+#define FRAME_MAX_LEN 1024*64
+//the size of peer buf header
+#define PEER_HEADER_LEN 8
+// the maximum size of peer buf
+#define PEER_BUF_MAX_LEN 1024*60
+// the maximum size of peer buf + local buf
+#define FT_MAX_LEN (FRAME_MAX_LEN -PEER_HEADER_LEN - 9)
+
+/* teh define of escape key */
+#define   STX_OCTET            	0x55
+#define   MUX_KEY_WORD		    0x5A
+#define   SOFT_FLOW_CTRL_BYTE   0x77
+#define   STX_L1HEADER         	0xA5
+
+
+//CCB: Mux Header size
+/***************************************************
+Mux Header Format
+   0                   1                 2                      3          
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+  |                        mux header magic  (4B)               |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+  |           len           (2B)         |               
+  +-+-+-+-+-+-+-+-+-+-+-+-+-
+  
+  mux header magic:
+   0                   1                   2                   3
+   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |     0xAC      |     0xCA      |     0x00      |     0xFF      |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+****************************************************/
+#define META_CCB_MUX_HEADER_LEN 			6
+#define META_CCB_TX_MAX_RETRY				10
+#define META_CCB_INIT_MAX_RETRY				10
+#define META_CCB_POOL_BITMASK   			1    //For Meta, the bitmask is fixed
+#define META_CCB_BUFFER_ID   				0    //For Meta, the buffer id is fixed.
+
+/* Define the rs232 frame phase states */
+#define  RS232_FRAME_STX               				0
+#define  RS232_FRAME_LENHI             				1
+#define  RS232_FRAME_LENLO             				2
+#define  RS232_FRAME_TYPE              				3
+#define  RS232_FRAME_LOCAL_LENHI       				4
+#define  RS232_FRAME_LOCAL_LENLO       				5
+#define  RS232_FRAME_PEER_LENHI        				6
+#define  RS232_FRAME_PEER_LENLO        				7
+#define  RS232_FRAME_COMMAND_DATA      				8
+#define  RS232_FRAME_COMMAND_HEADER    				9
+#define  RS232_FRAME_UT_DATA		   				10
+#define  RS232_FRAME_MD_DATA		   				11
+#define  RS232_FRAME_AP_INJECT_PIRIMITIVE_HEADER 	12
+#define  RS232_FRAME_AP_PRIM_LOCAL_PARA_DATA     	13
+#define  RS232_FRAME_AP_PRIM_PEER_DATA           	14
+#define  RS232_FRAME_CHECKSUM          				15
+#define  RS232_FRAME_KEYWORD		   				16
+#define  RS232_FRAME_SOFT_CTRL         				17
+#define  RS232_FRAME_MD_CONFIRM_DATA				18
+#define  RS232_FRAME_MD_TUNNELING_DATA 				19
+#define  RS232_FRAME_MD_TUNNELING_CHECKSUM 			20
+#define  RS232_FRAME_MD_TUNNELING_COMPRESS_DATA                 21
+
+
+#define  UART1_PATH_TTYS	"/dev/ttyS0"
+#define  UART2_PATH_TTYS	"/dev/ttyS1"
+#define  UART3_PATH_TTYS	"/dev/ttyS2"
+#define  UART4_PATH_TTYS	"/dev/ttyS3"
+
+#define  UART1_PATH_TTYMT	"/dev/ttyMT0"
+#define  UART2_PATH_TTYMT	"/dev/ttyMT1"
+#define  UART3_PATH_TTYMT	"/dev/ttyMT2"
+#define  UART4_PATH_TTYMT	"/dev/ttyMT3"
+
+
+////////////////////////////log ctrl///////////////////////////////////
+
+#define MDLOG_SOCKET_NAME		     "/dev/mdlogger_socket1"
+#define MBLOG_SOCKET_NAME            "/dev/log_controld"
+#define CONNSYSLOG_SOCKET_NAME       "ConnsysFWHidlServer"
+#define GPSLOG_SOCKET_NAME           "mtk_meta2mnld_logctrl"
+
+#define MDLOG_START                  "meta_start,%d"
+#define MDLOG_STOP			      	 "meta_pause"	
+#define MDLOG_PULL_START	         "pull_mdlog_start,1"
+#define MDLOG_PULL_STOP  	         "pull_mdlog_stop"
+#define MDLOG_QUERY_STATUS           "get_running_state"
+#define MDLOG_QUERY_NORMALLOG_PATH   "get_run_folder" 
+#define MDLOG_QUERY_EELOG_PATH       "get_ee_folder"
+#define MDLOG_PULL_STATUS            "get_pullmdlog_state"
+#define MDLOG_EE_DONE_STATUS         "get_ee_done_state"
+#define MDLOG_SET_FILTER		     "meta_mdfilter,%d"
+
+#define MBLOG_START                  "meta_aplog_rec_start" 
+#define MBLOG_STOP                   "meta_aplog_rec_stop"
+#define MBLOG_PULL_START             "meta_aplog_pull_start"
+#define MBLOG_PULL_STOP              "meta_aplog_pull_stop"
+
+#define MBLOG_QUERY_NORMALLOG_PATH   "get_run_mbfolder"
+#define MBLOG_PULL_STATUS            "get_pullmblog_state"
+
+#define CONNLOG_START                "meta_connsys_start" 
+#define CONNLOG_STOP                 "meta_connsys_stop"
+#define CONNLOG_PULL_START	         "pull_FWlog_start"
+#define CONNLOG_PULL_STOP  	         "pull_FWlog_stop"
+#define CONNLOG_PULL_STATUS          "pull_FWlog_status"
+#define CONNLOG_QUERY_STATUS         "log_running_status"
+
+#define GPSLOG_START                 "meta_gpslog_start" 
+#define GPSLOG_STOP                  "meta_gpslog_stop"
+#define GPSLOG_PULL_START	         "pull_gpslog_start"
+#define GPSLOG_PULL_STOP  	         "pull_gpslog_stop"
+
+#define SET_FWLOG_LEVEL  	         "meta_set_fwlog_level,%d,%d"
+#define MDDB_PULL_START				 "pull_MDDB"
+//////////////////////////////////////////////////////////////////////////
+
+//-------------------------------------
+// define com mask parameter
+//-------------------------------------
+#define DEFAULT_COM_MASK    (EV_RXCHAR | EV_RLSD | EV_ERR | EV_BREAK | EV_RING)
+
+//////////////////////////////////////////////////////////////////////////
+
+typedef signed short	int16;
+typedef signed int		int32;
+typedef unsigned char	uint8;
+typedef unsigned short	uint16;
+typedef unsigned int	uint32;
+
+
+
+//*****************************************************************************
+//
+//                          META Driver data structure def
+//
+//*****************************************************************************
+
+
+
+// defie the type of frame.
+typedef enum
+{
+	AP_FRAME =0,	//ap side
+	MD_FRAME		//modem side
+} META_FRAME_TYPE;
+
+
+// the data pass between FT and TST
+typedef struct
+{
+	META_FRAME_TYPE eFrameType;	//frame type
+	unsigned char *pData;
+	unsigned short LocalLen;			//local len
+	unsigned short PeerLen;			//peer len
+} META_RX_DATA;
+
+typedef enum
+{
+	META_UNKNOWN_COM=0,
+	META_UART_COM,
+	META_USB_COM,
+	META_SOCKET,
+	META_PCIE_COM
+}META_COM_TYPE;
+
+typedef struct
+{
+	unsigned short	token;
+	unsigned short	id;
+}FT_H;
+
+typedef struct
+{	
+    char* ip_addr;
+	unsigned int port;
+}WIFI_PARA;
+
+
+//the ID define of ft req and cnf, it is used to ananlyze the different module.
+typedef enum
+{
+	/* RF */
+	FT_RF_TEST_REQ_ID = 0					   ,/*0*/
+	FT_RF_TEST_CNF_ID = 1					   ,
+	/* BaseBand */
+	FT_REG_READ_ID = 2						   ,
+	FT_REG_READ_CNF_ID = 3					   ,
+	FT_REG_WRITE_ID	= 4						   ,
+	FT_REG_WRITE_CNF_ID	= 5					   ,/*5*/
+	FT_ADC_GETMEADATA_ID = 6				   ,
+	FT_ADC_GETMEADATA_CNF_ID = 7			   ,
+	/* test alive */
+	FT_IS_ALIVE_REQ_ID = 8						   ,
+	FT_IS_ALIVE_CNF_ID = 9						   ,
+	/* power off */
+	FT_POWER_OFF_REQ_ID = 10						   ,/*10*/
+	/* unused */
+	FT_RESERVED04_ID = 11 						   ,
+	/* required META_DLL version */
+	FT_CHECK_META_VER_REQ_ID = 12 				   ,
+	FT_CHECK_META_VER_CNF_ID = 13 				   ,
+	/* utility command */
+	FT_UTILITY_COMMAND_REQ_ID = 14				   ,
+	FT_UTILITY_COMMAND_CNF_ID = 15				   ,/*15*/
+	/* for NVRAM */
+	FT_NVRAM_GET_DISK_INFO_REQ_ID = 16			   ,
+	FT_NVRAM_GET_DISK_INFO_CNF_ID = 17			   ,
+	FT_NVRAM_RESET_REQ_ID = 18					   ,
+	FT_NVRAM_RESET_CNF_ID = 19					   ,
+	FT_NVRAM_LOCK_CNF_ID = 20					   ,/*20*/
+	FT_NVRAM_LOCK_REQ_ID = 21 					   ,
+	FT_NVRAM_READ_REQ_ID = 22 					   ,
+	FT_NVRAM_READ_CNF_ID = 23 					   ,
+	FT_NVRAM_WRITE_REQ_ID = 24					   ,
+	FT_NVRAM_WRITE_CNF_ID = 25					   ,/*25*/
+	/* FAT */
+	FT_FAT_OPERATION_ID = 26 				   ,/* 26 ~ 40 */
+	/* L4 Audio */
+	FT_L4AUD_REQ_ID = 41 					   ,/* 41 ~ 50 */
+	FT_L4AUD_CNF_ID							   ,
+	/* Version Info */
+	FT_VER_INFO_REQ_ID = 51					   ,/* 51 */
+	FT_VER_INFO_CNF_ID						   ,
+	/* CCT */
+	FT_CCT_REQ_ID = 53						   ,/* 53 */
+	FT_CCT_CNF_ID							   ,
+	/* WiFi */
+	FT_WIFI_WNDRV_SET_REQ_ID = 55			   ,/* 55 */
+	FT_WIFI_WNDRV_SET_CNF_ID 				   ,
+	FT_WIFI_WNDRV_QUERY_REQ_ID = 57			   ,/* 57 */
+	FT_WIFI_WNDRV_QUERY_CNF_ID				   ,
+	FT_WIFI_REQ_ID = 59						   ,/* 59 */
+	FT_WIFI_CNF_ID							   ,  
+	FT_BT_REQ_ID = 61						   ,
+	FT_BT_CNF_ID 							   ,
+	FT_PMIC_REG_READ_ID = 63 		   , 
+	FT_PMIC_REG_READ_CNF_ID			   ,
+	FT_PMIC_REG_WRITE_ID = 65		   , 
+	FT_PMIC_REG_WRITE_CNF_ID 			   ,
+	FT_URF_TEST_REQ_ID = 67					 ,	 /* 67 */
+	FT_URF_TEST_CNF_ID				   ,
+	FT_FM_REQ_ID = 69						  ,   /* 69 */
+	FT_FM_CNF_ID = 70						  ,
+	FT_TDMB_REQ_ID = 71				  , /* 71 */
+	FT_TDMB_CNF_ID = 72				  , /* 72 */
+	/* This is a special message defined to handle L1 report. */
+	FT_DISPATCH_REPORT_ID					   ,
+	FT_WM_METATEST_REQ_ID						,  	/* 74 */
+	FT_WM_METATEST_CNF_ID						,
+	// for battery dfi
+	FT_WM_BAT_REQ_ID								,	/* 76 */
+	FT_WM_BAT_CNF_ID								,
+	//for dvbt test
+	FT_WM_DVB_REQ_ID								,	/* 78 */
+	FT_WM_DVB_CNF_ID								,
+	FT_BATT_READ_INFO_REQ_ID=80    ,
+	FT_BATT_READ_INFO_CNF_ID,
+	FT_GPS_REQ_ID = 82							,
+	FT_GPS_CNF_ID 							    ,
+	FT_BAT_CHIPUPDATE_REQ_ID = 84	,
+	FT_BAT_CHIPUPDATE_CNF_ID 			,
+	FT_SDCARD_REQ_ID = 86 ,
+	FT_SDCARD_CNF_ID 	 ,
+	FT_LOW_POWER_REQ_ID = 88,
+	FT_LOW_POWER_CNF_ID ,
+	FT_GPIO_REQ_ID = 90,
+	FT_GPIO_CNF_ID ,
+	// For NVRAM backup & restore
+	FT_NVRAM_BACKUP_REQ_ID = 94,
+	FT_NVRAM_BACKUP_CNF_ID,
+	FT_NVRAM_RESTORE_REQ_ID = 96,
+	FT_NVRAM_RESTORE_CNF_ID,
+	// For G-Sensor
+	FT_GSENSOR_REQ_ID = 114,
+	FT_GSENSOR_CNF_ID ,
+	FT_META_MODE_LOCK_REQ_ID = 116,
+	FT_META_MODE_LOCK_CNF_ID,
+	// Reboot
+	FT_REBOOT_REQ_ID = 118,
+	// For MATV
+	FT_MATV_CMD_REQ_ID = 119,
+	FT_MATV_CMD_CNF_ID,
+	// Customer API
+	FT_CUSTOMER_REQ_ID = 121,
+	FT_CUSTOMER_CNF_ID = 122,
+	// Get chip ID
+	FT_GET_CHIPID_REQ_ID = 123,
+	FT_GET_CHIPID_CNF_ID = 124,
+	// M-Sensor
+	FT_MSENSOR_REQ_ID = 125,
+	FT_MSENSOR_CNF_ID = 126,
+	// Touch panel
+	FT_CTP_REQ_ID = 127,
+	FT_CTP_CNF_ID = 128,
+	// ALS_PS
+	FT_ALSPS_REQ_ID = 129,
+	FT_ALSPS_CNF_ID = 130,
+	//Gyroscope	
+	FT_GYROSCOPE_REQ_ID = 131,
+	FT_GYROSCOPE_CNF_ID = 132,
+	// Get version info V2
+	FT_VER_INFO_V2_REQ_ID = 133,
+	FT_VER_INFO_V2_CNF_ID = 134,
+	//CMMB
+	FT_CMMB_REQ_ID = 135,
+	FT_CMMB_CNF_ID = 136,
+
+	FT_BUILD_PROP_REQ_ID = 137,
+	FT_BUILD_PROP_CNF_ID = 138,
+
+	// NFC
+	FT_NFC_REQ_ID = 139,
+	FT_NFC_CNF_ID = 140,
+
+	FT_ADC_REQ_ID = 141,
+   	FT_ADC_CNF_ID = 142,
+
+   	FT_EMMC_REQ_ID = 143,
+   	FT_EMMC_CNF_ID = 144,
+
+   	FT_CRYPTFS_REQ_ID = 145,
+   	FT_CRYPTFS_CNF_ID = 146,
+
+   	FT_MODEM_REQ_ID = 147,
+   	FT_MODEM_CNF_ID = 148,
+
+   	FT_SIM_NUM_REQ_ID = 149,
+   	FT_SIM_NUM_CNF_ID = 150,
+   
+   	// DFO
+   	FT_DFO_REQ_ID = 151,
+   	FT_DFO_CNF_ID = 152,
+
+   	//DRMKey
+   	FT_DRMKEY_REQ_ID = 153,
+   	FT_DRMKEY_CNF_ID = 154,
+
+   	//FT_HDCP_REQ_ID = 155,
+   	//FT_HDCP_CNF_ID = 156,
+
+	//SPECIALTEST
+   	FT_SPECIALTEST_REQ_ID = 157,
+   	FT_SPECIALTEST_CNF_ID = 158,
+
+	FT_CHIP_INFO_REQ_ID = 159,
+	FT_CHIP_INFO_CNF_ID = 160,
+
+	FT_SIM_DETECT_REQ_ID = 161,
+	FT_SIM_DETECT_CNF_ID = 162,
+
+    FT_FILE_OPERATION_REQ_ID = 163,
+    FT_FILE_OPERATION_CNF_ID = 164,
+	FT_GAMMA_REQ_ID = 165,
+	FT_GAMMA_CNF_ID = 166,
+
+	FT_RATCONFIG_REQ_ID = 167,
+	FT_RATCONFIG_CNF_ID = 168,
+
+	FT_MSIM_REQ_ID = 169,
+	FT_MSIM_CNF_ID = 170,
+
+    //MD logger ctrl
+    FT_TARGETLOG_CTRL_REQ_ID = 171,
+    FT_TARGETLOG_CTRL_CNF_ID = 172,
+
+    FT_APDB_REQ_ID = 173,
+    FT_APDB_CNF_ID = 174,
+
+    FT_ATTESTATIONKEY_REQ_ID = 175,
+	FT_ATTESTATIONKEY_CNF_ID = 176,
+
+	FT_SYSENV_REQ_ID = 177,
+	FT_SYSENV_CNF_ID = 178,
+
+	FT_TARGETCLOCK_REQ_ID = 179,
+	FT_TARGETCLOCK_CNF_ID = 180,	
+
+	FT_DISCONNECT_REQ_ID = 181,
+	FT_DISCONNECT_CNF_ID = 182,
+
+	FT_MSG_LAST_ID	
+} FT_MESSAGE_ID;
+
+
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+#ifndef BOOL
+#define BOOL bool
+#endif
+
+#ifndef META_BOOL
+#define META_BOOL bool
+#endif
+
+typedef unsigned char BYTE;
+
+#endif	// _META_PUB_H_
diff --git a/src/devtools/meta/src/common/inc/Meta_mipc.h b/src/devtools/meta/src/common/inc/Meta_mipc.h
new file mode 100644
index 0000000..70dc88e
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/Meta_mipc.h
@@ -0,0 +1,26 @@
+#ifndef _CMD_METAMIPC_H_

+#define _CMD_METAMIPC_H_

+

+class MetaMIPC

+{

+public:

+	MetaMIPC(void);

+	 ~MetaMIPC(void);

+

+public:

+	void Init();

+	bool Send_at_cmd(const char* cmd, char *res);

+	bool IsModemReady()

+	{

+		return m_bReady;

+	}

+

+	void SetModemReady(bool bStatus) 

+	{
+		 m_bReady = bStatus;

+	}

+private:

+	bool m_bReady;

+};

+

+#endif

diff --git a/src/devtools/meta/src/common/inc/Modem.h b/src/devtools/meta/src/common/inc/Modem.h
new file mode 100644
index 0000000..ea3a262
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/Modem.h
@@ -0,0 +1,32 @@
+#ifndef _MODEM_H_
+#define _MODEM_H_
+
+#include "CmdTarget.h"
+#include "SerPort.h"
+
+class IDevWatcher;
+
+class Modem : public CmdTarget
+{
+public:
+	Modem(const char*, unsigned short);
+	Modem(unsigned short id);
+	virtual ~Modem(void);
+
+public:
+	virtual void exec(Frame*);
+	virtual void exec(const unsigned char *p, unsigned int len );
+
+	signed int pumpAsync(IDevWatcher*);
+	signed int getDevHandle();
+	void popUpAsync(); 
+
+protected:
+	 int init(Frame*);
+	 void deinit();
+
+private:
+	Device *m_pDev;
+};
+
+#endif	// _MODEM_H_
diff --git a/src/devtools/meta/src/common/inc/PortHandle.h b/src/devtools/meta/src/common/inc/PortHandle.h
new file mode 100644
index 0000000..b4eaca7
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/PortHandle.h
@@ -0,0 +1,20 @@
+#ifndef _PORTHANDLE_H_
+#define _PORTHANDLE_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int WriteDataToPC(void *Local_buf,unsigned short Local_len,void *Peer_buf,unsigned short Peer_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	// _PORTHANDLE_H_
+
+
+
+
+
diff --git a/src/devtools/meta/src/common/inc/PortInterface.h b/src/devtools/meta/src/common/inc/PortInterface.h
new file mode 100644
index 0000000..a0f72bc
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/PortInterface.h
@@ -0,0 +1,22 @@
+
+#ifndef _PORTINTERFACE_H_
+#define _PORTINTERFACE_H_
+
+#include "MetaPub.h"
+
+class SerPort;
+
+void destroyPortHandle();
+META_COM_TYPE getComType();
+void setComType(META_COM_TYPE comType);
+SerPort * createSerPort();
+SerPort * getSerPort();
+void querySerPortStatus();
+void destroySerPort();
+void usbMutexLock(bool bLock);
+
+
+
+#endif	// _PORTINTERFACE_H_
+
+
diff --git a/src/devtools/meta/src/common/inc/SerPort.h b/src/devtools/meta/src/common/inc/SerPort.h
new file mode 100644
index 0000000..5127856
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/SerPort.h
@@ -0,0 +1,105 @@
+#pragma once
+#include "Device.h"
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <poll.h>
+#include <dirent.h>
+#include <errno.h>
+
+
+class CCCI : public Device
+{
+public:
+	CCCI(const char*);
+	virtual signed int read(unsigned char *buf, unsigned int len);
+	virtual signed int write(const unsigned char *p, unsigned int len);
+
+private:
+	static signed int open(const char*);
+};
+
+class CCB : public Device
+{
+public:
+	CCB();
+
+private:
+	int init();
+	void *ccb_memcpy(void *dst,void *src, size_t n);
+	void ccb_data_copy(void* dst, void* src, unsigned int length, void* alignment_addr);
+public:
+	virtual signed int read(unsigned char*, unsigned int);
+	virtual signed int write(const unsigned char*, unsigned int);
+};
+
+class SerPort : public Device
+{
+public:
+	SerPort(const char*);
+	SerPort();
+	~SerPort();
+	virtual void setSerPortExitFlag();
+
+protected:
+	virtual signed int open(const char*);
+	static void initTermIO(int portFd);
+};
+
+
+class UartPort : public SerPort
+{
+public:
+	UartPort(const char*);
+};
+
+class UsbPort : public SerPort
+{
+public:
+	UsbPort(const char*);
+	~UsbPort();
+
+public:
+	virtual signed int read(unsigned char*, unsigned int);
+	virtual signed int write(const unsigned char*, unsigned int);
+	virtual void update();
+	
+
+private:
+	void close();
+	int isReady();
+	void initUeventSocket();
+	void deinitUeventSocket();
+	void handleUsbUevent(const char *buff, int len);
+	int getUsbState() const;
+
+private:
+	const char *m_devPath;
+	int m_usbMutexFlag;
+	int m_usbConnected;
+	int m_ueventSocket;
+	bool m_getUsbUvent;
+};
+
+class MetaSocket : public SerPort
+{
+public:
+	MetaSocket(const char*);
+	~MetaSocket();
+public:
+	virtual signed int open(const char*);
+	virtual signed int read(unsigned char*, unsigned int);
+	virtual signed int write(const unsigned char*, unsigned int);
+	virtual void close();
+    virtual void setSerPortExitFlag();
+private:
+	signed int connect();
+	void disconnect();
+
+private:
+	int m_nClientFd;
+	bool m_bConnect;
+    int m_nSocketConnectExitFlag;
+
+};
diff --git a/src/devtools/meta/src/common/inc/UsbRxWatcher.h b/src/devtools/meta/src/common/inc/UsbRxWatcher.h
new file mode 100644
index 0000000..d021dac
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/UsbRxWatcher.h
@@ -0,0 +1,92 @@
+#ifndef _USB_RX_WATCHER_H_
+#define _USB_RX_WATCHER_H_
+
+#include "Device.h"
+#include "Frame.h"
+#include "MetaPub.h"
+#include "DriverInterface.h"
+
+#define FrameMaxSize 4096*16//2048
+
+typedef struct
+{
+	unsigned short     local_len;
+	unsigned short     peer_len;
+} PRIM_HEADER;
+
+/* the define of buf of meta type */
+typedef struct
+{
+	PRIM_HEADER	inject_prim;				//lenght of peer buf and local buf
+	unsigned short	received_prig_header_length;	//recieved header count
+	unsigned short	received_buf_para_length;		//recieved buf count
+	unsigned char	*header_ptr;					//header pointer
+	unsigned char	*buf_ptr;						//buf pointer
+} PRIM_FRAME;
+
+
+typedef struct 
+{
+	unsigned short	frame_len;
+	unsigned char		frame_state;
+	unsigned char		frame_cksm;
+	unsigned char		frame_md_index;
+	unsigned char		frame_buf[FrameMaxSize]; // Must be 4-byte aligned
+	unsigned char*   	frame_data_ptr; // this is a frame type dependent data pointer
+} TST_FRMAE_INTERNAL_STRUCT;
+
+class UsbRxWatcher : public IDevWatcher
+{
+public:
+	UsbRxWatcher(void);
+	virtual ~UsbRxWatcher(void);
+
+public:
+	virtual signed int onReceived(
+		unsigned char*, unsigned int);
+
+private:
+	Frame *decode(unsigned char*, unsigned int, unsigned short&);
+	Frame *decodeMDFrame(void *pdata, unsigned int len, unsigned char frmType,unsigned short&);
+	Frame *decodeAPFrame(unsigned int input_len,unsigned char * src,unsigned short&);	
+	Frame *decodeLTE_C2KFrame(unsigned int input_len,unsigned char * src,unsigned char frmType,unsigned short &u16Length);
+	Frame *sendFtTask();
+	
+	Frame * sendMdTask(void *pdata, unsigned int len,unsigned char frmType);
+
+	unsigned char transferFrame(unsigned char * ch);
+	unsigned char checkEscape(unsigned char ch);
+	
+	Frame * dispatchFrame(unsigned char ch, unsigned char *buf_ptr, unsigned int input_len, unsigned char *src,unsigned short& );
+	
+	unsigned char *reallocFrameBuf(unsigned int len);
+
+	unsigned int flowControl(
+		void *pdata, unsigned int len);
+	
+	unsigned char getUARTEsc(unsigned char &ch);
+
+    bool uncompress(void *pdata, int len, char *uncompressed, int *uncompressed_len);
+	unsigned int nRemainLen;	
+	unsigned char szRemainBuf[FrameMaxSize*2];
+	char m_uncompressed[FrameMaxSize];
+private:
+	unsigned char m_checksum;
+	unsigned short m_uFrameLength;
+
+	char m_cTstFrameState;
+	char m_cOldTstFrameState;
+
+	unsigned short m_frame_buf_len;
+	PRIM_FRAME m_sRs232Frame;
+
+	char m_flow_ctrl_flag;
+
+	unsigned char m_md_index;//Only LTE modem use
+
+	unsigned char m_frm_len_byte; //frame length take up to bytes
+	unsigned int m_nStartByteLen;
+
+};
+
+#endif	// _USB_RX_WATCHER_H_
diff --git a/src/devtools/meta/src/common/inc/mlist.h b/src/devtools/meta/src/common/inc/mlist.h
new file mode 100644
index 0000000..a8414db
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/mlist.h
@@ -0,0 +1,160 @@
+#ifndef _M_LIST_
+#define _M_LIST_
+
+#include <stddef.h>
+
+template <typename _Tx>
+struct mlist_item
+{
+	_Tx data;
+	struct mlist_item<_Tx> *next;	
+};
+
+template <typename _Tx>
+class mlist_iter
+{
+public:
+	typedef mlist_item<_Tx> nodetype;
+	typedef mlist_iter<_Tx> self;
+	
+	mlist_iter() : node(NULL)
+	{
+	}
+	
+	mlist_iter(nodetype *p) : node(p)
+	{
+	}
+	
+public:
+	self &operator++()
+	{
+	//	assert(node != NULL);
+		node = node->next;
+		return *this;
+	}
+	
+	_Tx &operator*()
+	{
+	//	assert(node != NULL);
+		return node->data;
+	}
+	
+	_Tx *operator->()
+	{
+	//	assert(node != NULL);
+		return &(node->data);
+	}
+	
+	bool operator==(const self &ref) const
+	{
+		return (node == ref.node);
+	}
+	
+	bool operator!=(const self &ref) const
+	{
+		return (node != ref.node);
+	}
+	
+private:
+	nodetype *node;
+};
+
+template <typename _Tx>
+class mlist
+{
+public:
+	typedef mlist_iter<_Tx> iterator;
+	typedef mlist_item<_Tx> nodetype;
+	
+	mlist()
+	{
+		head = NULL;
+		tail = NULL;
+	}
+	
+	~mlist()
+	{
+		nodetype *tmp = NULL;
+		
+		while (head != NULL)
+		{
+			tmp = head->next;
+			delete head;
+			head = tmp;
+		}
+	}
+	
+public:
+	void push_back(const _Tx &x)
+	{
+		if (tail != NULL)
+		{
+			tail->next = new nodetype;
+			tail = tail->next;
+		}
+		else
+		{
+			tail = new nodetype;
+			head = tail;
+		}
+		tail->data = x;
+		tail->next = NULL;
+	}
+	
+	void destroy_node(const _Tx &x)
+	{
+		nodetype *tmp = NULL;
+		nodetype *delete_node =NULL;
+		
+		if(head->data == x)
+		{
+			delete_node = head;
+			head = head->next;
+		}
+		else
+		{
+			tmp = head;	
+			while(tmp->next->data != x)
+			{
+				tmp = tmp->next;				
+			}
+			delete_node = tmp->next;
+			tmp->next = tmp->next->next;
+		}
+
+		if(head == NULL)
+			tail = NULL;
+
+		if(delete_node != NULL)
+			delete delete_node;		
+	}
+	
+	iterator begin() const
+	{
+		return iterator(head);
+	}
+		
+	iterator end() const
+	{
+		return iterator(NULL);
+	}
+
+	void clear()
+	{
+		nodetype *tmp = NULL;
+		while (head != NULL)
+		{
+			tmp = head->next;
+			delete head;
+			head = tmp;
+		}
+		head = NULL;
+		tail = NULL;
+	}
+
+private:
+	nodetype *head;
+	nodetype *tail;
+};
+
+#endif	// _M_LIST_
diff --git a/src/devtools/meta/src/common/src/CmdTarget.cpp b/src/devtools/meta/src/common/src/CmdTarget.cpp
new file mode 100644
index 0000000..0aeebb3
--- /dev/null
+++ b/src/devtools/meta/src/common/src/CmdTarget.cpp
@@ -0,0 +1,37 @@
+#include "CmdTarget.h"
+#include "LogDefine.h"
+
+CmdTarget::CmdTarget(unsigned short id)
+	: m_myId(id), m_isInited(false)
+{
+	META_LOG("[Meta] id = %d", m_myId);
+	m_token = 0;
+}
+
+CmdTarget::~CmdTarget(void)
+{
+	if (m_isInited)
+	{
+		deinit();
+		m_isInited = false;
+	}
+}
+
+void CmdTarget::exec(Frame* pFrame)
+{
+	if (!m_isInited)
+	{
+		if(init(pFrame))
+			m_isInited = true;
+	}
+}
+
+
+int CmdTarget::init(Frame*)
+{
+	return true;
+}
+
+void CmdTarget::deinit()
+{
+}
diff --git a/src/devtools/meta/src/common/src/Context.cpp b/src/devtools/meta/src/common/src/Context.cpp
new file mode 100644
index 0000000..31988f7
--- /dev/null
+++ b/src/devtools/meta/src/common/src/Context.cpp
@@ -0,0 +1,2169 @@
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <stdint.h>
+#include <string.h>
+
+
+#ifdef IS_SUPPORT_SP
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+#include "CFG_PRODUCT_INFO_File.h"
+#include "Custom_NvRam_LID.h"
+#include "libnvram.h"
+#endif
+
+#include <unistd.h>
+#include "mlist.h"
+#include "Modem.h"
+#include "MdRxWatcher.h"
+#include "UsbRxWatcher.h"
+#include "MSocket.h"
+
+#include "FtModule.h"
+#include "Context.h"
+#include "LogDefine.h"
+//#include "hardware/ccci_intf.h"
+#include <sys/time.h>
+#include "ccci_intf.h" 
+
+#include "Meta_mipc.h"
+#include "PortInterface.h"
+
+#ifdef TST_C2K_SUPPORT
+#ifndef MTK_ECCCI_C2K
+#include "c2kutils.h"
+#endif
+#endif
+
+#define CCCI_ONE_PATH	"/dev/ttyC1"
+#define CCCI_TWO_PATH	"/dev/ccci2_tty1"
+#define CCCI_FIVE_PATH	"/dev/eemcs_md_log"
+#define USB_EXTERNAL_PATH "/dev/ttyACM0"
+
+UsbRxWatcher hostSerPortRx;
+
+class Context
+{
+private:
+	Context(void);
+public:
+	~Context(void);
+
+public:
+	static Context *instance();
+
+	Modem * createModem(const char *ccci, unsigned short id);
+	Modem * createModem(unsigned short id);
+	void destroyModem(Modem *p);
+	Modem * getModem(unsigned short id);
+
+	CmdTarget *getModule(unsigned short id);
+	
+	unsigned int dumpData(const unsigned char* con, int length);
+	unsigned int dumpDataInHexString(const unsigned char* con, int length, unsigned int bytesPerRow);
+	
+	unsigned int getFileSize(int fd);
+	const char* makepath(unsigned char file_ID);
+
+	unsigned getMdmInfo();
+
+	unsigned int getMdmType();
+	unsigned int getActiveMdmId();	
+	unsigned int getMdmNumber();
+	signed int getModemHandle(unsigned short id);
+	void createModemThread(unsigned short modemIndex,int usbUsb);
+	void createSerPortThread();
+	void destroySerPortThread();
+	void destroyModemThread(unsigned short modemIndex);	
+	void createAllModemThread();
+	void destroyAllModemThread();
+	
+	void setLogLevel(unsigned int level);
+	unsigned int getLogLevel();
+	int queryModemProtocol(unsigned short modemIndex);
+	int getModemProtocol(unsigned short modemIndex, MODEM_CAPABILITY_LIST_CNF* modem_capa);
+	FT_MODEM_CH_TYPE getMDChType(unsigned short modemIndex);
+	unsigned int getPropValue(const char *key);
+	unsigned int getMDMode(void);
+	void setMDMode(unsigned int modem_boot_mode);//normal= 1 meta=2
+	void setActiveATModem(unsigned int activeATModemId);
+	unsigned int getActiveATModem();
+	int getIOCPort(unsigned int nModemIndex, int & bDataDevice);
+	void destroy();
+	void setMDThreadFlag(int modemThreadFlag);
+	int getMDThreadFlag();
+	void destroyVirtualRxThread();
+	void createVirtualRxThread();
+	UsbRxWatcher * getVirtualRxWatcher() const;
+	void setVirtualRxWatcher(UsbRxWatcher * virtualRxWatcher);
+	int readSys_int(char const * path);
+	int getBootMode();
+	int getDataChannelType();
+	MSocket * createSocket(SOCKET_TYPE type);
+	MSocket * getSocket(SOCKET_TYPE type);
+	void delSocket(SOCKET_TYPE type);
+	
+	int encrypt(int plainText, int key){return plainText^key;}
+	int decrypt(int cipherText, int key){return cipherText^key;}
+	void queryNormalModeTestFlag();
+	int getNormalModeTestFlag();
+	int setNormalModeTestFlag(int flag);
+
+	int setProductInfo(int type, int flag, int offset);
+	int getProductInfo(int type, int offset);
+	int modifyProductInfo(int type, int flag, int offset);
+
+    void queryWifiPara(int argc, char** argv);
+    WIFI_PARA getWifiPara();
+	
+	int getLoadType();
+	void queryModemHwVersion(unsigned short modemIndex);
+	int getModemHwVersion(unsigned short modemIndex);
+	
+	void setATRespFlag(int atFlag);
+	int getATRespFlag();
+
+	void setCurrentMdMode(int mdMode);
+
+	int notifyModemDoRFByATCI();
+	int ChangeModemMode(int mode);
+
+	void writeBootprof(char * str);
+
+	int writePortIndex();
+	
+	int getModemModeSwitching();
+
+	void setModemModeSwitching(int modemModeSwitching);
+
+	void switchComType(META_COM_TYPE targetComType);
+	unsigned int checkMdStatus();
+
+    void SetDataCompressStatus(unsigned int enable);
+	unsigned int GetDataCompressStatus();
+
+	void HandleSocketCmd(char* socket_cmd);
+
+private:
+	void initModuleList();
+	bool IsModemSupport(int idx);
+	int notifyModemDoRF(int mdIdx);
+	void waitMdResponse(int fd, const char *rsp);
+
+private:
+	mlist<Modem*>		m_mdmList;
+	mlist<CmdTarget*>	m_modList;
+	SerPort *			m_serPort;
+	UsbRxWatcher *      m_virtualRxWatcher;
+	MSocket *			m_socket[SOCKET_END];
+
+	MODEM_CAPABILITY_LIST_CNF m_modem_cap_list;
+
+	static Context *	m_myInst;
+
+	unsigned int m_mdmNumber;
+	unsigned int m_activeMdmId;
+	unsigned int m_activeATModemId;
+	unsigned int m_mdmType;
+	unsigned int m_logLevel;
+	unsigned int m_modem_boot_mode;
+	unsigned int m_modemThreadFlag;
+	unsigned int m_virtualRxThreadFlag;
+	unsigned int m_mdDataChannel; //0: CCCI, 1:CCB
+
+	Modem_Hw_Version m_modem_hw_version;
+	char m_modemProtocol[16];
+
+	int m_normalModeTestFlag;
+	int m_bootMode;
+
+	WIFI_PARA m_WifiPara;
+
+	int m_atFlag;
+	int m_currentMdMode;
+	unsigned int m_dataCompressStatus;
+};
+
+Context *Context::m_myInst = NULL;
+
+
+Context::Context(void)
+	:m_serPort(NULL),m_virtualRxWatcher(NULL)
+{
+	initModuleList();
+	META_LOG("[Meta] initModuleList");
+	getMdmInfo();
+	memset(&m_modem_cap_list,0,sizeof(m_modem_cap_list));
+	m_logLevel = 0;
+	m_modemThreadFlag = 0;
+	m_modem_boot_mode = 0;
+	m_virtualRxThreadFlag = 0;
+	m_activeATModemId = 0;
+	m_mdDataChannel = 0;
+	m_normalModeTestFlag = 0;
+	m_bootMode = UNKNOWN_BOOT;
+
+	m_modem_hw_version = MODEM_END;
+	memset(m_modemProtocol, 0, sizeof(m_modemProtocol));
+
+	m_WifiPara.ip_addr = (char *)"0.0.0.0";
+	m_WifiPara.port = 0;
+
+	for(int i=0; i<SOCKET_END; i++)
+	{
+		m_socket[i] = NULL;
+	}
+	
+	m_atFlag = 0;
+	m_currentMdMode = 0;
+        m_dataCompressStatus = 0;
+}
+
+Context::~Context(void)
+{
+	mlist<Modem*>::iterator it0 = m_mdmList.begin();
+
+	while (it0 != m_mdmList.end())
+	{
+		delete (*it0);
+		++ it0;
+	}
+
+	mlist<CmdTarget*>::iterator it1 = m_modList.begin();
+
+	while (it1 != m_modList.end())
+	{
+		delete (*it1);
+		++ it1;
+	}
+
+	if (m_serPort != NULL)
+	{
+		delete m_serPort;
+	}
+}
+
+Context *Context::instance()
+{
+	return (m_myInst==NULL) ? ((m_myInst=new Context)) : m_myInst;
+}
+
+void Context::destroy()
+{
+	delete m_myInst;
+	m_myInst = NULL;
+}
+
+bool Context::IsModemSupport(int idx)
+{
+
+//	char szVal[128]       = {0};
+//	char szProperty[128]  = {0};
+	int  ret              = 0;
+
+#ifdef IS_SUPPORT_SP	
+	sprintf(szProperty, "ro.vendor.mtk_md%d_support", idx);
+	property_get(szProperty, szVal, "0");	
+	ret = atoi(szVal);
+#else
+	if(idx == 1)
+		ret = 1;
+#endif
+
+	if(ret > 0)
+		return true;
+
+	return false;
+}
+
+int Context::getLoadType()  //eng : 1 or user : 2
+{
+	char szVal[128] = {0};
+	int  ret  = 0;
+
+#ifdef IS_SUPPORT_SP
+	property_get("ro.build.type", szVal, NULL);
+
+	if(strcmp(szVal,"eng")==0)
+	{
+		ret = 1;	
+	}
+	else if(strcmp(szVal,"user")==0)
+	{
+		ret = 2;
+	}
+	else if(strcmp(szVal,"userdebug")==0)
+	{
+		ret = 3;
+	}
+#else
+ 	ret = 1;
+#endif
+
+	META_LOG("[Meta] ro.build.type = %s ret = %d.",szVal,ret);
+	return ret;
+	
+}
+
+void Context::destroyModem(Modem *p)
+{	
+	if(p!=NULL)
+	{
+		m_mdmList.destroy_node(p);
+		delete p; //close handle
+		META_LOG("[Meta] Delete modem success.");
+	}
+	else
+	{
+		META_LOG("[Meta] Delete modem fail.");
+	}
+}
+
+Modem * Context::createModem(const char *ccci, unsigned short id)
+{
+	Modem *p = new Modem(ccci, id);
+
+	if(p!=NULL)
+	{
+		m_mdmList.push_back(p);
+		META_LOG("[Meta] Create modem%d success.",id+1);
+	}
+	else
+	{
+		META_LOG("[Meta] Create modem%d fail.",id+1);
+	}
+	return p;
+}
+
+Modem * Context::createModem(unsigned short id)
+{
+	Modem *p = new Modem(id);
+
+	if(p == NULL)
+	{
+		return NULL;
+	}
+
+	if(p->getDevHandle()> 0)
+	{
+		m_mdmList.push_back(p);
+		META_LOG("[Meta] Create modem%d success.",id+1);	
+	}
+	else
+	{
+		delete(p);
+		META_LOG("[Meta] Create modem%d failed.",id+1);
+		return NULL;	
+	}
+	return p;
+}
+
+
+CmdTarget * Context::getModule(unsigned short id)
+{
+	mlist<CmdTarget*>::iterator it = m_modList.begin();
+
+	while (it != m_modList.end())
+	{
+		//META_LOG("[Meta] it->id = %d",(*it)->getId());
+		if ((*it)->getId() == id)
+		{
+			return (*it);
+		}
+		++ it;
+	}
+	return NULL;
+}
+
+int Context::readSys_int(char const * path)
+{
+    int fd;
+    if (path == NULL)
+        return -1;
+
+    fd = open(path, O_RDONLY);
+    if (fd >= 0) 
+	{
+		int buffer[8] = {0};
+        int len = read(fd, &buffer, sizeof(int)*8);
+		META_LOG("[Meta] read boot mode struct len = %d\n", len);
+		if(len > 0)
+		{
+			META_LOG("[Meta] boot mode size = %d, tag = %d, mode = %d\n", buffer[0], buffer[1], buffer[2]);
+			close(fd);
+			return buffer[2];
+        }
+		close(fd);
+    }
+    META_LOG("[Meta] read boot mode failed to open %s\n", path);   
+	return -1;
+	
+}
+
+int Context::getBootMode()
+{
+	if(UNKNOWN_BOOT == m_bootMode)
+	{
+		m_bootMode = readSys_int(BOOTMODE_PATH);
+
+		if(NORMAL_BOOT== m_bootMode)
+		{
+			META_LOG("[Meta] Normal mode boot!");
+		}
+		else if(META_BOOT== m_bootMode)
+		{
+			META_LOG("[Meta] Meta mode boot!");
+		}
+		else
+		{
+			META_LOG("[Meta] Not Support boot mode! BootMode=%d",m_bootMode);
+			m_bootMode = UNKNOWN_BOOT;
+		}
+	}
+
+    return m_bootMode;
+}
+
+Modem * Context::getModem(unsigned short id)
+{
+	mlist<Modem*>::iterator it = m_mdmList.begin();
+
+	while (it != m_mdmList.end())
+	{
+		META_LOG("[Meta] modem it->id = %d",(*it)->getId());
+		if ((*it)->getId() == id)
+		{
+			return (*it);
+		}
+		++ it;
+	}
+	return NULL;
+}
+
+void Context::initModuleList()
+{
+		META_LOG("[Meta] Enter initModuleList");
+
+//#ifdef FT_WIFI_FEATURE
+	m_modList.push_back(new FtModWifi);
+//#endif
+
+#ifdef FT_GPS_FEATURE
+	m_modList.push_back(new FtModGPS);
+#endif
+
+#ifdef FT_NFC_FEATURE
+	m_modList.push_back(new FtModNFC);
+#endif
+
+#ifdef FT_BT_FEATURE
+	m_modList.push_back(new FtModBT);
+#endif
+
+#ifdef FT_FM_FEATURE
+	m_modList.push_back(new FtModFM);
+#endif
+
+#ifdef FT_AUDIO_FEATURE
+	m_modList.push_back(new FtModAudio);
+#endif
+
+#ifdef FT_CCAP_FEATURE
+	m_modList.push_back(new FtModCCAP);
+#endif
+
+#ifdef FT_DRM_KEY_MNG_FEATURE
+	m_modList.push_back(new FtModDRM);
+#endif
+
+#ifdef FT_GAMMA_FEATURE
+    m_modList.push_back(new FtModGAMMA);
+#endif
+
+#ifdef FT_ATTESTATION_KEY_FEATURE
+	m_modList.push_back(new FtModAttestationKey);
+#endif
+
+#ifdef FT_NVRAM_FEATURE
+	m_modList.push_back(new FtModNvramBackup);
+	m_modList.push_back(new FtModNvramRestore);
+	m_modList.push_back(new FtModNvramReset);
+	m_modList.push_back(new FtModNvramRead);
+	m_modList.push_back(new FtModNvramWrite);
+    m_modList.push_back(new FtModAPDB);
+#endif
+
+#ifdef FT_GSENSOR_FEATURE  
+	m_modList.push_back(new FtModGSensor);
+#endif
+
+#ifdef FT_MSENSOR_FEATURE
+	m_modList.push_back(new FtModMSensor);
+#endif
+
+#ifdef FT_ALSPS_FEATURE 
+	m_modList.push_back(new FtModALSPS);
+#endif
+
+#ifdef FT_GYROSCOPE_FEATURE   
+	m_modList.push_back(new FtModGyroSensor);
+#endif
+
+#ifdef FT_SDCARD_FEATURE	
+	m_modList.push_back(new FtModSDcard);
+#endif
+
+#ifdef FT_EMMC_FEATURE
+	m_modList.push_back(new FtModEMMC);
+#endif
+
+#ifdef FT_NAND_FEATURE
+	m_modList.push_back(new FtModEMMC);
+#endif
+
+#ifdef FT_CRYPTFS_FEATURE
+	m_modList.push_back(new FtModCRYPTFS);
+#endif
+
+#ifdef FT_ADC_FEATURE
+	m_modList.push_back(new FtModADC);
+#endif
+
+#ifdef FT_TOUCH_FEATURE
+	m_modList.push_back(new FtModCTP);
+#endif
+
+#ifdef FT_GPIO_FEATURE
+	m_modList.push_back(new FtModGPIO);
+#endif
+
+#ifdef FT_RAT_FEATURE
+	m_modList.push_back(new FtModRAT);
+#endif
+
+#ifdef FT_MSIM_FEATURE
+	m_modList.push_back(new FtModMSIM);
+#endif
+
+	m_modList.push_back(new FtModCustomer);
+	m_modList.push_back(new FtModChipID);
+	m_modList.push_back(new FtModTestAlive);
+	m_modList.push_back(new FtModVersionInfo);
+	m_modList.push_back(new FtModVersionInfo2);
+	m_modList.push_back(new FtModPowerOff);
+	m_modList.push_back(new FtModReboot);
+	m_modList.push_back(new FtModBuildProp);
+	m_modList.push_back(new FtModModemInfo);
+	m_modList.push_back(new FtModSIMNum);
+	m_modList.push_back(new FtModUtility);
+	m_modList.push_back(new FtModSpecialTest);
+	m_modList.push_back(new FtModChipInfo);
+	m_modList.push_back(new FtModFileOperation);
+	m_modList.push_back(new FtModTargetloggerCtrl);
+	m_modList.push_back(new FtModTargetClock);
+	m_modList.push_back(new FtModMetaDisconnect);
+	
+#ifdef MTK_META_SYSENV_SUPPORT  
+	m_modList.push_back(new FtModSysEnv);
+#endif
+
+	
+}
+
+unsigned int Context::getMdmInfo()
+{
+	unsigned int modem_number =0;
+	unsigned int active_modem_id = 0;
+	unsigned int modem_type = 0;
+	bool isactive = false;
+
+    if(IsModemSupport(3))
+	{
+	    modem_type |= MD3_INDEX;	
+		modem_number++;
+		META_LOG("[Meta] modem[3] is enable");
+	}
+	
+    if(IsModemSupport(1))
+	{
+		modem_type |= MD1_INDEX;	
+		modem_number++;
+		if(!isactive)
+		{
+		    active_modem_id = 1;
+			isactive = true;
+		}
+		META_LOG("[Meta] modem[1] is enable");
+	}
+
+    if(IsModemSupport(2))
+	{
+		modem_type |= MD2_INDEX;
+		modem_number++;
+		if(!isactive)
+		{
+			active_modem_id = 2;
+			isactive = true;
+		}
+		META_LOG("[Meta] modem[2] is enable");
+	}
+
+    if(IsModemSupport(5))
+	{
+		modem_type |= MD5_INDEX;	
+		modem_number++;
+		if(!isactive)
+		{
+			active_modem_id = 5;
+			isactive = true;
+		}
+		META_LOG("[Meta] modem[5] is enable");
+	}
+
+	META_LOG("[Meta] modem_type = %d, modem_number = %d, active_modem_id = %d", modem_type, modem_number, active_modem_id);
+
+	m_mdmType = modem_type;
+	m_mdmNumber = modem_number;
+	m_activeMdmId = active_modem_id;
+	
+	return modem_number;		
+}
+
+
+void Context::setLogLevel(unsigned int level)
+{
+	m_logLevel = level;
+}
+unsigned int Context::getLogLevel()
+{
+	return m_logLevel;
+}
+
+unsigned int Context::getMdmType()
+{
+	return m_mdmType;
+}
+
+
+unsigned int Context::getActiveMdmId()
+{
+	return m_activeMdmId;
+}
+
+
+unsigned int Context::getMdmNumber()
+{
+	return m_mdmNumber;		
+}
+
+signed int Context::getModemHandle(unsigned short id) 
+{
+	Modem *md = getModem(id);
+	if(md != NULL)
+		return md->getDevHandle();
+
+	return -1;
+}
+
+int Context::getDataChannelType()
+{
+	return m_mdDataChannel;
+}
+
+unsigned int Context::dumpData(const unsigned char* con, int length)
+{
+	META_LOG("[Meta] Dump data is:  ");
+	int i = 0;
+	for(i = 0; i < length; i++)
+		printf(" (%02x) ",con[i]);
+	META_LOG("[Meta] Dump finished!");
+	return 0;
+
+
+}
+
+unsigned int Context::dumpDataInHexString(const unsigned char* con, int length, unsigned int bytesPerRow)
+{
+
+//	if(getLogLevel() || getPropValue("persist.vendor.meta.dumpdata") == 1)
+	{
+		int i = 0;
+		unsigned int j = 0;
+		unsigned int rowLength = 3 * bytesPerRow + 1;
+		unsigned char hex[rowLength];
+		unsigned char high;
+		unsigned char low;
+		META_LOG("[Meta] Dump begin!");
+		for(i = 0; i < length; i++)
+		{
+			high = (con[i] >> 4);
+			low = (con[i] & 0x0f);
+		
+			if(high < 0x0a)
+         	   high += 0x30;
+        	else
+         	   high += 0x37;
+        
+        	if(low < 0x0a)
+        	    low += 0x30;
+        	else
+         	   low += 0x37;
+        
+        	hex[j++] = high;
+        	hex[j++] = low;
+        	hex[j++] = ' ';
+
+			if (j == rowLength - 1 || i == length - 1)
+			{
+				hex[j] = '\0';
+				j = 0;
+				META_LOG("%s", hex);
+			}
+		}
+
+		META_LOG("[Meta] Dump finished!");	
+	}
+	
+	return 0;
+}
+
+
+unsigned int Context::getFileSize(int fd)
+{
+	struct stat file_stat;
+	if(fstat(fd, &file_stat) < 0)
+	{
+		return 0;
+	}
+	else
+	{
+		return (unsigned int)file_stat.st_size;
+	}
+}
+
+
+const char* Context::makepath(unsigned char file_ID)
+{
+	if(access("/data/nvram/AllMap",F_OK)==0)
+	{
+	    META_LOG("[Meta] /data/nvram/AllMap exist");
+		if(file_ID == 0)
+		{
+			return "/data/nvram/AllMap";
+		}
+		else if(file_ID == 1)
+		{
+			return "/data/nvram/AllFile";	
+		}
+		else
+		{
+			META_LOG("[Meta] makepath error: invalid file_ID %d! ", file_ID);
+			return "";
+		}
+	}
+	else
+	{
+		META_LOG("[Meta] /data/nvram/AllMap not exist");
+		if(file_ID == 0)
+		{
+			return "/mnt/vendor/nvdata/AllMap";
+		}
+		else if(file_ID == 1)
+		{
+			return "/mnt/vendor/nvdata/AllFile";	
+		}
+		else
+		{
+			META_LOG("[Meta] makepath error: invalid file_ID %d! ", file_ID);
+			return "";
+		}
+	}
+}
+
+void Context::destroyAllModemThread()
+{
+	if(getMDThreadFlag()==1)
+	{
+		setMDThreadFlag(0);
+	}
+	else
+	{
+		META_LOG("[Meta] No MD thread!");
+		return;
+	}
+	unsigned int modemType = getMdmType();
+	
+	if((modemType & MD1_INDEX) == MD1_INDEX)
+	{
+		META_LOG("[Meta] DestroyModemThread 0");
+		destroyModemThread(0);
+	}
+
+	if((modemType & MD2_INDEX) == MD2_INDEX)
+	{
+		META_LOG("[Meta] DestroyModemThread 1");
+		destroyModemThread(1);
+	}
+
+#ifdef TST_C2K_SUPPORT
+	if((modemType & MD3_INDEX) == MD3_INDEX)
+	{
+		META_LOG("[Meta] DestroyModemThread 2");
+		destroyModemThread(2);
+	}
+#endif
+
+	if((modemType & MD5_INDEX) == MD5_INDEX)
+	{
+		META_LOG("[Meta] DestroyModemThread 4");
+		destroyModemThread(4);
+	}
+	
+}
+void Context::createSerPortThread()
+{
+	SerPort *pPort = NULL;
+	
+	pPort = createSerPort();
+	
+	if (pPort != NULL)
+	{
+		pPort->pumpAsync(&hostSerPortRx);
+	}
+	else
+	{
+		META_LOG("[Meta] Enter meta_tst normal mode init fail");
+	}
+
+}
+void Context::destroySerPortThread()
+{
+	SerPort *pPort = NULL;
+	pPort = getSerPort();
+	pPort->setExitFlag(1);
+	destroySerPort();
+}
+void Context::createAllModemThread()
+{
+	if(getMDThreadFlag()==0)
+	{
+		setMDThreadFlag(1);
+	}
+	else
+	{
+		META_LOG("[Meta] Alread created MD thread");
+		return;
+	}
+	unsigned int modemType = getMdmType();
+
+	META_LOG("[Meta] createAllModemThread - modemtype = %d", modemType);
+	if((modemType & MD1_INDEX) == MD1_INDEX)
+	{
+		META_LOG("[Meta] CreateAllModemThread 0");
+		createModemThread(0,0);
+		Modem *p = getModem(0);
+		if(p!=NULL)
+		{
+			META_LOG("[Meta] P is not NULL");	
+		}
+		else
+		{
+			META_LOG("[Meta] P is NULL");	
+		}
+	}
+
+	if((modemType & MD2_INDEX) == MD2_INDEX)
+	{
+		META_LOG("[Meta] CreateAllModemThread 1");
+		createModemThread(1,0);
+	}
+
+#ifdef TST_C2K_SUPPORT
+	if((modemType & MD3_INDEX) == MD3_INDEX)
+	{
+		META_LOG("[Meta] CreateAllModemThread 3");
+		createModemThread(2,0);
+	}
+#endif
+
+	if((modemType & MD5_INDEX) == MD5_INDEX)
+	{
+		META_LOG("[Meta] CreateAllModemThread 4");
+		createModemThread(4,0);
+	}
+}
+
+void Context::destroyModemThread(unsigned short modemIndex)
+{
+	Modem *p = getModem(modemIndex);
+	
+	if(p!=NULL)
+	{
+		p->popUpAsync();
+		destroyModem(p);
+		META_LOG("[Meta] DestroyModemThread success modemIndex = %d" ,modemIndex);		
+	}
+	else
+	{
+		META_LOG("[Meta] DestroyModemThread fail");		
+	}		
+}
+
+void Context::createModemThread(unsigned short modemIndex, int usbUsb)
+{
+
+	Modem *pMdHandle = NULL;	
+	MdRxWatcher *pRxWatcher = NULL;
+	pRxWatcher = new MdRxWatcher(modemIndex);
+
+	getModemProtocol(modemIndex, &m_modem_cap_list);
+	if((m_mdDataChannel == 1) && (modemIndex == 0))
+	{
+		notifyModemDoRF(modemIndex);
+		pMdHandle = createModem(modemIndex);
+	}
+
+	if(pMdHandle != NULL)
+	{
+	    pMdHandle->pumpAsync(pRxWatcher);
+	}
+	else
+	{
+	    delete pRxWatcher;
+	}
+}
+
+void Context::setActiveATModem(unsigned int activeATModemId)
+{
+	m_activeATModemId = activeATModemId;			
+}
+
+unsigned int Context::getActiveATModem()
+{
+	return m_activeATModemId;
+}
+
+int Context::getModemHwVersion(unsigned short modemIndex)
+{
+	if(MODEM_END == m_modem_hw_version)
+	{
+		if(-1 != queryModemProtocol(modemIndex))
+		{
+			META_LOG("[Meta][Protocol] get MD%d protocol, modem_protocol:%s",(modemIndex+1),m_modemProtocol);
+			if(strcmp(m_modemProtocol,"AP_TST") == 0)
+			{
+				m_modem_hw_version = MODEM_AP_TST;
+			}
+			else if(strcmp(m_modemProtocol,"DHL") == 0)
+			{
+				m_modem_hw_version = MODEM_DHL;
+			}
+			else if(strcmp(m_modemProtocol,"6292") == 0)
+			{
+				m_modem_hw_version = MODEM_6292;	
+			}
+			else if(strcmp(m_modemProtocol,"6293") == 0)
+			{
+				m_modem_hw_version = MODEM_6293;
+			}
+			else if(strcmp(m_modemProtocol,"6295") == 0)
+			{
+				m_modem_hw_version = MODEM_6295;
+			}
+		}
+	}
+
+	return m_modem_hw_version;
+}
+	
+int Context::getModemProtocol(unsigned short modemIndex, MODEM_CAPABILITY_LIST_CNF* modem_capa)
+{
+	int nRet = 1;
+	modem_capa->modem_cap[modemIndex].md_service = FT_MODEM_SRV_DHL;
+	modem_capa->modem_cap[modemIndex].ch_type = FT_MODEM_CH_TUNNELING;
+	m_mdDataChannel = 1;
+
+	META_LOG("[Meta][Protocol] modem_cap[%d]%d,%d",modemIndex,modem_capa->modem_cap[modemIndex].md_service,modem_capa->modem_cap[modemIndex].ch_type);
+				
+	return nRet;
+}
+
+FT_MODEM_CH_TYPE Context::getMDChType(unsigned short modemIndex)
+{
+	return m_modem_cap_list.modem_cap[modemIndex].ch_type;
+}
+
+unsigned int Context::getPropValue(const char *key)
+{
+#ifdef IS_SUPPORT_SP
+    char tempstr[128]={0};
+    property_get(key,tempstr,"0");
+	if(tempstr[0] == '1')
+	    return 1;
+	else
+		return 0;
+#else
+	return 0;
+#endif
+
+}
+
+unsigned int Context::getMDMode(void)
+{
+	return m_modem_boot_mode;
+}
+void Context::setMDMode(unsigned int modem_boot_mode)
+{
+	m_modem_boot_mode = modem_boot_mode; 
+}
+
+int Context::getIOCPort(unsigned int nModemIndex,int & bDataDevice)
+{
+	int fd = -1;
+	char dev_node[32] = {0};
+	
+	if((nModemIndex == 0) || (nModemIndex == 1) || (nModemIndex == 4 && ccci_get_version() == EDSDA))
+	{
+        snprintf(dev_node, 32, "%s", "/dev/ccci_ioctl4");
+	    fd = open(dev_node, O_RDWR|O_NOCTTY|O_NDELAY );
+		bDataDevice = 0;
+	}
+	else
+	{
+	    unsigned short id = getActiveMdmId() - 1; 
+		fd= getModemHandle(id);
+		bDataDevice = 1;
+	}
+
+	if(fd< 0)
+	{
+		META_LOG("[Meta]Open MD%d device note %s fail errno = %d",(nModemIndex+1),dev_node,errno);	
+	}
+
+	return fd;
+}
+
+int Context::queryModemProtocol(unsigned short modemIndex)
+{
+	int fd = -1;
+	int nRet = -1;
+
+
+	META_LOG("[META] m_modemProtocol[0] = %c",m_modemProtocol[0]);
+	if(0 == m_modemProtocol[0])
+	{
+		int bDataDevice = 0;
+
+		fd = getIOCPort(modemIndex,bDataDevice);
+		
+		if(fd >= 0 && 0 == ioctl(fd, CCCI_IOC_GET_MD_PROTOCOL_TYPE, m_modemProtocol))
+		{
+			META_LOG("[Meta][Protocol] get MD%d protocol, modem_protocol:%s",(modemIndex+1),m_modemProtocol);
+			nRet = 0;
+		}
+
+		if(bDataDevice == FALSE)
+		{
+			if(fd != -1)
+			{
+				close(fd);
+				META_LOG("[Meta][FT]Close fd");
+				fd = -1;
+			}
+		}
+	}
+	else
+	{
+		nRet = 0;
+	}
+
+	return nRet;
+}
+
+void Context::setMDThreadFlag(int modemThreadFlag)
+{
+	m_modemThreadFlag = modemThreadFlag;
+	META_LOG("[Meta] Set MD Thread Flag = %d",m_modemThreadFlag);
+}
+
+int Context::getMDThreadFlag()
+{
+	return m_modemThreadFlag;
+}
+
+unsigned int Context::checkMdStatus()
+{
+    int ret = 0;
+#ifdef IS_SUPPORT_SP
+	char status[128]={0};
+    property_get("vendor.mtk.md1.status",status, "0");
+	META_LOG("[Meta] modem status = %s", status);
+	if(0 ==	strncmp(status, "ready", 5)) //ccb owner tell us to check this property.
+		ret = 1;
+	else if(0 == strncmp(status, "exception", 9))
+		ret = 2;
+#else
+/*	int count = 0;
+	struct md_status_event status_buf;
+
+	META_LOG("[Meta] begin to open [/dev/ccci_md1_sta]");
+	int md_status_fd =  open("/dev/ccci_md1_sta", O_RDWR);
+	META_LOG("[Meta] end open [/dev/ccci_md1_sta]");
+	if (md_status_fd < 0)
+	{
+		META_LOG("[Meta] failed to open [/dev/ccci_md1_sta]");
+		return ret;
+	}
+
+	META_LOG("[Meta] begin to read [/dev/ccci_md1_sta]");
+	count = read(md_status_fd, &status_buf, sizeof(struct md_status_event));
+	if (count > 0)
+	{
+		META_LOG("[Meta] modem status = %d", status_buf.event_type); 
+        if (status_buf.event_type == MD_STA_EV_READY)
+			ret = 1;
+		else if(status_buf.event_type == MD_STA_EV_EXCEPTION)
+			ret = 2;
+	}
+*/
+	ret = 1; //ccci module not ready, so set default value.
+#endif
+	return ret;
+}
+
+void Context::setATRespFlag(int atFlag)
+{
+	m_atFlag = atFlag;	
+}
+
+int Context::getATRespFlag()
+{
+	return m_atFlag;
+}
+
+void Context::setCurrentMdMode(int mdMode)
+{
+	m_currentMdMode = mdMode;
+}
+
+int Context::notifyModemDoRFByATCI()
+{
+	META_LOG("[Meta] notifyModemDoRFByATCI");
+	if(0 == ChangeModemMode(2))
+	{
+	    setMDMode(2);//normal= 1 meta=2
+	}
+	return 0;
+}
+
+int Context::ChangeModemMode(int mode)  // 1:modem to normal  2:modem to meta
+{
+	unsigned int nRetry = 0;
+	int nMdStatus = 0;
+
+	META_LOG("[Meta] Enter ChangeModemMode");
+	META_LOG("[Meta] To wait modem ready");
+	do
+	{
+		nMdStatus = checkMdStatus();
+		if( 2 == nMdStatus) //Modem exception, return -1 immediatly
+		{
+			return -1;
+		}
+		usleep(100*1000);
+		nRetry++;
+		if(nRetry > 100)  //return if it takes more than 10 seconds
+		    return -1;
+	}while(0 == nMdStatus);
+
+
+	MSocket *pSocket = getSocket(SOCKET_ATCI_SERVER);
+	if(pSocket == NULL)
+	{
+		pSocket = createSocket(SOCKET_ATCI_SERVER);
+		if(pSocket != NULL)
+		{
+			int bInit = pSocket->initClient("adb_atci_socket", 0);
+			if(bInit == 0)
+			{
+				delSocket(SOCKET_ATCI_SERVER);
+				return -1;
+			}
+		}
+		else
+			return -1;
+	}
+
+	META_LOG("[META] Check Modem ready by send AT");
+
+	setATRespFlag(1);
+	pSocket->send_msg("AT\r");
+	nRetry = 0;
+	while(getATRespFlag()!=0)
+	{
+		usleep(100*1000);
+		if(getATRespFlag()==-1)
+			pSocket->send_msg("AT\r");		
+        nRetry++;
+		if(nRetry > 100)    //return if it takes more than 10 seconds
+		    return -1;
+	}
+/*
+	META_LOG("[META] Check sim status");
+	char strSimStatus[128] = {0};
+	property_get("persist.vendor.radio.simswitch",strSimStatus,"unknown");
+	nRetry = 0;
+	if((strcmp(strSimStatus,"1") == 0) || (strcmp(strSimStatus,"unknown") == 0))
+	{
+		META_LOG("[META] Sim1 is the main slot, need to send AT+ESUO=4 first");
+		setATRespFlag(1);
+		pSocket->send_msg("AT+ESUO=4\r");	
+
+		while(getATRespFlag()!=0)
+		{
+			usleep(100*1000);
+			nRetry++;
+			if(nRetry > 100)    //return if it takes more than 10 seconds
+				return -1;
+		}
+	}
+	else if(strcmp(strSimStatus,"2") == 0)
+	{
+		META_LOG("[META] Sim2 is the main slot, need to send AT+ESUO=5 first");
+		setATRespFlag(1);
+		pSocket->send_msg("AT+ESUO=5\r");	
+
+		while(getATRespFlag()!=0)
+		{
+			usleep(100*1000);
+			nRetry++;
+			if(nRetry > 100)    //return if it takes more than 10 seconds
+				return -1;
+		}
+	}
+*/
+   META_LOG("[Meta] Query current modem mode");
+	setCurrentMdMode(0);
+	pSocket->send_msg("AT+EMETACFG?\r");
+	nRetry = 0;
+	while(1)
+	{
+		if(1 == m_currentMdMode || 2 == m_currentMdMode) 
+			break;
+		usleep(100*1000);
+		nRetry++;
+		if(nRetry > 100)    //return if it takes more than 10 seconds
+			return -1;
+	}
+	META_LOG("[Meta] Current modem mode = %d", m_currentMdMode);
+	if(m_currentMdMode == mode)  //No need to switch modem mode, return 0 directly
+	{
+		META_LOG("[Meta] No need to switch modem mode");
+		return 0;
+	}
+
+	META_LOG("[META] Switch modem mode to %d", mode);
+	setATRespFlag(1);
+	if(mode == 1)
+	{
+		pSocket->send_msg("AT+EMETACFG=0\r");
+		META_LOG("[Meta] Send AT+EMETACFG=0");
+	}
+	else if(mode == 2)
+	{
+		pSocket->send_msg("AT+EMETACFG=1\r");
+		META_LOG("[Meta] Send AT+EMETACFG=1");
+	}
+	else
+	{
+		META_LOG("[Meta]Invalid mode = %d",mode);
+		return -1;
+	}
+	nRetry = 0;
+	while(getATRespFlag()!=0)
+	{
+		usleep(100*1000);
+		nRetry++;
+		if(nRetry > 100)    //return if it takes more than 10 seconds
+			return -1;
+	}
+
+	META_LOG("[META]AT+EMETACFG return OK, switch modem success");
+	return 0;
+}
+
+void Context::writeBootprof(char * str)
+{
+	FILE *pBootProfFile = NULL;
+    pBootProfFile = fopen("proc/bootprof","w");
+	if(pBootProfFile!=NULL)
+	{
+		 fputs(str,pBootProfFile);
+		 fclose(pBootProfFile);
+		 pBootProfFile = NULL;
+		 META_LOG("[META] write proc/bootprof success");
+	}
+	else
+	{
+		META_LOG("[META] open proc/bootprof fail!");
+	}
+}
+
+int Context::notifyModemDoRF(int mdIdx)
+{
+
+    META_LOG("[Meta] To wait modem ready");
+#ifdef IS_SUPPORT_SP
+	char dev_node[32] = {0};
+	const char *cmd = "AT+EMETACFG=1\r";
+        const char *cmdClearURC = "AT+EURCRPT=0\r";
+	const char *urc = "+EIND: 128";
+	const char *rsp = "OK";
+
+	while(0 == checkMdStatus())
+	{
+		META_LOG("[Meta] To check modem status before open USR_MUXD_DATA");
+		usleep(100*1000);
+	}
+
+	//write bootprof
+	writeBootprof((char *)"[META] checkMdStatus mtk.md1.status=ready.");
+
+	snprintf(dev_node, 32, "%s", ccci_get_node_name(USR_MUXD_DATA,(CCCI_MD)mdIdx));
+    signed int fd = open(dev_node, O_RDWR|O_NOCTTY);
+	if(fd < 0)
+	{
+		META_LOG("[Meta] Can't open CCCI MUXD channel: %s", dev_node);
+		return 0;	
+	}
+  
+	META_LOG("[Meta] open CCCI MUXD channel: %s", dev_node);
+	META_LOG("[Meta] To read modem URC");
+	waitMdResponse(fd, urc);
+
+	writeBootprof((char *)"[META] Wait Modem urc +EIND: 128");
+	
+	//Send AT command to modem
+	int len = write(fd, cmd, strlen(cmd));
+	META_LOG("[Meta] Send AT command - len = %d, cmd = %s", len, cmd);
+	META_LOG("[Meta] To read AT response");
+	waitMdResponse(fd, rsp);
+
+	writeBootprof((char *)"[META] AT+EMETACFG=1 return OK.");
+
+    int lenClearURC = write(fd, cmdClearURC, strlen(cmdClearURC));
+	META_LOG("[Meta] Send AT command - lenClearURC = %d, cmdClearURC = %s", lenClearURC, cmdClearURC);
+	
+	close(fd);   
+	META_LOG("[Meta] Close CCCI MUXD channel. fd = %d", fd);
+#else
+/*	while(0 == checkMdStatus())
+	{
+		META_LOG("[Meta] To check modem status before read URC");
+		usleep(100*1000);
+	}
+
+*/	MetaMIPC ipc;
+	const char *cmd = "AT+EMETACFG=1\r";
+	char rsp[1024] = {0};
+	
+	ipc.Init();
+/*
+	while(!ipc.IsModemReady())	
+	{
+		META_LOG("[Meta] [META] Wait Modem urc [+EIND: 128]");
+		usleep(500*1000);
+	}
+*/
+	if(ipc.Send_at_cmd(cmd, rsp))
+	{
+		if(NULL != strstr(rsp, "OK"))
+		{
+			META_LOG("[Meta] modem seamless switch successful");
+		}
+		else
+		{
+			META_LOG("[Meta] modem seamless switch failed");
+		}
+	}		
+#endif	
+
+	return 0;
+}
+
+void Context::waitMdResponse(int fd, const char *rsp)
+{
+	char szbuf[1024] = {0};
+	char data[33] = {0};
+	int  len = 0;
+	int  totalLen = 0;
+
+	while(1)
+	{
+		len = ::read(fd, data, 32);
+		if(len > 0)
+		{
+			data[len] = '\0';
+			META_LOG("[Meta] read data from AT channel: len= %d,  %s", len, data);
+			dumpDataInHexString((const unsigned char*)data,len, 16);
+			strncpy(szbuf+totalLen, data, len);
+			totalLen += len;
+			if(totalLen >= 1024)
+			{
+				totalLen = 0;
+				META_LOG("[Meta] Modem response too long");
+			}
+
+			if( NULL != strstr(szbuf, rsp))
+				break;
+		}
+		memset(data, 0, 33);
+	}
+	META_LOG("[Meta] Read AT response sucess");
+}
+
+MSocket* Context::createSocket(SOCKET_TYPE type)
+{
+	for(int i=0; i<SOCKET_END; i++)
+	{
+		if(m_socket[i] == NULL)
+		{
+			switch(type)
+			{
+				case SOCKET_MDLOGGER:
+				case SOCKET_MOBILELOG:
+				case SOCKET_CONNSYSLOG:
+				case SOCKET_GPSLOGGER:
+					m_socket[i]  = (MSocket*)new MLogSocket(type);	
+					break;
+				case SOCKET_ATCI_CLIENT:
+					m_socket[i]  = (MSocket*)new MATCIClientSocket(type);	
+					break;
+				case SOCKET_ATCI_SERVER:
+					m_socket[i]  = (MSocket*)new MATCIServerSocket(type);	
+					break;
+				case SOCKET_ATM_COMM:
+					m_socket[i]  = (MSocket*)new MATMSocket(type);	
+					break;
+				default:
+					return NULL;
+			}
+			
+			if(m_socket[i] != NULL)
+	        {
+				//META_LOG("[Meta][Socket] Create socket success. idx=%d, pSocket=0x%08x, type=%d", i, m_socket[i], m_socket[i]->m_type);
+				return m_socket[i];
+	        }
+	        else
+	        {
+		        META_LOG("[Meta][Socket] Create socket fail.");
+				return NULL;
+			}
+		}
+	}
+	
+	META_LOG("[Meta][Socket] no empty socket object!");
+	return NULL;
+
+}
+
+MSocket* Context::getSocket(SOCKET_TYPE type)
+{
+	
+	META_LOG("[Meta][Socket] To get socket object!");
+	for(int i=0; i<SOCKET_END; i++)
+	{
+		if(m_socket[i] != NULL)
+		{
+			//META_LOG("[Meta][Socket] Get socket,  idx=%d, pSocket=0x%08x, type=%d", i, m_socket[i], m_socket[i]->m_type);		
+			if(m_socket[i]->m_type == type)
+				return m_socket[i];
+		}
+	}
+
+	META_LOG("[Meta][Socket] Can not find socket object!");
+	return NULL;	
+}
+
+void Context::delSocket(SOCKET_TYPE type)
+{
+	META_LOG("[Meta][Socket] To delete socket object!");
+	for(int i=0; i<SOCKET_END; i++)
+	{
+		if(m_socket[i] != NULL)
+		{
+			//META_LOG("[Meta][Socket] Get socket,  idx=%d, pSocket=0x%08x, type=%d", i, m_socket[i], m_socket[i]->m_type);		
+			if(m_socket[i]->m_type == type)
+			{
+				free(m_socket[i]);
+				m_socket[i] = NULL;
+			}
+		}
+	}
+
+	return;
+}
+void Context::destroyVirtualRxThread()
+{
+	SerPort *pPort = getSerPort();
+	if(pPort!=NULL)
+	{
+        pPort->setExitFlag(1);
+        pPort->setSerPortExitFlag();  //Stop socket connect while loop
+        pPort->waitForThreadExit();   //Sync virtual rx thread with main thread before destroy
+		//destroyPortHandle();
+		destroySerPort();
+		META_LOG("[Meta] destroyVirtualRxThread success" );
+	}
+	else
+	{
+		META_LOG("[Meta] destroyVirtualRxThread fail");
+	}
+}
+
+//For USB,UART,SOCKET, etc.
+void Context::createVirtualRxThread()
+{
+    SerPort *pPort = createSerPort();
+	UsbRxWatcher *pVirtualRxWatcher = getVirtualRxWatcher();
+
+	if (pPort != NULL && pVirtualRxWatcher != NULL)
+	{
+	    META_LOG("[Meta] createVirtualRxThread success");
+		pPort->pumpAsync(pVirtualRxWatcher);
+	}
+	else
+	{
+		META_LOG("[Meta] createVirtualRxThread fail");
+	}
+}
+
+UsbRxWatcher * Context::getVirtualRxWatcher() const
+{
+	return m_virtualRxWatcher;
+}
+
+void Context::setVirtualRxWatcher(UsbRxWatcher * virtualRxWatcher)
+{
+	m_virtualRxWatcher = virtualRxWatcher;
+}
+
+void Context::queryNormalModeTestFlag()
+{
+	m_normalModeTestFlag = getProductInfo(0, OFFSET_ATM);
+}
+
+int Context::getNormalModeTestFlag()
+{
+	return m_normalModeTestFlag;
+}
+
+int Context::setNormalModeTestFlag(int flag)
+{
+   return modifyProductInfo(0, flag, OFFSET_ATM);
+}
+
+int Context::modifyProductInfo(int type, int flag, int offset)
+{
+	int fd = -1;
+    int result = 0;
+    int cipherText = 0;
+    char write_buf[1024] = {0};
+	char log_flag = 0;
+
+	META_LOG("[Meta][FT] setProductInfo flag = %d", flag);
+
+	if(type == 0) //ATM flag
+    {
+		cipherText = encrypt((KEY1+flag), KEY2);
+		META_LOG("[Meta][FT] setProductInfo after encrypt, flag = %d", cipherText);
+		sprintf(write_buf, "%d", cipherText);
+	}
+	
+	fd = open(FLAG_PATH, O_RDWR);
+	if(fd < 0)
+	{
+		META_LOG("[Meta][FT] setProductInfo open /proinfo fail, errno = %d", errno);
+		return -1;
+	} 
+	else
+	{
+		if(lseek(fd, offset, SEEK_SET) < 0)
+		{
+			META_LOG("[Meta][FT] setProductInfo lseek failed.");
+			close(fd);
+			fd = NULL_FILE_DESCRIPTOR;
+			return -1;
+		}
+
+		if(type == 0) //ATM flag
+			result = write(fd, write_buf, ENCRYPT_LENTH); 
+		else if(type == 1) //meta log
+		{
+			log_flag = (char)flag;
+			result = write(fd, &log_flag, 1);
+		}
+
+		if(result > 0)
+		{
+			META_LOG("[Meta][FT] setProductInfo write /proinfo success");
+			close(fd);
+			fd = NULL_FILE_DESCRIPTOR;
+			return 0;
+		}
+		else
+		{
+			META_LOG("[Meta][FT] setProductInfo write /proinfo fail, errno = %d", errno);
+			close(fd);
+			fd = NULL_FILE_DESCRIPTOR;
+			return -1;
+		}
+	}
+}
+
+int Context::setProductInfo(int type, int flag, int offset)
+{
+	return modifyProductInfo(type, flag, offset);
+}
+
+int Context::getProductInfo(int type, int offset)
+{
+    int fd = -1;
+    char read_buf[1024] = {0};
+    int result = 0;
+    int val = -1;
+    char log_val = -1;
+    int ret = 0;
+  
+    fd = open(FLAG_PATH,O_RDWR);
+    if(fd < 0)
+    {
+       META_LOG("[Meta][FT] queryProductInfo open /proinfo fail, errno = %d", errno);
+       return val;
+    }
+    ret = lseek(fd, offset, SEEK_SET);
+    if(ret == -1)
+    {
+        close(fd);
+        return -1;
+    }
+
+    if(type == 0)
+    {
+    	result = read(fd, read_buf, ENCRYPT_LENTH);
+	META_LOG("[Meta][FT] queryProductInfo read /proinfo success");
+	META_LOG("[Meta][FT] queryProductInfo before decrypt, flag = %d", atoi(read_buf));
+	if(result > 0)
+	    val = decrypt(atoi(read_buf), KEY2) - KEY1;
+    }
+    else if(type == 1)
+    {
+	result = read(fd, &log_val, 1);
+	val = log_val;
+    }
+	
+    if(result > 0)
+    {
+
+        META_LOG("[Meta][FT] queryProductInfo flag = %d", val);
+	}
+	else
+	{
+		META_LOG("[Meta][FT] queryProductInfo read /proinfo fail, errno = %d", errno);
+	}
+
+	close(fd);
+	fd = NULL_FILE_DESCRIPTOR;
+
+	return val;
+}
+
+void Context::queryWifiPara(int argc, char** argv)
+{	
+    META_LOG("[Meta] Enter queryWifiPara");
+    const char* wifi_opt = "a:p:";
+    int opt = 0;
+
+    while( (opt = getopt(argc, argv, wifi_opt)) != -1)
+    {
+        META_LOG("[Meta] queryWifiPara opt = %d", opt);
+        switch(opt)
+        {			
+            case 'a':
+                m_WifiPara.ip_addr = optarg;
+                META_LOG("[Meta] queryWifiPara get ip address: %s", m_WifiPara.ip_addr);
+                break;
+            case 'p':
+                m_WifiPara.port = atoi(optarg);
+                META_LOG("[Meta] queryWifiPara get port: %d", m_WifiPara.port);
+                break;
+            default:
+                META_LOG("[Meta] queryWifiPara invalid option!");
+                break;
+        }
+    }
+
+    META_LOG("[Meta] Exit queryWifiPara");
+}
+
+WIFI_PARA Context::getWifiPara()
+{
+#ifdef IS_SUPPORT_SP
+    char strIpAddr[128] = {0};
+    property_get("persist.vendor.atm.ipaddress", strIpAddr, "0,0,0,0");
+    m_WifiPara.ip_addr = strIpAddr;
+    m_WifiPara.port = 9000;
+#endif
+
+    return m_WifiPara;
+}
+
+int Context::writePortIndex() 
+{
+    int res = 0;
+    int fd = ::open("/sys/class/android_usb/android0/f_acm/port_index", O_WRONLY);
+    if (fd != -1)
+    {
+        res = ::write(fd,"1,4",4);
+		if(res>0)
+        {
+            META_LOG("[Meta] writePortIndex /sys/class/android_usb/android0/f_acm/port_index 1,4 Success");
+			close(fd);
+			fd = NULL_FILE_DESCRIPTOR;
+		    return 0;
+		}
+		else
+		{
+			META_LOG("[Meta] writePortIndex /sys/class/android_usb/android0/f_acm/port_index 1,4 Failed");
+			close(fd);
+			fd = NULL_FILE_DESCRIPTOR;
+			return -1;
+		}
+    }
+    else
+    {
+        META_LOG("[Meta] Failed to open:/sys/class/android_usb/android0/f_acm/port_index");
+		return -1;
+    }
+         	
+}
+
+void Context::switchComType(META_COM_TYPE targetComType)
+{
+	if(getComType() != targetComType)
+	{
+		usbMutexLock(true);
+		destroyVirtualRxThread();
+		usleep(100*1000); //sleep 100 ms
+		setComType(targetComType);
+#ifndef MTK_ATM_METAWIFIONLY
+		createVirtualRxThread();
+#else
+		if(META_SOCKET == targetComType)
+		{
+			createVirtualRxThread();
+		}
+#endif
+		META_LOG("[Meta] Change connect type to %d", (int)targetComType);
+		usbMutexLock(false);
+	}
+	else
+	{
+		META_LOG("[Meta] Connect type is already %d, no need to switch", (int)targetComType);
+	}
+}
+
+void Context::SetDataCompressStatus(unsigned int enable)
+{
+	m_dataCompressStatus = enable;
+}
+unsigned int Context::GetDataCompressStatus()
+{
+	return m_dataCompressStatus;
+}
+
+void Context::HandleSocketCmd(char* socket_cmd)
+{
+
+#ifdef IS_SUPPORT_SP
+	if(sizeof(socket_cmd) > 32) {
+		META_LOG("[Meta] HandleSocketCmd: Invalid socket command: %s", socket_cmd);
+		return;
+	}
+	META_LOG("[Meta] HandleSocketCmd: command: %s", socket_cmd);
+
+	if(strstr(socket_cmd, "ATM_WIFI_INFO_IP_ADDRESS") != NULL)
+	{
+		string strcmd = string(socket_cmd);
+		string strIP = strcmd.erase(0, strcmd.find_last_of(':')+1);
+		property_set("persist.vendor.atm.ipaddress", strIP.c_str());
+		META_LOG("[Meta] HandleSocketCmd: ipaddr: %s", strIP.c_str());
+	}	
+	else
+	{
+	if(0 == strcmp(socket_cmd, "ATM_SWITCH_META_TO_WIFI")) {
+		switchComType(META_SOCKET);
+			property_set("persist.vendor.meta.connecttype", "wifi");
+	} else if(0 == strcmp(socket_cmd, "ATM_SWITCH_META_TO_USB")) {
+		switchComType(META_USB_COM);
+			property_set("persist.vendor.meta.connecttype", "usb");
+	} else if(0 == strcmp(socket_cmd, "ATM_SWITCH_MODEM_TO_META")) {
+		if(0 == ChangeModemMode(2))
+		{
+			META_LOG("[Meta] HandleSocketCmd: switch modem to META mode success");
+			setMDMode(2);
+			property_set("persist.vendor.atm.mdmode", "meta");
+		}
+		else
+		{
+			META_LOG("[Meta] HandleSocketCmd: switch modem to META mode fail");
+		}
+	} else if(0 == strcmp(socket_cmd, "ATM_SWITCH_MODEM_TO_NORMAL")) {
+		if(0 == ChangeModemMode(1))
+		{
+			META_LOG("[Meta] HandleSocketCmd: switch modem to normal mode success");
+			setMDMode(1);
+			property_set("persist.vendor.atm.mdmode", "normal");
+		}
+		else
+		{
+			META_LOG("[Meta] HandleSocketCmd: switch modem to normal mode fail");
+		}
+	} else if(0 == strcmp(socket_cmd, "ATM_DESTORY_WIFI_SOCKET")) {
+		destroyVirtualRxThread();
+		setComType(META_UNKNOWN_COM);
+	} else if(0 == strcmp(socket_cmd, "ATM_NEW_WIFI_SOCKET")) {
+		setComType(META_SOCKET);
+		createVirtualRxThread();
+	} else if(0 == strcmp(socket_cmd, "ATM_REBOOT_MODEM")) {
+		int bDataDevice = 0;
+		int fd = getIOCPort(0, bDataDevice);
+		if(fd >= 0)
+		{
+			if(0 == ioctl(fd, CCCI_IOC_MD_RESET))
+			{
+				setMDMode(1);
+				property_set("persist.vendor.atm.mdmode", "normal");
+				META_LOG("[Meta] HandleSocketCmd: reboot modem to normal mode success");
+			}
+			else
+			{
+				META_LOG("[Meta] HandleSocketCmd: reboot modem to normal mode fail");
+			}
+			if(FALSE == bDataDevice)
+			{
+				close(fd);
+				META_LOG("[Meta] HandleSocketCmd: close fd: %d", fd);
+				fd = -1;
+			}
+		}
+		}
+
+	}
+#endif
+}
+//////////////////////////////////////////////////////////////////////////
+
+void destroyModem(Modem *p)
+{
+	return Context::instance()->destroyModem(p);	
+}
+
+Modem * createModem(const char *ccci, unsigned short id)
+{
+	return Context::instance()->createModem(ccci, id);
+}
+
+Modem * createModem(unsigned short id)
+{
+	return Context::instance()->createModem(id);
+}
+
+CmdTarget * getModule(unsigned short id)
+{
+	return Context::instance()->getModule(id);
+}
+
+Modem * getModem(unsigned short id)
+{
+	return Context::instance()->getModem(id);
+}
+
+unsigned int dumpData(const unsigned char* con, int length)
+{
+	return Context::instance()->dumpData(con,length);
+}
+
+unsigned int dumpDataInHexString(const unsigned char* con, int length, unsigned int bytesPerRow)
+{
+	return Context::instance()->dumpDataInHexString(con,length,bytesPerRow);
+}
+
+unsigned int getFileSize(int fd)
+{
+	return Context::instance()->getFileSize(fd);
+}
+
+const char* makepath(unsigned char file_ID)
+{
+	return Context::instance()->makepath(file_ID);
+}
+
+void destroyContext()
+{
+	return Context::instance()->destroy();
+}
+
+unsigned int getMdmType()
+{
+	return Context::instance()->getMdmType();
+}
+
+unsigned int getActiveMdmId()
+{
+	return Context::instance()->getActiveMdmId();
+}
+
+unsigned int getMdmNumber()
+{
+	return Context::instance()->getMdmNumber();
+}
+
+signed int getModemHandle(unsigned short id)
+{
+	return Context::instance()->getModemHandle(id);
+}
+
+void setLogLevel(unsigned int level)
+{
+	return Context::instance()->setLogLevel(level);	
+}
+unsigned int getLogLevel()
+{
+	return Context::instance()->getLogLevel();	
+}
+
+void destroyModemThread(unsigned short modemIndex)
+{
+	return Context::instance()->destroyModemThread(modemIndex);
+}
+
+void destroyAllModemThread()
+{
+	return Context::instance()->destroyAllModemThread();
+}
+
+void createAllModemThread()
+{
+	return Context::instance()->createAllModemThread();		
+}
+
+
+void createModemThread(unsigned short modemIndex,int usbUsb)
+{
+	return Context::instance()->createModemThread(modemIndex,usbUsb);	
+}
+
+void createSerPortThread()
+{
+	return Context::instance()->createSerPortThread();
+}
+
+void destroySerPortThread()
+{
+	return Context::instance()->destroySerPortThread();	
+}
+
+
+int getModemProtocol(unsigned short modemIndex, void* modem_capa)
+{
+    return Context::instance()->getModemProtocol(modemIndex, (MODEM_CAPABILITY_LIST_CNF*)modem_capa);
+}
+
+int getMDChType(unsigned short modemIndex)
+{
+    return Context::instance()->getMDChType(modemIndex);
+}
+
+unsigned int getMDMode(void)
+{
+	return Context::instance()->getMDMode();;
+}
+
+void setMDMode(unsigned int modem_boot_mode)
+{
+	return Context::instance()->setMDMode(modem_boot_mode);
+}
+
+void setActiveATModem(unsigned int activeATModemId)
+{
+	return Context::instance()->setActiveATModem(activeATModemId);			
+}
+
+unsigned int getActiveATModem()
+{
+	return Context::instance()->getActiveATModem();	
+}
+
+int getIOCPort(unsigned int nModemIndex,int & bDataDevice)
+{
+	return Context::instance()->getIOCPort(nModemIndex,bDataDevice);
+}
+
+int getBootMode()
+{
+	return Context::instance()->getBootMode();
+}
+
+void queryNormalModeTestFlag()
+{
+	return Context::instance()->queryNormalModeTestFlag();
+}
+
+int getNormalModeTestFlag()
+{
+	return Context::instance()->getNormalModeTestFlag();
+}
+
+int setNormalModeTestFlag(int flag)
+{
+	return Context::instance()->setNormalModeTestFlag(flag);
+}
+
+int setProductInfo(int type, int flag, int offset)
+{
+	return Context::instance()->setProductInfo(type, flag, offset);
+}
+
+int getProductInfo(int type, int offset)
+{
+	return Context::instance()->getProductInfo(type, offset);
+}
+
+int getDataChannelType()
+{
+	return Context::instance()->getDataChannelType();
+}
+
+int getPropValue(const char *key)
+{
+	return Context::instance()->getPropValue(key);
+}
+
+MSocket * createSocket(unsigned int  type)
+{
+	return Context::instance()->createSocket((SOCKET_TYPE)type);
+}
+
+MSocket * getSocket(unsigned int  type)
+{
+	return Context::instance()->getSocket((SOCKET_TYPE)type);
+} 
+
+void delSocket(unsigned int  type)
+{
+	return Context::instance()->delSocket((SOCKET_TYPE)type);
+}
+void destroyVirtualRxThread()
+{
+	return Context::instance()->destroyVirtualRxThread();
+}
+
+void createVirtualRxThread()
+{
+	return Context::instance()->createVirtualRxThread();
+}
+
+void setVirtualRxWatcher(UsbRxWatcher * virtualRxWatcher)
+{
+	return Context::instance()->setVirtualRxWatcher(virtualRxWatcher);
+}
+
+int getLoadType()
+{
+	return Context::instance()->getLoadType();
+}
+
+int getModemHwVersion(unsigned short modemIndex)
+{
+	return Context::instance()->getModemHwVersion(modemIndex);
+}
+
+void queryWifiPara(int argc, char** argv)
+{
+    return Context::instance()->queryWifiPara(argc, argv);
+}
+
+WIFI_PARA getWifiPara()
+{
+    return Context::instance()->getWifiPara();
+}
+
+void setATRespFlag(int atFlag)
+{
+	return Context::instance()->setATRespFlag(atFlag);
+}
+
+int getATRespFlag()
+{
+	return Context::instance()->getATRespFlag();
+}
+
+int notifyModemDoRFByATCI()
+{
+	return Context::instance()->notifyModemDoRFByATCI();
+}
+
+int ChangeModemMode(int mode)
+{
+	return Context::instance()->ChangeModemMode(mode);
+}
+
+int writePortIndex()
+{
+	return Context::instance()->writePortIndex();
+}
+
+void writeBootprof(char * str)
+{
+	return Context::instance()->writeBootprof(str);
+}
+
+
+void setCurrentMdMode(int mdMode)
+{
+	return Context::instance()->setCurrentMdMode(mdMode);
+}
+
+void HandleSocketCmd(char* socket_cmd)
+{
+	return Context::instance()->HandleSocketCmd(socket_cmd);
+}
+
+int readSys_int(char const * path)
+{
+	return Context::instance()->readSys_int(path);
+}
+
+unsigned int checkMdStatus()
+{
+	return Context::instance()->checkMdStatus();
+
+}
+
+void SetDataCompressStatus(unsigned int enable)
+{
+	return Context::instance()->SetDataCompressStatus(enable);
+}
+unsigned int GetDataCompressStatus()
+{
+	return Context::instance()->GetDataCompressStatus();
+}
+
+
diff --git a/src/devtools/meta/src/common/src/Device.cpp b/src/devtools/meta/src/common/src/Device.cpp
new file mode 100644
index 0000000..df6d0c5
--- /dev/null
+++ b/src/devtools/meta/src/common/src/Device.cpp
@@ -0,0 +1,150 @@
+#include <assert.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+#include "Context.h"
+#include "Device.h"
+#include "LogDefine.h"
+
+#define BUF_SIZE (64+12)*1024+6
+IDevWatcher::~IDevWatcher(void){}
+
+Device::Device(void)
+	: m_exitFlag(0), m_fd(NULL_FILE_DESCRIPTOR), m_pWatcher(NULL)
+{
+	m_wMutex = PTHREAD_MUTEX_INITIALIZER;
+	memset(&m_thread, 0, sizeof(pthread_t));
+	m_buf = (unsigned char *)malloc(BUF_SIZE);
+	if(m_buf != NULL)
+		memset(m_buf, 0, BUF_SIZE);
+}
+
+Device::~Device(void)
+{
+	if (m_fd != NULL_FILE_DESCRIPTOR)
+	{
+		::close(m_fd);
+        m_fd = NULL_FILE_DESCRIPTOR;
+	}
+
+	if(m_buf != NULL)
+	{
+		free(m_buf);
+		m_buf = NULL;
+	}
+
+	if(m_pWatcher != NULL)
+	{
+		delete(m_pWatcher);
+		m_pWatcher = NULL;
+	}
+
+}
+
+void Device::close()
+{
+	META_LOG("[Meta] Close Handle m_fd = %d",m_fd);
+	if(m_fd != NULL_FILE_DESCRIPTOR)
+	{
+		int result = ::close(m_fd);
+		META_LOG("[Meta] Close handle success result = %d",result);
+		m_fd = NULL_FILE_DESCRIPTOR;
+	}
+}
+
+signed int Device::read(unsigned char *buf, unsigned int len)
+{
+	int tmpLen = 0;
+
+	if(m_fd < 0)
+		sleep(1);
+	else
+	        tmpLen = ::read(m_fd, buf, len);
+	//META_LOG("[Meta] read data from device: len =%d , m_fd = %d", tmpLen, m_fd);
+	return tmpLen;
+}
+
+signed int Device::write(const unsigned char *p, unsigned int len)
+{
+    int bytes_written = -1;
+	int remain_size = len;
+	pthread_mutex_lock(&m_wMutex);
+	while(remain_size > 0)
+	{
+		bytes_written = ::write(m_fd, p, remain_size);
+		if (bytes_written < 0) 
+		{
+			 META_LOG("[Meta] Write data to device failed, return %d, errno=%d, m_fd=%d", bytes_written, errno, m_fd);
+			 pthread_mutex_unlock(&m_wMutex);
+			 return bytes_written;
+		}
+		else
+		{
+			META_LOG("[Meta] Write %d bytes to device: m_fd = %d, ", bytes_written, m_fd);
+		}
+		remain_size -= bytes_written;
+		p += bytes_written;
+	}
+	pthread_mutex_unlock(&m_wMutex);
+	return (len - remain_size);
+}
+
+signed int Device::pump(IDevWatcher *p)
+{
+	//unsigned char buf[65*1024+6]={0};
+//	unsigned char buf[(64+12)*1024+6]={0};
+	int len = 0;
+
+	assert (p != NULL);
+	if(m_buf == NULL)
+	{
+		META_LOG("[Meta] failed to malloc rx buf");
+		return 0;
+	}
+	
+	while (m_exitFlag == 0)
+	{
+		len = read(m_buf, BUF_SIZE);
+
+		if (len > 0)
+		{
+			p->onReceived(m_buf, len);
+		}
+	}
+	return 0;
+}
+
+void Device::setExitFlag(unsigned int exitFlag)
+{
+	m_exitFlag = exitFlag;	
+}
+
+signed int Device::pumpAsync(IDevWatcher *p)
+{
+	m_pWatcher = p;
+	pthread_create(&m_thread, NULL, ThreadProc, this);
+	return 0;
+}
+
+void *Device::ThreadProc(void *p)
+{
+	Device *inst = (Device*)p;
+	inst->pump(inst->m_pWatcher);
+	return NULL;
+}
+
+void Device::waitForThreadExit()
+{
+    pthread_join(m_thread, NULL);
+}
+
+void Device::update()
+{
+}
+
+
+
+
diff --git a/src/devtools/meta/src/common/src/Frame.cpp b/src/devtools/meta/src/common/src/Frame.cpp
new file mode 100644
index 0000000..dd496ec
--- /dev/null
+++ b/src/devtools/meta/src/common/src/Frame.cpp
@@ -0,0 +1,33 @@
+#include <stddef.h>
+#include <string.h>
+#include "Frame.h"
+#include "CmdTarget.h"
+#include "LogDefine.h"
+
+Frame::Frame(const META_RX_DATA &data, CmdTarget *mod)
+	: m_myMod(mod), m_frmData(data),m_isValid(1)
+{
+}
+Frame::Frame()
+	: m_isValid(0)
+{
+    m_myMod = NULL;
+	memset(&m_frmData, 0, sizeof(META_RX_DATA));
+}
+
+
+Frame::~Frame(void)
+{
+}
+
+void Frame::exec()
+{
+	if (m_myMod != NULL)
+	{
+		m_myMod->exec(this);
+	}
+	else
+	{
+		META_LOG("[Meta] No module assigned; data discarded.");
+	}
+}
diff --git a/src/devtools/meta/src/common/src/FtModule.cpp b/src/devtools/meta/src/common/src/FtModule.cpp
new file mode 100644
index 0000000..4cc838f
--- /dev/null
+++ b/src/devtools/meta/src/common/src/FtModule.cpp
@@ -0,0 +1,4594 @@
+#ifdef IS_SUPPORT_SP
+#ifdef FT_DRM_KEY_MNG_FEATURE
+#ifdef FT_DRM_KEY_MNG_TEE_FEATURE
+#include "Keymanage.h"
+#include <vendor/mediatek/hardware/keymanage/1.0/IKeymanage.h>
+using namespace vendor::mediatek::hardware::keymanage::V1_0;
+#else
+#include "Keyinstall.h"
+#include <vendor/mediatek/hardware/keyinstall/1.0/IKeyinstall.h>
+using namespace vendor::mediatek::hardware::keyinstall::V1_0;
+#endif
+#endif
+#include <vendor/mediatek/hardware/nvram/1.1/INvram.h>
+
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+//#include "sysenv_utils.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/reboot.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <time.h>
+
+#include "FtModule.h"
+#include "LogDefine.h"
+#include "Context.h"
+#include "PortInterface.h"
+#include "PortHandle.h"
+#include <sys/time.h>
+#include "ccci_intf.h" 
+
+#include "MSocket.h"
+
+
+#define SIM_SWITCH_MODE_FILE  "/sys/mtk_ssw/mode"
+#define SIM_SWITCH_MODE_STR_LEN 8
+
+#define MTK_MDDB_PATH 	"vendor/etc/mddb"
+#define MTK_APDB_PATH   "vendor/etc/apdb"
+
+#ifndef FT_CNF_OK
+#define FT_CNF_OK 0
+#endif
+#ifndef FT_CNF_FAIL
+#define FT_CNF_FAIL 1
+#endif
+
+#if defined(__LP64__)
+#define CCAP_LIB_PATH "/system/lib64/libccap.so"
+#else
+#define CCAP_LIB_PATH "/system/lib/libccap.so"
+#endif
+
+
+FtModWifi::FtModWifi(void)
+	:CmdTarget(FT_WIFI_REQ_ID)
+{
+}
+
+FtModWifi::~FtModWifi(void)
+{
+}
+
+void FtModWifi::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+	META_LOG("[Meta][FT] FT_WIFI_OP ");
+	
+#ifdef FT_WIFI_FEATURE
+    META_WIFI_OP((FT_WM_WIFI_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+#else
+    //write fake for DataCard
+	FT_TARGETLOG_CTRL_CNF  ft_cnf;	
+    memset(&ft_cnf, 0, sizeof(FT_TARGETLOG_CTRL_CNF));
+	FT_TARGETLOG_CTRL_REQ *req = (FT_TARGETLOG_CTRL_REQ *)pFrm->localBuf();
+    ft_cnf.status = META_FAILED;
+    ft_cnf.header.id = req->header.id +1;
+    ft_cnf.header.token = req->header.token;
+    ft_cnf.type= req->type;
+
+	WriteDataToPC(&ft_cnf, sizeof(FT_TARGETLOG_CTRL_CNF),NULL, 0);
+#endif
+    
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_GPS_FEATURE
+
+FtModGPS::FtModGPS(void)
+	:CmdTarget(FT_GPS_REQ_ID)
+{
+}
+
+FtModGPS::~FtModGPS(void)
+{
+}
+
+void FtModGPS::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+	META_LOG("[Meta][FT] FT_GPS_OP ");
+
+    int ATM_Test = ((NORMAL_BOOT == getBootMode()) && (1 == getNormalModeTestFlag()))? 1:0;
+    META_GPS_OP((GPS_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen(), 1);
+}
+
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef FT_NFC_FEATURE
+FtModNFC::FtModNFC(void)
+	:CmdTarget(FT_NFC_REQ_ID)
+{
+}
+
+FtModNFC::~FtModNFC(void)
+{
+}
+
+void FtModNFC::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+	META_LOG("[Meta][FT] FT_NFC_OP ");
+
+	if(getInitState())
+    META_NFC_OP((NFC_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+}
+
+int FtModNFC::init(Frame*)
+{
+	if (META_NFC_init() != 0)
+	{	
+		 META_NFC_deinit();
+		 return false;
+	}
+	return true;
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_FM_FEATURE
+
+FtModFM::FtModFM(void)
+	:CmdTarget(FT_FM_REQ_ID)
+{
+}
+
+FtModFM::~FtModFM(void)
+{
+
+}
+
+void FtModFM::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+	META_LOG("[Meta][FT] FT_FM_OP ");
+    META_FM_OP((FM_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+}
+
+int FtModFM::init(Frame*)
+{
+	META_FM_init();
+	return true;
+
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_BT_FEATURE
+
+FtModBT::FtModBT(void)
+	:CmdTarget(FT_BT_REQ_ID)
+{
+}
+
+FtModBT::~FtModBT(void)
+{
+}
+
+void FtModBT::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+	META_LOG("[Meta][FT] FT_BT_OP ");
+
+    META_BT_OP((BT_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_AUDIO_FEATURE
+
+FtModAudio::FtModAudio(void)
+	:CmdTarget(FT_L4AUD_REQ_ID)
+{
+}
+
+FtModAudio::~FtModAudio(void)
+{
+}
+
+void FtModAudio::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+	META_LOG("[Meta][FT] FT_Audio_OP ");
+
+    META_Audio_OP((FT_L4AUD_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+}
+
+int FtModAudio::init(Frame*)
+{
+	META_Audio_init();
+	return true;
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_CCAP_FEATURE
+
+FtModCCAP::FtModCCAP(void)
+	:CmdTarget(FT_CCT_REQ_ID)
+{
+}
+
+FtModCCAP::~FtModCCAP(void)
+{
+}
+
+void FtModCCAP::exec(Frame *pFrm)
+{
+    static void *CcapHwhndl = NULL;
+    
+    static int (*func_ccap_init)() = NULL;
+    static void (*func_ccap_op)(const void*, void*, void**, unsigned short*, void**, unsigned short*) = NULL;
+    static void (*func_ccap_const)(int*, int*, int*, int*, int*) = NULL;
+    static void (*func_ccap_set_error)(const void*, void*) = NULL;
+    static int (*func_ccap_get_req_op)(const void*) = NULL;
+    
+    static int cnf_size = 0;
+    static int FT_CCT_OP_SUBPREVIEW_LCD_START = 0;
+    static int FT_CCT_OP_SUBPREVIEW_LCD_STOP = 0;
+    
+    if(CcapHwhndl == NULL)
+    {
+        CcapHwhndl = dlopen(CCAP_LIB_PATH, RTLD_NOW);
+        
+        if(CcapHwhndl == NULL)
+        {
+            META_LOG("[Meta][FT] link libccap.so fail ");	
+            return;
+        }
+        else
+        {
+            func_ccap_init = (int(*)()) dlsym(CcapHwhndl, "intf_ccap_init");
+            func_ccap_op = (void(*)(const void*, void*, void**, unsigned short*, void**, unsigned short*)) dlsym(CcapHwhndl, "intf_ccap_op");
+            func_ccap_const = (void(*)(int*, int*, int*, int*, int*)) dlsym(CcapHwhndl, "intf_ccap_const");
+            func_ccap_set_error = (void(*)(const void*, void*)) dlsym(CcapHwhndl, "intf_ccap_set_error");
+            func_ccap_get_req_op = (int(*)(const void*)) dlsym(CcapHwhndl, "intf_ccap_get_req_op");
+            if (func_ccap_init == NULL || func_ccap_op == NULL || 
+                func_ccap_const == NULL || func_ccap_set_error == NULL ||
+                func_ccap_get_req_op == NULL )
+            {
+                META_LOG("[Meta][FT] link libccap.so function pointers fail ");	
+                dlclose(CcapHwhndl);
+                CcapHwhndl = NULL;
+                return;
+            }
+
+            func_ccap_const(NULL, &cnf_size, NULL, &FT_CCT_OP_SUBPREVIEW_LCD_START, &FT_CCT_OP_SUBPREVIEW_LCD_STOP);
+        }
+    }
+    
+	CmdTarget::exec(pFrm);
+   	
+	void *req = (void*)pFrm->localBuf();
+	int req_op = func_ccap_get_req_op( req );
+	if ((req_op != FT_CCT_OP_SUBPREVIEW_LCD_START) && (req_op !=FT_CCT_OP_SUBPREVIEW_LCD_STOP))
+	{
+		META_LOG("[Meta][FT] META_CCAP_init ");	
+		if (func_ccap_init() == 0)
+		{
+            void *cnf = malloc(cnf_size);
+            if(cnf == NULL)
+            {
+			    META_LOG("[Meta][FT] FT_CCAP_OP META_CCT_init Fail, malloc Fail. ");
+                return;
+            }
+	        memset(cnf, 0, cnf_size);
+
+            func_ccap_set_error(req, cnf);
+			WriteDataToPC(cnf, cnf_size, NULL, 0);
+
+            free(cnf);
+
+			META_LOG("[Meta][FT] FT_CCAP_OP META_CCT_init Fail ");
+			return;
+		}
+	}
+	else
+    {
+   		META_LOG("[Meta][FT] Now is sub Camera, init will be do later");	
+   	}
+
+	META_LOG("[Meta][FT] FT_CCAP_OP ");
+
+#if 0
+    func_ccap_op( (const void*)req, (void*)pFrm->peerBuf() );
+#else
+    //sned data & free buffer in meta 
+    void *localBuf = NULL, *peerBuf = NULL;
+    unsigned short localBufLen = 0, peerBufLen = 0;
+    
+    func_ccap_op( (const void*)req, (void*)pFrm->peerBuf(), &localBuf, &localBufLen, &peerBuf, &peerBufLen );    
+    WriteDataToPC(localBuf, localBufLen, peerBuf, peerBufLen);    
+    free(localBuf);
+    free(peerBuf);    
+#endif
+    
+    //dlclose(CcapHwhndl);    
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_DRM_KEY_MNG_FEATURE
+FtModDRM::FtModDRM(void)
+	:CmdTarget(FT_DRMKEY_REQ_ID)
+{
+}
+
+FtModDRM::~FtModDRM(void)
+{
+
+}
+
+void FtModDRM::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+#ifdef FT_DRM_KEY_MNG_TRUSTONIC_FEATURE
+	//phone drmkey solution
+	META_LOG("[Meta][FT] Trustonic Ft_DRM");
+	FT_DRMKEY_INSTALL_CNF ft_cnf;
+	memset(&ft_cnf, 0, sizeof(FT_DRMKEY_INSTALL_CNF));
+	//init the header
+	ft_cnf.header.id = pFrm->getCmdTarget()->getId() + 1;
+	ft_cnf.header.token = pFrm->getCmdTarget()->getToken();
+	ft_cnf.status = DRMKEY_INSTALL_FAIL;
+
+	META_LOG("[DRMKEY] pFrm->localBuf())->header.token: %d\n", ((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf())->header.token);
+	META_LOG("[DRMKEY] pFrm->localBuf())->header.id: %d\n", ((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf())->header.id);
+	META_LOG("[DRMKEY] pFrm->localBuf())->op: %d\n", ((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf())->op);
+	META_LOG("[DRMKEY] pFrm->localBuf())->cmd.set_req.file_size: %d\n", ((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf())->cmd.set_req.file_size);
+	META_LOG("[DRMKEY] pFrm->localBuf())->cmd.set_req.stage: %d\n", ((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf())->cmd.set_req.stage);
+	META_LOG("[DRMKEY] pFrm->localBuf())->cmd.query_req.req: %d\n", ((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf())->cmd.query_req.req);
+	META_LOG("[DRMKEY] =========================================================\n");
+	META_LOG("[DRMKEY] ft_cnf.header.token: %d\n", ft_cnf.header.token);
+	META_LOG("[DRMKEY] ft_cnf.header.id: %d\n", ft_cnf.header.id);
+	META_LOG("[DRMKEY] ft_cnf.op: %d\n", ft_cnf.op);
+	META_LOG("[DRMKEY] ft_cnf.status: %d\n", ft_cnf.status);
+	META_LOG("[DRMKEY] ft_cnf.result.set_cnf.result: %d\n", ft_cnf.result.set_cnf.result);
+	META_LOG("[DRMKEY] ft_cnf.result.keyresult.keycount %d\n", ft_cnf.result.keyresult.keycount);
+
+	META_DRMKEY_INSTALL_OP((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf(), &ft_cnf, (char *)pFrm->peerBuf(), pFrm->peerLen());
+	WriteDataToPC(&ft_cnf, sizeof(FT_DRMKEY_INSTALL_CNF), NULL, 0);
+	META_LOG("[DRMKEY_HIDL] WriteDataToPC done");
+#else
+	//tablet drmkey solution
+	META_LOG("[Meta][FT] Inhouse Ft_DRM");
+
+        FT_DRMKEY_INSTALL_CNF ft_cnf;
+        memset(&ft_cnf, 0, sizeof(FT_DRMKEY_INSTALL_CNF));
+
+        //init the header
+        ft_cnf.header.id = pFrm->getCmdTarget()->getId() + 1;
+        ft_cnf.header.token = pFrm->getCmdTarget()->getToken();
+        ft_cnf.status = DRMKEY_INSTALL_FAIL;
+
+        android::hardware::hidl_vec<uint8_t> data;
+        HIDL_FT_DRMKEY_INSTALL_REQ toServer_req;
+        HIDL_FT_DRMKEY_INSTALL_CNF toServer_cnf;
+
+        convertREQ2HIDL((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf(), &toServer_req);
+
+        memset(&toServer_cnf, 0, sizeof(HIDL_FT_DRMKEY_INSTALL_CNF));
+        convertCNF2HIDL(&ft_cnf, &toServer_cnf);
+
+        META_LOG("[KM_HIDL] start HIDL");
+        android::sp<IKeymanage> client = IKeymanage::getService();
+        META_LOG("[KM_HIDL] getService done");
+
+        data.setToExternal(pFrm->peerBuf(), pFrm->peerLen());
+        META_LOG("[KM_HIDL] data.setToExternal done");
+
+        auto callback = [&] (const HIDL_FT_DRMKEY_INSTALL_CNF& fromServer_cnf) {
+        convertCNF2nonHIDL(&fromServer_cnf, &ft_cnf);
+        };
+
+        client->meta_drmkey_install_op(toServer_req, toServer_cnf, data, pFrm->peerLen(), callback);
+
+        META_LOG("[KM_HIDL] hidl_meta_drmkey_install_op done");
+        WriteDataToPC(&ft_cnf, sizeof(FT_DRMKEY_INSTALL_CNF), NULL, 0);
+        META_LOG("[KM_HIDL] WriteDataToPC done");
+
+#endif
+
+}
+#endif
+
+#ifdef FT_GAMMA_FEATURE
+FtModGAMMA::FtModGAMMA(void)
+    :CmdTarget(FT_GAMMA_REQ_ID)
+{
+}
+FtModGAMMA::~FtModGAMMA(void)
+{
+}
+void FtModGAMMA::exec(Frame *pFrm)
+{
+    CmdTarget::exec(pFrm);
+    META_LOG("[Meta][FT] FT_GAMMA_OP ");
+    META_GAMMA_OP((GAMMA_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+}
+#endif
+///////////////////////////////////////////////////////////////////////////////////////////////+
+
+#ifdef FT_ATTESTATION_KEY_FEATURE
+FtModAttestationKey::FtModAttestationKey(void)
+	:CmdTarget(FT_ATTESTATIONKEY_REQ_ID)
+{
+
+}
+
+FtModAttestationKey::~FtModAttestationKey(void)
+{
+
+}
+
+void FtModAttestationKey::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+	META_LOG("[Meta] FtModAttestationKey");
+
+	int finish = 0;
+	FT_ATTESTATIONKEY_INSTALL_CNF  ft_cnf;
+
+	memset(&ft_cnf, 0, sizeof(FT_ATTESTATIONKEY_INSTALL_CNF));
+	ft_cnf.status = META_FAILED;
+
+
+	FT_ATTESTATIONKEY_INSTALL_REQ *req = (FT_ATTESTATIONKEY_INSTALL_REQ *)pFrm->localBuf();
+
+	ft_cnf.header.id = req->header.id +1;
+	ft_cnf.header.token = req->header.token;
+	ft_cnf.type= req->type;
+
+	META_LOG("[Meta] FtModAttestationKey req->type = %d", req->type);
+	switch(req->type)
+	{
+		case FT_ATTESTATIONKEY_INSTALL_SET:
+			{
+				META_LOG("[Meta] FtModAttestationKey state = %d", req->cmd.set_req.stage);
+				if((req->cmd.set_req.stage & 0x04) == 0x04) //KEY_BLK_EOF
+					finish = 1;
+				META_LOG("[Meta] call ree_import_attest_keybox to send (%d) byte.", pFrm->peerLen());
+				META_LOG("[Meta] ft_cnf.status(B): %d\n", ft_cnf.status);
+				META_LOG("[Meta] ft_cnf.result.set_cnf.result(B): %d\n", ft_cnf.result.set_cnf.result);
+				ft_cnf.result.set_cnf.result = ree_import_attest_keybox((const uint8_t *)pFrm->peerBuf(), (const uint32_t)pFrm->peerLen(), finish);
+				META_LOG("[Meta] ft_cnf.status(A): %d\n", ft_cnf.status);
+				META_LOG("[Meta] ft_cnf.result.set_cnf.result(A): %d\n", ft_cnf.result.set_cnf.result);
+				if(ft_cnf.result.set_cnf.result == 0)
+					ft_cnf.status = META_SUCCESS;
+				else
+					ft_cnf.status = META_FAILED;
+			}
+			break;
+		default:
+			break;
+	}
+
+	WriteDataToPC(&ft_cnf, sizeof(FT_ATTESTATIONKEY_INSTALL_CNF), NULL, 0);
+}
+
+#endif
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define NVRAM_PEER_MAX_LEN 2000
+#define BLK_CREATE	0x01
+#define BLK_WRITE	0x02
+#define BLK_EOF		0x04
+
+#ifdef FT_NVRAM_FEATURE
+
+FtModNvramBackup::FtModNvramBackup(void)
+	:CmdTarget(FT_NVRAM_BACKUP_REQ_ID)
+{
+}
+
+FtModNvramBackup::~FtModNvramBackup(void)
+{
+}
+
+bool FtModNvramBackup::SendNVRAMFile(unsigned char file_ID, FT_NVRAM_BACKUP_CNF* pft_cnf)
+{
+	int backupFd;
+	int peer_buff_size = 0;
+    char* peer_buf = 0;
+	bool return_value = FALSE;
+
+	backupFd = open(makepath(file_ID), O_RDWR);
+
+	if(backupFd >= 0)
+	{
+		META_LOG("[Meta][FT] File%d opens succeed ! ",file_ID);
+		unsigned int fileLen = getFileSize(backupFd);
+
+		peer_buf = (char*)malloc(NVRAM_PEER_MAX_LEN);
+		memset(peer_buf, 0, NVRAM_PEER_MAX_LEN);
+
+		pft_cnf->block.stage = BLK_CREATE;
+		pft_cnf->block.file_ID = file_ID;
+
+		while(!(pft_cnf->block.stage & BLK_EOF))
+		{
+			peer_buff_size = read(backupFd, peer_buf, NVRAM_PEER_MAX_LEN);
+
+			if(peer_buff_size != -1)
+			{
+				pft_cnf->status = META_SUCCESS;
+				if(peer_buff_size == 0)
+				{
+					pft_cnf->block.stage |= BLK_EOF;
+					META_LOG("[Meta][FT] File%d backups succeed! ",file_ID);
+					pft_cnf->block.file_size = fileLen;
+
+					close(backupFd);
+
+					free(peer_buf);
+
+					if(remove(makepath(file_ID)) == 0)
+					{
+						META_LOG("[Meta][FT] File%d DeleteFile succeed! ",file_ID);
+						return_value = TRUE;
+						WriteDataToPC(pft_cnf, sizeof(FT_NVRAM_BACKUP_CNF),NULL, 0);
+					}
+					return return_value;
+				}
+				else
+				{
+					pft_cnf->block.stage |= BLK_WRITE;
+					if(peer_buff_size != NVRAM_PEER_MAX_LEN)
+					{
+						META_LOG("[Meta][FT] File%d backups %d data ! ",file_ID,peer_buff_size);
+					}
+					WriteDataToPC(pft_cnf, sizeof(FT_NVRAM_BACKUP_CNF),peer_buf, peer_buff_size);
+					memset(peer_buf,0,NVRAM_PEER_MAX_LEN);
+					pft_cnf->block.stage &= ~BLK_CREATE;
+				}
+
+			}
+			else
+			{
+				pft_cnf->block.stage |= BLK_EOF;
+				META_LOG("[Meta][FT] File%d backups read failed ! ", file_ID);
+			}
+
+		}
+
+		free(peer_buf);
+		close(backupFd);
+
+	}
+	else
+	{
+		META_LOG("[Meta][FT] File%d backups open failed ! ", file_ID);
+	}
+
+	return return_value;
+
+}
+
+void FtModNvramBackup::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+	META_LOG("[Meta][FT] FT_NvramBackup_OP ");
+
+	FT_NVRAM_BACKUP_CNF ft_cnf;
+	int bFileOpResult = 0;
+	memset(&ft_cnf, 0, sizeof(FT_NVRAM_BACKUP_CNF));
+	//init the header
+	ft_cnf.header.id = pFrm->getCmdTarget()->getId() + 1;
+	ft_cnf.header.token = pFrm->getCmdTarget()->getToken();
+	ft_cnf.status = META_FAILED;
+
+	FT_NVRAM_BACKUP_REQ *req = (FT_NVRAM_BACKUP_REQ *)pFrm->localBuf();
+
+	if (req->count > 0)
+	{
+		META_LOG("[Meta][FT] Count is %d, backup parts of NvRam!", req->count);
+		bFileOpResult = FileOp_BackupData_Special(req->buffer, req->count, req->mode);
+	}
+	else
+	{
+		META_LOG("[Meta][FT] Count is %d, backup all NvRam!", req->count);
+		bFileOpResult = FileOp_BackupAll_NvRam();
+	}
+	
+	if(bFileOpResult)
+	{
+	    META_LOG("[Meta][FT] NVM_PcBackup_Get_Data Start ! ");
+		if(SendNVRAMFile(0,&ft_cnf))
+		{
+			META_LOG("[Meta][FT] Send file 0 succeed! ! ");
+			//init the header
+			ft_cnf.header.id = req->header.id +1;
+			ft_cnf.header.token = req->header.token;
+			ft_cnf.status = META_FAILED;
+			ft_cnf.block.file_size = 0;
+
+			if(SendNVRAMFile(1,&ft_cnf))
+			{
+				META_LOG("[Meta][FT] Send file 1 succeed! ! ");
+				return;
+			}
+		}
+	}
+	else
+	{
+		META_LOG("[Meta][FT] Failed to backup NvRam!");
+	}
+
+	WriteDataToPC(&ft_cnf, sizeof(FT_NVRAM_BACKUP_CNF),NULL, 0);
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModNvramRestore::FtModNvramRestore(void)
+	:CmdTarget(FT_NVRAM_RESTORE_REQ_ID)
+{
+}
+
+FtModNvramRestore::~FtModNvramRestore(void)
+{
+}
+
+
+void FtModNvramRestore::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+	META_LOG("[Meta][FT] FT_NvramRestore_OP ");
+
+	FT_NVRAM_RESTORE_CNF ft_cnf;
+	memset(&ft_cnf, 0, sizeof(FT_NVRAM_RESTORE_CNF));
+
+	FT_NVRAM_RESTORE_REQ *req = (FT_NVRAM_RESTORE_REQ *)pFrm->localBuf();
+	
+	//init the header
+	ft_cnf.header.id = req->header.id +1;
+	ft_cnf.header.token = req->header.token;
+	ft_cnf.status = META_FAILED;
+	
+	int backupFd;
+	unsigned int fileLen;
+	META_LOG("[Meta][FT] FT_NVRAM_Restore_OP receive block stage %x  file id %d file size %d!",req->block.stage,req->block.file_ID,req->block.file_size);
+	if(req->block.stage & BLK_CREATE)
+	{
+		backupFd = open(makepath(req->block.file_ID), O_RDWR | O_TRUNC | O_CREAT, 0777);
+	}
+	else
+	{
+		backupFd = open(makepath(req->block.file_ID), O_RDWR | O_APPEND);
+	}
+	
+	if(backupFd >= 0)
+	{
+		META_LOG("[Meta][FT] FT_NVRAM_Restore_OP create or open file OK!");
+		int sWriten = 0;
+		sWriten = write(backupFd,pFrm->peerBuf(),pFrm->peerLen());
+
+		if(sWriten>0)
+		{
+			ft_cnf.status = META_SUCCESS;
+			META_LOG("[Meta][FT] FT_NVRAM_Restore_OP File%d write %d data total data %d!",req->block.file_ID,sWriten,pFrm->peerLen());
+			if(req->block.stage & BLK_EOF)
+			{
+				fileLen = getFileSize(backupFd);
+				if(req->block.file_size == fileLen)
+				{
+					META_LOG("[Meta][FT] FT_NVRAM_Restore_OP write file transfer success! ");
+					close(backupFd);
+					backupFd = -1;
+	
+					if(req->block.file_ID == 1)
+					{
+						if(!FileOp_RestoreAll_NvRam())
+						{
+							ft_cnf.status = META_FAILED;
+							META_LOG("[Meta][FT] META_Editor_PcRestore_Set_Data failed! ");
+	
+						}
+					}
+				}
+				else
+				{
+					ft_cnf.status = META_FAILED;
+					META_LOG("[Meta][FT] FT_NVRAM_Restore_OP file %d size error! / %d ",req->block.file_ID,req->block.file_size);
+				}
+			}
+		}
+		else
+		{
+			META_LOG("[Meta][FT] FT_NVRAM_Restore_OP write file failed! sWriten =%d errno = %d",sWriten,errno);
+		}
+	
+		if(backupFd != -1)
+			close(backupFd);
+	
+	
+	}
+	else
+	{
+		META_LOG("[Meta][FT] FT_NVRAM_Restore_OP create or open file failed!");
+	}
+	
+	WriteDataToPC(&ft_cnf, sizeof(FT_NVRAM_RESTORE_CNF),NULL, 0);
+
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModNvramReset::FtModNvramReset(void)
+	:CmdTarget(FT_NVRAM_RESET_REQ_ID)
+{
+}
+
+FtModNvramReset::~FtModNvramReset(void)
+{
+}
+
+void FtModNvramReset::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+	META_LOG("[Meta][FT] FT_NvramReset_OP ");
+	FT_AP_Editor_reset_cnf ft_cnf;
+ 
+    memset(&ft_cnf, 0, sizeof(FT_AP_Editor_reset_cnf));
+
+	FT_AP_Editor_reset_req *req = (FT_AP_Editor_reset_req *)pFrm->localBuf();
+
+    //if the reset_category and file_idx is 0xfc and 0xfccf, we reset all nvram files.
+    if ((req->reset_category == 0xfc )&& (req->file_idx ==0xfccf))
+        ft_cnf = META_Editor_ResetAllFile_OP(req);	//reset all files
+    else
+        ft_cnf = META_Editor_ResetFile_OP(req);		//reset one nvram file
+
+    //fill the ft module header
+    ft_cnf.header.id = req->header.id +1;
+    ft_cnf.header.token = req->header.token;
+    ft_cnf.status = META_SUCCESS;
+
+    WriteDataToPC(&ft_cnf, sizeof(FT_AP_Editor_reset_cnf),NULL, 0);
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+FtModNvramRead::FtModNvramRead(void)
+	:CmdTarget(FT_NVRAM_READ_REQ_ID)
+{
+}
+
+FtModNvramRead::~FtModNvramRead(void)
+{
+}
+
+void FtModNvramRead::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+	META_LOG("[Meta][FT] FT_NvramRead_OP ");
+ 	// just call the inferface of ap_editor lib which will reture the data after reading sucessfully
+ 	if (!META_Editor_ReadFile_OP((FT_AP_Editor_read_req *)pFrm->localBuf()))
+	 	META_LOG("[Meta][FT] FT_APEditorR_OP META Test Fail");
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModNvramWrite::FtModNvramWrite(void)
+	:CmdTarget(FT_NVRAM_WRITE_REQ_ID)
+{
+}
+
+FtModNvramWrite::~FtModNvramWrite(void)
+{
+}
+
+void FtModNvramWrite::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+	META_LOG("[Meta][FT] FT_NvramWrite_OP ");
+
+    FT_AP_Editor_write_cnf ft_cnf;
+
+    memset(&ft_cnf, 0, sizeof(FT_AP_Editor_write_cnf));
+	FT_AP_Editor_write_req *req = (FT_AP_Editor_write_req *)pFrm->localBuf();
+
+    //// just call the inferface of ap_editor lib
+    ft_cnf = META_Editor_WriteFile_OP(req, (char *)pFrm->peerBuf(), pFrm->peerLen());
+
+
+
+    //fill the ft module header
+    ft_cnf.header.id = req->header.id +1;
+    ft_cnf.header.token = req->header.token;
+    ft_cnf.status = META_SUCCESS;
+
+    WriteDataToPC(&ft_cnf, sizeof(FT_AP_Editor_write_cnf),NULL, 0);
+
+}
+#endif
+
+
+FtModAPDB::FtModAPDB(void)
+    :CmdTarget(FT_APDB_REQ_ID)
+{
+}
+
+FtModAPDB::~FtModAPDB(void)
+{
+}
+
+void FtModAPDB::exec(Frame *pFrm)
+{
+    CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] FT_APDB_OP ");
+
+    FT_APDB_CNF ft_cnf;
+    memset(&ft_cnf, 0, sizeof(FT_APDB_CNF));
+
+    FT_APDB_REQ *req = (FT_APDB_REQ *)pFrm->localBuf();
+
+
+    //fill the ft module header
+    ft_cnf.header.id = req->header.id +1;
+    ft_cnf.header.token = req->header.token;
+    ft_cnf.type= req->type;
+    ft_cnf.status = META_FAILED;
+
+    char szAPDBPath[64] = {MTK_APDB_PATH};
+
+    switch(req->type)
+    {
+        case FT_APDB_OP_QUERYPATH:
+            memcpy(ft_cnf.result.query_apdbpath_cnf.apdb_path, szAPDBPath, strlen(szAPDBPath));
+            META_LOG("[Meta][FT] FT_APDB_OP FT_APDB_OP_QUERYPATH apdb_path: %s",
+            ft_cnf.result.query_apdbpath_cnf.apdb_path);
+            ft_cnf.status = META_SUCCESS;
+            break;
+        default:
+            break;
+    }
+
+    WriteDataToPC(&ft_cnf, sizeof(FT_APDB_CNF),NULL, 0);
+
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef FT_SYSENV_SUPPORT
+
+FtModSysEnv::FtModSysEnv(void)
+    :CmdTarget(FT_SYSENV_REQ_ID)
+{
+}
+
+FtModSysEnv::~FtModSysEnv(void)
+{
+}
+
+void FtModSysEnv::exec(Frame *pFrm)
+{
+	
+	CmdTarget::exec(pFrm);
+	
+	META_LOG("[Meta][FT] FT_SYS_ENV_OP");
+	
+	FT_SYS_ENV_CNF ft_cnf;
+	memset(&ft_cnf, 0, sizeof(FT_SYS_ENV_CNF));	
+	FT_SYS_ENV_REQ *req = (FT_SYS_ENV_REQ *)pFrm->localBuf();	
+	
+	//fill the ft module header
+	ft_cnf.header.id = req->header.id +1;
+	ft_cnf.header.token = req->header.token;
+	ft_cnf.type= req->type;
+	ft_cnf.status = META_FAILED;
+	const char *val;
+    switch(req->type)
+    {
+        case FT_SYSENV_SET:
+            META_LOG("[Meta][FT] FT_SYS_ENV_OP FT_SYSENV_SET name = %s, value = %s",
+            req->cmd.sysenv_set_req.name, req->cmd.sysenv_set_req.value);
+            if(sysenv_set((char*)req->cmd.sysenv_set_req.name, (char*)req->cmd.sysenv_set_req.value) < 0)
+            {
+                META_LOG("[Meta][FT] FT_SYS_ENV_OP FT_SYSENV_SET failed!");
+            }
+            else
+            {
+                META_LOG("[Meta][FT] FT_SYS_ENV_OP FT_SYSENV_SET succeed!");
+                ft_cnf.status = META_SUCCESS;
+            }	
+            break;
+	case FT_SYSENV_GET:
+            META_LOG("[Meta][FT] FT_SYS_ENV_OP FT_SYSENV_GET name = %s", req->cmd.sysenv_get_req.name);
+            val = sysenv_get((char*)req->cmd.sysenv_get_req.name);
+            if(val != NULL)
+            {
+                META_LOG("[Meta][FT] FT_SYS_ENV_OP FT_SYSENV_GET value = %s", val);
+                memcpy(ft_cnf.result.sysenv_get_cnf.value, val, strlen(val));
+                ft_cnf.status = META_SUCCESS;
+            }
+            break;
+        case FT_SYSENV_END:
+            META_LOG("[Meta][FT] FT_SYS_ENV_OP FT_SYSENV_END");
+            break;
+    }
+
+	
+    WriteDataToPC(&ft_cnf, sizeof(FT_SYS_ENV_CNF),NULL, 0);
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModTargetClock::FtModTargetClock(void)
+    :CmdTarget(FT_TARGETCLOCK_REQ_ID)
+{
+}
+
+FtModTargetClock::~FtModTargetClock(void)
+{
+}
+
+void FtModTargetClock::exec(Frame *pFrm)
+{
+	
+	CmdTarget::exec(pFrm);
+	
+	META_LOG("[Meta][Clock] FT_TARGET_CLOCK_OP");
+	
+	FT_TARGETCLOCK_CNF ft_cnf;
+	memset(&ft_cnf, 0, sizeof(FT_TARGETCLOCK_CNF));	
+	FT_TARGETCLOCK_REQ *req = (FT_TARGETCLOCK_REQ *)pFrm->localBuf();	
+	
+	//fill the ft module header
+	ft_cnf.header.id = req->header.id +1;
+	ft_cnf.header.token = req->header.token;
+	ft_cnf.type= req->type;
+	ft_cnf.status = META_FAILED;
+
+	switch(req->type)
+    {
+        case FT_CLOCK_SET:
+			if(SetSysClock(&req->cmd.set_clock_req))
+			{
+				ft_cnf.status = META_SUCCESS;
+			}
+			break;
+		case FT_CLOCK_GET:
+			break;
+        case FT_CLOCK_END:
+            META_LOG("[Meta][Clock] FT_TARGET_CLOCK_OP FT_CLOCK_END");
+            break;
+	}
+	
+    WriteDataToPC(&ft_cnf, sizeof(FT_TARGETCLOCK_CNF), NULL, 0);
+}
+
+unsigned int FtModTargetClock::SetSysClock(SET_TARGET_CLOCK_REQ *req)
+{
+	int ret = 0;	
+	struct tm tmpsec;     
+	struct timespec rtime;     
+	struct timespec cur_time;
+
+	memset(&tmpsec, 0, sizeof(tm));
+	memset(&rtime, 0, sizeof(timespec));
+	memset(&cur_time, 0, sizeof(timespec));
+
+	META_LOG("[Meta][Clock] set time to: %d-%02d-%02d %02d-%02d-%02d.%03d", req->year, req->mon, req->day, req->hour, req->min, req->sec, req->ms); 
+	if(!IsValidDate(req))
+		return ret;
+	
+	tmpsec.tm_year  = req->year- 1900;
+	tmpsec.tm_mon   = req->mon - 1;
+	tmpsec.tm_mday  = req->day;
+	tmpsec.tm_hour  = req->hour;
+	tmpsec.tm_min   = req->min;
+	tmpsec.tm_sec   = req->sec;
+	tmpsec.tm_isdst = -1;
+
+	rtime.tv_sec = mktime(&tmpsec);
+	clock_gettime(CLOCK_REALTIME, &cur_time);
+	rtime.tv_nsec = req->ms*1000*1000;
+	
+	if(clock_settime(CLOCK_REALTIME, &rtime) != 0)
+	{
+		META_LOG("[Meta][Clock] set target clock failed! ret = %d, err = %d, err string = %s", ret, errno, strerror(errno)); 
+		return 0;
+	}
+	
+	META_LOG("[Meta][Clock] set target clock successful!");
+	return 1;
+
+}
+
+unsigned int FtModTargetClock::IsValidDate(SET_TARGET_CLOCK_REQ *req)
+{
+	if((req->year > 2067) || (req->year < 1900))
+	{
+		META_LOG("[Meta][Clock] invalid year [1900~2067]! year = %d",  req->year);
+		return 0;
+	}
+
+	if((req->mon > 12) || (req->mon < 1))
+	{
+		META_LOG("[Meta][Clock] invalid mon [1~12]! mon = %d",  req->mon);
+		return 0;
+	}
+	
+	if((req->day > 31) || (req->day < 1))
+	{
+		META_LOG("[Meta][Clock] invalid day [1~31]! day = %d",  req->day);
+		return 0;
+	}
+
+	if(req->hour > 23)
+	{
+		META_LOG("[Meta][Clock] invalid hour [0~23]! hour = %d", req->hour);
+		return 0;
+	}
+
+	if(req->min > 59)
+	{
+		META_LOG("[Meta][Clock] invalid min [0~59]! min = %d", req->min);
+		return 0;
+	}
+
+	if(req->sec > 59)
+	{
+		META_LOG("[Meta][Clock] invalid sec [0~59]! sec = %d", req->sec);
+		return 0;
+	}
+
+	if(req->ms > 999)
+	{
+		META_LOG("[Meta][Clock] invalid ms [0~999]! ms = %d", req->ms);
+		return 0;
+	}
+
+	return 1;
+}
+
+
+FtModTestAlive::FtModTestAlive(void)
+	:CmdTarget(FT_IS_ALIVE_REQ_ID)
+{
+}
+
+FtModTestAlive::~FtModTestAlive(void)
+{
+}
+
+void FtModTestAlive::exec(Frame *pFrm)
+{
+	META_LOG("[Meta][FT] FT_TestAlive");
+	FT_IS_ALIVE_CNF ft_cnf;
+	memset(&ft_cnf, 0, sizeof(FT_IS_ALIVE_CNF));
+
+	CmdTarget::exec(pFrm);
+
+	
+	//just give the respone.
+	ft_cnf.header.id = pFrm->getCmdTarget()->getId()+1;
+	ft_cnf.header.token = pFrm->getCmdTarget()->getToken();
+	
+	//write bootprof
+	writeBootprof((char *)"[META] AP Send FT_TestAlive To PC.");
+	
+	WriteDataToPC(&ft_cnf, sizeof(FT_IS_ALIVE_CNF),NULL, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+//for normal version
+
+#define RELEASE_SW_TOKEN            "ro.vendor.mediatek.version.release"
+#define RELEASE_PLATFORM_TOKEN      "ro.board.platform"
+#define RELEASE_PRODUCT_TOKEN       "ro.product.name"
+#define RELEASE_BUILD_TIME_TOKEN    "ro.build.date"
+#define RELEASE_BUILD_DISP_ID_TOKEN "ro.build.display.id"
+#define RELEASE_RSC_PROJECT_TOKEN   "ro.boot.rsc"
+
+FtModVersionInfo::FtModVersionInfo(void)
+	:CmdTarget(FT_VER_INFO_REQ_ID)
+{
+}
+
+FtModVersionInfo::~FtModVersionInfo(void)
+{
+}
+
+void FtModVersionInfo::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+	META_LOG("[Meta][FT] FT_VersionInfo");
+	FT_VER_INFO_CNF ft_cnf;
+
+	memset(&ft_cnf, 0, sizeof(ft_cnf));
+	//char product[256] = {0};
+		
+	//initail the value of ft header
+	ft_cnf.header.id = pFrm->getCmdTarget()->getId()+1;
+	ft_cnf.header.token = pFrm->getCmdTarget()->getToken();
+	ft_cnf.status = META_SUCCESS;
+
+#ifdef IS_SUPPORT_SP	
+	property_get(RELEASE_SW_TOKEN, (char*)ft_cnf.sw_ver, "");
+	META_LOG("[Meta][FT] ft_cnf.sw_ver = %s ", ft_cnf.sw_ver);
+	
+	property_get(RELEASE_PLATFORM_TOKEN, (char*)ft_cnf.bb_chip, "");
+	META_LOG("[Meta][FT] ft_cnf.bb_chip = %s ", ft_cnf.bb_chip);
+	
+	property_get(RELEASE_BUILD_TIME_TOKEN, (char*)ft_cnf.sw_time, "");
+	META_LOG("[Meta][FT] ft_cnf.sw_time = %s ", ft_cnf.sw_time);
+		
+	property_get(RELEASE_PRODUCT_TOKEN, product, "");
+	META_LOG("[Meta][FT] Product Name = %s\n", product);
+		
+	property_get(RELEASE_RSC_PROJECT_TOKEN, (char*)ft_cnf.rsc_ver, "");
+	META_LOG("[Meta][FT] ft_cnf.rsc_ver = %s\n", ft_cnf.rsc_ver);
+#else
+	strcpy((char*)ft_cnf.sw_ver, "Dual-IPC v1.0");
+	strcpy((char*)ft_cnf.bb_chip, "mt6870");
+	strcpy((char*)ft_cnf.sw_time, "2020-06-08-15:02:00");
+#endif
+
+	WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModVersionInfo2::FtModVersionInfo2(void)
+	:CmdTarget(FT_VER_INFO_V2_REQ_ID)
+{
+}
+
+FtModVersionInfo2::~FtModVersionInfo2(void)
+{
+}
+
+void FtModVersionInfo2::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm); 
+	META_LOG("[Meta][FT] FT_VersionInfo2");
+	FT_VER_INFO_V2_CNF ft_cnf;
+    memset(&ft_cnf, 0, sizeof(ft_cnf));
+	//char product[256] = {0};
+	//char disp_id[256] = {0};
+		
+	//initail the value of ft header
+	ft_cnf.header.id = pFrm->getCmdTarget()->getId()+1;
+	ft_cnf.header.token = pFrm->getCmdTarget()->getToken();
+	ft_cnf.status = META_SUCCESS;
+
+#ifdef IS_SUPPORT_SP
+	property_get(RELEASE_SW_TOKEN, (char*)ft_cnf.sw_ver, "");
+	META_LOG("[Meta][FT] ft_cnf.sw_ver = %s ", ft_cnf.sw_ver);
+	
+	property_get(RELEASE_PLATFORM_TOKEN, (char*)ft_cnf.bb_chip, "");
+	META_LOG("[Meta][FT] ft_cnf.bb_chip = %s ", ft_cnf.bb_chip);
+	
+	property_get(RELEASE_BUILD_TIME_TOKEN, (char*)ft_cnf.sw_time, "");
+	META_LOG("[Meta][FT] ft_cnf.sw_timep = %s ", ft_cnf.sw_time);
+
+	property_get(RELEASE_BUILD_DISP_ID_TOKEN, disp_id, "");
+	strncpy((char*)ft_cnf.build_disp_id, disp_id, 63);
+	META_LOG("[Meta][FT] ft_cnf.build_disp_id = %s ", ft_cnf.build_disp_id);
+		
+	property_get(RELEASE_PRODUCT_TOKEN, product, "");
+	META_LOG("[Meta][FT] Product Name = %s\n", product);
+#else
+    //to do
+#endif 
+	WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+//for chip version
+#define CHIPINFO_CODE_FUNC          "/proc/chip/code_func"
+#define CHIPINFO_CODE_PROJ          "/proc/chip/code_proj"
+#define CHIPINFO_CODE_DATE          "/proc/chip/code_date"
+#define CHIPINFO_CODE_FAB           "/proc/chip/code_fab"
+
+FtModChipInfo::FtModChipInfo(void)
+	:CmdTarget(FT_CHIP_INFO_REQ_ID)
+{
+}
+
+FtModChipInfo::~FtModChipInfo(void)
+{
+}
+
+void FtModChipInfo::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+	META_LOG("[Meta][FT] FT_ChipInfo");
+	FT_CHIP_INFO_CNF ft_cnf;
+	FILE *fd = 0;
+	char szInfoPath[][32] = { 
+			CHIPINFO_CODE_FUNC,
+			CHIPINFO_CODE_PROJ,
+		    CHIPINFO_CODE_DATE,
+			CHIPINFO_CODE_FAB};
+
+	char chip_info[4][64];
+	memset(&chip_info,0,sizeof(char)*4*64);
+	
+	memset(&ft_cnf, 0, sizeof(ft_cnf));
+	
+	//initail the value of ft header
+	ft_cnf.header.id = pFrm->getCmdTarget()->getId()+1;
+	ft_cnf.header.token = pFrm->getCmdTarget()->getToken();
+	ft_cnf.status = META_FAILED;
+	
+	/* Get the chip info */
+	int i = 0;
+	for(i=0; i<4; i++)
+	{
+		if((fd = fopen(szInfoPath[i], "r")) != NULL)
+		{
+			if(fgets((char*)chip_info[i], 64, fd) != NULL)
+			{
+				META_LOG("[Meta][FT] %s = %s\n", szInfoPath[i], chip_info[i]);
+			}
+			else
+			{
+				META_LOG("[Meta][FT] failed to read <%s>\n", szInfoPath[i]);
+			}
+
+			fclose(fd);
+		}
+		else
+		{
+			META_LOG("[Meta][FT] Can't open file : %s\n", szInfoPath[i]);
+			break;
+		}
+	}
+
+	if(i == 4)
+	{
+		strncpy((char*)ft_cnf.code_func, chip_info[0], 63);
+		strncpy((char*)ft_cnf.code_proj, chip_info[1], 63);
+		strncpy((char*)ft_cnf.code_date, chip_info[2], 63);
+		strncpy((char*)ft_cnf.code_fab, chip_info[3], 63);
+		ft_cnf.status = META_SUCCESS;
+	}
+	
+	WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+
+}
+///////////////////////////////////////////////////////////////////////////////////////////////
+FtModPowerOff::FtModPowerOff(void)
+	:CmdTarget(FT_POWER_OFF_REQ_ID)
+{
+}
+
+FtModPowerOff::~FtModPowerOff(void)
+{
+}
+
+void FtModPowerOff::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] FT_PowerOff");
+
+	
+	FT_POWER_OFF_REQ *req = (FT_POWER_OFF_REQ *)pFrm->localBuf();
+
+	META_LOG("[Meta][FT] req->dummy = %d", req->dummy);
+
+	//sync();
+    usleep(200*1000);
+
+    int comPortType = getComType();
+    if(comPortType == META_USB_COM && req->dummy != 3)
+    {
+		closeUSB();		
+    }
+	else if(comPortType == META_SOCKET)
+	{
+		if(NORMAL_BOOT == getBootMode())
+		{
+		    /*
+		    META_LOG("[Meta][FT] Send broadcast to disconnect WIFI");
+		    const char *strBroadcast = "am broadcast -a Exit_Meta_Info_Activity";
+		    system(strBroadcast);
+		    */
+		    MSocket *mSocket = getSocket(SOCKET_ATM_COMM);
+		    if(mSocket != NULL)
+		    {
+				mSocket->send_msg("ATM_EXIT_WIFI_APP");
+		    }
+
+		}
+    }
+    else
+    {
+        META_LOG("[Meta][FT] com port type is uart! ");
+    }
+
+
+	switch(req->dummy)
+	{
+		case 0:
+			{
+				usleep(1000 * 1000);
+#ifdef IS_SUPPORT_SP
+				property_set("sys.powerctl","shutdown");
+#else
+				reboot(RB_POWER_OFF);
+#endif
+			}
+			break;
+		case 2:
+			{
+				usleep(1000 * 1000);
+#ifdef IS_SUPPORT_SP
+				property_set("sys.powerctl","reboot");
+#else
+				reboot(RB_AUTOBOOT);
+#endif
+			}
+			break;
+		case 3:
+			{
+				META_LOG("[Meta][FT] Disconnect ATM Meta ");
+				destroySerPortThread();	
+				MSocket *pSocket = getSocket(SOCKET_ATCI_CLIENT);
+				if(pSocket != NULL)
+				{
+					pSocket->send_msg("calibration_stop");
+				}
+				else
+				{
+					META_LOG("[Meta][FT] pSocket is NULL");	
+				}
+			}
+			break;
+		case 4:
+			{
+				checkUSBOnline();
+#ifdef IS_SUPPORT_SP
+				property_set("sys.powerctl","shutdown");
+#else
+				reboot(RB_POWER_OFF);
+#endif
+			}
+			break;
+		case 5:
+			{
+				rebootToRecovery();
+			}
+			break;
+	}
+	
+}
+
+void FtModPowerOff::checkUSBOnline()
+{	
+	int status = 0;
+	while((status=readSys_int(USBONLINE_STATUS_PATH)) != 0)
+	{
+		usleep(200*1000);
+		META_LOG("[Meta][PowerOff] usb online status= %d", status);	
+	}
+
+	META_LOG("[Meta][PowerOff] usb online off and to power off ");	
+}
+
+#define MISC_PART_PATH "/dev/block/platform/bootdevice/by-name/para"
+void FtModPowerOff::rebootToRecovery()
+{
+	META_LOG("[Meta][PowerOff] enter rebootToRecovery");
+	const char* command = "boot-recovery";
+	int fd = -1;
+	int ret = 0;
+
+	fd = open(MISC_PART_PATH, O_RDWR);
+	if(fd < 0)
+	{
+		META_LOG("[Meta][PowerOff] open misc partition fail, errno = %d", errno);
+		return;
+	}
+
+	META_LOG("[Meta][PowerOff] command is %s", command);
+
+	ret = write(fd, command, 13);
+	if(ret > 0)
+	{
+		META_LOG("[Meta][PowerOff] write %s to misc partition success", command);
+	}
+	else
+	{
+		META_LOG("[Meta][PowerOff] write %s to misc partition failed, errno = %d",command, errno);
+	}
+	close(fd);
+	usleep(200*1000);
+#ifdef IS_SUPPORT_SP
+	property_set("sys.powerctl","reboot");
+#else
+	reboot(RB_AUTOBOOT);
+#endif
+
+}
+
+void FtModPowerOff::closeUSB()
+{
+	FILE *PUsbFile = NULL;
+    PUsbFile = fopen("sys/devices/platform/mt_usb/cmode","w");
+    if(PUsbFile == NULL)
+	{
+       	META_LOG("[Meta][FT] Could not open sys/devices/platform/mt_usb/cmode ");
+	    PUsbFile = fopen("/sys/devices/platform/musb-mtu3d/musb-hdrc/cmode","w");
+		if(PUsbFile == NULL)
+		{
+		    META_LOG("[Meta][FT] Could not open /sys/devices/platform/musb-mtu3d/musb-hdrc/cmode ");
+		    PUsbFile = fopen("/sys/class/udc/musb-hdrc/device/cmode","w");
+		    if(PUsbFile == NULL)
+		    {
+		        META_LOG("[Meta][FT] Could not open /sys/class/udc/musb-hdrc/device/cmode ");
+		    }
+		    else
+		    {
+		        fputc('0',PUsbFile);
+		        fclose(PUsbFile);
+		    }
+		}
+		else
+		{
+		    fputc('0',PUsbFile);
+		    fclose(PUsbFile);
+		}
+    }
+    else
+    {
+    	fputc('0',PUsbFile);
+		fclose(PUsbFile);	
+    }
+}
+///////////////////////////////////////////////////////////////////////////////////////////////
+FtModMetaDisconnect::FtModMetaDisconnect(void)
+	:CmdTarget(FT_DISCONNECT_REQ_ID)
+{
+}
+
+FtModMetaDisconnect::~FtModMetaDisconnect(void)
+{
+}
+
+void FtModMetaDisconnect::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] FtModMetaDisconnect");
+	
+	FT_DISCONNECT_REQ *req = (FT_DISCONNECT_REQ *)pFrm->localBuf();
+	FtModPowerOff ft_poweroff;
+
+	META_LOG("[Meta][FT] req->type = %d", req->type);
+
+    usleep(200*1000);
+
+    int comPortType = getComType();
+    if(comPortType == META_USB_COM && req->type != FT_CTRL_DISCONN_ATM)
+    {
+		ft_poweroff.closeUSB();		
+    }
+	else if(comPortType == META_SOCKET)
+	{
+		if(NORMAL_BOOT == getBootMode())
+		{
+			META_LOG("[Meta][FT] Send broadcast to disconnect WIFI");
+			const char *strBroadcast = "am broadcast -a Exit_Meta_Info_Activity";
+			system(strBroadcast);	
+		}
+    }
+    else
+    {
+        META_LOG("[Meta][FT] com port type is uart! ");
+    }
+
+	switch(req->type)
+	{
+		case FT_CTRL_POWEROFF:
+			{
+				usleep(1000 * 1000);
+#ifdef IS_SUPPORT_SP
+				property_set("sys.powerctl","shutdown");
+#else
+				reboot(RB_POWER_OFF);
+#endif
+			}
+			break;
+		case FT_CTRL_REBOOT:
+			{
+				usleep(1000 * 1000);
+#ifdef IS_SUPPORT_SP
+				property_set("sys.powerctl","reboot");
+#else
+				reboot(RB_AUTOBOOT);
+#endif
+			}
+			break;
+		case FT_CTRL_REBOOT_BYDELAY:
+			{
+				META_LOG("[Meta][FT] reboot by delay = %d", req->cmd.disconnect_req.delay);
+				sleep(req->cmd.disconnect_req.delay);
+#ifdef IS_SUPPORT_SP
+				property_set("sys.powerctl","reboot");
+#else
+				reboot(RB_AUTOBOOT);
+#endif
+			}
+			break;
+		case FT_CTRL_DISCONN_ATM:
+			{
+				META_LOG("[Meta][FT] Disconnect ATM Meta ");
+				destroySerPortThread();	
+				MSocket *pSocket = getSocket(SOCKET_ATCI_CLIENT);
+				if(pSocket != NULL)
+				{
+					pSocket->send_msg("calibration_stop");
+				}
+				else
+				{
+					META_LOG("[Meta][FT] pSocket is NULL");	
+				}
+			}
+			break;
+		case FT_CTRL_CHECKUSB_POWEROFF:
+			{
+				ft_poweroff.checkUSBOnline();
+#ifdef IS_SUPPORT_SP
+				property_set("sys.powerctl","shutdown");
+#else
+				reboot(RB_POWER_OFF);
+#endif
+			}
+			break;
+		case FT_CTRL_REBOOT_RECOVERY:
+			{
+				ft_poweroff.rebootToRecovery();
+			}
+			break;
+		case FT_CTRL_DONOTHING:
+		case FT_CTRL_TARGET_OP_END:
+			break;
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModReboot::FtModReboot(void)
+	:CmdTarget(FT_REBOOT_REQ_ID)
+{
+}
+
+FtModReboot::~FtModReboot(void)
+{
+}
+
+void FtModReboot::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] FT_Reboot");
+
+	
+	FT_META_REBOOT_REQ *req = (FT_META_REBOOT_REQ *)pFrm->localBuf();
+
+	sleep(req->delay);
+
+    //Reboot target side after finishing the meta
+	//sync();
+	//reboot(RB_AUTOBOOT);
+#ifdef IS_SUPPORT_SP
+	property_set("sys.powerctl","reboot");
+#else
+	reboot(RB_AUTOBOOT);
+#endif
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+FtModBuildProp::FtModBuildProp(void)
+	:CmdTarget(FT_BUILD_PROP_REQ_ID)
+{
+}
+
+FtModBuildProp::~FtModBuildProp(void)
+{
+}
+
+void FtModBuildProp::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] FT_BuildProp");
+
+	FT_BUILD_PROP_CNF ft_cnf;
+	FT_BUILD_PROP_REQ *req = (FT_BUILD_PROP_REQ *)pFrm->localBuf();
+	memset(&ft_cnf, 0, sizeof(FT_BUILD_PROP_CNF));
+
+	ft_cnf.header.id = req->header.id +1;
+    ft_cnf.header.token = req->header.token;
+
+#ifdef IS_SUPPORT_SP	
+    property_get((const char*)req->tag, (char *)ft_cnf.content, "unknown");	
+#endif
+
+	META_LOG("[Meta][FT] %s = %s ",req->tag,ft_cnf.content);
+	ft_cnf.status = META_SUCCESS;
+
+	WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);	
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_GSENSOR_FEATURE
+
+FtModGSensor::FtModGSensor(void)
+    :CmdTarget(FT_GSENSOR_REQ_ID)
+{
+}
+
+FtModGSensor::~FtModGSensor(void)
+{
+    Meta_GSensor_Close();
+}
+
+void FtModGSensor::exec(Frame *pFrm)
+{
+    CmdTarget::exec(pFrm);
+
+    //do the G-Sensor test by called the interface in meta G-Sensor lib
+    if(getInitState())
+        Meta_GSensor_OP((GS_REQ *)pFrm->localBuf());
+}
+
+int FtModGSensor::init(Frame*pFrm)
+{
+    META_LOG("[Meta][FT] FT_GSensor");
+
+    GS_CNF ft_cnf;
+    static int bInitFlag_GS = false;
+    GS_REQ *req = (GS_REQ *)pFrm->localBuf();
+
+    memset(&ft_cnf, 0, sizeof(GS_CNF));
+
+    if (bInitFlag_GS == false) {
+        // initial the G-Sensor module when it is called first time
+        if (!Meta_GSensor_Open()) {
+            ft_cnf.header.id = req->header.id +1;
+            ft_cnf.header.token = req->header.token;
+            ft_cnf.status = META_FAILED;
+            ft_cnf.op = req->op;
+
+            META_LOG("[Meta][FT] FT_GSENSOR_OP Meta_GSensor_Open Fail ");
+            WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+            return false;
+        }
+        bInitFlag_GS = true;
+    }
+    return true;
+}
+
+#endif
+
+
+#ifdef FT_MSENSOR_FEATURE
+
+FtModMSensor::FtModMSensor(void)
+    :CmdTarget(FT_MSENSOR_REQ_ID)
+{
+    memset(&m_ft_cnf, 0, sizeof(FT_MSENSOR_CNF));
+}
+
+FtModMSensor::~FtModMSensor(void)
+{
+    Meta_MSensor_Close();
+}
+
+void FtModMSensor::exec(Frame *pFrm)
+{
+
+    META_LOG("[Meta][FT] FT_MSensor");
+
+    int res = -1;
+    memset(&m_ft_cnf, 0, sizeof(FT_MSENSOR_CNF));
+
+    FT_MSENSOR_REQ *req = (FT_MSENSOR_REQ *)pFrm->localBuf();
+
+    m_ft_cnf.header.id = req->header.id + 1;
+    m_ft_cnf.header.token = req->header.token;
+    m_ft_cnf.status = META_SUCCESS;
+
+    CmdTarget::exec(pFrm);
+
+    if(getInitState()) {
+        res = Meta_MSensor_OP();
+        if (0 == res) {
+            META_LOG("[Meta][FT] FT_MSENSOR_OP Meta_MSensor_OP success!");
+            m_ft_cnf.status = META_SUCCESS;
+        }
+        else {
+            META_LOG("[Meta][FT] FT_MSENSOR_OP Meta_MSensor_OP failed!");
+            m_ft_cnf.status = META_FAILED;
+        }
+
+        WriteDataToPC(&m_ft_cnf, sizeof(m_ft_cnf),NULL, 0);
+    }
+
+}
+
+int FtModMSensor::init(Frame*)
+{
+    static int bInitFlag_MS = false;
+
+    if (bInitFlag_MS == false) {
+        // initial the M-Sensor module when it is called first time
+        if (!Meta_MSensor_Open()) {
+            META_LOG("[Meta][FT] FT_MSENSOR_OP Meta_MSensor_Open failed!");
+            m_ft_cnf.status = META_FAILED;
+            WriteDataToPC(&m_ft_cnf, sizeof(m_ft_cnf),NULL, 0);
+            return false;
+        }
+        bInitFlag_MS = TRUE;
+    }
+
+    return true;
+}
+#endif
+
+#ifdef FT_ALSPS_FEATURE
+
+FtModALSPS::FtModALSPS(void)
+    :CmdTarget(FT_ALSPS_REQ_ID)
+{
+    memset(&m_ft_cnf, 0, sizeof(FT_ALSPS_CNF));
+}
+
+FtModALSPS::~FtModALSPS(void)
+{
+    Meta_ALSPS_Close();
+}
+
+void FtModALSPS::exec(Frame *pFrm)
+{
+    META_LOG("[Meta][FT] FT_ALSPS");
+
+    int res = -1;
+    memset(&m_ft_cnf, 0, sizeof(FT_ALSPS_CNF));
+
+    FT_ALSPS_REQ *req = (FT_ALSPS_REQ *)pFrm->localBuf();
+
+    m_ft_cnf.header.id = req->header.id + 1;
+    m_ft_cnf.header.token = req->header.token;
+    m_ft_cnf.status = META_SUCCESS;
+
+    CmdTarget::exec(pFrm);
+
+    if(getInitState()) {
+        res = Meta_ALSPS_OP();
+        if (0 == res) {
+            META_LOG("[Meta][FT] FT_ALSPS_OP Meta_ALSPS_OP success!");
+            m_ft_cnf.status = META_SUCCESS;
+        } else {
+            META_LOG("[Meta][FT] FT_ALSPS_OP Meta_ALSPS_OP failed!");
+            m_ft_cnf.status = META_FAILED;
+        }
+        WriteDataToPC(&m_ft_cnf, sizeof(m_ft_cnf),NULL, 0);
+    }
+
+}
+
+int FtModALSPS::init(Frame*)
+{
+    static int bInitFlag_ALSPS = false;
+
+    if (bInitFlag_ALSPS == false) {
+        // initial the M-Sensor module when it is called first time
+        if (!Meta_ALSPS_Open()) {
+            META_LOG("[Meta][FT] FT_ALSPS_OP Meta_ALSPS_Open failed!");
+            m_ft_cnf.status = META_FAILED;
+            WriteDataToPC(&m_ft_cnf, sizeof(m_ft_cnf),NULL, 0);
+            return false;
+        }
+        bInitFlag_ALSPS = true;
+    }
+    return true;
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_GYROSCOPE_FEATURE
+
+FtModGyroSensor::FtModGyroSensor(void)
+    :CmdTarget(FT_GYROSCOPE_REQ_ID)
+{
+}
+
+FtModGyroSensor::~FtModGyroSensor(void)
+{
+    Meta_Gyroscope_Close();
+}
+
+void FtModGyroSensor::exec(Frame *pFrm)
+{
+    CmdTarget::exec(pFrm);
+
+    //do the Gyroscope-Sensor test by called the interface in meta Gyroscope-Sensor lib  
+    if(getInitState())
+        Meta_Gyroscope_OP((GYRO_REQ *)pFrm->localBuf());
+}
+
+int FtModGyroSensor::init(Frame* pFrm)
+{
+    META_LOG("[Meta][FT] FT_GyroSensor");
+    GYRO_REQ *req = (GYRO_REQ *)pFrm->localBuf();
+    static int bInitFlag_GYRO = false;
+    GYRO_CNF ft_cnf;
+    memset(&ft_cnf, 0, sizeof(GYRO_CNF));
+
+    if (bInitFlag_GYRO == false) {
+        // initial the Gyroscope-Sensor module when it is called first time
+        if (!Meta_Gyroscope_Open()) {
+            ft_cnf.header.id = req->header.id +1;
+            ft_cnf.header.token = req->header.token;
+            ft_cnf.status = META_FAILED;
+            ft_cnf.op = req->op;
+
+            META_LOG("[Meta][FT] FT_GYROSENSOR_OP Meta_GYROSensor_Open Fail ");
+            WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+            return false;
+        }
+        bInitFlag_GYRO = true;
+    }
+
+    return true;
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#define MDDB_FILE_FOLDER "/data/vendor_de/meta/mddb/"
+#define MDDB_FILE_FOLDER_EX "/data/vendor_de/meta/mddb"
+#define MD1INFO_FILE_PATH "/data/vendor_de/meta/mddb/md1_file_map.log"
+#define MD1INFO_FILE_MAP_KEYWORD "md1_file_map"
+#define MD1DB_FILE_KEYWORD "md1_mddbmeta"
+#define MD1OPENDB_FILE_KEYWORD "md1_mddbmetaodb"
+
+#define MD3INFO_FILE_PATH "/data/vendor_de/meta/mddb/md3_file_map.log"
+#define MD3INFO_FILE_MAP_KEYWORD "md3_file_map"
+#define MD3DB_FILE_KEYWORD "md3_mddb_c2k_meta"
+
+
+
+FtModModemInfo::FtModModemInfo(void)
+	:CmdTarget(FT_MODEM_REQ_ID)
+{
+}
+
+FtModModemInfo::~FtModModemInfo(void)
+{
+}
+
+int FtModModemInfo::getModemCapability(MODEM_CAPABILITY_LIST_CNF* modem_capa)
+{
+	int modem_type = 0;	
+	modem_type = getMdmType();
+
+	if((modem_type & MD1_INDEX) == MD1_INDEX)
+	{
+	    if(getModemProtocol(0, (void*)modem_capa) == 0)
+	    {
+	        META_LOG("[Meta][FT] MD1 getModemProtocol fail");
+	        return 0;
+	    }
+	}
+
+	if((modem_type & MD2_INDEX) == MD2_INDEX)
+	{
+	    if(getModemProtocol(1, (void*)modem_capa) == 0)
+	    {
+	        META_LOG("[Meta][FT] MD2 getModemProtocol fail");
+	        return 0;
+	    }
+	}
+
+	if((modem_type & MD3_INDEX) == MD3_INDEX)
+	{
+	    if(getModemProtocol(2, (void*)modem_capa) == 0)
+	    {
+	        META_LOG("[Meta][FT] MD3 getModemProtocol fail");
+	        return 0;
+	    }
+	}
+
+	if((modem_type & MD5_INDEX) == MD5_INDEX)
+	{	
+	    if(getModemProtocol(4, (void*)modem_capa) == 0)
+	    {
+	        META_LOG("[Meta][FT] MD5 getModemProtocol fail");
+	        return 0;
+	    }
+	}
+
+	return 1;
+}
+
+void FtModModemInfo::rebootModem(FT_MODEM_REQ *req, FT_MODEM_CNF & ft_cnf, int fd)
+{
+	META_LOG("[Meta] Enter rebootModem");
+	int result = 0;
+	int modem_mode = req->cmd.reboot_modem_req.mode;
+	int modem_index = req->cmd.reboot_modem_req.modem_index;
+	META_LOG("[Meta] modem_mode = %d", modem_mode);
+	META_LOG("[Meta] modem_index = %d", modem_index);
+
+	if(getModemHwVersion(0) >= MODEM_6293) //for Gen 93 and subsequent modem
+	{
+		if(0 == ChangeModemMode(modem_mode))
+		{
+			META_LOG("[Meta] Switch modem mode to %d success", modem_mode);
+			setMDMode(modem_mode);
+			if(modem_mode == 1)
+			{
+#ifdef IS_SUPPORT_SP			
+				property_set("persist.vendor.atm.mdmode", "normal");
+#endif
+			}
+			else if(modem_mode == 2)
+			{
+#ifdef IS_SUPPORT_SP
+				property_set("persist.vendor.atm.mdmode", "meta");
+#endif
+				createAllModemThread();
+			}
+			ft_cnf.status = META_SUCCESS;
+		}
+		else
+		{
+			META_LOG("[Meta] Switch modem mode from %d to %d fail", getMDMode(), modem_mode);
+			ft_cnf.status = META_FAILED;
+		}
+	}
+	else  //for modem before 93
+	{
+		setActiveATModem(modem_index);
+
+		META_LOG("[Meta] Destory modem thread and close modem handle");
+		destroyAllModemThread();
+		if (fd >= 0 && 0 == (result = ioctl(fd, CCCI_IOC_SET_MD_BOOT_MODE, &modem_mode)))
+		{	
+			META_LOG("[Meta][FT] ioctl CCCI_IOC_SET_MD_BOOT_MODE success modem_mode = %d", modem_mode);
+			if (0 == (result = ioctl(fd, CCCI_IOC_MD_RESET)))
+			{
+				ft_cnf.status = META_SUCCESS;
+				META_LOG("[Meta][FT] ioctl CCCI_IOC_MD_RESET success " );
+			}
+			else
+			{
+				ft_cnf.status = META_FAILED;
+				META_LOG("[Meta][FT] ioctl CCCI_IOC_MD_RESET fail result = %d, errno = %d, fd = %d", result, errno, fd);	
+			}
+		}
+		else
+		{
+			ft_cnf.status = META_FAILED;
+			META_LOG("[Meta][FT] ioctl CCCI_IOC_SET_MD_BOOT_MODE fail modem_mode = %d, result = %d, errno = %d, fd = %d", modem_mode, result, errno, fd);
+		}
+
+	}
+}
+int FtModModemInfo::getModemMode(FT_MODEM_REQ *req, FT_MODEM_CNF & ft_cnf, int fd)
+{
+	int modem_state = 0;
+	int modem_boot_mode = 0;
+	int result = 0;
+
+	META_LOG("[Meta][FT] getModemMode req->type = %d", req->type);
+	if(fd < 0)
+	{
+		ft_cnf.status = META_FAILED;
+		META_LOG("[Meta][FT] invalid ioctl dev port. fd = %d", fd );
+		return -1;
+	}
+	
+	while(modem_state != 2)
+	{
+		if(0 == (result=ioctl(fd, CCCI_IOC_GET_MD_STATE, &modem_state)))
+		{
+			META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_STATE success modem_state = %d",modem_state );
+			usleep(200*1000);
+		}
+		else
+		{
+			ft_cnf.status = META_FAILED;
+			META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_STATE fail result = %d, errno = %d, fd = %d", result, errno, fd );
+			return -1;
+		}				
+	}
+		
+	if (0 == (result=ioctl(fd, CCCI_IOC_GET_MD_BOOT_MODE,&modem_boot_mode)))
+	{
+		ft_cnf.status = META_SUCCESS;
+		ft_cnf.result.get_modem_mode_cnf.mode = modem_boot_mode;
+		META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_BOOT_MODE success modem_boot_mode = %d",modem_boot_mode );
+		setMDMode(modem_boot_mode);//normal= 1 meta=2
+		return 0;
+		}
+	else
+	{
+		ft_cnf.status = META_FAILED;
+		META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_BOOT_MODE fail result = %d, errno = %d, fd = %d", result, errno, fd);	
+		return -1;
+	}
+
+	return 0;
+}
+
+int FtModModemInfo::getModemState(int *modem_state, int fd)
+{
+	int result = 0;
+	int retry_count = 0;
+
+	//Get modem reboot status
+	do
+	{
+		if(0 == ioctl(fd, CCCI_IOC_GET_MD_STATE, modem_state))
+		{
+			retry_count++;
+		}
+		usleep(500*1000);
+		META_LOG("[Meta][FT][DEBUG] Query modem reboot result %d times", retry_count);
+	}while((*modem_state != 2) && (retry_count<10));
+	if(*modem_state == 2)
+	{
+		META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_STATE success, modem_state = %d", *modem_state);
+	}
+	else
+	{
+		META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_STATE fail, modem_state = %d", *modem_state);
+		result = -1;
+	}
+
+	return result;
+}
+
+int FtModModemInfo::getModemType(int *modem_type, int fd)
+{
+	int result = 0;
+
+	//Get modem type
+	if (fd >= 0 && 0 == ioctl(fd, CCCI_IOC_GET_MD_TYPE, modem_type))
+	{
+		META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_TYPE success, modem_type = %d", *modem_type);
+	}
+	else
+	{
+		META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_TYPE fail, modem_type = %d", *modem_type);
+	    result = -1;
+	}
+	return result;
+}
+
+int FtModModemInfo::setModemType(int modem_type, int fd)
+{
+	int result = 0;
+
+	//Set modem type and reboot modem
+	if (fd >= 0 && 0 == ioctl(fd, CCCI_IOC_RELOAD_MD_TYPE, &modem_type))
+	{
+		META_LOG("[Meta][FT] ioctl CCCI_IOC_RELOAD_MD_TYPE success, modem_type = %d", modem_type);
+		if (0 == ioctl(fd, CCCI_IOC_MD_RESET))
+		{
+			META_LOG("[Meta][FT] ioctl CCCI_IOC_MD_RESET success " );
+		}
+		else
+		{
+			META_LOG("[Meta][FT] ioctl CCCI_IOC_MD_RESET fail " );
+		    result = -1;
+		}
+	}
+	else
+	{
+		META_LOG("[Meta][FT] ioctl CCCI_IOC_RELOAD_MD_TYPE fail, modem_type = %d", modem_type);
+		result = -1;
+	}
+	return result;
+}
+
+int FtModModemInfo::getModemIndex(FT_MODEM_REQ *req)
+{
+	int nModemIndex = 0;	
+	
+	if(req->type == FT_MODEM_OP_SET_MODEMTYPE)
+    {
+        nModemIndex = req->cmd.set_modem_type_req.modem_id;
+    }
+	else if(req->type == FT_MODEM_OP_GET_CURENTMODEMTYPE)
+	{
+	    nModemIndex = req->cmd.get_currentmodem_type_req.modem_id;
+	}
+	else if(req->type == FT_MODEM_OP_QUERY_MDIMGTYPE)
+	{
+	    nModemIndex = req->cmd.query_modem_imgtype_req.modem_id;
+	}
+	
+	if(nModemIndex > 0 && nModemIndex < 6)
+	{
+	    nModemIndex = nModemIndex - 1;
+	}
+	else
+	{
+	    nModemIndex = 0;
+	}	
+
+	return nModemIndex;
+	
+}
+
+#ifdef MTK_SINGLE_BIN_MODEM_SUPPORT
+int FtModModemInfo::CopyMDDBFile(unsigned int nModemId)
+{
+    if (access(MDDB_FILE_FOLDER,F_OK) != 0 )
+    {
+        META_LOG("[Meta][FT] CopyMDDBFile %s folder doesn't exist error %s\n", MDDB_FILE_FOLDER, strerror(errno));
+        return 0;
+    }
+
+    char mddb_path[256] = {0};
+    char mdopendb_path[256] = {0};
+    char info_name[128] = {0};
+    char info_path[256] = {0};
+    memcpy(mddb_path,MDDB_FILE_FOLDER, strlen(MDDB_FILE_FOLDER));
+    memcpy(mdopendb_path,MDDB_FILE_FOLDER, strlen(MDDB_FILE_FOLDER));
+    if(nModemId == 2)
+    {
+        memcpy(info_name,MD3INFO_FILE_MAP_KEYWORD, strlen(MD3INFO_FILE_MAP_KEYWORD));
+        memcpy(info_path,MD3INFO_FILE_PATH, strlen(MD3INFO_FILE_PATH));
+    }
+    else
+    {
+        memcpy(info_name,MD1INFO_FILE_MAP_KEYWORD, strlen(MD1INFO_FILE_MAP_KEYWORD));
+        memcpy(info_path,MD1INFO_FILE_PATH, strlen(MD1INFO_FILE_PATH));
+    }
+
+    int dbRet = -1;
+    int opendbRet = -1;
+    int info_ret = restore_image_from_pt(info_name, info_path);
+    META_LOG("[Meta][FT] CopyMDDBFile copy info file retore_image_from_pt info_ret:%d", info_ret);
+    if(info_ret <= 0)
+    {
+        META_LOG("[Meta][FT] CopyMDDBFile copy info file error %s\n", strerror(errno));
+        return -1;
+    }
+    else
+    {
+        FILE* fileInfoFd = NULL;
+        fileInfoFd = fopen(info_path,"r");
+        if (fileInfoFd == NULL)
+        {
+            META_LOG("[Meta][FT] CopyMDDBFile open info file error %s\n", strerror(errno));
+            return -1;
+        }
+        else
+        {
+            char *loc = NULL;
+            char* tmp = NULL;
+            char str[256] = {0};
+            while(!feof(fileInfoFd))
+            {
+                if(fgets(str, 256, fileInfoFd)!=NULL)
+                {
+                    tmp = str;
+                    loc = strsep(&tmp, "=");
+                    if(nModemId == 2)
+                    {
+                        if(!strcmp(loc, MD3DB_FILE_KEYWORD))
+                        {
+                            if (tmp[strlen(tmp)-1] == '\n')
+                            {
+                                tmp[strlen(tmp)-1] = '\0';
+                            }
+                            else if (tmp[strlen(tmp)-1] == '\r')
+                            {
+                                tmp[strlen(tmp)-1] = '\0';
+                            }
+                            strncat(mddb_path, tmp, strlen(tmp));
+                            META_LOG("[Meta][FT] CopyMDDBFile MDDB file path =%s, len =%d\n", mddb_path,strlen(mddb_path));
+                        }
+                    }
+                    else   //default is 0
+                    {
+                        if(!strcmp(loc, MD1DB_FILE_KEYWORD))
+                        {
+                            if (tmp[strlen(tmp)-1] == '\n')
+                            {
+                                tmp[strlen(tmp)-1] = '\0';
+                            }
+                            else if (tmp[strlen(tmp)-1] == '\r')
+                            {
+                                tmp[strlen(tmp)-1] = '\0';
+                            }
+                            strncat(mddb_path, tmp, strlen(tmp));
+                            META_LOG("[Meta][FT] CopyMDDBFile MDDB file path =%s, len =%d\n", mddb_path,strlen(mddb_path));
+                        }
+                        else if(!strcmp(loc, MD1OPENDB_FILE_KEYWORD))
+                        {
+                            if (tmp[strlen(tmp)-1] == '\n')
+                            {
+                                tmp[strlen(tmp)-1] = '\0';
+                            }
+                            else if (tmp[strlen(tmp)-1] == '\r')
+                            {
+                                tmp[strlen(tmp)-1] = '\0';
+                            }
+                            strncat(mdopendb_path, tmp, strlen(tmp));
+                            META_LOG("[Meta][FT] CopyMDDBFile MD open DB file path =%s, len =%d\n", mdopendb_path,strlen(mdopendb_path));
+                        }
+                    }
+                }
+            }
+            if (fileInfoFd != NULL)
+            {
+                fclose(fileInfoFd);
+            }
+        }
+    }
+    if(nModemId == 2)
+    {
+        dbRet = restore_image_from_pt(MD3DB_FILE_KEYWORD, mddb_path);
+        return dbRet;
+    }
+    else
+    {
+        dbRet = restore_image_from_pt(MD1DB_FILE_KEYWORD, mddb_path);
+        opendbRet = restore_image_from_pt(MD1OPENDB_FILE_KEYWORD, mdopendb_path);
+        if (dbRet > 0)
+        {
+            return dbRet;
+        }
+        else
+        {
+            return opendbRet;
+        }
+    }
+}
+#endif
+
+void FtModModemInfo::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] FT_ModemInfo");	
+
+	FT_MODEM_CNF ft_cnf;
+	int fd = -1;
+	static int modemCreate = 0;
+	int bDataDevice = FALSE;
+	
+
+	memset(&ft_cnf, 0, sizeof(FT_MODEM_CNF));
+	ft_cnf.status = META_FAILED;
+
+	
+	FT_MODEM_REQ *req = (FT_MODEM_REQ *)pFrm->localBuf();
+    META_LOG("[Meta][FT] FT_MODEM_INFO_OP, req type:%d ",req->type);
+
+	if(req->type == FT_MODEM_OP_QUERY_INFO)
+	{
+		ft_cnf.result.query_modem_info_cnf.modem_number = getMdmNumber();
+		ft_cnf.result.query_modem_info_cnf.modem_id = getActiveMdmId();
+		ft_cnf.status = META_SUCCESS;
+	}
+	else if(req->type == FT_MODEM_OP_CAPABILITY_LIST)
+	{
+		int nRet = 0;
+		MODEM_CAPABILITY_LIST_CNF modem_capa;
+		memset(&modem_capa, 0, sizeof(MODEM_CAPABILITY_LIST_CNF));
+		nRet = getModemCapability(&modem_capa);
+		memcpy(&ft_cnf.result.query_modem_cap_cnf,&modem_capa,sizeof(MODEM_CAPABILITY_LIST_CNF));
+		if (nRet == 1)
+		{
+		    ft_cnf.status = META_SUCCESS;
+		}
+		else
+		{
+		    ft_cnf.status = META_FAILED;
+		}
+	}
+	else if(req->type == FT_MODEM_OP_QUERY_MDDOWNLOADSTATUS)
+	{
+		char temp[128]={0};
+		int percentage = 0;
+		int status_code = 0;
+		//property_get("persist.sys.extmddlprogress",temp,NULL);
+		META_LOG("[Meta][FT] persist.sys.extmddlprogress = %s",temp);
+		sscanf(temp,"%03d_%04d",&percentage,&status_code);
+		META_LOG("[Meta][FT] FT_MODEM_INFO_OP FT_MODEM_OP_QUERY_MDDOWNLOADSTATUS percentage = %d,status_code = %d",percentage,status_code);
+		ft_cnf.result.query_modem_download_status_cnf.percentage = percentage;
+		ft_cnf.result.query_modem_download_status_cnf.status_code = status_code;
+		
+		if(percentage == 110 && status_code ==0 && modemCreate == 0)
+		{
+			unsigned int modemType = getMdmType();
+			if((modemType & MD5_INDEX) == MD5_INDEX)
+			{
+				createModemThread(4,1);
+			}
+			modemCreate = 1;
+		}
+		ft_cnf.status = META_SUCCESS;
+	}
+	else if(req->type == FT_MODEM_OP_QUERY_MDDBPATH)
+	{
+		char szMDDBPath[64] = {0};
+#ifdef MTK_SINGLE_BIN_MODEM_SUPPORT		
+        	if (CopyMDDBFile(req->cmd.query_mddbpath_req.modem_id) <= 0)
+		{
+		    META_LOG("[Meta][FILE OPERATION] FtModModemInfo Failed to copy MD %d DB from modem image, error %s\n",req->cmd.query_mddbpath_req.modem_id,strerror(errno));
+		    ft_cnf.status = META_FAILED;
+		}
+		else
+		{
+		    ft_cnf.status = META_SUCCESS;
+		}
+
+		strncpy(szMDDBPath, MDDB_FILE_FOLDER_EX, strlen(MDDB_FILE_FOLDER_EX));
+#else
+
+                strncpy(szMDDBPath, MTK_MDDB_PATH, strlen(MTK_MDDB_PATH));
+                ft_cnf.status = META_SUCCESS;
+#endif
+		memcpy(ft_cnf.result.query_mddbpath_cnf.mddb_path, szMDDBPath, strlen(szMDDBPath));
+		META_LOG("[Meta][FT] FtModModemInfo mddb_path: %s",ft_cnf.result.query_mddbpath_cnf.mddb_path);
+		ft_cnf.header.id = req->header.id +1;
+		ft_cnf.header.token = req->header.token;
+		ft_cnf.type = req->type;
+		WriteDataToPC(&ft_cnf, sizeof(FT_MODEM_CNF),NULL, 0);
+		return;
+	}
+
+	else if(req->type == FT_MODEM_OP_SET_MODEMTYPE)
+    {
+
+		unsigned int modem_type = req->cmd.set_modem_type_req.modem_type;
+		fd = getIOCPort(getModemIndex(req),bDataDevice);
+
+		if (fd >= 0 && 0 == ioctl(fd, CCCI_IOC_RELOAD_MD_TYPE, &modem_type))
+		{
+			if (0 == ioctl(fd, CCCI_IOC_MD_RESET))
+			{
+				ft_cnf.status = META_SUCCESS;		
+			}
+			else
+			{
+				ft_cnf.status = META_FAILED;
+				META_LOG("[Meta][FT] ioctl CCCI_IOC_MD_RESET fail " );	
+			}
+		}
+		else
+		{
+			ft_cnf.status = META_FAILED;
+			META_LOG("[Meta][FT] ioctl CCCI_IOC_RELOAD_MD_TYPE fail modem_type = %d", modem_type);	
+		}
+
+	}
+	else if(req->type == FT_MODEM_OP_GET_CURENTMODEMTYPE)
+	{
+		unsigned int modem_type=0;
+
+		fd = getIOCPort(getModemIndex(req),bDataDevice);
+		
+		if (fd >= 0 && 0 == ioctl(fd, CCCI_IOC_GET_MD_TYPE, &modem_type))
+		{
+			ft_cnf.status = META_SUCCESS;
+			ft_cnf.result.get_currentmodem_type_cnf.current_modem_type = modem_type;	
+			META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_TYPE success modem_type = %d", modem_type);
+		}
+		else
+		{
+			ft_cnf.status = META_FAILED;
+			META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_TYPE fail");	
+		}	
+		
+	}
+	else if(req->type == FT_MODEM_OP_QUERY_MDIMGTYPE)
+	{
+		unsigned int mdimg_type[16]={0};
+		fd = getIOCPort(getModemIndex(req),bDataDevice);
+
+		if (fd >= 0 && 0 == ioctl(fd, CCCI_IOC_GET_MD_IMG_EXIST, &mdimg_type))
+		{
+			ft_cnf.status = META_SUCCESS;
+			memcpy(ft_cnf.result.query_modem_imgtype_cnf.mdimg_type,mdimg_type,16*sizeof(unsigned int));
+
+			for(int i = 0;i<16;i++)
+			{
+				META_LOG("[Meta][FT] mdimg_type[%d] %d",i, mdimg_type[i]);	
+			}
+				
+		}
+		else
+		{
+			ft_cnf.status = META_FAILED;
+			META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_IMG_EXIST fail");	
+		}
+
+	}
+	else if(req->type == FT_MODEM_OP_REBOOT_MODEM)
+	{
+		fd = getIOCPort(getModemIndex(req),bDataDevice);
+		rebootModem(req,ft_cnf,fd);
+	}
+	else if(req->type == FT_MODEM_OP_GET_MODEMMODE)
+	{
+		fd = getIOCPort(getModemIndex(req),bDataDevice);
+		int result = getModemMode(req,ft_cnf,fd);
+		if(bDataDevice == FALSE)
+		{
+	     	if(fd != -1)
+		 	{
+		     	close(fd);
+				META_LOG("[Meta][FT]Close fd");
+				fd = -1;
+	     	}
+		}
+
+		//create modem thread and open modem handle
+		if(result == 0)
+			createAllModemThread();		
+		
+	}
+	else if(req->type == FT_MODEM_OP_SUPPORT_COMPRESS)
+	{
+
+#ifdef MTK_META_COMPRESS_SUPPORT
+		META_LOG("[Meta][FT] set data compress status: %d", req->cmd.set_compress_req.action);
+		SetDataCompressStatus(req->cmd.set_compress_req.action);
+		ft_cnf.result.set_compress_cnf.result = 1;
+		ft_cnf.status = META_SUCCESS;
+#else
+		META_LOG("[Meta][FT] not support data compress");
+#endif
+
+	
+	}
+	else
+	{
+		META_LOG("[Meta][FT] FT_MODEM_REQ have no this type %d",req->type );		
+	}
+	
+
+	if(bDataDevice == FALSE)
+	{
+	     if(fd != -1)
+		 {
+		     close(fd);
+			 META_LOG("[Meta][FT]Close fd");
+			 fd = -1;
+	     }
+	}
+	
+	ft_cnf.header.id = req ->header.id +1;
+    ft_cnf.header.token = req ->header.token;
+	ft_cnf.type = req ->type;	
+
+
+	META_LOG("[META] ft_cnf.status = %d",ft_cnf.status);
+	
+	WriteDataToPC(&ft_cnf, sizeof(FT_MODEM_CNF),NULL, 0);	
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModSIMNum::FtModSIMNum(void)
+	:CmdTarget(FT_SIM_NUM_REQ_ID)
+{
+}
+
+FtModSIMNum::~FtModSIMNum(void)
+{
+}
+
+void FtModSIMNum::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] Ft_SIMNum");	
+
+	FT_GET_SIM_CNF ft_cnf;
+
+	FT_GET_SIM_REQ *req = (FT_GET_SIM_REQ *)pFrm->localBuf();
+
+	ft_cnf.header.id = req->header.id +1;
+    ft_cnf.header.token = req->header.token;
+    ft_cnf.type = req->type;
+    ft_cnf.status = META_SUCCESS;
+	ft_cnf.number = 2;
+
+#ifdef IS_SUPPORT_SP			
+	char tempstr[128]={0};
+	property_get("persist.vendor.radio.multisim.config",tempstr,"ss");
+
+    META_LOG("[Meta][FT] The sim card number default is two");
+	if((strcmp(tempstr,"dsds")==0) || (strcmp(tempstr,"dsda")==0))
+	{
+		ft_cnf.number = 2;
+		META_LOG("[Meta][FT] The sim card number is two");
+	}
+	else if(strcmp(tempstr,"tsts")==0)
+	{
+		ft_cnf.number = 3;
+		META_LOG("[Meta][FT] The sim card number is three");
+	}
+	else if(strcmp(tempstr,"qsqs")==0)
+	{
+		ft_cnf.number = 4;
+		META_LOG("[Meta][FT] The sim card number is four");
+    }
+	else if(strcmp(tempstr,"ss")==0)
+    {
+		ft_cnf.number = 1;
+    }
+#endif
+
+   	WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_SDCARD_FEATURE
+
+FtModSDcard::FtModSDcard(void)
+	:CmdTarget(FT_SDCARD_REQ_ID)
+{
+}
+
+FtModSDcard::~FtModSDcard(void)
+{
+}
+
+void FtModSDcard::exec(Frame *pFrm)
+{
+
+	CmdTarget::exec(pFrm);
+	
+	if(getInitState())   
+	    Meta_SDcard_OP((SDCARD_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+
+}
+
+int FtModSDcard::init(Frame* pFrm)
+{
+ 	META_LOG("[Meta][FT] Ft_SDcard");
+
+    SDCARD_CNF ft_cnf;	
+	memset(&ft_cnf, 0, sizeof(SDCARD_CNF));
+    static int bInitFlag_SDcard = FALSE;
+	
+	SDCARD_REQ *req = (SDCARD_REQ *)pFrm->localBuf();
+
+	META_LOG("[Meta][FT] FT_SDcard_OP META Test req: %zd , %zd ",
+        sizeof(SDCARD_REQ), sizeof(SDCARD_CNF));
+		
+    if (FALSE == bInitFlag_SDcard)
+    {
+        // initial the DVB module when it is called first time
+        if (!Meta_SDcard_Init(req))
+        {
+            ft_cnf.header.id = req->header.id +1;
+            ft_cnf.header.token = req->header.token;
+            ft_cnf.status = META_FAILED;
+
+            META_LOG("[Meta][FT] FT_SDcard_OP Meta_SDcard_Init Fail ");
+    		WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+			return false;
+        }
+        bInitFlag_SDcard = TRUE;
+    }
+	return true;
+}
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_EMMC_FEATURE
+
+FtModEMMC::FtModEMMC(void)
+	:CmdTarget(FT_EMMC_REQ_ID)
+{
+}
+
+FtModEMMC::~FtModEMMC(void)
+{
+}
+
+void FtModEMMC::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] Ft_EMMC");
+
+    META_CLR_EMMC_OP((FT_EMMC_REQ *)pFrm->localBuf());
+
+}
+#endif
+
+#ifdef FT_NAND_FEATURE
+
+FtModEMMC::FtModEMMC(void)
+	:CmdTarget(FT_EMMC_REQ_ID)
+{
+}
+
+FtModEMMC::~FtModEMMC(void)
+{
+}
+
+void FtModEMMC::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] Ft_EMMC");
+
+    META_CLR_EMMC_OP((FT_EMMC_REQ *)pFrm->localBuf());
+
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_CRYPTFS_FEATURE
+
+FtModCRYPTFS::FtModCRYPTFS(void)
+	:CmdTarget(FT_CRYPTFS_REQ_ID)
+{
+}
+
+FtModCRYPTFS::~FtModCRYPTFS(void)
+{
+}
+
+void FtModCRYPTFS::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] Ft_CRYPTFS");
+	
+    META_CRYPTFS_OP((FT_CRYPTFS_REQ *)pFrm->localBuf());    
+
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_ADC_FEATURE
+
+FtModADC::FtModADC(void)
+	:CmdTarget(FT_ADC_REQ_ID)
+{
+}
+
+FtModADC::~FtModADC(void)
+{
+}
+
+void FtModADC::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] Ft_ADC");
+
+	Meta_ADC_OP((ADC_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(),  pFrm->peerLen());  
+}
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModCustomer::FtModCustomer(void)
+	:CmdTarget(FT_CUSTOMER_REQ_ID)
+{
+}
+
+FtModCustomer::~FtModCustomer(void)
+{
+}
+
+void FtModCustomer::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] Ft_Customer");
+
+    FT_CUSTOMER_CNF ft_cnf;
+    memset(&ft_cnf, 0, sizeof(FT_CUSTOMER_CNF));
+	FT_CUSTOMER_REQ *req = (FT_CUSTOMER_REQ *)pFrm->localBuf();
+	
+	int peer_buff_size = 1;
+    char* peer_buf = NULL;
+    int setResult = -1;
+    
+	// Implement custom API logic here. The following is a sample code for testing.
+    ft_cnf.header.id = req->header.id +1;
+    ft_cnf.header.token = req->header.token;
+	ft_cnf.type = req->type;
+    ft_cnf.status = META_SUCCESS;
+	
+	peer_buf = (char*)malloc(peer_buff_size);
+	memset(peer_buf, 0, peer_buff_size);
+
+	META_LOG("[Meta][FT] setNormalModeTestFlag");
+	setResult = setNormalModeTestFlag(req->cmd.m_u1Dummy);
+	if(0 == setResult)
+	{
+		ft_cnf.status = META_SUCCESS;
+	}
+	else
+	{
+	    ft_cnf.status = META_FAILED;
+	}
+	
+	META_LOG("[Meta][FT] FT_CUSTOMER_OP successful, OP type is %d!", req->type);
+	
+    WriteDataToPC(&ft_cnf, sizeof(ft_cnf), peer_buf, peer_buff_size);
+	free(peer_buf);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModSpecialTest::FtModSpecialTest(void)
+	:CmdTarget(FT_SPECIALTEST_REQ_ID)
+{
+}
+
+FtModSpecialTest::~FtModSpecialTest(void)
+{
+}
+
+void FtModSpecialTest::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] Ft_SpecialTest");
+	
+	FT_SPECIALTEST_REQ *req = (FT_SPECIALTEST_REQ *)pFrm->localBuf();
+	
+    FT_SPECIALTEST_CNF SpecialTestCnf;
+    memset(&SpecialTestCnf, 0, sizeof(FT_SPECIALTEST_CNF));
+    SpecialTestCnf.header.id = req->header.id +1;
+    SpecialTestCnf.header.token = req->header.token;
+    SpecialTestCnf.type = req->type;
+    SpecialTestCnf.status= META_FAILED;
+
+    switch (req->type)
+    {
+          case FT_SPECIALTEST_OP_HUGEDATA:		//query the supported modules
+                  META_LOG("[Meta][FT] pFTReq->type is FT_SPECIALTEST_OP_HUGEDATA ");                 
+                  SpecialTestCnf.status= META_SUCCESS;
+                  break;
+          default :
+                  break;
+    }
+
+    WriteDataToPC(&SpecialTestCnf, sizeof(FT_SPECIALTEST_CNF),(char *)pFrm->peerBuf(),  pFrm->peerLen());   
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define CHIP_RID_PATH	"/proc/rid"
+#define CHIP_RID_LEN 	16 
+
+
+FtModChipID::FtModChipID(void)
+	:CmdTarget(FT_GET_CHIPID_REQ_ID)
+{
+}
+
+FtModChipID::~FtModChipID(void)
+{
+}
+
+void FtModChipID::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] Ft_ChipID");
+
+	FT_GET_CHIPID_CNF ft_cnf;
+	int bytes_read = 0;
+	int res = 0;
+		
+	memset(&ft_cnf, 0, sizeof(FT_GET_CHIPID_CNF));
+
+	
+	FT_GET_CHIPID_REQ *req = (FT_GET_CHIPID_REQ *)pFrm->localBuf();
+		
+	ft_cnf.header.id = req->header.id +1;
+	ft_cnf.header.token = req->header.token;
+	ft_cnf.status = META_FAILED;
+		
+	int fd = open(CHIP_RID_PATH, O_RDONLY);
+	if (fd != -1)
+	{
+		while (bytes_read < CHIP_RID_LEN)
+		{
+			res = read(fd, ft_cnf.chipId + bytes_read, CHIP_RID_LEN);
+			if (res > 0)
+				bytes_read += res;
+			else
+				break;
+		}
+		close(fd);
+		ft_cnf.chipId[bytes_read] = '\0';
+		ft_cnf.status = META_SUCCESS;
+		META_LOG("[Meta][FT] Chip rid=%s", ft_cnf.chipId);
+	}
+	else
+	{
+		if (errno == ENOENT)
+		{
+			ft_cnf.status = META_FAILED;
+		}
+		META_LOG("[Meta][FT] Failed to open chip rid file %s, errno=%d", CHIP_RID_PATH, errno);
+	}
+		
+	WriteDataToPC(&ft_cnf, sizeof(ft_cnf), NULL, 0);
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_TOUCH_FEATURE
+
+FtModCTP::FtModCTP(void)
+	:CmdTarget(FT_CTP_REQ_ID)
+{
+	memset(&m_ft_cnf, 0, sizeof(Touch_CNF));
+}
+
+FtModCTP::~FtModCTP(void)
+{
+}
+
+void FtModCTP::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+	
+	memset(&m_ft_cnf, 0, sizeof(Touch_CNF));
+	Touch_REQ *req = (Touch_REQ *)pFrm->localBuf();
+	
+	m_ft_cnf.header.id = req->header.id + 1;
+	m_ft_cnf.header.token = req->header.token;
+	m_ft_cnf.status = META_SUCCESS;
+	m_ft_cnf.tpd_type = req->tpd_type;
+	
+	if(getInitState())
+		Meta_Touch_OP(req,(char *)pFrm->peerBuf(),  pFrm->peerLen());	
+
+}
+
+int FtModCTP::init(Frame*)
+{
+	META_LOG("[Meta][FT] Ft_CTP");
+	
+	static int bInitFlag_CTP = false;
+	if (false == bInitFlag_CTP)
+	{
+		// initial the touch panel module when it is called first time
+		if (!Meta_Touch_Init())
+		{
+			META_LOG("[Meta][FT] FT_CTP_OP Meta_Touch_Init failed!");
+			m_ft_cnf.status = META_FAILED;
+			WriteDataToPC(&m_ft_cnf, sizeof(m_ft_cnf),NULL, 0);
+			return false;
+		}
+		bInitFlag_CTP = TRUE;
+	}
+
+	return true;
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef FT_GPIO_FEATURE
+
+FtModGPIO::FtModGPIO(void)
+	:CmdTarget(FT_GPIO_REQ_ID)
+{
+	
+}
+
+FtModGPIO::~FtModGPIO(void)
+{
+}
+
+void FtModGPIO::exec(Frame *pFrm)
+{
+	GPIO_CNF ft_cnf;
+	CmdTarget::exec(pFrm);
+
+    META_LOG("[Meta][FT] Ft_GPIO");
+	memset(&ft_cnf, 0, sizeof(GPIO_CNF));
+
+	GPIO_REQ *req = (GPIO_REQ *)pFrm->localBuf();
+
+	if(getInitState())
+	{	//do the bat test by called the interface in meta bat lib
+    	ft_cnf = Meta_GPIO_OP(*req,(unsigned char *)pFrm->peerBuf(),  pFrm->peerLen());
+    	WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+	}
+}
+
+int FtModGPIO::init(Frame*pFrm)
+{
+	GPIO_CNF ft_cnf;
+    static int bInitFlag_GPIO = false;
+
+    META_LOG("[Meta][FT] FT_GPIO_OP META Test ");
+    memset(&ft_cnf, 0, sizeof(GPIO_CNF));
+	GPIO_REQ *req = (GPIO_REQ *)pFrm->localBuf();
+
+    if (FALSE == bInitFlag_GPIO)
+    {
+        // initial the bat module when it is called first time
+        if (!Meta_GPIO_Init())
+        {
+            ft_cnf.header.id = req->header.id +1;
+            ft_cnf.header.token = req->header.token;
+            ft_cnf.status = META_FAILED;
+
+            META_LOG("[Meta][FT] FT_GPIO_OP Meta_GPIO_Init Fail ");
+            WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+
+			return false;
+        }
+        bInitFlag_GPIO = true;
+    }
+
+	return true;
+}
+
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+//for mdlogger ctrl
+//#define MDLOG_SOCKET_NAME		     "com.mediatek.mdlogger.socket1"
+//#define MBLOG_SOCKET_NAME          "mobilelogd"
+
+FtModTargetloggerCtrl::FtModTargetloggerCtrl(void)
+	:CmdTarget(FT_TARGETLOG_CTRL_REQ_ID)
+{
+}
+
+FtModTargetloggerCtrl::~FtModTargetloggerCtrl(void)
+{
+}
+
+void FtModTargetloggerCtrl::exec(Frame *pFrm)
+{
+	META_LOG("[Meta][TARGETLOG CTRL] FtModTargetloggerCtrl");	
+
+	FT_TARGETLOG_CTRL_CNF  ft_cnf;	
+
+	memset(&ft_cnf, 0, sizeof(FT_TARGETLOG_CTRL_CNF));
+	ft_cnf.status = META_FAILED;
+
+	
+	FT_TARGETLOG_CTRL_REQ *req = (FT_TARGETLOG_CTRL_REQ *)pFrm->localBuf();
+
+	ft_cnf.header.id = req->header.id +1;
+    ft_cnf.header.token = req->header.token;
+    ft_cnf.type= req->type;
+
+	META_LOG("[Meta][TARGETLOG CTRL] FtModTargetloggerCtrl req->type = %d", req->type);
+	switch(req->type)
+	{
+		case FT_MDLOGGER_OP_SWITCH_TYPE:
+			{
+				if(SwitchMdloggerMode(req))
+					ft_cnf.status = META_SUCCESS;
+			}
+			break;
+		case FT_MDLOGGER_OP_QUERY_STATUS:
+			{
+				if(QueryMdloggerStatus(ft_cnf))
+					ft_cnf.status = META_SUCCESS;
+			}
+			break;
+		case FT_MDLOGGER_OP_QUERY_NORMALLOG_PATH:
+			{
+				if(QueryMdNormalLogPath(ft_cnf))
+	                ft_cnf.status = META_SUCCESS;
+			}
+			break;
+		case FT_MDLOGGER_OP_QUERY_EELOG_PATH:
+			{
+				if(QueryMdEELogPath(ft_cnf))
+	                ft_cnf.status = META_SUCCESS;
+			}
+			break;
+		case FT_MOBILELOG_OP_SWITCH_TYPE:
+			{
+				if(SwitchMobilelogMode(req))
+					ft_cnf.status = META_SUCCESS;
+			}
+			break;
+		case FT_MOBILELOG_OP_QUERY_LOG_PATH:
+			{
+                if(QueryMBLogPath(ft_cnf))
+	                ft_cnf.status = META_SUCCESS;
+			}
+			break;
+		case FT_TARGETLOG_OP_PULL:
+			{
+				if(TargetLogPulling(req))
+					ft_cnf.status = META_SUCCESS;
+			}
+			break;
+		case FT_TARGETLOG_OP_PULLING_STATUS:
+			{
+                if(GetTargetLogPullingStatus(req, ft_cnf))
+	                ft_cnf.status = META_SUCCESS;
+			}
+			break;
+		case FT_MDLOGGER_OP_SET_FILTER:
+			{
+				if(SetModemLogFilter(req))
+					ft_cnf.status = META_SUCCESS;
+			}
+			break;
+		case FT_CONNSYSLOG_OP_SWITCH_TYPE:
+			{
+				if(SwitchConnsyslogMode(req))
+					ft_cnf.status = META_SUCCESS;
+			}
+			break;
+		case FT_GPSLOGGER_OP_SWITCH_TYPE:
+			{
+				if(SwitchGPSlogMode(req))
+					ft_cnf.status = META_SUCCESS;
+			}
+			break;
+		case FT_TARGET_OP_CONNSYSLOG_LEVEL:
+			{
+				if(SetConnsysLogLevel(req))
+					ft_cnf.status = META_SUCCESS;
+			}
+			break;
+			
+		default:
+			break;
+	}
+
+	WriteDataToPC(&ft_cnf, sizeof(FT_TARGETLOG_CTRL_CNF),NULL, 0);
+}
+
+unsigned int FtModTargetloggerCtrl::SwitchGPSlogMode(FT_TARGETLOG_CTRL_REQ *req)
+{
+	char msg[32] = {0};
+	//char rsp[256] = {0};
+	int mode   = req->cmd.gpslog_ctrl_req.mode;
+	int action = req->cmd.gpslog_ctrl_req.action;
+	META_LOG("[Meta][TARGETLOG CTRL] GPS mode = %d, action = %d", mode, action);
+
+	if(action)
+	{
+		if(sprintf(msg, GPSLOG_START)<0)
+		{
+			META_LOG("[Meta][TARGETLOG CTRL]sprintf GPSLOG_START fail");	
+		}
+	}
+	else
+	{
+		if(sprintf(msg, GPSLOG_STOP)<0)
+		{
+			META_LOG("[Meta][TARGETLOG CTRL]sprintf GPSLOG_STOP fail");	
+		}	
+	}
+
+	MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_GPSLOGGER, GPSLOG_SOCKET_NAME);
+	if(pSocket != NULL)
+	{
+		pSocket->send_msg(msg, true);
+		return 1;
+	}
+			
+	return 0;	
+	
+}
+
+
+unsigned int FtModTargetloggerCtrl::SetConnsysLogLevel(FT_TARGETLOG_CTRL_REQ *req)
+{
+	char msg[32] = {0};
+	//char rsp[32]	 = {0};
+	META_LOG("[Meta][TARGETLOG CTRL] Set connsys log level");
+	
+	if(sprintf(msg, SET_FWLOG_LEVEL, req->cmd.connsyslog_set_level_req.type, req->cmd.connsyslog_set_level_req.level)<0)
+	{
+		META_LOG("[Meta][TARGETLOG CTRL]sprintf SET_FWLOG_LEVEL fail");	
+	}	
+
+	MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_CONNSYSLOG, CONNSYSLOG_SOCKET_NAME);
+	if(pSocket != NULL)
+	{
+		pSocket->send_msg(msg, true);
+		return 1;
+	}
+
+	return 0;
+}
+
+
+unsigned int FtModTargetloggerCtrl::SwitchMdloggerMode(FT_TARGETLOG_CTRL_REQ *req)
+{
+	char msg[32] = {0};
+//	char rsp[256] = {0};
+	int mode   = req->cmd.mdlogger_ctrl_req.mode;
+	int action = req->cmd.mdlogger_ctrl_req.action;
+	META_LOG("[Meta][TARGETLOG CTRL] mode = %d, action = %d", mode, action);
+
+	if(action)
+		sprintf(msg, MDLOG_START, mode);
+	else
+		sprintf(msg, MDLOG_STOP);
+
+	MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+	if(pSocket != NULL)
+	{
+		pSocket->send_msg(msg, true);
+		return 1;
+	}
+			
+	return 0;			
+}
+
+unsigned int FtModTargetloggerCtrl::QueryMdloggerStatus(FT_TARGETLOG_CTRL_CNF &cnf)
+{
+	char rsp[256] = {0};
+	MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+	if(pSocket != NULL)
+	{
+		pSocket->send_msg(MDLOG_QUERY_STATUS, false);
+		pSocket->recv_rsp(rsp);
+
+		cnf.result.mdlogger_status_cnf.status = atoi(rsp);
+		META_LOG("[Meta][TARGETLOG CTRL] mdlogger staus = %d", cnf.result.mdlogger_status_cnf.status);
+				
+		return 1;
+	}
+	else
+	{
+		META_LOG("[Meta][TARGETLOG CTRL] failed to find psocket");
+	}
+	return 0;
+}
+
+unsigned int FtModTargetloggerCtrl::QueryMdNormalLogPath(FT_TARGETLOG_CTRL_CNF &cnf)
+{
+	char rsp[256] = {0};
+	MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+	if(pSocket != NULL)
+	{
+		pSocket->send_msg(MDLOG_QUERY_NORMALLOG_PATH, false);
+		pSocket->recv_rsp(rsp);
+
+		if(rsp[0] != 0)
+            strncpy((char*)cnf.result.mdlogger_logpath_cnf.path, rsp, strlen(rsp));			
+		else
+		    cnf.result.mdlogger_logpath_cnf.path[0] = 0;
+
+		META_LOG("[Meta][TARGETLOG CTRL] modem normal log path = (%s)", cnf.result.mdlogger_logpath_cnf.path);
+		return 1;
+	}
+
+	return 0;
+}
+
+unsigned int FtModTargetloggerCtrl::QueryMdEELogPath(FT_TARGETLOG_CTRL_CNF &cnf)
+{
+	char rsp[256] = {0};
+	MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+	if(pSocket != NULL)
+	{
+		pSocket->send_msg(MDLOG_QUERY_EELOG_PATH, false);
+		pSocket->recv_rsp(rsp);
+
+		if(rsp[0] != 0)
+			strncpy((char*)cnf.result.mdlogger_logpath_cnf.path, rsp, strlen(rsp));				
+		else
+			cnf.result.mdlogger_logpath_cnf.path[0] = 0; 			
+
+		META_LOG("[Meta][TARGETLOG CTRL] modem EE log path = (%s)", cnf.result.mdlogger_logpath_cnf.path);	
+		return 1;
+	}
+
+	return 0;
+}
+
+unsigned int FtModTargetloggerCtrl::QueryMBLogPath(FT_TARGETLOG_CTRL_CNF &cnf)
+{
+	char rsp[256] = {0};
+	MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MOBILELOG, MBLOG_SOCKET_NAME);
+	if(pSocket != NULL)
+	{
+		pSocket->send_msg(MBLOG_QUERY_NORMALLOG_PATH, false);
+		pSocket->recv_rsp(rsp);
+
+		if(rsp[0] != 0)
+			strncpy((char*)cnf.result.mobilelog_logpath_cnf.path, rsp, strlen(rsp));				
+		else
+			cnf.result.mobilelog_logpath_cnf.path[0] = 0; 			
+		
+		META_LOG("[Meta][TARGETLOG CTRL] mobile log path = (%s)", cnf.result.mobilelog_logpath_cnf.path);	
+		return 1;
+	}
+
+	return 0;
+}
+unsigned int FtModTargetloggerCtrl::SwitchMobilelogMode(FT_TARGETLOG_CTRL_REQ *req)
+{
+	char msg[32] = {0};
+//	char rsp[256] = {0};
+	int mode   = req->cmd.mobilelog_ctrl_req.mode;
+	int action = req->cmd.mobilelog_ctrl_req.action;
+	META_LOG("[Meta][TARGETLOG CTRL] mode = %d, action = %d", mode, action);
+
+	if(action)
+		sprintf(msg, MBLOG_START);
+	else
+		sprintf(msg, MBLOG_STOP);
+
+	MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MOBILELOG, MBLOG_SOCKET_NAME);
+	if(pSocket != NULL)
+	{
+		pSocket->send_msg(msg, true);
+		return 1;
+	}
+	
+	return 0;			
+}
+
+unsigned int FtModTargetloggerCtrl::TargetLogPulling(FT_TARGETLOG_CTRL_REQ *req)
+{
+	char service[32] = {0};
+	char msg[32]     = {0};
+//	char rsp[256]    = {0};
+	int socket_type  = -1;
+	
+	int type   = req->cmd.targetlog_pull_req.type;
+	int action = req->cmd.targetlog_pull_req.action;
+	META_LOG("[Meta][TARGETLOG CTRL] type = %d, action = %d", type, action);
+
+	switch(type)
+	{
+		case 0:
+			{
+				socket_type = SOCKET_MDLOGGER;
+				strncpy(service, MDLOG_SOCKET_NAME, strlen(MDLOG_SOCKET_NAME));
+		        if(action)
+			        strncpy(msg, MDLOG_PULL_START, strlen(MDLOG_PULL_START));
+		        else
+			        strncpy(msg, MDLOG_PULL_STOP, strlen(MDLOG_PULL_STOP));
+			}
+			break;
+		case 1:
+			{
+				socket_type = SOCKET_MOBILELOG;
+				strncpy(service, MBLOG_SOCKET_NAME, strlen(MBLOG_SOCKET_NAME));
+				if(action)
+					strncpy(msg, MBLOG_PULL_START, strlen(MBLOG_PULL_START));
+				else
+					strncpy(msg, MBLOG_PULL_STOP, strlen(MBLOG_PULL_STOP));
+			}
+			break;
+		case 2:
+			{
+				socket_type = SOCKET_CONNSYSLOG;
+				strncpy(service,CONNSYSLOG_SOCKET_NAME, strlen(CONNSYSLOG_SOCKET_NAME));
+				if(action)
+					strncpy(msg, CONNLOG_PULL_START, strlen(CONNLOG_PULL_START));
+				else
+					strncpy(msg, CONNLOG_PULL_STOP, strlen(CONNLOG_PULL_STOP));
+			}
+			break;
+		case 3:
+			{
+				socket_type = SOCKET_MDLOGGER;
+				strncpy(service, MDLOG_SOCKET_NAME, strlen(MDLOG_SOCKET_NAME));
+		        if(action)
+			        strncpy(msg, MDDB_PULL_START, strlen(MDDB_PULL_START));
+			}
+			break;
+		case 4:
+			{
+				socket_type = SOCKET_GPSLOGGER;
+				strncpy(service, GPSLOG_SOCKET_NAME, strlen(GPSLOG_SOCKET_NAME)+1);
+		        if(action)
+			        strncpy(msg, GPSLOG_PULL_START, strlen(GPSLOG_PULL_START)+1);
+			}
+			break;
+		default:
+			return 0;
+	}
+
+	MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(socket_type, service);
+	if(pSocket != NULL)
+	{
+		pSocket->setLogPullingStatus(socket_type, 0);
+		pSocket->send_msg(msg, true);
+		return 1;
+	}
+
+	return 0;
+	
+}
+
+unsigned int FtModTargetloggerCtrl::GetTargetLogPullingStatus(FT_TARGETLOG_CTRL_REQ *req, FT_TARGETLOG_CTRL_CNF &cnf)
+{
+//	unsigned int status = 0;
+	unsigned int ret    = 0;
+	char rsp[32]     = {0};
+//	unsigned int socket_type = (unsigned int)SOCKET_END;
+	unsigned int type = req->cmd.targetlog_pulling_status_req.type;
+	MLogSocket *pSocket = NULL;
+		
+	META_LOG("[Meta][TARGETLOG CTRL] type = %d", type);
+
+	switch(type)
+	{
+		case 0:
+			{
+				pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+				if(pSocket != NULL)
+				{
+					cnf.result.targetlog_pulling_status_cnf.status = pSocket->getLogPullingStatus(type);
+					META_LOG("[Meta][GetTargetLogPullingStatus] status = %d", cnf.result.targetlog_pulling_status_cnf.status);
+					ret = 1;
+				}
+			}
+			break;
+		case 1:
+			{
+				pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MOBILELOG, MBLOG_SOCKET_NAME);
+				if(pSocket != NULL)
+				{
+					cnf.result.targetlog_pulling_status_cnf.status = pSocket->getLogPullingStatus(type);
+					META_LOG("[Meta][GetTargetLogPullingStatus] status = %d", cnf.result.targetlog_pulling_status_cnf.status);
+					ret = 1;
+				}
+			}
+			break;
+		case 2:
+			{
+				pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+				if(pSocket != NULL)
+				{
+					pSocket->send_msg(MDLOG_EE_DONE_STATUS, false);
+					pSocket->recv_rsp(rsp);
+					cnf.result.targetlog_pulling_status_cnf.status = atoi(rsp);
+					META_LOG("[Meta][GetTargetLogPullingStatus] status = %d", cnf.result.targetlog_pulling_status_cnf.status);
+					ret = 1;
+				}
+			}
+			break;
+		case 3:
+			{
+				pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_CONNSYSLOG, CONNSYSLOG_SOCKET_NAME);
+				if(pSocket != NULL)
+				{
+					cnf.result.targetlog_pulling_status_cnf.status = pSocket->getLogPullingStatus(type);
+					META_LOG("[Meta][GetTargetLogPullingStatus] status = %d", cnf.result.targetlog_pulling_status_cnf.status);
+					ret = 1;
+				}
+			}
+			break;
+		case 4:
+			{
+				pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+				if(pSocket != NULL)
+				{
+					cnf.result.targetlog_pulling_status_cnf.status = pSocket->getLogPullingStatus(type);
+					META_LOG("[Meta][GetTargetLogPullingStatus] status = %d", cnf.result.targetlog_pulling_status_cnf.status);
+					ret = 1;
+				}
+			}
+            		break;
+		case 5:
+			{
+				pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_GPSLOGGER, GPSLOG_SOCKET_NAME);
+				if(pSocket != NULL)
+				{
+					cnf.result.targetlog_pulling_status_cnf.status = pSocket->getLogPullingStatus(type);
+					META_LOG("[Meta][GetTargetLogPullingStatus] status = %d", cnf.result.targetlog_pulling_status_cnf.status);
+					ret = 1;
+				}
+			}
+			break;
+		default:
+			break;
+	}
+	
+	return ret;
+	
+}
+
+unsigned int FtModTargetloggerCtrl::GetLogPropValue(char *key)
+{
+#ifdef IS_SUPPORT_SP
+	char val[128]={0};
+    property_get(key, val, "0");
+
+	return atoi(val);
+#else 
+	return 0;
+#endif
+
+}
+
+unsigned int FtModTargetloggerCtrl::SetModemLogFilter(FT_TARGETLOG_CTRL_REQ *req)
+{
+	char msg[32] = {0};
+//	char rsp[32]     = {0};
+	META_LOG("[Meta][TARGETLOG CTRL] Set modem log filter");
+	
+	sprintf(msg, MDLOG_SET_FILTER, req->cmd.mdlogger_setfilter_req.type);
+
+	MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+	if(pSocket != NULL)
+	{
+		pSocket->send_msg(msg, true);
+		//pSocket->recv_rsp(rsp);
+		return 1;
+	}
+
+	return 0;	
+}
+
+void* FtModTargetloggerCtrl::GetLoggerSocket(unsigned int type, const char * service)
+{
+	MSocket *pSocket = getSocket(type);
+	if(pSocket == NULL)
+	{
+		pSocket = createSocket(type);
+		if(pSocket != NULL)
+		{
+			int bInit = pSocket->initClient(service, 0);
+			if(bInit == 0)
+			{
+				delSocket(type);
+				return NULL;
+			}
+		}
+		else
+			return NULL;
+	}
+
+	return (void*)pSocket;
+}
+
+unsigned int FtModTargetloggerCtrl::SwitchConnsyslogMode(FT_TARGETLOG_CTRL_REQ *req)
+{
+	char msg[32] = {0};
+//	char rsp[256] = {0};
+	int mode   = req->cmd.mobilelog_ctrl_req.mode;
+	int action = req->cmd.mobilelog_ctrl_req.action;
+	META_LOG("[Meta][TARGETLOG CTRL] mode = %d, action = %d", mode, action);
+
+	if(action)
+		sprintf(msg, CONNLOG_START);
+	else
+		sprintf(msg, CONNLOG_STOP);
+
+	MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_CONNSYSLOG, CONNSYSLOG_SOCKET_NAME);
+	if(pSocket != NULL)
+	{
+		pSocket->send_msg(msg, true);
+		return 1;
+	}
+	
+	return 0;			
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModFileOperation::FtModFileOperation(void)
+	:CmdTarget(FT_FILE_OPERATION_REQ_ID)
+{
+	m_nFileCount = 0;
+}
+
+FtModFileOperation::~FtModFileOperation(void)
+{    
+	ClearFileInfoList();
+}
+
+unsigned int FtModFileOperation::GetFileLen(char *pFilePath)
+{
+    struct stat st;
+	if(stat((const char*)pFilePath, &st) < 0)
+	{
+	    META_LOG("[Meta][FT] GetFileLen pFilePath(%s) fail, errno=%d",pFilePath,errno);
+	    return 0;
+	}
+	else
+	{
+	    return (unsigned int)st.st_size;
+	}
+}
+
+void FtModFileOperation::ClearFileInfoList(void)
+{
+    mlist<FT_FILE_INFO*>::iterator it1 = m_fileInfoList.begin();	
+	while (it1 != m_fileInfoList.end())
+	{
+		delete (*it1);
+		++ it1;
+	}
+	m_fileInfoList.clear();
+}
+
+
+int FtModFileOperation::ListPath(unsigned char *pPath,unsigned char *pFileNameSubStr) 
+{
+	if(pPath == NULL)
+	{
+	    META_LOG("[Meta][FT] ListPath path is NULL");
+		return 1;
+	}
+
+	if(pFileNameSubStr == NULL || pFileNameSubStr[0]  == '\0')
+	{
+	    META_LOG("[Meta][FT] ListPath file name substr is NULL or 0");
+		return 1;
+	}
+
+	struct stat s;
+	if(stat((const char*)pPath, &s) < 0)
+	{
+	    META_LOG("[Meta][FT] ListPath call stat fail, errno=%d",errno);
+		return 1;
+	}
+
+	if(!S_ISDIR(s.st_mode))
+	{
+	    META_LOG("[Meta][FT] ListPath path(%s) is not a folder name",pPath);
+		return 1;
+	}
+
+    char currfile[1024] = {0};
+    DIR *dir = NULL;
+    struct dirent *ptr = NULL;
+    dir = opendir((const char*)pPath);
+	if(dir == NULL)
+    {
+        META_LOG("[Meta][FT] ListPath opendir(%s) fail, errno=%d",pPath,errno);
+        return 1;
+    }
+    
+    m_nFileCount = 0;
+	ClearFileInfoList();
+    while((ptr = readdir(dir)) != NULL)
+    {
+        if(strcmp(ptr->d_name,".") == 0
+          || strcmp(ptr->d_name,"..") ==0)
+            continue;
+		if(strlen(ptr->d_name) > 256)
+		{
+		    META_LOG("[Meta][FT] ListPath file name(%s) length is too large,just skip this file!!!!",ptr->d_name);
+		    continue;
+		}
+
+        if(strcmp((const char*)pFileNameSubStr,"*") == 0
+			|| strstr(ptr->d_name,(const char*)pFileNameSubStr) != NULL)
+        {
+		     FT_FILE_INFO *pFileInfo = new FT_FILE_INFO;
+	         if(pFileInfo==NULL)
+	         {		    
+		         META_LOG("[Meta][FT] ListPath new FT_FILE_INFO fail,errno=%d",errno);
+			     closedir(dir);
+		         return 1;
+	         }
+		     memset(pFileInfo,0,sizeof(FT_FILE_INFO));		
+             memcpy(pFileInfo->file_name, ptr->d_name, strlen(ptr->d_name));
+			 if(pPath[strlen((const char*)pPath)-1] != '/')
+			 {
+			     sprintf(currfile,"%s/%s",(char*)pPath,ptr->d_name);
+			 }
+			 else
+		     {
+		         sprintf(currfile,"%s%s",(char*)pPath,ptr->d_name);
+			 }
+		
+             if(ptr->d_type == DT_REG)  //file
+             {
+                 pFileInfo->file_type = FT_FILE_TYPE_FILE;
+			     pFileInfo->file_size = GetFileLen(currfile);
+             }
+             else if(ptr->d_type == DT_DIR) //directory
+             {
+                 pFileInfo->file_type = FT_FILE_TYPE_FOLDER;
+			     pFileInfo->file_size = 0;			
+             }
+			 else
+			 {
+			     pFileInfo->file_type = FT_FILE_TYPE_INVALID;
+			     pFileInfo->file_size = 0;
+			 }
+		     m_nFileCount++;
+		     META_LOG("[Meta][FT] ListPath find one file or folder,file_name=%s,file_type:%d,file_size:%d,m_nFileCount:%d",pFileInfo->file_name,pFileInfo->file_type,pFileInfo->file_size,m_nFileCount);
+		     m_fileInfoList.push_back(pFileInfo);
+        }
+
+    }
+
+	closedir(dir);
+	return 0;
+}
+
+FT_FILE_INFO* FtModFileOperation::GetFileInfo(unsigned int id)
+{
+    mlist<FT_FILE_INFO*>::iterator it = m_fileInfoList.begin();
+	unsigned int i = 0;
+
+	while (it != m_fileInfoList.end())
+	{
+		
+		if (i == id)
+		{
+			return (*it);
+		}
+		i++;
+		++ it;
+	}
+	return NULL;
+}
+
+
+
+int FtModFileOperation::SaveSendData(FILE_OPERATION_SENDFILE_REQ *req, char *peer_buff, unsigned short peer_len)
+{
+    int nRet = 1;
+    if(req == NULL || peer_buff == NULL)
+    {
+        return nRet;
+    }
+    if(req->dest_file_name[0] == '\0')
+    {
+      	return nRet;
+    }
+	  
+    int SendFileFd = -1;
+    unsigned int fileLen;
+	bool bCreate = false;
+	META_LOG("[Meta][FT] SaveSendData receive block stage %x, file size %d!",req->stream_block.stage,req->stream_block.file_size);
+	if(req->stream_block.stage & BLK_CREATE)
+	{
+		SendFileFd = open((const char*)req->dest_file_name, O_RDWR | O_TRUNC | O_CREAT, 0777);
+		bCreate = true;
+	}
+	else
+	{
+		SendFileFd = open((const char*)req->dest_file_name, O_RDWR | O_APPEND);
+	}
+	
+	if(SendFileFd >= 0)
+	{
+		if(bCreate)
+		{
+			if(chown((const char*)req->dest_file_name,2000,1000) == -1)
+		    {
+			    META_LOG("[Meta][FT] SaveSendData, failed to chown");
+				close(SendFileFd);
+			    return nRet;
+				
+		    }
+		}
+		
+		META_LOG("[Meta][FT] SaveSendData create or open file OK!");
+		unsigned short sWriten = 0;
+		sWriten = write(SendFileFd, peer_buff, peer_len);
+
+		if(sWriten)
+		{
+			META_LOG("[Meta][FT] SaveSendData  write %d data total data %d!",sWriten,peer_len);
+			if(req->stream_block.stage & BLK_EOF)
+			{
+				fileLen = getFileSize(SendFileFd);
+				if(req->stream_block.file_size == fileLen)
+				{
+					META_LOG("[Meta][FT] SaveSendData write file BLK_EOF success! ");
+					close(SendFileFd);
+					SendFileFd = -1;
+					nRet = 0;
+				}
+				else
+				{
+					META_LOG("[Meta][FT] SaveSendData file size(%d) error! ",req->stream_block.file_size);
+				}
+			}
+			else
+			{
+			    META_LOG("[Meta][FT] SaveSendData write file BLK_WRITE success! ");
+			    nRet = 0;
+			}
+		}
+		else
+		{
+			META_LOG("[Meta][FT] SaveSendData write file failed!");
+		}
+	
+		if(SendFileFd != -1)
+			close(SendFileFd);
+	
+	}
+	else
+	{
+		META_LOG("[Meta][FT] SaveSendData create or open file failed!");
+	}
+	return nRet;
+	
+}
+
+#define RECEIVE_PEER_MAX_LEN 20*1024
+
+int FtModFileOperation::SetReceiveData(FILE_OPERATION_RECEIVEFILE_REQ *req, FT_FILE_OPERATION_CNF* pft_cnf)
+{
+    int nRet = 1;
+	if(req == NULL || pft_cnf == NULL)
+	{
+		return nRet;
+	}
+	if(req->source_file_name[0]  == '\0')
+	{
+		return nRet;
+	}
+
+    unsigned int nReceiveDataSize = 0;
+    int ReceiveFileFd = -1;
+	int nPeerBuffSize = 0;
+    char* pPeerBuf = NULL;
+	
+	ReceiveFileFd = open((const char*)req->source_file_name, O_RDONLY);
+ 
+  
+	if(ReceiveFileFd >= 0)
+	{
+            unsigned int nFileLen = getFileSize(ReceiveFileFd);
+            META_LOG("[Meta][FT] SetReceiveData open file %s succeed, fileSize %d ! ",req->source_file_name,nFileLen);
+
+		pPeerBuf = (char*)malloc(RECEIVE_PEER_MAX_LEN);
+		memset(pPeerBuf, 0, RECEIVE_PEER_MAX_LEN);
+
+		pft_cnf->result.receivefile_cnf.stream_block.stage = BLK_CREATE;
+
+		while(!(pft_cnf->result.receivefile_cnf.stream_block.stage & BLK_EOF))
+		{
+			nPeerBuffSize = read(ReceiveFileFd, pPeerBuf, RECEIVE_PEER_MAX_LEN);
+
+                        META_LOG("[Meta][FT] SetReceiveData nPeerBuffSize:%d,nReceiveDataSize:%d,",nPeerBuffSize,nReceiveDataSize);
+			if(nPeerBuffSize != -1)
+			{
+				pft_cnf->status = META_SUCCESS;
+				pft_cnf->result.receivefile_cnf.receive_result = 0;
+				if(nPeerBuffSize == 0)
+				{
+					pft_cnf->result.receivefile_cnf.stream_block.stage |= BLK_EOF;
+					pft_cnf->result.receivefile_cnf.stream_block.file_size = nReceiveDataSize;
+					WriteDataToPC(pft_cnf, sizeof(FT_FILE_OPERATION_CNF),NULL, 0);
+					META_LOG("[Meta][FT] SetReceiveData file end, set BLK_EOF! ");
+					nRet = 0;
+					break;
+				}
+				else
+				{
+					pft_cnf->result.receivefile_cnf.stream_block.stage |= BLK_WRITE;
+					pft_cnf->result.receivefile_cnf.stream_block.file_size = nReceiveDataSize;
+					META_LOG("[Meta][FT] SetReceiveData File set %d data ! ",nPeerBuffSize);
+					WriteDataToPC(pft_cnf, sizeof(FT_FILE_OPERATION_CNF),pPeerBuf, nPeerBuffSize);
+					memset(pPeerBuf,0,RECEIVE_PEER_MAX_LEN);
+					pft_cnf->result.receivefile_cnf.stream_block.stage &= ~BLK_CREATE;
+					META_LOG("[Meta][FT] SetReceiveData set BLK_WRITE! ");
+				}
+				nReceiveDataSize = nReceiveDataSize + nPeerBuffSize;
+
+			}
+			else
+			{
+				pft_cnf->result.receivefile_cnf.stream_block.stage |= BLK_EOF;
+				META_LOG("[Meta][FT] SetReceiveData read file fail, set BLK_EOF! ");
+			}
+
+		}
+
+		free(pPeerBuf);
+		close(ReceiveFileFd);
+
+	}
+	else
+	{
+	    META_LOG("[Meta][FT] SetReceiveData open File %s failed, errno=%d",req->source_file_name,errno);
+	}
+
+	return nRet;
+}
+void FtModFileOperation::exec(Frame *pFrm)
+{
+	META_LOG("[Meta][FILE OPERATION] FtModFileOperation");	
+
+	FT_FILE_OPERATION_CNF  ft_cnf;
+
+	memset(&ft_cnf, 0, sizeof(FT_FILE_OPERATION_CNF));
+	ft_cnf.status = META_FAILED;
+
+	
+	FT_FILE_OPERATION_REQ *req = (FT_FILE_OPERATION_REQ *)pFrm->localBuf();
+
+	ft_cnf.header.id = req->header.id +1;
+    ft_cnf.header.token = req->header.token;
+    ft_cnf.type= req->type;
+
+	META_LOG("[Meta][FILE OPERATION] FtModFileOperation req->type = %d", req->type);
+	switch(req->type)
+	{
+		case FT_FILE_OP_PARSE:
+			{
+				if(ListPath(req->cmd.parse_req.path_name,req->cmd.parse_req.filename_substr) == 0)
+				{
+				    ft_cnf.result.parse_cnf.file_count = m_nFileCount;
+				    ft_cnf.status = META_SUCCESS;
+				    META_LOG("[Meta][FILE OPERATION] FtModFileOperation parse folder success!");
+				}
+				else
+				{
+				    META_LOG("[Meta][FILE OPERATION] FtModFileOperation parse folder fail!");
+				}
+			}
+			break;
+		case FT_FILE_OP_GETFILEINFO:
+			{
+				if(req->cmd.getfileinfo_req.index > m_nFileCount)
+				{
+				    META_LOG("[Meta][FILE OPERATION] FtModFileOperation invalid file index!");
+				}
+				else
+				{
+				    FT_FILE_INFO* pFileInfo = GetFileInfo(req->cmd.getfileinfo_req.index);
+				    if(pFileInfo != NULL)
+				    {				  
+				        memcpy(&(ft_cnf.result.getfileinfo_cnf.file_info),pFileInfo,sizeof(FT_FILE_INFO));
+						META_LOG("[Meta][FILE OPERATION] file_name=%s,file_type:%d,file_size:%d",pFileInfo->file_name,pFileInfo->file_type,pFileInfo->file_size);
+				        ft_cnf.status = META_SUCCESS;
+				    }
+				}
+			}
+			break;
+		case FT_FILE_OP_SENDFILE:
+			{
+				if(SaveSendData(&(req->cmd.sendfile_req),(char *)pFrm->peerBuf(), pFrm->peerLen()) == 0)
+				{
+				    ft_cnf.result.sendfile_cnf.send_result = 0;
+				    ft_cnf.status = META_SUCCESS;					   
+				}
+			}
+			break;
+		case FT_FILE_OP_RECEIVEFILE:
+			{
+				if(SetReceiveData(&(req->cmd.receivefile_req),&ft_cnf) == 0)
+		        {
+			        META_LOG("[Meta][FILE OPERATION] FtModFileOperation success to set receive data!");
+					return;
+		        }
+	            else
+	            {
+		            META_LOG("[Meta][FILE OPERATION] FtModFileOperation Failed to set receive data!");
+	            }
+			}
+			break;
+		default:
+			break;
+	}
+
+	WriteDataToPC(&ft_cnf, sizeof(FT_FILE_OPERATION_CNF),NULL, 0);
+}
+
+#ifdef FT_RAT_FEATURE
+
+FtModRAT::FtModRAT(void)
+	:CmdTarget(FT_RATCONFIG_REQ_ID)
+{
+}
+
+FtModRAT::~FtModRAT(void)
+{
+}
+
+int FtModRAT::init(Frame*pFrm)
+{
+	RAT_CNF ft_cnf;
+    static int bInitFlag_RAT = false;
+
+    memset(&ft_cnf, 0, sizeof(RAT_CNF));
+	RAT_REQ *req = (RAT_REQ *)pFrm->localBuf();
+
+    if (FALSE == bInitFlag_RAT)
+    {
+        // initial the bat module when it is called first time
+        if (!META_RAT_init())
+        {
+            ft_cnf.header.id = req->header.id +1;
+            ft_cnf.header.token = req->header.token;
+            ft_cnf.status = META_FAILED;
+
+            META_LOG("[Meta][FT] FT_RAT_OP META_RAT_init Fail ");
+            WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+
+			return false;
+        }
+        bInitFlag_RAT = true;
+    }
+
+	return true;
+}
+
+
+void FtModRAT::exec(Frame *pFrm)
+{
+	META_LOG("[Meta][FT] FT_RAT_OP FtModRAT ");
+
+	CmdTarget::exec(pFrm);
+	if(getInitState())
+		META_RAT_OP((RAT_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+}
+
+#endif
+
+
+#ifdef FT_MSIM_FEATURE
+FtModMSIM::FtModMSIM(void)
+	:CmdTarget(FT_MSIM_REQ_ID)
+{
+}
+
+FtModMSIM::~FtModMSIM(void)
+{
+}
+
+int FtModMSIM::init(Frame*pFrm)
+{
+	MSIM_CNF ft_cnf;
+    static int bInitFlag_MSIM = false;
+
+    memset(&ft_cnf, 0, sizeof(MSIM_CNF));
+	MSIM_REQ *req = (MSIM_REQ *)pFrm->localBuf();
+
+    if (FALSE == bInitFlag_MSIM)
+    {
+        // initial the bat module when it is called first time
+        if (!META_MSIM_init())
+        {
+            ft_cnf.header.id = req->header.id +1;
+            ft_cnf.header.token = req->header.token;
+            ft_cnf.status = META_FAILED;
+
+            META_LOG("[Meta][FT] FT_MSIM_OP META_MSIM_init Fail ");
+            WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+
+			return false;
+        }
+        bInitFlag_MSIM = true;
+    }
+
+	return true;
+}
+
+
+void FtModMSIM::exec(Frame *pFrm)
+{
+	META_LOG("[Meta][FT] FT_MSIM_OP FtModMSIM");
+
+	CmdTarget::exec(pFrm);
+	if(getInitState())
+		META_MSIM_OP((MSIM_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+BOOL Meta_Mobile_Log()
+{        
+    int fd = 0;
+	int len = 0;
+	BOOL ret = FALSE;
+	META_LOG("[Meta][FT] Meta_Mobile_Log ");
+
+    //support end load and user load,send stop command to mobilelog 
+
+//	fd = socket_local_client("mobilelogd", ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); to modify
+	if (fd < 0) 
+	{
+		META_LOG("[Meta][FT] socket fd <0 ");
+		return FALSE;
+	}
+	META_LOG("[Meta][FT] socket ok\n");
+	if((len = write(fd, "stop", sizeof("stop"))) < 0)
+	{
+		META_LOG("[Meta][FT] socket write error!");
+		ret = FALSE;
+	}
+	else
+	{
+		META_LOG("[Meta][FT] write %d Bytes.", len);
+		ret = TRUE;
+	}
+	close(fd);
+	sleep(4);	      
+	return ret;
+	
+}
+
+void FT_UtilCheckIfFuncExist(FT_UTILITY_COMMAND_REQ  *req, FT_UTILITY_COMMAND_CNF  *cnf)
+{
+
+    unsigned int	query_ft_msg_id = req->cmd.CheckIfFuncExist.query_ft_msg_id;
+    unsigned int	query_op_code = req->cmd.CheckIfFuncExist.query_op_code;
+    META_LOG("[Meta][FT] FT_UtilCheckIfFuncExist META Test ");
+    cnf->status = FT_CNF_FAIL;
+
+	META_LOG("[Meta][FT] request id = %d op = %d",query_ft_msg_id,query_op_code);
+
+	
+    switch (query_ft_msg_id)
+    {
+
+#ifdef FT_FM_FEATURE 
+    	case FT_FM_REQ_ID:
+			if(query_op_code == 0)//FT_FM_OP_READ_CHIP_ID
+			{
+				cnf->status = FT_CNF_OK; 
+			}        	
+        	break;
+#endif
+
+#ifdef FT_CRYPTFS_FEATURE
+		case FT_CRYPTFS_REQ_ID:
+			if(query_op_code == 0)//FT_CRYPTFS_OP_QUERYSUPPORT
+			{
+				cnf->status = FT_CNF_OK;
+			}
+			else if(query_op_code == 1)//FT_CRYPTFS_OP_VERITIFY
+			{
+				cnf->status = FT_CNF_OK;
+			}
+        	break;
+#endif
+			
+		case FT_MODEM_REQ_ID:
+			if(query_op_code == FT_MODEM_OP_QUERY_INFO )
+			{
+				cnf->status = FT_CNF_OK;
+			}
+			else if(query_op_code == FT_MODEM_OP_CAPABILITY_LIST)
+			{
+				cnf->status = FT_CNF_OK;
+			}/*
+			else if(query_op_code == FT_MODEM_OP_SET_MODEMTYPE)
+			{
+				cnf->status = FT_CNF_OK;
+			}
+			else if(query_op_code == FT_MODEM_OP_GET_CURENTMODEMTYPE)
+			{
+				cnf->status = FT_CNF_OK;
+			}
+			else if(query_op_code == FT_MODEM_OP_QUERY_MDIMGTYPE )
+			{
+				cnf->status = FT_CNF_OK;
+			}*/
+			else if(query_op_code == FT_MODEM_OP_QUERY_MDDBPATH)
+			{
+			    cnf->status = FT_CNF_OK;
+			}
+#ifdef MTK_META_COMPRESS_SUPPORT
+			else if(query_op_code == FT_MODEM_OP_SUPPORT_COMPRESS)
+			{
+				cnf->status = FT_CNF_OK;
+			}
+#endif
+			break;
+
+		case FT_L4AUD_REQ_ID:
+			if(query_op_code == 59)//FT_L4AUD_OP_SPEAKER_CALIBRATION_SUPPORT
+			{
+#ifdef MTK_SPEAKER_MONITOR_SUPPORT
+				cnf->status = FT_CNF_OK;
+				META_LOG("[Meta][FT] MTK_SPEAKER_MONITOR_SUPPORT = yes");
+#else
+				cnf->status = FT_CNF_FAIL;
+				META_LOG("[Meta][FT] MTK_SPEAKER_MONITOR_SUPPORT = no");
+#endif
+			}
+
+			break;
+		case FT_SIM_DETECT_REQ_ID:
+			if(query_op_code == FT_SIM_DETECT_OP_EXTMOD)
+			{
+				cnf->status = FT_CNF_OK;
+				META_LOG("[Meta][FT] FT_SIM_DETECT_OP_EXTMOD = yes");
+			}
+			break;
+		case FT_TARGETLOG_CTRL_REQ_ID:
+			if((query_op_code < FT_CONNSYSLOG_OP_SWITCH_TYPE) || (query_op_code == FT_GPSLOGGER_OP_SWITCH_TYPE))
+			{
+				if(getDataChannelType() == 1) //93 modem ccb channel
+				{
+					cnf->status = FT_CNF_OK;
+					META_LOG("[Meta][FT] FT_MDLOGGER_OP = yes");
+				}
+				else
+				{
+					META_LOG("[Meta][FT] FT_MDLOGGER_OP = no");
+				}
+			}
+			break;			
+		case FT_TARGETCLOCK_REQ_ID:
+			if(query_op_code <= FT_CLOCK_GET)
+			{
+				cnf->status = FT_CNF_OK;
+				META_LOG("[Meta][FT] FT_TARGETCLOCK_OP = yes");
+			}
+			break;					
+		case FT_DISCONNECT_REQ_ID:
+			if(query_op_code < FT_CTRL_DONOTHING)
+			{
+				cnf->status = FT_CNF_OK;
+				META_LOG("[Meta][FT] FT_DISCONN_TARGET_OP = yes");
+			}
+			break;				
+		case FT_UTILITY_COMMAND_REQ_ID:
+			if(query_op_code == FT_UTILCMD_QUERY_WCNDRIVER_READY)
+			{
+			    cnf->status = FT_CNF_OK;
+				META_LOG("[Meta][FT] FT_UTILCMD_QUERY_WCNDRIVER_READY = yes");
+			}
+			else if(query_op_code == FT_UTILCMD_SWITCH_WIFI_USB)
+			{
+			    cnf->status = FT_CNF_OK;
+				META_LOG("[Meta][FT] FT_UTILCMD_SWITCH_WIFI_USB = yes");
+			}
+			else if(query_op_code == FT_UTILCMD_PRINTF_CUSLOG)
+			{
+			    cnf->status = FT_CNF_OK;
+				META_LOG("[Meta][FT] FT_UTILCMD_PRINTF_CUSLOG = yes");
+			}
+			break;
+		case FT_FILE_OPERATION_REQ_ID:
+			if(query_op_code == FT_FILE_OP_PARSE )
+			{
+				cnf->status = FT_CNF_OK;
+			}
+			else if(query_op_code == FT_FILE_OP_GETFILEINFO)
+			{
+			    cnf->status = FT_CNF_OK;
+			}
+			else if(query_op_code == FT_FILE_OP_SENDFILE)
+			{
+			    cnf->status = FT_CNF_OK;
+			}
+			else if(query_op_code == FT_FILE_OP_RECEIVEFILE)
+			{
+				cnf->status = FT_CNF_OK;
+			}
+            break;			
+		case FT_RATCONFIG_REQ_ID:
+#ifdef FT_RAT_FEATURE
+			if(query_op_code == RAT_OP_READ_OPTR )
+			{
+				cnf->status = FT_CNF_OK;
+			}
+			else if(query_op_code == RAT_OP_READ_OPTRSEG)
+			{
+			    cnf->status = FT_CNF_OK;
+			}
+			else if(query_op_code == RAT_OP_GET_CURRENT_RAT)
+			{
+			    cnf->status = FT_CNF_OK;
+			}
+			else if(query_op_code == RAT_OP_SET_NEW_RAT)
+			{
+			    cnf->status = FT_CNF_OK;
+			}
+#else
+            cnf->status = FT_CNF_FAIL;
+#endif
+            break;
+		case FT_MSIM_REQ_ID:
+#ifdef FT_MSIM_FEATURE
+            if(query_op_code == MSIM_OP_GET_MSIM )
+            {
+				cnf->status = FT_CNF_OK;
+            }
+            else if(query_op_code == MSIM_OP_SET_MSIM)
+            {
+				cnf->status = FT_CNF_OK;
+            }
+#else
+            cnf->status = FT_CNF_FAIL;
+#endif
+            break;
+        case FT_APDB_REQ_ID:
+#ifdef FT_NVRAM_FEATURE
+            if(query_op_code == FT_APDB_OP_QUERYPATH )
+            {
+				cnf->status = FT_CNF_OK;
+            }
+#else
+            cnf->status = FT_CNF_FAIL;
+#endif
+			break;
+#if ((defined FT_EMMC_FEATURE) || (defined FT_NAND_FEATURE))
+		case FT_EMMC_REQ_ID:
+			if(query_op_code == 3/*FT_EMMC_OP_UNMOUNT*/ )
+			{
+				cnf->status = FT_CNF_OK;
+            }
+			break;
+#endif
+		case FT_POWER_OFF_REQ_ID:
+			if(query_op_code == FT_SHUTDOWN_OP_WAITUSB )
+			{
+				META_LOG("[Meta][FT] FT_SHUTDOWN_OP_WAITUSB = yes");
+				cnf->status = FT_CNF_OK;
+            }
+			break;
+    	default:
+			META_LOG("[Meta][FT] NOT FOUND THE PRIMITIVE_ID");
+        	cnf->status = FT_CNF_FAIL;		
+        	break;
+    }
+    
+
+    // assign return structure
+    cnf->result.CheckIfFuncExist.query_ft_msg_id = query_ft_msg_id;
+    cnf->result.CheckIfFuncExist.query_op_code = query_op_code;
+}
+
+FtModUtility::FtModUtility(void)
+	:CmdTarget(FT_UTILITY_COMMAND_REQ_ID)
+{
+}
+
+FtModUtility::~FtModUtility(void)
+{
+}
+
+#ifdef FT_NVRAM_FEATURE
+void FtModUtility::covertArray2Vector(unsigned char* in, int len, std::vector<uint8_t>& out) {
+    out.clear();
+    for(int i = 0; i < len; i++) {
+       out.push_back(in[i]);
+    }
+}
+void FtModUtility::covertVector2Array(std::vector<uint8_t> in, char* out) {
+	int size = in.size();
+	for(int i = 0; i < size; i++) {
+		out[i] = in.at(i);
+	}
+}
+#endif
+
+void FtModUtility::exec(Frame *pFrm)
+{
+	META_LOG("[Meta][FT] FT_Peripheral_OP META Test");
+	 
+	CmdTarget::exec(pFrm);  
+
+	FT_UTILITY_COMMAND_CNF UtilityCnf;
+    //PROCESS_INFORMATION cleanBootProcInfo;
+    static META_BOOL bLCDBKInitFlag_Peri = FALSE;
+    static META_BOOL bLCDFtInitFlag_Peri = FALSE;
+    static META_BOOL bVibratorInitFlag_Peri = FALSE;
+	int nNVRAMFlag = 0;
+	unsigned int level = 0;
+	char tempstr[128]={0};
+
+    //cleanBootProcInfo.hProcess = NULL;
+    //cleanBootProcInfo.hThread = NULL;
+
+    memset(&UtilityCnf, 0, sizeof(FT_UTILITY_COMMAND_CNF));
+	FT_UTILITY_COMMAND_REQ *req = (FT_UTILITY_COMMAND_REQ *)pFrm->localBuf();
+	
+    META_LOG("[Meta][FT] FT_Peripheral_OP META Test, type = %d", req->type); 
+
+    UtilityCnf.header.id = req->header.id +1;
+    UtilityCnf.header.token = req->header.token;
+    UtilityCnf.type = req->type;
+    UtilityCnf.status= META_FAILED;
+
+    //do the related test.
+    switch (req->type)
+    {
+    case FT_UTILCMD_CHECK_IF_FUNC_EXIST:		//query the supported modules
+        META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_CHECK_IF_FUNC_EXIST ");
+        FT_UtilCheckIfFuncExist(req, &UtilityCnf);
+        break;
+    //delete since no use.
+    //case FT_UTILCMD_QUERY_LOCAL_TIME:			//query RTC from meta cpu lib
+    //    META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_QUERY_LOCAL_TIME ");
+    //    UtilityCnf.result.m_WatchDogCnf= META_RTCRead_OP(req->cmd.m_WatchDogReq);
+    //    UtilityCnf.status= META_SUCCESS;
+    //    break;
+
+#ifdef FT_LCDBK_FEATURE
+    case FT_UTILCMD_MAIN_SUB_LCD_LIGHT_LEVEL:	//test lcd backlight from meta lcd backlight lig
+        META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_MAIN_SUB_LCD_LIGHT_LEVEL ");
+	    if(bLCDBKInitFlag_Peri==FALSE)
+     	{   		
+			if (!Meta_LCDBK_Init())
+			{
+				META_LOG("[Meta][FT] FT_Peripheral_OP Meta_LCDBK_Init Fail ");
+				goto Per_Exit;
+			}   		
+		    bLCDBKInitFlag_Peri = TRUE;
+    	}        
+        UtilityCnf.result.m_LCDCnf = Meta_LCDBK_OP(req->cmd.m_LCDReq);
+        UtilityCnf.status= META_SUCCESS;
+        break;
+#endif
+
+#ifdef FT_LCD_FEATURE
+	case FT_UTILCMD_LCD_COLOR_TEST:
+        META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_LCD_COLOR_TEST ");
+	    if(bLCDFtInitFlag_Peri==FALSE)
+     	{   					
+			if (!Meta_LCDFt_Init())
+			{
+			    META_LOG("[Meta][FT]] FT_Peripheral_OP Meta_LCDFt_Init Fail ");
+			    goto Per_Exit;
+			}			
+		    bLCDFtInitFlag_Peri = TRUE;
+    	}        
+        UtilityCnf.result.m_LCDColorTestCNF = Meta_LCDFt_OP(req->cmd.m_LCDColorTestReq);
+        UtilityCnf.status= META_SUCCESS;
+        break;
+#endif
+
+#ifdef FT_VIBRATOR_FEATURE
+    case FT_UTILCMD_SIGNAL_INDICATOR_ONOFF:
+        META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SIGNAL_INDICATOR_ONOFF ");
+        UtilityCnf.result.m_NLEDCnf = Meta_Vibrator_OP(req->cmd.m_NLEDReq);
+        UtilityCnf.status= META_SUCCESS;
+        break;
+#endif
+
+		
+#ifdef FT_VIBRATOR_FEATURE
+    case FT_UTILCMD_VIBRATOR_ONOFF:				//test vibrate and indicator from meta nled lib
+        META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_VIBRATOR_ONOFF ");
+	    if(bVibratorInitFlag_Peri==FALSE)
+     	{
+    		if (!Meta_Vibrator_Init())
+        	{
+            	META_LOG("[Meta][FT] FT_Peripheral_OP Meta_Vibrator_Init Fail ");
+            	goto Per_Exit;
+        	}	
+		    bVibratorInitFlag_Peri = TRUE;
+    	}         
+        UtilityCnf.result.m_NLEDCnf = Meta_Vibrator_OP(req->cmd.m_NLEDReq);
+        UtilityCnf.status= META_SUCCESS;
+        break;
+#endif
+
+#ifdef FT_VIBRATOR_FEATURE
+    case FT_UTILCMD_KEYPAD_LED_ONOFF:	
+        META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_KEYPAD_LED_ONOFF ");
+        UtilityCnf.result.m_NLEDCnf = Meta_Vibrator_OP(req->cmd.m_NLEDReq);
+        UtilityCnf.status= META_SUCCESS;
+        break;
+#endif
+
+#ifdef FT_NVRAM_FEATURE
+      case FT_UTILCMD_SET_CLEAN_BOOT_FLAG:
+	        nNVRAMFlag = req->cmd.m_SetCleanBootFlagReq.Notused;
+	        META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SET_CLEAN_BOOT_FLAG, nNVRAMFlag =%d",nNVRAMFlag);
+	        if ((req->cmd.m_SetCleanBootFlagReq.BackupTime)[0] != '\0')
+	        {
+	            META_LOG("[Meta][FT] FT_UTILCMD_SET_CLEAN_BOOT_FLAG, BackupTime =%s",req->cmd.m_SetCleanBootFlagReq.BackupTime);
+                    UtilityCnf.result.m_SetCleanBootFlagCnf.drv_statsu = FileOp_BackupToBinRegion_All_Exx(req->cmd.m_SetCleanBootFlagReq.BackupTime);
+	        }
+	        else
+	        {
+           		 //For NVRAM to record write barcode(1) and IMEI(2) and both barcode and IMEI(3) history
+            	if ( nNVRAMFlag == 1 || nNVRAMFlag == 2 || nNVRAMFlag == 3 )
+	            {
+                UtilityCnf.result.m_SetCleanBootFlagCnf.drv_statsu = FileOp_BackupToBinRegion_All_Ex(nNVRAMFlag);
+	            }
+	            else
+	            {
+                UtilityCnf.result.m_SetCleanBootFlagCnf.drv_statsu = FileOp_BackupToBinRegion_All();
+	        }
+        }
+        UtilityCnf.status=META_SUCCESS;
+        break;
+#endif
+    case FT_UTILCMD_CHECK_IF_LOW_COST_SINGLE_BANK_FLASH:	//query the single flash feature, we now just return.
+        META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_CHECK_IF_LOW_COST_SINGLE_BANK_FLASH ");
+        UtilityCnf.status=META_SUCCESS;
+        break;
+
+    case FT_UTILCMD_SAVE_MOBILE_LOG:                           //save mobile log
+        META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SAVE_MOBILE_LOG ");
+        META_LOG("[Meta][FT] FT_UTILCMD_SAVE_MOBILE_LOG META Test %s,%d,%s",__FILE__,__LINE__,__FUNCTION__);
+        UtilityCnf.result.m_SaveMobileLogCnf.drv_status = Meta_Mobile_Log();
+        UtilityCnf.status = META_SUCCESS;
+		break;
+	case FT_UTILCMD_SET_LOG_LEVEL:	  
+		level = req->cmd.m_SetLogLevelReq.level;
+		META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SET_LOG_LEVEL ");
+		META_LOG("[Meta][FT] FT_UTILCMD_SET_LOG_LEVEL META Test %s,%d,%s,level = %d",__FILE__,__LINE__,__FUNCTION__,level);
+		setLogLevel(level);
+		UtilityCnf.status = META_SUCCESS;
+		break;
+	case FT_UTILCMD_SDIO_AUTO_CALIBRATION:	
+		META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SDIO_AUTO_CALIBRATION ");
+		META_LOG("[Meta][FT] FT_UTILCMD_SDIO_AUTO_CALIBRATION META Test: no more supported");
+		break;
+	case FT_UTILCMD_QUERY_WCNDRIVER_READY:
+		META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_QUERY_WCNDRIVER_READY ");
+#ifdef IS_SUPPORT_SP
+		property_get("vendor.connsys.driver.ready",tempstr,"no");
+		if(strcmp(tempstr,"yes")==0)
+		{
+		    UtilityCnf.result.m_QueryWCNDriverReadyCnf.result = 1; //has ready
+		    META_LOG("[Meta][FT] FT_UTILCMD_QUERY_WCNDRIVER_READY() wcn driver ready");
+		}
+		else
+		{
+		    UtilityCnf.result.m_QueryWCNDriverReadyCnf.result = 0;  //not ready
+		    META_LOG("[Meta][FT] FT_UTILCMD_QUERY_WCNDRIVER_READY() wcn driver not ready");
+		}
+#else
+		UtilityCnf.result.m_QueryWCNDriverReadyCnf.result = 1;
+#endif
+		UtilityCnf.status = META_SUCCESS;
+		break;
+	case FT_UTILCMD_SET_ATM_FLAG:
+		META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SET_ATM_FLAG ");
+
+		META_LOG("[Meta][FT] setNormalModeTestFlag");
+	
+		if(0 == setNormalModeTestFlag(req->cmd.m_SetATMFlagReq.flag))
+		{
+			UtilityCnf.status = META_SUCCESS;
+		}
+		else
+		{
+	    	UtilityCnf.status = META_FAILED;
+		}
+		break;
+	case FT_UTILCMD_SET_PRODUCT_INFO:		
+		{
+			int offset = 0;
+			META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SET_PRODUCT_INFO ");
+		
+			switch(req->cmd.m_SetProductInfo.type)
+			{	
+				case 0: //ATM flag
+					offset = OFFSET_ATM;
+					break;
+				case 1: //meta log flag
+					offset = OFFSET_METALOG;
+					break;
+				default:
+					break;
+			}
+			
+			META_LOG("[Meta][FT] setProductInfo, type = %d, offset = %d", req->cmd.m_SetProductInfo.type, offset);
+			if(0 == setProductInfo(req->cmd.m_SetProductInfo.type, req->cmd.m_SetProductInfo.flag, offset))
+			{
+				UtilityCnf.status = META_SUCCESS;
+			}
+			else
+			{
+	    		UtilityCnf.status = META_FAILED;
+			}
+		}
+		break;
+	case FT_UTILCMD_SWITCH_WIFI_USB:
+		META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SWITCH_WIFI_USB ");
+#ifdef IS_SUPPORT_SP
+		//send response to PC
+		UtilityCnf.result.m_SwitchWiFiUSBCnf.result = 1;
+		UtilityCnf.status = META_SUCCESS;
+		WriteDataToPC(&UtilityCnf, sizeof(FT_UTILITY_COMMAND_CNF),NULL, 0);
+		//destroy related resource
+		destroyVirtualRxThread();
+		//set property and then create resource
+		if(req->cmd.m_SwitchWiFiUSBReq.flag == 0) //wifi to usb
+		{
+			property_set("persist.vendor.meta.connecttype","usb");
+			META_LOG("[Meta][FT] persist.vendor.meta.connecttype = usb");
+			setComType(META_USB_COM);
+		}
+		else if(req->cmd.m_SwitchWiFiUSBReq.flag == 1) //usb to wifi
+		{
+		    property_set("persist.vendor.meta.connecttype","wifi");
+			META_LOG("[Meta][FT] persist.vendor.meta.connecttype = wifi");
+			setComType(META_SOCKET);
+		}
+		else
+		{
+		    META_LOG("[Meta][FT] FT_UTILCMD_SWITCH_WIFI_USB flag = %d is valid",req->cmd.m_SwitchWiFiUSBReq.flag);
+		}
+		createVirtualRxThread();
+#endif
+		return;
+	case FT_UTILCMD_PRINTF_CUSLOG:
+		META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_PRINTF_CUSLOG "); 
+		if(strlen((char*)req->cmd.m_PrintCusLogReq.log) > 0)
+		{
+			META_LOG("[Meta][Customization Log] %s", req->cmd.m_PrintCusLogReq.log);
+		}
+		UtilityCnf.status = META_SUCCESS;
+		break;
+    default:
+        META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type error ");
+        UtilityCnf.status= META_FAILED;
+        break;
+
+    }
+
+Per_Exit:
+    WriteDataToPC(&UtilityCnf, sizeof(FT_UTILITY_COMMAND_CNF),NULL, 0);
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+
+
diff --git a/src/devtools/meta/src/common/src/MSocket.cpp b/src/devtools/meta/src/common/src/MSocket.cpp
new file mode 100644
index 0000000..cc47411
--- /dev/null
+++ b/src/devtools/meta/src/common/src/MSocket.cpp
@@ -0,0 +1,623 @@
+#ifdef IS_SUPPORT_SP

+#include <cutils/sockets.h>

+#endif

+

+#include <stdio.h>

+#include <sys/socket.h>

+#include <netinet/tcp.h>

+#include <unistd.h>

+#include <errno.h>

+#include <pthread.h>

+

+#include <unistd.h>

+#include <sys/wait.h>

+#include <sys/types.h>

+#include <sys/un.h>

+

+#include "Context.h"

+#include "LogDefine.h"

+#include "MSocket.h"

+

+#define DATA_LEN	256

+

+MSocket::MSocket()

+{

+	m_serverID = -1;

+	m_clientID = -1;

+	m_threadID = -1;

+	m_stop = 0;

+	memset(&m_thread, 0, sizeof(pthread_t));

+	m_type = SOCKET_END;

+	m_bClientConnected = false;

+	

+//	signal(SIGPIPE,SIG_IGN); to modify

+	

+}

+

+MSocket::~MSocket(void)

+{

+	deinit();

+}

+

+int MSocket::initServer(const char * socket_name, int namespaceId, int bListen)

+{

+	META_LOG("[META][Socket] To Create Socket Server:(%s)", socket_name);

+

+#ifdef IS_SUPPORT_SP

+	m_serverID = socket_local_server(socket_name, namespaceId, SOCK_STREAM);

+	

+	META_LOG("[Meta][Socket] m_serverID = %d errno = %d", m_serverID, errno);	

+

+	listen(m_serverID,4);

+#else

+

+

+#endif

+

+	if(bListen)

+	{

+		m_threadID = pthread_create(&m_thread, NULL, ThreadFunc,  this);

+		if(m_threadID)

+		{

+			META_LOG("[Meta][Socket] Failed to create socket thread!");

+			return 0;

+		}

+	}

+	

+	return 1;	

+		

+}

+

+int MSocket::initClient(const char * socket_name, int namespaceId, int bListen)

+{

+	int count = 0;

+	int val = 0;

+	signal(SIGCHLD, SIG_IGN);	

+	META_LOG("[Meta][Socket] To connect server:(%s)", socket_name);

+

+#ifdef IS_SUPPORT_SP

+	while(m_clientID < 0) 

+	{

+		count++;

+		m_clientID = socket_local_client(socket_name, namespaceId, SOCK_STREAM);

+		META_LOG("[Meta][Socket] init client m_clientID = %d", m_clientID);

+        META_LOG("[Meta][Socket] errno = %d, string = %s", errno, strerror(errno));

+		usleep(200*1000);

+		if(count == 5)

+			return 0;		

+	}

+#else

+	int ret = -1;

+    struct sockaddr_un sun;

+	memset(&sun, 0, sizeof(struct sockaddr_un));

+    sun.sun_family = AF_UNIX;

+    strcpy(sun.sun_path, socket_name);

+    m_clientID = socket(PF_UNIX,SOCK_STREAM, 0);

+	if(m_clientID <0 )

+    {

+        META_LOG("[Meta][Socket] init client m_clientID = %d", m_clientID);

+        return 0;

+    }  

+

+	while(ret == -1)

+	{

+		count++;

+		ret = ::connect(m_clientID, (struct sockaddr*)&sun, sizeof(sun));

+		META_LOG("[Meta][Socket] To connect server = %d", ret);

+        META_LOG("[Meta][Socket] errno = %d, string = %s", errno, strerror(errno));

+		usleep(200*1000);

+		if(count == 50)

+			return 0;

+	}

+	

+#endif

+	META_LOG("[Meta][Socket] connect successful");

+	//if bListen is true, we will create thread to read socket data.

+	if(bListen)

+	{

+		m_threadID = pthread_create(&m_thread, NULL, ThreadFunc,  this);

+		if(m_threadID)

+		{

+			META_LOG("[Meta][Socket] Failed to create socket thread!");

+			return 0;

+		}

+	}

+/*	

+	if(0 == setsockopt(m_clientID, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)))

+	{

+		META_LOG("[Meta][Socket] set socket option to TCP_NODELAY!");

+	}

+*/

+	return 1;

+}

+

+void MSocket::deinit()

+{

+	if(m_threadID == 0)

+	{

+		m_stop = 1;

+		pthread_join(m_thread, NULL);

+	}

+

+    if (m_clientID > 0)

+    {

+       	close (m_clientID);

+        m_clientID = -1;

+    }

+

+	if (m_serverID > 0)

+    {

+       	close (m_serverID);

+        m_serverID = -1;

+    }

+}

+

+int MSocket::connect()

+{

+	if(m_bClientConnected)

+		return 0;

+

+	while((m_clientID = accept(m_serverID, NULL, NULL)) == -1)

+	{

+		if(errno == EAGAIN)

+		{

+			usleep(100*1000);

+			continue;

+		}

+		META_LOG("[Meta][Socket] Socket accept error, errno=%d", errno);

+		return -1;

+	}

+	META_LOG("[Meta][Socket] Accept client connection, m_clientID = %d", m_clientID);

+	m_bClientConnected = true;

+	

+	return 0;

+}

+

+

+void MSocket::disconnect()

+{

+	if (m_bClientConnected)

+	{

+		if (m_clientID != -1)

+		{

+			META_LOG("[Meta][Socket] Disconnect client connection, m_clientID = %d", m_clientID);

+			close(m_clientID);

+			m_clientID = -1;

+			m_bClientConnected = false;

+		}

+    }

+}

+

+

+void MSocket::send_msg(const char *msg)

+{

+	int nWritten = 0;

+

+	META_LOG("[Meta][Socket] send mssage (%s) - socket id = %d", msg,  m_clientID);

+

+	if((nWritten = write(m_clientID, msg, strlen(msg))) < 0)

+	{

+		META_LOG("[Meta][Socket] socket write error: %s", strerror(errno));

+	}

+	else

+	{

+		META_LOG("[Meta][Socket] write %d Bytes, total = %zd", nWritten, strlen(msg));

+	}

+}

+

+void *MSocket::ThreadFunc(void *p)

+{

+	MSocket *pSocket = (MSocket *)p;

+	if(pSocket != NULL)

+		pSocket->wait_msg();

+	

+	return NULL;

+}

+

+//////////////////////////////////////////////MATCIClientSocket////////////////////////////////////////////////////

+

+MATCIClientSocket::MATCIClientSocket()

+{

+

+}

+

+MATCIClientSocket::MATCIClientSocket(SOCKET_TYPE type)

+{

+	m_type = type;

+}

+

+MATCIClientSocket::~MATCIClientSocket()

+{

+

+}

+

+void MATCIClientSocket::wait_msg()

+{

+	const char *msg = "calibration";

+	char data[DATA_LEN] = {0};

+	int  len = 0;

+	

+	META_LOG("[Meta][MATCIClientSocket] wait_msg m_clientID = %d", m_clientID);

+

+	while(m_stop == 0)

+	{

+		if(!m_bClientConnected)

+		{

+			if(-1 == connect())

+				continue;

+		}

+		memset(data, 0, DATA_LEN);	

+		len = read(m_clientID, data, DATA_LEN);

+		

+		if(len >0)

+		{

+            if(len == DATA_LEN)

+				data[len-1] = 0;

+			else

+				data[len] = 0;

+			

+			META_LOG("[Meta][MATCIClientSocket] data len = %d, rawdata = (%s)", len, data);

+			char *pos = strstr(data, msg);

+			if(pos != NULL)

+			{

+				createSerPortThread();

+				createAllModemThread();

+				continue;

+			}

+		}

+		else if(0 == len)

+		{	

+			META_LOG("[Meta][MATMSocket] Socket connection lost, need to reconnect");

+			disconnect();

+		}

+		else

+		{

+			usleep(100000); // wake up every 0.1sec   

+		}

+	}

+	return;

+}

+

+//////////////////////////////////////////////MATCIServerSocket////////////////////////////////////////////////////

+

+MATCIServerSocket::MATCIServerSocket()

+{

+

+}

+

+MATCIServerSocket::MATCIServerSocket(SOCKET_TYPE type)

+{

+	m_type = type;

+}

+

+MATCIServerSocket::~MATCIServerSocket()

+{

+

+}

+

+void MATCIServerSocket::wait_msg()

+{

+	const char *msg = "EMETACFG";

+	const char *msg_ok = "OK";

+	char data[DATA_LEN] = {0};

+	int len = 0;

+	

+	META_LOG("[Meta][MATCIServerSocket] wait_msg m_clientID = %d", m_clientID);

+

+	while(m_stop == 0)

+	{

+		memset(data, 0, DATA_LEN);				

+		len = read(m_clientID, data, DATA_LEN);

+

+		if(len > 0)

+		{

+			if(len == DATA_LEN)

+				data[len-1] = 0;

+			else

+				data[len] = 0;

+						

+			META_LOG("[Meta][MATCIServerSocket] data len = %d, rawdata = %s", len, data);

+			

+			char *pos = strstr(data, msg);

+			if(pos != NULL)

+			{

+				pos += 10; //reply format is +EMETACFG: X, the X is modem mode

+				int mdmode = atoi(pos);  //Modem side : meta=0, normal=1

+				if(0 == mdmode) 

+					setCurrentMdMode(2); //AP side: normal=1; meta = 2;

+				else if(1 == mdmode) 

+					setCurrentMdMode(1);

+			

+				continue;

+			}

+

+			pos = strstr(data, msg_ok);

+			if(pos != NULL)

+			{

+				META_LOG("[Meta][MATCIServerSocket] got OK from modem");

+				if(getATRespFlag()==1)

+				{

+					META_LOG("[Meta][MATCIServerSocket] setATRespFlag to 0");

+					setATRespFlag(0);

+				}

+				continue;

+			}

+			setATRespFlag(-1);

+		}

+		else

+		{

+			usleep(100*1000); // wake up every 0.1sec

+		}

+	}

+	

+	return;

+}

+

+//////////////////////////////////////////////MLogSocket////////////////////////////////////////////////////

+

+MLogSocket::MLogSocket()

+{

+	m_mdlogpulling = -1;

+	m_mblogpulling = -1;

+	m_connsyslogpulling = -1;

+	m_mddbpulling = -1;

+	m_gpslogpulling = -1;

+	m_Mutex = PTHREAD_MUTEX_INITIALIZER;

+}

+

+MLogSocket::MLogSocket(SOCKET_TYPE type)

+{

+	m_type = type;

+	m_mdlogpulling = -1;

+	m_mblogpulling = -1;

+	m_connsyslogpulling = -1;

+	m_mddbpulling = -1;

+	m_gpslogpulling = -1;

+	m_Mutex = PTHREAD_MUTEX_INITIALIZER;

+}

+

+MLogSocket::~MLogSocket()

+{

+

+}

+

+void MLogSocket::wait_msg()

+{

+	char data[DATA_LEN] = {0};

+	int  len = 0;

+

+	META_LOG("[Meta][MLogSocket] wait_msg m_clientID = %d", m_clientID);

+

+	while(m_stop == 0)

+	{

+		memset(data, 0, DATA_LEN);				

+		len = read(m_clientID, data, DATA_LEN);

+

+		if(len > 0)

+		{

+		    if(len == DATA_LEN)

+				data[len-1] = 0;

+			else

+				data[len] = 0;

+			

+			META_LOG("[Meta][MLogSocket] m_clientID = %d, data len = %d, rawdata = (%s), cmd = (%s)", m_clientID, len, data, m_strCmd.c_str());

+			

+			if(strstr(data, MDLOG_PULL_START) != NULL)

+			{

+				setLogPullingStatus(0, 1);

+				META_LOG("[Meta][MLogSocket] modem log pull done");

+			}

+			else if(strstr(data, MBLOG_PULL_START) != NULL)

+			{

+				setLogPullingStatus(1, 1);

+				META_LOG("[Meta][MLogSocket] mobile log pull done");

+			}

+			else if(strstr(data, CONNLOG_PULL_START) != NULL)

+			{

+				setLogPullingStatus(3, 1);

+				META_LOG("[Meta][MLogSocket] connsys log pull done");

+			}

+			else if(strstr(data, MDDB_PULL_START) != NULL)

+			{

+				setLogPullingStatus(4, 1);

+				META_LOG("[Meta][MLogSocket] mddb pull done");

+			}

+			else if(strstr(data, GPSLOG_PULL_START) != NULL)

+			{

+				setLogPullingStatus(5, 1);

+				META_LOG("[Meta][MLogSocket] gps log pull done");

+			}

+			

+			if(m_strCmd.size() > 1)

+			{

+				if(strstr(data, m_strCmd.c_str()) != NULL)

+				{

+					pthread_mutex_lock(&m_Mutex);

+					m_strRsp = string(data);

+					m_strCmd = "";

+					META_LOG("[Meta][MLogSocket] wait_msg response = (%s)", m_strRsp.c_str());

+					pthread_mutex_unlock(&m_Mutex);

+				}

+			}

+		}

+		else

+		{		

+			usleep(100000); // wake up every 0.1sec   

+		}		

+	}

+	return;

+}

+

+int MLogSocket::recv_rsp(char *buf)

+{

+	META_LOG("[Meta][MLogSocket] recv_rsp begin");

+	int count = 0;

+	while(1)

+	{

+		pthread_mutex_lock(&m_Mutex);

+		if(m_strRsp.length() > 0)

+		{

+			string strRsp = m_strRsp.erase(0, m_strRsp.find_last_of(',')+1);

+			if(strRsp.length() > 0)

+				strncpy(buf, strRsp.c_str(), strRsp.length());

+			META_LOG("[Meta][MLogSocket] recv_rsp response = (%s)", buf);

+			m_strRsp = "";

+			pthread_mutex_unlock(&m_Mutex);

+			return true;

+		}

+		pthread_mutex_unlock(&m_Mutex);

+		usleep(100000);

+		if (++count == 45)

+		{

+			pthread_mutex_lock(&m_Mutex);

+			META_LOG("[Meta][MLogSocket] recv_rsp end-false");

+			m_strCmd = "";

+			pthread_mutex_unlock(&m_Mutex);

+			return false;

+		}

+	}

+

+	META_LOG("[Meta][MLogSocket] recv_rsp end-true");

+	return true;

+}

+

+

+void MLogSocket::send_msg(const char *msg, bool ignore)

+{

+	int nWritten = 0;

+

+	if(msg==NULL)

+		return;

+

+	META_LOG("[Meta][MLogSocket] send mssage (%s) - socket id = %d", msg,  m_clientID);

+

+	if(ignore == false)

+	{

+		pthread_mutex_lock(&m_Mutex);

+		m_strCmd = string(msg);

+		pthread_mutex_unlock(&m_Mutex);

+	}

+	

+	if((nWritten = write(m_clientID, msg, strlen(msg))) < 0)

+	{

+		m_strCmd = "";

+		META_LOG("[Meta][MLogSocket] socket write error: %s", strerror(errno));

+	}

+	else

+	{

+		META_LOG("[Meta][MLogSocket] write %d Bytes, total = %zd", nWritten, strlen(msg));

+	}

+}

+

+int MLogSocket::getLogPullingStatus(int type)

+{

+	int status = -1;

+	switch(type)

+	{

+		case 0:

+			status = m_mdlogpulling;

+			break;

+		case 1:

+			status = m_mblogpulling;

+			break;

+		case 3:

+			status = m_connsyslogpulling;

+			break;

+		case 4:

+			status = m_mddbpulling;

+			break;

+		case 5:

+			status = m_gpslogpulling;

+			break;

+		default:

+			break;

+	}

+

+	return status;

+}

+

+void MLogSocket::setLogPullingStatus(int type, int value)

+{	

+	pthread_mutex_lock(&m_Mutex);

+

+	switch(type)

+	{

+		case 0:

+			m_mdlogpulling = value;

+			break;

+		case 1:

+			m_mblogpulling = value;

+			break;

+		case 3:

+			m_connsyslogpulling = value;

+			break;

+		case 4:

+			m_mddbpulling = value;

+			break;

+		case 5:

+			m_gpslogpulling = value;

+			break;

+		default:

+			break;

+	}

+

+	pthread_mutex_unlock(&m_Mutex);

+}

+

+

+//////////////////////////////////////////////MATMSocket////////////////////////////////////////////////////

+

+MATMSocket::MATMSocket()

+{

+

+}

+

+MATMSocket::MATMSocket(SOCKET_TYPE type)

+{

+	m_type = type;

+}

+

+MATMSocket::~MATMSocket()

+{

+

+}

+

+void MATMSocket::wait_msg()

+{

+	const char *msg = "ATM";

+	char data[DATA_LEN] = {0};

+	int len = 0;

+	

+	META_LOG("[Meta][MATMSocket] wait_msg m_clientID = %d", m_clientID);

+

+	while(m_stop == 0)

+	{

+		memset(data, 0, DATA_LEN);				

+		len = read(m_clientID, data, DATA_LEN);

+

+		if(len > 0)

+		{

+			if(len == DATA_LEN)

+				data[len-1] = 0;

+			else

+				data[len] = 0;

+						

+			META_LOG("[Meta][MATMSocket] data len = %d, rawdata = %s", len, data);

+			char *pos = strstr(data, msg);

+			if(pos != NULL)

+			{

+				HandleSocketCmd(data);

+				continue;

+			}

+		}

+		else

+		{

+			usleep(100*1000); // wake up every 0.1sec

+		}

+	}

+	return;

+}

+

+

+

+

diff --git a/src/devtools/meta/src/common/src/MdRxWatcher.cpp b/src/devtools/meta/src/common/src/MdRxWatcher.cpp
new file mode 100644
index 0000000..82767cc
--- /dev/null
+++ b/src/devtools/meta/src/common/src/MdRxWatcher.cpp
@@ -0,0 +1,336 @@
+#include <assert.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include <string.h>
+#include "SerPort.h"
+#include "LogDefine.h"
+#include "MdRxWatcher.h"
+#include "Context.h"
+#include "PortInterface.h"
+#include "FtModule.h"
+#include "snappy-c.h"
+
+MdRxWatcher::MdRxWatcher(int index)
+{
+	m_bufLen = 0;
+	m_frmStat = 0;
+	m_frmStat0 = 0;
+	m_chkSum = 0;
+	m_frmLen = 0;
+	m_bL1Header = 0;
+	nModemIndex = index;
+
+	m_recv_buf = (TST_MD_RECV_BUF *)malloc(sizeof(TST_MD_RECV_BUF));
+}
+
+MdRxWatcher::~MdRxWatcher(void)
+{
+	if(m_recv_buf != NULL)
+	{
+		free(m_recv_buf);
+		m_recv_buf = NULL;
+	}
+}
+
+signed int MdRxWatcher::onReceived(
+	 unsigned char *buf,
+	unsigned int len)
+{	
+	META_LOG("[Meta] Receive data from modem[%d], len = %d", nModemIndex, len);
+	if(getMDMode()==1)//normal mode
+	{
+		SerPort *pPort = getSerPort();
+		if(NULL == pPort || 1 == getNormalModeTestFlag())  return 0;  //Discard this packet if pPort is NULL or in ATM mode
+		signed int cbWriten = 0;
+		cbWriten= pPort->write(buf, len);
+		META_LOG("[Meta] Write data by USB. data len = %d, write done = %d", len, cbWriten);		
+		dumpDataInHexString(buf,len,16);
+	}
+	else
+	{
+		dumpDataInHexString(buf,len,16);  
+		int mdType = getMDChType(nModemIndex); 
+		if 	( mdType == FT_MODEM_CH_TUNNELING || 
+	      	mdType == FT_MODEM_CH_TUNNELING_IGNORE_CKSM )
+		{
+			processTunnelData(buf, len);
+		}
+		else
+		{
+	   		process(buf, len);
+		}
+	}
+	return 0;
+}
+
+int MdRxWatcher:: fillDataToTSTBufferReverse(unsigned char data, char **buffer_ptr)
+{
+	if (data == 0x5A) {
+		*(*buffer_ptr)-- = 0x5A;
+		*(*buffer_ptr)-- = 0x5A;
+		return 2;
+	} else if (data == 0xA5) {
+		*(*buffer_ptr)-- = 0x01;
+		*(*buffer_ptr)-- = 0x5A;
+		return 2;
+	}
+	
+	*(*buffer_ptr)-- = data;
+	return 1;
+}
+
+int MdRxWatcher::fillDataToTSTBuffer(unsigned char data, char **buffer_ptr)
+{
+	if (data == 0x5A) {
+		*(*buffer_ptr)++ = 0x5A;
+		*(*buffer_ptr)++ = 0x5A;
+		return 2;
+	} else if (data == 0xA5) {
+		*(*buffer_ptr)++ = 0x5A;
+		*(*buffer_ptr)++ = 0x01;
+		return 2;
+	}
+	
+	*(*buffer_ptr)++ = data;
+	return 1;
+}
+
+void MdRxWatcher::processTunnelData(unsigned char *pdata, unsigned int len)
+{
+	//META_LOG("[Meta] processTunnelData, len = %d", len);
+	int md_rsp_type = RS232_RESPONSE_MD_DATA_TUNNEL_START;
+	char *buf_begin = NULL;
+	char *p = NULL;
+	if(m_recv_buf == NULL)
+	{
+		META_LOG("[Meta] failed to malloc buf in processTunnelData");
+		return;
+	}
+	
+	memset(m_recv_buf, 0, sizeof(TST_MD_RECV_BUF));
+	memcpy(m_recv_buf->data, pdata, len);
+	m_recv_buf->data_len = len;
+	
+	// create tunneling header
+	// TST spec: For confirm message, the length of frame content includes data and message type (1 byte). 
+	// See TST spec for detail
+	unsigned int length_in_tunnel_resp = m_recv_buf->data_len + 1;
+	// Write the TST header in RESERSE ORDER, please note that buffer space must preseve enough spacing for possibile escaping translation
+	buf_begin = (char *)m_recv_buf->data-1;
+	fillDataToTSTBufferReverse((md_rsp_type + nModemIndex), &buf_begin);
+	fillDataToTSTBufferReverse((length_in_tunnel_resp & 0xff), &buf_begin);
+	fillDataToTSTBufferReverse((length_in_tunnel_resp >> 8), &buf_begin);
+	*(buf_begin) = 0x55;
+
+	// calculate checksum if needed, otherwise the checksum field is 0xff
+	char cksm_byte = 0xff;
+	char *recv_buf_end = m_recv_buf->data + m_recv_buf->data_len;
+
+	if (getMDChType(nModemIndex) == FT_MODEM_CH_TUNNELING) 
+	{
+		cksm_byte = (md_rsp_type+nModemIndex);
+		cksm_byte ^=(length_in_tunnel_resp & 0xff);
+		cksm_byte ^=(length_in_tunnel_resp >> 8);
+		cksm_byte ^= 0x55;
+		
+		for(p = (char *)m_recv_buf->data; p < recv_buf_end; p++) {
+			cksm_byte ^= *p;
+		}
+	}
+
+	fillDataToTSTBuffer(cksm_byte, &recv_buf_end);
+
+	processMDConfirm(buf_begin, recv_buf_end - buf_begin);
+
+}
+
+
+void MdRxWatcher::processMDConfirm(char *pdata, unsigned short len)
+{
+	//META_LOG("[Meta] processMDConfirm, len = %d", len);
+	signed int cbWriten = 0;
+
+	SerPort *pPort = getSerPort();
+	if(NULL == pPort) return; //Discard this packet because it is during port switching process, and pPort is NULL
+
+	/*
+	so we use 0x77 and 0x01 indicate 0x11,
+	use 0x77 and 0x03 indicate 0x77,
+	use 0x77 and 0x13 indicate 0x13
+	the escape is just for compatible with feature phone
+	*/
+
+	META_COM_TYPE eComType = getComType();
+	if(eComType == META_USB_COM || eComType == META_PCIE_COM )
+	{
+		cbWriten = pPort->write((unsigned char *)pdata, len);
+		//META_LOG("[Meta] write data by USB. data len = %d, write done = %d", len, cbWriten);		
+		dumpDataInHexString((unsigned char *)pdata,len,16);
+		return;
+	}
+}
+
+void MdRxWatcher::process(const unsigned char *buf, unsigned int len)
+{
+	unsigned char	ch=0;	
+	unsigned short	u16Length=0;
+	const unsigned char	*src=buf;
+
+	while (u16Length < len)
+	{
+		ch = *src;
+		m_frmBuf[m_bufLen] = ch;
+
+		++ u16Length;
+		++ m_bufLen;
+
+		if ((ch == STX_OCTET || ch == STX_L1HEADER ) &&
+			(m_frmStat != RS232_FRAME_MD_CONFIRM_DATA) &&
+			(m_frmStat != RS232_FRAME_LENHI) &&
+			(m_frmStat != RS232_FRAME_LENLO) )
+		{
+			if(ch == STX_L1HEADER)
+				m_bL1Header = true;
+			else
+				m_bL1Header = false;
+			
+			if ( m_frmStat != RS232_FRAME_CHECKSUM)
+			{
+				m_frmStat = RS232_FRAME_LENHI;
+				META_LOG("[Meta] Flag change to RS232_FRAME_LENHI");
+				++ src;
+				m_chkSum = ch;
+				ch = *src;
+				m_frmLen = 0;
+				continue;
+			}		
+		}
+		else
+		{
+			if ((!m_bL1Header)   &&
+				(*src == MUX_KEY_WORD ) &&
+				(m_frmStat != RS232_FRAME_KEYWORD))
+			{ // enter MUX state(0x5A) and save the old
+
+				m_frmStat0 = m_frmStat;
+				m_frmStat = RS232_FRAME_KEYWORD;
+
+				++ src;
+
+				continue;
+			}
+			else if(m_frmStat == RS232_FRAME_KEYWORD)
+			{
+				if (*src== MUX_KEY_WORD)
+					ch = MUX_KEY_WORD;
+				else if (*src == 0x01)
+					ch=STX_L1HEADER; //0xA5 escaping
+
+				//leave MUX state and restore the state
+				m_frmStat = m_frmStat0;
+				++ m_frmLen;				
+			}
+		}
+
+		switch (m_frmStat)
+		{
+			/*the state is RS232_FRAME_LENHI*/
+		case RS232_FRAME_LENHI:
+			if(m_bL1Header)
+				m_frmLen = ch;
+			else
+				m_frmLen = ch << 8;
+			m_frmStat = RS232_FRAME_LENLO;
+			break;
+
+			/*the state is RS232_FRAME_LENLO*/
+		case RS232_FRAME_LENLO:
+			if(m_bL1Header)
+				m_frmLen += (ch << 8);
+			else
+				m_frmLen += ch;
+			if ((m_frmLen +4) > FRAME_MAX_LEN)
+			{
+				m_frmStat = RS232_FRAME_STX;
+				META_LOG("[Meta] frame too long: %d+4 > %d.",
+					m_frmLen, FRAME_MAX_LEN);
+				return;
+			}
+			else
+			{
+				m_frmStat = RS232_FRAME_MD_CONFIRM_DATA;
+			}
+			break;
+
+		case RS232_FRAME_MD_CONFIRM_DATA:
+			if (m_bufLen == m_frmLen+3)
+			{
+				m_frmStat = RS232_FRAME_CHECKSUM;
+			}
+
+			break;
+
+
+		case  RS232_FRAME_CHECKSUM:
+			m_frmStat = RS232_FRAME_STX;
+
+			if (m_chkSum == ch)
+			{
+				processMDConfirm((char*)m_frmBuf, m_frmLen+4);
+
+				buf = src;
+				m_bufLen = 0;
+				m_frmLen = 0;
+				m_chkSum = 0;
+			}
+			else
+			{
+				META_LOG("[Meta] CheckSum error: %d != %d",
+					(signed int)m_chkSum, (signed int)ch);
+			}
+			break;
+		case RS232_FRAME_STX:
+			m_bufLen = 0;
+			m_frmLen = 0;
+			m_chkSum = ch;
+			break;
+		default:
+			/* exception of g_cTstFrameState */
+			break;
+
+		}
+		m_chkSum ^= ch;
+		++ src;
+	}
+
+
+}
+bool MdRxWatcher::compress(char *pdata, unsigned short len, char *compressed, size_t *compressed_len)
+{
+    META_LOG("[Meta] META Confirm. compress starts\n");
+
+    char *pTempBuf = (char*) pdata;
+    // Ask for the max size of the compressed object.
+    size_t max_compressed_len = snappy_max_compressed_length(len);
+    if (*compressed_len < max_compressed_len)
+    {
+    	// to modify
+        //META_LOG("[Meta] error: snappy compression buffer is not enough. buffer size: %d, max compression len: %d\n", *compressed_len, max_compressed_len);
+        return false;
+    }
+
+    META_LOG("[Meta] snappy compress starts. len: %d\n", len);
+    snappy_status status = snappy_compress(pTempBuf, len, compressed, (size_t *)compressed_len);
+    if (status != SNAPPY_OK)
+    {
+        META_LOG("[Meta] Compression failed. status: %d\n", status);
+        return false;
+    }
+	// to modify
+    //META_LOG("[Meta] snappy compress done. comp_len: %d\n", *compressed_len);
+
+    return true;
+}
diff --git a/src/devtools/meta/src/common/src/Meta_mipc.cpp b/src/devtools/meta/src/common/src/Meta_mipc.cpp
new file mode 100644
index 0000000..1ce842f
--- /dev/null
+++ b/src/devtools/meta/src/common/src/Meta_mipc.cpp
@@ -0,0 +1,90 @@
+#include <pthread.h>

+

+#include "Meta_mipc.h"

+#include "LogDefine.h"

+

+

+#include "mipc_msg_host.h"

+#include "mipc_msg_tlv_const.h"

+//#include "mipc_msg_tlv_api.h"

+

+MetaMIPC::MetaMIPC()

+{

+	m_bReady = false;

+}

+

+MetaMIPC::~MetaMIPC(void)

+{

+	mipc_deinit();

+}

+

+

+static void atcid_mipc_ind_cb(mipc_msg_t *msg_ptr, void *priv_ptr)

+{

+	MetaMIPC *pData = (MetaMIPC*)priv_ptr;

+		

+	const char *urc = "+EIND: 128";

+	char *urc_ptr = NULL;

+	uint16_t urc_len;

+

+	urc_ptr = (char *)mipc_msg_get_val_ptr(msg_ptr, MIPC_SYS_AT_IND_T_ATCMD, &urc_len);

+

+	META_LOG("[Meta] read URC: len= %d,  %s", urc_len, urc_ptr);

+

+	if( NULL != strstr(urc_ptr, urc))

+	{

+		if(pData != NULL)

+			pData->SetModemReady(true);

+	}		

+}

+

+

+void MetaMIPC::Init()

+{

+	int ret =mipc_init("meta_tst");

+	META_LOG("[Meta] [MIPC] mipc_init result = %d", ret);

+	

+	mipc_msg_register_ind((mipc_msg_sim_ps_id_enum)MIPC_SYS_SIM_PS_PS0, MIPC_SYS_AT_IND, (void*)atcid_mipc_ind_cb, this);

+}

+

+bool MetaMIPC::Send_at_cmd(const char* cmd, char *res)

+{

+	mipc_msg_t *msg_req_ptr = NULL;

+	mipc_msg_t *msg_cnf_ptr = NULL;

+	mipc_result_enum result;

+	char *atcmd_res_ptr = NULL;

+	uint16_t atcmd_res_len = 0;

+

+	msg_req_ptr = mipc_msg_init(MIPC_SYS_AT_REQ, (mipc_msg_sim_ps_id_enum)MIPC_SYS_SIM_PS_PS0);

+	if(msg_req_ptr != NULL)

+	{

+

+	    mipc_msg_add_tlv(msg_req_ptr, MIPC_SYS_AT_REQ_T_ATCMD, strlen(cmd), cmd);

+		

+	    msg_cnf_ptr = mipc_msg_sync(msg_req_ptr);

+		if(msg_cnf_ptr == NULL )

+		{

+			META_LOG("[Meta] [MIPC] mipc_msg_sync failed");

+			return false;

+		}

+		META_LOG("[Meta] [MIPC] Send AT command [%s] with len:[%zd]", cmd, strlen(cmd));

+		

+		mipc_msg_deinit(msg_req_ptr);

+	}

+	else

+	{

+		META_LOG("[Meta] [MIPC] mipc_msg_init failed");

+		return false;

+	}

+	

+	atcmd_res_ptr = (char *)mipc_msg_get_val_ptr(msg_cnf_ptr, MIPC_SYS_AT_CNF_T_ATCMD, &atcmd_res_len);

+	atcmd_res_ptr[atcmd_res_len] = '\0';

+	META_LOG("[Meta] [MIPC] AT response:[%s] with len:[%d]", atcmd_res_ptr, atcmd_res_len);

+	strcpy(res, atcmd_res_ptr);

+	res[atcmd_res_len] = '\0';

+

+	mipc_msg_deinit(msg_cnf_ptr);

+	return true;

+	

+}

+

diff --git a/src/devtools/meta/src/common/src/Modem.cpp b/src/devtools/meta/src/common/src/Modem.cpp
new file mode 100644
index 0000000..5bac286
--- /dev/null
+++ b/src/devtools/meta/src/common/src/Modem.cpp
@@ -0,0 +1,58 @@
+#include "Modem.h"
+#include "Device.h"
+#include "LogDefine.h"
+
+Modem::Modem(const char *ccci, unsigned short id)
+	: CmdTarget(id), m_pDev(new CCCI(ccci))
+{
+}
+
+Modem::Modem(unsigned short id)
+	: CmdTarget(id), m_pDev(new CCB())
+{
+
+}
+Modem::~Modem(void)
+{	
+	m_pDev->close();
+	META_LOG("[Meta] Delete Modem");
+	delete m_pDev;
+}
+
+signed int Modem::pumpAsync(IDevWatcher *p)
+{
+	return m_pDev->pumpAsync(p);
+}
+
+void Modem::popUpAsync()
+{
+	m_pDev->setExitFlag(1);
+}
+
+
+void Modem::exec(Frame *pFrm)
+{
+	CmdTarget::exec(pFrm);
+	m_pDev->write(pFrm->localBuf(), pFrm->localLen());
+}
+
+void Modem::exec(const unsigned char *p, unsigned int len )
+{
+	m_pDev->write(p,len);
+}
+
+signed int Modem::getDevHandle()
+{
+	return m_pDev->getDevHandle();
+}
+	
+int Modem::init(Frame*)
+{
+	return 1;
+}
+
+
+void Modem::deinit()
+{
+}
+
diff --git a/src/devtools/meta/src/common/src/PortHandle.cpp b/src/devtools/meta/src/common/src/PortHandle.cpp
new file mode 100644
index 0000000..6e51ad1
--- /dev/null
+++ b/src/devtools/meta/src/common/src/PortHandle.cpp
@@ -0,0 +1,508 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#ifdef IS_SUPPORT_SP
+#include <cutils/properties.h>
+#endif
+#include <dirent.h>
+#include <sys/poll.h>
+#include <linux/input.h>
+#include <unistd.h>
+#include "PortHandle.h"
+#include "PortInterface.h"
+#include "LogDefine.h"
+#include "SerPort.h"
+#include "Context.h"
+
+#ifdef MTK_META_DIPC
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "dipc_intf.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#if defined(MTK_META_APONLY)
+	#define DEV_USB_PATH	"/dev/ttyGS0"
+#else
+    #define DEV_USB_PATH    "/dev/ttyGS0"
+#endif
+
+#define DEV_PCIE_PATH    "/dev/ccci_hsapif_meta"
+
+
+#define COM_PORT_TYPE_FILE "/sys/bus/platform/drivers/meta_com_type_info/meta_com_type_info"
+#define COM_PORT_TYPE_STR_LEN 1
+
+#define UART_PORT_INFO_FILE "/sys/bus/platform/drivers/meta_uart_port_info/meta_uart_port_info"
+#define UART_PORT_INFO_STR_LEN 1
+
+#define MAX_DEVICES 32
+#define MAX_LENGTH  1024
+
+
+class PortHandle
+{
+private:
+	PortHandle(void);
+public:
+	~PortHandle(void);
+
+	static PortHandle *instance();
+	SerPort * createPort();
+	void destroyPort();
+	SerPort * getPort() const;
+	META_COM_TYPE getComType();
+	void setComType(META_COM_TYPE comType);
+	void querySerPortStatus();
+	void FTMuxPrimitiveData(META_RX_DATA *pMuxBuf);
+	int WriteDataToPC(void *Local_buf,unsigned short Local_len,void *Peer_buf,unsigned short Peer_len);
+	int getMetaUartPort(void);
+	void destroy();
+	void usbMutexLock(bool bLock);
+
+	META_COM_TYPE getDualIPCType();
+
+private:
+	META_COM_TYPE		m_comType;
+	SerPort *			m_serPort;
+private:
+	static PortHandle *	m_myInst;
+
+	unsigned int ev_count;
+	unsigned int ev_touch;
+	struct pollfd ev_fds[MAX_DEVICES];
+	pthread_mutex_t m_usbMutex;
+
+};
+
+PortHandle *PortHandle::m_myInst = NULL;
+
+PortHandle::PortHandle(void)
+	: m_comType(META_UNKNOWN_COM),
+	  m_serPort(NULL)
+{
+    ev_count = 0;
+	ev_touch = 0;
+	memset(&ev_fds, 0, sizeof(pollfd)*MAX_DEVICES);
+	m_usbMutex = PTHREAD_MUTEX_INITIALIZER;
+}
+
+PortHandle::~PortHandle(void)
+{
+	if (m_serPort != NULL)
+	{
+		delete m_serPort;
+		m_serPort = NULL;
+	}
+}
+
+
+PortHandle *PortHandle::instance()
+{
+	return (m_myInst==NULL) ? ((m_myInst=new PortHandle)) : m_myInst;
+}
+
+void PortHandle::destroy()
+{
+	delete m_myInst;
+	m_myInst = NULL;
+}
+
+void PortHandle::destroyPort()
+{
+	if(m_serPort != NULL)
+	{
+		delete m_serPort;
+		m_serPort = NULL;			
+	}
+}
+
+SerPort * PortHandle::createPort()
+{
+#if (defined(MTK_META_DIPC) && defined(MTK_META_APONLY))
+    META_COM_TYPE eComType = getDualIPCType();
+
+#else
+    META_COM_TYPE eComType = META_USB_COM;
+#endif
+
+    if(eComType == META_USB_COM)
+    {
+        m_serPort = new UsbPort(DEV_USB_PATH);
+    }
+	else if(eComType == META_PCIE_COM)
+    {
+        m_serPort = new UsbPort(DEV_PCIE_PATH);
+    }
+
+	setComType(eComType);
+
+	return m_serPort;
+}
+
+SerPort * PortHandle::getPort() const
+{
+	return m_serPort;
+}
+
+static int getBootMode_local()
+{
+    int bootMode;
+
+    bootMode = readSys_int(BOOTMODE_PATH);
+
+    if(NORMAL_BOOT== bootMode)
+    {
+    	META_LOG("[Meta] Normal mode boot!");
+    }
+    else if(META_BOOT== bootMode)
+    {
+    	META_LOG("[Meta] Meta mode boot!");
+    }
+    else 
+	{
+		META_LOG("[Meta] Not Support boot mode! BootMode=%d",bootMode);
+        bootMode = -1;       
+    }     
+    return bootMode;   
+}
+
+void PortHandle::setComType(META_COM_TYPE comType)
+{
+	META_LOG("[META] setComType %d",comType);	
+	m_comType = comType;		
+}
+
+META_COM_TYPE PortHandle::getDualIPCType()
+{
+	META_COM_TYPE type = META_USB_COM;
+#ifdef MTK_META_DIPC
+	dipc_user_init();
+
+	dipc_mode mode = query_dipc_mode();
+	META_LOG("[META] get dipc mode. PCIe_ADV:1, PCIe_ONLY:2, DUAL_IPC:3, mode = %d", mode);	
+	
+	port_interface interface = query_ap_port_interface(AP_PORT_META);
+	META_LOG("[META] get port interface. usb:1, PCIe:2, interface = %d", interface);	
+
+	if((interface == INTF_PCIE) || (interface == INTF_USB_AND_PCIE)) 
+	{
+		port_status status = query_ap_pcie_port_status(AP_PORT_META);
+		META_LOG("[META] get port status. Enable:2, Disable:1, status = %d", status);	
+		if(status == PORT_ENABLE)
+			type = META_PCIE_COM;
+	}
+#endif
+	return type;
+}
+
+META_COM_TYPE PortHandle::getComType()
+{
+	if (m_comType == META_UNKNOWN_COM)
+	{
+#if (defined(MTK_META_DIPC) && defined(MTK_META_APONLY))
+		m_comType  = getDualIPCType();
+		
+#else
+		m_comType  = META_USB_COM;
+#endif
+		META_LOG("[Meta] com port type: %d", m_comType);
+    }
+
+	return m_comType;
+}
+
+
+void PortHandle::querySerPortStatus()
+{
+	usbMutexLock(true);
+	if (m_comType == META_USB_COM)
+	{
+		SerPort * pPort = getSerPort();
+		if (pPort != NULL)
+		{
+			pPort->update();
+		}
+	}
+
+	usbMutexLock(false);
+}
+
+int PortHandle::getMetaUartPort(void)
+{
+    int nPort = 1;
+    if (m_comType == META_UART_COM)
+    {
+	    char buf[UART_PORT_INFO_STR_LEN + 1] = {0};
+	    int fd = open(UART_PORT_INFO_FILE, O_RDONLY);
+	    if (fd != -1)
+	    {
+			if (read(fd, buf, sizeof(char)*COM_PORT_TYPE_STR_LEN) <= 0)
+			{
+			    META_LOG("[Meta] ERROR can not read meta uart port ");
+		    }
+			else
+			{
+			    nPort = atoi(buf);
+			}
+		    close(fd);
+
+	    }
+	    else
+	    {
+		    META_LOG("[Meta] Failed to open meta uart port file %s", UART_PORT_INFO_FILE);
+	    }
+	    META_LOG("[Meta] uart com port: %d", nPort);
+    }
+	else
+	{
+	    META_LOG("[Meta] com port type is not uart");
+	}
+	return nPort;
+}
+
+void PortHandle::FTMuxPrimitiveData(META_RX_DATA *pMuxBuf)
+{
+    /* This primitive is logged by TST */
+    unsigned char *pTempBuf = NULL;
+    unsigned char *pTempDstBuf = NULL;
+    unsigned char *pMamptrBase = NULL;
+    unsigned char *pDestptrBase = NULL;
+    int iCheckNum = 0;
+    int dest_index=0;
+    unsigned char cCheckSum = 0;
+    int cbWriten = 0;
+    int cbTxBuffer = 0;
+    SerPort * pPort = getSerPort();
+
+    if(pMuxBuf == NULL)
+    {
+        META_LOG("[Meta] (FTMuxPrimitiveData) Err: pMuxBuf is NULL");
+        return;
+    }
+
+    cbTxBuffer = pMuxBuf->LocalLen + pMuxBuf->PeerLen + 9;
+    if (cbTxBuffer>FRAME_MAX_LEN)
+    {
+        META_LOG("[Meta] (FTMuxPrimitiveData) error frame size is too big!! ");
+        return;
+    }
+    else
+        META_LOG("[Meta] (FTMuxPrimitiveData) Type = %d Local_len = %d, Peer_len = %d", pMuxBuf->eFrameType, pMuxBuf->LocalLen, pMuxBuf->PeerLen);
+
+    //META_LOG("[Meta] (FTMuxPrimitiveData) total size = %d", cbTxBuffer);
+    pMamptrBase = (unsigned char *)malloc(cbTxBuffer);
+
+    if(pMamptrBase == NULL)
+    {
+        META_LOG("[Meta] (FTMuxPrimitiveData) Err: malloc pMamptrBase Fail");
+        return;
+    }
+    pDestptrBase = (unsigned char *)malloc(FRAME_MAX_LEN);
+    if(pDestptrBase == NULL)
+    {
+        META_LOG("[Meta] (FTMuxPrimitiveData) Err: malloc pDestptrBase Fail");
+        free(pMamptrBase);
+        return;
+    }
+
+
+    pTempDstBuf = pDestptrBase;
+    pTempBuf = pMamptrBase;
+
+    /* fill the frameheader */
+    *pTempBuf++ = 0x55;
+    *pTempBuf++=((pMuxBuf->LocalLen + pMuxBuf->PeerLen +5)&0xff00)>>8;
+    *pTempBuf++= (pMuxBuf->LocalLen + pMuxBuf->PeerLen +5)&0xff;
+    *pTempBuf++ = 0x60;
+
+    /*fill the local and peer data u16Length and its data */
+    *pTempBuf++ = ((pMuxBuf->LocalLen)&0xff); /// pMuxBuf->LocalLen ;
+    *pTempBuf++ = ((pMuxBuf->LocalLen)&0xff00)>>8;
+    *pTempBuf++ = (pMuxBuf->PeerLen )&0xff;   ///pMuxBuf->PeerLen ;
+    *pTempBuf++ = ((pMuxBuf->PeerLen)&0xff00)>>8;
+
+    memcpy((pTempBuf), pMuxBuf->pData, pMuxBuf->LocalLen + pMuxBuf->PeerLen);
+
+    pTempBuf = pMamptrBase;
+
+    /* 0x5a is start data, so we use 0x5a and 0x01 inidcate 0xa5, use 0x5a and 0x5a indicate 0x5a
+    the escape is just for campatiable with feature phone */
+    while (iCheckNum != (cbTxBuffer-1))
+    {
+        cCheckSum ^= *pTempBuf;
+        *pTempDstBuf = *pTempBuf;
+        iCheckNum++;
+
+        if (*pTempBuf ==0xA5 )
+        {
+            *pTempDstBuf++ = 0x5A;
+            *pTempDstBuf++ = 0x01;
+            dest_index++;		//do the escape, dest_index should add for write to uart or usb
+        }
+        else if (*pTempBuf ==0x5A )
+        {
+            *pTempDstBuf++ = 0x5A;
+            *pTempDstBuf++ = 0x5A;
+            dest_index++;		//do the escape, dest_index should add for write to uart or usb
+        }
+        else
+            pTempDstBuf++;
+
+        dest_index++;
+        pTempBuf++;
+    }
+
+    /* 0x5a is start data, so we use 0x5a and 0x01 inidcate 0xa5 for check sum, use 0x5a and 0x5a indicate 0x5a
+    the escape is just for campatiable with feature phone */
+    if ( cCheckSum ==0xA5 )
+    {
+        dest_index++;		//do the escape, dest_index should add for write to uart or usb
+        //Wayne replace 2048 with MAX_TST_RECEIVE_BUFFER_LENGTH
+        if ((dest_index) > FRAME_MAX_LEN)//2048)
+        {
+            META_LOG("[Meta] (FTMuxPrimitiveData) Data is too big: index = %d cbTxBuffer = %d ",dest_index, cbTxBuffer);
+            goto TSTMuxError;
+        }
+
+        *pTempDstBuf++= 0x5A;
+        *pTempDstBuf = 0x01;
+    }
+    else if ( cCheckSum ==0x5A )
+    {
+        dest_index++;		//do the escape, dest_index should add for write to uart or usb
+        if ((dest_index) > FRAME_MAX_LEN)
+        {
+            META_LOG("[Meta] (FTMuxPrimitiveData) Data is too big: index = %d cbTxBuffer = %d ",dest_index, cbTxBuffer);
+            goto TSTMuxError;
+        }
+        *pTempDstBuf++= 0x5A;
+        *pTempDstBuf = 0x5A;
+    }
+    else
+        *pTempDstBuf =(char )cCheckSum;
+
+    dest_index++;
+
+    //write to PC
+    //cbWriten = write(getPort(), (void *)pDestptrBase, dest_index);
+
+	pPort->write(pDestptrBase, dest_index);
+    pTempDstBuf = pDestptrBase;
+
+    META_LOG("[Meta] FTMuxPrimitiveData: %d  %d %d  cChecksum: %d ",cbWriten, cbTxBuffer, dest_index,cCheckSum);
+
+    TSTMuxError:
+
+    free(pMamptrBase);
+    free(pDestptrBase);
+}
+
+
+int PortHandle::WriteDataToPC(void *Local_buf,unsigned short Local_len,void *Peer_buf,unsigned short Peer_len)
+{
+	META_RX_DATA metaRxData;
+	memset(&metaRxData,0, sizeof(META_RX_DATA));
+	unsigned int dataLen = Local_len+Peer_len+8+1;
+	unsigned char *metaRxbuf = (unsigned char *)malloc(dataLen);
+	if(metaRxbuf==NULL)
+	{
+		return 0;
+	}
+	memset(metaRxbuf,0, dataLen);
+	unsigned char *cPeerbuf = &metaRxbuf[Local_len+8];
+
+	metaRxData.eFrameType = AP_FRAME;
+	metaRxData.pData = metaRxbuf;
+	metaRxData.LocalLen = Local_len;
+	metaRxData.PeerLen = Peer_len >0 ? Peer_len+8 : Peer_len;
+
+    if (((Local_len + Peer_len)> FT_MAX_LEN)||(Peer_len >PEER_BUF_MAX_LEN))
+    {
+        META_LOG("[Meta] (WriteDataToPC) Err: Local_len = %hu, Peer_len = %hu", Local_len,Peer_len);
+		free(metaRxbuf);
+		metaRxbuf = NULL;
+        return 0;
+    }
+
+    if ((Local_len == 0) && (Local_buf == NULL))
+    {
+        META_LOG("[Meta] (WriteDataToPC) Err: Local_len = %hu, Peer_len = %hu", Local_len,Peer_len);
+		free(metaRxbuf);
+		metaRxbuf = NULL;
+        return 0;
+    }
+
+    // copy to the temp buffer, and send it to the tst task.
+    memcpy(metaRxbuf, Local_buf, Local_len);
+    if ((Peer_len >0)&&(Peer_buf !=NULL))
+        memcpy(cPeerbuf, Peer_buf, Peer_len);
+
+    FTMuxPrimitiveData(&metaRxData);
+	free(metaRxbuf);
+	metaRxbuf = NULL;
+    return 1;
+}
+
+void PortHandle::usbMutexLock(bool bLock)
+{
+	if(bLock)
+		pthread_mutex_lock(&m_usbMutex);
+	else
+		pthread_mutex_unlock(&m_usbMutex);
+}
+/////////////////////////////////////////////////////////////////////////////////
+
+void destroyPortHandle()
+{
+	return PortHandle::instance()->destroy();
+}
+
+META_COM_TYPE getComType()
+{
+	return PortHandle::instance()->getComType();
+}
+
+SerPort * createSerPort()
+{
+	return PortHandle::instance()->createPort();
+}
+
+void destroySerPort()
+{
+	return PortHandle::instance()->destroyPort();
+}
+
+SerPort * getSerPort()
+{
+	return PortHandle::instance()->getPort();
+}
+
+void querySerPortStatus()
+{
+     return PortHandle::instance()->querySerPortStatus();
+}
+
+int WriteDataToPC(void *Local_buf,unsigned short Local_len,void *Peer_buf,unsigned short Peer_len)
+{
+	return PortHandle::instance()->WriteDataToPC(Local_buf,Local_len,Peer_buf,Peer_len);
+}
+
+void setComType(META_COM_TYPE comType)
+{
+	return 	PortHandle::instance()->setComType(comType);
+}
+
+void usbMutexLock(bool bLock)
+{
+	return 	PortHandle::instance()->usbMutexLock(bLock);
+}
+
+
diff --git a/src/devtools/meta/src/common/src/SerPort.cpp b/src/devtools/meta/src/common/src/SerPort.cpp
new file mode 100644
index 0000000..eaf952f
--- /dev/null
+++ b/src/devtools/meta/src/common/src/SerPort.cpp
@@ -0,0 +1,856 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <termios.h> 
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#ifdef IS_SUPPORT_SP
+#include <cutils/properties.h>
+extern "C" {
+#include "hardware/ccci_intf.h"
+}
+#endif
+
+#include <sys/time.h> 
+
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+#include "ccci_intf.h"
+#ifdef __cplusplus
+}
+#endif
+
+#include <linux/ioctl.h>
+#include <netinet/tcp.h>
+#include <sys/mman.h>
+#include <linux/netlink.h> //add for listen uevent from kernel space
+
+#include "SerPort.h"
+#include "LogDefine.h"
+#include "Context.h"
+
+static const int BACKLOG = 32;
+
+//////////////////////////////////////////////////////////////////////////
+CCCI::CCCI(const char *path)
+{
+	m_fd = open(path);
+}
+
+signed int CCCI::open(const char *path)
+{
+	int retry = 100;
+	signed int fd = NULL_FILE_DESCRIPTOR;
+	
+	while(fd == NULL_FILE_DESCRIPTOR && retry != 0)
+	{
+		fd = ::open(path, O_RDWR|O_NOCTTY|O_NONBLOCK);
+	    META_LOG("[Meta]Open modem. m_fd = %d", fd);
+	    if (fd != NULL_FILE_DESCRIPTOR)
+	    {
+		    META_LOG("[Meta] Open modem port:(%s) success.", path);
+			break;
+	    }
+	    else
+	    {
+		    META_LOG("[Meta] Open modem port:(%s) fail. errno = %d", path, errno);
+			usleep(100*1000);
+			retry--;
+	    }
+	}
+	
+	return fd;
+}
+
+signed int CCCI::read(unsigned char *buf, unsigned int len)
+{
+	int tmpLen = 0;
+	while(1)
+	{
+		tmpLen = ::read(m_fd, buf, len);
+		if(tmpLen <= 0)
+		{
+            if(errno == EAGAIN)
+            {
+                usleep(10*1000);
+                continue;
+            }
+			//META_LOG("[META]read data error: fd = %d", m_fd);
+            return -1;
+		}
+		return tmpLen;
+	}
+	//META_LOG("[Meta] read data from device: len =%d , m_fd = %d", tmpLen, m_fd);
+}
+
+
+
+signed int CCCI::write(const unsigned char *p, unsigned int len)
+{
+	int bytes_written = -1;
+	int remain_size = len;
+	while(remain_size > 0)
+	{
+		bytes_written = ::write(m_fd, p, remain_size);
+		if (bytes_written < 0)
+		{
+            if(errno == 11)  //modem is busy,AP send data too fast and modem is not able to process it, need to retry.
+            {
+                META_LOG("[Meta] Write data to CCCI device failed, modem is busy, retry to write, m_fd=%d", m_fd);
+                usleep(50*1000);
+                continue;
+            }
+            META_LOG("[Meta] Write data to CCCI device failed, return %d, errno=%d, m_fd=%d", bytes_written, errno, m_fd);
+            return bytes_written;
+		}
+		else
+		{
+            META_LOG("[Meta] Write %d bytes to CCCI device: m_fd = %d, ", bytes_written, m_fd);
+		}
+		remain_size -= bytes_written;
+		p += bytes_written;
+	}
+	return (len - remain_size);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+CCB::CCB()
+{
+	init();
+}
+
+int CCB::init()
+{
+	while(0 == checkMdStatus())
+	{
+		META_LOG("[Meta] To check modem status");
+		usleep(100*1000);
+	}
+
+	META_LOG("[Meta] To init CCB");
+	// Initialize CCB related stuffs
+    m_fd = ccci_ccb_register(MD_SYS1, USR_SMEM_CCB_META);
+    if (m_fd <= 0) {
+        META_LOG("[Meta] ccb register failed, %d", m_fd);
+        return 0;
+    }
+
+    int ccb_ready = 0;
+    int retry = 0;
+    // check whether CCB state is ready
+    while ((ccb_ready = ccci_ccb_query_status()) != 0 && retry < META_CCB_INIT_MAX_RETRY) {
+        META_LOG("[Meta] ccb not ready, ret %d, retry %d", ccb_ready, retry);
+        usleep(100*1000);
+        retry++;
+    }
+    
+    if (retry == META_CCB_INIT_MAX_RETRY) {
+        META_LOG("[Meta] ccb not retry after %d retries, ret %d", META_CCB_INIT_MAX_RETRY, ccb_ready);
+        return 0;
+    }
+    META_LOG("[Meta] CCB is ready");
+
+	return m_fd;
+
+}
+
+signed int CCB::read(unsigned char* buf, unsigned int len)
+{
+	META_LOG("[Meta] CCB to read data from device");
+	
+	int bitmask = ccci_ccb_poll(META_CCB_POOL_BITMASK);
+	 if (bitmask < 0) {
+        META_LOG("[Meta] CCB ccci_ccb_poll error, ret %d", bitmask);
+        return -1;
+    }
+
+	unsigned char *ccb_data_buf = NULL;
+    unsigned int ccb_data_len = 0; 
+	len = 0;
+	int ret = ccci_ccb_read_get(META_CCB_BUFFER_ID, &ccb_data_buf, &ccb_data_len);
+
+	META_LOG("[Meta] CCB to read data, ret = %d, len = %d", ret, ccb_data_len);
+	
+	if ((ret < 0) || (ccb_data_len == 0))
+		return 0;
+
+	//add mux header
+	buf[0] = 0xAC;
+	buf[1] = 0xCA;
+	buf[2] = 0x00;
+	buf[3] = 0xFF;
+	buf[4] = (ccb_data_len & 0x000000ff);
+	buf[5] = (ccb_data_len >> 8) & 0x000000ff;
+
+	//fill raw data- ccb buffer need 8byte align.
+	ccb_data_copy(buf+META_CCB_MUX_HEADER_LEN, ccb_data_buf, ccb_data_len, ccb_data_buf);
+		
+	if ((ret = ccci_ccb_read_done(META_CCB_BUFFER_ID)) < 0) {
+            META_LOG("[Meta] CCB ccb_read_done failed, ret %d", ret);
+    }
+
+	return ccb_data_len+META_CCB_MUX_HEADER_LEN;
+}
+
+signed int CCB::write(const unsigned char* buf, unsigned int len)
+{
+	META_LOG("[Meta] CCB: to call ccci_ccb_write_alloc");
+		
+	unsigned char *write_buf = NULL;
+    int retry = 0;
+    while ((write_buf = ccci_ccb_write_alloc(META_CCB_BUFFER_ID)) == NULL && retry < META_CCB_TX_MAX_RETRY)
+	{
+        META_LOG("[Meta] CCB ccb_buffer_write: cannot alloc ccb buf, retry %d", retry);
+        usleep(10000);
+        retry++;
+    }
+
+	META_LOG("[Meta] CCB: end call ccci_ccb_write_alloc");
+	
+	if (retry >= META_CCB_TX_MAX_RETRY) {
+        META_LOG("[Meta] CCB ccb_buffer_write: cannot alloc ccb buf!");
+        return 0;
+    }
+
+	//ccb buffer need 8byte align.
+	ccb_data_copy(write_buf, (char*)buf, len, write_buf);
+
+	META_LOG("[Meta] CCB: to call ccci_ccb_write_done");
+	
+	int ret = ccci_ccb_write_done(META_CCB_BUFFER_ID, write_buf, len);
+    if (ret < 0)
+	{
+        META_LOG("[Meta] CCB ccb_buffer_write: ccb_write_done error, ret %d", ret);
+		return 0;
+    }
+
+	META_LOG("[Meta] CCB Write %d bytes to device: m_fd = %d, ", len, m_fd);
+	
+	return len;
+}
+
+void* CCB::ccb_memcpy(void *dst,void *src, size_t n) 
+{
+	long *p1 = (long*)dst;
+	long *p2 = (long*)src;
+    for (unsigned int idx = 0; idx < n/sizeof(long); idx++)
+        *p1++ = *p2++;
+	
+    return dst;
+}
+void CCB::ccb_data_copy(void* dst, void* src, unsigned int length, void* alignment_addr)
+{ 
+	unsigned int i=0,c=(0x8-(((long)(alignment_addr))&0x7)); 
+	
+	for(; i<c && i<(unsigned int)length; i++) 
+		*(((char *)(dst))+i) = *(((char *)(src))+i); 
+
+	c = (length-i)&(~0x7); 
+	ccb_memcpy(((char *)(dst))+i, ((char *)(src))+i, c); 
+
+	for(i+=c; i<(unsigned int)length; i++) 
+		*(((char *)(dst))+i) = *(((char *)(src))+i); 
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SerPort::SerPort(const char *path)
+{
+	m_fd = open(path);	
+}
+
+SerPort::SerPort()
+{
+}
+
+
+SerPort::~SerPort()
+{
+	if(m_fd > 0)
+	{
+		META_LOG("[Meta] Close serPort m_fd = %d", m_fd );
+	    ::close(m_fd);
+		m_fd = NULL_FILE_DESCRIPTOR;
+	}
+}
+
+signed int SerPort::open(const char *path)
+{
+/*	signed int fd = ::open(path, O_RDWR|O_NOCTTY);
+
+	META_LOG("[Meta] Open serPort. m_fd = %d", fd);
+
+	if (fd != NULL_FILE_DESCRIPTOR)
+	{
+		META_LOG("[Meta] Open serport:(%s) success.", path);
+		initTermIO(fd);
+	}
+	else
+	{
+		//META_LOG("[Meta] Open serport:(%s) fail, error code = %d", path, errno);		
+		META_LOG("[Meta] Open(%s) failed, reason=[%s]%d, fd=%d.",
+				path, strerror( errno ), errno, fd );
+	}
+*/	
+	signed int fd = NULL_FILE_DESCRIPTOR;
+
+	while(fd == NULL_FILE_DESCRIPTOR)
+	{
+	    fd = ::open(path, O_RDWR|O_NOCTTY);
+
+	    META_LOG("[Meta] Open serPort. m_fd = %d", fd);
+
+	    if (fd != NULL_FILE_DESCRIPTOR)
+	    {
+		    META_LOG("[Meta] Open serport:(%s) success.", path);
+		    initTermIO(fd);
+	    }
+	    else
+	    {
+		    //META_LOG("[Meta] Open serport:(%s) fail, error code = %d", path, errno);		
+		    META_LOG("[Meta] Open(%s) failed, reason=[%s]%d, fd=%d.",
+				path, strerror( errno ), errno, fd );
+	    }
+		sleep(1);
+	}
+	
+	return fd;
+}
+
+void SerPort::initTermIO(int portFd)
+{
+	struct termios termOptions;
+	if (fcntl(portFd, F_SETFL, 0) == -1)
+	{
+	    META_LOG("[Meta] initTermIO call fcntl fail");
+	}
+	// Get the current options:
+	tcgetattr(portFd, &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;
+
+	// 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(portFd,TCIFLUSH);//clear input buffer
+	termOptions.c_cc[VTIME] = (1 == getNormalModeTestFlag())? 10:100; /* inter-character timer unused */
+	termOptions.c_cc[VMIN] = 0; /* blocking read until 0 character arrives */
+
+
+	cfsetispeed(&termOptions, B921600);
+    cfsetospeed(&termOptions, B921600);
+	/*
+	* Set the new options for the port...
+	*/
+	tcsetattr(portFd, TCSANOW, &termOptions);
+}
+
+void SerPort::setSerPortExitFlag()
+{
+	//Do nothing here
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+UartPort::UartPort(const char *path)
+	: SerPort(path)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+UsbPort::UsbPort(const char *path)
+	: SerPort(path)
+{
+	m_devPath = strdup(path);
+	m_ueventSocket = NULL_FILE_DESCRIPTOR;
+	m_usbMutexFlag = 1;
+	m_usbConnected = getUsbState();
+	m_getUsbUvent = false;
+}
+
+UsbPort::~UsbPort()
+{
+	// it'll never get here
+	// so it doesn't make much sense...
+	free((char*)m_devPath);
+        m_devPath = NULL;
+	deinitUeventSocket();	
+}
+
+signed int UsbPort::read(unsigned char *buf, unsigned int len)
+{
+	// try to reopen USB if it was unplugged
+/*	if (NULL_FILE_DESCRIPTOR == m_fd && !update())
+	{
+		return -1;
+	}
+*/
+	
+	signed int ret = SerPort::read(buf, len);
+
+	// in case of error, see if USB is unplugged
+
+
+	// it doesn't make sense to do PnP check if 'read' succeeds
+
+	return ret;
+}
+
+signed int UsbPort::write(const unsigned char *buf, unsigned int len)
+{
+	// try to reopen USB if it was unplugged
+	if (NULL_FILE_DESCRIPTOR == m_fd)	//&& !update())
+	{
+		return -1;
+	}
+	signed int ret = SerPort::write(buf, len);
+
+	// it doesn't make sense to do PnP check if 'write' succeeds
+
+	return ret;
+}
+
+void UsbPort::close()
+{
+	if (m_fd != NULL_FILE_DESCRIPTOR)
+	{
+		META_LOG("[Meta] Close fd : %d", m_fd);
+		::close(m_fd);
+		m_fd = NULL_FILE_DESCRIPTOR;
+	}
+}
+void UsbPort::initUeventSocket()
+{
+	struct sockaddr_nl addr_sock;
+	int optval = 64 * 1024;
+
+	m_ueventSocket = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+	if (m_ueventSocket < 0)
+	{
+		META_LOG("[Meta] Unable to create uevent socket: %s", strerror(errno));
+		return;
+	}
+	META_LOG("[Meta] Create uevent socket success, m_ueventSocket: %d", m_ueventSocket);
+	if(setsockopt(m_ueventSocket, SOL_SOCKET, SO_RCVBUFFORCE, &optval, sizeof(optval)) <0)
+	{
+		META_LOG("[Meta] Unable to set uevent socket SO_RCVBUF option: %s(%d)", strerror(errno),errno);
+	}
+
+	memset(&addr_sock, 0, sizeof(addr_sock));
+	addr_sock.nl_family = AF_NETLINK;
+	addr_sock.nl_pid = getpid();
+	addr_sock.nl_groups = 0xffffffff;
+
+	if (bind(m_ueventSocket, (struct sockaddr *)&addr_sock, sizeof(addr_sock)) < 0)
+	{
+		META_LOG("[Meta] Failed to bind uevent socket: %s(%d)",strerror(errno), errno);
+		::close(m_ueventSocket);
+		m_ueventSocket = NULL_FILE_DESCRIPTOR;
+		return;
+	}
+	META_LOG("[Meta] Bind uevent socket success");
+}
+void UsbPort::deinitUeventSocket()
+{
+	if(NULL_FILE_DESCRIPTOR != m_ueventSocket)
+	{
+		::close(m_ueventSocket);
+		m_ueventSocket = NULL_FILE_DESCRIPTOR;
+	}
+}
+void UsbPort::handleUsbUevent(const char *buff, int len)
+{
+	const char *s = buff;
+
+	if(0 == strcmp(s, "change@/devices/virtual/android_usb/android0"))
+	{
+		m_getUsbUvent = true;
+		char state[32];
+		memset(state, 0, sizeof(state));
+		s += strlen(s) + 1;
+
+		while (*s)
+		{
+			META_LOG("[Meta] Handle uevents: %s", s);
+			if(!strncmp(s, "USB_STATE=", strlen("USB_STATE=")))
+			{
+				strncpy(state, s + strlen("USB_STATE="), sizeof(state)-1);
+				META_LOG("[Meta] uevents: USB_STATE=%s", state);
+				break;
+			}
+			s += strlen(s) + 1;
+			if (s - buff >= len)
+				break;
+		}
+
+		if (!strncmp(state, "CONFIGURED", sizeof("CONFIGURED")))
+		{
+			META_LOG("[Meta] uevents: USB connected");
+			m_usbConnected = 1;
+		}
+		else
+		{
+			META_LOG("[Meta] uevents: USB disconnected");
+			m_usbConnected = 0;
+		}
+	}
+}
+
+#define UEVENT_BUFFER_SIZE 2048
+int UsbPort::isReady()
+{
+	if(m_ueventSocket < 0)
+		initUeventSocket();
+
+	struct pollfd fds;
+	static char uevent_desc[UEVENT_BUFFER_SIZE * 2];
+
+	fds.fd = m_ueventSocket;
+	fds.events = POLLIN;
+	fds.revents = 0;
+	int ret = poll(&fds, 1, -1);
+	if (ret > 0 && (fds.revents & POLLIN))
+	{
+		/* keep last 2 zeroes to ensure double 0 termination */
+		int count = recv(m_ueventSocket, uevent_desc, sizeof(uevent_desc) - 2, 0);
+		if (count > 0) 
+		{
+			//META_LOG("[Meta][DEBUG] uevent_desc: %s, count: %d ", uevent_desc, count);
+			handleUsbUevent(uevent_desc, count);
+		}
+	}
+	return m_usbConnected;
+}
+
+int UsbPort::getUsbState() const
+{
+	int type = 0;
+	char buf[21];
+	int bytes_read = 0;
+	int res = 0;
+	int fd = ::open("/sys/class/android_usb/android0/state", O_RDONLY);
+	if (fd != -1)
+	{
+		META_LOG("[Meta] Query usb state OK.");
+		memset(buf, 0, 21);
+		while (bytes_read < 10)
+		{
+			res = ::read(fd, buf + bytes_read, 10);
+			if (res > 0)
+				bytes_read += res;
+			else
+				break;
+		}
+		::close(fd);
+		buf[bytes_read] = '\0';
+		type = strcmp(buf,"CONFIGURED");
+
+		if(0 == type)
+		{
+			META_LOG("[Meta] USB is ready.");
+		}
+		else
+		{
+			META_LOG("[Meta] USB is not ready.");
+		}
+	}
+	else
+	{
+		META_LOG("[Meta] Failed to open:/sys/class/android_usb/android0/state");
+	}
+
+	return (type == 0);
+}
+
+void UsbPort::update()
+{
+	if (!isReady())
+	{
+		if(m_usbMutexFlag && m_getUsbUvent)
+		{
+			close();
+			m_usbMutexFlag = 0;
+		}
+	}
+	else
+	{
+		if(!m_usbMutexFlag)
+		{
+			sleep(1);
+			m_fd = open(m_devPath);
+
+			if(m_fd != NULL_FILE_DESCRIPTOR)
+			{
+				m_usbMutexFlag = 1;
+			}
+		}
+	}
+
+}
+
+MetaSocket::MetaSocket(const char *path)
+{
+	m_fd = open(path);
+	m_nClientFd = NULL_FILE_DESCRIPTOR;
+	m_bConnect = false;
+    m_nSocketConnectExitFlag = 0;
+}
+
+MetaSocket::~MetaSocket()
+{
+    close();
+}
+
+signed int MetaSocket::open(const char *path)
+{
+    int sock_opt = 1;
+    int enable = 1;
+    path = NULL;
+    int fd = NULL_FILE_DESCRIPTOR;
+    char serverIP[16] = {0};
+    int nPort = 0;
+	
+    if(1 == getNormalModeTestFlag())
+    {
+		WIFI_PARA wifi_para = getWifiPara();
+		strncpy(serverIP, wifi_para.ip_addr, sizeof(serverIP)-1);
+		nPort = wifi_para.port;
+		META_LOG("[Meta] Socket get server IP address:%s Port:%d", serverIP, nPort);
+    }
+
+    //Create socket
+    if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+    {
+        META_LOG("[META] Socket created fail. errno=%d", errno);
+		return -1;
+    }
+
+    META_LOG("[META] Socket created success fd:%d",fd);
+
+    // SET SOCKET REUSE Address
+    if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&sock_opt, sizeof(sock_opt)) < 0)
+    {
+        META_LOG("[META] Socket setsockopt failed. errno=%d", errno);
+		::close(fd);
+        fd = NULL_FILE_DESCRIPTOR;
+		return -1;
+    }
+    // SET SOCKET RECEIVE TIMEOUT
+    // Set socket to nonblock to avoid release problem
+    struct timeval timeout = {1,0};
+    if(setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeval)) < 0)
+    {
+        META_LOG("[META] Socket set receive timeout failed. errno=%d", errno);
+		::close(fd);
+        fd = NULL_FILE_DESCRIPTOR;
+		return -1;
+    }
+    //SET TCP_NODELAY
+    if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&enable, sizeof(enable)) < 0)
+    {
+        META_LOG("[META] Socket setsockopt TCP_NODELAY failed. errno=%d", errno);
+    }
+    //Prepare the sockaddr_in structure
+    struct sockaddr_in* serverAddr = new struct sockaddr_in;
+    if(serverAddr == NULL)
+    {
+        META_LOG("[Meta] Socket new server addr failed. errno=%d", errno);
+        ::close(fd);
+        fd = NULL_FILE_DESCRIPTOR;
+        return -1;
+    }
+	else
+	{
+		memset(serverAddr,0,sizeof(sockaddr_in));
+	}
+
+    serverAddr->sin_family = AF_INET;
+    serverAddr->sin_port = htons(nPort);
+    serverAddr->sin_addr.s_addr = inet_addr(serverIP);
+
+    //Bind
+    if(bind(fd,(struct sockaddr*)serverAddr, sizeof(struct sockaddr)) < 0)
+    {
+        META_LOG("[META] Socket bind failed. errno=%d", errno);
+        goto errout;
+    }
+    META_LOG("[META] Socket bind done");
+
+    //Listen
+    if (listen(fd, BACKLOG) == -1)
+    {
+        META_LOG("[META] Socket Failed to listen Socket port, errno=%d", errno);
+        goto errout;
+	}
+	META_LOG("[META] Socket listen done");
+
+	delete serverAddr;
+	serverAddr = NULL;
+	return fd;
+
+errout:
+	delete serverAddr;
+	serverAddr = NULL;
+	::close(fd);
+	fd = NULL_FILE_DESCRIPTOR;
+	return fd;
+}
+
+signed int MetaSocket::read(unsigned char *buf, unsigned int len)
+{
+	if(!m_bConnect)
+	{
+	    if(connect() == -1)
+	    {
+	        META_LOG("[Meta] Socket::read connect fail");
+			return -1;
+	    }
+	}
+    
+    if(m_nClientFd < 0)
+    {
+        return -1;
+    }
+
+	//META_LOG("[META] Socket enter read, connect success");
+	int tmpLen = 0;
+	tmpLen = recv(m_nClientFd, buf, len, 0);
+	if(tmpLen == 0)
+	{
+	    META_LOG("[META] Socket recv data len is 0, network interrupt, need to reconnect - m_nClientFd = %d, len = %d", m_nClientFd, tmpLen);
+	    disconnect();
+	}
+	else
+	{
+	    META_LOG("[META] Socket recv data from socket client - m_nClientFd = %d, len = %d", m_nClientFd, tmpLen);
+	}
+	return tmpLen;
+}
+
+signed int MetaSocket::write(const unsigned char *buf, unsigned int len)
+{
+    if (NULL_FILE_DESCRIPTOR == m_nClientFd)
+	{
+		return -1;
+	}
+
+	int bytes_written = -1;
+	int remain_size = len;
+	pthread_mutex_lock(&(Device::m_wMutex));
+	//META_LOG("[Meta] Socket enter write");
+	while(remain_size > 0)
+    {
+		bytes_written = send(m_nClientFd, buf, remain_size, 0);
+		if (bytes_written < 0)
+		{
+		    META_LOG("[Meta] Socket write data by socket failed, return %d, errno=%d, m_nClientFd=%d", bytes_written, errno, m_nClientFd);
+			pthread_mutex_unlock(&(Device::m_wMutex));
+			return bytes_written;
+		}
+		else
+		{
+			META_LOG("[Meta] Socket write %d bytes by socket: m_nClientFd = %d, ", bytes_written, m_nClientFd);
+		}
+		remain_size -= bytes_written;
+		buf += bytes_written;
+	}
+    pthread_mutex_unlock(&(Device::m_wMutex));
+    return (len - remain_size);
+
+}
+
+void MetaSocket::close()
+{
+    disconnect();
+	if (m_fd != NULL_FILE_DESCRIPTOR)
+	{
+		::close(m_fd);
+		m_fd = NULL_FILE_DESCRIPTOR;
+	}
+}
+
+signed int MetaSocket::connect()
+{
+    if (NULL_FILE_DESCRIPTOR == m_fd)
+	{
+		return -1;
+	}
+
+	if (m_bConnect)
+	{
+	    return 0;
+	}
+
+	struct sockaddr_in* clientAddr = new struct sockaddr_in;
+	if (clientAddr == NULL)
+	{
+	    META_LOG("[Meta] Socket new client addr failed. errno=%d", errno);
+		m_bConnect = false;
+		return -1;
+	}
+	memset(clientAddr,0,sizeof(struct sockaddr_in));
+	socklen_t alen = sizeof(struct sockaddr);
+	
+    META_LOG("[Meta] Socket connect, accept the connection: m_nSocketConnectExitFlag = %d",m_nSocketConnectExitFlag);
+	while(m_nSocketConnectExitFlag == 0)
+	{    
+	    if ((m_nClientFd = accept(m_fd, (struct sockaddr*)clientAddr, &alen)) == -1)
+	    {
+			if(errno == EAGAIN || errno == EINVAL)
+			{
+				usleep(200*1000);
+		        continue;
+			}
+			META_LOG("Socket accept error, errno=%d", errno);
+			
+			m_bConnect = false;
+
+			delete clientAddr;
+			clientAddr = NULL;
+			return -1;
+	    }
+	    else
+	    {
+			m_bConnect = true;
+		    META_LOG("[Meta] Socket connect, Received a connection from %s, m_nClientFd = %d",
+				(char*)inet_ntoa(clientAddr->sin_addr), m_nClientFd);
+			delete clientAddr;
+			clientAddr = NULL;
+			return 0;
+	    }
+	}
+	delete clientAddr;
+	clientAddr = NULL;
+    return -1;
+}
+
+void MetaSocket::disconnect()
+{
+    if (m_bConnect)
+    {
+        if (m_nClientFd != NULL_FILE_DESCRIPTOR)
+	    {
+	        m_bConnect = false;
+	        ::close(m_nClientFd);
+	        m_nClientFd = NULL_FILE_DESCRIPTOR;
+		}
+    }
+}
+
+void MetaSocket::setSerPortExitFlag()
+{
+    m_nSocketConnectExitFlag = 1;
+}
+
diff --git a/src/devtools/meta/src/common/src/UsbRxWatcher.cpp b/src/devtools/meta/src/common/src/UsbRxWatcher.cpp
new file mode 100644
index 0000000..9d688c6
--- /dev/null
+++ b/src/devtools/meta/src/common/src/UsbRxWatcher.cpp
@@ -0,0 +1,1013 @@
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
+#include "LogDefine.h"
+#include "UsbRxWatcher.h"
+#include "Modem.h"
+#include "Context.h"
+#include "PortInterface.h"
+#include "FtModule.h"
+#include "snappy-c.h"
+
+
+
+
+typedef struct _MetaFrame
+{
+	unsigned char start;
+	unsigned char frmLen[2];
+	unsigned char frmType;
+	unsigned char localLen[2];
+	unsigned char peerLen[2];
+	unsigned char token[2];
+	unsigned char reqId[2];
+
+}MetaFrame;
+
+
+UsbRxWatcher::UsbRxWatcher(void)
+{
+	m_checksum = STX_OCTET;
+	m_uFrameLength = 0;
+	m_frame_buf_len = 0;
+	m_flow_ctrl_flag = 0;
+	m_cTstFrameState = RS232_FRAME_STX;
+	m_cOldTstFrameState = RS232_FRAME_STX;
+	
+	nRemainLen = 0;
+	m_nStartByteLen = 0;
+	m_frm_len_byte = 2;
+	m_md_index = 0;
+	memset(&m_sRs232Frame, 0, sizeof(m_sRs232Frame));
+
+}
+
+UsbRxWatcher::~UsbRxWatcher(void)
+{
+	if (m_frame_buf_len > 0)
+	{
+		free(m_sRs232Frame.buf_ptr);
+	}
+
+	//delete ti
+}
+
+signed int UsbRxWatcher::onReceived(
+							 unsigned char *buf,
+							 unsigned int len)
+{
+
+	META_LOG("[Meta] Receive data from USB, len = %d",len);
+	unsigned int activeATModemId = 0;
+	activeATModemId = getActiveATModem();
+	
+	dumpDataInHexString(buf,len,16);
+
+	
+	//modem mode = normal, boot mode = meta mode
+	if((getMDMode()==1) && (META_BOOT == getBootMode()))
+	{
+		Modem *p = getModem(activeATModemId);
+
+		char * temp =NULL;
+
+		
+		if(p!=NULL)
+		{
+			dumpData(buf,len);
+			temp = strstr((char *)buf,"AT+REBOOTMD");
+			if(temp == NULL)
+			{
+				temp = strstr((char *)buf,"AT+EAMDIMG");
+				if(temp == NULL)
+				{
+				    p->exec(buf,len);
+				}
+				else
+				{
+					//META_LOG("[Meta] [DEBUG] Got AT+EAMDIMG");
+					int bDataDevice = FALSE;
+					int fd = -1;
+					FtModModemInfo *pRebootMD = new FtModModemInfo;
+					SerPort *pPort = getSerPort();
+					char ack_buf[64] = {0};
+					fd = getIOCPort(0,bDataDevice);
+					int modem_type = -1;
+					temp += strlen("AT+EAMDIMG=");
+					int first_command = atoi(temp);
+					//META_LOG("[Meta] [DEBUG] first command = %d", first_command);
+					if(0 == first_command) //Get
+					{
+						temp+=2;
+						int second_command = atoi(temp);
+						//META_LOG("[Meta] [DEBUG] second command = %d", second_command);
+						if(0 == second_command) //Get modem type
+						{
+							META_LOG("[Meta] get modem type");
+					        int result = pRebootMD->getModemType(&modem_type,fd);
+							if(result == 0)
+							{
+								META_LOG("[Meta][FT] Get modem type: %d success", modem_type);
+							}
+							else
+							{
+								META_LOG("[Meta][FT] Get modem type fail");
+							}
+							sprintf(ack_buf,"\r\n%d\r\n",modem_type);
+						}
+						else if(1 == second_command)
+						{
+							int modem_state = 0;
+							META_LOG("[Meta] get modem state");
+					        int result = pRebootMD->getModemState(&modem_state,fd);
+							if(result == 0)
+							{
+								META_LOG("[Meta][FT] Get modem state: %d success", modem_state);
+							}
+							else
+							{
+								META_LOG("[Meta][FT] Get modem state fail");
+							}
+							sprintf(ack_buf,"\r\n%d\r\n",modem_state);
+						}
+						pPort->write((unsigned char *)ack_buf, strlen(ack_buf));
+					}
+					else if(1 == first_command) //Set Modem Type
+					{
+						temp+=2;
+						modem_type = atoi(temp);
+					    META_LOG("[Meta] set modem type= %d",modem_type);
+
+						setActiveATModem(0);
+					    META_LOG("Destory modem thread and close modem handle");
+	                    destroyAllModemThread();
+						int result = pRebootMD->setModemType(modem_type,fd);
+					    if(result == 0)
+						{
+							sleep(5);
+							META_LOG("[Meta][FT] Set modem type to %d success", modem_type);
+							sprintf(ack_buf,"%s","\r\nPASS\r\n");
+						}
+						else
+						{
+							META_LOG("[Meta][FT] Set modem type to %d fail", modem_type);
+							sprintf(ack_buf,"%s","\r\nFAIL\r\n");
+						}
+						createAllModemThread();
+						pPort->write((unsigned char *)ack_buf, strlen(ack_buf));
+					}
+
+					if(bDataDevice == FALSE)
+					{
+						if(fd != -1)
+						{
+							close(fd);
+							META_LOG("[Meta][FT]Close fd");
+							fd = -1;
+						}
+					}
+					if(pRebootMD!=NULL)
+					    delete pRebootMD;
+				}
+
+			}
+			else
+			{
+				temp+=strlen("AT+REBOOTMD=");
+				int nModemIndex = atoi(temp);
+				META_LOG("[Meta] nModemIndex = %d",nModemIndex);
+				temp+=2;
+				int modem_mode = atoi(temp);
+				META_LOG("[Meta] modem_mode = %d",modem_mode);
+				FtModModemInfo *pRebootMD = new FtModModemInfo;
+				FT_MODEM_REQ req; 
+				FT_MODEM_CNF ft_cnf;
+				int bDataDevice = FALSE;
+				int fd = -1;
+				memset(&req, 0, sizeof(FT_MODEM_REQ));
+				memset(&ft_cnf, 0, sizeof(FT_MODEM_CNF));
+				fd = getIOCPort(nModemIndex,bDataDevice);
+				req.cmd.reboot_modem_req.modem_index = nModemIndex;
+				req.cmd.reboot_modem_req.mode = modem_mode;
+				pRebootMD->rebootModem(&req, ft_cnf,fd);
+				sleep(5);
+				memset(&req, 0, sizeof(FT_MODEM_REQ));
+				memset(&ft_cnf, 0, sizeof(FT_MODEM_CNF));
+				int result = pRebootMD->getModemMode(&req, ft_cnf,fd);
+				if(bDataDevice == FALSE)
+				{
+	     			if(fd != -1)
+		 			{
+		     			close(fd);
+						META_LOG("[Meta][FT]Close fd");
+						fd = -1;
+	     			}
+				}
+
+				//create modem thread and open modem handle
+				if(result == 0)
+				{
+					setMDMode(modem_mode);
+					createAllModemThread();	
+				}
+
+				if(pRebootMD!=NULL)
+					delete pRebootMD;
+			}
+		}
+		else
+		{
+			META_LOG("[Meta] activeATModemId = %d is invalid",activeATModemId);	
+		}
+		return 0;
+	}
+	META_LOG("[Meta] nRemainLen = %d", nRemainLen);
+	
+	unsigned char * data = NULL;
+	unsigned short u16Length = 0;
+
+	if(nRemainLen > 0)
+	{
+		bcopy(buf, szRemainBuf+nRemainLen, len);  //Fix for memcpy do not support src/dst overlap case
+		data = szRemainBuf;
+		len = nRemainLen + len;
+	}
+	else
+	{
+		data = buf;
+	}
+
+	Frame *pFrm = decode(data, len, u16Length);
+
+	if (NULL != pFrm)
+	{
+		if(pFrm->getIsValid() == 1)
+		{
+			pFrm->exec();
+			if(len > u16Length)
+			{
+				bcopy(data+u16Length, szRemainBuf, len-u16Length);  //Fix for memcpy do not support src/dst overlap case
+				nRemainLen = 0;
+				onReceived(szRemainBuf, len-u16Length);
+			}
+			else if(len == u16Length)
+			{
+				nRemainLen = 0;
+			}
+		}
+		else
+		{
+			META_LOG("[Meta] Unsupport request id");
+			if(len == u16Length)
+			{
+				nRemainLen = 0;
+				META_LOG("[Meta] discard the whole frame");
+			}
+			else if(len > u16Length)
+			{
+				bcopy(data+u16Length, szRemainBuf, len-u16Length);	//Fix for memcpy do not support src/dst overlap case
+				nRemainLen = len-u16Length;
+			}
+		}
+		delete pFrm;
+	}
+	else
+	{
+		META_LOG("[Meta] pFrm is NULL");
+		if(len == u16Length)
+		{
+			nRemainLen = len;
+			bcopy(data, szRemainBuf, len);  //Fix for memcpy do not support src/dst overlap case 
+			META_LOG("[Meta] Data is incomplete, received = %d",len);
+		}
+		else
+		{
+			META_LOG("[Meta] Discard incomplete frame %d bytes",u16Length);
+			nRemainLen = 0;
+			onReceived(data+(u16Length-1), len-(u16Length-1));
+		}
+	}
+	
+	return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+unsigned char *UsbRxWatcher::reallocFrameBuf(unsigned int len)
+{
+	unsigned char *buf_ptr = m_sRs232Frame.buf_ptr;
+
+	META_LOG("[Meta] (reallocFrameBuf) len = %d, m_frame_buf_len=%d",len, m_frame_buf_len);
+
+	if (buf_ptr != NULL)
+	{
+		free(buf_ptr);
+	}
+
+	buf_ptr = (unsigned char *)malloc(len);
+	memset(buf_ptr,'\0',len);
+	m_frame_buf_len = len;
+
+	return buf_ptr;
+}
+
+unsigned int UsbRxWatcher::flowControl(void *pdata, unsigned int len)
+{
+	/* if the data is 0x77 and 0x01, escape to 0x11
+	if the data is 0x77 and 0x02, escape to 0x13
+	if the data is 0x77 and 0x77, escape to 0x77
+	*/
+	if (getComType() == META_UART_COM)
+	{
+		unsigned int idx = 0;
+		unsigned int newLen = 0;
+		unsigned char *pTempBuf = (unsigned char*)pdata;
+		unsigned char *pDestBuf = pTempBuf;
+
+		while (idx != len)
+		{
+			++ idx;
+
+			if (idx == len)
+			{
+				META_LOG("[Meta] root cause1:cnt:%d",idx);
+				if(*pTempBuf ==0x77)
+				{
+					m_flow_ctrl_flag = 1;
+					break;
+				}
+			}
+
+			if (*pTempBuf ==0x77 || m_flow_ctrl_flag != 0)
+			{
+				if (m_flow_ctrl_flag != 0)
+				{
+					m_flow_ctrl_flag = 0;
+				}
+				else
+				{
+					++ idx;
+					++ pTempBuf;
+				}
+
+				if (*pTempBuf ==0x01)
+				{
+					*pDestBuf = 0x11;
+				}
+				else if (*pTempBuf ==0x02 )
+				{
+					*pDestBuf = 0x13;
+				}
+				else if (*pTempBuf ==0x03 )
+				{
+					*pDestBuf = 0x77;
+				}
+				else
+				{
+					META_LOG("[Meta] root cause2: cnt:%d",idx);
+					break;
+				}
+			}
+			else
+			{
+				*pDestBuf = *pTempBuf;
+			}
+
+			++ newLen;
+			++ pTempBuf;
+			++ pDestBuf;
+		}
+		len = newLen;
+	}
+	return len;
+}
+
+Frame *UsbRxWatcher::decodeMDFrame(void *pdata, unsigned int len,unsigned char frmType,unsigned short &u16Length)
+{
+	assert(pdata != NULL);
+
+
+	int bFrm = false;
+	unsigned char * local_ptr = (unsigned char*)pdata + u16Length;
+	unsigned char	ch;
+	int newLen = m_uFrameLength;
+		
+	while(u16Length != len)
+	{
+		++u16Length;
+		ch = *local_ptr;
+
+		if(ch == MUX_KEY_WORD)
+		{
+			if(u16Length == len)
+				return NULL;
+			
+			++u16Length;
+			++local_ptr;
+			ch = *local_ptr;
+			if((ch == MUX_KEY_WORD) || (ch == 0x01))
+				newLen ++;
+		}
+
+		if(getComType() == META_UART_COM && ch == 0x77)
+		{
+			if(u16Length == len)
+				return NULL;
+			
+			++u16Length;
+			++local_ptr;
+			ch = *local_ptr;
+			if((ch == 0x01) || (ch == 0x02) || (ch == 0x03))
+				newLen ++;
+		}
+
+		if(ch == STX_OCTET)
+		{
+			META_LOG("[Meta] New modem frame header");
+			bFrm = true;
+			u16Length--;
+			
+		}
+		else if(u16Length == newLen + 3 + m_frm_len_byte + m_nStartByteLen)   // 3 + m_frm_len_byte = start byte  + data type + checksum + data len(m_frm_len_byte)
+		{
+			
+			META_LOG("[Meta] New modem frame tail, m_nStartByteLen:%d",m_nStartByteLen);
+			bFrm = true;
+		}
+
+		if(bFrm)
+		{
+			len = flowControl(pdata, u16Length);
+			return sendMdTask((unsigned char*)pdata + m_nStartByteLen, len - m_nStartByteLen, frmType);
+		}
+		
+		++local_ptr;
+	}
+
+	return NULL;			
+}
+
+Frame * UsbRxWatcher::sendMdTask(void *pdata, unsigned int len,unsigned char frmType)
+{
+	assert(pdata != NULL);
+	Frame * pFrame = NULL;
+
+	unsigned char mdId = 0;
+	unsigned int compress = 0;
+	void *mdData = pdata;
+	
+	if ((frmType == RS232_INJECT_PRIMITIVE_OCTET)|| (frmType == RS232_COMMAND_TYPE_OCTET))//0x64 0x63
+	{
+		mdId = 0;
+		//TODO
+	}
+	else if(frmType >= RS232_INJECT_PRIMITIVE_OCTETMODEM2 && frmType <= RS232_INJECT_PRIMITIVE_OCTETMODEM2_END)//0xA0 ~ A7
+	{
+		mdId = m_md_index;	
+	}
+	else if(frmType >= RS232_COMMAND_TYPE_MD2_MEMORY_DUMP && frmType<= RS232_COMMAND_TYPE_MD2_MEMORY_DUMP_END)//0xC0 ~ 0xC7
+	{
+		mdId = m_md_index;
+	}
+	else if(frmType >= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_START && frmType <= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_END)//0xD0 ~ 0xD7
+	{
+		mdId = m_md_index;
+	}
+
+#ifdef MTK_META_COMPRESS_SUPPORT
+	else if(frmType >= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_COMP_START && frmType <= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_COMP_END)//0xF0 ~ 0xF7
+	{
+		mdId = m_md_index;
+		compress = 1;
+	}
+#endif
+
+	CmdTarget *md = getModem(mdId);
+
+	META_LOG("[Meta] Send data to modem[%d], data len:%d", mdId,len);
+	
+	dumpDataInHexString((const unsigned char *)pdata,len,16);
+	
+
+#ifdef MTK_META_COMPRESS_SUPPORT
+
+//	char uncompressed[FrameMaxSize] = {0};
+    int uncompressed_len = FrameMaxSize;
+		
+	if(GetDataCompressStatus() && compress)
+    {
+    	memset(m_uncompressed, 0, FrameMaxSize);
+		if (true != uncompress(pdata, len, &m_uncompressed[0], &uncompressed_len))
+		{
+			META_LOG("[Meta] error: uncompress failed\n");
+        	return NULL;
+		}
+
+		META_LOG("[Meta] uncompressed frame[%d]\n", uncompressed_len);
+		dumpDataInHexString((const unsigned char *)m_uncompressed, uncompressed_len, 16);
+
+//		pdata = uncompressed;
+		mdData = &m_uncompressed[0];
+		len = uncompressed_len;
+	}
+	
+#endif	
+
+	if (NULL != md)
+	{
+		META_RX_DATA metaRxData =
+		{
+			MD_FRAME, (unsigned char*)mdData, static_cast<unsigned short>(len), 0
+		};
+
+		pFrame = new Frame(metaRxData, md);
+	}
+	else
+	{
+		META_LOG("[Meta] can not get modem object");
+		pFrame = new Frame();
+	}
+	return pFrame;
+}
+
+Frame *UsbRxWatcher::sendFtTask()
+{
+	/* send data FT task */
+	Frame * pFrame = NULL;
+ 
+	const unsigned short localLen = m_sRs232Frame.inject_prim.local_len;
+	const unsigned short peerLen  = m_sRs232Frame.inject_prim.peer_len;
+
+	META_LOG("[Meta] Send data to FT module. localLen = %d, peerLen = %d", localLen, peerLen);
+
+	unsigned char *localBuf = m_sRs232Frame.buf_ptr;
+
+	const FT_H *hdr = (FT_H*)localBuf;
+	META_LOG("[Meta] token = %d, id = %d", hdr->token, hdr->id);
+
+	CmdTarget *mod = getModule(hdr->id);
+
+	if (mod != NULL)
+	{
+		mod->setToken( hdr->token);
+		META_RX_DATA metaRxData =
+		{
+			AP_FRAME,
+			localBuf,
+			localLen,
+			peerLen
+		};
+
+		pFrame = new Frame(metaRxData, mod);
+	}
+	else
+	{
+		pFrame = new Frame();
+	}
+
+	return pFrame;
+}
+
+Frame *UsbRxWatcher::decodeAPFrame( unsigned int input_len,unsigned char * src,unsigned short &u16Length)
+{
+	unsigned char * local_ptr = src;
+	unsigned char	ch;
+	
+	while(u16Length!=input_len)//request frame length don't include checksum
+	{
+		++ u16Length;
+		ch = *local_ptr;
+
+		if ( ch == STX_OCTET )
+		{
+			META_LOG("[Meta] New APP frame header");
+			return NULL;
+		}
+		
+		if (1 == checkEscape(ch))
+		{	
+			if(u16Length == input_len)
+				return NULL;
+			
+			ch = *(++local_ptr);
+			if(transferFrame(&ch) != 1)
+			{
+				ch = *(--local_ptr);
+			}
+			else
+			{
+				++ u16Length;
+			}
+		}
+		
+		if (m_cTstFrameState == RS232_FRAME_AP_INJECT_PIRIMITIVE_HEADER)/* fill data to tst_primitive_header_struct */
+		{			
+			++ m_sRs232Frame.received_prig_header_length;
+			*(m_sRs232Frame.header_ptr++) = ch;
+
+			if (m_sRs232Frame.received_prig_header_length == sizeof(PRIM_HEADER))
+			{
+				if (m_sRs232Frame.inject_prim.local_len != 0)
+				{
+					m_cTstFrameState = RS232_FRAME_AP_PRIM_LOCAL_PARA_DATA;
+
+					META_LOG("[Meta] RS232_FRAME_AP_INJECT_PIRIMITIVE_HEADER: LOCAL len: %d m_peer_len : %d ",
+						m_sRs232Frame.inject_prim.local_len, m_sRs232Frame.inject_prim.peer_len);
+
+					m_sRs232Frame.buf_ptr = reallocFrameBuf(m_sRs232Frame.inject_prim.local_len + m_sRs232Frame.inject_prim.peer_len+1);
+				}
+			}
+		}			
+		else if(m_cTstFrameState == RS232_FRAME_AP_PRIM_LOCAL_PARA_DATA)/* fill the primitive body to local parameter buffer and peer buffer */
+		{
+			if (m_sRs232Frame.buf_ptr != NULL)
+			{
+				*(m_sRs232Frame.buf_ptr + m_sRs232Frame.received_buf_para_length) = ch;
+			}
+
+			++ m_sRs232Frame.received_buf_para_length;
+
+			if ((m_sRs232Frame.inject_prim.local_len + m_sRs232Frame.inject_prim.peer_len) == m_sRs232Frame.received_buf_para_length)
+			{
+				m_cTstFrameState = RS232_FRAME_CHECKSUM;
+			}
+		}
+		else if(m_cTstFrameState == RS232_FRAME_CHECKSUM)
+		{	
+			META_LOG("[Meta] parse state: RS232_FRAME_CHECKSUM: checksum: %d, ch: %d",m_checksum, ch);
+			m_cTstFrameState = RS232_FRAME_STX;
+			if(m_checksum != ch)
+			{
+				META_LOG("[Meta] Checksum error!");
+				return (new Frame());
+			}
+					
+			m_sRs232Frame.received_buf_para_length = 0;
+			m_checksum = STX_OCTET;
+			META_LOG("[Meta] (decodeAPFrame) u16Length = %d", u16Length);
+			return sendFtTask();
+		}
+		
+		++local_ptr;	
+		m_checksum ^= ch; 
+	}
+	return NULL;
+}
+
+
+Frame *UsbRxWatcher::decode(
+	unsigned char *buf_ptr,
+	unsigned int input_len,
+	unsigned short &u16Length)
+{
+	unsigned char	*src=buf_ptr;
+	unsigned char	ch;
+	unsigned int discard_word=0;
+	
+	//META_LOG("[Meta](UsbRxWatcher) To decode data");
+	dumpDataInHexString(buf_ptr,input_len,16);  
+
+	while (u16Length != input_len)
+	{
+		ch = *src;
+		++ u16Length;
+
+		if ( ch == STX_OCTET )
+		{
+			m_cTstFrameState = RS232_FRAME_LENHI;
+			++ src;
+			m_uFrameLength = 0;
+			m_frm_len_byte = 2;
+			m_checksum = STX_OCTET;
+			m_nStartByteLen = u16Length - 1;
+
+			if (discard_word > 0)
+			{
+				META_LOG("[Meta] Discards %d chars.", discard_word);
+				discard_word = 0;
+			}
+			continue;
+		}
+		else if(m_cTstFrameState == RS232_FRAME_STX)
+		{
+			++ discard_word;
+			++ src;
+			continue;
+		}
+		else
+		{
+			if (1 == checkEscape(ch))
+			{	
+				ch = *(++src);
+				if(transferFrame(&ch) != 1)
+				{
+					ch = *(--src);
+				}
+				else
+				{
+					if((m_cTstFrameState == RS232_FRAME_LENHI) || (m_cTstFrameState == RS232_FRAME_LENLO))
+					{
+						m_frm_len_byte += 1;
+					}
+					++ u16Length;
+				}
+			}
+		}
+
+		switch (m_cTstFrameState)
+		{
+		
+		case RS232_FRAME_LENHI:		
+			m_uFrameLength = ch << 8;
+			m_cTstFrameState = RS232_FRAME_LENLO;
+			//META_LOG("[Meta] parse state: RS232_FRAME_LENHI: %x", ch);
+			break;
+
+		case RS232_FRAME_LENLO:
+			m_uFrameLength += ch;
+			m_cTstFrameState = RS232_FRAME_TYPE;
+			META_LOG("[Meta] parse state: RS232_FRAME_LENLO: %x, total: %d",ch, m_uFrameLength);
+			if ((m_uFrameLength+5) > FRAME_MAX_LEN)
+			{
+				META_LOG("[Meta] parse state: Error: Frame size is %d+5, exceeds limit of %d.",m_uFrameLength, FRAME_MAX_LEN);
+				return NULL;
+			}
+			break;
+
+		case RS232_FRAME_TYPE:	
+			m_checksum ^= ch; 
+			//META_LOG("[Meta] (decode) u16Length = %d",u16Length);
+			return dispatchFrame(ch, buf_ptr, input_len, src,u16Length);			
+			break;
+		}
+
+		m_checksum ^= ch; 
+		++ src;		
+	}
+	return NULL;
+}
+
+unsigned char UsbRxWatcher:: checkEscape(unsigned char ch)
+{
+	if ((ch == MUX_KEY_WORD ) &&
+		(m_cTstFrameState != RS232_FRAME_KEYWORD) &&
+		(m_cTstFrameState != RS232_FRAME_MD_DATA))// enter MUX state(0x5A) and save the old
+	{ 
+		m_cOldTstFrameState = m_cTstFrameState;
+		m_cTstFrameState = RS232_FRAME_KEYWORD;
+		return 1;
+	}
+
+	return 0;
+}
+
+unsigned char UsbRxWatcher::transferFrame(unsigned char * ch)
+{
+	unsigned char ret = 0;
+	if (m_cTstFrameState == RS232_FRAME_KEYWORD)
+	{
+		switch(*ch)
+		{
+			case MUX_KEY_WORD:
+			*ch = MUX_KEY_WORD;  //5A 5A->5A
+				ret = 1;
+				break;
+			case 0x01:
+			*ch = STX_OCTET; //5A 01->55
+				ret = 1;
+				break;
+			default:
+				break;
+		}
+		m_cTstFrameState = m_cOldTstFrameState;//leave MUX state and restore the state
+	}
+	
+	return ret;
+}
+
+
+
+Frame * UsbRxWatcher::dispatchFrame(unsigned char ch, unsigned char *buf_ptr, unsigned int input_len, unsigned char *src,unsigned short &u16Length)
+{
+	META_LOG("[Meta] parse state: RS232_FRAME_TYPE: %x ", ch);
+
+	if (ch == RS232_INJECT_PRIMITIVE_OCTET || ch == RS232_COMMAND_TYPE_OCTET )
+	{
+		m_cTstFrameState = RS232_FRAME_MD_DATA ;
+		/* if the frame is modem side, we just write whole data to ccci port */
+		META_LOG("[Meta] parse state:  nRS232_FRAME_MD_DATA--: %d, total %d",input_len, m_uFrameLength);
+		return decodeMDFrame((void *)buf_ptr, input_len, ch,u16Length);		
+	}
+	else if(ch >= RS232_INJECT_PRIMITIVE_OCTETMODEM2 && ch <= RS232_INJECT_PRIMITIVE_OCTETMODEM2_END)//0xA0 ~ A7
+	{
+		m_md_index = (ch - RS232_INJECT_PRIMITIVE_OCTETMODEM2)+1; //A0--1(MD2)   A3--4(MD5)
+		m_cTstFrameState = RS232_FRAME_MD_DATA ;
+		/* if the frame is modem side, we just write whole data to ccci port */
+		META_LOG("[Meta] parse state:  nRS232_FRAME_MD_DATA--: %d, total %d",input_len, m_uFrameLength);
+		return decodeMDFrame((void *)buf_ptr, input_len, ch,u16Length);	
+	}
+	else if(ch >= RS232_COMMAND_TYPE_MD2_MEMORY_DUMP && ch<= RS232_COMMAND_TYPE_MD2_MEMORY_DUMP_END)//0xC0 ~ 0xC7
+	{
+		m_md_index = (ch - RS232_COMMAND_TYPE_MD2_MEMORY_DUMP)+1;
+		m_cTstFrameState = RS232_FRAME_MD_DATA ;
+		/* if the frame is modem side, we just write whole data to ccci port */
+		META_LOG("[Meta] parse state:  nRS232_FRAME_MD_DATA--: %d, total %d",input_len, m_uFrameLength);
+		return decodeMDFrame((void *)buf_ptr, input_len, ch,u16Length);	
+	}
+	else if (ch ==RS232_INJECT_APPRIMITIVE_OCTET)//0x66
+	{
+		m_cTstFrameState = RS232_FRAME_AP_INJECT_PIRIMITIVE_HEADER;
+		m_sRs232Frame.received_prig_header_length = 0;
+		m_sRs232Frame.received_buf_para_length = 0;
+		m_sRs232Frame.inject_prim.local_len = 0;
+		m_sRs232Frame.inject_prim.peer_len = 0;
+		m_sRs232Frame.header_ptr = (unsigned char*)&m_sRs232Frame.inject_prim;
+		return decodeAPFrame( input_len,++src,u16Length);
+		
+	}
+	else if(ch >= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_START && 
+			ch <= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_END)//0xD0 ~ 0xD7
+	{
+		m_cTstFrameState = RS232_FRAME_MD_TUNNELING_DATA;
+		m_md_index = ch - RS232_COMMAND_TYPE_MD_DATA_TUNNEL_START;
+		return decodeLTE_C2KFrame(input_len,++src,ch,u16Length);
+	}
+#ifdef MTK_META_COMPRESS_SUPPORT
+	else if(ch >= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_COMP_START && 
+			ch <= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_COMP_END)//0xF0 ~ 0xF7
+	{
+	        META_LOG("[Meta] compress meta frame");
+		m_cTstFrameState = RS232_FRAME_MD_TUNNELING_COMPRESS_DATA;
+		m_md_index = ch - RS232_COMMAND_TYPE_MD_DATA_TUNNEL_COMP_START;
+		return decodeLTE_C2KFrame(input_len,++src,ch,u16Length);
+	}
+#endif
+	else
+	{
+		m_cTstFrameState = RS232_FRAME_STX; //error reset
+		return NULL;
+	}
+	
+	
+}
+
+Frame *UsbRxWatcher::decodeLTE_C2KFrame(unsigned int input_len,unsigned char * src,unsigned char frmType,unsigned short &u16Length)
+{
+	unsigned char * local_ptr = src;
+	unsigned char	ch;
+	int data_len = 0;
+	unsigned short newlen = m_uFrameLength;
+
+	
+	META_LOG("[Meta] (decodeLTE_C2KFrame) input_len = %d, m_uFrameLength = %d",input_len,m_uFrameLength);
+	
+	while(u16Length!=input_len)
+	{
+		ch = *local_ptr;
+		++data_len;	
+		++ u16Length;
+		
+		if ((getComType() == META_UART_COM) && (data_len != newlen + 1))
+		{
+			if(ch == 0x77)
+			{
+				if(u16Length == input_len)
+					return NULL;
+				
+				ch = *(++local_ptr);
+				++ data_len;	
+				++ u16Length;
+				
+				if(getUARTEsc(ch) == 0)
+				{
+					META_LOG("[Meta] incorrect UART ESC (%d)\n", ch);
+					return NULL;
+				}
+
+				++ newlen;
+			}			
+		}
+		
+		if (data_len == newlen + 1) 
+		{
+			if(getMDChType(m_md_index) == FT_MODEM_CH_TUNNELING)
+			{
+				m_cTstFrameState = RS232_FRAME_STX;
+
+				//to check whether checksum is ESC.
+				if((int)input_len >= data_len + 3 + m_frm_len_byte)   //start byte + data len + data type +checksum
+				{
+					if((getComType() == META_UART_COM) && (ch == 0x77))
+					{
+						ch = *(++local_ptr); 
+						++ u16Length;
+						if(getUARTEsc(ch) == 0)
+						{
+							META_LOG("[Meta] [case1] incorrect checksum ESC (%d)\n", ch);
+							return (new Frame());
+						}
+					}
+					else if(ch == MUX_KEY_WORD)
+				{
+					ch = *(++local_ptr); 
+						++ u16Length;
+					if(ch == 0x01)
+						ch = STX_OCTET;
+					else if(ch == MUX_KEY_WORD)
+						ch = MUX_KEY_WORD;					
+					else
+					{
+							META_LOG("[Meta] [case2] incorrect checksum ESC (%d)\n", ch);
+							return (new Frame());
+						}
+					}
+				}
+ 			    else
+				{
+					//0x77 or 0x5A is the latest byte,  checksum is not completed, need to read 1 byte continue.  
+					if(((getComType() == META_UART_COM) && (ch == 0x77)) || (ch == MUX_KEY_WORD))
+					{
+						META_LOG("[Meta]checksum is not completed, need to read 1 byte continue. ESC (%d)", ch);
+						return NULL;
+					}
+				}
+
+				META_LOG("[Meta] parse state: RS232_FRAME_CHECKSUM: checksum: %d, ch: %d",m_checksum, ch);
+				
+				if(m_checksum != ch)
+				{
+					META_LOG("[Meta] LTE modem frame checksum error!");
+					return (new Frame());
+				}
+				
+				m_checksum = STX_OCTET;
+				META_LOG("[Meta] (decodeLTE_C2KFrame) u16Length2 = %d",u16Length);
+				
+			}
+			int len = flowControl(src, newlen);
+			return sendMdTask(src, len, frmType);
+		}
+		m_checksum ^= ch; 
+		++local_ptr;				
+	}
+	return NULL;
+}
+
+unsigned char UsbRxWatcher::getUARTEsc(unsigned char &ch)
+{
+	int ret = 1;
+
+	switch(ch)
+	{
+	case 0x01:
+		ch = 0x11;
+		break;
+	case 0x02:
+		ch = 0x13;
+		break;
+	case 0x03:
+		ch = 0x77;
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+
+	return ret;
+}
+
+bool UsbRxWatcher::uncompress(void *pdata, int len, char *uncompressed, int *uncompressed_len)
+{
+    META_LOG("[Meta] Uncompress starts\n");
+    char *pTempBuf = (char*) pdata;
+    char *pTempUncompBuf = (char*) uncompressed;
+    size_t max_uncompressed_len = 0;
+    size_t uncompressed_len_temp = *uncompressed_len;
+    
+    snappy_status status = snappy_uncompressed_length(pTempBuf, len, &max_uncompressed_len);
+    if (status != SNAPPY_OK)
+    {
+        META_LOG("[Meta] error: Can not calculate uncompressed length. status: %d\n", status);
+        return false;
+    }
+
+    if (uncompressed_len_temp < max_uncompressed_len)
+    {
+        META_LOG("[Meta] error: snappy uncompression buffer is not enough. buffer size: %lu, max uncompressed len: %lu\n", uncompressed_len_temp, max_uncompressed_len);
+        return false;
+    }
+    
+    META_LOG("[Meta] snappy uncompress starts. len: %d\n", len);
+    //dumpDataInHexString((const unsigned char *)pTempBuf,len,16);
+    status = snappy_uncompress((char*)pTempBuf, len, (char*)pTempUncompBuf, &uncompressed_len_temp);
+    if (status != SNAPPY_OK)
+    {
+        META_LOG("[Meta] error: Uncompression failed. status: %d\n", status);
+        return false;
+    }
+    //dumpDataInHexString((const unsigned char *)uncompressed, uncompressed_len_temp,16);
+    META_LOG("[Meta] snappy uncompress Done. uncomp_len: %lu\n", uncompressed_len_temp);
+    *uncompressed_len = (int) uncompressed_len_temp;
+    return true;
+}
+//////////////////////////////////////////////////////////////////////////
diff --git a/src/devtools/meta/src/common/src/tst_main.cpp b/src/devtools/meta/src/common/src/tst_main.cpp
new file mode 100644
index 0000000..981e5a5
--- /dev/null
+++ b/src/devtools/meta/src/common/src/tst_main.cpp
@@ -0,0 +1,73 @@
+#include <assert.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#ifdef IS_SUPPORT_SP
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+#endif
+
+#include <unistd.h>
+#include <syslog.h>
+
+#include "Modem.h"
+#include "SerPort.h"
+#include "MSocket.h"
+#include "UsbRxWatcher.h"
+#include "Context.h"
+#include "PortInterface.h"
+#include "LogDefine.h"
+
+int main(int argc, char** argv)
+{
+	openlog( "[META]", LOG_PID, LOG_DAEMON );
+
+	META_LOG("[Meta] Enter meta_tst init flow! V1.01.00");
+
+/*
+#ifndef	MTK_META_APONLY
+	if(META_BOOT != getBootMode())
+	{
+		META_LOG("[Meta] not meta mode boot!");
+		return 0;
+	}
+#endif
+*/
+
+	umask(007);
+
+	UsbRxWatcher hostRx;
+    setVirtualRxWatcher(&hostRx);
+
+	SerPort *pPort = NULL;
+
+	META_LOG("[Meta] is meta mode");
+	pPort = createSerPort();
+	if (pPort != NULL)
+	{
+		pPort->pumpAsync(&hostRx);
+	}
+	else
+	{
+		META_LOG("[Meta] Enter meta_tst init fail");
+	}
+
+/*
+#ifndef	MTK_META_APONLY
+	createAllModemThread();
+#endif
+*/
+    createAllModemThread();
+
+	while (1)
+	{
+		usleep(100*1000);
+		//querySerPortStatus(); //query port type change every 100ms
+	}
+
+	// infinite loop above; it'll never get here...
+	destroyContext();
+
+	return 0;
+}
diff --git a/src/devtools/meta/src/misc/snappy/snappy-c.cpp b/src/devtools/meta/src/misc/snappy/snappy-c.cpp
new file mode 100644
index 0000000..473a0b0
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-c.cpp
@@ -0,0 +1,90 @@
+// Copyright 2011 Martin Gieseking <martin.gieseking@uos.de>.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "snappy.h"
+#include "snappy-c.h"
+
+extern "C" {
+
+snappy_status snappy_compress(const char* input,
+                              size_t input_length,
+                              char* compressed,
+                              size_t *compressed_length) {
+  if (*compressed_length < snappy_max_compressed_length(input_length)) {
+    return SNAPPY_BUFFER_TOO_SMALL;
+  }
+  snappy::RawCompress(input, input_length, compressed, compressed_length);
+  return SNAPPY_OK;
+}
+
+snappy_status snappy_uncompress(const char* compressed,
+                                size_t compressed_length,
+                                char* uncompressed,
+                                size_t* uncompressed_length) {
+  size_t real_uncompressed_length;
+  if (!snappy::GetUncompressedLength(compressed,
+                                     compressed_length,
+                                     &real_uncompressed_length)) {
+    return SNAPPY_INVALID_INPUT;
+  }
+  if (*uncompressed_length < real_uncompressed_length) {
+    return SNAPPY_BUFFER_TOO_SMALL;
+  }
+  if (!snappy::RawUncompress(compressed, compressed_length, uncompressed)) {
+    return SNAPPY_INVALID_INPUT;
+  }
+  *uncompressed_length = real_uncompressed_length;
+  return SNAPPY_OK;
+}
+
+size_t snappy_max_compressed_length(size_t source_length) {
+  return snappy::MaxCompressedLength(source_length);
+}
+
+snappy_status snappy_uncompressed_length(const char *compressed,
+                                         size_t compressed_length,
+                                         size_t *result) {
+  if (snappy::GetUncompressedLength(compressed,
+                                    compressed_length,
+                                    result)) {
+    return SNAPPY_OK;
+  } else {
+    return SNAPPY_INVALID_INPUT;
+  }
+}
+
+snappy_status snappy_validate_compressed_buffer(const char *compressed,
+                                                size_t compressed_length) {
+  if (snappy::IsValidCompressedBuffer(compressed, compressed_length)) {
+    return SNAPPY_OK;
+  } else {
+    return SNAPPY_INVALID_INPUT;
+  }
+}
+
+}  // extern "C"
diff --git a/src/devtools/meta/src/misc/snappy/snappy-c.h b/src/devtools/meta/src/misc/snappy/snappy-c.h
new file mode 100644
index 0000000..c6c2a86
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-c.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2011 Martin Gieseking <martin.gieseking@uos.de>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Plain C interface (a wrapper around the C++ implementation).
+ */
+
+#ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_C_H_
+#define UTIL_SNAPPY_OPENSOURCE_SNAPPY_C_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+
+/*
+ * Return values; see the documentation for each function to know
+ * what each can return.
+ */
+typedef enum {
+  SNAPPY_OK = 0,
+  SNAPPY_INVALID_INPUT = 1,
+  SNAPPY_BUFFER_TOO_SMALL = 2
+} snappy_status;
+
+/*
+ * Takes the data stored in "input[0..input_length-1]" and stores
+ * it in the array pointed to by "compressed".
+ *
+ * <compressed_length> signals the space available in "compressed".
+ * If it is not at least equal to "snappy_max_compressed_length(input_length)",
+ * SNAPPY_BUFFER_TOO_SMALL is returned. After successful compression,
+ * <compressed_length> contains the true length of the compressed output,
+ * and SNAPPY_OK is returned.
+ *
+ * Example:
+ *   size_t output_length = snappy_max_compressed_length(input_length);
+ *   char* output = (char*)malloc(output_length);
+ *   if (snappy_compress(input, input_length, output, &output_length)
+ *       == SNAPPY_OK) {
+ *     ... Process(output, output_length) ...
+ *   }
+ *   free(output);
+ */
+snappy_status snappy_compress(const char* input,
+                              size_t input_length,
+                              char* compressed,
+                              size_t* compressed_length);
+
+/*
+ * Given data in "compressed[0..compressed_length-1]" generated by
+ * calling the snappy_compress routine, this routine stores
+ * the uncompressed data to
+ *   uncompressed[0..uncompressed_length-1].
+ * Returns failure (a value not equal to SNAPPY_OK) if the message
+ * is corrupted and could not be decrypted.
+ *
+ * <uncompressed_length> signals the space available in "uncompressed".
+ * If it is not at least equal to the value returned by
+ * snappy_uncompressed_length for this stream, SNAPPY_BUFFER_TOO_SMALL
+ * is returned. After successful decompression, <uncompressed_length>
+ * contains the true length of the decompressed output.
+ *
+ * Example:
+ *   size_t output_length;
+ *   if (snappy_uncompressed_length(input, input_length, &output_length)
+ *       != SNAPPY_OK) {
+ *     ... fail ...
+ *   }
+ *   char* output = (char*)malloc(output_length);
+ *   if (snappy_uncompress(input, input_length, output, &output_length)
+ *       == SNAPPY_OK) {
+ *     ... Process(output, output_length) ...
+ *   }
+ *   free(output);
+ */
+snappy_status snappy_uncompress(const char* compressed,
+                                size_t compressed_length,
+                                char* uncompressed,
+                                size_t* uncompressed_length);
+
+/*
+ * Returns the maximal size of the compressed representation of
+ * input data that is "source_length" bytes in length.
+ */
+size_t snappy_max_compressed_length(size_t source_length);
+
+/*
+ * REQUIRES: "compressed[]" was produced by snappy_compress()
+ * Returns SNAPPY_OK and stores the length of the uncompressed data in
+ * *result normally. Returns SNAPPY_INVALID_INPUT on parsing error.
+ * This operation takes O(1) time.
+ */
+snappy_status snappy_uncompressed_length(const char* compressed,
+                                         size_t compressed_length,
+                                         size_t* result);
+
+/*
+ * Check if the contents of "compressed[]" can be uncompressed successfully.
+ * Does not return the uncompressed data; if so, returns SNAPPY_OK,
+ * or if not, returns SNAPPY_INVALID_INPUT.
+ * Takes time proportional to compressed_length, but is usually at least a
+ * factor of four faster than actual decompression.
+ */
+snappy_status snappy_validate_compressed_buffer(const char* compressed,
+                                                size_t compressed_length);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  /* UTIL_SNAPPY_OPENSOURCE_SNAPPY_C_H_ */
diff --git a/src/devtools/meta/src/misc/snappy/snappy-internal.h b/src/devtools/meta/src/misc/snappy/snappy-internal.h
new file mode 100644
index 0000000..c99d331
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-internal.h
@@ -0,0 +1,150 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Internals shared between the Snappy implementation and its unittest.
+
+#ifndef UTIL_SNAPPY_SNAPPY_INTERNAL_H_
+#define UTIL_SNAPPY_SNAPPY_INTERNAL_H_
+
+#include "snappy-stubs-internal.h"
+
+namespace snappy {
+namespace internal {
+
+class WorkingMemory {
+ public:
+  WorkingMemory() : large_table_(NULL) { }
+  ~WorkingMemory() { delete[] large_table_; }
+
+  // Allocates and clears a hash table using memory in "*this",
+  // stores the number of buckets in "*table_size" and returns a pointer to
+  // the base of the hash table.
+  uint16* GetHashTable(size_t input_size, int* table_size);
+
+ private:
+  uint16 small_table_[1<<10];    // 2KB
+  uint16* large_table_;          // Allocated only when needed
+
+  DISALLOW_COPY_AND_ASSIGN(WorkingMemory);
+};
+
+// Flat array compression that does not emit the "uncompressed length"
+// prefix. Compresses "input" string to the "*op" buffer.
+//
+// REQUIRES: "input_length <= kBlockSize"
+// REQUIRES: "op" points to an array of memory that is at least
+// "MaxCompressedLength(input_length)" in size.
+// REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero.
+// REQUIRES: "table_size" is a power of two
+//
+// Returns an "end" pointer into "op" buffer.
+// "end - op" is the compressed size of "input".
+char* CompressFragment(const char* input,
+                       size_t input_length,
+                       char* op,
+                       uint16* table,
+                       const int table_size);
+
+// Return the largest n such that
+//
+//   s1[0,n-1] == s2[0,n-1]
+//   and n <= (s2_limit - s2).
+//
+// Does not read *s2_limit or beyond.
+// Does not read *(s1 + (s2_limit - s2)) or beyond.
+// Requires that s2_limit >= s2.
+//
+// Separate implementation for x86_64, for speed.  Uses the fact that
+// x86_64 is little endian.
+#if defined(ARCH_K8)
+static inline int FindMatchLength(const char* s1,
+                                  const char* s2,
+                                  const char* s2_limit) {
+  assert(s2_limit >= s2);
+  int matched = 0;
+
+  // Find out how long the match is. We loop over the data 64 bits at a
+  // time until we find a 64-bit block that doesn't match; then we find
+  // the first non-matching bit and use that to calculate the total
+  // length of the match.
+  while (PREDICT_TRUE(s2 <= s2_limit - 8)) {
+    if (PREDICT_FALSE(UNALIGNED_LOAD64(s2) == UNALIGNED_LOAD64(s1 + matched))) {
+      s2 += 8;
+      matched += 8;
+    } else {
+      // On current (mid-2008) Opteron models there is a 3% more
+      // efficient code sequence to find the first non-matching byte.
+      // However, what follows is ~10% better on Intel Core 2 and newer,
+      // and we expect AMD's bsf instruction to improve.
+      uint64 x = UNALIGNED_LOAD64(s2) ^ UNALIGNED_LOAD64(s1 + matched);
+      int matching_bits = Bits::FindLSBSetNonZero64(x);
+      matched += matching_bits >> 3;
+      return matched;
+    }
+  }
+  while (PREDICT_TRUE(s2 < s2_limit)) {
+    if (PREDICT_TRUE(s1[matched] == *s2)) {
+      ++s2;
+      ++matched;
+    } else {
+      return matched;
+    }
+  }
+  return matched;
+}
+#else
+static inline int FindMatchLength(const char* s1,
+                                  const char* s2,
+                                  const char* s2_limit) {
+  // Implementation based on the x86-64 version, above.
+  assert(s2_limit >= s2);
+  int matched = 0;
+
+  while (s2 <= s2_limit - 4 &&
+         UNALIGNED_LOAD32(s2) == UNALIGNED_LOAD32(s1 + matched)) {
+    s2 += 4;
+    matched += 4;
+  }
+  if (LittleEndian::IsLittleEndian() && s2 <= s2_limit - 4) {
+    uint32 x = UNALIGNED_LOAD32(s2) ^ UNALIGNED_LOAD32(s1 + matched);
+    int matching_bits = Bits::FindLSBSetNonZero(x);
+    matched += matching_bits >> 3;
+  } else {
+    while ((s2 < s2_limit) && (s1[matched] == *s2)) {
+      ++s2;
+      ++matched;
+    }
+  }
+  return matched;
+}
+#endif
+
+}  // end namespace internal
+}  // end namespace snappy
+
+#endif  // UTIL_SNAPPY_SNAPPY_INTERNAL_H_
diff --git a/src/devtools/meta/src/misc/snappy/snappy-sinksource.cpp b/src/devtools/meta/src/misc/snappy/snappy-sinksource.cpp
new file mode 100644
index 0000000..5844552
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-sinksource.cpp
@@ -0,0 +1,71 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <string.h>
+
+#include "snappy-sinksource.h"
+
+namespace snappy {
+
+Source::~Source() { }
+
+Sink::~Sink() { }
+
+char* Sink::GetAppendBuffer(size_t length, char* scratch) {
+  return scratch;
+}
+
+ByteArraySource::~ByteArraySource() { }
+
+size_t ByteArraySource::Available() const { return left_; }
+
+const char* ByteArraySource::Peek(size_t* len) {
+  *len = left_;
+  return ptr_;
+}
+
+void ByteArraySource::Skip(size_t n) {
+  left_ -= n;
+  ptr_ += n;
+}
+
+UncheckedByteArraySink::~UncheckedByteArraySink() { }
+
+void UncheckedByteArraySink::Append(const char* data, size_t n) {
+  // Do no copying if the caller filled in the result of GetAppendBuffer()
+  if (data != dest_) {
+    memcpy(dest_, data, n);
+  }
+  dest_ += n;
+}
+
+char* UncheckedByteArraySink::GetAppendBuffer(size_t len, char* scratch) {
+  return dest_;
+}
+
+}
diff --git a/src/devtools/meta/src/misc/snappy/snappy-sinksource.h b/src/devtools/meta/src/misc/snappy/snappy-sinksource.h
new file mode 100644
index 0000000..faabfa1
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-sinksource.h
@@ -0,0 +1,137 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_
+#define UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_
+
+#include <stddef.h>
+
+
+namespace snappy {
+
+// A Sink is an interface that consumes a sequence of bytes.
+class Sink {
+ public:
+  Sink() { }
+  virtual ~Sink();
+
+  // Append "bytes[0,n-1]" to this.
+  virtual void Append(const char* bytes, size_t n) = 0;
+
+  // Returns a writable buffer of the specified length for appending.
+  // May return a pointer to the caller-owned scratch buffer which
+  // must have at least the indicated length.  The returned buffer is
+  // only valid until the next operation on this Sink.
+  //
+  // After writing at most "length" bytes, call Append() with the
+  // pointer returned from this function and the number of bytes
+  // written.  Many Append() implementations will avoid copying
+  // bytes if this function returned an internal buffer.
+  //
+  // If a non-scratch buffer is returned, the caller may only pass a
+  // prefix of it to Append().  That is, it is not correct to pass an
+  // interior pointer of the returned array to Append().
+  //
+  // The default implementation always returns the scratch buffer.
+  virtual char* GetAppendBuffer(size_t length, char* scratch);
+
+
+ private:
+  // No copying
+  Sink(const Sink&);
+  void operator=(const Sink&);
+};
+
+// A Source is an interface that yields a sequence of bytes
+class Source {
+ public:
+  Source() { }
+  virtual ~Source();
+
+  // Return the number of bytes left to read from the source
+  virtual size_t Available() const = 0;
+
+  // Peek at the next flat region of the source.  Does not reposition
+  // the source.  The returned region is empty iff Available()==0.
+  //
+  // Returns a pointer to the beginning of the region and store its
+  // length in *len.
+  //
+  // The returned region is valid until the next call to Skip() or
+  // until this object is destroyed, whichever occurs first.
+  //
+  // The returned region may be larger than Available() (for example
+  // if this ByteSource is a view on a substring of a larger source).
+  // The caller is responsible for ensuring that it only reads the
+  // Available() bytes.
+  virtual const char* Peek(size_t* len) = 0;
+
+  // Skip the next n bytes.  Invalidates any buffer returned by
+  // a previous call to Peek().
+  // REQUIRES: Available() >= n
+  virtual void Skip(size_t n) = 0;
+
+ private:
+  // No copying
+  Source(const Source&);
+  void operator=(const Source&);
+};
+
+// A Source implementation that yields the contents of a flat array
+class ByteArraySource : public Source {
+ public:
+  ByteArraySource(const char* p, size_t n) : ptr_(p), left_(n) { }
+  virtual ~ByteArraySource();
+  virtual size_t Available() const;
+  virtual const char* Peek(size_t* len);
+  virtual void Skip(size_t n);
+ private:
+  const char* ptr_;
+  size_t left_;
+};
+
+// A Sink implementation that writes to a flat array without any bound checks.
+class UncheckedByteArraySink : public Sink {
+ public:
+  explicit UncheckedByteArraySink(char* dest) : dest_(dest) { }
+  virtual ~UncheckedByteArraySink();
+  virtual void Append(const char* data, size_t n);
+  virtual char* GetAppendBuffer(size_t len, char* scratch);
+
+  // Return the current output pointer so that a caller can see how
+  // many bytes were produced.
+  // Note: this is not a Sink method.
+  char* CurrentDestination() const { return dest_; }
+ private:
+  char* dest_;
+};
+
+
+}
+
+#endif  // UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_
diff --git a/src/devtools/meta/src/misc/snappy/snappy-stubs-internal.cpp b/src/devtools/meta/src/misc/snappy/snappy-stubs-internal.cpp
new file mode 100644
index 0000000..3822805
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-stubs-internal.cpp
@@ -0,0 +1,42 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <string>
+#include <algorithm>
+
+#include "snappy-stubs-internal.h"
+
+namespace snappy {
+
+void Varint::Append32(string* s, uint32 value) {
+  char buf[Varint::kMax32];
+  const char* p = Varint::Encode32(buf, value);
+  s->append(buf, p - buf);
+}
+
+}  // namespace snappy
diff --git a/src/devtools/meta/src/misc/snappy/snappy-stubs-internal.h b/src/devtools/meta/src/misc/snappy/snappy-stubs-internal.h
new file mode 100644
index 0000000..12393b6
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-stubs-internal.h
@@ -0,0 +1,491 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Various stubs for the open-source version of Snappy.
+
+#ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
+#define UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#include "snappy-stubs-public.h"
+
+#if defined(__x86_64__)
+
+// Enable 64-bit optimized versions of some routines.
+#define ARCH_K8 1
+
+#endif
+
+// Needed by OS X, among others.
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+// Pull in std::min, std::ostream, and the likes. This is safe because this
+// header file is never used from any public header files.
+using namespace std;
+
+// The size of an array, if known at compile-time.
+// Will give unexpected results if used on a pointer.
+// We undefine it first, since some compilers already have a definition.
+#ifdef ARRAYSIZE
+#undef ARRAYSIZE
+#endif
+#define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
+
+// Static prediction hints.
+#ifdef HAVE_BUILTIN_EXPECT
+#define PREDICT_FALSE(x) (__builtin_expect(x, 0))
+#define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
+#else
+#define PREDICT_FALSE(x) x
+#define PREDICT_TRUE(x) x
+#endif
+
+// This is only used for recomputing the tag byte table used during
+// decompression; for simplicity we just remove it from the open-source
+// version (anyone who wants to regenerate it can just do the call
+// themselves within main()).
+#define DEFINE_bool(flag_name, default_value, description) \
+  bool FLAGS_ ## flag_name = default_value
+#define DECLARE_bool(flag_name) \
+  extern bool FLAGS_ ## flag_name
+
+namespace snappy {
+
+static const uint32 kuint32max = static_cast<uint32>(0xFFFFFFFF);
+static const int64 kint64max = static_cast<int64>(0x7FFFFFFFFFFFFFFFLL);
+
+// Potentially unaligned loads and stores.
+
+// x86 and PowerPC can simply do these loads and stores native.
+
+#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__)
+
+#define UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
+#define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
+#define UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p))
+
+#define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
+#define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
+#define UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val))
+
+// ARMv7 and newer support native unaligned accesses, but only of 16-bit
+// and 32-bit values (not 64-bit); older versions either raise a fatal signal,
+// do an unaligned read and rotate the words around a bit, or do the reads very
+// slowly (trip through kernel mode). There's no simple #define that says just
+// “ARMv7 or higher”, so we have to filter away all ARMv5 and ARMv6
+// sub-architectures.
+//
+// This is a mess, but there's not much we can do about it.
+
+#elif defined(__arm__) && \
+      !defined(__ARM_ARCH_4__) && \
+      !defined(__ARM_ARCH_4T__) && \
+      !defined(__ARM_ARCH_5__) && \
+      !defined(__ARM_ARCH_5T__) && \
+      !defined(__ARM_ARCH_5TE__) && \
+      !defined(__ARM_ARCH_5TEJ__) && \
+      !defined(__ARM_ARCH_6__) && \
+      !defined(__ARM_ARCH_6J__) && \
+      !defined(__ARM_ARCH_6K__) && \
+      !defined(__ARM_ARCH_6Z__) && \
+      !defined(__ARM_ARCH_6ZK__) && \
+      !defined(__ARM_ARCH_6T2__)
+
+#define UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
+#define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
+
+#define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
+#define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
+
+// TODO(user): NEON supports unaligned 64-bit loads and stores.
+// See if that would be more efficient on platforms supporting it,
+// at least for copies.
+
+inline uint64 UNALIGNED_LOAD64(const void *p) {
+  uint64 t;
+  memcpy(&t, p, sizeof t);
+  return t;
+}
+
+inline void UNALIGNED_STORE64(void *p, uint64 v) {
+  memcpy(p, &v, sizeof v);
+}
+
+#else
+
+// These functions are provided for architectures that don't support
+// unaligned loads and stores.
+
+inline uint16 UNALIGNED_LOAD16(const void *p) {
+  uint16 t;
+  memcpy(&t, p, sizeof t);
+  return t;
+}
+
+inline uint32 UNALIGNED_LOAD32(const void *p) {
+  uint32 t;
+  memcpy(&t, p, sizeof t);
+  return t;
+}
+
+inline uint64 UNALIGNED_LOAD64(const void *p) {
+  uint64 t;
+  memcpy(&t, p, sizeof t);
+  return t;
+}
+
+inline void UNALIGNED_STORE16(void *p, uint16 v) {
+  memcpy(p, &v, sizeof v);
+}
+
+inline void UNALIGNED_STORE32(void *p, uint32 v) {
+  memcpy(p, &v, sizeof v);
+}
+
+inline void UNALIGNED_STORE64(void *p, uint64 v) {
+  memcpy(p, &v, sizeof v);
+}
+
+#endif
+
+// This can be more efficient than UNALIGNED_LOAD64 + UNALIGNED_STORE64
+// on some platforms, in particular ARM.
+inline void UnalignedCopy64(const void *src, void *dst) {
+  if (sizeof(void *) == 8) {
+    UNALIGNED_STORE64(dst, UNALIGNED_LOAD64(src));
+  } else {
+    const char *src_char = reinterpret_cast<const char *>(src);
+    char *dst_char = reinterpret_cast<char *>(dst);
+
+    UNALIGNED_STORE32(dst_char, UNALIGNED_LOAD32(src_char));
+    UNALIGNED_STORE32(dst_char + 4, UNALIGNED_LOAD32(src_char + 4));
+  }
+}
+
+// The following guarantees declaration of the byte swap functions.
+#ifdef WORDS_BIGENDIAN
+
+#ifdef HAVE_SYS_BYTEORDER_H
+#include <sys/byteorder.h>
+#endif
+
+#ifdef HAVE_SYS_ENDIAN_H
+#include <sys/endian.h>
+#endif
+
+#ifdef _MSC_VER
+#include <stdlib.h>
+#define bswap_16(x) _byteswap_ushort(x)
+#define bswap_32(x) _byteswap_ulong(x)
+#define bswap_64(x) _byteswap_uint64(x)
+
+#elif defined(__APPLE__)
+// Mac OS X / Darwin features
+#include <libkern/OSByteOrder.h>
+#define bswap_16(x) OSSwapInt16(x)
+#define bswap_32(x) OSSwapInt32(x)
+#define bswap_64(x) OSSwapInt64(x)
+
+#elif defined(HAVE_BYTESWAP_H)
+#include <byteswap.h>
+
+#elif defined(bswap32)
+// FreeBSD defines bswap{16,32,64} in <sys/endian.h> (already #included).
+#define bswap_16(x) bswap16(x)
+#define bswap_32(x) bswap32(x)
+#define bswap_64(x) bswap64(x)
+
+#elif defined(BSWAP_64)
+// Solaris 10 defines BSWAP_{16,32,64} in <sys/byteorder.h> (already #included).
+#define bswap_16(x) BSWAP_16(x)
+#define bswap_32(x) BSWAP_32(x)
+#define bswap_64(x) BSWAP_64(x)
+
+#else
+
+inline uint16 bswap_16(uint16 x) {
+  return (x << 8) | (x >> 8);
+}
+
+inline uint32 bswap_32(uint32 x) {
+  x = ((x & 0xff00ff00UL) >> 8) | ((x & 0x00ff00ffUL) << 8);
+  return (x >> 16) | (x << 16);
+}
+
+inline uint64 bswap_64(uint64 x) {
+  x = ((x & 0xff00ff00ff00ff00ULL) >> 8) | ((x & 0x00ff00ff00ff00ffULL) << 8);
+  x = ((x & 0xffff0000ffff0000ULL) >> 16) | ((x & 0x0000ffff0000ffffULL) << 16);
+  return (x >> 32) | (x << 32);
+}
+
+#endif
+
+#endif  // WORDS_BIGENDIAN
+
+// Convert to little-endian storage, opposite of network format.
+// Convert x from host to little endian: x = LittleEndian.FromHost(x);
+// convert x from little endian to host: x = LittleEndian.ToHost(x);
+//
+//  Store values into unaligned memory converting to little endian order:
+//    LittleEndian.Store16(p, x);
+//
+//  Load unaligned values stored in little endian converting to host order:
+//    x = LittleEndian.Load16(p);
+class LittleEndian {
+ public:
+  // Conversion functions.
+#ifdef WORDS_BIGENDIAN
+
+  static uint16 FromHost16(uint16 x) { return bswap_16(x); }
+  static uint16 ToHost16(uint16 x) { return bswap_16(x); }
+
+  static uint32 FromHost32(uint32 x) { return bswap_32(x); }
+  static uint32 ToHost32(uint32 x) { return bswap_32(x); }
+
+  static bool IsLittleEndian() { return false; }
+
+#else  // !defined(WORDS_BIGENDIAN)
+
+  static uint16 FromHost16(uint16 x) { return x; }
+  static uint16 ToHost16(uint16 x) { return x; }
+
+  static uint32 FromHost32(uint32 x) { return x; }
+  static uint32 ToHost32(uint32 x) { return x; }
+
+  static bool IsLittleEndian() { return true; }
+
+#endif  // !defined(WORDS_BIGENDIAN)
+
+  // Functions to do unaligned loads and stores in little-endian order.
+  static uint16 Load16(const void *p) {
+    return ToHost16(UNALIGNED_LOAD16(p));
+  }
+
+  static void Store16(void *p, uint16 v) {
+    UNALIGNED_STORE16(p, FromHost16(v));
+  }
+
+  static uint32 Load32(const void *p) {
+    return ToHost32(UNALIGNED_LOAD32(p));
+  }
+
+  static void Store32(void *p, uint32 v) {
+    UNALIGNED_STORE32(p, FromHost32(v));
+  }
+};
+
+// Some bit-manipulation functions.
+class Bits {
+ public:
+  // Return floor(log2(n)) for positive integer n.  Returns -1 iff n == 0.
+  static int Log2Floor(uint32 n);
+
+  // Return the first set least / most significant bit, 0-indexed.  Returns an
+  // undefined value if n == 0.  FindLSBSetNonZero() is similar to ffs() except
+  // that it's 0-indexed.
+  static int FindLSBSetNonZero(uint32 n);
+  static int FindLSBSetNonZero64(uint64 n);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Bits);
+};
+
+#ifdef HAVE_BUILTIN_CTZ
+
+inline int Bits::Log2Floor(uint32 n) {
+  return n == 0 ? -1 : 31 ^ __builtin_clz(n);
+}
+
+inline int Bits::FindLSBSetNonZero(uint32 n) {
+  return __builtin_ctz(n);
+}
+
+inline int Bits::FindLSBSetNonZero64(uint64 n) {
+  return __builtin_ctzll(n);
+}
+
+#else  // Portable versions.
+
+inline int Bits::Log2Floor(uint32 n) {
+  if (n == 0)
+    return -1;
+  int log = 0;
+  uint32 value = n;
+  for (int i = 4; i >= 0; --i) {
+    int shift = (1 << i);
+    uint32 x = value >> shift;
+    if (x != 0) {
+      value = x;
+      log += shift;
+    }
+  }
+  assert(value == 1);
+  return log;
+}
+
+inline int Bits::FindLSBSetNonZero(uint32 n) {
+  int rc = 31;
+  for (int i = 4, shift = 1 << 4; i >= 0; --i) {
+    const uint32 x = n << shift;
+    if (x != 0) {
+      n = x;
+      rc -= shift;
+    }
+    shift >>= 1;
+  }
+  return rc;
+}
+
+// FindLSBSetNonZero64() is defined in terms of FindLSBSetNonZero().
+inline int Bits::FindLSBSetNonZero64(uint64 n) {
+  const uint32 bottombits = static_cast<uint32>(n);
+  if (bottombits == 0) {
+    // Bottom bits are zero, so scan in top bits
+    return 32 + FindLSBSetNonZero(static_cast<uint32>(n >> 32));
+  } else {
+    return FindLSBSetNonZero(bottombits);
+  }
+}
+
+#endif  // End portable versions.
+
+// Variable-length integer encoding.
+class Varint {
+ public:
+  // Maximum lengths of varint encoding of uint32.
+  static const int kMax32 = 5;
+
+  // Attempts to parse a varint32 from a prefix of the bytes in [ptr,limit-1].
+  // Never reads a character at or beyond limit.  If a valid/terminated varint32
+  // was found in the range, stores it in *OUTPUT and returns a pointer just
+  // past the last byte of the varint32. Else returns NULL.  On success,
+  // "result <= limit".
+  static const char* Parse32WithLimit(const char* ptr, const char* limit,
+                                      uint32* OUTPUT);
+
+  // REQUIRES   "ptr" points to a buffer of length sufficient to hold "v".
+  // EFFECTS    Encodes "v" into "ptr" and returns a pointer to the
+  //            byte just past the last encoded byte.
+  static char* Encode32(char* ptr, uint32 v);
+
+  // EFFECTS    Appends the varint representation of "value" to "*s".
+  static void Append32(string* s, uint32 value);
+};
+
+inline const char* Varint::Parse32WithLimit(const char* p,
+                                            const char* l,
+                                            uint32* OUTPUT) {
+  const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
+  const unsigned char* limit = reinterpret_cast<const unsigned char*>(l);
+  uint32 b, result;
+  if (ptr >= limit) return NULL;
+  b = *(ptr++); result = b & 127;          if (b < 128) goto done;
+  if (ptr >= limit) return NULL;
+  b = *(ptr++); result |= (b & 127) <<  7; if (b < 128) goto done;
+  if (ptr >= limit) return NULL;
+  b = *(ptr++); result |= (b & 127) << 14; if (b < 128) goto done;
+  if (ptr >= limit) return NULL;
+  b = *(ptr++); result |= (b & 127) << 21; if (b < 128) goto done;
+  if (ptr >= limit) return NULL;
+  b = *(ptr++); result |= (b & 127) << 28; if (b < 16) goto done;
+  return NULL;       // Value is too long to be a varint32
+ done:
+  *OUTPUT = result;
+  return reinterpret_cast<const char*>(ptr);
+}
+
+inline char* Varint::Encode32(char* sptr, uint32 v) {
+  // Operate on characters as unsigneds
+  unsigned char* ptr = reinterpret_cast<unsigned char*>(sptr);
+  static const int B = 128;
+  if (v < (1<<7)) {
+    *(ptr++) = v;
+  } else if (v < (1<<14)) {
+    *(ptr++) = v | B;
+    *(ptr++) = v>>7;
+  } else if (v < (1<<21)) {
+    *(ptr++) = v | B;
+    *(ptr++) = (v>>7) | B;
+    *(ptr++) = v>>14;
+  } else if (v < (1<<28)) {
+    *(ptr++) = v | B;
+    *(ptr++) = (v>>7) | B;
+    *(ptr++) = (v>>14) | B;
+    *(ptr++) = v>>21;
+  } else {
+    *(ptr++) = v | B;
+    *(ptr++) = (v>>7) | B;
+    *(ptr++) = (v>>14) | B;
+    *(ptr++) = (v>>21) | B;
+    *(ptr++) = v>>28;
+  }
+  return reinterpret_cast<char*>(ptr);
+}
+
+// If you know the internal layout of the std::string in use, you can
+// replace this function with one that resizes the string without
+// filling the new space with zeros (if applicable) --
+// it will be non-portable but faster.
+inline void STLStringResizeUninitialized(string* s, size_t new_size) {
+  s->resize(new_size);
+}
+
+// Return a mutable char* pointing to a string's internal buffer,
+// which may not be null-terminated. Writing through this pointer will
+// modify the string.
+//
+// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
+// next call to a string method that invalidates iterators.
+//
+// As of 2006-04, there is no standard-blessed way of getting a
+// mutable reference to a string's internal buffer. However, issue 530
+// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-defects.html#530)
+// proposes this as the method. It will officially be part of the standard
+// for C++0x. This should already work on all current implementations.
+inline char* string_as_array(string* str) {
+  return str->empty() ? NULL : &*str->begin();
+}
+
+}  // namespace snappy
+
+#endif  // UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
diff --git a/src/devtools/meta/src/misc/snappy/snappy-stubs-public.h b/src/devtools/meta/src/misc/snappy/snappy-stubs-public.h
new file mode 100644
index 0000000..2db0373
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-stubs-public.h
@@ -0,0 +1,98 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+// Author: sesse@google.com (Steinar H. Gunderson)
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Various type stubs for the open-source version of Snappy.
+//
+// This file cannot include config.h, as it is included from snappy.h,
+// which is a public header. Instead, snappy-stubs-public.h is generated by
+// from snappy-stubs-public.h.in at configure time.
+
+#ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_
+#define UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_
+
+#if 1
+#include <stdint.h>
+#endif
+
+#if 1
+#include <stddef.h>
+#endif
+
+#if 0
+#include <sys/uio.h>
+#endif
+
+#define SNAPPY_MAJOR 1
+#define SNAPPY_MINOR 1
+#define SNAPPY_PATCHLEVEL 2
+#define SNAPPY_VERSION \
+    ((SNAPPY_MAJOR << 16) | (SNAPPY_MINOR << 8) | SNAPPY_PATCHLEVEL)
+
+#include <string>
+
+namespace snappy {
+
+#if 1
+typedef int8_t int8;
+typedef uint8_t uint8;
+typedef int16_t int16;
+typedef uint16_t uint16;
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef int64_t int64;
+typedef uint64_t uint64;
+#else
+typedef signed char int8;
+typedef unsigned char uint8;
+typedef short int16;
+typedef unsigned short uint16;
+typedef int int32;
+typedef unsigned int uint32;
+typedef long long int64;
+typedef unsigned long long uint64;
+#endif
+
+typedef std::string string;
+
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&);               \
+  void operator=(const TypeName&)
+
+#if !0
+// Windows does not have an iovec type, yet the concept is universally useful.
+// It is simple to define it ourselves, so we put it inside our own namespace.
+struct iovec {
+        void* iov_base;
+        size_t iov_len;
+};
+#endif
+
+}  // namespace snappy
+
+#endif  // UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_
diff --git a/src/devtools/meta/src/misc/snappy/snappy.cpp b/src/devtools/meta/src/misc/snappy/snappy.cpp
new file mode 100644
index 0000000..02982f5
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy.cpp
@@ -0,0 +1,1305 @@
+// Copyright 2005 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "snappy.h"
+#include "snappy-internal.h"
+#include "snappy-sinksource.h"
+
+#include <stdio.h>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+namespace snappy {
+
+// Any hash function will produce a valid compressed bitstream, but a good
+// hash function reduces the number of collisions and thus yields better
+// compression for compressible input, and more speed for incompressible
+// input. Of course, it doesn't hurt if the hash function is reasonably fast
+// either, as it gets called a lot.
+static inline uint32 HashBytes(uint32 bytes, int shift) {
+  uint32 kMul = 0x1e35a7bd;
+  return (bytes * kMul) >> shift;
+}
+static inline uint32 Hash(const char* p, int shift) {
+  return HashBytes(UNALIGNED_LOAD32(p), shift);
+}
+
+size_t MaxCompressedLength(size_t source_len) {
+  // Compressed data can be defined as:
+  //    compressed := item* literal*
+  //    item       := literal* copy
+  //
+  // The trailing literal sequence has a space blowup of at most 62/60
+  // since a literal of length 60 needs one tag byte + one extra byte
+  // for length information.
+  //
+  // Item blowup is trickier to measure.  Suppose the "copy" op copies
+  // 4 bytes of data.  Because of a special check in the encoding code,
+  // we produce a 4-byte copy only if the offset is < 65536.  Therefore
+  // the copy op takes 3 bytes to encode, and this type of item leads
+  // to at most the 62/60 blowup for representing literals.
+  //
+  // Suppose the "copy" op copies 5 bytes of data.  If the offset is big
+  // enough, it will take 5 bytes to encode the copy op.  Therefore the
+  // worst case here is a one-byte literal followed by a five-byte copy.
+  // I.e., 6 bytes of input turn into 7 bytes of "compressed" data.
+  //
+  // This last factor dominates the blowup, so the final estimate is:
+  return 32 + source_len + source_len/6;
+}
+
+enum {
+  LITERAL = 0,
+  COPY_1_BYTE_OFFSET = 1,  // 3 bit length + 3 bits of offset in opcode
+  COPY_2_BYTE_OFFSET = 2,
+  COPY_4_BYTE_OFFSET = 3
+};
+static const int kMaximumTagLength = 5;  // COPY_4_BYTE_OFFSET plus the actual offset.
+
+// Copy "len" bytes from "src" to "op", one byte at a time.  Used for
+// handling COPY operations where the input and output regions may
+// overlap.  For example, suppose:
+//    src    == "ab"
+//    op     == src + 2
+//    len    == 20
+// After IncrementalCopy(src, op, len), the result will have
+// eleven copies of "ab"
+//    ababababababababababab
+// Note that this does not match the semantics of either memcpy()
+// or memmove().
+static inline void IncrementalCopy(const char* src, char* op, ssize_t len) {
+  assert(len > 0);
+  do {
+    *op++ = *src++;
+  } while (--len > 0);
+}
+
+// Equivalent to IncrementalCopy except that it can write up to ten extra
+// bytes after the end of the copy, and that it is faster.
+//
+// The main part of this loop is a simple copy of eight bytes at a time until
+// we've copied (at least) the requested amount of bytes.  However, if op and
+// src are less than eight bytes apart (indicating a repeating pattern of
+// length < 8), we first need to expand the pattern in order to get the correct
+// results. For instance, if the buffer looks like this, with the eight-byte
+// <src> and <op> patterns marked as intervals:
+//
+//    abxxxxxxxxxxxx
+//    [------]           src
+//      [------]         op
+//
+// a single eight-byte copy from <src> to <op> will repeat the pattern once,
+// after which we can move <op> two bytes without moving <src>:
+//
+//    ababxxxxxxxxxx
+//    [------]           src
+//        [------]       op
+//
+// and repeat the exercise until the two no longer overlap.
+//
+// This allows us to do very well in the special case of one single byte
+// repeated many times, without taking a big hit for more general cases.
+//
+// The worst case of extra writing past the end of the match occurs when
+// op - src == 1 and len == 1; the last copy will read from byte positions
+// [0..7] and write to [4..11], whereas it was only supposed to write to
+// position 1. Thus, ten excess bytes.
+
+namespace {
+
+const int kMaxIncrementCopyOverflow = 10;
+
+inline void IncrementalCopyFastPath(const char* src, char* op, ssize_t len) {
+  while (op - src < 8) {
+    UnalignedCopy64(src, op);
+    len -= op - src;
+    op += op - src;
+  }
+  while (len > 0) {
+    UnalignedCopy64(src, op);
+    src += 8;
+    op += 8;
+    len -= 8;
+  }
+}
+
+}  // namespace
+
+static inline char* EmitLiteral(char* op,
+                                const char* literal,
+                                int len,
+                                bool allow_fast_path) {
+  int n = len - 1;      // Zero-length literals are disallowed
+  if (n < 60) {
+    // Fits in tag byte
+    *op++ = LITERAL | (n << 2);
+
+    // The vast majority of copies are below 16 bytes, for which a
+    // call to memcpy is overkill. This fast path can sometimes
+    // copy up to 15 bytes too much, but that is okay in the
+    // main loop, since we have a bit to go on for both sides:
+    //
+    //   - The input will always have kInputMarginBytes = 15 extra
+    //     available bytes, as long as we're in the main loop, and
+    //     if not, allow_fast_path = false.
+    //   - The output will always have 32 spare bytes (see
+    //     MaxCompressedLength).
+    if (allow_fast_path && len <= 16) {
+      UnalignedCopy64(literal, op);
+      UnalignedCopy64(literal + 8, op + 8);
+      return op + len;
+    }
+  } else {
+    // Encode in upcoming bytes
+    char* base = op;
+    int count = 0;
+    op++;
+    while (n > 0) {
+      *op++ = n & 0xff;
+      n >>= 8;
+      count++;
+    }
+    assert(count >= 1);
+    assert(count <= 4);
+    *base = LITERAL | ((59+count) << 2);
+  }
+  memcpy(op, literal, len);
+  return op + len;
+}
+
+static inline char* EmitCopyLessThan64(char* op, size_t offset, int len) {
+  assert(len <= 64);
+  assert(len >= 4);
+  assert(offset < 65536);
+
+  if ((len < 12) && (offset < 2048)) {
+    size_t len_minus_4 = len - 4;
+    assert(len_minus_4 < 8);            // Must fit in 3 bits
+    *op++ = COPY_1_BYTE_OFFSET + ((len_minus_4) << 2) + ((offset >> 8) << 5);
+    *op++ = offset & 0xff;
+  } else {
+    *op++ = COPY_2_BYTE_OFFSET + ((len-1) << 2);
+    LittleEndian::Store16(op, offset);
+    op += 2;
+  }
+  return op;
+}
+
+static inline char* EmitCopy(char* op, size_t offset, int len) {
+  // Emit 64 byte copies but make sure to keep at least four bytes reserved
+  while (len >= 68) {
+    op = EmitCopyLessThan64(op, offset, 64);
+    len -= 64;
+  }
+
+  // Emit an extra 60 byte copy if have too much data to fit in one copy
+  if (len > 64) {
+    op = EmitCopyLessThan64(op, offset, 60);
+    len -= 60;
+  }
+
+  // Emit remainder
+  op = EmitCopyLessThan64(op, offset, len);
+  return op;
+}
+
+
+bool GetUncompressedLength(const char* start, size_t n, size_t* result) {
+  uint32 v = 0;
+  const char* limit = start + n;
+  if (Varint::Parse32WithLimit(start, limit, &v) != NULL) {
+    *result = v;
+    return true;
+  } else {
+    return false;
+  }
+}
+
+namespace internal {
+uint16* WorkingMemory::GetHashTable(size_t input_size, int* table_size) {
+  // Use smaller hash table when input.size() is smaller, since we
+  // fill the table, incurring O(hash table size) overhead for
+  // compression, and if the input is short, we won't need that
+  // many hash table entries anyway.
+  assert(kMaxHashTableSize >= 256);
+  size_t htsize = 256;
+  while (htsize < kMaxHashTableSize && htsize < input_size) {
+    htsize <<= 1;
+  }
+
+  uint16* table;
+  if (htsize <= ARRAYSIZE(small_table_)) {
+    table = small_table_;
+  } else {
+    if (large_table_ == NULL) {
+      large_table_ = new uint16[kMaxHashTableSize];
+    }
+    table = large_table_;
+  }
+
+  *table_size = htsize;
+  memset(table, 0, htsize * sizeof(*table));
+  return table;
+}
+}  // end namespace internal
+
+// For 0 <= offset <= 4, GetUint32AtOffset(GetEightBytesAt(p), offset) will
+// equal UNALIGNED_LOAD32(p + offset).  Motivation: On x86-64 hardware we have
+// empirically found that overlapping loads such as
+//  UNALIGNED_LOAD32(p) ... UNALIGNED_LOAD32(p+1) ... UNALIGNED_LOAD32(p+2)
+// are slower than UNALIGNED_LOAD64(p) followed by shifts and casts to uint32.
+//
+// We have different versions for 64- and 32-bit; ideally we would avoid the
+// two functions and just inline the UNALIGNED_LOAD64 call into
+// GetUint32AtOffset, but GCC (at least not as of 4.6) is seemingly not clever
+// enough to avoid loading the value multiple times then. For 64-bit, the load
+// is done when GetEightBytesAt() is called, whereas for 32-bit, the load is
+// done at GetUint32AtOffset() time.
+
+#ifdef ARCH_K8
+
+typedef uint64 EightBytesReference;
+
+static inline EightBytesReference GetEightBytesAt(const char* ptr) {
+  return UNALIGNED_LOAD64(ptr);
+}
+
+static inline uint32 GetUint32AtOffset(uint64 v, int offset) {
+  assert(offset >= 0);
+  assert(offset <= 4);
+  return v >> (LittleEndian::IsLittleEndian() ? 8 * offset : 32 - 8 * offset);
+}
+
+#else
+
+typedef const char* EightBytesReference;
+
+static inline EightBytesReference GetEightBytesAt(const char* ptr) {
+  return ptr;
+}
+
+static inline uint32 GetUint32AtOffset(const char* v, int offset) {
+  assert(offset >= 0);
+  assert(offset <= 4);
+  return UNALIGNED_LOAD32(v + offset);
+}
+
+#endif
+
+// Flat array compression that does not emit the "uncompressed length"
+// prefix. Compresses "input" string to the "*op" buffer.
+//
+// REQUIRES: "input" is at most "kBlockSize" bytes long.
+// REQUIRES: "op" points to an array of memory that is at least
+// "MaxCompressedLength(input.size())" in size.
+// REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero.
+// REQUIRES: "table_size" is a power of two
+//
+// Returns an "end" pointer into "op" buffer.
+// "end - op" is the compressed size of "input".
+namespace internal {
+char* CompressFragment(const char* input,
+                       size_t input_size,
+                       char* op,
+                       uint16* table,
+                       const int table_size) {
+  // "ip" is the input pointer, and "op" is the output pointer.
+  const char* ip = input;
+  assert(input_size <= kBlockSize);
+  assert((table_size & (table_size - 1)) == 0); // table must be power of two
+  const int shift = 32 - Bits::Log2Floor(table_size);
+  assert(static_cast<int>(kuint32max >> shift) == table_size - 1);
+  const char* ip_end = input + input_size;
+  const char* base_ip = ip;
+  // Bytes in [next_emit, ip) will be emitted as literal bytes.  Or
+  // [next_emit, ip_end) after the main loop.
+  const char* next_emit = ip;
+
+  const size_t kInputMarginBytes = 15;
+  if (PREDICT_TRUE(input_size >= kInputMarginBytes)) {
+    const char* ip_limit = input + input_size - kInputMarginBytes;
+
+    for (uint32 next_hash = Hash(++ip, shift); ; ) {
+      assert(next_emit < ip);
+      // The body of this loop calls EmitLiteral once and then EmitCopy one or
+      // more times.  (The exception is that when we're close to exhausting
+      // the input we goto emit_remainder.)
+      //
+      // In the first iteration of this loop we're just starting, so
+      // there's nothing to copy, so calling EmitLiteral once is
+      // necessary.  And we only start a new iteration when the
+      // current iteration has determined that a call to EmitLiteral will
+      // precede the next call to EmitCopy (if any).
+      //
+      // Step 1: Scan forward in the input looking for a 4-byte-long match.
+      // If we get close to exhausting the input then goto emit_remainder.
+      //
+      // Heuristic match skipping: If 32 bytes are scanned with no matches
+      // found, start looking only at every other byte. If 32 more bytes are
+      // scanned, look at every third byte, etc.. When a match is found,
+      // immediately go back to looking at every byte. This is a small loss
+      // (~5% performance, ~0.1% density) for compressible data due to more
+      // bookkeeping, but for non-compressible data (such as JPEG) it's a huge
+      // win since the compressor quickly "realizes" the data is incompressible
+      // and doesn't bother looking for matches everywhere.
+      //
+      // The "skip" variable keeps track of how many bytes there are since the
+      // last match; dividing it by 32 (ie. right-shifting by five) gives the
+      // number of bytes to move ahead for each iteration.
+      uint32 skip = 32;
+
+      const char* next_ip = ip;
+      const char* candidate;
+      do {
+        ip = next_ip;
+        uint32 hash = next_hash;
+        assert(hash == Hash(ip, shift));
+        uint32 bytes_between_hash_lookups = skip++ >> 5;
+        next_ip = ip + bytes_between_hash_lookups;
+        if (PREDICT_FALSE(next_ip > ip_limit)) {
+          goto emit_remainder;
+        }
+        next_hash = Hash(next_ip, shift);
+        candidate = base_ip + table[hash];
+        assert(candidate >= base_ip);
+        assert(candidate < ip);
+
+        table[hash] = ip - base_ip;
+      } while (PREDICT_TRUE(UNALIGNED_LOAD32(ip) !=
+                            UNALIGNED_LOAD32(candidate)));
+
+      // Step 2: A 4-byte match has been found.  We'll later see if more
+      // than 4 bytes match.  But, prior to the match, input
+      // bytes [next_emit, ip) are unmatched.  Emit them as "literal bytes."
+      assert(next_emit + 16 <= ip_end);
+      op = EmitLiteral(op, next_emit, ip - next_emit, true);
+
+      // Step 3: Call EmitCopy, and then see if another EmitCopy could
+      // be our next move.  Repeat until we find no match for the
+      // input immediately after what was consumed by the last EmitCopy call.
+      //
+      // If we exit this loop normally then we need to call EmitLiteral next,
+      // though we don't yet know how big the literal will be.  We handle that
+      // by proceeding to the next iteration of the main loop.  We also can exit
+      // this loop via goto if we get close to exhausting the input.
+      EightBytesReference input_bytes;
+      uint32 candidate_bytes = 0;
+
+      do {
+        // We have a 4-byte match at ip, and no need to emit any
+        // "literal bytes" prior to ip.
+        const char* base = ip;
+        int matched = 4 + FindMatchLength(candidate + 4, ip + 4, ip_end);
+        ip += matched;
+        size_t offset = base - candidate;
+        assert(0 == memcmp(base, candidate, matched));
+        op = EmitCopy(op, offset, matched);
+        // We could immediately start working at ip now, but to improve
+        // compression we first update table[Hash(ip - 1, ...)].
+        const char* insert_tail = ip - 1;
+        next_emit = ip;
+        if (PREDICT_FALSE(ip >= ip_limit)) {
+          goto emit_remainder;
+        }
+        input_bytes = GetEightBytesAt(insert_tail);
+        uint32 prev_hash = HashBytes(GetUint32AtOffset(input_bytes, 0), shift);
+        table[prev_hash] = ip - base_ip - 1;
+        uint32 cur_hash = HashBytes(GetUint32AtOffset(input_bytes, 1), shift);
+        candidate = base_ip + table[cur_hash];
+        candidate_bytes = UNALIGNED_LOAD32(candidate);
+        table[cur_hash] = ip - base_ip;
+      } while (GetUint32AtOffset(input_bytes, 1) == candidate_bytes);
+
+      next_hash = HashBytes(GetUint32AtOffset(input_bytes, 2), shift);
+      ++ip;
+    }
+  }
+
+ emit_remainder:
+  // Emit the remaining bytes as a literal
+  if (next_emit < ip_end) {
+    op = EmitLiteral(op, next_emit, ip_end - next_emit, false);
+  }
+
+  return op;
+}
+}  // end namespace internal
+
+// Signature of output types needed by decompression code.
+// The decompression code is templatized on a type that obeys this
+// signature so that we do not pay virtual function call overhead in
+// the middle of a tight decompression loop.
+//
+// class DecompressionWriter {
+//  public:
+//   // Called before decompression
+//   void SetExpectedLength(size_t length);
+//
+//   // Called after decompression
+//   bool CheckLength() const;
+//
+//   // Called repeatedly during decompression
+//   bool Append(const char* ip, size_t length);
+//   bool AppendFromSelf(uint32 offset, size_t length);
+//
+//   // The rules for how TryFastAppend differs from Append are somewhat
+//   // convoluted:
+//   //
+//   //  - TryFastAppend is allowed to decline (return false) at any
+//   //    time, for any reason -- just "return false" would be
+//   //    a perfectly legal implementation of TryFastAppend.
+//   //    The intention is for TryFastAppend to allow a fast path
+//   //    in the common case of a small append.
+//   //  - TryFastAppend is allowed to read up to <available> bytes
+//   //    from the input buffer, whereas Append is allowed to read
+//   //    <length>. However, if it returns true, it must leave
+//   //    at least five (kMaximumTagLength) bytes in the input buffer
+//   //    afterwards, so that there is always enough space to read the
+//   //    next tag without checking for a refill.
+//   //  - TryFastAppend must always return decline (return false)
+//   //    if <length> is 61 or more, as in this case the literal length is not
+//   //    decoded fully. In practice, this should not be a big problem,
+//   //    as it is unlikely that one would implement a fast path accepting
+//   //    this much data.
+//   //
+//   bool TryFastAppend(const char* ip, size_t available, size_t length);
+// };
+
+// -----------------------------------------------------------------------
+// Lookup table for decompression code.  Generated by ComputeTable() below.
+// -----------------------------------------------------------------------
+
+// Mapping from i in range [0,4] to a mask to extract the bottom 8*i bits
+static const uint32 wordmask[] = {
+  0u, 0xffu, 0xffffu, 0xffffffu, 0xffffffffu
+};
+
+// Data stored per entry in lookup table:
+//      Range   Bits-used       Description
+//      ------------------------------------
+//      1..64   0..7            Literal/copy length encoded in opcode byte
+//      0..7    8..10           Copy offset encoded in opcode byte / 256
+//      0..4    11..13          Extra bytes after opcode
+//
+// We use eight bits for the length even though 7 would have sufficed
+// because of efficiency reasons:
+//      (1) Extracting a byte is faster than a bit-field
+//      (2) It properly aligns copy offset so we do not need a <<8
+static const uint16 char_table[256] = {
+  0x0001, 0x0804, 0x1001, 0x2001, 0x0002, 0x0805, 0x1002, 0x2002,
+  0x0003, 0x0806, 0x1003, 0x2003, 0x0004, 0x0807, 0x1004, 0x2004,
+  0x0005, 0x0808, 0x1005, 0x2005, 0x0006, 0x0809, 0x1006, 0x2006,
+  0x0007, 0x080a, 0x1007, 0x2007, 0x0008, 0x080b, 0x1008, 0x2008,
+  0x0009, 0x0904, 0x1009, 0x2009, 0x000a, 0x0905, 0x100a, 0x200a,
+  0x000b, 0x0906, 0x100b, 0x200b, 0x000c, 0x0907, 0x100c, 0x200c,
+  0x000d, 0x0908, 0x100d, 0x200d, 0x000e, 0x0909, 0x100e, 0x200e,
+  0x000f, 0x090a, 0x100f, 0x200f, 0x0010, 0x090b, 0x1010, 0x2010,
+  0x0011, 0x0a04, 0x1011, 0x2011, 0x0012, 0x0a05, 0x1012, 0x2012,
+  0x0013, 0x0a06, 0x1013, 0x2013, 0x0014, 0x0a07, 0x1014, 0x2014,
+  0x0015, 0x0a08, 0x1015, 0x2015, 0x0016, 0x0a09, 0x1016, 0x2016,
+  0x0017, 0x0a0a, 0x1017, 0x2017, 0x0018, 0x0a0b, 0x1018, 0x2018,
+  0x0019, 0x0b04, 0x1019, 0x2019, 0x001a, 0x0b05, 0x101a, 0x201a,
+  0x001b, 0x0b06, 0x101b, 0x201b, 0x001c, 0x0b07, 0x101c, 0x201c,
+  0x001d, 0x0b08, 0x101d, 0x201d, 0x001e, 0x0b09, 0x101e, 0x201e,
+  0x001f, 0x0b0a, 0x101f, 0x201f, 0x0020, 0x0b0b, 0x1020, 0x2020,
+  0x0021, 0x0c04, 0x1021, 0x2021, 0x0022, 0x0c05, 0x1022, 0x2022,
+  0x0023, 0x0c06, 0x1023, 0x2023, 0x0024, 0x0c07, 0x1024, 0x2024,
+  0x0025, 0x0c08, 0x1025, 0x2025, 0x0026, 0x0c09, 0x1026, 0x2026,
+  0x0027, 0x0c0a, 0x1027, 0x2027, 0x0028, 0x0c0b, 0x1028, 0x2028,
+  0x0029, 0x0d04, 0x1029, 0x2029, 0x002a, 0x0d05, 0x102a, 0x202a,
+  0x002b, 0x0d06, 0x102b, 0x202b, 0x002c, 0x0d07, 0x102c, 0x202c,
+  0x002d, 0x0d08, 0x102d, 0x202d, 0x002e, 0x0d09, 0x102e, 0x202e,
+  0x002f, 0x0d0a, 0x102f, 0x202f, 0x0030, 0x0d0b, 0x1030, 0x2030,
+  0x0031, 0x0e04, 0x1031, 0x2031, 0x0032, 0x0e05, 0x1032, 0x2032,
+  0x0033, 0x0e06, 0x1033, 0x2033, 0x0034, 0x0e07, 0x1034, 0x2034,
+  0x0035, 0x0e08, 0x1035, 0x2035, 0x0036, 0x0e09, 0x1036, 0x2036,
+  0x0037, 0x0e0a, 0x1037, 0x2037, 0x0038, 0x0e0b, 0x1038, 0x2038,
+  0x0039, 0x0f04, 0x1039, 0x2039, 0x003a, 0x0f05, 0x103a, 0x203a,
+  0x003b, 0x0f06, 0x103b, 0x203b, 0x003c, 0x0f07, 0x103c, 0x203c,
+  0x0801, 0x0f08, 0x103d, 0x203d, 0x1001, 0x0f09, 0x103e, 0x203e,
+  0x1801, 0x0f0a, 0x103f, 0x203f, 0x2001, 0x0f0b, 0x1040, 0x2040
+};
+
+// In debug mode, allow optional computation of the table at startup.
+// Also, check that the decompression table is correct.
+#ifndef NDEBUG
+DEFINE_bool(snappy_dump_decompression_table, false,
+            "If true, we print the decompression table at startup.");
+
+static uint16 MakeEntry(unsigned int extra,
+                        unsigned int len,
+                        unsigned int copy_offset) {
+  // Check that all of the fields fit within the allocated space
+  assert(extra       == (extra & 0x7));          // At most 3 bits
+  assert(copy_offset == (copy_offset & 0x7));    // At most 3 bits
+  assert(len         == (len & 0x7f));           // At most 7 bits
+  return len | (copy_offset << 8) | (extra << 11);
+}
+
+static void ComputeTable() {
+  uint16 dst[256];
+
+  // Place invalid entries in all places to detect missing initialization
+  int assigned = 0;
+  for (int i = 0; i < 256; i++) {
+    dst[i] = 0xffff;
+  }
+
+  // Small LITERAL entries.  We store (len-1) in the top 6 bits.
+  for (unsigned int len = 1; len <= 60; len++) {
+    dst[LITERAL | ((len-1) << 2)] = MakeEntry(0, len, 0);
+    assigned++;
+  }
+
+  // Large LITERAL entries.  We use 60..63 in the high 6 bits to
+  // encode the number of bytes of length info that follow the opcode.
+  for (unsigned int extra_bytes = 1; extra_bytes <= 4; extra_bytes++) {
+    // We set the length field in the lookup table to 1 because extra
+    // bytes encode len-1.
+    dst[LITERAL | ((extra_bytes+59) << 2)] = MakeEntry(extra_bytes, 1, 0);
+    assigned++;
+  }
+
+  // COPY_1_BYTE_OFFSET.
+  //
+  // The tag byte in the compressed data stores len-4 in 3 bits, and
+  // offset/256 in 5 bits.  offset%256 is stored in the next byte.
+  //
+  // This format is used for length in range [4..11] and offset in
+  // range [0..2047]
+  for (unsigned int len = 4; len < 12; len++) {
+    for (unsigned int offset = 0; offset < 2048; offset += 256) {
+      dst[COPY_1_BYTE_OFFSET | ((len-4)<<2) | ((offset>>8)<<5)] =
+        MakeEntry(1, len, offset>>8);
+      assigned++;
+    }
+  }
+
+  // COPY_2_BYTE_OFFSET.
+  // Tag contains len-1 in top 6 bits, and offset in next two bytes.
+  for (unsigned int len = 1; len <= 64; len++) {
+    dst[COPY_2_BYTE_OFFSET | ((len-1)<<2)] = MakeEntry(2, len, 0);
+    assigned++;
+  }
+
+  // COPY_4_BYTE_OFFSET.
+  // Tag contents len-1 in top 6 bits, and offset in next four bytes.
+  for (unsigned int len = 1; len <= 64; len++) {
+    dst[COPY_4_BYTE_OFFSET | ((len-1)<<2)] = MakeEntry(4, len, 0);
+    assigned++;
+  }
+
+  // Check that each entry was initialized exactly once.
+  if (assigned != 256) {
+    fprintf(stderr, "ComputeTable: assigned only %d of 256\n", assigned);
+    abort();
+  }
+  for (int i = 0; i < 256; i++) {
+    if (dst[i] == 0xffff) {
+      fprintf(stderr, "ComputeTable: did not assign byte %d\n", i);
+      abort();
+    }
+  }
+
+  if (FLAGS_snappy_dump_decompression_table) {
+    printf("static const uint16 char_table[256] = {\n  ");
+    for (int i = 0; i < 256; i++) {
+      printf("0x%04x%s",
+             dst[i],
+             ((i == 255) ? "\n" : (((i%8) == 7) ? ",\n  " : ", ")));
+    }
+    printf("};\n");
+  }
+
+  // Check that computed table matched recorded table
+  for (int i = 0; i < 256; i++) {
+    if (dst[i] != char_table[i]) {
+      fprintf(stderr, "ComputeTable: byte %d: computed (%x), expect (%x)\n",
+              i, static_cast<int>(dst[i]), static_cast<int>(char_table[i]));
+      abort();
+    }
+  }
+}
+#endif /* !NDEBUG */
+
+// Helper class for decompression
+class SnappyDecompressor {
+ private:
+  Source*       reader_;         // Underlying source of bytes to decompress
+  const char*   ip_;             // Points to next buffered byte
+  const char*   ip_limit_;       // Points just past buffered bytes
+  uint32        peeked_;         // Bytes peeked from reader (need to skip)
+  bool          eof_;            // Hit end of input without an error?
+  char          scratch_[kMaximumTagLength];  // See RefillTag().
+
+  // Ensure that all of the tag metadata for the next tag is available
+  // in [ip_..ip_limit_-1].  Also ensures that [ip,ip+4] is readable even
+  // if (ip_limit_ - ip_ < 5).
+  //
+  // Returns true on success, false on error or end of input.
+  bool RefillTag();
+
+ public:
+  explicit SnappyDecompressor(Source* reader)
+      : reader_(reader),
+        ip_(NULL),
+        ip_limit_(NULL),
+        peeked_(0),
+        eof_(false) {
+  }
+
+  ~SnappyDecompressor() {
+    // Advance past any bytes we peeked at from the reader
+    reader_->Skip(peeked_);
+  }
+
+  // Returns true iff we have hit the end of the input without an error.
+  bool eof() const {
+    return eof_;
+  }
+
+  // Read the uncompressed length stored at the start of the compressed data.
+  // On succcess, stores the length in *result and returns true.
+  // On failure, returns false.
+  bool ReadUncompressedLength(uint32* result) {
+    assert(ip_ == NULL);       // Must not have read anything yet
+    // Length is encoded in 1..5 bytes
+    *result = 0;
+    uint32 shift = 0;
+    while (true) {
+      if (shift >= 32) return false;
+      size_t n;
+      const char* ip = reader_->Peek(&n);
+      if (n == 0) return false;
+      const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip));
+      reader_->Skip(1);
+      *result |= static_cast<uint32>(c & 0x7f) << shift;
+      if (c < 128) {
+        break;
+      }
+      shift += 7;
+    }
+    return true;
+  }
+
+  // Process the next item found in the input.
+  // Returns true if successful, false on error or end of input.
+  template <class Writer>
+  void DecompressAllTags(Writer* writer) {
+    const char* ip = ip_;
+
+    // We could have put this refill fragment only at the beginning of the loop.
+    // However, duplicating it at the end of each branch gives the compiler more
+    // scope to optimize the <ip_limit_ - ip> expression based on the local
+    // context, which overall increases speed.
+    #define MAYBE_REFILL() \
+        if (ip_limit_ - ip < kMaximumTagLength) { \
+          ip_ = ip; \
+          if (!RefillTag()) return; \
+          ip = ip_; \
+        }
+
+    MAYBE_REFILL();
+    for ( ;; ) {
+      const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip++));
+
+      if ((c & 0x3) == LITERAL) {
+        size_t literal_length = (c >> 2) + 1u;
+        if (writer->TryFastAppend(ip, ip_limit_ - ip, literal_length)) {
+          assert(literal_length < 61);
+          ip += literal_length;
+          // NOTE(user): There is no MAYBE_REFILL() here, as TryFastAppend()
+          // will not return true unless there's already at least five spare
+          // bytes in addition to the literal.
+          continue;
+        }
+        if (PREDICT_FALSE(literal_length >= 61)) {
+          // Long literal.
+          const size_t literal_length_length = literal_length - 60;
+          literal_length =
+              (LittleEndian::Load32(ip) & wordmask[literal_length_length]) + 1;
+          ip += literal_length_length;
+        }
+
+        size_t avail = ip_limit_ - ip;
+        while (avail < literal_length) {
+          if (!writer->Append(ip, avail)) return;
+          literal_length -= avail;
+          reader_->Skip(peeked_);
+          size_t n;
+          ip = reader_->Peek(&n);
+          avail = n;
+          peeked_ = avail;
+          if (avail == 0) return;  // Premature end of input
+          ip_limit_ = ip + avail;
+        }
+        if (!writer->Append(ip, literal_length)) {
+          return;
+        }
+        ip += literal_length;
+        MAYBE_REFILL();
+      } else {
+        const uint32 entry = char_table[c];
+        const uint32 trailer = LittleEndian::Load32(ip) & wordmask[entry >> 11];
+        const uint32 length = entry & 0xff;
+        ip += entry >> 11;
+
+        // copy_offset/256 is encoded in bits 8..10.  By just fetching
+        // those bits, we get copy_offset (since the bit-field starts at
+        // bit 8).
+        const uint32 copy_offset = entry & 0x700;
+        if (!writer->AppendFromSelf(copy_offset + trailer, length)) {
+          return;
+        }
+        MAYBE_REFILL();
+      }
+    }
+
+#undef MAYBE_REFILL
+  }
+};
+
+bool SnappyDecompressor::RefillTag() {
+  const char* ip = ip_;
+  if (ip == ip_limit_) {
+    // Fetch a new fragment from the reader
+    reader_->Skip(peeked_);   // All peeked bytes are used up
+    size_t n;
+    ip = reader_->Peek(&n);
+    peeked_ = n;
+    if (n == 0) {
+      eof_ = true;
+      return false;
+    }
+    ip_limit_ = ip + n;
+  }
+
+  // Read the tag character
+  assert(ip < ip_limit_);
+  const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip));
+  const uint32 entry = char_table[c];
+  const uint32 needed = (entry >> 11) + 1;  // +1 byte for 'c'
+  assert(needed <= sizeof(scratch_));
+
+  // Read more bytes from reader if needed
+  uint32 nbuf = ip_limit_ - ip;
+  if (nbuf < needed) {
+    // Stitch together bytes from ip and reader to form the word
+    // contents.  We store the needed bytes in "scratch_".  They
+    // will be consumed immediately by the caller since we do not
+    // read more than we need.
+    memmove(scratch_, ip, nbuf);
+    reader_->Skip(peeked_);  // All peeked bytes are used up
+    peeked_ = 0;
+    while (nbuf < needed) {
+      size_t length;
+      const char* src = reader_->Peek(&length);
+      if (length == 0) return false;
+      uint32 to_add = min<uint32>(needed - nbuf, length);
+      memcpy(scratch_ + nbuf, src, to_add);
+      nbuf += to_add;
+      reader_->Skip(to_add);
+    }
+    assert(nbuf == needed);
+    ip_ = scratch_;
+    ip_limit_ = scratch_ + needed;
+  } else if (nbuf < kMaximumTagLength) {
+    // Have enough bytes, but move into scratch_ so that we do not
+    // read past end of input
+    memmove(scratch_, ip, nbuf);
+    reader_->Skip(peeked_);  // All peeked bytes are used up
+    peeked_ = 0;
+    ip_ = scratch_;
+    ip_limit_ = scratch_ + nbuf;
+  } else {
+    // Pass pointer to buffer returned by reader_.
+    ip_ = ip;
+  }
+  return true;
+}
+
+template <typename Writer>
+static bool InternalUncompress(Source* r, Writer* writer) {
+  // Read the uncompressed length from the front of the compressed input
+  SnappyDecompressor decompressor(r);
+  uint32 uncompressed_len = 0;
+  if (!decompressor.ReadUncompressedLength(&uncompressed_len)) return false;
+  return InternalUncompressAllTags(&decompressor, writer, uncompressed_len);
+}
+
+template <typename Writer>
+static bool InternalUncompressAllTags(SnappyDecompressor* decompressor,
+                                      Writer* writer,
+                                      uint32 uncompressed_len) {
+  writer->SetExpectedLength(uncompressed_len);
+
+  // Process the entire input
+  decompressor->DecompressAllTags(writer);
+  return (decompressor->eof() && writer->CheckLength());
+}
+
+bool GetUncompressedLength(Source* source, uint32* result) {
+  SnappyDecompressor decompressor(source);
+  return decompressor.ReadUncompressedLength(result);
+}
+
+size_t Compress(Source* reader, Sink* writer) {
+  size_t written = 0;
+  size_t N = reader->Available();
+  char ulength[Varint::kMax32];
+  char* p = Varint::Encode32(ulength, N);
+  writer->Append(ulength, p-ulength);
+  written += (p - ulength);
+
+  internal::WorkingMemory wmem;
+  char* scratch = NULL;
+  char* scratch_output = NULL;
+
+  while (N > 0) {
+    // Get next block to compress (without copying if possible)
+    size_t fragment_size;
+    const char* fragment = reader->Peek(&fragment_size);
+    assert(fragment_size != 0);  // premature end of input
+    const size_t num_to_read = min(N, kBlockSize);
+    size_t bytes_read = fragment_size;
+
+    size_t pending_advance = 0;
+    if (bytes_read >= num_to_read) {
+      // Buffer returned by reader is large enough
+      pending_advance = num_to_read;
+      fragment_size = num_to_read;
+    } else {
+      // Read into scratch buffer
+      if (scratch == NULL) {
+        // If this is the last iteration, we want to allocate N bytes
+        // of space, otherwise the max possible kBlockSize space.
+        // num_to_read contains exactly the correct value
+        scratch = new char[num_to_read];
+      }
+      memcpy(scratch, fragment, bytes_read);
+      reader->Skip(bytes_read);
+
+      while (bytes_read < num_to_read) {
+        fragment = reader->Peek(&fragment_size);
+        size_t n = min<size_t>(fragment_size, num_to_read - bytes_read);
+        memcpy(scratch + bytes_read, fragment, n);
+        bytes_read += n;
+        reader->Skip(n);
+      }
+      assert(bytes_read == num_to_read);
+      fragment = scratch;
+      fragment_size = num_to_read;
+    }
+    assert(fragment_size == num_to_read);
+
+    // Get encoding table for compression
+    int table_size;
+    uint16* table = wmem.GetHashTable(num_to_read, &table_size);
+
+    // Compress input_fragment and append to dest
+    const int max_output = MaxCompressedLength(num_to_read);
+
+    // Need a scratch buffer for the output, in case the byte sink doesn't
+    // have room for us directly.
+    if (scratch_output == NULL) {
+      scratch_output = new char[max_output];
+    } else {
+      // Since we encode kBlockSize regions followed by a region
+      // which is <= kBlockSize in length, a previously allocated
+      // scratch_output[] region is big enough for this iteration.
+    }
+    char* dest = writer->GetAppendBuffer(max_output, scratch_output);
+    char* end = internal::CompressFragment(fragment, fragment_size,
+                                           dest, table, table_size);
+    writer->Append(dest, end - dest);
+    written += (end - dest);
+
+    N -= num_to_read;
+    reader->Skip(pending_advance);
+  }
+
+  delete[] scratch;
+  delete[] scratch_output;
+
+  return written;
+}
+
+// -----------------------------------------------------------------------
+// IOVec interfaces
+// -----------------------------------------------------------------------
+
+// A type that writes to an iovec.
+// Note that this is not a "ByteSink", but a type that matches the
+// Writer template argument to SnappyDecompressor::DecompressAllTags().
+class SnappyIOVecWriter {
+ private:
+  const struct iovec* output_iov_;
+  const size_t output_iov_count_;
+
+  // We are currently writing into output_iov_[curr_iov_index_].
+  int curr_iov_index_;
+
+  // Bytes written to output_iov_[curr_iov_index_] so far.
+  size_t curr_iov_written_;
+
+  // Total bytes decompressed into output_iov_ so far.
+  size_t total_written_;
+
+  // Maximum number of bytes that will be decompressed into output_iov_.
+  size_t output_limit_;
+
+  inline char* GetIOVecPointer(int index, size_t offset) {
+    return reinterpret_cast<char*>(output_iov_[index].iov_base) +
+        offset;
+  }
+
+ public:
+  // Does not take ownership of iov. iov must be valid during the
+  // entire lifetime of the SnappyIOVecWriter.
+  inline SnappyIOVecWriter(const struct iovec* iov, size_t iov_count)
+      : output_iov_(iov),
+        output_iov_count_(iov_count),
+        curr_iov_index_(0),
+        curr_iov_written_(0),
+        total_written_(0),
+        output_limit_(-1) {
+  }
+
+  inline void SetExpectedLength(size_t len) {
+    output_limit_ = len;
+  }
+
+  inline bool CheckLength() const {
+    return total_written_ == output_limit_;
+  }
+
+  inline bool Append(const char* ip, size_t len) {
+    if (total_written_ + len > output_limit_) {
+      return false;
+    }
+
+    while (len > 0) {
+      assert(curr_iov_written_ <= output_iov_[curr_iov_index_].iov_len);
+      if (curr_iov_written_ >= output_iov_[curr_iov_index_].iov_len) {
+        // This iovec is full. Go to the next one.
+        if (curr_iov_index_ + 1 >= output_iov_count_) {
+          return false;
+        }
+        curr_iov_written_ = 0;
+        ++curr_iov_index_;
+      }
+
+      const size_t to_write = std::min(
+          len, output_iov_[curr_iov_index_].iov_len - curr_iov_written_);
+      memcpy(GetIOVecPointer(curr_iov_index_, curr_iov_written_),
+             ip,
+             to_write);
+      curr_iov_written_ += to_write;
+      total_written_ += to_write;
+      ip += to_write;
+      len -= to_write;
+    }
+
+    return true;
+  }
+
+  inline bool TryFastAppend(const char* ip, size_t available, size_t len) {
+    const size_t space_left = output_limit_ - total_written_;
+    if (len <= 16 && available >= 16 + kMaximumTagLength && space_left >= 16 &&
+        output_iov_[curr_iov_index_].iov_len - curr_iov_written_ >= 16) {
+      // Fast path, used for the majority (about 95%) of invocations.
+      char* ptr = GetIOVecPointer(curr_iov_index_, curr_iov_written_);
+      UnalignedCopy64(ip, ptr);
+      UnalignedCopy64(ip + 8, ptr + 8);
+      curr_iov_written_ += len;
+      total_written_ += len;
+      return true;
+    }
+
+    return false;
+  }
+
+  inline bool AppendFromSelf(size_t offset, size_t len) {
+    if (offset > total_written_ || offset == 0) {
+      return false;
+    }
+    const size_t space_left = output_limit_ - total_written_;
+    if (len > space_left) {
+      return false;
+    }
+
+    // Locate the iovec from which we need to start the copy.
+    int from_iov_index = curr_iov_index_;
+    size_t from_iov_offset = curr_iov_written_;
+    while (offset > 0) {
+      if (from_iov_offset >= offset) {
+        from_iov_offset -= offset;
+        break;
+      }
+
+      offset -= from_iov_offset;
+      --from_iov_index;
+      assert(from_iov_index >= 0);
+      from_iov_offset = output_iov_[from_iov_index].iov_len;
+    }
+
+    // Copy <len> bytes starting from the iovec pointed to by from_iov_index to
+    // the current iovec.
+    while (len > 0) {
+      assert(from_iov_index <= curr_iov_index_);
+      if (from_iov_index != curr_iov_index_) {
+        const size_t to_copy = std::min(
+            output_iov_[from_iov_index].iov_len - from_iov_offset,
+            len);
+        Append(GetIOVecPointer(from_iov_index, from_iov_offset), to_copy);
+        len -= to_copy;
+        if (len > 0) {
+          ++from_iov_index;
+          from_iov_offset = 0;
+        }
+      } else {
+        assert(curr_iov_written_ <= output_iov_[curr_iov_index_].iov_len);
+        size_t to_copy = std::min(output_iov_[curr_iov_index_].iov_len -
+                                      curr_iov_written_,
+                                  len);
+        if (to_copy == 0) {
+          // This iovec is full. Go to the next one.
+          if (curr_iov_index_ + 1 >= output_iov_count_) {
+            return false;
+          }
+          ++curr_iov_index_;
+          curr_iov_written_ = 0;
+          continue;
+        }
+        if (to_copy > len) {
+          to_copy = len;
+        }
+        IncrementalCopy(GetIOVecPointer(from_iov_index, from_iov_offset),
+                        GetIOVecPointer(curr_iov_index_, curr_iov_written_),
+                        to_copy);
+        curr_iov_written_ += to_copy;
+        from_iov_offset += to_copy;
+        total_written_ += to_copy;
+        len -= to_copy;
+      }
+    }
+
+    return true;
+  }
+
+};
+
+bool RawUncompressToIOVec(const char* compressed, size_t compressed_length,
+                          const struct iovec* iov, size_t iov_cnt) {
+  ByteArraySource reader(compressed, compressed_length);
+  return RawUncompressToIOVec(&reader, iov, iov_cnt);
+}
+
+bool RawUncompressToIOVec(Source* compressed, const struct iovec* iov,
+                          size_t iov_cnt) {
+  SnappyIOVecWriter output(iov, iov_cnt);
+  return InternalUncompress(compressed, &output);
+}
+
+// -----------------------------------------------------------------------
+// Flat array interfaces
+// -----------------------------------------------------------------------
+
+// A type that writes to a flat array.
+// Note that this is not a "ByteSink", but a type that matches the
+// Writer template argument to SnappyDecompressor::DecompressAllTags().
+class SnappyArrayWriter {
+ private:
+  char* base_;
+  char* op_;
+  char* op_limit_;
+
+ public:
+  inline explicit SnappyArrayWriter(char* dst)
+      : base_(dst),
+        op_(dst) {
+  }
+
+  inline void SetExpectedLength(size_t len) {
+    op_limit_ = op_ + len;
+  }
+
+  inline bool CheckLength() const {
+    return op_ == op_limit_;
+  }
+
+  inline bool Append(const char* ip, size_t len) {
+    char* op = op_;
+    const size_t space_left = op_limit_ - op;
+    if (space_left < len) {
+      return false;
+    }
+    memcpy(op, ip, len);
+    op_ = op + len;
+    return true;
+  }
+
+  inline bool TryFastAppend(const char* ip, size_t available, size_t len) {
+    char* op = op_;
+    const size_t space_left = op_limit_ - op;
+    if (len <= 16 && available >= 16 + kMaximumTagLength && space_left >= 16) {
+      // Fast path, used for the majority (about 95%) of invocations.
+      UnalignedCopy64(ip, op);
+      UnalignedCopy64(ip + 8, op + 8);
+      op_ = op + len;
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  inline bool AppendFromSelf(size_t offset, size_t len) {
+    char* op = op_;
+    const size_t space_left = op_limit_ - op;
+
+    // Check if we try to append from before the start of the buffer.
+    // Normally this would just be a check for "produced < offset",
+    // but "produced <= offset - 1u" is equivalent for every case
+    // except the one where offset==0, where the right side will wrap around
+    // to a very big number. This is convenient, as offset==0 is another
+    // invalid case that we also want to catch, so that we do not go
+    // into an infinite loop.
+    assert(op >= base_);
+    size_t produced = op - base_;
+    if (produced <= offset - 1u) {
+      return false;
+    }
+    if (len <= 16 && offset >= 8 && space_left >= 16) {
+      // Fast path, used for the majority (70-80%) of dynamic invocations.
+      UnalignedCopy64(op - offset, op);
+      UnalignedCopy64(op - offset + 8, op + 8);
+    } else {
+      if (space_left >= len + kMaxIncrementCopyOverflow) {
+        IncrementalCopyFastPath(op - offset, op, len);
+      } else {
+        if (space_left < len) {
+          return false;
+        }
+        IncrementalCopy(op - offset, op, len);
+      }
+    }
+
+    op_ = op + len;
+    return true;
+  }
+};
+
+bool RawUncompress(const char* compressed, size_t n, char* uncompressed) {
+  ByteArraySource reader(compressed, n);
+  return RawUncompress(&reader, uncompressed);
+}
+
+bool RawUncompress(Source* compressed, char* uncompressed) {
+  SnappyArrayWriter output(uncompressed);
+  return InternalUncompress(compressed, &output);
+}
+
+bool Uncompress(const char* compressed, size_t n, string* uncompressed) {
+  size_t ulength;
+  if (!GetUncompressedLength(compressed, n, &ulength)) {
+    return false;
+  }
+  // On 32-bit builds: max_size() < kuint32max.  Check for that instead
+  // of crashing (e.g., consider externally specified compressed data).
+  if (ulength > uncompressed->max_size()) {
+    return false;
+  }
+  STLStringResizeUninitialized(uncompressed, ulength);
+  return RawUncompress(compressed, n, string_as_array(uncompressed));
+}
+
+
+// A Writer that drops everything on the floor and just does validation
+class SnappyDecompressionValidator {
+ private:
+  size_t expected_;
+  size_t produced_;
+
+ public:
+  inline SnappyDecompressionValidator() : produced_(0) { }
+  inline void SetExpectedLength(size_t len) {
+    expected_ = len;
+  }
+  inline bool CheckLength() const {
+    return expected_ == produced_;
+  }
+  inline bool Append(const char* ip, size_t len) {
+    produced_ += len;
+    return produced_ <= expected_;
+  }
+  inline bool TryFastAppend(const char* ip, size_t available, size_t length) {
+    return false;
+  }
+  inline bool AppendFromSelf(size_t offset, size_t len) {
+    // See SnappyArrayWriter::AppendFromSelf for an explanation of
+    // the "offset - 1u" trick.
+    if (produced_ <= offset - 1u) return false;
+    produced_ += len;
+    return produced_ <= expected_;
+  }
+};
+
+bool IsValidCompressedBuffer(const char* compressed, size_t n) {
+  ByteArraySource reader(compressed, n);
+  SnappyDecompressionValidator writer;
+  return InternalUncompress(&reader, &writer);
+}
+
+void RawCompress(const char* input,
+                 size_t input_length,
+                 char* compressed,
+                 size_t* compressed_length) {
+  ByteArraySource reader(input, input_length);
+  UncheckedByteArraySink writer(compressed);
+  Compress(&reader, &writer);
+
+  // Compute how many bytes were added
+  *compressed_length = (writer.CurrentDestination() - compressed);
+}
+
+size_t Compress(const char* input, size_t input_length, string* compressed) {
+  // Pre-grow the buffer to the max length of the compressed output
+  compressed->resize(MaxCompressedLength(input_length));
+
+  size_t compressed_length;
+  RawCompress(input, input_length, string_as_array(compressed),
+              &compressed_length);
+  compressed->resize(compressed_length);
+  return compressed_length;
+}
+
+
+} // end namespace snappy
+
diff --git a/src/devtools/meta/src/misc/snappy/snappy.h b/src/devtools/meta/src/misc/snappy/snappy.h
new file mode 100644
index 0000000..e879e79
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy.h
@@ -0,0 +1,184 @@
+// Copyright 2005 and onwards Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// A light-weight compression algorithm.  It is designed for speed of
+// compression and decompression, rather than for the utmost in space
+// savings.
+//
+// For getting better compression ratios when you are compressing data
+// with long repeated sequences or compressing data that is similar to
+// other data, while still compressing fast, you might look at first
+// using BMDiff and then compressing the output of BMDiff with
+// Snappy.
+
+#ifndef UTIL_SNAPPY_SNAPPY_H__
+#define UTIL_SNAPPY_SNAPPY_H__
+
+#include <stddef.h>
+#include <string>
+
+#include "snappy-stubs-public.h"
+
+namespace snappy {
+  class Source;
+  class Sink;
+
+  // ------------------------------------------------------------------------
+  // Generic compression/decompression routines.
+  // ------------------------------------------------------------------------
+
+  // Compress the bytes read from "*source" and append to "*sink". Return the
+  // number of bytes written.
+  size_t Compress(Source* source, Sink* sink);
+
+  // Find the uncompressed length of the given stream, as given by the header.
+  // Note that the true length could deviate from this; the stream could e.g.
+  // be truncated.
+  //
+  // Also note that this leaves "*source" in a state that is unsuitable for
+  // further operations, such as RawUncompress(). You will need to rewind
+  // or recreate the source yourself before attempting any further calls.
+  bool GetUncompressedLength(Source* source, uint32* result);
+
+  // ------------------------------------------------------------------------
+  // Higher-level string based routines (should be sufficient for most users)
+  // ------------------------------------------------------------------------
+
+  // Sets "*output" to the compressed version of "input[0,input_length-1]".
+  // Original contents of *output are lost.
+  //
+  // REQUIRES: "input[]" is not an alias of "*output".
+  size_t Compress(const char* input, size_t input_length, string* output);
+
+  // Decompresses "compressed[0,compressed_length-1]" to "*uncompressed".
+  // Original contents of "*uncompressed" are lost.
+  //
+  // REQUIRES: "compressed[]" is not an alias of "*uncompressed".
+  //
+  // returns false if the message is corrupted and could not be decompressed
+  bool Uncompress(const char* compressed, size_t compressed_length,
+                  string* uncompressed);
+
+
+  // ------------------------------------------------------------------------
+  // Lower-level character array based routines.  May be useful for
+  // efficiency reasons in certain circumstances.
+  // ------------------------------------------------------------------------
+
+  // REQUIRES: "compressed" must point to an area of memory that is at
+  // least "MaxCompressedLength(input_length)" bytes in length.
+  //
+  // Takes the data stored in "input[0..input_length]" and stores
+  // it in the array pointed to by "compressed".
+  //
+  // "*compressed_length" is set to the length of the compressed output.
+  //
+  // Example:
+  //    char* output = new char[snappy::MaxCompressedLength(input_length)];
+  //    size_t output_length;
+  //    RawCompress(input, input_length, output, &output_length);
+  //    ... Process(output, output_length) ...
+  //    delete [] output;
+  void RawCompress(const char* input,
+                   size_t input_length,
+                   char* compressed,
+                   size_t* compressed_length);
+
+  // Given data in "compressed[0..compressed_length-1]" generated by
+  // calling the Snappy::Compress routine, this routine
+  // stores the uncompressed data to
+  //    uncompressed[0..GetUncompressedLength(compressed)-1]
+  // returns false if the message is corrupted and could not be decrypted
+  bool RawUncompress(const char* compressed, size_t compressed_length,
+                     char* uncompressed);
+
+  // Given data from the byte source 'compressed' generated by calling
+  // the Snappy::Compress routine, this routine stores the uncompressed
+  // data to
+  //    uncompressed[0..GetUncompressedLength(compressed,compressed_length)-1]
+  // returns false if the message is corrupted and could not be decrypted
+  bool RawUncompress(Source* compressed, char* uncompressed);
+
+  // Given data in "compressed[0..compressed_length-1]" generated by
+  // calling the Snappy::Compress routine, this routine
+  // stores the uncompressed data to the iovec "iov". The number of physical
+  // buffers in "iov" is given by iov_cnt and their cumulative size
+  // must be at least GetUncompressedLength(compressed). The individual buffers
+  // in "iov" must not overlap with each other.
+  //
+  // returns false if the message is corrupted and could not be decrypted
+  bool RawUncompressToIOVec(const char* compressed, size_t compressed_length,
+                            const struct iovec* iov, size_t iov_cnt);
+
+  // Given data from the byte source 'compressed' generated by calling
+  // the Snappy::Compress routine, this routine stores the uncompressed
+  // data to the iovec "iov". The number of physical
+  // buffers in "iov" is given by iov_cnt and their cumulative size
+  // must be at least GetUncompressedLength(compressed). The individual buffers
+  // in "iov" must not overlap with each other.
+  //
+  // returns false if the message is corrupted and could not be decrypted
+  bool RawUncompressToIOVec(Source* compressed, const struct iovec* iov,
+                            size_t iov_cnt);
+
+  // Returns the maximal size of the compressed representation of
+  // input data that is "source_bytes" bytes in length;
+  size_t MaxCompressedLength(size_t source_bytes);
+
+  // REQUIRES: "compressed[]" was produced by RawCompress() or Compress()
+  // Returns true and stores the length of the uncompressed data in
+  // *result normally.  Returns false on parsing error.
+  // This operation takes O(1) time.
+  bool GetUncompressedLength(const char* compressed, size_t compressed_length,
+                             size_t* result);
+
+  // Returns true iff the contents of "compressed[]" can be uncompressed
+  // successfully.  Does not return the uncompressed data.  Takes
+  // time proportional to compressed_length, but is usually at least
+  // a factor of four faster than actual decompression.
+  bool IsValidCompressedBuffer(const char* compressed,
+                               size_t compressed_length);
+
+  // The size of a compression block. Note that many parts of the compression
+  // code assumes that kBlockSize <= 65536; in particular, the hash table
+  // can only store 16-bit offsets, and EmitCopy() also assumes the offset
+  // is 65535 bytes or less. Note also that if you change this, it will
+  // affect the framing format (see framing_format.txt).
+  //
+  // Note that there might be older data around that is compressed with larger
+  // block sizes, so the decompression code should not rely on the
+  // non-existence of long backreferences.
+  static const int kBlockLog = 16;
+  static const size_t kBlockSize = 1 << kBlockLog;
+
+  static const int kMaxHashTableBits = 14;
+  static const size_t kMaxHashTableSize = 1 << kMaxHashTableBits;
+}  // end namespace snappy
+
+
+#endif  // UTIL_SNAPPY_SNAPPY_H__