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

Change-Id: I11f167edfea428d9fab198ff00ff1364932d1b0b
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