480 lines
13 KiB
C++
480 lines
13 KiB
C++
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <unistd.h>
|
||
|
#include <strings.h>
|
||
|
#include <iostream>
|
||
|
#include <vector>
|
||
|
#include <signal.h>
|
||
|
#include <string.h>
|
||
|
#include <unistd.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <termios.h>
|
||
|
#include <curl/curl.h>
|
||
|
#include <iostream>
|
||
|
#include <fstream>
|
||
|
#include <cstring>
|
||
|
#include <vector>
|
||
|
#include <iomanip>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
|
||
|
|
||
|
#include <termios.h>
|
||
|
|
||
|
#include <getopt.h>
|
||
|
|
||
|
#include "ymodem.h"
|
||
|
#include "serial_port.h"
|
||
|
#include "download.h"
|
||
|
#include "checkversion.h"
|
||
|
#include <curl/curl.h>
|
||
|
|
||
|
#include <semaphore.h>
|
||
|
|
||
|
|
||
|
#define DEV_PATH_DEF "/dev/ttyUSB0"
|
||
|
#define BAUDRATE_DEF 115200
|
||
|
#define TIMEOUT_DEF 20 //10*100ms
|
||
|
double processvalue = 0;
|
||
|
#define short_wait_time 30
|
||
|
#define long_wait_time 3600
|
||
|
|
||
|
|
||
|
|
||
|
static int g_fd;
|
||
|
static struct ymodem ymodem;
|
||
|
static FILE* g_fp;
|
||
|
|
||
|
sem_t *my_semaphore;
|
||
|
int is_insem = 0;
|
||
|
|
||
|
void signal_handler(int signo) {
|
||
|
if (signo == SIGINT || signo == SIGTERM) {
|
||
|
// 在这里执行你的操作
|
||
|
sleep(1);
|
||
|
printf("Received termination signal. Performing cleanup...\n");
|
||
|
unsigned char stop_data[] = {0x18, 0x18, 0x18, 0x18, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08};
|
||
|
write(g_fd, stop_data, sizeof(stop_data));
|
||
|
sleep(1);
|
||
|
// system("/demo/bin/testprogram &");
|
||
|
if(is_insem == 1){
|
||
|
sem_post(my_semaphore);
|
||
|
is_insem = 0;
|
||
|
printf("%d\n",is_insem);
|
||
|
printf("出锁\n");
|
||
|
}
|
||
|
exit(0);
|
||
|
}
|
||
|
}
|
||
|
//输入进入ota的命令
|
||
|
void put_start_char(){
|
||
|
unsigned char start_data[] = {0xac,0x53,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x11,0x22,0x33,0x44,0x85,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x01,0x00,0x84,0x09};
|
||
|
write(g_fd, start_data, sizeof(start_data));
|
||
|
}
|
||
|
//清空串口缓存
|
||
|
int flush_serial_input() {
|
||
|
int result = tcflush(g_fd, TCIFLUSH);
|
||
|
if (result == -1) {
|
||
|
perror("tcflush");
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
int _putchar(unsigned char ch)
|
||
|
{
|
||
|
return write(g_fd, &ch, 1);
|
||
|
}
|
||
|
|
||
|
int _getchar(void)
|
||
|
{
|
||
|
ssize_t size;
|
||
|
unsigned char ch;
|
||
|
|
||
|
size = read(g_fd, &ch, 1);
|
||
|
if (size == 1)
|
||
|
return ch;
|
||
|
else
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
int get_result(void)
|
||
|
{
|
||
|
ssize_t size;
|
||
|
unsigned char ch;
|
||
|
char buffer[255];
|
||
|
|
||
|
size = read(g_fd, buffer, sizeof(buffer));
|
||
|
if (size > 0){
|
||
|
char hexData[1024];
|
||
|
std::vector<unsigned char> byteArray;
|
||
|
int i;
|
||
|
for (i = 0; i < size; i++) {
|
||
|
snprintf(&hexData[i * 2], sizeof(hexData) - i * 2, "%02X", buffer[i]);
|
||
|
byteArray.push_back(static_cast<unsigned char>(buffer[i]));
|
||
|
}
|
||
|
|
||
|
printf("Received result: %s\n", hexData);
|
||
|
for (unsigned char c : byteArray) {
|
||
|
std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(c) << " ";
|
||
|
}
|
||
|
std::cout << std::endl;
|
||
|
|
||
|
//解析部分
|
||
|
if (byteArray.size() >= 16 && byteArray[15] == 0x04) {
|
||
|
// 第15个字节是1
|
||
|
// 在这里编写处理逻辑
|
||
|
std::cout << "功能码为0x04 OTA升级时状态码上报" <<std::endl;
|
||
|
if(byteArray.size() >= 23 && byteArray[22] == 0x01){
|
||
|
std::cout << "升级包过大,取消升级" <<std::endl;
|
||
|
}
|
||
|
if(byteArray.size() >= 23 && byteArray[22] == 0x02){
|
||
|
std::cout << "写入闪存错误" <<std::endl;
|
||
|
}
|
||
|
if(byteArray.size() >= 23 && byteArray[22] == 0x03){
|
||
|
std::cout << "用户取消升级" <<std::endl;
|
||
|
}
|
||
|
if(byteArray.size() >= 23 && byteArray[22] == 0x04){
|
||
|
std::cout << "获取包错误" <<std::endl;
|
||
|
}
|
||
|
if(byteArray.size() >= 23 && byteArray[22] == 0x05){
|
||
|
std::cout << " 升级超时" <<std::endl;
|
||
|
}
|
||
|
if(byteArray.size() >= 23 && byteArray[22] == 0x06){
|
||
|
std::cout << "升级成功!" <<std::endl;
|
||
|
}
|
||
|
if(byteArray.size() >= 23 && byteArray[22] == 0x07){
|
||
|
std::cout << "错误太多" <<std::endl;
|
||
|
}
|
||
|
if(byteArray.size() >= 23 && byteArray[22] == 0x08){
|
||
|
std::cout << "包名错误" <<std::endl;
|
||
|
}
|
||
|
if(byteArray.size() >= 23 && byteArray[22] == 0x09){
|
||
|
std::cout << "包名相同" <<std::endl;
|
||
|
}
|
||
|
return 0;
|
||
|
}else
|
||
|
{
|
||
|
std::cout << "功能码错误" <<std::endl;
|
||
|
return -1;
|
||
|
}
|
||
|
}else{
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
int recv_file_size = 0;
|
||
|
|
||
|
int begin_packet_callback(const unsigned char *buf, unsigned long len)
|
||
|
{
|
||
|
recv_file_size = 0;
|
||
|
|
||
|
g_fp = fopen(ymodem.file_name,"wb+");
|
||
|
if(g_fp == NULL) {
|
||
|
printf("open %s error\r\n", ymodem.file_name);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int data_packet_callback(const unsigned char *buf, unsigned long len)
|
||
|
{
|
||
|
int invalid = 0;
|
||
|
|
||
|
//由于我传入data_packet_cb(&packet[PACKET_HEADER], packet_size)的
|
||
|
//是&packet[PACKET_HEADER], 是不带index的, 如果需要, 可以将整个包传入(ymodem.c line:273),
|
||
|
//再在这里判断index,避免出现重复写入或丢数据
|
||
|
|
||
|
recv_file_size += len;
|
||
|
|
||
|
if (recv_file_size > ymodem.file_size) {
|
||
|
invalid = recv_file_size - ymodem.file_size;
|
||
|
}
|
||
|
fwrite(buf, 1, len - invalid, g_fp);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int end_packet_callback(const unsigned char *buf, unsigned long len)
|
||
|
{
|
||
|
fclose(g_fp);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int recevice(void)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
printf("Receice Ymodem!\r\n");
|
||
|
|
||
|
ret = ymodem_receive(&ymodem);
|
||
|
|
||
|
//需要再发送两个0x4F,xshell/secureCRT才会提示传送完成
|
||
|
sleep(1);
|
||
|
ymodem.putchar(0x4F);
|
||
|
ymodem.putchar(0x4F);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
int send_begin_packet_callback(const unsigned char *buf, unsigned long len)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int send_data_packet_callback(const unsigned char *buf, unsigned long len)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int send_end_packet_callback(const unsigned char *buf, unsigned long len)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int send_file(const char* file_name)
|
||
|
{
|
||
|
int ret, fd, index, size;
|
||
|
|
||
|
printf("Send Ymodem! file: %s\r\n", file_name);
|
||
|
|
||
|
strcpy(ymodem.file_name, file_name);
|
||
|
|
||
|
fd = open(file_name, O_RDONLY);
|
||
|
if (fd <= 0)
|
||
|
return -1;
|
||
|
//get file data
|
||
|
index = 0;
|
||
|
ymodem.data = (unsigned char *)malloc(300*1024);
|
||
|
do {
|
||
|
size = read(fd, &ymodem.data[index], 1024);
|
||
|
if (size)
|
||
|
index += size;
|
||
|
} while(size > 0);
|
||
|
close(fd);
|
||
|
ymodem.file_size = index;
|
||
|
ret = ymodem_send(&ymodem);
|
||
|
|
||
|
free(ymodem.data);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void ymodem_help(void)
|
||
|
{
|
||
|
printf("Usage : ./ymodem [options]\n");
|
||
|
printf("options:\r\n");
|
||
|
printf("eg send Ymodem: ./ymodem -d /dev/ttyUSB0 -s /sdcard/test.txt\r\n");
|
||
|
printf("eg receive Ymodem: ./ymodem -d /dev/ttyUSB0\r\n");
|
||
|
printf("\t -d <device name> device path.设置设备名,默认/dev/ttyUSB0.\r\n");
|
||
|
printf("\t -s <file name> send Ymodem, receiving mode if not set.发送文件,如果不选,默认为接收文件\r\n");
|
||
|
printf("\t -t <timeout> Set getchar timeout,def:10(1s), 1=100ms.设置getchar超时,1为100毫秒,默认10=>1s.\r\n");
|
||
|
printf("\t --help display specific types of command line options.\r\n\r\n");
|
||
|
}
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
// 注册信号处理函数
|
||
|
signal(SIGINT, signal_handler); // SIGINT 对应Ctrl+C
|
||
|
signal(SIGTERM, signal_handler); // SIGTERM 对应kill或pkill
|
||
|
my_semaphore = sem_open("/my_semaphore", O_CREAT, 0644, 1);
|
||
|
|
||
|
int this_option_optind = optind ? optind : 1;
|
||
|
int option_index = 0;
|
||
|
int c = -1;
|
||
|
int timeout = TIMEOUT_DEF;
|
||
|
char dev_path[128] = DEV_PATH_DEF;
|
||
|
int is_send = 0;
|
||
|
char g_file_name[256] = {0};
|
||
|
int putchar_flag = 0;
|
||
|
int putchar_value = 0;
|
||
|
char url_download[256] = "";
|
||
|
char url_check[256] = "";
|
||
|
|
||
|
|
||
|
|
||
|
int res = -1;
|
||
|
|
||
|
while (1) {
|
||
|
struct option long_options[] = {
|
||
|
{"help", no_argument, 0, 'h' },
|
||
|
{"url_download", required_argument, 0, 'u'},
|
||
|
{"url_check", required_argument, 0, 'w'},
|
||
|
{0, 0, 0, 0 }
|
||
|
};
|
||
|
|
||
|
c = getopt_long_only(argc, argv, "c:s:d:t:u:w:h",
|
||
|
long_options, &option_index);
|
||
|
if (c == -1)
|
||
|
break;
|
||
|
|
||
|
switch (c) {
|
||
|
case 0:
|
||
|
break;
|
||
|
case 'c':
|
||
|
putchar_flag = 1;
|
||
|
putchar_value = optarg[0];
|
||
|
printf("putchar value: %c\r\n", putchar_value);
|
||
|
break;
|
||
|
case 'd':
|
||
|
strcpy(dev_path, optarg);
|
||
|
printf("dev path: %s\r\n", dev_path);
|
||
|
break;
|
||
|
case 's':
|
||
|
strcpy(g_file_name, optarg);
|
||
|
printf("send file: %s.\r\n", g_file_name);
|
||
|
is_send = 1;
|
||
|
break;
|
||
|
case 't':
|
||
|
timeout = atoi(optarg);
|
||
|
printf("timeout: %d*100ms.\r\n", timeout);
|
||
|
break;
|
||
|
case 'u':
|
||
|
strcpy(url_download, optarg);
|
||
|
printf("URL_downlaod: %s\r\n", url_download);
|
||
|
break;
|
||
|
case 'w':
|
||
|
strcpy(url_check, optarg);
|
||
|
printf("URL_check: %s\r\n", url_check);
|
||
|
break;
|
||
|
case 'h':
|
||
|
case '?':
|
||
|
ymodem_help();
|
||
|
return 0;
|
||
|
// break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if (optind < argc) {
|
||
|
printf("non-option ARGV-elements: ");
|
||
|
while (optind < argc)
|
||
|
printf("%s ", argv[optind++]);
|
||
|
printf("\n");
|
||
|
|
||
|
ymodem_help();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
while(1){
|
||
|
char local_SE_APP_version[50] = {0};
|
||
|
char download_SE_APP_version[50] = {0};
|
||
|
char download_SE_APP_url[255] = {0};
|
||
|
if(check_version(local_SE_APP_version,download_SE_APP_version,download_SE_APP_url,
|
||
|
sizeof(local_SE_APP_version),sizeof(download_SE_APP_version),sizeof(download_SE_APP_url))){
|
||
|
|
||
|
printf("_save_APP_path = %s\n",_save_APP_path);
|
||
|
//获取文件
|
||
|
int res = download_file(download_SE_APP_url, _save_APP_path);
|
||
|
if (res == -1) {
|
||
|
printf("download_file error.\n");
|
||
|
sleep(long_wait_time);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
strcpy(g_file_name, _save_APP_path);
|
||
|
is_send = 1;
|
||
|
|
||
|
// init serial
|
||
|
printf("open dev: %s\r\n", dev_path);
|
||
|
g_fd = open(dev_path, O_RDWR);
|
||
|
if (g_fd <= 0) {
|
||
|
printf("open %s failed!\r\n", dev_path);
|
||
|
sleep(long_wait_time);
|
||
|
continue;
|
||
|
}
|
||
|
serial_set(g_fd, BAUDRATE_DEF, 8, 'N', 1, timeout, 0); //1vtime = 100ms, 10=1000ms=1s
|
||
|
|
||
|
ymodem.putchar = _putchar;
|
||
|
ymodem.getchar = _getchar;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
if (putchar_flag) {
|
||
|
ymodem.putchar(putchar_value);
|
||
|
printf("putchar: %c/%d\r\n", putchar_value,putchar_value);
|
||
|
sleep(30);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (is_send) {
|
||
|
// system("pkill testprogram");
|
||
|
printf("等锁\n");
|
||
|
sem_wait(my_semaphore);
|
||
|
is_insem = 1;
|
||
|
printf("入锁\n");
|
||
|
sleep(1);
|
||
|
ymodem.begin_packet_cb = send_begin_packet_callback;
|
||
|
ymodem.data_packet_cb = send_data_packet_callback;
|
||
|
ymodem.end_packet_cb = send_end_packet_callback;
|
||
|
|
||
|
|
||
|
if (send_file(g_file_name) == 0) {
|
||
|
printf("Transfer complete!\r\n");
|
||
|
// int i = 0;
|
||
|
// do {
|
||
|
// res = get_result();
|
||
|
// i++;
|
||
|
// printf("res: %d i=%d\n",res,i);
|
||
|
// } while ((res != 0) && (i < 3));
|
||
|
sem_post(my_semaphore);
|
||
|
is_insem = 0;
|
||
|
printf("出锁\n");
|
||
|
// system("/demo/bin/testprogram &");
|
||
|
|
||
|
} else {
|
||
|
printf("Send Ymodem err!\r\n");
|
||
|
printf("stage: %d\r\n", ymodem.stage);
|
||
|
// int i = 0;
|
||
|
// do {
|
||
|
// res = get_result();
|
||
|
// i++;
|
||
|
// printf("res: %d i=%d\n",res,i);
|
||
|
// } while ((res != 0) && (i < 3));
|
||
|
sem_post(my_semaphore);
|
||
|
is_insem = 0;
|
||
|
printf("出锁\n");
|
||
|
// system("/demo/bin/testprogram &");
|
||
|
}
|
||
|
} else {
|
||
|
ymodem.begin_packet_cb = begin_packet_callback;
|
||
|
ymodem.data_packet_cb = data_packet_callback;
|
||
|
ymodem.end_packet_cb = end_packet_callback;
|
||
|
|
||
|
if (recevice() == 0) {
|
||
|
printf("Recevice complete!\r\n");
|
||
|
printf("file: %s, size: %d\r\n", ymodem.file_name, ymodem.file_size);
|
||
|
} else {
|
||
|
printf("Recevice Ymodem err!\r\n");
|
||
|
printf("stage: %d\r\n", ymodem.stage);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
close(g_fd);
|
||
|
sleep(long_wait_time);
|
||
|
continue;
|
||
|
|
||
|
}else{
|
||
|
sleep(long_wait_time);
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|