[Feature][ZXW-33]merge ZXW 0428 version

Change-Id: I11f167edfea428d9fab198ff00ff1364932d1b0b
diff --git a/ap/hostapp/zdownloader/CSerial.c b/ap/hostapp/zdownloader/CSerial.c
new file mode 100755
index 0000000..45f932f
--- /dev/null
+++ b/ap/hostapp/zdownloader/CSerial.c
@@ -0,0 +1,626 @@
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <sys/time.h>
+#include <string.h>
+#include <errno.h>
+#include "LogInfo.h"
+#include "CSerial.h"
+
+/*******************************************************************************
+ *                       		宏定义                                  *
+ *******************************************************************************/
+#define DEV_RSP_COUNT (1024)
+
+/*******************************************************************************
+ *                       		全局变量                                  *
+ *******************************************************************************/
+static int m_fd;
+static char rspBufex[DEV_RSP_COUNT] = {0};
+
+/*******************************************************************************
+ *                       			函数声明                                  *
+ *******************************************************************************/
+static ssize_t SendAT(const char *pData, size_t length);
+static ssize_t ReadAT(BYTE *pbyReadBuffer, size_t dwReadCount);
+
+
+/*******************************************************************************
+ *                       		内部函数                                  *
+ *******************************************************************************/
+/**
+ * @brief 发送AT命令
+ * @param pData      		入参,AT命令写入缓冲区
+ * @param length          	入参,AT命令长度
+ * @return 成功返回成功写入的字节数,失败返回-1
+ * @retval
+ * @note  length不计算结尾\0
+ * @warning
+ */
+static ssize_t SendAT(const char *pData, size_t length)
+{
+	ssize_t dwBytesWritten = -1;
+	ssize_t writeCount = 0;
+	struct timeval timeout;
+	fd_set fds, temps;
+	int result = 0;
+
+	if (m_fd < 0)
+	{
+		return -1;
+	}
+	if (pData != NULL)
+	{
+		LogInfo("pData= (%s)  length = %ld ", pData, length);
+	}
+
+	// gettimeofday(&end, NULL);
+	// gettimeofday(&begin, NULL);
+	FD_ZERO(&fds);
+	FD_SET(m_fd, &fds);
+	/* 超时不能在此设置!
+	因为调用select后,结构体timeval的成员tv_sec和tv_usec的值将被替换为超时前剩余时间.
+	调用select函数前,每次都需要初始化timeval结构体变量.
+	timeout.tv_sec = 1;
+	timeout.tv_usec = 0; */
+
+	while (1)
+	{
+		/* 将准备好的fd_set变量reads的内容复制到temps变量,因为调用select函数后,除了发生变化的fd对应位外,
+		剩下的所有位都将初始化为0,为了记住初始值,必须经过这种复制过程。*/
+		temps = fds;
+		// 设置超时
+		timeout.tv_sec = 1;
+		timeout.tv_usec = 0;
+		// 调用select函数
+		result = select(m_fd + 1, NULL, &temps, NULL, &timeout);
+		if (result <= 0)
+		{
+			if (0 == result)
+			{
+				LogInfo("timeout");
+			}
+			else
+			{
+				LogInfo("select() error");
+			}
+			break;
+			// return -1;
+		}
+		else
+		{
+			// 判断m_fd是否可写,若可写,写入数据
+			if (FD_ISSET(m_fd, &temps))
+			{
+				dwBytesWritten = write(m_fd, pData + writeCount, length - writeCount);
+				LogInfo("pData= (%s)  dwBytesWritten = %ld ", pData, dwBytesWritten);
+				if (dwBytesWritten > 0)
+				{
+					writeCount += dwBytesWritten;
+					if (writeCount >= length)
+					{
+						break;
+					}
+				}
+				if (dwBytesWritten < 0 && errno != EINTR)
+				{
+					printf("SendAT:: write error, dwBytesWritten = %ld, %s\r\n", dwBytesWritten, strerror(errno));
+					break;
+				}
+			}
+		}
+	}
+
+	if (dwBytesWritten > 0)
+	{
+		return dwBytesWritten;
+	}
+	else
+	{
+		return -1;
+	}
+}
+
+/**
+ * @brief 接收AT命令应答
+ * @param pbyReadBuffer      		出参,应答读取缓冲区
+ * @param dwReadCount          		入参,应答读取长度
+ * @return 成功返回成功写入的字节数,失败返回-1
+ * @retval
+ * @note
+ * @warning
+ */
+static ssize_t ReadAT(BYTE *pbyReadBuffer, size_t dwReadCount)
+{
+	ssize_t dwBytesRead = -1;
+	ssize_t readCount = 0;
+	int result;
+	fd_set fds, temps;
+	struct timeval timeout;
+
+	if (m_fd < 0)
+	{
+		return -1;
+	}
+	LogInfo("ReadAT start");
+
+	FD_ZERO(&fds);
+	FD_SET(m_fd, &fds);
+
+	while (1)
+	{
+		temps = fds;
+		// 设置超时
+		timeout.tv_sec = 1;
+		timeout.tv_usec = 0;
+		// 调用select函数
+		result = select(m_fd + 1, &temps, NULL, NULL, &timeout);
+		if (result <= 0)
+		{
+			if (0 == result)
+			{
+				LogInfo("timeout");
+			}
+			else
+			{
+				LogInfo("select() error");
+			}
+			return -1;
+		}
+		else
+		{
+			// 判断m_fd是否可读,若可读,读取数据
+			if (FD_ISSET(m_fd, &temps))
+			{
+				dwBytesRead = read(m_fd, pbyReadBuffer + readCount, dwReadCount - readCount);
+				LogInfo("pData= (%s)  dwBytesWritten = %ld ", pbyReadBuffer, dwBytesRead);
+				if (dwBytesRead > 0)
+				{
+					readCount += dwBytesRead;
+					if (readCount >= dwReadCount)
+					{
+						break;
+					}
+				}
+				if (dwBytesRead < 0 && errno != EINTR)
+				{
+					printf("ReadAT::read error, dwBytesRead = %ld, %s\r\n", dwBytesRead, strerror(errno));
+					break;
+				}
+			}
+		}
+	}
+
+	if (dwBytesRead > 0)
+	{
+		return dwBytesRead;
+	}
+	else
+	{
+		return -1;
+	}
+}
+
+
+/*******************************************************************************
+ *                       		外部函数                                  *
+ *******************************************************************************/
+/**
+ * @brief 打开设备文件,并设置波特率等参数
+ * @param  portName                  入参,端口名
+ * @return 成功返回0,失败返回-1
+ * @retval
+ * @note
+ * @warning
+ */
+int Open(const char *portName)
+{
+	// char portname_full[20] = "/dev/";
+	// strcat(portname_full, portName);
+	// portName = +portName ;
+
+	struct termios attr;
+	int flags;
+
+	if (portName != NULL)
+	{
+		LogInfo("portname = (%s)", portName);
+	}
+	m_fd = open(portName, O_RDWR | O_NONBLOCK | O_NOCTTY | O_TRUNC);
+	if (m_fd < 0)
+	{
+		LogInfo("Open m_fd < 0 m_fd = %d\n", m_fd);
+		return -1;
+	}
+	else
+	{
+		LogInfo("Open m_fd > 0 m_fd = %d\n", m_fd);
+	}
+	tcflush(m_fd, TCIOFLUSH); // clear serial data
+	if (tcgetattr(m_fd, &attr) < 0)
+	{
+		close(m_fd);
+		return -1;
+	}
+	attr.c_iflag = IXON | IXOFF;
+	attr.c_oflag = 0;
+	attr.c_cflag &= ~(CSIZE | CFLAGS_TO_CLEAR | CFLAGS_HARDFLOW);
+	attr.c_cflag |= (CS8 | CFLAGS_TO_SET);
+	attr.c_cflag |= CFLAGS_HARDFLOW;
+	attr.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ISIG);
+	attr.c_lflag &= ~OPOST;
+	int i;
+#ifdef _POSIX_VDISABLE
+	attr.c_cc[0] = _POSIX_VDISABLE;
+#else
+	attr.c_cc[0] = fpathconf(m_fd, _PC_VDISABLE);
+#endif
+
+	for (i = 1; i < NCCS; i++)
+	{
+		attr.c_cc[i] = attr.c_cc[0];
+	}
+
+	attr.c_cc[VMIN] = 0;
+	attr.c_cc[VTIME] = 5;
+	cfsetispeed(&attr, BAUDRATE);
+	cfsetospeed(&attr, BAUDRATE);
+	if (tcsetattr(m_fd, TCSANOW, &attr) < 0)
+	{
+		close(m_fd);
+		return -1;
+	}
+	flags = fcntl(m_fd, F_GETFL, 0);
+	if (flags < 0)
+	{
+		close(m_fd);
+		return -1;
+	}
+	if (fcntl(m_fd, F_SETFL, flags) < 0)
+	{
+		close(m_fd);
+		return -1;
+	}
+	// m_isOpen = true;
+	// StartRead();
+	return 0;
+}
+
+/**
+ * @brief 关闭设备文件
+ * @param  无
+ * @return 成功关闭返回0,否则返回-1
+ * @retval
+ * @note
+ * @warning
+ */
+int Close()
+{
+	tcflush(m_fd, TCIOFLUSH); // clear serial data
+	if (m_fd > 0)
+	{
+		// printf("close m_fd\n");
+		close(m_fd);
+	}
+	else
+	{
+		printf("%s:: close->else\n", __FUNCTION__);
+		return -1;
+	}
+	m_fd = 0;
+	return 0;
+}
+
+/**
+ * @brief 发送AT命令并读取返回值
+ * @param Dev_tty      			入参,打开的AT口设备路径
+ * @param AtString      		入参,发送的AT命令字符串
+ * @param RebackString          出参,AT命令返回的字符串
+ * @return 成功返回0,失败返回-1
+ * @retval
+ * @note
+ * @warning
+ */
+int SendATString(const char *Dev_tty, const char *AtString, char *RebackString)
+{
+	BYTE tmp[1024] = {0};
+
+	printf("%s:: Before Open port, (%s)\n", __FUNCTION__, Dev_tty);
+	if (-1 == (Open(Dev_tty)))
+	{
+		if (AtString != NULL)
+		{
+			LogInfo("SendATString Failed AtString = (%s)", AtString);
+		}
+		printf("%s:: Open port error\r\n", __FUNCTION__);
+		return -1;
+	}
+	if (AtString != NULL)
+	{
+		LogInfo("SendATString OK, AtString = (%s)", AtString);
+	}
+
+	LogInfo("Before SendAT");
+	if(SendAT(AtString, strlen(AtString)) < 0)
+	{
+		LogInfo("SendAT failed");
+		Close();
+		return -1;
+	}	
+	LogInfo("After SendAT");
+
+	ReadAT(tmp, 1024);
+	LogInfo("out ReadAT");
+
+	memcpy(RebackString, tmp, 1024);
+	LogInfo("after memcpy");
+
+	Close();
+	return 0;
+}
+
+/**
+ * @brief 发送数据
+ * @param pbyWriteBuffer      			入参,写入数据缓冲区
+ * @param dwWriteCount          		入参,写入数据长度
+ * @param dwSleepAfterAction      		入参,
+ * @param dwTimeoutCount          		入参,超时时间,单位秒
+ * @return 成功返回TRUE,失败返回FALSE
+ * @retval
+ * @note
+ * @warning
+ */
+BOOL SendData(const BYTE *pbyWriteBuffer, size_t dwWriteCount, DWORD dwSleepAfterAction, DWORD dwTimeoutCount)
+{
+	ssize_t sBytesWritten = -1;
+	ssize_t writeCount = 0;	
+	struct timeval timeout;
+	fd_set fds, temps;
+	int result = 0;
+	// int count = 0; // 超时计数
+
+	LogInfo("writecount %d, timeout %d s", dwWriteCount, dwTimeoutCount);
+	if (m_fd < 0)
+	{
+		LogInfo("m_fd < 0");
+		return FALSE;
+	}
+
+	FD_ZERO(&fds);
+	FD_SET(m_fd, &fds);
+
+	tcflush(m_fd, TCIOFLUSH); // clear serial data
+
+	if (dwTimeoutCount < 10)
+	{
+		dwTimeoutCount = 10;
+	}
+	/* 超时不能在此设置!
+	因为调用select后,结构体timeval的成员tv_sec和tv_usec的值将被替换为超时前剩余时间.
+	调用select函数前,每次都需要初始化timeval结构体变量.
+	timeout.tv_sec = 1;
+	timeout.tv_usec = 0; */
+
+	while (1)
+	{
+		/*将准备好的fd_set变量reads的内容复制到temps变量,因为调用select函数后,除了发生变化的fd对应位外,
+		剩下的所有位都将初始化为0,为了记住初始值,必须经过这种复制过程。*/
+		temps = fds;
+		// 设置超时
+		timeout.tv_sec = dwTimeoutCount;
+		timeout.tv_usec = 0;
+		// 调用select函数
+		result = select(m_fd + 1, NULL, &temps, NULL, &timeout);
+		LogInfo("select result = %d ", result);
+		if (-1 == result)
+		{
+			LogInfo("select() error\n");
+			perror("SendData:: select() error\n");
+			break;
+		}
+		else if (0 == result)
+		{
+			puts("SendData:: timeout\r\n");
+			break;
+		}
+		else
+		{
+			// 判断m_fd是否可写,若可写,写入数据
+			if (FD_ISSET(m_fd, &temps))
+			{
+				sBytesWritten = write(m_fd, (char *)pbyWriteBuffer + writeCount, dwWriteCount - writeCount);
+				LogInfo("pbyWriteBuffer= (%s)  dwBytesWritten = %ld ", pbyWriteBuffer, sBytesWritten);
+				if (sBytesWritten > 0)
+				{
+					writeCount += sBytesWritten;
+					if (writeCount >= dwWriteCount)
+					{
+						return TRUE; // complete success
+					}
+				}
+				else
+				{
+					if (sBytesWritten < 0 && errno != EINTR)
+					{
+						printf("SendData::write error, dwBytesWritten = %ld, %s\r\n", sBytesWritten, strerror(errno));
+					}
+					return FALSE;
+				}
+			}
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * @brief 接收数据
+ * @param pbyReadBuffer      			入参,读取数据缓冲区
+ * @param dwReadCount          			入参,读取数据长度
+ * @param dwSleepAfterAction      		入参,
+ * @param dwTimeoutCount          		入参,超时时间,单位秒
+ * @return 成功返回TRUE,失败返回FALSE
+ * @retval
+ * @note
+ * @warning
+ */
+BOOL ReadData(BYTE *pbyReadBuffer, size_t dwReadCount, DWORD dwSleepAfterAction, DWORD dwTimeoutCount)
+{
+	ssize_t sBytesReadn = -1;
+	ssize_t readCount = 0;	
+	int result;
+	fd_set fds, temps;
+	struct timeval timeout;
+	// int readCount = 0;
+	// int count = 0; // 超时计数
+
+	LogInfo("ReadData reacount %d, timeout %d s\n", dwReadCount, dwTimeoutCount);
+	if (m_fd < 0)
+	{
+		LogInfo("m_fd < 0");
+		return -1;
+	}
+
+	FD_ZERO(&fds);
+	FD_SET(m_fd, &fds);
+
+	if (dwTimeoutCount < 10)
+	{
+		dwTimeoutCount = 10;
+	}
+
+	while (1)
+	{
+		temps = fds;
+		timeout.tv_sec = dwTimeoutCount;
+		timeout.tv_usec = 0;
+
+		result = select(m_fd + 1, &temps, NULL, NULL, &timeout);
+		LogInfo("select result = %d ", result);
+		if (-1 == result)
+		{
+			LogInfo("select() error\n");
+			perror("ReadData:: select() error\n");
+			break;
+		}
+		else if (0 == result)
+		{
+			puts("ReadData:: timeout\n");
+			break;
+		}
+		else
+		{
+			// 判断m_fd是否可读,若可读,读取数据
+			if (FD_ISSET(m_fd, &temps))
+			{
+				sBytesReadn = read(m_fd, pbyReadBuffer + readCount, dwReadCount - readCount);
+				LogInfo("pbyReadBuffer= (%s)  sBytesReadn = %ld ", pbyReadBuffer, sBytesReadn);
+				if (sBytesReadn > 0)
+				{
+					readCount += sBytesReadn;
+					if (readCount >= dwReadCount)
+					{
+						return TRUE; // complete success
+					}
+				}
+				else
+				{
+					if (sBytesReadn < 0 && errno != EINTR)
+					{
+						printf("ReadData::read error, sBytesReadn = %ld, %s\r\n", sBytesReadn, strerror(errno));
+					}
+					return FALSE;
+				}
+			}
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * @brief 接收数据缓冲
+ * @param dwReadCount          			入参,读取数据长度
+ * @param dwSleepAfterAction      		入参,
+ * @param dwTimeoutCount          		入参,超时时间,单位秒
+ * @return 成功返回读取的数据指针,失败返回NULL
+ * @retval
+ * @note
+ * @warning
+ */
+BYTE *ReadDataExtraFuncB(DWORD dwReadCount, DWORD dwSleepAfterAction, DWORD dwTimeoutCount)
+{
+	ssize_t sBytesReadn = -1;
+	ssize_t readCount = 0;
+	int result;
+	fd_set fds, temps;
+	struct timeval timeout;
+
+	LogInfo("readcount %d, timeout %d s", dwReadCount, dwTimeoutCount);
+
+	memset(rspBufex, 0, DEV_RSP_COUNT);
+
+	if (m_fd < 0)
+	{
+		LogInfo("m_fd < 0");
+		return rspBufex;
+	}
+
+	FD_ZERO(&fds);
+	FD_SET(m_fd, &fds);
+
+	if (dwTimeoutCount < 10)
+	{
+		dwTimeoutCount = 10;
+	}
+
+	while (1)
+	{
+		temps = fds;
+		timeout.tv_sec = dwTimeoutCount;
+		timeout.tv_usec = 0;
+
+		result = select(m_fd + 1, &fds, NULL, NULL, &timeout);
+		LogInfo("select result = %d ", result);
+		if (-1 == result)
+		{
+			LogInfo("select() error\n");
+			perror("ReadDataExtraFuncB:: select() error\n");
+			break;
+		}
+		else if (0 == result)
+		{
+			puts("ReadDataExtraFuncB:: timeout\n");
+			break;
+		}
+		else
+		{
+			// 判断m_fd是否可读,若可读,读取数据
+			if (FD_ISSET(m_fd, &temps))
+			{
+				sBytesReadn = read(m_fd, rspBufex + readCount, DEV_RSP_COUNT - readCount);
+				LogInfo("pbyReadBuffer= (%s)  sBytesReadn = %ld ", rspBufex, sBytesReadn);
+				if (sBytesReadn > 0)
+				{
+					readCount += sBytesReadn;
+					printf("ReadDataExtraFuncB:: readCount = %ld, dwReadCount = %d \r\n", readCount, dwReadCount);
+					if (readCount >= dwReadCount)
+					{
+						break; // complete success
+					}
+				}
+				else
+				{
+					if (sBytesReadn < 0 && errno != EINTR)
+					{
+						printf("ReadData::read error, sBytesReadn = %ld, %s\r\n", sBytesReadn, strerror(errno));
+					}
+					break;
+				}
+			}
+		}
+	}
+	LogInfo("rspBufex = (%s)", rspBufex);
+
+	return rspBufex;
+}
diff --git a/ap/hostapp/zdownloader/CSerial.h b/ap/hostapp/zdownloader/CSerial.h
new file mode 100755
index 0000000..67e67fe
--- /dev/null
+++ b/ap/hostapp/zdownloader/CSerial.h
@@ -0,0 +1,20 @@
+#ifndef CSERIAL_H_INCLUDED
+#define CSERIAL_H_INCLUDED
+
+#include "define.h"
+
+#define BAUDRATE 		B115200
+#define READLENGTH 		1024
+#define CFLAGS_TO_SET 	(CREAD | HUPCL)
+#define CFLAGS_TO_CLEAR (CSTOPB | PARENB | CLOCAL)
+#define CFLAGS_HARDFLOW (CRTSCTS)
+
+int Open(const char *portName);
+int Close();
+/* send AT cmd, and return */
+int SendATString(const char *Dev_tty, const char *AtString, char *RebackString);
+BOOL SendData(const BYTE *pbyWriteBuffer, size_t dwWriteCount, DWORD dwSleepAfterAction, DWORD dwTimeoutCount);
+BOOL ReadData(BYTE *pbyWriteBuffer, size_t dwWriteCount, DWORD dwSleepAfterAction, DWORD dwTimeoutCount);
+BYTE *ReadDataExtraFuncB(DWORD dwReadCount, DWORD dwSleepAfterAction,DWORD dwTimeoutCount);
+
+#endif // CSERIAL_H_INCLUDED
diff --git "a/ap/hostapp/zdownloader/Linux\345\271\263\345\217\260zdownloader\345\212\237\350\203\275\344\275\277\347\224\250\344\273\213\347\273\215.pdf" "b/ap/hostapp/zdownloader/Linux\345\271\263\345\217\260zdownloader\345\212\237\350\203\275\344\275\277\347\224\250\344\273\213\347\273\215.pdf"
new file mode 100755
index 0000000..d61147d
--- /dev/null
+++ "b/ap/hostapp/zdownloader/Linux\345\271\263\345\217\260zdownloader\345\212\237\350\203\275\344\275\277\347\224\250\344\273\213\347\273\215.pdf"
Binary files differ
diff --git a/ap/hostapp/zdownloader/LogInfo.c b/ap/hostapp/zdownloader/LogInfo.c
new file mode 100755
index 0000000..4a6d6db
--- /dev/null
+++ b/ap/hostapp/zdownloader/LogInfo.c
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <time.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "LogInfo.h"
+#include "define.h"
+
+#define LOG_ENTRY_SIZE (BUFSIZ * 8)
+
+static int s_log_flag = 0;
+static char s_file_name[FILE_NAME_LENGTH_MAX] = {0};
+// char g_log_path[FOLDER_PATH_LENGTH_MAX] = LOG_PATH;
+
+/* 保存Log信息到文件 */
+void DownLoad_LogInfo(const int line, const char *fn,
+					  const char *func_name, const char *fmt, ...)
+{
+
+	char log_fn[FILE_PATH_LENGTH_MAX] = {0};
+	struct timeval t;
+	FILE *fp_log = NULL;
+
+	gettimeofday(&t, NULL);
+	struct tm *p = localtime(&t.tv_sec);
+
+	if(s_log_flag == 0)
+	{
+		strftime(s_file_name, FILE_NAME_LENGTH_MAX, "%Y-%m-%d_%H%M%S", p);
+		s_log_flag = 1;
+	}	
+	snprintf(log_fn, FILE_PATH_LENGTH_MAX, "%s/downloader_%s.log", g_log_path, s_file_name);	
+	fp_log = fopen(log_fn, "a+");
+
+	va_list arglist;
+	static char buffer[LOG_ENTRY_SIZE] = ("");
+	static char tmp[LOG_ENTRY_SIZE] = ("");
+
+	va_start(arglist, fmt);
+	vsnprintf(tmp, LOG_ENTRY_SIZE, fmt, arglist);
+	va_end(arglist);
+	sprintf(buffer, "[%d-%d-%d %d:%d:%d.%ld] <%s>: #%d @ %s\n \t %s\n",
+			(1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday,
+			p->tm_hour, p->tm_min, p->tm_sec, t.tv_usec,
+			func_name,
+			line, fn, tmp);
+
+	if (NULL != fp_log)
+	{
+		fprintf(fp_log, ("%s"), buffer);
+		fclose(fp_log);
+	}
+}
diff --git a/ap/hostapp/zdownloader/LogInfo.h b/ap/hostapp/zdownloader/LogInfo.h
new file mode 100755
index 0000000..f0103b2
--- /dev/null
+++ b/ap/hostapp/zdownloader/LogInfo.h
@@ -0,0 +1,16 @@
+#ifndef _DOWNLOADER_LOGINFO_H_
+#define _DOWNLOADER_LOGINFO_H_
+
+#define LOGBOTTON 				(1)
+#define DEFAULT_LOG_PATH 		("/tmp")
+
+void DownLoad_LogInfo(const int line, const char *fn, 
+					 const char *func_name, const char *fmt, ...);
+
+#if (LOGBOTTON==1)
+#define LogInfo(fmt, ...)	DownLoad_LogInfo(__LINE__, __FILE__, __FUNCTION__, fmt, ##__VA_ARGS__)
+#else
+#define LogInfo(fmt, ...)
+#endif
+
+#endif
\ No newline at end of file
diff --git a/ap/hostapp/zdownloader/Makefile b/ap/hostapp/zdownloader/Makefile
new file mode 100755
index 0000000..ccea03e
--- /dev/null
+++ b/ap/hostapp/zdownloader/Makefile
@@ -0,0 +1,19 @@
+

+CC=gcc -g

+RM = rm

+INCLUDES += -I./

+CFLAGS +=  $(INCLUDES)

+OBJS =  main.o CSerial.o LogInfo.o download.o devUsb.o

+LIBS += #-lpthread

+TARGET = zdownloader

+

+all:$(TARGET)

+$(TARGET):$(OBJS) $(LIBS)

+	$(CC) $(OBJS) $(LIBS) -o $@

+	

+%o:%cpp

+	$(CC) -c $(CFLAGS) $(LIBS) $< -o $@

+

+clean:

+	-$(RM) *.o $(TARGET)

+	

diff --git a/ap/hostapp/zdownloader/define.h b/ap/hostapp/zdownloader/define.h
new file mode 100755
index 0000000..cda42d4
--- /dev/null
+++ b/ap/hostapp/zdownloader/define.h
@@ -0,0 +1,34 @@
+#ifndef _DEFINE_H_
+#define _DEFINE_H_
+
+#define FALSE   		        (0)
+#define TRUE    		        (1)
+
+#define FOLDER_PATH_LENGTH_MAX  (256)
+#define FILE_NAME_LENGTH_MAX 	(128)
+#define FILE_PATH_LENGTH_MAX 	(512)
+
+typedef unsigned char 	BYTE;
+typedef unsigned int 	DWORD;
+typedef unsigned long 	ULONG;
+typedef int  			BOOL;
+typedef unsigned short 	WORD;
+typedef enum  
+{  
+    Download_OK = 0,//下载成功
+	Download_NOT_ROOT,//非root权限执行下载应用
+	Download_ERROR_INPUT_ARGC,//参数错误,比如没有带参数执行下载应用
+    Download_CHECK_BIN_FAIL,//校验传入参数的bin文件是否合法
+	Download_FIND_AT_FAIL,//找不到AT口
+	Download_SAME_VERSION_NONEED_DL,//下载前读取软件版本,如果相同则不下载,此功能视用户需求可有可无,但是枚举值保留
+    Download_AT_OPEN_DL_FAIL,//下载前发AT指令打开DL下载端口失败,此功能视用户需求可有可无,但是枚举值保留
+	Download_OPENDLPORT_FAIL,//打开下载端口失败,openport失败
+	Download_DOWNLOAD_IMAGE_FAIL,//下载版本文件失败
+	Download_CHECK_VERSION_FAIL,//下载完成后,校验版本失败,此功能视用户需求可有可无,但是枚举值保留
+	Download_AT_CLOSE_DL_FAIL,
+	Download_NONE//未定义
+}enERRORCODE;
+
+char g_log_path[FOLDER_PATH_LENGTH_MAX];
+
+#endif
diff --git a/ap/hostapp/zdownloader/devUsb.c b/ap/hostapp/zdownloader/devUsb.c
new file mode 100755
index 0000000..e48075e
--- /dev/null
+++ b/ap/hostapp/zdownloader/devUsb.c
@@ -0,0 +1,183 @@
+/*******************************************************************************

+* 版权所有 (C)2016, 中兴通讯股份有限公司。

+* 

+* 文件名称:     usb_dev.c

+* 文件标识:     usb_dev.c

+* 内容摘要:     usb设备访问工具

+* 

+* 修改日期        版本号      修改标记        修改人          修改内容

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

+* 2016/3/10      V1.0        Create                             创建

+* 

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

+

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

+*                                   头文件                                     *

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

+#include<stdlib.h>

+#include<stdio.h>

+#include<string.h>

+#include<sys/types.h>

+#include<sys/stat.h>

+#include<fcntl.h>

+#include<errno.h>

+#include<getopt.h>

+#include<stdarg.h>

+#include<termios.h>

+#include<stddef.h>

+#include<dirent.h>

+#include <unistd.h>

+

+#include "devUsb.h"

+

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

+*                                   宏定义                                     *

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

+#define USB_DIR_FILE_NAME_SIZE (512)

+#define USB_DIR_BASE           ("/sys/bus/usb/devices")

+#define SUCCESS                (0)

+#define FAIL                   (-1)

+

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

+*                                  变量定义                                    *

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

+

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

+*                                数据类型定义                                  *

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

+

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

+*                                函数声明                                  *

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

+static int dev_get_usbsys_val(const char *sys_filename, int base);

+static int dev_strStartsWith(const char *line, const char *src);

+static int dev_get_ttyport_by_syspath(char *syspath);

+

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

+*                              局部静态变量声明                                *

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

+static char sys_filename[USB_DIR_FILE_NAME_SIZE] = {0};

+

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

+*                                全局变量定义                                  *

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

+int g_usb_dev = -1;

+

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

+*                                局部函数实现                                  *

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

+static int dev_get_usbsys_val(const char *sys_filename, int base)

+{

+	char buff[64] = {0};

+	int ret_val = -1;

+	int fd = -1;

+

+	fd = open(sys_filename, O_RDONLY);

+	if (fd < 0) {

+		// printf("failed to open usbsys, error is %s\n", strerror(errno));

+		return FAIL;

+	}

+

+	if (read(fd, buff, sizeof(buff)) <= 0) {

+		printf("[%s] read:%s failed\n", __func__, sys_filename);

+	}

+	else {

+		ret_val = strtoul(buff, NULL, base);

+	}

+	close(fd);

+

+	return ret_val;

+}

+

+static int dev_strStartsWith(const char *line, const char *src)

+{

+	int ret = -1;

+

+	for ( ; *line != '\0' && *src != '\0'; line++, src++) {

+		if (*line != *src) {

+			return FAIL;

+		}

+	}

+	ret = atoi(line);

+	return ret;

+}

+

+static int dev_get_ttyport_by_syspath(char *syspath)

+{

+	DIR *usbdir = NULL;

+	struct dirent *dent = NULL;

+	int usb_port = -1;

+

+	usbdir = opendir(syspath);

+	if (usbdir == NULL) {

+		printf("%s: open [%s] busdir failed\n", __func__, syspath);

+		return FAIL;

+	}

+

+	while ((dent = readdir(usbdir)) != NULL)

+	{

+		usb_port = dev_strStartsWith(dent->d_name, "ttyUSB");

+		if ( usb_port >= 0) {

+			closedir(usbdir);

+			usbdir = NULL;

+			return usb_port;

+		}

+	}

+

+	if (usbdir) {

+		closedir(usbdir);

+		usbdir = NULL;

+	}

+	return FAIL;

+}

+

+int dev_get_device(int *pPortInfo)

+{

+	DIR *usbdir = NULL;

+	struct dirent *dent = NULL;

+	int idVendor = 0, idProduct = 0;

+	int bConfigurationValue = 0;

+	int num = 0;

+	usbdir = opendir(USB_DIR_BASE);

+	if (usbdir == NULL)

+		return -1;

+

+	while ((dent = readdir(usbdir)) != NULL){

+		if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) {

+			continue;

+		}

+

+        snprintf(sys_filename, sizeof(sys_filename), "%s/%s/idVendor", USB_DIR_BASE, dent->d_name);

+        if ((idVendor = dev_get_usbsys_val(sys_filename, 16)) <= 0) {

+            continue;

+        }

+

+		snprintf(sys_filename, sizeof(sys_filename), "%s/%s/idProduct", USB_DIR_BASE, dent->d_name);

+		if ((idProduct = dev_get_usbsys_val(sys_filename, 16)) <= 0) {

+			continue;

+		}

+

+		snprintf(sys_filename, sizeof(sys_filename), "%s/%s/bConfigurationValue", USB_DIR_BASE, dent->d_name);

+		if ((bConfigurationValue = dev_get_usbsys_val(sys_filename, 10)) <= 0) {

+			continue;

+		}

+

+		if (idVendor == pPortInfo[0] && idProduct == pPortInfo[1]){

+			snprintf(sys_filename, sizeof(sys_filename), "%s/%s/%s:%d.%d", USB_DIR_BASE, dent->d_name, dent->d_name, bConfigurationValue, pPortInfo[2]);

+			g_usb_dev = dev_get_ttyport_by_syspath(sys_filename);

+            printf("port found: /dev/ttyUSB%d -- %s\n", g_usb_dev, sys_filename);

+			closedir(usbdir);

+			usbdir = NULL;

+			return 0;

+		}

+        usleep(10000);

+	}

+	if (usbdir) {

+		closedir(usbdir);

+		usbdir = NULL;

+	}

+	printf("Can not find port.\n");

+

+	return -1;

+}

+

diff --git a/ap/hostapp/zdownloader/devUsb.h b/ap/hostapp/zdownloader/devUsb.h
new file mode 100755
index 0000000..8745a41
--- /dev/null
+++ b/ap/hostapp/zdownloader/devUsb.h
@@ -0,0 +1,8 @@
+#ifndef _DEV_USB_H_

+#define _DEV_USB_H_

+

+int g_usb_dev;

+

+int dev_get_device(int *pPortInfo);

+

+#endif
\ No newline at end of file
diff --git a/ap/hostapp/zdownloader/download.c b/ap/hostapp/zdownloader/download.c
new file mode 100755
index 0000000..500f89c
--- /dev/null
+++ b/ap/hostapp/zdownloader/download.c
@@ -0,0 +1,2053 @@
+
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+// #include <io.h>
+#include "LogInfo.h"
+#include "CSerial.h"
+#include "download.h"
+
+/*******************************************************************************
+ *                       			宏定义                                  *
+ *******************************************************************************/
+#define ERASENVRW            (0)
+#define LOWORD(l)            ((WORD)(l))
+#define MAXFILENUM           (50)
+// 大小端转换
+#define ExchangeEndian(data) (data = ((data >> 24) & 0x000000FF) | ((data >> 8) & 0x0000FF00) | ((data << 8) & 0x00FF0000) | ((data << 24) & 0xFF000000))
+
+/*******************************************************************************
+ *                       			全局变量                                  *
+ *******************************************************************************/
+const stSTAT m_DownloadImageTable[] =
+	{
+		{STAT_TERMINATE, STAT_TERMINATE},		   // 0
+		{STAT_TERMINATE, STAT_TERMINATE},		   // 1
+		{STAT_TERMINATE, STAT_TERMINATE},		   // 2
+		{STAT_TERMINATE, STAT_TERMINATE},		   // 3
+		{STAT_TERMINATE, STAT_TERMINATE},		   // 4
+		{STAT_EXECUTE_CODE, STAT_TERMINATE},	   // 5
+		{STAT_ERASE_SEG_ST_ADDR, STAT_TERMINATE},  // 6
+		{STAT_TERMINATE, STAT_TERMINATE},		   // 7
+		{STAT_TERMINATE, STAT_TERMINATE},		   // 8
+		{STAT_PROG_DEV_END_ADDR, STAT_TERMINATE},  // 9
+		{STAT_SET_PACKET_SIZE, STAT_TERMINATE},	   // 10
+		{STAT_DATAPACKET, STAT_TERMINATE},		   // 11
+		{STAT_TERMINATE, STAT_TERMINATE},		   // 12
+		{STAT_ERASE_SEG_END_ADDR, STAT_TERMINATE}, // 13
+		{STAT_PROG_DEV_ST_ADDR, STAT_TERMINATE},   // 14
+		{STAT_TERMINATE, STAT_TERMINATE},		   // 15
+		{STAT_TERMINATE, STAT_TERMINATE},		   // 16
+		{STAT_TERMINATE, STAT_TERMINATE}		   // 17
+};
+
+const stSTAT m_DownloadRAMImageTable[] =
+	{
+		{STAT_TERMINATE, STAT_TERMINATE},		  // 0
+		{STAT_TERMINATE, STAT_TERMINATE},		  // 1
+		{STAT_TERMINATE, STAT_TERMINATE},		  // 2
+		{STAT_TERMINATE, STAT_TERMINATE},		  // 3
+		{STAT_TERMINATE, STAT_TERMINATE},		  // 4
+		{STAT_EXECUTE_CODE, STAT_TERMINATE},	  // 5
+		{STAT_PROG_DEV_ST_ADDR, STAT_TERMINATE},  // 6
+		{STAT_TERMINATE, STAT_TERMINATE},		  // 7
+		{STAT_TERMINATE, STAT_TERMINATE},		  // 8
+		{STAT_PROG_DEV_END_ADDR, STAT_TERMINATE}, // 9
+		{STAT_SET_PACKET_SIZE, STAT_TERMINATE},	  // 10
+		{STAT_DATAPACKET, STAT_TERMINATE},		  // 11
+		{STAT_TERMINATE, STAT_TERMINATE},		  // 12
+		{STAT_TERMINATE, STAT_TERMINATE},		  // 13
+		{STAT_TERMINATE, STAT_TERMINATE},		  // 14
+		{STAT_TERMINATE, STAT_TERMINATE},		  // 15
+		{STAT_TERMINATE, STAT_TERMINATE},		  // 16
+		{STAT_TERMINATE, STAT_TERMINATE}		  // 17
+};
+
+FILE *pf = NULL;			 // 版本文件FILE指针
+char g_path[FILE_PATH_LENGTH_MAX]; // 版本文件路径
+DWORD m_dwPartitionSize;
+DWORD m_dwBootStage1StartAddress; // Tloader起始地址
+DWORD m_dwBootStage1Size;		  // Tloader大小
+DWORD m_dwBootStage2StartAddress; // Tboot起始地址
+DWORD m_dwBootStage2Size;		  // Tboot大小
+DWORD m_iFileNum;				  // 文件总数
+BOOL m_StartAMT;
+BOOL m_StartAMT_MODEM;
+BOOL m_StartAMT_AP;
+BOOL m_bBackUpNV;
+BOOL m_bCRCCheck; // CRC校验标志位
+const stSTAT *m_pProtocolTable;
+stBinMasterInfo m_stMasterInfo;	 // 大BIN版本head结构
+stFileItem FileItem[MAXFILENUM]; // 用于存放image信息
+int g_DownLoadFileNum = 0;		 // 真正要下载的文件个数
+
+/*******************************************************************************
+ *                       			声明                                  *
+ *******************************************************************************/
+// 擦除NVRW
+static BOOL EraseNVRW();
+// 对下载文件进行解析
+static BOOL PreInitBoot();
+
+// 下载boot
+static BOOL DownloadOneBoot(DWORD dwBootStartAddress, DWORD dwBootSize, FILE *pBootFile, size_t dwPacketSize, DWORD dwOffset, BOOL SYNC);
+// 同步, 配置分区
+static BOOL DownloadPartition(size_t dwPartitionSize, FILE *pFile, DWORD dwPacketSize, DWORD dwOffset, BOOL bCheckPartition);
+// 释放boot资源
+static BOOL UnPreInitBoot();
+
+// 下载版本文件前初始化
+static BOOL Initialize();
+// 进行解析bin文件信息
+static BOOL FileAnalysis();
+// 获取版本文件信息接口
+static void GetFileList(BOOL bDownload, enDownloadType DownloadType, BYTE *pBuffer, DWORD dwSize, DWORD nIndex);
+// 解析大BIN文件信息总接口
+static void CollectDownloadImage(enDownloadType DownloadType, BYTE *pBuffer, DWORD dwSize);
+// 跳入下一个下载阶段
+static enSTAT GotoNextState(enSTAT enCurrentStat, BOOL bRet);
+// 下载文件
+static BOOL DownloadOneImage(stDownloadConfig CurrentConfig);
+// 下载文件接口
+static BOOL DownloadImage(stFileItem ImageInfo, BOOL bExecuteCode);
+// 下载文件总接口
+static BOOL ExchangeImage();
+// 下载版本文件后释放资源
+static BOOL UnInitialize();
+// 下载版本文件
+static BOOL DoDownload(enDownloadType DownloadType, BYTE *pBuffer, DWORD dwSize, BOOL bBackupNV, enDownloadNVBackupMethod Method, BOOL bEableCRCCheck);
+
+/*******************************************************************************
+ *                       		内部函数                                  *
+ *******************************************************************************/
+static BOOL EraseNVRW()
+{
+	BOOL bRet = FALSE;
+	BYTE *AckBuffer;
+	char buf[100];
+	LogInfo("start...");
+	BYTE *WriteBufferErase = (BYTE *)malloc(200);
+	memset(WriteBufferErase, 0, 200);
+	memcpy(WriteBufferErase, "erase nvrw", 10);
+
+	bRet = SendData(WriteBufferErase, 11, 10, 1);
+	usleep(1000 * 1000);
+	if (bRet)
+	{
+		AckBuffer = (BYTE *)ReadDataExtraFuncB(4, 20, 30);
+	}
+	memset(buf, 0, 100);
+	if (AckBuffer == NULL)
+	{
+		LogInfo("AckBuffer is null...");
+		return bRet;
+	}
+	strcpy(buf, (char *)AckBuffer);
+	if (bRet && (!memcmp(buf, "OKAY", 5)))
+	{
+		LogInfo("Erase OK...");
+
+		usleep(100 * 1000); // 延时必须要加,否则下载文件失败
+
+		bRet = TRUE;
+	}
+	else
+	{
+		LogInfo("Erase FAIL...");
+		bRet = FALSE;
+	}
+	return bRet;
+}
+
+// 如果打不开待下载的代理文件,则失败
+static BOOL PreInitBoot()
+{
+	m_dwBootStage1StartAddress = 0x00082000;
+	m_dwBootStage2StartAddress = 0x21ef0000;
+	printf("PreInitBootfunc:: g_path=%s.\n", g_path);
+
+	if (access(g_path, 0) != 0)
+	{
+		printf("PreInitBootfunc:: software file path is error.\n");
+		return FALSE;
+	}
+	pf = fopen(g_path, "rb");
+
+	if (pf == NULL)
+	{
+		LogInfo("Open file FAIL... %s", g_path);
+		return FALSE;
+	}
+	stBinMasterInfo MasterHead;
+	stFileItem FileItem;
+
+	int num = fread((BYTE *)&MasterHead, 1, sizeof(MasterHead), pf);
+	if (num == 0)
+	{
+		LogInfo("Read file FAIL... %s", g_path);
+		return FALSE;
+	}
+	m_iFileNum = MasterHead.nTotalFileNum;
+	m_stMasterInfo.nTotalFileNum = MasterHead.nTotalFileNum;
+
+	m_stMasterInfo.nFlashType = MasterHead.nFlashType;
+	m_stMasterInfo.nNVCoalition = MasterHead.nNVCoalition;
+	memcpy(m_stMasterInfo.chVersionIN, MasterHead.chVersionIN, sizeof(MasterHead.chVersionIN));
+	memcpy(m_stMasterInfo.chVersionOUT, MasterHead.chVersionOUT, sizeof(MasterHead.chVersionOUT));
+	m_stMasterInfo.iFileSize = MasterHead.iFileSize;
+	m_stMasterInfo.iImageStructOffset = MasterHead.iImageStructOffset;
+	m_stMasterInfo.PartitionLength = MasterHead.PartitionLength;
+	m_stMasterInfo.PartitionOffset = MasterHead.PartitionOffset;
+
+	m_stMasterInfo.tloaderLength = MasterHead.tloaderLength;
+	m_stMasterInfo.tloaderOffset = MasterHead.tloaderOffset;
+	m_stMasterInfo.tBootLength = MasterHead.tBootLength - 64;
+	m_stMasterInfo.tBootOffset = MasterHead.tBootOffset + 64;
+
+	m_dwBootStage2Size = m_stMasterInfo.tBootLength;
+	m_dwBootStage1Size = m_stMasterInfo.tloaderLength;
+	m_dwPartitionSize = m_stMasterInfo.PartitionLength;
+
+	LogInfo("PreInitBootfunc:: m_iFileNum = %d", m_iFileNum);
+	LogInfo("PreInitBootfunc:: m_stMasterInfo.nTotalFileNum = %d", m_stMasterInfo.nTotalFileNum);
+	LogInfo("PreInitBootfunc:: m_stMasterInfo.nFlashType = %d", m_stMasterInfo.nFlashType);
+	LogInfo("PreInitBootfunc:: m_stMasterInfo.nNVCoalition = %d", m_stMasterInfo.nNVCoalition);
+	LogInfo("PreInitBootfunc:: m_stMasterInfo.chVersionIN = %s", m_stMasterInfo.chVersionIN);
+	LogInfo("PreInitBootfunc:: m_stMasterInfo.chVersionOUT = %s", m_stMasterInfo.chVersionOUT);
+	LogInfo("PreInitBootfunc:: m_stMasterInfo.iFileSize = %d", m_stMasterInfo.iFileSize);
+	LogInfo("PreInitBootfunc:: m_stMasterInfo.iImageStructOffset = %d", m_stMasterInfo.iImageStructOffset);
+	LogInfo("PreInitBootfunc:: m_stMasterInfo.PartitionLength = %d", m_stMasterInfo.PartitionLength);
+	LogInfo("PreInitBootfunc:: m_stMasterInfo.PartitionOffset = %d", m_stMasterInfo.PartitionOffset);
+	LogInfo("PreInitBootfunc:: m_stMasterInfo.tloaderLength = %d", m_stMasterInfo.tloaderLength);
+	LogInfo("PreInitBootfunc:: m_stMasterInfo.tloaderOffset = %d", m_stMasterInfo.tloaderOffset);
+	LogInfo("PreInitBootfunc:: m_stMasterInfo.tBootLength = %d", m_stMasterInfo.tBootLength);
+	LogInfo("PreInitBootfunc:: m_stMasterInfo.tBootOffset = %d", m_stMasterInfo.tBootOffset);
+	LogInfo("PreInitBootfunc:: m_dwBootStage2Size = %d", m_dwBootStage2Size);
+	LogInfo("PreInitBootfunc:: m_dwBootStage1Size = %d", m_dwBootStage1Size);
+	LogInfo("PreInitBootfunc:: m_dwPartitionSize = %d", m_dwPartitionSize);
+
+	// 从tboot文件前面的64个字节中获取tboot下载和启动地址
+	unsigned char header[64] = {0};
+	fseek(pf, MasterHead.tBootOffset, 0);
+	if (fread(header, 1, sizeof(header), pf) != sizeof(header))
+	{
+		LogInfo("Read tboot FAIL...");
+		return FALSE;
+	}
+	// 获取TBoot下载地址
+	m_dwBootStage2StartAddress = (header[20] << 24) | (header[21] << 16) | (header[22] << 8) | (header[23]);
+	LogInfo("m_dwBootStage2StartAddress = 0x%x", m_dwBootStage2StartAddress);
+
+	if (pf != NULL)
+	{
+		fclose(pf);
+		pf = NULL;
+	}
+	return TRUE;
+}
+
+static BOOL DownloadOneBoot(DWORD dwBootStartAddress, DWORD dwBootSize, FILE *pBootFile, size_t dwPacketSize, DWORD dwOffset, BOOL SYNC)
+{
+	enSTAT State = STAT_SYNC;
+	BOOL bRet = FALSE;
+	BOOL bExit = FALSE;
+	DWORD dwCurrentSize = 0;
+	DWORD dwPacketCount = 0;
+
+	if (access(g_path, 0) != 0)
+	{
+		printf("DownloadOneBootfunc:: software file path is error.\n");
+		return FALSE;
+	}
+	pf = fopen(g_path, "rb");
+	if (pf == NULL)
+	{
+		LogInfo("DownloadOneBootfunc::  PreInitBoot Open file FAIL... %s", g_path);
+		return FALSE;
+	}
+	if (SYNC == FALSE)
+	{
+		State = STAT_START_BYTE;
+		LogInfo("DownloadOneBootfunc::  not need STAT_SYNC 0X5A...");
+	}
+
+	LogInfo("DownloadOneBootfunc::  dwOffset = %d...dwPacketSize = %d", dwOffset, dwPacketSize);
+	while (!bExit)
+	{
+		switch (State)
+		{
+		//------------------------------同步---------------------------------
+		case STAT_SYNC:
+		{
+			BYTE nCommand = 0;
+			BYTE nAck = 0;
+
+			// PrintInfo(_T("开始同步DownloadOneBoot..."));
+			nCommand = CMD_SYNC_TBOOT;
+			bRet = SendData(&nCommand, 1, 10, 20);
+			if (bRet)
+			{
+				bRet = ReadData(&nAck, 1, 20, 20);
+			}
+
+			if (bRet && (CMD_SYNC_BYTE_ACK_BOOTROM == nAck))
+			{
+				// PrintInfo(_T("同步完毕!"));
+				LogInfo("DownloadOneBootfunc::  Send STAT_SYNC OK...");
+				State = STAT_START_BYTE;
+			}
+			else
+			{
+				// 同步失败后退出
+				// PrintInfo(_T("同步失败!"));
+				LogInfo("DownloadOneBootfunc::  Send STAT_SYNC FAIL...nAck = 0x%x", nAck);
+				bExit = TRUE;
+				bRet = FALSE;
+			}
+		}
+		break;
+
+		//-----------------------------设置寄存器---------------------------------
+		case STAT_START_BYTE:
+		{
+			State = STAT_NO_MODIFY_REG; // 不执行配置,直接进入下一个流程
+		}
+		break;
+
+		case STAT_NO_MODIFY_REG:
+		{
+			BYTE nCommand = CMD_SEND_DATA_BOOTROM;
+
+			// PrintInfo(_T("设置寄存器..."));
+			bRet = SendData(&nCommand, 1, 10, 1);
+			if (bRet)
+			{
+				// PrintInfo(_T("设置寄存器完毕!"));
+				LogInfo("DownloadOneBootfunc::  Send CMD_SEND_DATA_BOOTROM OK...");
+				State = STAT_ADDRESS;
+			}
+			else
+			{
+				LogInfo("DownloadOneBootfunc::  Send CMD_SEND_DATA_BOOTROM FAIL...");
+				State = STAT_TERMINATE;
+			}
+		}
+		break;
+
+		//------------------------------地址---------------------------------
+		case STAT_ADDRESS:
+		{
+			DWORD dwStartAddress = dwBootStartAddress;
+			// PrintInfo(_T("设置地址..."));
+			ExchangeEndian(dwStartAddress);
+			bRet = SendData((BYTE *)&dwStartAddress, sizeof(DWORD), 10, 1);
+			if (bRet)
+			{
+				// PrintInfo(_T("设置地址完毕!"));
+				LogInfo("DownloadOneBootfunc::  Send dwStartAddress OK...");
+				State = STAT_DATA_LEN;
+			}
+			else
+			{
+				LogInfo("DownloadOneBootfunc::  Send dwStartAddress FAIL...");
+				State = STAT_TERMINATE;
+			}
+		}
+		break;
+
+		//----------------------------数据长度-------------------------------
+		case STAT_DATA_LEN:
+		{
+			DWORD dwSize = dwBootSize;
+			BYTE nAck = 0;
+
+			// PrintInfo(_T("设置数据长度..."));
+			ExchangeEndian(dwSize);
+			bRet = SendData((BYTE *)&dwSize, sizeof(DWORD), 20, 1);
+			if (bRet)
+			{
+				bRet = ReadData(&nAck, 1, 20, 20);
+				if (bRet && (CMD_SEND_ADDRESS_LEN_ACK_BOOTROM == nAck))
+				{
+					LogInfo("DownloadOneBootfunc::  Set  address and length OK...");
+					// printf("DownloadOneBootfunc::  Set  address and length OK...\n");
+					// 判断Boot文件的状态
+					if (NULL == pf)
+					{
+						LogInfo("DownloadOneBootfunc::  pf not exsist...");
+						State = STAT_TERMINATE;
+					}
+					else
+					{
+						fseek(pf, dwOffset, 0);
+						dwCurrentSize = dwBootSize;
+						LogInfo("DownloadOneBootfunc::  dwOffset = %d,  dwBootSize = %d", dwOffset, dwBootSize);
+						// PrintInfo(_T("开始发送Boot数据..."));
+						State = STAT_DATAPACKET;
+						LogInfo("DownloadOneBootfunc::  start send BootFile...");
+					}
+				}
+				else
+				{
+					LogInfo("DownloadOneBootfunc::  Get ADDRESS_LEN_ACK FAIL!bRet=%d, nAck=%d", bRet, nAck);
+					State = STAT_TERMINATE;
+				}
+			}
+			else
+			{
+				LogInfo("DownloadOneBootfunc::  Send dwBootSize FAIL...");
+				State = STAT_TERMINATE;
+			}
+		}
+		break;
+
+		//----------------------------boot数据---------------------------------
+		case STAT_DATAPACKET:
+		{
+			BYTE WriteBuffer[PACKET_SIZE_BOOT] = {0};
+			BYTE nAck = 0;
+			size_t dwSendSize = 0;
+
+			if (dwPacketSize > PACKET_SIZE_BOOT)
+			{
+				// PrintInfo(_T("数据包长度越界!"));
+				LogInfo("DownloadOneBootfunc::  dwPacketSize>PACKET_SIZE_BOOT too big...");
+				bRet = FALSE;
+				State = STAT_TERMINATE;
+			}
+			else
+			{
+				LogInfo("DownloadOneBootfunc:: dwPacketSize = %d   PACKET_SIZE_BOOT = %d", dwPacketSize, PACKET_SIZE_BOOT);
+			}
+
+			memset(WriteBuffer, 0, sizeof(WriteBuffer));
+			if (dwCurrentSize >= dwPacketSize)
+			{
+				LogInfo("DownloadOneBootfunc::  dwCurrentSize >= dwPacketSize...");
+				if (fread(&WriteBuffer[0], 1, dwPacketSize, pf) != dwPacketSize) // pBootFile->Read(&WriteBuffer[0], dwPacketSize) != dwPacketSize)
+				{
+					// PrintInfo(_T("Boot文件读取失败!"));
+					LogInfo("DownloadOneBootfunc::  Read bootfile FAIL...");
+					bRet = FALSE;
+					State = STAT_TERMINATE;
+					break;
+				}
+				LogInfo("DownloadOneBootfunc::  dwPacketSize = %d", dwPacketSize);
+				bRet = SendData(WriteBuffer, dwPacketSize, 10, 1);
+				LogInfo("DownloadOneBootfunc::  dwPacketCount = %d...bRet = %d", dwPacketCount, bRet);
+				if (bRet)
+				{
+					LogInfo("DownloadOneBootfunc::  send bootfile  one packet OK...");
+					dwPacketCount++;
+					dwCurrentSize -= dwPacketSize;
+					if (0x00 == dwCurrentSize)
+					{
+						bRet = ReadData(&nAck, 1, 20, 20);
+						if (bRet && (CMD_SEND_DATA_ACK_BOOTROM == nAck))
+						{
+							State = STAT_EXECUTE_CODE; // 下载完成后,下一状态是执行代码  zxw 20121010
+						}
+						else
+						{
+							LogInfo("DownloadOneBootfunc::  Get send bootfile ACK FAIL!");
+							printf("DownloadOneBootfunc::  Get send bootfile ACK FAIL!\n");
+							bRet = FALSE;
+							State = STAT_TERMINATE;
+						}
+					}
+				}
+				else
+				{
+					LogInfo("DownloadOneBootfunc::  send bootfile  one packet FAIL...");
+					bRet = FALSE;
+					State = STAT_TERMINATE;
+				}
+			}
+			else if (dwCurrentSize > 0)
+			{
+				if ((dwCurrentSize % 512) == 0)
+				{
+					dwSendSize = dwCurrentSize - 8; // 512整包时,拆包
+					LogInfo("DownloadOneImagefunc:: STAT_DATAPACKET  split packet");
+					// printf("DownloadOneImagefunc:: STAT_DATAPACKET  split packet\n");
+				}
+				else
+				{
+					dwSendSize = dwCurrentSize;
+					usleep(2 * 1000); // 最后一包,等待一段时间
+				}
+
+				LogInfo("DownloadOneBootfunc::  dwCurrentSize > 0 but <packetsize...");
+				if (fread(&WriteBuffer[0], 1, dwSendSize, pf) != dwSendSize) // pBootFile->Read(&WriteBuffer[0], dwCurrentSize) != dwCurrentSize)
+				{
+					// PrintInfo(_T("Boot文件读取失败!"));
+					LogInfo("DownloadOneBootfunc::  Read bootfile FAIL...");
+					bRet = FALSE;
+					State = STAT_TERMINATE;
+					break;
+				}
+				bRet = SendData(WriteBuffer, dwSendSize, 10, 1);
+				LogInfo("DownloadOneBootfunc::  dwPacketCount = %d...", dwPacketCount);
+				if (bRet)
+				{
+					dwPacketCount++;
+					dwCurrentSize -= dwSendSize;
+					if (dwCurrentSize == 0)
+					{
+						bRet = ReadData(&nAck, 1, 20, 20);
+						if (bRet && (CMD_SEND_DATA_ACK_BOOTROM == nAck))
+						{
+							State = STAT_EXECUTE_CODE; // 下载完成后,下一状态是执行代码  zxw 20121010
+							LogInfo("DownloadOneBootfunc::  send bootfile  last packet OK...");
+						}
+						else
+						{
+							LogInfo("DownloadOneBootfunc::  Get send bootfile ACK FAIL!");
+							bRet = FALSE;
+							State = STAT_TERMINATE;
+						}
+					}
+				}
+				else
+				{
+					// PrintInfo(_T("BOOT数据发送失败!"));
+					LogInfo("DownloadOneBootfunc::  send bootfile  one packet FAIL...");
+					bRet = FALSE;
+					State = STAT_TERMINATE;
+				}
+			}
+			else
+			{
+				bRet = TRUE;
+				State = STAT_EXECUTE_CODE; // 下载完成后,下一状态是执行代码  zxw 20121010
+			}
+		}
+		break;
+		case STAT_EXECUTE_CODE:
+		{
+			unsigned char buf[5];
+			BYTE nAck = 0;
+			DWORD dwStartAddress = dwBootStartAddress;
+			buf[0] = CMD_STARTUP_BOOTROM;
+			ExchangeEndian(dwStartAddress);
+			memcpy(&buf[1], &dwStartAddress, sizeof(DWORD));
+			// PrintInfo(_T("开始启动BOOT..."));
+			bRet = SendData(buf, sizeof(buf), 10, 1);
+			if (bRet)
+			{
+				bRet = ReadData(&nAck, 1, 20, 20);
+				if (bRet && (CMD_STARTUP_ACK_BOOTROM == nAck))
+				{
+					// PrintInfo(_T("启动Boot完毕!"));
+					LogInfo("DownloadOneBootfunc::  start boot OK...");
+					State = STAT_TERMINATE;
+					bRet = TRUE;
+				}
+				else
+				{
+					LogInfo("DownloadOneBootfunc::  Get start boot ACK FAIL...");
+					State = STAT_TERMINATE;
+					bRet = FALSE;
+				}
+			}
+			else
+			{
+				// PrintInfo(_T("启动Boot失败!"));
+				LogInfo("DownloadOneBootfunc::  send  boot start command FAIL...");
+				State = STAT_TERMINATE;
+				bRet = FALSE;
+			}
+		}
+		break;
+		default:
+			bExit = TRUE;
+			break;
+		}
+	}
+
+	if (pf != NULL)
+	{
+		fclose(pf);
+		pf = NULL;
+	}
+	return bRet;
+}
+
+static BOOL DownloadPartition(size_t dwPartitionSize, FILE *pFile, DWORD dwPacketSize, DWORD dwOffset, BOOL bCheckPartition)
+{
+	enParpSTAT State = STAT_SYNC_PARTIITON;
+	BOOL bRet = FALSE;
+	BOOL bExit = FALSE;
+
+	DWORD dwCurrentSize = 0;
+	DWORD dwPacketCount = 0;
+
+	BYTE *AckBuffer;
+	if (access(g_path, 0) != 0)
+	{
+		printf("DownloadPartitionfunc:: software file path is error.\r\n");
+		return FALSE;
+	}
+	pf = fopen(g_path, "rb");
+	if (pf == NULL)
+	{
+		LogInfo("DownloadPartitionfunc::  Open file FAIL... %s", g_path);
+		return FALSE;
+	}
+
+	while (!bExit)
+	{
+		switch (State)
+		{
+		//------------------------------同步---------------------------------
+		case STAT_SYNC_PARTIITON:
+		{
+			BYTE nCommand = 0;
+			BYTE nAck = 0;
+
+			// PrintInfo(_T("开始同步DownloadPartition1..."));
+			LogInfo("DownloadPartitionfunc::  STAT_SYNC_PARTIITON DownloadPartition...");
+			nCommand = CMD_SYNC_TBOOT;
+			bRet = SendData(&nCommand, 1, 10, 1);
+			if (bRet)
+			{
+				bRet = ReadData(&nAck, 1, 10, 10);
+			}
+
+			if (bRet && (CMD_SYNC_ACK_TBOOT == nAck))
+			{
+				// PrintInfo(_T("同步完毕!"));
+				LogInfo("DownloadPartitionfunc::  STAT_SYNC_PARTIITON DownloadPartition OK...");
+				printf("DownloadPartitionfunc::  STAT_SYNC_PARTIITON DownloadPartition OK...\n");
+
+				State = STAT_SET_PARTITION_CMD;
+			}
+			else
+			{
+				// 空片下载的时候需要遍历flash生产坏块分区表需要一定的时间。
+				// PrintInfo(_T("同步失败!"));
+				LogInfo("DownloadPartitionfunc::  STAT_SYNC_PARTIITON DownloadPartition FAIL...");
+				State = STAT_SYNC_PARTIITON;
+				int count = 0;
+				count++;
+				if (count > 20)
+				{
+					State = STAT_EXIT;
+					bExit = TRUE;
+					bRet = FALSE;
+				}
+			}
+			usleep(10 * 1000);
+		}
+		break;
+
+		case STAT_SET_PARTITION_CMD:
+		{
+			BYTE CommandHead[] = "set partitions 1000\0";
+			BYTE CommandBuf[200] = {0};
+			BYTE bRead = 0;
+			BYTE ByteBuf[17] = {0};
+
+			// memset(CommandBuf,0,200);
+			// memset(AckBuffer,0,150);
+			memcpy(CommandBuf, CommandHead, sizeof(CommandHead));
+			// CommandBuf[sizeof(CommandHead)] = dwPartitionSize;
+
+			LogInfo("DownloadPartitionfunc::  STAT_SET_PARTITION_CMD strlen((char*)CommandBuf)) = %d...", strlen((char *)CommandBuf));
+			bRet = SendData(CommandBuf, strlen((char *)CommandBuf) + 1, 10, 1);
+			if (bRet)
+			{
+				AckBuffer = (BYTE *)ReadDataExtraFuncB(17, 10, 20);
+			}
+			if (AckBuffer != NULL)
+			{
+				LogInfo("DownloadPartitionfunc::  STAT_SET_PARTITION_CMD AckBuffer = %s...", AckBuffer);
+			}
+			else
+			{
+				LogInfo("DownloadPartitionfunc::  STAT_SET_PARTITION_CMD AckBuffer is NULL");
+			}
+
+			if (bRet && (!memcmp(AckBuffer, "OKAY RECV_TABLES", 16)))
+			{
+				// PrintInfo(_T("设置分区表命令成功!"));
+				LogInfo("DownloadPartitionfunc::  STAT_SET_PARTITION_CMD set partitions OK...");
+				printf("DownloadPartitionfunc::  STAT_SET_PARTITION_CMD set partitions OK...\n");
+
+				State = STAT_SEND_PARTIITON;
+			}
+			else
+			{
+				LogInfo("DownloadPartitionfunc::  STAT_SET_PARTITION_CMD set partitions FAIL...");
+				// PrintInfo(_T("设置分区表命令失败!"));
+				State = STAT_EXIT;
+
+				bExit = TRUE;
+				bRet = FALSE;
+			}
+		}
+		break;
+
+		case STAT_SEND_PARTIITON:
+		{
+			// memset(AckBuffer,0,150);
+			char *strfail1 = "FAIL INVALID_PARTITION_TABLE";	// 分区表自身内容不合法
+			char *strfail2 = "FAIL ACCEPTABLE_PARTITION_CHANGE";	// 分区表对比出错,但NV分区一致
+			char *strfail3 = "FAIL UNACCEPTABLE_PARTITION_CHANGE";	// 分区表对比出错,NV分区不一致
+			BYTE bRead = 0;
+
+			BYTE *WriteBuffer = (BYTE *)malloc(dwPartitionSize);
+			if (!WriteBuffer)
+			{
+				printf("DownloadPartitionfunc:: malloc WriteBuffer failed\n");
+				bRet = FALSE;
+				break;
+			}
+
+			fseek(pf, dwOffset, 0);
+			if (fread(WriteBuffer, 1, dwPartitionSize, pf) != dwPartitionSize)
+			{
+				// PrintInfo(_T("分区表文件读取失败!"));
+				LogInfo("DownloadPartitionfunc::  STAT_SEND_PARTIITON read partition data FAIL...");
+				if (WriteBuffer != NULL)
+				{
+					free(WriteBuffer);
+					WriteBuffer = NULL;
+				}
+				bRet = FALSE;
+				break;
+			}
+
+			int dlPTindex = 0;
+			int dlTime = dwPartitionSize / 1000;
+
+			printf("DownloadPartitionfunc::  STAT_SEND_PARTIITON start !\n");
+			for (dlPTindex = 0; dlPTindex < dlTime; dlPTindex++)
+			{
+				bRet = SendData(WriteBuffer + 1000 * dlPTindex, 1000, 10, 1);
+				printf("DownloadPartitionfunc::  STAT_SEND_PARTIITON dlPTindex = %d.\n", dlPTindex);
+			}
+			if (dwPartitionSize % 1000 != 0)
+			{
+				bRet = SendData(WriteBuffer + 1000 * dlTime, dwPartitionSize % 1000, 10, 1);
+				printf("DownloadPartitionfunc::  STAT_SEND_PARTIITON SendData\n");
+			}							
+			if (bRet)
+			{
+				usleep(10 * 1000);
+				// bRet = ReadData(&bRead,1,50,20);
+				// bRet = ReadData(AckBuffer,strlen(strfail3)+1,50,20);
+				AckBuffer = (BYTE *)ReadDataExtraFuncB(strlen(strfail3) + 1, 10, 5);
+			}
+			printf("DownloadPartitionfunc::  STAT_SEND_PARTIITON ReadDataExtraFuncB\n");
+
+			char buf[100];
+			memset(buf, 0, 100);
+			strcpy(buf, (char *)AckBuffer);
+
+			if (buf[0] == '\0')
+			{
+				LogInfo("DownloadPartitionfunc::  STAT_SEND_PARTIITON read error !");
+				bExit = TRUE;
+				bRet = FALSE;
+				State = STAT_EXIT;
+				break;
+			}
+			if (!memcmp(buf, "OKAY", 4))
+			{
+				// PrintInfo("分区文件下载成功!");
+				LogInfo("DownloadPartitionfunc::  STAT_SEND_PARTIITON send partition OK...");
+				printf("DownloadPartitionfunc::  STAT_SEND_PARTIITON send partition OK...\n");
+
+				State = STAT_EXIT;
+				bRet = TRUE;
+				break;
+			}
+			if (!memcmp(buf, strfail1, strlen(strfail1)))
+			{
+				// PrintInfo("生成的分区表有问题!");
+				LogInfo("DownloadPartitionfunc::  STAT_SEND_PARTIITON  partition has some problem..");
+				bExit = TRUE;
+				bRet = FALSE;
+				State = STAT_EXIT;
+				break;
+			}
+			if (!memcmp(buf, strfail2, strlen(strfail2)))
+			{
+				// memset(AckBuffer,0,150);
+				// PrintInfo("分区表发生变化,需要擦除所有分区除了NV分区进行下载!");
+
+				LogInfo("DownloadPartitionfunc::  FAIL ACCEPTABLE_PARTITION_CHANGE...");
+				printf("DownloadPartitionfunc::  PARTITION_CHANGE...\n");
+
+				BYTE *WriteBufferErase = (BYTE *)malloc(200);
+
+				memset(WriteBufferErase, 0, 200);
+				memcpy(WriteBufferErase, "erase auto", 10);
+
+				bRet = SendData(WriteBufferErase, 11, 10, 1);
+				if (bRet)
+				{
+					bRet = ReadData(AckBuffer, 5, 20, 4 * 60); // 适配nor flash,最大超时时间改为4分钟
+				}
+
+				memset(buf, 0, 100);
+				strcpy(buf, (char *)AckBuffer);
+
+				if (bRet && (!memcmp(buf, "OKAY", 5)))
+				{
+					if (WriteBuffer != NULL)
+					{
+						free(WriteBuffer);
+						WriteBuffer = NULL;
+					}
+
+					LogInfo("DownloadPartitionfunc::  Erase Partition OK...");
+					printf("DownloadPartitionfunc::  Erase Partition OK...\n");
+
+					// PrintInfo("擦除分区成功!");
+					usleep(100 * 1000); // 延时必须要加,否则下载文件失败
+					bExit = TRUE;
+
+					bRet = TRUE;
+					State = STAT_EXIT;
+					break;
+				}
+				else
+				{
+					if (WriteBuffer != NULL)
+					{
+						free(WriteBuffer);
+						WriteBuffer = NULL;
+					}
+					LogInfo("DownloadPartitionfunc::  Erase Partition FAIL...");
+					// PrintInfo("擦除分区失败!");
+					bExit = TRUE;
+					bRet = FALSE;
+					State = STAT_EXIT;
+					break;
+				}
+			}
+			if (!memcmp(buf, strfail3, strlen(strfail3)))
+			{
+				// PrintInfo("分区表信息发生变化,NV分区发生变化,下载异常中止!");
+				LogInfo("DownloadPartitionfunc::  Partition change, stop download...");
+				State = STAT_EXIT;
+
+				bExit = TRUE;
+				bRet = FALSE;
+
+				State = STAT_EXIT;
+				break;
+			}
+			else
+			{
+				LogInfo("DownloadPartitionfunc::  Partition other fail, stop download...");
+				State = STAT_EXIT;
+
+				bExit = TRUE;
+				bRet = FALSE;
+
+				State = STAT_EXIT;
+				break;
+			}
+		}
+		break;
+
+		default:
+			bExit = TRUE;
+		}
+	}
+	if (pf != NULL)
+	{
+		fclose(pf);
+		pf = NULL;
+	}
+	return bRet;
+}
+
+static BOOL UnPreInitBoot()
+{
+	return TRUE;
+}
+
+static BOOL Initialize()
+{
+	// 下载小系统使用,下载完小系统,该标志为真
+	// 当该标志为真时,PC侧会发送一个结束命令使UE启动小系统
+	m_StartAMT = FALSE;
+	m_StartAMT_MODEM = FALSE;
+	m_StartAMT_AP = FALSE;
+	// 清空协议指针
+	m_pProtocolTable = (stSTAT *)NULL;
+	return TRUE;
+}
+
+static BOOL FileAnalysis()
+{
+	int fileIndex = 0;
+	BOOL bRet = FALSE;
+	stBinImageHead BinFileHeader;
+	int i = 0;
+	if (access(g_path, 0) != 0)
+	{
+		printf("FileAnalysisfunc:: software file path is error.\n");
+		return FALSE;
+	}
+	pf = fopen(g_path, "rb");
+	if (pf == NULL)
+	{
+		// 文件打开失败
+		if (g_path != NULL)
+		{
+			LogInfo("FileAnalysisfunc:: Open file FAIL... %s", g_path);
+		}
+		else
+		{
+			LogInfo("FileAnalysisfunc:: g_path ptr is NULL");
+		}
+	}
+	else
+	{
+		if (g_path != NULL)
+		{
+			LogInfo("FileAnalysisfunc:: Open file OK... %s", g_path);
+		}
+		else
+		{
+			LogInfo("FileAnalysisfunc:: g_path ptr is NULL");
+		}
+	}
+	if (m_iFileNum <= 0)
+	{
+		LogInfo("FileAnalysisfunc:: file num error m_iFileNum = %d", m_iFileNum);
+		return bRet;
+	}
+	fseek(pf, sizeof(m_stMasterInfo), 0);
+	// 逐个文件添加到上/下载列表中
+	for (i = 0; i < m_iFileNum; i++)
+	{
+		if (fread((BYTE *)&BinFileHeader, 1, sizeof(stBinImageHead), pf) != sizeof(stBinImageHead)) // pBootFile->Read(&WriteBuffer[0], dwPacketSize) != dwPacketSize)
+		{
+			LogInfo("FileAnalysisfunc:: Read file FAIL...");
+			bRet = FALSE;
+		}
+		if (memcmp(BinFileHeader.PartitionName, "NVR", 3) != 0)
+		{
+			if (BinFileHeader.PartitionName != NULL)
+			{
+				LogInfo("FileAnalysisfunc:: not NVR file, BinFileHeader.PartitionName = %s", BinFileHeader.PartitionName);
+			}
+			else
+			{
+				LogInfo("FileAnalysisfunc:: not NVR file, BinFileHeader.PartitionName  ptr is NULL");
+			}
+			fileIndex++;
+			g_DownLoadFileNum++;
+		}
+		else
+		{
+			if (BinFileHeader.PartitionName != NULL)
+			{
+				LogInfo("FileAnalysisfunc:: NVR file, BinFileHeader.PartitionName = %s", BinFileHeader.PartitionName);
+			}
+			else
+			{
+				LogInfo("FileAnalysisfunc:: NVR file, BinFileHeader.PartitionName ptr is NULL");
+			}
+			continue;
+		}
+		// 上载/下载
+		FileItem[fileIndex].bDownload = TRUE;
+
+		// 文件名称(包含路径)
+		FileItem[fileIndex].strFileName = g_path;
+
+		// 是否使用相对路径
+		FileItem[fileIndex].bUseRelativePath = 0;
+
+		// 是否直接从文件读取数据
+		FileItem[fileIndex].bReadFromFile = 1;
+
+		// 自动回收缓存空间
+		FileItem[fileIndex].bAutoDeleteImageCache = FALSE;
+
+		// 若从缓存中读取数据,赋值缓存指针
+		FileItem[fileIndex].pImageCache = NULL;
+
+		// 相对于文件/缓存的偏移地址
+		FileItem[fileIndex].dwOffset = BinFileHeader.iFileOffset;
+
+		// 分区名
+		strcpy(FileItem[fileIndex].PartitionName, (char *)BinFileHeader.PartitionName);
+
+		// 待写入的长度,单位:字节
+		FileItem[fileIndex].dwLength = BinFileHeader.iFileLength;
+
+		// 分区的偏移地址
+		FileItem[fileIndex].nPartitionOffset = BinFileHeader.iPartitionOffset;
+
+		// 分区文件类型 raw nv fs nand
+		strcpy(FileItem[fileIndex].PartitionType, (char *)BinFileHeader.PartitionType);
+
+		FileItem[fileIndex].nType = nand;
+
+		// 打印Log
+		LogInfo("FileAnalysisfunc:: FileItem[%d].bDownload = %d", fileIndex, FileItem[fileIndex].bDownload);
+		if (FileItem[fileIndex].strFileName != NULL)
+		{
+			LogInfo("FileAnalysisfunc:: FileItem[%d].strFileName = %s", fileIndex, FileItem[fileIndex].strFileName);
+		}
+		else
+		{
+			LogInfo("FileAnalysisfunc:: FileItem[%d].strFileName ptr is NULL", fileIndex);
+		}
+		LogInfo("FileAnalysisfunc:: FileItem[%d].bUseRelativePath = %d", fileIndex, FileItem[fileIndex].bUseRelativePath);
+		LogInfo("FileAnalysisfunc:: FileItem[%d].bReadFromFile = %d", fileIndex, FileItem[fileIndex].bReadFromFile);
+
+		LogInfo("FileAnalysisfunc:: FileItem[%d].bAutoDeleteImageCache = %d", fileIndex, FileItem[fileIndex].bAutoDeleteImageCache);
+
+		if (FileItem[fileIndex].pImageCache != NULL)
+		{
+			LogInfo("FileAnalysisfunc:: FileItem[%d].pImageCache = %s", fileIndex, FileItem[fileIndex].pImageCache);
+		}
+		else
+		{
+			LogInfo("FileAnalysisfunc:: FileItem[%d].pImageCache ptr is NULL", fileIndex);
+		}
+		LogInfo("FileAnalysisfunc:: FileItem[%d].dwOffset = %d", fileIndex, FileItem[fileIndex].dwOffset);
+		if (FileItem[fileIndex].PartitionName != NULL)
+		{
+			LogInfo("FileAnalysisfunc:: FileItem[%d].PartitionName = %s", fileIndex, FileItem[fileIndex].PartitionName);
+		}
+		else
+		{
+			LogInfo("FileAnalysisfunc:: FileItem[%d].PartitionName ptr is NULL", fileIndex);
+		}
+		LogInfo("FileAnalysisfunc:: FileItem[%d].dwLength = %d", fileIndex, FileItem[fileIndex].dwLength);
+		LogInfo("FileAnalysisfunc:: FileItem[%d].nPartitionOffset = %d", fileIndex, FileItem[fileIndex].nPartitionOffset);
+		LogInfo("FileAnalysisfunc:: FileItem[%d].PartitionType = %d", fileIndex, FileItem[fileIndex].PartitionType);
+		LogInfo("FileAnalysisfunc:: FileItem[%d].nType = %d", fileIndex, FileItem[fileIndex].nType);
+		// 计算单个文件的CRC校验值
+		// if(m_bCRCCheck)
+		//{
+		//	if(!GetCRCValue(&FileItem))
+		//	{
+		//		return bRet;
+		//	}
+		// }
+	}
+	bRet = TRUE;
+	if (pf != NULL)
+	{
+		fclose(pf);
+		pf = NULL;
+		LogInfo("FileAnalysisfunc:: fclose(pf)... ");
+	}
+	return bRet;
+}
+
+static void GetFileList(BOOL bDownload, enDownloadType DownloadType, BYTE *pBuffer, DWORD dwSize, DWORD nIndex)
+{
+	switch (LOWORD(DownloadType))
+	{
+	case DOWNLOAD_TYPE_IMAGE:
+		// 下载版本文件信息
+		if (FileAnalysis())
+		{
+			LogInfo("GetFileListfunc:: FileAnalysis OK");
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static void CollectDownloadImage(enDownloadType DownloadType, BYTE *pBuffer, DWORD dwSize)
+{
+	GetFileList(TRUE, DownloadType, pBuffer, dwSize, 0);
+	LogInfo("CollectDownloadImagefunc:: GetFileList OK... ");
+}
+
+static enSTAT GotoNextState(enSTAT enCurrentStat, BOOL bRet)
+{
+	enSTAT NextState = STAT_TERMINATE;
+	int nDim = 0;
+
+	if (NULL == m_pProtocolTable)
+	{
+		LogInfo("GotoNextStatefunc:: NULL == m_pProtocolTable...");
+		return NextState;
+	}
+
+	if (m_DownloadImageTable == m_pProtocolTable)
+	{
+		nDim = sizeof(m_DownloadImageTable) / sizeof(m_DownloadImageTable[0]);
+	}
+	else if (m_DownloadRAMImageTable == m_pProtocolTable)
+	{
+		nDim = sizeof(m_DownloadRAMImageTable) / sizeof(m_DownloadRAMImageTable[0]);
+	}
+	else
+	{
+		nDim = 0;
+	}
+
+	if (enCurrentStat >= nDim)
+	{
+		if (m_DownloadImageTable == m_pProtocolTable)
+		{
+			LogInfo("GotoNextStatefunc:: m_pProtocolTable -> m_DownloadImageTable...");
+		}
+		else if (m_DownloadRAMImageTable == m_pProtocolTable)
+		{
+			LogInfo("GotoNextStatefunc:: m_pProtocolTable -> m_DownloadRAMImageTable...");
+		}
+		else
+		{
+			LogInfo("GotoNextStatefunc:: error state...");
+		}
+		return NextState;
+	}
+
+	if (TRUE == bRet)
+	{
+		NextState = m_pProtocolTable[enCurrentStat].mNextTRUE;
+	}
+	else
+	{
+		NextState = m_pProtocolTable[enCurrentStat].mNextFALSE;
+	}
+
+	return NextState;
+}
+
+static BOOL DownloadOneImage(stDownloadConfig CurrentConfig)
+{
+	enSTAT State = CurrentConfig.mStartState;
+
+	BOOL bRet = FALSE;
+	BOOL bExit = FALSE;
+	ULONG ulAckCRCValue = 0;
+
+	DWORD dwCurrentSize = 0;
+	DWORD dwPacketCount = 0;
+
+	BYTE CommandBuffer[255] = {0};
+	BYTE *AckBuffer;
+
+	BYTE Buftmp[20] = {0};	 // 用于临时存放数据, add zxw 20130422
+	size_t dwPacketSize = 0; // add zxw 20130422 数据包长度
+	DWORD dwDDRPacketSize = 0;
+	BYTE *pBuffer = CurrentConfig.mCurrentFile.pImageCache;
+	DWORD dwFileSize = 0;
+
+	if (access(g_path, 0) != 0)
+	{
+		printf("DownloadOneImagefunc:: software file path is error.\r\n");
+		return FALSE;
+	}
+	pf = fopen(g_path, "rb");
+	if (pf == NULL)
+	{
+		// 文件打开失败
+		if (g_path != NULL)
+		{
+			LogInfo("DownloadOneImagefunc:: Open file FAIL... %s", g_path);
+			printf("33333333333333333333333\n");
+		}
+		else
+		{
+			LogInfo("DownloadOneImagefunc:: g_path ptr is NULL", g_path);
+			printf("44444444444444444444\n");
+		}
+	}
+	else
+	{
+		LogInfo("DownloadOneImagefunc:: Open file OK ");
+		printf("DownloadOneImagefunc:: Open file OK \n");
+	}
+	fseek(pf, CurrentConfig.mCurrentFile.dwOffset, 0);
+	while (!bExit)
+	{
+		switch (State)
+		{
+			//-------------------------设置Packet长度----------------------------
+		case STAT_SET_PACKET_SIZE:
+		{
+			LogInfo("DownloadOneImagefunc:: STAT_SET_PACKET_SIZE");
+			printf("DownloadOneImagefunc:: STAT_SET_PACKET_SIZE\n");
+
+			memset(CommandBuffer, 0, 255);
+			sprintf(CommandBuffer, "compat_write %s %08x %0x", CurrentConfig.mCurrentFile.PartitionName, CurrentConfig.mCurrentFile.nPartitionOffset, CurrentConfig.mCurrentFile.dwLength);
+			LogInfo("DownloadOneImagefunc:: CommandBuffer = %s", CommandBuffer);
+			printf("DownloadOneImagefunc:: CommandBuffer = %s\n", CommandBuffer);
+			dwFileSize = CurrentConfig.mCurrentFile.dwLength;
+			bRet = SendData(CommandBuffer, strlen((const char *)CommandBuffer) + 1, 20, 1);
+			if (bRet)
+			{
+				AckBuffer = (BYTE *)ReadDataExtraFuncB(14, 10, 4 * 60); // 适配nor flash,最大超时时间改为4分钟
+				LogInfo("DownloadOneImagefunc::  AckBuffer = %x", AckBuffer[0]);
+			}		
+			if ((AckBuffer[0] == 0x00) && (AckBuffer[1] == 0x44))
+			{
+				int indexextra = 0;
+				for (indexextra = 0; indexextra < 14; indexextra++)
+				{
+					AckBuffer[indexextra] = AckBuffer[indexextra + 1];
+				}
+			}
+			if (bRet && (!memcmp(AckBuffer, "DATA", 4)))
+			{
+				// 成功
+				LogInfo("DownloadOneImagefunc:: STAT_SET_PACKET_SIZE OK");
+				printf("DownloadOneImagefunc:: STAT_SET_PACKET_SIZE OK\n");
+
+				dwDDRPacketSize = strtoul((char *)AckBuffer + 4, 0, 16);
+				// 将此包不是发送的一包的长度值实际是是DDR中设置的一包内存的大小。
+				if (dwDDRPacketSize > CurrentConfig.mCurrentFile.dwLength)
+				// 如果返回待写数据长度,大于镜像文件长度,则失败
+				{
+					LogInfo("DownloadOneImagefunc:: return data length greater than file total length, fail...dwDDRPacketSize = %d, CurrentConfig.mCurrentFile.dwLength = %d", dwDDRPacketSize, CurrentConfig.mCurrentFile.dwLength);
+					printf("DownloadOneImagefunc:: return data length greater than file total length, fail...dwDDRPacketSize = %d, CurrentConfig.mCurrentFile.dwLength = %d\n", dwDDRPacketSize, CurrentConfig.mCurrentFile.dwLength);
+
+					State = GotoNextState(State, FALSE);
+					bRet = FALSE;
+				}
+				else
+				{
+					LogInfo("DownloadOneImagefunc:: return data length  <= file total length, dwDDRPacketSize = %d, CurrentConfig.mCurrentFile.dwLength = %d", dwDDRPacketSize, CurrentConfig.mCurrentFile.dwLength);
+					// 执行下一项流程
+					dwCurrentSize = dwDDRPacketSize;
+					State = GotoNextState(State, TRUE);
+				}
+			}
+			else // 失败
+			{
+				LogInfo("DownloadOneImagefunc:: STAT_SET_PACKET_SIZE fail");
+				State = GotoNextState(State, FALSE);
+				bRet = FALSE;
+			}
+		}
+		break;
+
+			//------------------------Image数据-----------------------------
+		case STAT_DATAPACKET:
+		{
+			dwFileSize -= dwCurrentSize;
+			if (dwCurrentSize >= CurrentConfig.mPacketSize)
+			{
+				dwPacketSize = CurrentConfig.mPacketSize;
+			}
+			else
+			{
+				dwPacketSize = dwCurrentSize;
+			}
+
+			BYTE *WriteBuffer = (BYTE *)malloc(dwPacketSize);
+			if (dwCurrentSize > 0)
+			{
+				while (1)
+				{
+					// 读取磁盘数据
+					memset(WriteBuffer, 0, dwPacketSize);
+
+					if (CurrentConfig.mCurrentFile.bReadFromFile)
+					{
+						if (dwCurrentSize > dwPacketSize)
+						{
+							dwPacketSize = dwPacketSize;
+						}
+						else
+						{
+							dwPacketSize = dwCurrentSize;
+
+							if ((dwPacketSize % 512) == 0)
+							{
+								dwPacketSize -= 8;
+								// usb若不支持长度是512整数包,用0包表示结束时,则在此处拆包。
+								LogInfo("DownloadOneImagefunc:: STAT_DATAPACKET  split packet");
+								// printf("DownloadOneImagefunc:: STAT_DATAPACKET  split packet\n");
+							}
+							else
+							{
+								usleep(2 * 1000);
+								// 由于有拆包动作,最后一包需要等待先前数据发送完成。
+							}
+						}
+						if (fread(&WriteBuffer[0], 1, dwPacketSize, pf) != dwPacketSize)
+						{
+							LogInfo("DownloadOneImagefunc:: read packte fail");
+
+							State = GotoNextState(State, FALSE);
+							if (WriteBuffer != NULL)
+							{
+								free(WriteBuffer);
+								WriteBuffer = NULL;
+							}
+							bRet = FALSE;
+							break;
+						}
+					}
+					else
+					{
+						if (CurrentConfig.mCurrentFile.pImageCache != NULL)
+						{
+							memcpy(&WriteBuffer[0], pBuffer, dwPacketSize);
+							pBuffer += dwPacketSize;
+						}
+					}
+
+					// 发送数据到UE
+					bRet = SendData(WriteBuffer, dwPacketSize, 20, 1);
+					if (bRet == TRUE)
+					{
+						LogInfo("DownloadOneImagefunc:: STAT_DATAPACKET :send one packet success");
+						// printf("DownloadOneImagefunc:: STAT_DATAPACKET :send one packet success\n");
+					}
+					else
+					{
+						LogInfo("DownloadOneImagefunc:: STAT_DATAPACKET :send one packet FAIL!");
+						State = GotoNextState(State, FALSE);
+						bRet = FALSE;
+						break;
+					}
+					dwCurrentSize -= dwPacketSize;
+					if (dwCurrentSize == 0)
+					{
+						LogInfo("DownloadOneImagefunc:: STAT_DATAPACKET :dwCurrentSize == 0");
+						if (dwFileSize > 0) //
+						{
+							AckBuffer = (BYTE *)ReadDataExtraFuncB(14, 10, 4 * 60); // 适配nor flash,最大超时时间改为4分钟
+							LogInfo("DownloadOneImagefunc::  AckBuffer = %x", AckBuffer[0]);
+							if ((AckBuffer[0] == 0x00) && (AckBuffer[1] == 0x44))
+							{
+								int indexextra = 0;
+								for (indexextra = 0; indexextra < 14; indexextra++)
+								{
+									AckBuffer[indexextra] = AckBuffer[indexextra + 1];
+								}
+							}
+							if (bRet && (!memcmp(AckBuffer, "DATA", 4)))
+							{
+								// 成功
+								LogInfo("DownloadOneImagefunc:: STAT_SET_PACKET_SIZE OK");
+								printf("DownloadOneImagefunc:: STAT_SET_PACKET_SIZE OK\n");
+
+								dwDDRPacketSize = strtoul((char *)AckBuffer + 4, 0, 16);
+								// 将此包不是发送的一包的长度值实际是是DDR中设置的一包内存的大小。
+								if (dwDDRPacketSize > CurrentConfig.mCurrentFile.dwLength)
+								// 如果返回待写数据长度,大于镜像文件长度,则失败
+								{
+									LogInfo("DownloadOneImagefunc:: return data length greater than file total length, fail...dwDDRPacketSize = %d, CurrentConfig.mCurrentFile.dwLength = %d", dwDDRPacketSize, CurrentConfig.mCurrentFile.dwLength);
+									State = GotoNextState(State, FALSE);
+									bRet = FALSE;
+								}
+								else
+								{
+									LogInfo("DownloadOneImagefunc:: return data length  <= file total length, dwDDRPacketSize = %d, CurrentConfig.mCurrentFile.dwLength = %d", dwDDRPacketSize, CurrentConfig.mCurrentFile.dwLength);
+									// 执行下一项流程
+									dwCurrentSize = dwDDRPacketSize;
+								}
+							}
+							else // 失败
+							{
+								LogInfo("DownloadOneImagefunc:: STAT_SET_PACKET_SIZE fail");
+								State = GotoNextState(State, FALSE);
+								bRet = FALSE;
+							}
+						}
+						else // 文件的最后一包
+						{
+
+							// lx,如果支持CRC校验,boot回复CRC校验值,否则回复OKEY
+							if (m_bCRCCheck)
+							{
+								bRet = ReadData((BYTE *)&ulAckCRCValue, 4, 30, 4 * 60); // 适配nor flash,最大超时时间改为4分钟
+								LogInfo("DownloadOneImagefunc:: CurrentConfig.mCurrentFile.ulCRCValue = %ld ulAckCRCValue = %ld", CurrentConfig.mCurrentFile.ulCRCValue, ulAckCRCValue);
+								// printf("DownloadOneImagefunc:: CurrentConfig.mCurrentFile.ulCRCValue = %ld ulAckCRCValue = %ld\n", CurrentConfig.mCurrentFile.ulCRCValue, ulAckCRCValue);
+								if (bRet && (CurrentConfig.mCurrentFile.ulCRCValue == ulAckCRCValue))
+								{
+									// PrintInfo(_T("Image data send success!"));
+									LogInfo("DownloadOneImagefunc:: Image data send success!CurrentConfig.mCurrentFile.ulCRCValue = %ld ulAckCRCValue = %ld", CurrentConfig.mCurrentFile.ulCRCValue, ulAckCRCValue);
+									// printf("DownloadOneImagefunc:: Image data send success!CurrentConfig.mCurrentFile.ulCRCValue = %ld ulAckCRCValue = %ld\n", CurrentConfig.mCurrentFile.ulCRCValue, ulAckCRCValue);
+									bRet = TRUE;
+									State = GotoNextState(State, TRUE);
+								}
+								else
+								{
+									// PrintInfo(_T("Image data send fail!"));
+									LogInfo("DownloadOneImagefunc:: Image data send fail!");
+									bRet = FALSE;
+									State = GotoNextState(State, FALSE);
+								}
+							}
+							else
+							{
+								LogInfo("DownloadOneImagefunc:: not CRCCheck");
+								printf("DownloadOneImagefunc:: not CRCCheck\n");
+								AckBuffer = (BYTE *)ReadDataExtraFuncB(5, 10, 4 * 60); // 适配nor flash,最大超时时间改为4分钟
+								// bRet = ReadDataExtraFuncA(14, 10 , 100);
+								if (AckBuffer != NULL)
+								{
+									LogInfo("DownloadOneImagefunc::  AckBuffer... %s", AckBuffer);
+									// printf("DownloadOneImagefunc::  AckBuffer... %s\n", AckBuffer);
+								}
+								else
+								{
+									LogInfo("DownloadOneImagefunc::  AckBuffer is NULL");
+								}
+								if (bRet && (!memcmp(AckBuffer, "OKAY", 4)))
+								{
+									LogInfo("DownloadOneImagefunc::  Image data send success!");
+									printf("DownloadOneImagefunc::  Image data send success!\n");
+									bRet = TRUE;
+									State = GotoNextState(State, TRUE);
+								}
+								else
+								{
+									LogInfo("DownloadOneImagefunc::  Image data send fail!");
+									State = GotoNextState(State, FALSE);
+									bRet = FALSE;
+								}
+							}
+						}
+						break;
+					}
+				}
+			}
+
+			if (WriteBuffer != NULL)
+			{
+				free(WriteBuffer);
+				WriteBuffer = NULL;
+			}
+		}
+		break;
+			//--------------------------执行代码-----------------------------
+		case STAT_EXECUTE_CODE:
+		{
+			LogInfo("DownloadOneImagefunc:: EXECUTE_CODE IN mbExecuteCode = %d PartitionType = %s", CurrentConfig.mbExecuteCode, CurrentConfig.mCurrentFile.PartitionType);
+			// printf("DownloadOneImagefunc:: EXECUTE_CODE IN mbExecuteCode = %d PartitionType = %s\n", CurrentConfig.mbExecuteCode, CurrentConfig.mCurrentFile.PartitionType);
+			if ((TRUE == CurrentConfig.mbExecuteCode) && (memcmp(CurrentConfig.mCurrentFile.PartitionType, "zftl", 3) == 0))
+			{
+				LogInfo("DownloadOneImagefunc::   start EXECUTE_CODE");
+				printf("DownloadOneImagefunc::   start EXECUTE_CODE\n");
+				memset(CommandBuffer, 0, sizeof(CommandBuffer));
+				memcpy(CommandBuffer, ("reboot"), strlen(("reboot")));
+				bRet = SendData(CommandBuffer, strlen((const char *)CommandBuffer) + 1, 10, 1);
+				if (bRet)
+				{
+					AckBuffer = (BYTE *)ReadDataExtraFuncB(14, 10, 10);
+					if (AckBuffer != NULL)
+					{
+						LogInfo("DownloadOneImagefunc::  AckBuffer... %s", AckBuffer);
+						// printf("DownloadOneImagefunc::  AckBuffer... %s\n", AckBuffer);
+					}
+					else
+					{
+						LogInfo("DownloadOneImagefunc::  AckBuffer is NULL");
+					}
+				}
+				if (bRet && !memcmp(AckBuffer, "OKAY REBOOT", 11))
+				{
+					// PrintInfo(_T("正在执行代码..."));
+					LogInfo("DownloadOneImagefunc::   EXECUTE_CODE  on doing...");
+					printf("DownloadOneImagefunc::   EXECUTE_CODE  on doing...\n");
+				}
+				else
+				{
+					char *strInfo;
+					char *strTemp;
+
+					// sprintf(strInfo,"bRet = %d",bRet);
+					// sprintf(strTemp,"%s",&AckBuffer[0]);
+					LogInfo("DownloadOneImagefunc::   EXECUTE_CODE  fail");
+
+					bRet = FALSE;
+				}
+			}
+			else
+			{
+				bRet = TRUE;
+			}
+			State = GotoNextState(State, TRUE);
+		}
+		break;
+		default:
+			bExit = TRUE;
+			break;
+		}
+	}
+
+	if (pf != NULL)
+	{
+		fclose(pf);
+		pf = NULL;
+		LogInfo("DownloadOneImagefunc::  fclose(pf) ");
+	}
+	return bRet;
+}
+
+// 修改这个函数的打印 bufantong
+static BOOL DownloadImage(stFileItem ImageInfo, BOOL bExecuteCode)
+{
+	BOOL bRet = FALSE;
+	stDownloadConfig CurrentConfig;
+	CurrentConfig.mCurrentFile = ImageInfo;
+
+	// 判断文件的类型
+	switch (ImageInfo.nType)
+	{
+	case nand: // 类型为nand 时,写操作之前全部擦除。
+		LogInfo("DownloadImagefunc:: case nand...");
+		printf("DownloadImagefunc:: case nand...\n");
+
+		m_pProtocolTable = m_DownloadImageTable;
+
+		CurrentConfig.mPacketSize = PACKET_SIZE_FLASH;
+
+		// 下载到Flash中的文件是不需要打开启动AMT的标志的
+		m_StartAMT = FALSE;
+		break;
+
+	case fs:
+		LogInfo("DownloadImagefunc:: case fs...");
+		printf("DownloadImagefunc:: case fs...\n");
+		m_pProtocolTable = m_DownloadImageTable;
+
+		CurrentConfig.mPacketSize = PACKET_SIZE_FLASH;
+
+		// 下载到Flash中的文件是不需要打开启动AMT的标志的
+		m_StartAMT = FALSE;
+		break;
+
+	case zftl: // 该分支是下载NVR分区用的 分区名是NVR,NVRW ,RAMDISK三个分区是该类型,写操作时,是先备份再擦写再覆盖。
+		LogInfo("DownloadImagefunc:: case zftl...");
+		printf("DownloadImagefunc:: case zftl...\n");
+		ImageInfo.nType = zftl;
+		m_pProtocolTable = m_DownloadImageTable;
+		CurrentConfig.mPacketSize = PACKET_SIZE_FLASH;
+
+		// 下载NV备份文件是不需要打开启动AMT的标志的
+		m_StartAMT = FALSE;
+		break;
+
+	case ddr:
+		// pImageInfo->nType = EXTSRAM;
+		LogInfo("DownloadImagefunc:: case ddr...");
+		printf("DownloadImagefunc:: case ddr...\n");
+		ImageInfo.nType = ddr;
+		m_pProtocolTable = m_DownloadRAMImageTable;
+		CurrentConfig.mPacketSize = PACKET_SIZE_IMAGE;
+		CurrentConfig.mCurrentFile.PartitionName[0] = 'd';
+		CurrentConfig.mCurrentFile.PartitionName[1] = 'd';
+		CurrentConfig.mCurrentFile.PartitionName[2] = 'r';
+		CurrentConfig.mCurrentFile.PartitionName[3] = '\0';
+
+		m_StartAMT = TRUE;
+		break;
+	case zloader:
+		LogInfo("DownloadImagefunc::  case zloader...");
+		printf("DownloadImagefunc::  case zloader...\n");
+		// pImageInfo->nType = EXTSRAM;
+		ImageInfo.nType = zloader;
+		m_pProtocolTable = m_DownloadRAMImageTable;
+		CurrentConfig.mPacketSize = PACKET_SIZE_IMAGE;
+		CurrentConfig.mCurrentFile.PartitionName[0] = 'z';
+		CurrentConfig.mCurrentFile.PartitionName[1] = 'l';
+		CurrentConfig.mCurrentFile.PartitionName[2] = 'o';
+		CurrentConfig.mCurrentFile.PartitionName[3] = 'a';
+		CurrentConfig.mCurrentFile.PartitionName[4] = 'd';
+		CurrentConfig.mCurrentFile.PartitionName[5] = 'e';
+		CurrentConfig.mCurrentFile.PartitionName[6] = 'r';
+		CurrentConfig.mCurrentFile.PartitionName[7] = '\0';
+
+		m_StartAMT = TRUE;
+		break;
+
+	default:
+	{
+		LogInfo("DownloadImagefunc:: not right type...");
+		printf("DownloadImagefunc:: not right type...\n");
+		return TRUE;
+	}
+	break;
+	}
+
+	if (ImageInfo.bReadFromFile)
+	{
+		if (access(g_path, 0) != 0)
+		{
+			printf("DownloadImagefunc:: software file path is error.\r\n");
+			return FALSE;
+		}
+		pf = fopen(g_path, "rb");
+		if (pf == NULL)
+		{
+			LogInfo("DownloadImagefunc::  Open file FAIL... %s", g_path);
+		}
+	}
+	CurrentConfig.mStartState = STAT_SET_PACKET_SIZE;
+	// CurrentConfig.mpFile = pf;
+	CurrentConfig.mbExecuteCode = bExecuteCode;
+	// 这个函数里也加了打印
+	bRet = DownloadOneImage(CurrentConfig);
+	// usleep(10*1000);
+	if (ImageInfo.bReadFromFile)
+	{
+		if (pf != NULL)
+		{
+			fclose(pf);
+			pf = NULL;
+			LogInfo("DownloadImagefunc::  fclose(pf) ");
+		}
+	}
+	return bRet;
+}
+
+static BOOL ExchangeImage()
+{
+	BOOL bRet = FALSE;
+	BOOL bExecuteCode = FALSE;
+	LogInfo("ExchangeImagefunc:: g_DownLoadFileNum = %d ...", g_DownLoadFileNum);
+	if (g_DownLoadFileNum == 0)
+	{
+		LogInfo("ExchangeImagefunc:: g_DownLoadFileNum == 0 ...", g_DownLoadFileNum);
+		return bRet;
+	}
+	int fileIndex = 0;
+	for (fileIndex = 1; fileIndex <= g_DownLoadFileNum; fileIndex++)
+	{
+		LogInfo("CYF start ExchangeImage = %d ...", fileIndex);
+
+		LogInfo("ExchangeImagefunc:: FileItem[%d].bDownload = %d", fileIndex, FileItem[fileIndex].bDownload);
+		LogInfo("ExchangeImagefunc:: FileItem[%d].strFileName = %s", fileIndex, FileItem[fileIndex].strFileName);
+		LogInfo("ExchangeImagefunc:: FileItem[%d].bUseRelativePath = %d", fileIndex, FileItem[fileIndex].bUseRelativePath);
+		LogInfo("ExchangeImagefunc:: FileItem[%d].bReadFromFile = %d", fileIndex, FileItem[fileIndex].bReadFromFile);
+		LogInfo("ExchangeImagefunc:: FileItem[%d].bAutoDeleteImageCache = %d", fileIndex, FileItem[fileIndex].bAutoDeleteImageCache);
+		LogInfo("ExchangeImagefunc:: FileItem[%d].pImageCache = %s", fileIndex, FileItem[fileIndex].pImageCache);
+		LogInfo("ExchangeImagefunc:: FileItem[%d].dwOffset = %d", fileIndex, FileItem[fileIndex].dwOffset);
+		LogInfo("ExchangeImagefunc:: FileItem[%d].PartitionName = %s", fileIndex, FileItem[fileIndex].PartitionName);
+		LogInfo("ExchangeImagefunc:: FileItem[%d].dwLength = %d", fileIndex, FileItem[fileIndex].dwLength);
+		LogInfo("ExchangeImagefunc:: FileItem[%d].nPartitionOffset = %d", fileIndex, FileItem[fileIndex].nPartitionOffset);
+		LogInfo("ExchangeImagefunc:: FileItem[%d].PartitionType = %d", fileIndex, FileItem[fileIndex].PartitionType);
+		LogInfo("ExchangeImagefunc:: FileItem[%d].nType = %d", fileIndex, FileItem[fileIndex].nType);
+
+		LogInfo("ExchangeImagefunc:: bDownload FileItem[fileIndex].bDownload = %d...", FileItem[fileIndex].bDownload);
+		if (FileItem[fileIndex].bDownload)
+		{
+			if (fileIndex == g_DownLoadFileNum)
+			{
+				LogInfo("ExchangeImagefunc::   bExecuteCode == TRUE ..., fileIndex = %d", fileIndex);
+				bExecuteCode = FALSE;
+			}
+			else
+			{
+				LogInfo("ExchangeImagefunc::   bExecuteCode == FALSE ..., fileIndex = %d", fileIndex);
+			}
+			LogInfo("ExchangeImagefunc::   bDownload true ...");
+			bRet = DownloadImage(FileItem[fileIndex], bExecuteCode);
+			usleep(10 * 1000);
+		}
+		else
+		{
+			LogInfo("ExchangeImagefunc::  bDownload false...");
+		}
+
+		if (bRet)
+		{
+			LogInfo("ExchangeImagefunc::  %d  OK...", fileIndex);
+			printf("ExchangeImagefunc::  %d  OK...\r\n", fileIndex);
+		}
+		else
+		{
+			LogInfo("ExchangeImagefunc::  %d  FAIL...", fileIndex);
+			printf("ExchangeImagefunc::  %d  FAIL...\r\n", fileIndex);
+			break;
+		}
+	}
+	return bRet;
+}
+
+static BOOL UnInitialize()
+{
+	return TRUE;
+}
+
+static BOOL DoDownload(enDownloadType DownloadType, BYTE *pBuffer, DWORD dwSize, BOOL bBackupNV, enDownloadNVBackupMethod Method, BOOL bEableCRCCheck)
+{
+	BOOL bRet = FALSE;
+	BOOL bReturn = FALSE;
+	BOOL bExit = FALSE;
+	typedef enum
+	{
+		STAT_INIT,
+		STAT_COLLECT_UPLOAD_NV_INFO,
+		STAT_COLLECT_DOWNLOAD_IMAGE_INFO,
+		STAT_EXCHANGE_IMAGE,
+		STAT_START_AMT,
+		STAT_UNINIT,
+		STAT_EXIT
+	} STAT_ITEM;
+	int nState = STAT_INIT;
+	LogInfo("DoDownloadfunc:: start...");
+	m_bBackUpNV = bBackupNV;
+	while (!bExit)
+	{
+		switch (nState)
+		{
+		case STAT_INIT: // 初始化资源
+			bRet = Initialize();
+			if (bRet)
+			{
+				LogInfo("DoDownloadfunc::  STAT_INIT OK...");
+				// PrintInfo(_T("init sucess!"));
+				nState = STAT_COLLECT_UPLOAD_NV_INFO;
+			}
+			else
+			{
+				// PrintInfo(_T("init fail!"));
+				LogInfo("DoDownloadfunc::  STAT_INIT FAIL...");
+				nState = STAT_EXIT;
+			}
+			break;
+
+		case STAT_COLLECT_UPLOAD_NV_INFO: // 收集备份NV上载信息
+			// lx增加CRC校验握手状态
+			if (bEableCRCCheck)
+			{
+				nState = STAT_CRC_ON;
+			}
+			else if (m_bCRCCheck)
+			{
+				nState = STAT_CRC_OFF;
+			}
+			else
+			{
+				nState = STAT_COLLECT_DOWNLOAD_IMAGE_INFO;
+			}
+			break;
+
+		case STAT_CRC_ON:
+		{
+			// 打开CRC校验
+			BYTE CommandBuffer[255] = {0};
+			BYTE AckBuffer[255] = {0};
+			memset(CommandBuffer, 0, sizeof(CommandBuffer));
+			memset(AckBuffer, 0, sizeof(AckBuffer));
+			memcpy(&CommandBuffer[0], "CRC ON", 6);
+			bRet = SendData(CommandBuffer, strlen((const char *)CommandBuffer) + 1, 10, 1);
+			if (bRet)
+			{
+				bRet = ReadData(AckBuffer, 5, 10, 30);
+			}
+			if (bRet && (!memcmp(AckBuffer, "OKAY", 4)))
+			{
+				// boot支持CRC校验
+				// PrintInfo(_T("CRC校验打开成功!"));
+				LogInfo("DoDownloadfunc::  CRC open OK...");
+				m_bCRCCheck = TRUE;
+				nState = STAT_COLLECT_DOWNLOAD_IMAGE_INFO;
+			}
+			else // 失败
+			{
+				// PrintInfo(_T("CRC校验打开失败!"));
+				LogInfo("DoDownloadfunc::  CRC open FAIL..");
+				m_bCRCCheck = FALSE;
+				nState = STAT_COLLECT_DOWNLOAD_IMAGE_INFO;
+			}
+		}
+		break;
+		case STAT_CRC_OFF:
+		{
+			// 关闭CRC校验
+			BYTE CommandBuffer[255] = {0};
+			BYTE AckBuffer[255] = {0};
+			memset(CommandBuffer, 0, sizeof(CommandBuffer));
+			memset(AckBuffer, 0, sizeof(AckBuffer));
+			memcpy(&CommandBuffer[0], "CRC OFF", 7);
+			bRet = SendData(CommandBuffer, strlen((const char *)CommandBuffer) + 1, 10, 1);
+			if (bRet)
+			{
+				bRet = ReadData(AckBuffer, 5, 10, 30);
+			}
+			if (bRet && (!memcmp(AckBuffer, "OKAY", 4)))
+			{
+				// boot支持CRC校验
+				// PrintInfo(_T("CRC校验关闭成功!"));
+				LogInfo("DoDownloadfunc::  CRC close OK...");
+				m_bCRCCheck = FALSE;
+				nState = STAT_COLLECT_DOWNLOAD_IMAGE_INFO;
+			}
+			else // 失败
+			{
+				// PrintInfo(_T("CRC校验关闭失败!"));
+				LogInfo("DoDownloadfunc::  CRC close FAIL...");
+				m_bCRCCheck = TRUE;
+				nState = STAT_COLLECT_DOWNLOAD_IMAGE_INFO;
+			}
+		}
+		break;
+
+		case STAT_COLLECT_DOWNLOAD_IMAGE_INFO: // 收集下载Image信息
+											   // 收集下载Image信息
+			LogInfo("DoDownloadfunc::  Collect image...");
+			CollectDownloadImage(DownloadType, pBuffer, dwSize);
+			nState = STAT_EXCHANGE_IMAGE;
+			break;
+
+		case STAT_EXCHANGE_IMAGE: // Exchange数据
+
+			LogInfo("DoDownloadfunc::  ExchangeImage...");
+			bRet = ExchangeImage();
+			if (bRet)
+			{
+				// PrintInfo(_T("Exchange data success!"));
+				nState = STAT_START_AMT;
+			}
+			else
+			{
+				// PrintInfo(_T("Exchange data fail!"));
+				nState = STAT_UNINIT;
+			}
+			break;
+
+		case STAT_START_AMT: // 发送启动AMT标志
+			bReturn = TRUE;
+			nState = STAT_UNINIT;
+			break;
+
+		case STAT_UNINIT: // 释放资源
+			bRet = UnInitialize();
+			if (bRet)
+			{
+				// PrintInfo(_T("release success!"));
+			}
+			else
+			{
+				// PrintInfo(_T("release fail!"));
+				bReturn = FALSE;
+			}
+			nState = STAT_EXIT;
+			break;
+
+		default:
+			bExit = TRUE;
+		}
+	}
+
+	return bReturn;
+}
+
+/*******************************************************************************
+ *                       		外部函数                                  *
+ *******************************************************************************/
+BOOL ExecuteEraseNVRW(const char *softwarepath)
+{
+	BOOL bRet = FALSE;
+
+	LogInfo("ExecuteEraseNVRWfunc:: start...");
+	printf("ExecuteEraseNVRWfunc:: start...");
+
+	strcpy(g_path, (char *)softwarepath);
+
+	if (!EraseNVRW())
+	{
+		LogInfo("ExecuteEraseNVRWfunc:: EraseNVRW FAIL...");
+	}
+	else
+	{
+		LogInfo("ExecuteEraseNVRWfunc:: EraseNVRW OK...");
+		bRet = TRUE;
+	}
+	return bRet;
+}
+
+int PrimaryDoDownload(const char *softwarepath)
+{
+	// 打开log文件
+	// 提示开始下载
+	printf("PrimaryDoDownloadfunc:: start\r\n");
+	LogInfo("PrimaryDoDownloadfunc:: start\r\n");
+
+	enERRORCODE DownloadResult = Download_OK;
+	strcpy(g_path, softwarepath);
+
+	// 下载版本文件
+	if (!DoDownload(DOWNLOAD_TYPE_IMAGE, NULL, 0, FALSE, METHOD_NORMAL, FALSE))
+	{
+		LogInfo("PrimaryDoDownloadfunc:: DoDownload Image FAIL...");
+		DownloadResult = Download_DOWNLOAD_IMAGE_FAIL;
+	}
+	else
+	{
+		LogInfo("PrimaryDoDownloadfunc:: DoDownload Image OK...");
+	}
+	LogInfo("PrimaryDoDownloadfunc:: DoDownload Image DownloadResult=%d", DownloadResult);
+
+	return DownloadResult;
+}
+
+// 下载tloader, tboot, partion
+BOOL DoDownloadBootForDL(BOOL bCheckPartition, const char *softwarepath)
+{
+	long n = 1000000;
+	double duration = 0;
+
+	clock_t start;
+	clock_t finish;
+	DWORD nStartTime = 0;
+	DWORD nStopTime = 0;
+	BOOL bRet = FALSE;
+	BOOL bTotalRet = TRUE;
+	BOOL bExit = FALSE;
+	typedef enum
+	{
+		STAT_INIT,
+		STAT_DOWNLOAD_BOOT1,
+		STAT_DOWNLOAD_BOOT2,
+
+		STAT_DOWNLOAD_PARTITION,
+		STAT_UNINIT,
+		STAT_EXIT
+	} STAT;
+	int nState = STAT_INIT;
+	int nWhile = 0;
+
+	strcpy(g_path, softwarepath);
+
+	LogInfo("DoDownloadBootForDL:: start...");
+	printf("DoDownloadBootForDL:: start...\n");
+
+	while (!bExit)
+	{
+		LogInfo("DoDownloadBootForDLfunc:: nWhile = %d\n", nWhile);
+		printf("DoDownloadBootForDLfunc:: nWhile = %d\n", nWhile);
+		nWhile++;
+
+		switch (nState)
+		{
+		case STAT_INIT: // 初始化资源
+
+			bRet = PreInitBoot();
+
+			if (bRet)
+			{
+				LogInfo("DoDownloadBootForDLfunc::  PreInitBoot OK...");
+				nState = STAT_DOWNLOAD_BOOT1;
+			}
+			else
+			{
+				LogInfo("DoDownloadBootForDLfunc:: PreInitBoot FAIL...");
+				printf("DoDownloadBootForDLfunc:: PreInitBoot FAIL...\n");
+
+				bTotalRet = FALSE;
+				nState = STAT_EXIT;
+			}
+			break;
+			/*********************add zxw 20121009 for 296301 begin************************************/
+		case STAT_DOWNLOAD_BOOT1: // 下载stage1, TLoader
+
+			start = clock(); // 记录开始时间
+			LogInfo("DoDownloadBootForDLfunc::  start download BOOT1...");
+			printf("DoDownloadBootForDLfunc::  start download BOOT1...\n");
+
+			bRet = DownloadOneBoot(m_dwBootStage1StartAddress, m_dwBootStage1Size, pf, 4000, m_stMasterInfo.tloaderOffset, TRUE);
+
+			finish = clock(); // 结束时间
+			duration = (double)(finish - start) / CLOCKS_PER_SEC;
+			LogInfo("DoDownloadBootForDLfunc::  download BOOT1 communication time: %lf", duration);
+
+			if (bRet)
+			{
+				LogInfo("DoDownloadBootForDLfunc::  download BOOT1 OK");
+				nState = STAT_DOWNLOAD_BOOT2;
+			}
+			else
+			{
+				LogInfo("DoDownloadBootForDLfunc::  download BOOT1 FAIL");
+				printf("DoDownloadBootForDLfunc::  download BOOT1 FAIL\n");
+
+				bTotalRet = FALSE;
+				nState = STAT_UNINIT;
+			}
+			break;
+
+		case STAT_DOWNLOAD_BOOT2: // 下载stage2, TBoot
+
+			start = clock(); // 记录开始时间
+			LogInfo("DoDownloadBootForDLfunc::  start download BOOT2...");
+			printf("DoDownloadBootForDLfunc::  start download BOOT2...\n");
+
+			bRet = DownloadOneBoot(m_dwBootStage2StartAddress, m_dwBootStage2Size, pf, 4000, m_stMasterInfo.tBootOffset, TRUE);
+
+			finish = clock(); // 结束时间
+			duration = (double)(finish - start) / CLOCKS_PER_SEC;
+			LogInfo("DoDownloadBootForDLfunc::  download BOOT2 communication time: %lf", duration);
+
+			if (bRet)
+			{
+				LogInfo("DoDownloadBootForDLfunc::  download BOOT2 OK");
+				nState = STAT_DOWNLOAD_PARTITION;
+			}
+			else
+			{
+				LogInfo("DoDownloadBootForDLfunc::  download BOOT2 FAIL");
+				printf("DoDownloadBootForDLfunc::  download BOOT2 FAIL\n");
+
+				nState = STAT_UNINIT;
+				bTotalRet = FALSE;
+			}
+			break;
+			/*********************add zxw 20121009 for 296301 end************************************/
+		case STAT_DOWNLOAD_PARTITION:
+
+			start = clock(); // 记录开始时间
+			LogInfo("DoDownloadBootForDLfunc::  start download PARTITION");
+			printf("DoDownloadBootForDLfunc::  start download PARTITION\n");
+
+			bRet = DownloadPartition((size_t)m_dwPartitionSize, pf, 4096, m_stMasterInfo.PartitionOffset, FALSE);
+
+			finish = clock(); // 结束时间
+			duration = (double)(finish - start) / CLOCKS_PER_SEC;
+			LogInfo("DoDownloadBootForDLfunc::  download PARTITION communication time: %lf", duration);
+
+			if (bRet)
+			{
+				LogInfo("DoDownloadBootForDLfunc:: DownloadPartition : download OK");
+			}
+			else
+			{
+				LogInfo("DoDownloadBootForDLfunc:: DownloadPartition : download FAIL");
+				printf("DoDownloadBootForDLfunc:: DownloadPartition : download FAIL\n");
+				bTotalRet = FALSE;
+			}
+
+			nState = STAT_UNINIT;
+			break;
+
+		case STAT_UNINIT:
+			bRet = UnPreInitBoot();
+			if (bRet)
+			{
+				LogInfo("DoDownloadBootForDLfunc::  UnPreInitBoot OK");
+			}
+			else
+			{
+				LogInfo("DoDownloadBootForDLfunc::  UnPreInitBoot FAIL");
+				bTotalRet = FALSE;
+			}
+			nState = STAT_EXIT;
+			break;
+
+		default:
+
+			bExit = TRUE;
+			break;
+		}
+	}
+	return bTotalRet;
+}
diff --git a/ap/hostapp/zdownloader/download.h b/ap/hostapp/zdownloader/download.h
new file mode 100755
index 0000000..0fae875
--- /dev/null
+++ b/ap/hostapp/zdownloader/download.h
@@ -0,0 +1,476 @@
+#ifndef _DOWNLOAD_H_
+#define _DOWNLOAD_H_
+
+#include "define.h"
+
+// BI层最大支持线程数
+#define TSP_THREAD_NUM      64
+
+// 下载文件类型
+#define FLASH                   (0x01)
+#define EXTSRAM                 (0x02)
+#define FPGA                    (0x03)
+#define RAMIMAGE                (0x04)
+#define NVBACKUP                (0x05)
+#define ZPHY_ERFC_CA_NUMBER     2
+
+// 串行口参数配置
+#define READ_INTERVAL_TIMEOUT           (0)
+#define READ_TOTAL_TIMEOUT_MULTIPLIER   (0)
+#define READ_TOTAL_TIMEOUT_CONSTANT     (0)
+#define WRITE_TOTAL_TIMEOUT_MULTIPLIER  (0)
+#define WRITE_TOTAL_TIMEOUT_CONSTANT    (1000)
+
+// 收发数据包大小
+#define READ_QUEUE      (4096)
+#define WRITE_QUEUE     (4096)
+
+// 波特率设置选项
+#define NO_OF_PARAMS    (7)
+#define COM_PORT        (1)
+#define BAUD_RATE       (2)
+#define PARITY          (3)
+#define STOP_BITS       (4)
+#define DATA_BITS       (5)
+#define READ_INTVL      (6)
+#define TOTAL_TIME      (7)
+
+//
+//#define BUFFERLEN             1100
+#define AT_CMD_TYPE_TEST      1000
+#define AT_CMD_TYPE_AT        1001
+#define INFO_PACKET_LEN       1024
+// 下载的配置文件选项
+#define VERSION_NUM           4
+
+#define CONFIG_SECTION_CFG                  _T("Configuration")
+#define CONFIG_SECTION_VERSION              _T("Version")
+#define CONFIG_SECTION_CHIPDETAILS          _T("ChipDetails")
+#define CONFIG_SECTION_ARM_BIN              _T("ArmBin")
+#define CONFIG_SECTION_ZSP_BIN              _T("ZspBin")
+#define CONFIG_SECTION_ZSPCC_BIN            _T("ZspCCBin")
+#define CONFIG_SECTION_ARM1_BIN             _T("Arm1Bin")
+#define CONFIG_SECTION_TDNV_BIN             _T("TDNVBin")
+#define CONFIG_SECTION_AP_BIN               _T("APBin")
+#define CONFIG_SECTION_RAMDISK_BIN          _T("RAMDiskBin")
+#define CONFIG_SECTION_PHY_FILES_INFO       _T("AMT_PHY_FILES_INFO")
+#define CONFIG_SECTION_DOWNLOAD_IMAGE       _T("DownloadImage")
+#define CONFIG_SECTION_NV_BACKUP            _T("NVBackup")
+#define CONFIG_SECTION_INDEX_LIST           _T("IndexList")
+#define CONFIG_SECTION_IN_SOFTVERSION       _T("SoftVersionIn")
+#define CONFIG_SECTION_OUT_SOFTVERSION      _T("SoftVersionOut")
+#define CONFIG_SECTION_SSID_FLAG            _T("SSIDFlag")
+#define CONFIG_SECTION_SSID                 _T("SSID")
+
+#define CONFIG_SECTION_BUILD_DATE           _T("BuildDate")
+#define CONFIG_SECTION_BUILD_TIME           _T("BuildTime")
+#define CONFIG_SECTION_RALETIVEPATHBOOT     _T("RaletivePathBOOT")
+#define CONFIG_SECTION_RALETIVEPATHAT       _T("RaletivePathAT")
+#define CONFIG_SECTION_RALETIVEPATHATLC     _T("RaletivePathATLC")
+#define CONFIG_SECTION_RALETIVEPATHLOG      _T("RaletivePathLOG")
+#define CONFIG_SECTION_RALETIVEPATHFT       _T("RaletivePathFT")
+#define CONFIG_KEY_VERSION                  _T("Version")
+#define CONFIG_KEY_FILE                     _T("File")
+#define CONFIG_KEY_STARTADDRESS             _T("StartAddress")
+#define CONFIG_KEY_ENDADDRESS               _T("EndAddress")
+#define CONFIG_KEY_TYPE                     _T("Type")
+#define CONFIG_KEY_DEBUGINFO                _T("DebugInfo")
+#define CONFIG_KEY_OPENLOGPORT              _T("IsOpenLogPort")
+#define CONFIG_KEY_NVBACKUPCOUNT            _T("NVItemCount")
+#define CONFIG_KEY_TLFILE                   _T("TLFile")
+#define CONFIG_KEY_TLSTARTADDRESS           _T("TLStartAddress")
+#define CONFIG_KEY_TDPSTARTADDRESS          _T("TDPStartAddress")
+#define CONFIG_KEY_FLASHSTARTADDRESS        _T("FlashStartAddress")
+#define CONFIG_KEY_COUNT                    _T("Count")
+#define CONFIG_KEY_MANUID                   _T("ManuID")
+#define CONFIG_KEY_DEVICEID                 _T("DeviceID")
+#define CONFIG_KEY_TDPPATH                  _T("TDPPath")
+#define CONFIG_KEY_RELATIVEPATH             _T("UseRelativePath")
+#define CONFIG_KEY_READFROMFILE             _T("ReadFromFile")
+#define CONFIG_KEY_FILESYSTEM               _T("FileSystem")
+#define CONFIG_KEY_LENGTH                   _T("Length")
+#define CONFIG_KEY_BUILD_DATE               _T("BuildDate")
+#define CONFIG_KEY_BUILD_TIME               _T("BuildTime")
+#define CONFIG_KEY_SN_INDEX                 _T("SNIndex")
+// ....by wong
+#define CONFIG_KEY_HARDWARE_SN_INDEX        _T("HARDWARE_SNIndex")
+#define CONFIG_KEY_IMEI_INDEX               _T("IMEIIndex")
+#define CONFIG_KEY_WIFI_MAC_INDEX           _T("WIFIIndex")
+#define CONFIG_KEY_RJ45_MAC_INDEX           _T("RJ45MACIndex")
+#define CONFIG_KEY_TESTINFO_INDEX           _T("TestInfoIndex")
+#define CONFIG_KEY_SN_BACKUP_INDEX          _T("SNBackupIndex")
+#define CONFIG_KEY_IMEI_BACKUP_INDEX        _T("IMEIBackupIndex")
+#define CONFIG_KEY_TESTINFO_BACKUP_INDEX    _T("TestInfoBackupIndex")
+#define CONFIG_KEY_BBACKUPAREA              _T("bBackupArea")
+#define CONFIG_KEY_RALETIVEPATH             _T("RaletivePath")
+#define CONFIG_KEY_ATVERSION                _T("AtVersion")
+#define CONFIG_KEY_TESTINFODOWNLOAD			_T("TestInfoDLPV")
+
+//#define CONFIG_KET_ISBOOTROM				_T("IsBootRom")
+#define CONFIG_KEY_USBORUARTPORT            _T("USBORUARTPORT")
+#define CONFIG_KEY_BOOTSTAGE1FILE           _T("BootStage1File")   //add zxw 20130422 for 296301
+#define CONFIG_KEY_BOOTSTAGE1STARTADDRESS   _T("BootStage1StartAddress")
+#define CONFIG_KEY_BOOTSTAGE2FILE           _T("BootStage2File")   //add zxw 20120422 for 296301
+#define CONFIG_KEY_BOOTSTAGE2STARTADDRESS   _T("BootStage2StartAddress")
+#define CONFIG_KEY_PARTITIONFILE            _T("PartitionFile")   //add zxw 20120422 for 296301
+#define CONFIG_KEY_PARTITIONSTARTADDRESS    _T("PartitionStartAddress")
+#define CONFIG_KEY_PARTITIONNAME            _T("PartitionName")
+#define CONFIG_KEY_PARTITIONTYPE            _T("PartitionType")
+#define CONFIG_KEY_STARTAMTCMD              _T("StartAMTCMD")
+#define CONFIG_KEY_ISDOWNLOAD_PV            _T("ISDownLoadPV")
+#define CONFIG_KEY_PHY_FILE_NUMS            _T("FileNumber")
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+// For CDownload
+#define BI_TSP_ERROR_BASE_CDownload         (BI_TSP_ERROR_BASE_CTransmit + 10000)
+
+typedef enum
+{
+    TYPE_BOOT,              // 从TYPE_BOOT到TYPE_TEST_AUTO
+    TYPE_BOOT_AUTO,         // 属于老版本设计的思路,其初衷
+    TYPE_EVB_TEST,          // 是按照EVB、FWP、DATACARD进行
+    TYPE_EVB_LOG,           // 分类,根据配置界面(校准的脚本)
+    TYPE_FWP_TEST,          // 设置对应的值,达到找到对应端口
+    TYPE_FWP_LOG,           // 的目的。这种做法看似简单,但
+    TYPE_DATACARD_TEST,     // 带来了维护方面的困难,因此,
+    TYPE_DATACARD_LOG,      // 将采用新的方法进行兼容性过度
+    TYPE_TEST_AUTO,
+    TYPE_AT,                // 过度的准则是:在配置文件中设置对应端口的匹配信息
+    TYPE_LOG,               // 所有项目通过这对统一的入口与端口对接
+    TYPE_FT,                // 打开FT的AT口
+    TYPE_BOOT_P93B,         // P93B的Boot口
+    TYPE_AT_P93B,           // P93B的AT口
+    TYPE_AT_LC,
+    TYPE_INVALID = 99,
+} enCOMTYPE;
+
+typedef enum
+{
+    TYPE_GPIB = 0,
+    TYPE_LAN,
+
+} enTransferType;
+
+typedef enum
+{
+	OFF_STATE =0,
+	ON_STATE,
+	ERR_STATE,
+
+} enBootFlag;
+// BOOT口列表
+#define TYPE_BOOT_LIST  TYPE_BOOT, TYPE_BOOT_P93B
+// AT口列表
+#define TYPE_AT_LIST    TYPE_EVB_TEST, TYPE_FWP_TEST, TYPE_DATACARD_TEST, TYPE_AT, TYPE_FT, TYPE_AT_P93B
+// LOT口列表
+#define TYPE_LOG_LIST   TYPE_EVB_LOG, TYPE_FWP_LOG, TYPE_DATACARD_LOG
+
+typedef struct _COMSTRUCT
+{
+#pragma pack(1)
+    BYTE    byByteSize;
+    BYTE    byParity;
+    BYTE    byStopBits;
+    DWORD   dwBaudRate;
+    DWORD   dwReadInterval;
+    DWORD   dwTotalTime;
+#pragma pack()
+} COMSTRUCT;
+
+typedef struct
+{
+    int   cmd;
+    unsigned char   Msg[INFO_PACKET_LEN];
+}Msg_PACKET;
+
+// start =============================================================================================
+#define DLTYPE_CONTROL_BEGIN() \
+typedef enum{ \
+DLTYPE_OWNERSTATE_START	= 0x00, \
+
+#define DLTYPE_CONTROL_END() \
+DLTYPE_OWNERSTATE_END = 0X11, \
+}enDLTYPE_CONTROL;
+//  CDownload绑定状态位索引
+// 下载类型绑定状态位,enDownloadType高字合计2个字节空间,支持16个小bool位控制从BI传入BL
+// 如: 免PV的标志位IsNoPVDownLoad变量传入
+// 若已经使用某一位,则不可再复用
+
+#define STATEFLAG(x) (1<<x)
+
+DLTYPE_CONTROL_BEGIN()						// start 在此内部添加[下载类型绑定状态位]传入BL
+	DLTYPE_OWNERSTATE_NONEPV			= STATEFLAG(0),		// 免PV控制开关
+	DLTYPE_OWNERSTATE_NONEPV_ERASEAUTO	= STATEFLAG(1),
+	DLTYPE_OWNERSTATE_NONEPV_ERASEALL	= STATEFLAG(2),
+	// TODO
+
+DLTYPE_CONTROL_END()						// end
+// end    =============================================================================================
+
+
+//CDownload
+typedef enum
+{
+	DOWNLOAD_TYPE_AMT,
+    DOWNLOAD_TYPE_AMT_MODEM,        //modem 小系统
+    DOWNLOAD_TYPE_AMT_AP,           // AP小系统
+    DOWNLOAD_TYPE_IMAGE,            // 版本文件
+    DOWNLOAD_TYPE_NV_IMAGE,         // NV镜像文件
+    DOWNLOAD_TYPE_NV,               // NV 备份文件
+    DOWNLOAD_TYPE_SN,               // SN文件
+    DOWNLOAD_TYPE_IMEI,             // IMEI文件
+    DOWNLOAD_TYPE_TESTINFO,         // TESTINFO文件
+    DOWNLOAD_TYPE_SN_BACKUP,        // SN Backup文件
+    DOWNLOAD_TYPE_IMEI_BACKUP,      // IMEI Backup文件
+    DOWNLOAD_TYPE_TESTINFO_BACKUP,  // TESTINFO Backup文件
+    DOWNLOAD_TYPE_IN_SOFTVERSION,      // SoftVersion文件
+    DOWNLOAD_TYPE_MAC_WIFI,
+    DOWNLOAD_TYPE_SSID_FLAG,
+    DOWNLOAD_TYPE_SSID,
+    DOWNLOAD_TYPE_FS_FLAG,
+	DOWNLOAD_TYPE_OUT_SOFTVERSION,     // SoftVersion文件
+	DOWNLOAD_TYPE_HARDWARE_SN,		// HARDWARE_SN 下载硬件版本号
+	DOWNLOAD_TYPE_TESTINFO_DL_PV,		// 下载PV版本的生产测试标志位
+	DOWNLOAD_TYPE_TESTINFO_DL_RELEASE,	// 下载发货版本的生产测试标志位
+	DOWNLOAD_TYPE_TESTINFO_DL_AMT,		// 下载AMT版本的生产测试标志位
+	DOWNLOAD_TYPE_MAC_RJ45,
+} enDownloadType;
+
+typedef enum
+{
+    METHOD_NORMAL,              // 只备份工作区
+    METHOD_WORK_BACKUP,         // 根据标志位,备份工作区、备份区
+    METHOD_WRITE_TO_FILE,       // 备份时,若板号不为空,则将NV数据写入文件
+} enDownloadNVBackupMethod;
+
+// 待下载镜像文件信息 CDownload
+typedef struct
+{
+    BOOL    bDownload;              // 上/下载功能标志,TRUE = 下载;FALSE = 上载
+    char * strFileName;            // 文件路径
+    BOOL    bUseRelativePath;       // 文件路径是否为相对路径;TRUE = 相对路径;FALSE = 绝对路径
+    BOOL    bReadFromFile;          // 下载时,是否直接从文件读取;TRUE = 数据取自文件;FALSE = 数据取自内存
+  //  BOOL    bFileSystem;            // 镜像文件是否为文件系统;TRUE = 文件系统文件;FALSE = 非文件系统文件
+    BOOL    bAutoDeleteImageCache;  // 是否自动回收镜像缓存
+    BYTE   *pImageCache;            // 镜像缓存
+	//  DWORD   dwStartAddress;         // 下载/上载绝对起始地址
+
+    DWORD   dwOffset;               // 相对于文件/缓存的偏移 
+	DWORD   dwLength;               // 下载/上载数据长度
+    int     nType;                  // 下载类型
+	char    PartitionName[16];    	//分区名  add zxw 20130422
+	char    FileName[16];
+    char    PartitionType[16] ;
+    DWORD   nPartitionOffset;
+	//新增文件的CRC校验值
+	ULONG   ulCRCValue;
+	
+} stFileItem;
+
+// NV备份信息
+typedef struct
+{
+    enDownloadType   nType;         // NV备份的类型
+    BYTE            *pBuffer;       // NV备份的缓存
+    DWORD            dwStartAddress;// NV备份的下载地址
+    DWORD            dwLength;      // NV备份的长度
+} stNVItem;
+
+typedef struct
+{
+    unsigned long dwResult;
+} stResult;
+
+//////////////////////////////////////////////////////////////////////////
+typedef unsigned int UINT32;
+typedef   signed int SINT32;
+typedef unsigned short UINT16;
+typedef   signed short SINT16;
+
+// 分区表相关的信息
+#define MAX_ENTRY          16
+
+// add cxh 7510 下载分区文件类型
+#define nand                      (0x01) 
+#define fs                        (0x02)
+//#define NV                        (0x03) 
+#define zftl                      (0x03)
+#define ddr                       (0x04)
+#define raw                       (0x05)
+#define zloader                   (0x06)
+
+// 合并BIN文件中Masterhead结构
+typedef struct
+{
+	BYTE   FileId[16];
+    BYTE   chVersionIN[32];
+    BYTE   chVersionOUT[32];
+	DWORD  nTotalFileNum; 
+    DWORD  nFlashType;
+    DWORD  nNVCoalition; 
+    DWORD   iFileSize;      
+    DWORD   iCkeckSum;
+    DWORD   iImageStructOffset;
+    DWORD   tloaderOffset;
+    DWORD   tloaderLength;
+    DWORD   tBootOffset;
+    DWORD   tBootLength;
+    DWORD   PartitionOffset;
+    DWORD   PartitionLength;
+    BYTE    UnUsed[80];          //预留区
+}stBinMasterInfo;
+
+
+typedef struct  
+{
+    BYTE	PartitionName[16]; 
+    BYTE    PartitionType[16];
+    unsigned int    PartitionSize;
+    unsigned int    PartitionOffset;  
+}partition_entry;
+
+typedef struct 
+{
+    unsigned int       iPartitionMagic;
+    BYTE               PlatformName[16];
+    unsigned int       iPartitionVersion;     /* 分区版本 */
+    unsigned int       iPartitionEntrys;      /* 总的分区个数 */
+    unsigned int       iPartitionCrc;
+    partition_entry    PartitionTable[MAX_ENTRY];
+}partition_table;
+
+
+// 合并BIN文件的文件头部信息 CDownload
+typedef struct
+{
+    BYTE    nTotalFileNum;          // BIN文件中包含的子文件总数量
+    BYTE    UnUsed[15];             // 未使用
+} stBinInfo;
+
+// 合并BIN文件的每个文件信息 CDownload
+typedef struct
+{
+    DWORD   dwOffset;               // 子文件相对于BIN文件起始的偏移
+    DWORD   dwLength;               // 子文件长度
+    DWORD   dwStartAddress;         // 子文件待下载的绝对地址
+    DWORD    nType;                  // 子文件的类型
+    BYTE    bFileSystem;            // 子文件的文件系统标志
+	
+} stBinFileHeader;
+
+typedef struct  
+{
+    BYTE  FileName[64];
+    BYTE  PartitionName[16];
+	BYTE PartitionType[16];
+    unsigned int iFileLength;
+	unsigned int iPartitionOffset;
+    unsigned int iFileOffset; // 子文件相对于BIN文件起始的偏移
+    //相对于分区起始地址的偏移
+    BYTE  UnUsed[20];
+}stBinImageHead;
+
+typedef enum
+{
+	HDT_W_MAIN = 0,
+	HDT_W_ASSIST,
+	HDT_W_MAANDAS,
+}E_HDT_WAGCTYPE;
+
+typedef struct
+{
+    int  iErrorCode;
+    char cBarcode[21];
+} stDLDBInfo;
+
+typedef enum
+{
+    STAT_SYNC,                  // 0
+    STAT_START_BYTE,            // 1
+    STAT_NO_MODIFY_REG,         // 2
+    STAT_ADDRESS,               // 3
+    STAT_DATA_LEN,              // 4
+    STAT_DATAPACKET,            // 5
+    STAT_LINK_EST,              // 6
+    STAT_DEVICEINFO,            // 7
+    STAT_CONFIGTDP,             // 8
+    STAT_PROG_DEV_ST_ADDR,      // 9
+    STAT_PROG_DEV_END_ADDR,     // 10
+    STAT_SET_PACKET_SIZE,       // 11
+    STAT_CHANGE_CONFIG,         // 12
+    STAT_ERASE_SEG_ST_ADDR,     // 13
+    STAT_ERASE_SEG_END_ADDR,    // 14
+    STAT_DEV_BASE_ADDR,         // 15
+    STAT_EXECUTE_CODE,          // 16
+    STAT_TERMINATE,             // 17
+    STAT_RVRS_DWNLD,            // 18
+    STAT_UPLD_DATA_SIZE,        // 19
+    STAT_SUCCESS,               // 20
+	STAT_CRC_ON,   
+	STAT_CRC_OFF, 
+    // New stat add code here
+} enSTAT;
+
+
+//Bootrom & TLoader公用下载协议
+#define CMD_SYNC_BYTE_BOOTROM        0x5A
+#define CMD_SYNC_BYTE_ACK_BOOTROM    0xA5
+#define CMD_SEND_REG_CONFIG_BOOTROM  0x6A
+#define CMD_SEND_DATA_BOOTROM        0x7A
+#define CMD_STARTUP_BOOTROM          0x8A
+
+//7520V2 bootrom&TLoader新增回复命令
+#define CMD_SEND_ADDRESS_LEN_ACK_BOOTROM    0xA1
+#define CMD_SEND_DATA_ACK_BOOTROM           0xA7
+#define CMD_STARTUP_ACK_BOOTROM             0xA8
+
+
+//TBoot运行同步协议
+#define CMD_SYNC_TBOOT				 0x5A
+#define CMD_SYNC_ACK_TBOOT			 0xA7
+
+#define PACKET_SIZE_BOOT        131072 
+//#define PACKET_SIZE_BOOT        131072 
+
+#define PACKET_SIZE_TL          1024
+#define PACKET_SIZE_TDP         4096
+
+#define PACKET_SIZE_FLASH      	4096
+
+//#define PACKET_SIZE_FLASH      2097152
+#define PACKET_SIZE_IMAGE       131072
+#define PACKET_SIZE_FILESYSTEM  135168
+
+//partiiton协议
+typedef enum  
+{  // STAT_TBOOT_OK,
+    STAT_SYNC_PARTIITON,
+    STAT_SET_PARTITION_CMD,
+    STAT_SEND_PARTIITON,
+    STAT_EXIT,
+
+}enParpSTAT;
+
+typedef struct
+{
+    enSTAT  mNextTRUE;
+    enSTAT  mNextFALSE;
+} stSTAT;
+
+typedef struct DownloadConfig
+{  
+    enSTAT      mStartState;
+    BOOL        mbExecuteCode; //下载后,是否启动运行,暂时无用  zxw 20130422    
+    stFileItem  mCurrentFile;
+    DWORD       mPacketSize; //数据包大小,新方案由UE侧上传,暂无用处  zxw 20130422  //这个还是有用的,大小不超过2M就可以
+} stDownloadConfig;
+
+// 执行擦除NVRW
+BOOL ExecuteEraseNVRW(const char *softwarepath);
+// 下载boot和tloader
+BOOL DoDownloadBootForDL(BOOL bCheckPartition, const char *softwarepath);
+// 下载主流程
+int PrimaryDoDownload(const char *softwarepath);
+
+#endif
diff --git a/ap/hostapp/zdownloader/main.c b/ap/hostapp/zdownloader/main.c
new file mode 100755
index 0000000..a56e732
--- /dev/null
+++ b/ap/hostapp/zdownloader/main.c
@@ -0,0 +1,509 @@
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "CSerial.h"
+#include "LogInfo.h"
+#include "download.h"
+#include "devUsb.h"
+
+/*******************************************************************************
+ *                       			宏定义                                  *
+ *******************************************************************************/
+// #define OPENLOG 1
+#define KEYCODELENGTH            (16)
+#define IDENTIFYCODE             0xdf, 0xf1, 0x13, 0x63, 0x1a, 0x98, 0xcd, 0xa8, 0xa5, 0x19, 0x7c, 0x1b, 0x1a, 0xba, 0x9f, 0xd7
+
+#define TTY_USB0                 ("ttyUSB0")
+#define TTY_USB1                 ("ttyUSB1")
+#define TTY_USB2                 ("ttyUSB2")
+#define TTY_USB3                 ("ttyUSB3")
+
+#define PORT_STA_NO              (0)
+#define PORT_STA_AT              (7)
+#define PORT_STA_DL              (3)
+#define PORT_STA_BUSY            (12)
+
+#define MAX_PORT_PATH_LENGTH	 (32)
+#define MAX_CMD_LENGTH	         (64)
+#define MAX_CHECK_VERSION_TIMES  (10)
+#define MAX_OPEN_DL_PORT_TIMES   (50)
+
+static int g_atPortInfo[3] = {0x19d2, 0x0582, 4};
+static int g_dlPortInfo[3] = {0x19d2, 0x0256, 0};
+static int g_at_ttyId = -1;
+static int g_dl_ttyId = -1;
+
+/*******************************************************************************
+ *                       		内部函数声明                                  *
+ *******************************************************************************/
+// 模块掉电重启
+static void HardWareReset(int type);
+// 校验传入参数的相应bin文件是否合法
+static int FileAnalyse(const char* path);
+// 判断AT命令是否返回相应的子串
+static int ChekATBackString(const char *atstring, const char *findversion);
+// 进入下载流程
+static enERRORCODE OpenDownloadPortAndDownload(const char *softwarepath, const char *RebackString);
+// 参数选项介绍
+static int usage(const char *exe);
+
+/*******************************************************************************
+ *                       		内部函数定义                                  *
+ *******************************************************************************/
+ /** Modem(模块)掉电重启
+ * @brief 
+ * @param type      			入参,重启类型,0:通过AT命令重启,1:DL口reboot重启
+ * @return 
+ * @retval
+ * @note
+ * @warning
+ */
+#if 0
+void HardWareReset()
+{	/*
+	system("echo 1 > /sys/class/gpio_sw/PH12/data");	//模块下电
+	usleep(1*1000*1000);	//delay
+	system("echo 0 > /sys/class/gpio_sw/PH12/data");  //模块上电
+	*/
+	char * AT= "at\r\n";	
+	ChekATBackString(AT,"OK");
+	char * AT_SoftwareReset = "at+zsoftreset\r\n";	
+	ChekATBackString(AT_SoftwareReset,"OK");//reset
+	
+}
+#endif
+static void HardWareReset(int type)
+{
+	char cversion[1024] = {0};
+	char dev_tty[MAX_PORT_PATH_LENGTH] = {0};
+	char AT_Reset[MAX_CMD_LENGTH] = "\r\nat+zsoftreset\r\n";
+	char cmdDevReboot[MAX_CMD_LENGTH] = "echo reboot > /dev/ttyUSB";
+
+	snprintf(dev_tty, MAX_PORT_PATH_LENGTH, "/dev/ttyUSB%d", g_at_ttyId);
+	snprintf(cmdDevReboot, MAX_CMD_LENGTH, "echo reboot > /dev/ttyUSB%d", g_dl_ttyId);
+
+	if (type == 0)
+	{
+		SendATString(dev_tty, AT_Reset, cversion);
+	}
+	else
+	{
+		printf("HardWareReset(1):: %s \r\n", cmdDevReboot);
+		system(cmdDevReboot);
+	}
+}
+
+/**
+ * @brief 校验传入参数的相应bin文件是否合法
+ * @param path      			入参,要下载的bin文件路径
+ * @return 成功返回 TRUE,失败返回 FALSE
+ * @retval
+ * @note
+ * @warning
+ */
+static BOOL FileAnalyse(const char* path)
+{
+	FILE *pf;
+	unsigned char keycode[KEYCODELENGTH] = {0};
+	int i = 0;
+	unsigned char standardkeycod[] =
+		{
+			IDENTIFYCODE};
+	if (access(path, F_OK) != 0)
+	{
+		LogInfo("software file path is not exist.");
+		return FALSE;
+	}
+	pf = fopen(path, "rb");
+	if (NULL == pf)
+	{
+		LogInfo("open %s error:%s", path, strerror(errno));
+		return FALSE;
+	}
+
+	int num = fread(keycode, sizeof(char), KEYCODELENGTH, pf);
+	if (KEYCODELENGTH != num)
+	{
+		LogInfo("read %s error", path);
+		return FALSE;
+	}
+
+	for (i = 0; i < KEYCODELENGTH; i++)
+	{
+		if (keycode[i] != standardkeycod[i])
+		{
+			fclose(pf);
+			pf = NULL;
+			return FALSE;
+		}
+	}
+	fclose(pf);
+	pf = NULL;
+	return TRUE;
+}
+
+/**
+ * @brief 判断AT命令是否返回相应的子串
+ * @param AtString      		入参,发送的AT命令字符串
+ * @param findversion           入参,要比较的子串
+ * @return 成功返回0,失败返回-1
+ * @retval
+ * @note
+ * @warning
+ */
+static int ChekATBackString(const char *atstring, const char *findversion)
+{
+	char dev_tty[MAX_PORT_PATH_LENGTH] = {0};
+	char cversion[1024] = {0};
+
+	snprintf(dev_tty, MAX_PORT_PATH_LENGTH, "/dev/ttyUSB%d", g_at_ttyId);
+
+	SendATString(dev_tty, atstring, cversion);
+
+	if ((cversion != NULL) && (findversion != NULL))
+	{
+		LogInfo("AT send over , cversion = %s, findversion = %s", cversion, findversion);
+	}
+	else
+	{
+		LogInfo("AT send over , version ptr is error");
+	}
+
+	printf("AT actual return = %s\n", cversion);
+	printf("AT suppose to be = %s\n", findversion);
+
+	if (strstr(cversion, findversion))
+	{
+		return 0;
+	}
+	else
+	{
+		return -1;
+	}
+}
+
+/**
+ * @brief 打开下载口并进行下载流程
+ * @param softwarepath      	入参,要下载的bin文件路径
+ * @param RebackString          入参,要校验的bin文件版本号
+ * @return 返回 enERRORCODE 枚举值
+ * @retval
+ * @note
+ * @warning
+ */
+static enERRORCODE OpenDownloadPortAndDownload(const char *softwarepath, const char *RebackString)
+{
+	int ret;
+	// char *diagport = DL_PORT;
+	char dev_dltty[MAX_PORT_PATH_LENGTH] = {0};
+	char *AT_GetVersion = "at+cgmr\r\n";
+	char *AT_OpenDL = "at+zflag=\"BOOT\",0\r\n";
+	char *AT_CloseDL = "at+zflag=\"BOOT\",1\r\n";
+
+	char AtReturnValue[128] = {0};
+	int portState = 0;
+	BOOL SucFlag = FALSE;
+	int i = 0, z = 0;
+
+	printf("DL version = 1.0\n");
+	// 检查是否输入版本号
+	if(RebackString[0] != '\0')
+	{
+		printf("%s:: Bin version = %s\n", __FUNCTION__, RebackString);
+		LogInfo("Bin version = %s", RebackString);
+	}
+	else
+	{
+		printf("%s:: not check version\n", __FUNCTION__);
+		LogInfo("not check version");
+	}	
+	// 查找AT口
+	ret = dev_get_device(g_atPortInfo);
+	if(ret == -1)
+	{
+		printf("%s:: get at info failed, please restart module!!!\n", __FUNCTION__);
+		LogInfo("get at info failed, please restart module!!!");
+		return Download_FIND_AT_FAIL;
+	}
+	else
+	{
+		g_at_ttyId = g_usb_dev;
+		printf("%s:: Find AT port.\n", __FUNCTION__);
+	}
+
+		 	
+	int j = 0;
+	while (j < 3)
+	{
+		if (-1 == ChekATBackString(AT_OpenDL, "OK")) // open dl port ,at command
+		{
+			printf("OpenDownloadPortAndDownloadfunc:: AT_OpenDL send fail!, times = %d\n", j + 1);
+		}
+		else
+		{
+			printf("OpenDownloadPortAndDownloadfunc:: AT_OpenDL send ok!, times = %d\n", j + 1);
+			break;
+		}
+		j++;
+		usleep(500 * 1000); // delay
+
+		// if (j >= 3)
+		// {
+		// 	LogInfo("OpenDownloadPortAndDownloadfunc:: AT_OPENDLPORT FAIL");
+		// 	return Download_AT_OPENDLPORT_FAIL;
+		// }
+	}
+
+	// 重启,进入下载通道
+	printf("OpenDownloadPortAndDownloadfunc:: HardWare Reset 1, please wait\r\n");
+	HardWareReset(0);
+	usleep(4000 * 1000); // 延时等待DL口枚举
+	// 查找DL口
+	ret = dev_get_device(g_dlPortInfo);
+	if(ret == -1)
+	{
+		printf("get dl info failed\n");
+		return Download_OPENDLPORT_FAIL;
+	}
+	else
+	{
+		g_dl_ttyId = g_usb_dev;
+		snprintf(dev_dltty, MAX_PORT_PATH_LENGTH, "/dev/ttyUSB%d", g_dl_ttyId);
+	}		
+
+	i = MAX_OPEN_DL_PORT_TIMES;
+	while (i > 0)
+	{
+		// usleep(200*1000);
+		if (-1 == (Open(dev_dltty)))
+		{
+			printf("OpenDownloadPortAndDownloadfunc:: Diag open Failed, times = %d\r\n", MAX_OPEN_DL_PORT_TIMES - i + 1);
+			--i;
+			continue;
+		}
+		else
+		{
+			printf("OpenDownloadPortAndDownloadfunc:: Diag open ok!\r\n");
+			break;
+		}
+	}
+	if (i <= 0)
+	{
+		LogInfo("OpenDownloadPortAndDownloadfunc:: OPEN DLPORT FAIL");
+		return Download_OPENDLPORT_FAIL;
+	}
+
+	// 进入下载TLoader和TBoot流程
+	if (!DoDownloadBootForDL(FALSE, softwarepath))
+	{
+		LogInfo("DoDownloadBootForDL FAIL...");
+		printf("DoDownloadBootForDL FAIL\r\n");
+		Close();
+		return Download_DOWNLOAD_IMAGE_FAIL;
+	}
+	LogInfo("DoDownloadBootForDL ok...");
+	printf("DoDownloadBootForDL ok\r\n");
+
+#if (ERASENVRW == 1)
+	if (!ExecuteEraseNVRW(softwarepath))
+	{
+		printf("OpenDownloadPortAndDownloadfunc:: ExecuteEraseNVRW Fail\r\n");
+		Close();
+		return Download_DOWNLOAD_IMAGE_FAIL;
+	}
+	printf("OpenDownloadPortAndDownloadfunc:: ExecuteEraseNVRW ok.\r\n");
+#endif
+	
+	// 进入下载版本文件流程
+	if (Download_OK != PrimaryDoDownload(softwarepath))
+	{
+		printf("OpenDownloadPortAndDownloadfunc:: PrimaryDoDownload fail return value = %d\r\n", Download_DOWNLOAD_IMAGE_FAIL);
+		Close();
+		return Download_DOWNLOAD_IMAGE_FAIL;
+	}
+	printf("OpenDownloadPortAndDownloadfunc:: PrimaryDoDownload OK\r\n");
+	Close();
+	LogInfo("OpenDownloadPortAndDownloadfunc:: PrimaryDoDownload end");
+
+	// 重启,进行检查版本号流程
+	usleep(100 * 1000); // delay
+	printf("OpenDownloadPortAndDownloadfunc:: HardWare Reset 2, please wait\r\n");
+	HardWareReset(1);
+
+	// 检查是否输入版本号
+	if (RebackString[0] != '\0')
+	{
+		// 延时等待AT口枚举
+		usleep(15 * 1000 * 1000);
+		printf("OpenDownloadPortAndDownloadfunc:: Begin to check version after Downloader.\r\n");
+
+		i = MAX_CHECK_VERSION_TIMES;
+		while (i > 0)
+		{
+			if (-1 == ChekATBackString(AT_GetVersion, RebackString))
+			{
+				printf("OpenDownloadPortAndDownloadfunc:: check version fail, %d!\r\n", MAX_CHECK_VERSION_TIMES - i + 1);
+			}
+			else
+			{
+				printf("OpenDownloadPortAndDownloadfunc:: check version OK.\r\n");
+				break;
+			}
+			i--;
+			usleep(1 * 1000 * 1000); // delay
+		}
+
+		// 检查版本号
+		if (i <= 0)
+		{
+			printf("OpenDownloadPortAndDownloadfunc:: Check version error!\r\n");
+			LogInfo("Check version error!");
+			return Download_CHECK_VERSION_FAIL;
+		}
+	}
+
+	return Download_OK;
+#if 0
+	i=5;
+	while(i > 0)
+	{
+		if(-1 == ChekATBackString(AT_CloseDL,"OK"))   //close dl port ,at command
+		{
+			printf("OpenDownloadPortAndDownloadfunc:: close dl port fail!\r\n");
+			//return Download_AT_CLOSE_DL_FAIL;	
+		}
+		else
+		{
+			printf("OpenDownloadPortAndDownloadfunc:: close dl port OK.\r\n");
+			return Download_OK;
+		}
+		i--;
+		usleep(1000*1000);//delay
+	}
+	return Download_CLOSE_DL_FAIL;
+#endif
+}
+
+/**
+ * @brief 参数选项介绍
+ * @param exe      			入参,应用名
+ * @return 成功返回0
+ * @retval
+ * @note
+ * @warning
+ */
+static int usage(const char *exe)
+{
+	printf("%s -p bin_path -c check_version\n", exe);
+	printf("-h, help\n");
+	printf("-p bin_file_path\n");
+	printf("-c check_version\n");
+	printf("-s save_log_path, default path is (%s)\n", DEFAULT_LOG_PATH);
+	return 0;
+}
+
+/*******************************************************************************
+ *                       	    	主函数                                   *
+ *******************************************************************************/
+int main(int argc, char *argv[])
+{
+	int ch;
+	int ret = -1;
+
+	enERRORCODE DownloadResultMain = Download_OK;
+	// remove(LOG_PATH);
+	char BinPath[FILE_PATH_LENGTH_MAX] = {0}; // BinFile Path
+	char BinVersion[FILE_PATH_LENGTH_MAX] = {0};
+	strncpy(g_log_path, DEFAULT_LOG_PATH, FOLDER_PATH_LENGTH_MAX - 1);
+
+	printf("main:: downloading ...\r\n");
+	LogInfo("Program Start1");
+	if (geteuid() != 0)
+	{
+		fprintf(stderr, "main:: This program must run as root!\n");
+		LogInfo("Program close");
+		DownloadResultMain = Download_NOT_ROOT;
+		LogInfo("return Download_NOT_ROOT");
+		return DownloadResultMain;
+	}
+
+	LogInfo("Program Start2");
+	if (argc == 1)
+	{
+		fprintf(stderr, "main:: The Parameter at least need 1 input, but now is %d, error!\n", argc-1);
+		DownloadResultMain = Download_ERROR_INPUT_ARGC;
+		usage(argv[0]);
+		LogInfo("return Download_ERROR_INPUT_ARGC");
+		return DownloadResultMain;
+	}
+
+	LogInfo("Program Start3");
+	while ((ch = getopt(argc, argv, "hp:c:s:")) != -1)
+	{
+		switch (ch)
+		{
+		case 'h':
+			ret = usage(argv[0]);
+			return ret;
+		case 'p':
+			strncpy(BinPath, optarg, FILE_PATH_LENGTH_MAX - 1);
+			printf("main:: -p, BinPath = %s\n", BinPath);
+			break;
+		case 'c':	
+			strncpy(BinVersion, optarg, FILE_PATH_LENGTH_MAX - 1);
+			printf("main:: -c, BinVersion = %s\n", BinVersion);
+			break;
+		case 's':
+			strncpy(g_log_path, optarg, FOLDER_PATH_LENGTH_MAX - 1);
+			printf("main:: -s, g_log_path = %s\n", g_log_path);
+			break;			
+        default:
+            usage(argv[0]);
+            break;			
+		}
+	}
+	if(BinPath[0] == '\0')
+	{
+		printf("main:: BinPath is NULL, please add -p bin_path\n");
+		LogInfo("BinPath is NULL, please add -p bin_path");
+		return Download_ERROR_INPUT_ARGC;
+	}
+	if(BinVersion[0] == '\0')
+	{
+		printf("main:: BinVersion is NULL, not check\n");
+		LogInfo("BinVersion is NULL, not check");
+	}
+
+	LogInfo("Program Start4");
+	if (!FileAnalyse(BinPath))
+	{
+		LogInfo("FileAnalyse Failed");
+		DownloadResultMain = Download_CHECK_BIN_FAIL;
+		LogInfo("return Download_CHECK_BIN_FAIL");
+		return DownloadResultMain;
+	}
+
+	LogInfo("Program Start5");
+	DownloadResultMain = OpenDownloadPortAndDownload(BinPath, BinVersion);
+	LogInfo("DownloadResultMain = %d", DownloadResultMain);
+
+	if (DownloadResultMain == Download_OK)
+	{
+		LogInfo("download success...................");
+		printf("main:: download success...................\n");
+	}
+	else
+	{
+		LogInfo("download fail...................");
+		printf("main:: download fail...................\n");
+		return DownloadResultMain;
+	}
+
+	return Download_OK;
+}
\ No newline at end of file