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