| |
| #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; |
| } |