blob: a56e73268d3f7385396af7ff3fbdade9b7c281ab [file] [log] [blame]
#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;
}