1039 lines
34 KiB
C
1039 lines
34 KiB
C
#include "system/includes.h"
|
||
#include "app_config.h"
|
||
#include "update/update.h"
|
||
#include "fs/fs.h"
|
||
#include "syscfg/syscfg_id.h"
|
||
#include "update/update_loader_download.h"
|
||
#include "generic/errno-base.h"
|
||
#include "lwip/ip4_addr.h"
|
||
#include "wifi/wifi_connect.h"
|
||
#include "lwip/tcp.h"
|
||
#include "lwip/sockets.h"
|
||
#include "lwip/inet.h"
|
||
#include "lwip/netdb.h"
|
||
|
||
void sdfile_save_test(char *buf, int len, char one_file, char close);
|
||
void sdfile_read(void *buf, int offset, int len);
|
||
//========================网络单备份系统升级例子================================
|
||
#if (CONFIG_DOUBLE_BANK_ENABLE == 0)
|
||
#if 0
|
||
enum {
|
||
SEEK_SET = 0x01,
|
||
SEEK_CUR = 0x02
|
||
};
|
||
#endif
|
||
|
||
#ifdef CONFIG_WIFI_STA_MODE
|
||
#define HTTP_UPDATE_ENABLE 1 //1,STA模式下http断点续传OTA升级
|
||
#else
|
||
#define HTTP_UPDATE_ENABLE 0
|
||
#endif
|
||
|
||
#if HTTP_UPDATE_ENABLE
|
||
#define HTTP_UPDATE_PORT 80 //http端口
|
||
#define HTTP_RECV_BUF (20*1024) //http升级缓存大小
|
||
|
||
//HTTP升级的OTA升级文件网址
|
||
/*#define HTTP_UPDATE_URL "http://test02.jieliapp.com/file/2022/update-ota.ufw"*/
|
||
#define HTTP_UPDATE_URL "http://172.16.109.110:18888/update-ota.ufw"
|
||
|
||
#define HTTP_GET_HEAD "GET %s HTTP/1.1\r\n"\
|
||
"Host: %s\r\n"\
|
||
"User-Agent: User\r\n"\
|
||
"Accept: */*\r\n"\
|
||
"Connection: Close\r\n"\
|
||
"Range: bytes=%d-%d\r\n\r\n"
|
||
struct http_tcp {
|
||
struct ip4_addr ip_addr;
|
||
struct tcp_pcb *pcb;
|
||
unsigned char conneted: 1;
|
||
unsigned char lock: 7;
|
||
};
|
||
struct http_range_ota {
|
||
struct http_tcp tcp;
|
||
unsigned int file_size;//文件大小
|
||
unsigned int content_length;
|
||
unsigned int range_start;//断点续传起始
|
||
unsigned int range_end;//断点续传结束
|
||
unsigned int recv_offset;
|
||
unsigned int read_offset;
|
||
unsigned char *host;
|
||
unsigned char *file;
|
||
unsigned char *send_buf;
|
||
unsigned int buf_size;
|
||
unsigned char buf[0];
|
||
};
|
||
static struct http_range_ota *http_ota = NULL;
|
||
#endif
|
||
|
||
//升级端口
|
||
#define NET_UPDATE_PORT 3335
|
||
|
||
|
||
//升级状态
|
||
#define NET_UPDATE_STATUS_DOING (0 << 0)//设备端主动发送
|
||
#define NET_UPDATE_STATUS_OK (1 << 0)//设备端主动发送
|
||
#define NET_UPDATE_STATUS_ERR (1 << 1)//设备端主动发送
|
||
#define NET_UPDATE_STATUS_READ (1 << 2)//设备端主动发送
|
||
#define NET_UPDATE_STATUS_STOP (1 << 3)//APP主动的停止升级
|
||
#define NET_UPDATE_STATUS_SAME (1 << 4)//升级的是同一个固件
|
||
|
||
#define NET_OTA_FILE_RESV 0 //文件夹预留读取:0文件往后读取, 1往前读取
|
||
|
||
static struct tcp_pcb *client_pcb = 0;
|
||
static char client_accept = 0;
|
||
static char net_ota_stop = 0;
|
||
static char net_recv_err = 0;
|
||
|
||
#define OS_SEM_TIME_MAX 500 //5s
|
||
static OS_SEM read_sem;
|
||
|
||
//协议保持和APP和ota_loard一致
|
||
//协议:头部20字节
|
||
struct net_ota {
|
||
unsigned int sum_check;//设备端:头部16字节和校验,APP端:头部16字节+读取字节的和校验,(sum_check不加上和校验计算)
|
||
unsigned int seek_addr;//文件偏移地址
|
||
unsigned int read_size;//读取文件长度
|
||
unsigned int all_size;//升级过程中需要的文件总字节数(用在进度条),整个升级过程中会有一次的all_size > 0, 其他次all_size = 0
|
||
unsigned int status: 8; //升级转态,NET_UPDATE_STATUS_NONE正在升级,NET_UPDATE_STATUS_OK升级成功,NET_UPDATE_STATUS_ERR升级失败
|
||
unsigned int download_percent: 8; //升级过程中设备的百分比
|
||
unsigned int resv: 16; //预留,最后收到这4个字节代表成功和失败
|
||
unsigned char buf[0];
|
||
};
|
||
struct net_local { //除了buf以外,其他成员保持和struct net_ota一致
|
||
unsigned int sum_check;
|
||
unsigned int seek_addr;
|
||
unsigned int read_size;
|
||
unsigned int all_size;
|
||
unsigned int status: 8; //预留,最后发送这4个字节代表成功和失败
|
||
unsigned int download_percent: 8; //升级过程中设备的百分比
|
||
unsigned int resv: 16; //预留,最后发送这4个字节代表成功和失败
|
||
unsigned char *buf;//存留升级fread的地址
|
||
};
|
||
|
||
static u8 *ota_ram_addr = NULL; //OTA缓存地址,长度42*1024,42K
|
||
static struct net_local *net_local_addr = NULL;
|
||
static u32 ota_loard_size = 0;//OTA升级需要字节大小
|
||
static u32 ota_read_size = 0;//OTA升级代码后已读取的字节大小
|
||
|
||
#define NET_OTA_BUF_SIZE (20*1024) //务必<=40K,和APP相关
|
||
#define RECV_OFFSET_SIZE (sizeof(struct net_local))
|
||
#define RECV_BUF_MAX_SIZE (NET_OTA_BUF_SIZE - sizeof(struct net_local) - sizeof(struct net_ota))
|
||
#define NET_MAX_SIZE (RECV_BUF_MAX_SIZE)
|
||
#define NET_TCP_OTA (ota_ram_addr + sizeof(struct net_local))
|
||
|
||
#define UPDATE_IDLE 0
|
||
#define UPDATE_ERROR 1
|
||
#define UPDATE_DOING 2
|
||
#define UPDATE_SUCCES 3
|
||
#define UPDATE_STOP 4
|
||
static u8 update_succes_state = 0;
|
||
|
||
static unsigned int sumget(void *buf, int len)//和校验生成
|
||
{
|
||
unsigned char *pbuf = (unsigned char *)buf;
|
||
unsigned int sum = 0;
|
||
int i = 0;
|
||
while (i < len) {
|
||
sum += pbuf[i++];
|
||
}
|
||
return sum;
|
||
}
|
||
static int sumcheck(void *buf, int len, unsigned int sum)//和校验检测
|
||
{
|
||
unsigned char *pbuf = (unsigned char *)buf;
|
||
unsigned int sum_check = 0;
|
||
int i = 0;
|
||
while (i < len) {
|
||
sum_check += pbuf[i++];
|
||
}
|
||
if (sum_check != sum) {
|
||
printf("err sumcheck = 0x%x, 0x%x\n", sum_check, sum);
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
static int send_msg(struct tcp_pcb *pcb, u8 *buf, u32 len)//往TCP发送数据包
|
||
{
|
||
err_t err;
|
||
int size = tcp_sndbuf(pcb);
|
||
if (size < len) {
|
||
printf("err tcp no buf to send , %d , %d\n", size, len);
|
||
return 0;
|
||
}
|
||
size = MIN(size, len);
|
||
err = tcp_write(pcb, buf, size, 1);//往TCP发送数据包
|
||
if (err != ERR_OK) {
|
||
puts("tcp_write err \n");
|
||
return 0;
|
||
}
|
||
return size;
|
||
}
|
||
int msgsenddata(u8 *buf, u32 len, u8 no_wait)//读取缓冲区的指定地址和长度
|
||
{
|
||
int err = 0;
|
||
struct net_local *net_local = (struct net_local *)(buf);
|
||
struct net_ota *net_ota = (struct net_ota *)(NET_TCP_OTA);
|
||
if (len > RECV_OFFSET_SIZE) {
|
||
return 0;
|
||
}
|
||
if (client_pcb) {
|
||
int tcp_size = RECV_BUF_MAX_SIZE;
|
||
u32 read_size = 0;
|
||
if (net_local_addr->status == NET_UPDATE_STATUS_READ) {
|
||
if (!net_local->all_size) {
|
||
if (!net_ota->seek_addr && !net_ota->read_size) {
|
||
net_ota->seek_addr = net_local->seek_addr;
|
||
}
|
||
if (!net_ota->read_size || net_local->seek_addr < net_ota->seek_addr ||
|
||
((net_local->seek_addr + net_local->read_size) > (net_ota->seek_addr + net_ota->read_size))) {//没有数据则请求tcp
|
||
net_ota->all_size = 0;
|
||
net_ota->read_size = tcp_size;
|
||
net_ota->seek_addr = net_local->seek_addr;
|
||
} else {//二级缓存有数据则复制即可
|
||
memcpy(net_local->buf, net_ota->buf + (net_local->seek_addr - net_ota->seek_addr), net_local->read_size);
|
||
return net_local->read_size;
|
||
}
|
||
#if NET_OTA_FILE_RESV
|
||
if (net_ota->seek_addr > (RECV_BUF_MAX_SIZE - net_local->read_size)) {
|
||
net_ota->seek_addr -= (RECV_BUF_MAX_SIZE - net_local->read_size);
|
||
}
|
||
#endif
|
||
} else {
|
||
net_ota->all_size = net_local->all_size;
|
||
}
|
||
} else {
|
||
read_size = net_ota->read_size;
|
||
net_ota->read_size = 0;
|
||
net_ota->all_size = net_local->all_size ? net_local->all_size : net_ota->all_size;
|
||
}
|
||
os_sem_set(&read_sem, 0);
|
||
net_ota->download_percent = net_local_addr->download_percent;
|
||
net_ota->status = net_local_addr->status;//发送结果
|
||
net_ota->sum_check = sumget((char *)net_ota + sizeof(net_ota->sum_check), sizeof(struct net_ota) - sizeof(net_ota->sum_check));
|
||
err = send_msg(client_pcb, (u8 *)net_ota, len);
|
||
if (read_size) {
|
||
net_ota->read_size = read_size;
|
||
}
|
||
if (no_wait) {
|
||
return err;
|
||
}
|
||
if (os_sem_pend(&read_sem, OS_SEM_TIME_MAX)) {
|
||
return 0;
|
||
}
|
||
}
|
||
return err;
|
||
}
|
||
static err_t msgsend_buf(void *arg, struct tcp_pcb *pcb)
|
||
{
|
||
return ERR_OK;
|
||
}
|
||
static void msgerr(void *arg, err_t err)
|
||
{
|
||
}
|
||
static err_t msgpoll(void *arg, struct tcp_pcb *pcb)
|
||
{
|
||
return msgsend_buf(arg, pcb);
|
||
}
|
||
static err_t msgsent(void *arg, struct tcp_pcb *pcb, u16_t len)
|
||
{
|
||
return msgsend_buf(arg, pcb);
|
||
}
|
||
static int msgclose(struct tcp_pcb *pcb)
|
||
{
|
||
if (pcb) {
|
||
if (client_accept > 0) {
|
||
client_accept--;
|
||
}
|
||
if (client_accept == 0 || client_pcb == pcb) {
|
||
client_pcb = NULL;
|
||
}
|
||
#if HTTP_UPDATE_ENABLE
|
||
http_ota->tcp.lock = 1;
|
||
#endif
|
||
tcp_arg(pcb, NULL);
|
||
tcp_sent(pcb, NULL);
|
||
tcp_recv(pcb, NULL);
|
||
tcp_err(pcb, NULL);
|
||
tcp_abort(pcb);//关闭tcp就发送RST复位断开tcp并释放tcp占用的内存池
|
||
/*tcp_close(pcb);*/
|
||
#if HTTP_UPDATE_ENABLE
|
||
if (http_ota && http_ota->tcp.pcb == pcb) {
|
||
http_ota->tcp.pcb = NULL;
|
||
http_ota->tcp.conneted = 0;
|
||
}
|
||
http_ota->tcp.lock = 0;
|
||
#endif
|
||
return ERR_ABRT;
|
||
}
|
||
return ERR_OK;
|
||
}
|
||
static err_t msgrecvmemcpy(void *arg, int len)
|
||
{
|
||
struct net_local *net_local = (struct net_local *)(ota_ram_addr);
|
||
struct net_ota *net_ota = (struct net_ota *)arg;
|
||
|
||
if (net_ota->status == NET_UPDATE_STATUS_STOP) {
|
||
net_local->status = net_ota->status;
|
||
net_ota_stop = 1;
|
||
} else if (net_local->read_size) {//复制当前请求的地址和大小到一级缓存
|
||
memcpy(net_local->buf, net_ota->buf + (net_local->seek_addr - net_ota->seek_addr), net_local->read_size);
|
||
}
|
||
os_sem_post(&read_sem);
|
||
return ERR_OK;
|
||
}
|
||
static err_t msgrecv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
||
{
|
||
#if HTTP_UPDATE_ENABLE
|
||
struct http_range_ota *httpota = (struct http_range_ota *)arg;
|
||
if (!httpota) {
|
||
return ERR_OK;
|
||
}
|
||
if (err == ERR_OK && p != NULL) {
|
||
struct pbuf *q;
|
||
char Find = 0;
|
||
int tot_len = 0;
|
||
char *pt = (char *)httpota->buf + httpota->recv_offset;
|
||
int len = p->tot_len;
|
||
if ((httpota->recv_offset + len) <= httpota->buf_size) {
|
||
for (q = p; q != NULL; q = q->next) {
|
||
memcpy(pt, q->payload, q->len);
|
||
pt += q->len;
|
||
tot_len += q->len;
|
||
}
|
||
tcp_recved(pcb, tot_len);
|
||
/*printf("recv size : %d \n%s\n", tot_len, httpota->buf + httpota->recv_offset);*/
|
||
if (!httpota->recv_offset) {
|
||
char *p, *f, *c;
|
||
p = (char *)httpota->buf + httpota->recv_offset;
|
||
f = strstr(p, "HTTP/1.1 206");
|
||
/*sdfile_save_test(p, tot_len, 0, 1);*/
|
||
if (f) {
|
||
net_recv_err = 0;
|
||
c = strstr(f, "Content-Length:");
|
||
if (!c) {
|
||
c = strstr(f, "content-length:");
|
||
}
|
||
if (c) {
|
||
c += strlen("Content-Length:");
|
||
httpota->content_length = atoi(c);
|
||
}
|
||
c = strstr(f, "Content-Range:");
|
||
if (!c) {
|
||
c = strstr(f, "content-range:");
|
||
}
|
||
if (c) {
|
||
c += strlen("Content-Range:") + 1;
|
||
f = c;
|
||
while (c < (p + tot_len)) {
|
||
if (c[0] == '\r' && c[1] == '\n' && c[2] == '\r' && c[3] == '\n') {
|
||
c += 4;
|
||
Find = 1;
|
||
goto find;
|
||
}
|
||
if (c[0] == '\r' && c[1] == '\n') {
|
||
c += 2;
|
||
break;
|
||
}
|
||
if (c[0] == '/') {
|
||
httpota->file_size = atoi(++c);
|
||
/*printf("---> http ota file_size = %d \n", httpota->file_size);*/
|
||
}
|
||
c++;
|
||
}
|
||
f = strstr(f, "/");
|
||
if (f && f < c && !httpota->file_size) {
|
||
f += 1;
|
||
httpota->file_size = atoi(f);
|
||
/*printf("---> http ota file_size = %d \n",httpota->file_size);*/
|
||
}
|
||
} else {
|
||
c = f;
|
||
}
|
||
while (c < (p + tot_len)) {
|
||
if (c[0] == '\r' && c[1] == '\n' && c[2] == '\r' && c[3] == '\n') {
|
||
Find = 1;
|
||
c += 4;
|
||
break;
|
||
}
|
||
c++;
|
||
}
|
||
find:
|
||
if (Find) {
|
||
len = tot_len - (c - p);
|
||
memcpy(httpota->buf, c, len);
|
||
httpota->buf[len] = 0;
|
||
httpota->recv_offset += len;
|
||
} else {
|
||
printf("recv head data err\n");
|
||
goto err;
|
||
}
|
||
} else {
|
||
err:
|
||
printf("recv err \n");
|
||
net_recv_err++;
|
||
if (net_recv_err >= 3) {
|
||
net_recv_err = 0;
|
||
net_ota_stop = 1;
|
||
httpota->recv_offset = 0;
|
||
}
|
||
os_sem_post(&read_sem);
|
||
}
|
||
} else {
|
||
httpota->recv_offset += tot_len;
|
||
}
|
||
} else {
|
||
tcp_recved(pcb, p->tot_len);
|
||
}
|
||
pbuf_free(p);
|
||
/*printf("recv size : %d, request : %d \n", httpota->recv_offset, httpota->range_end - httpota->range_start);*/
|
||
//接收数据>=所请求字节,则接收数据完成
|
||
if (httpota->recv_offset && (httpota->recv_offset >= (httpota->range_end - httpota->range_start) || (http_ota->recv_offset >= http_ota->file_size && http_ota->file_size))) {
|
||
/*printf("---> recv size : %d, request : %d \n", httpota->recv_offset, httpota->range_end - httpota->range_start);*/
|
||
|
||
if (net_local_addr->buf && net_local_addr->read_size) {//复制到二级缓存20K里
|
||
memcpy(net_local_addr->buf, httpota->buf + (net_local_addr->seek_addr - httpota->range_start), net_local_addr->read_size);
|
||
}
|
||
os_sem_post(&read_sem);
|
||
}
|
||
}
|
||
#else
|
||
struct net_ota *net_ota = (struct net_ota *)arg;
|
||
if (!net_ota || !ota_ram_addr) {
|
||
return ERR_OK;
|
||
}
|
||
if (err == ERR_OK && p != NULL) {
|
||
struct pbuf *q;
|
||
char First = 0;
|
||
int tot_len = 0;
|
||
char *pt = (char *)net_ota + net_ota->all_size;
|
||
for (q = p; q != NULL; q = q->next) {
|
||
memcpy(pt, q->payload, q->len);
|
||
pt += q->len;
|
||
tot_len += q->len;
|
||
}
|
||
/*tcp_recved(pcb, p->tot_len);*/
|
||
tcp_recved(pcb, tot_len);
|
||
pbuf_free(p);
|
||
net_ota->all_size += tot_len;
|
||
if (net_ota->all_size >= (net_ota->read_size + sizeof(struct net_ota))) {//接收数据>=所请求字节,则接收数据完成
|
||
net_ota->all_size = 0;
|
||
//和校验检测,检测过才能复制到二级20K缓存
|
||
if (sumcheck((char *)net_ota + sizeof(net_ota->sum_check), net_ota->read_size + sizeof(struct net_ota) - sizeof(net_ota->sum_check), net_ota->sum_check)) {
|
||
} else { //和校验成功
|
||
msgrecvmemcpy(net_ota, tot_len);
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
else if (err == ERR_OK && p == NULL) {
|
||
puts("msgrecv close tcp\n");
|
||
return msgclose(pcb);
|
||
}
|
||
return ERR_OK;
|
||
}
|
||
static err_t msgaccept(void *arg, struct tcp_pcb *pcb, err_t err)
|
||
{
|
||
client_accept++;
|
||
if (client_accept > 1) {
|
||
printf("client_accept = %d \n", client_accept);
|
||
return msgclose(pcb);
|
||
} else {
|
||
client_pcb = pcb;
|
||
tcp_arg(pcb, NET_TCP_OTA);
|
||
tcp_recv(pcb, msgrecv);
|
||
tcp_sent(pcb, msgsent);
|
||
tcp_err(pcb, msgerr);
|
||
tcp_poll(pcb, msgpoll, 1);
|
||
int net_ota_single_back_update(void);//100ms后初始化单备份升级
|
||
sys_timeout_add_to_task("sys_timer", NULL, net_ota_single_back_update, 100);
|
||
puts("client accept ok\n");
|
||
}
|
||
return ERR_OK;
|
||
}
|
||
#if HTTP_UPDATE_ENABLE
|
||
static err_t tcp_dataconnected(void *arg, struct tcp_pcb *pcb, err_t err)
|
||
{
|
||
struct http_range_ota *httpota = (struct http_range_ota *)arg;
|
||
tcp_recv(pcb, msgrecv);
|
||
tcp_sent(pcb, msgsent);
|
||
tcp_err(pcb, msgerr);
|
||
httpota->tcp.conneted = 1;
|
||
puts("connet server ok\n");
|
||
return ERR_OK;
|
||
}
|
||
static int http_get(const char *url, char reset, int size)
|
||
{
|
||
int port = 0;
|
||
if (!url || !http_ota) {
|
||
goto exit;
|
||
}
|
||
char *p = strstr(url, "http://");
|
||
if (!p) {
|
||
goto exit;
|
||
}
|
||
p += strlen("http://");
|
||
char *e = strstr(p, ":");
|
||
int len = 0;
|
||
if (e) {
|
||
len = e - p;
|
||
if (len >= http_ota->buf_size) {
|
||
goto exit;
|
||
}
|
||
e++;
|
||
port = atoi(e);
|
||
e = strstr(p, "/");
|
||
} else {
|
||
e = strstr(p, "/");
|
||
if (e) {
|
||
len = e - p;
|
||
if (len >= http_ota->buf_size) {
|
||
goto exit;
|
||
}
|
||
} else {
|
||
http_ota->host = NULL;
|
||
http_ota->file = NULL;
|
||
http_ota->send_buf = NULL;
|
||
http_ota->recv_offset = 0;
|
||
http_ota->file_size = 0;
|
||
goto exit;
|
||
}
|
||
}
|
||
http_ota->host = http_ota->buf;
|
||
memcpy(http_ota->host, p, len);
|
||
http_ota->host[len] = 0;
|
||
http_ota->send_buf = http_ota->host + len + 1;
|
||
http_ota->file = NULL;
|
||
http_ota->recv_offset = 0;
|
||
if ((strlen(e) + len + 2) < http_ota->buf_size) {
|
||
http_ota->file = http_ota->host + len + 1;
|
||
len = strlen(e);
|
||
memcpy(http_ota->file, e, len);
|
||
http_ota->file[len] = 0;
|
||
http_ota->send_buf = http_ota->file + len + 1;
|
||
}
|
||
if (!http_ota->tcp.ip_addr.addr || reset) {
|
||
if (!atoi(http_ota->host)) {
|
||
printf("http gethostbyname\n");
|
||
struct hostent *host_ent = gethostbyname(http_ota->host);//域名解析
|
||
if (!host_ent) {
|
||
printf(" . ! lwip analayse ip err !!!\r\n");
|
||
goto exit;
|
||
}
|
||
http_ota->tcp.ip_addr.addr = *((u32_t *)host_ent->h_addr);
|
||
} else {
|
||
http_ota->tcp.ip_addr.addr = inet_addr(http_ota->host);
|
||
}
|
||
printf("http update DNS remoute ip : %s \n", inet_ntoa(http_ota->tcp.ip_addr.addr));
|
||
http_ota->file_size = 0;
|
||
}
|
||
while (http_ota->tcp.lock) {
|
||
os_time_dly(1);
|
||
}
|
||
http_ota->tcp.lock = 1;
|
||
struct tcp_pcb *pcb = tcp_new();
|
||
if (!pcb) {
|
||
goto exit;
|
||
}
|
||
ip_addr_t ip;
|
||
tcp_arg(pcb, http_ota);
|
||
IP_SET_TYPE_VAL(ip, IPADDR_TYPE_V4);
|
||
ip4_addr_copy(*ip_2_ip4(&ip), http_ota->tcp.ip_addr);
|
||
http_ota->tcp.pcb = pcb;
|
||
port = port ? port : HTTP_UPDATE_PORT;
|
||
if (tcp_connect(pcb, &ip, port, tcp_dataconnected) != ERR_OK) {
|
||
tcp_connect(pcb, &ip, 8080, tcp_dataconnected);
|
||
}
|
||
int cnt = 10 * 100;
|
||
while (!http_ota->tcp.conneted && --cnt) {
|
||
os_time_dly(10);
|
||
}
|
||
if (!cnt || net_ota_stop) {
|
||
tcp_arg(pcb, NULL);
|
||
tcp_sent(pcb, NULL);
|
||
tcp_recv(pcb, NULL);
|
||
tcp_err(pcb, NULL);
|
||
tcp_close(pcb);
|
||
http_ota->tcp.pcb = NULL;
|
||
http_ota->tcp.ip_addr.addr = 0;
|
||
goto exit;
|
||
}
|
||
size = size ? size : http_ota->buf_size;
|
||
if (http_ota->file_size && (http_ota->range_start + http_ota->buf_size) > http_ota->file_size) {
|
||
size = http_ota->file_size - http_ota->range_start;
|
||
}
|
||
http_ota->range_end = http_ota->range_start + size;
|
||
if (http_ota->send_buf) {
|
||
if (!http_ota->file) {
|
||
http_ota->file = "/";
|
||
}
|
||
sprintf(http_ota->send_buf, HTTP_GET_HEAD, http_ota->file, http_ota->host, http_ota->range_start, http_ota->range_end - 1);
|
||
/*printf("HTTP_GET_HEAD : \n%s\n", http_ota->send_buf);*/
|
||
len = strlen(http_ota->send_buf);
|
||
if (send_msg(pcb, http_ota->send_buf, len) != len) {//发送http数据头
|
||
goto exit;
|
||
}
|
||
}
|
||
http_ota->tcp.lock = 0;
|
||
return 0;
|
||
|
||
exit:
|
||
http_ota->tcp.lock = 0;
|
||
puts("http update err !!! \n");
|
||
return -EINVAL;
|
||
}
|
||
static int http_read(void *priv, char reset)
|
||
{
|
||
struct net_local *net_local = (struct net_local *)priv;
|
||
if (!http_ota || !net_local) {
|
||
return 0;
|
||
}
|
||
if (!http_ota->range_start && !http_ota->recv_offset) {
|
||
http_ota->range_start = net_local->seek_addr;
|
||
}
|
||
if (!http_ota->recv_offset || net_local->seek_addr < http_ota->range_start ||
|
||
((net_local->seek_addr + net_local->read_size) > (http_ota->range_start + http_ota->recv_offset))) {//没有数据或第一次则请求tcp
|
||
http_ota->recv_offset = 0;
|
||
http_ota->range_start = net_local->seek_addr;
|
||
} else {//二级缓存有数据则复制即可
|
||
memcpy(net_local->buf, http_ota->buf + (net_local->seek_addr - http_ota->range_start), net_local->read_size);
|
||
return net_local->read_size;
|
||
}
|
||
#if NET_OTA_FILE_RESV
|
||
if (http_ota->range_start > (http_ota->buf_size - net_local->read_size)) {
|
||
http_ota->range_start -= (http_ota->buf_size - net_local->read_size);
|
||
}
|
||
#endif
|
||
u8 cnt = 3;
|
||
redo:
|
||
os_sem_set(&read_sem, 0);
|
||
if (http_get(HTTP_UPDATE_URL, reset, 0)) {
|
||
return 0;
|
||
}
|
||
if (os_sem_pend(&read_sem, OS_SEM_TIME_MAX)) {
|
||
return 0;
|
||
}
|
||
if (net_recv_err && --cnt && !net_ota_stop) {
|
||
goto redo;
|
||
}
|
||
return net_local->read_size ? net_local->read_size : http_ota->buf_size;
|
||
}
|
||
static int http_stop(int err)
|
||
{
|
||
if (http_ota) {
|
||
http_ota->tcp.lock = 1;
|
||
if (http_ota->tcp.pcb) {
|
||
tcp_arg(http_ota->tcp.pcb, NULL);
|
||
tcp_sent(http_ota->tcp.pcb, NULL);
|
||
tcp_recv(http_ota->tcp.pcb, NULL);
|
||
tcp_err(http_ota->tcp.pcb, NULL);
|
||
tcp_close(http_ota->tcp.pcb);
|
||
}
|
||
http_ota->tcp.lock = 0;
|
||
http_ota->tcp.pcb = NULL;
|
||
http_ota->tcp.ip_addr.addr = 0;
|
||
http_ota->tcp.conneted = 0;
|
||
memset(http_ota->buf, 0, http_ota->buf_size);
|
||
memset(http_ota, 0, sizeof(struct http_range_ota));
|
||
}
|
||
return 0;
|
||
}
|
||
#endif
|
||
int net_ota_single_back_init(void)
|
||
{
|
||
#if HTTP_UPDATE_ENABLE
|
||
int size = HTTP_RECV_BUF;
|
||
if (!http_ota) {
|
||
http_ota = malloc(size);
|
||
}
|
||
if (http_ota) {
|
||
memset(http_ota, 0, size);
|
||
http_ota->buf_size = size - sizeof(struct http_range_ota);
|
||
puts("http update init ok \n");
|
||
} else {
|
||
return -1;
|
||
}
|
||
os_sem_create(&read_sem, 0);
|
||
syscfg_write(VM_HTTP_SINGLE_UPDATE_URL, (char *)HTTP_UPDATE_URL, strlen(HTTP_UPDATE_URL) + 1);
|
||
printf("---> HTTP_UPDATE_URL = %s \n", HTTP_UPDATE_URL);
|
||
#else
|
||
int err = 0;
|
||
int cnt = 0;
|
||
if (ota_ram_addr) {
|
||
printf("net_ota_single_back_init already\n");
|
||
return 0;
|
||
}
|
||
if (!ota_ram_addr) {
|
||
ota_ram_addr = malloc(NET_OTA_BUF_SIZE);
|
||
if (!ota_ram_addr) {
|
||
printf("net_ota_single_back_init err , no mem\n");
|
||
return -1;
|
||
}
|
||
}
|
||
memset(ota_ram_addr, 0, NET_OTA_BUF_SIZE);
|
||
struct tcp_pcb *pcb = tcp_new();
|
||
if (!pcb) {
|
||
printf("tcp_new err\n");
|
||
return -1;
|
||
}
|
||
tcp_bind(pcb, IP_ADDR_ANY, NET_UPDATE_PORT);
|
||
pcb = tcp_listen(pcb);
|
||
if (!pcb) {
|
||
tcp_close(pcb);
|
||
printf("tcp_new err\n");
|
||
return -1;
|
||
}
|
||
tcp_accept(pcb, msgaccept);
|
||
os_sem_create(&read_sem, 0);
|
||
puts("net_ota_open, wait APP accept .....\n");
|
||
#endif
|
||
return 0;
|
||
}
|
||
static u16 net_ota_single_back_fs_open(void)
|
||
{
|
||
#if HTTP_UPDATE_ENABLE
|
||
int size = HTTP_RECV_BUF;
|
||
if (!net_local_addr) {
|
||
net_local_addr = malloc(sizeof(struct net_local));
|
||
if (!net_local_addr) {
|
||
return false;
|
||
}
|
||
}
|
||
if (!http_ota) {
|
||
http_ota = malloc(size);
|
||
if (!http_ota) {
|
||
return false;
|
||
}
|
||
}
|
||
memset(http_ota, 0, size);
|
||
memset(net_local_addr, 0, sizeof(struct net_local));
|
||
http_ota->buf_size = size - sizeof(struct http_range_ota);
|
||
net_local_addr->download_percent = 1;
|
||
net_ota_stop = 0;
|
||
if (!http_read((void *)net_local_addr, 1)) {
|
||
puts("net_f_open err\n");
|
||
return false;
|
||
}
|
||
#else
|
||
int cnt = 500;//5秒
|
||
if (!ota_ram_addr) {
|
||
return false;
|
||
}
|
||
while (!client_pcb && --cnt) {
|
||
os_time_dly(10);
|
||
}
|
||
if (!cnt) { //等待APP连接超时
|
||
return false;
|
||
}
|
||
os_sem_set(&read_sem, 0);
|
||
//清空数据
|
||
net_local_addr = (struct net_local *)ota_ram_addr;
|
||
struct net_ota *net_ota = (struct net_ota *)(NET_TCP_OTA);
|
||
memset(net_ota, 0, sizeof(struct net_ota));
|
||
memset(net_local_addr, 0, sizeof(struct net_local));
|
||
net_ota_stop = 0;
|
||
net_local_addr->download_percent = 1;
|
||
#endif
|
||
printf("net_ota open ok\n");
|
||
return true;
|
||
}
|
||
|
||
static int net_ota_single_back_fs_seek(void *fp, u8 type, u32 offset)
|
||
{
|
||
#if HTTP_UPDATE_ENABLE
|
||
if (!net_local_addr) {
|
||
return -1;
|
||
}
|
||
#else
|
||
if (!net_local_addr || !ota_ram_addr) {
|
||
return (int) - 1;
|
||
}
|
||
if (net_local_addr->status == NET_UPDATE_STATUS_STOP || net_ota_stop) {
|
||
return 0;
|
||
}
|
||
#endif
|
||
if (type == SEEK_SET) {
|
||
net_local_addr->seek_addr = offset;
|
||
} else {
|
||
net_local_addr->seek_addr += offset;
|
||
}
|
||
//printf("---> seek_addr = 0x%X \n",net_local_addr->seek_addr);
|
||
return 0;
|
||
}
|
||
|
||
static int net_ota_single_back_fs_need_size(void *p, u32 len)//第一次发送本次升级的总字节
|
||
{
|
||
#if HTTP_UPDATE_ENABLE
|
||
if (!net_local_addr || net_ota_stop || !len) {
|
||
return -1;
|
||
}
|
||
net_local_addr->all_size = len;
|
||
ota_loard_size = len ? len : 0;
|
||
ota_read_size = 0;
|
||
#else
|
||
if (net_local_addr->status == NET_UPDATE_STATUS_STOP || net_ota_stop || !len) {
|
||
return -1;
|
||
}
|
||
net_local_addr->seek_addr = 0;
|
||
net_local_addr->read_size = 0;
|
||
net_local_addr->all_size = len;
|
||
net_local_addr->status = len ? 0 : NET_UPDATE_STATUS_SAME;
|
||
net_local_addr->resv = 0;
|
||
ota_loard_size = len ? len : 0;
|
||
ota_read_size = 0;
|
||
msgsenddata(net_local_addr, sizeof(struct net_ota), 0);
|
||
#endif
|
||
return 0;
|
||
}
|
||
static u16 net_ota_single_back_fs_read(void *fp, u8 *buff, u16 len)
|
||
{
|
||
int err;
|
||
#if HTTP_UPDATE_ENABLE
|
||
int cnt = 3;
|
||
if (!net_local_addr || net_ota_stop) {
|
||
printf("err ota read\n");
|
||
return 0;
|
||
}
|
||
if (ota_loard_size) {
|
||
u8 percent = (unsigned long long)ota_read_size * 100 / ota_loard_size;
|
||
u8 last_percent = net_local_addr->download_percent;
|
||
net_local_addr->download_percent = percent > net_local_addr->download_percent ? percent : net_local_addr->download_percent;
|
||
net_local_addr->download_percent = net_local_addr->download_percent < 100 ? net_local_addr->download_percent : 99;
|
||
if (net_local_addr->download_percent != last_percent) {
|
||
/*printf("update >> %d%%\n", net_local_addr->download_percent);*/
|
||
}
|
||
}
|
||
net_local_addr->read_size = len;
|
||
net_local_addr->resv = 0;
|
||
net_local_addr->buf = buff;
|
||
/*os_sem_set(&read_sem, 0);*/
|
||
/*printf("---> read = %d, seek = %d \n", len, net_local_addr->seek_addr);*/
|
||
redo:
|
||
cnt--;
|
||
if (!http_read((void *)net_local_addr, 0)) {
|
||
if (cnt) {
|
||
goto redo;
|
||
}
|
||
puts("http_read err\n");
|
||
return 0;
|
||
}
|
||
#else
|
||
if (!net_local_addr || !ota_ram_addr) {
|
||
printf("err ota read\n");
|
||
return 0;
|
||
}
|
||
if (len > NET_MAX_SIZE) {
|
||
printf("err ota read size\n");
|
||
return 0;
|
||
}
|
||
net_local_addr->read_size = len;
|
||
net_local_addr->status = NET_UPDATE_STATUS_READ;
|
||
net_local_addr->resv = 0;
|
||
net_local_addr->buf = buff;
|
||
net_local_addr->all_size = 0;
|
||
if (ota_loard_size) {
|
||
u8 percent = (unsigned long long)ota_read_size * 100 / ota_loard_size;
|
||
net_local_addr->download_percent = percent > net_local_addr->download_percent ? percent : net_local_addr->download_percent;
|
||
net_local_addr->download_percent = net_local_addr->download_percent < 100 ? net_local_addr->download_percent : 99;
|
||
}
|
||
if (net_local_addr->status == NET_UPDATE_STATUS_STOP || net_ota_stop) {
|
||
printf("err ota read net_ota_stop\n");
|
||
return 0;
|
||
}
|
||
if (!msgsenddata(net_local_addr, sizeof(struct net_ota), 0)) {
|
||
puts("net_f_read err\n");
|
||
}
|
||
|
||
if (net_local_addr->status == NET_UPDATE_STATUS_STOP || net_ota_stop) {
|
||
printf("err ota read net_ota_stop\n");
|
||
return 0;
|
||
}
|
||
#endif
|
||
net_local_addr->seek_addr += net_local_addr->read_size;
|
||
if (ota_loard_size) {
|
||
ota_read_size += net_local_addr->read_size;
|
||
}
|
||
return net_local_addr->read_size;
|
||
}
|
||
static u16 net_ota_single_back_fs_stop(u8 err)
|
||
{
|
||
u8 same = err & ~UPDATE_RESULT_FLAG_BITMAP;
|
||
switch (same) {
|
||
case UPDATE_RESULT_UPDATE_FILE_SAME:
|
||
update_succes_state = UPDATE_STOP;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
#if HTTP_UPDATE_ENABLE
|
||
if (!net_local_addr) {
|
||
return -1;
|
||
}
|
||
http_stop(err);
|
||
memset(net_local_addr, 0, sizeof(struct net_local));
|
||
#else
|
||
if (!net_local_addr || !ota_ram_addr) {
|
||
return (int) - 1;
|
||
}
|
||
memset(net_local_addr, 0, sizeof(struct net_local));
|
||
if (client_pcb) {
|
||
net_local_addr->read_size = 0;
|
||
if (!err) { //先发送100%
|
||
net_local_addr->status = 0;//发送结果
|
||
if (ota_loard_size) {
|
||
net_local_addr->download_percent = 100;
|
||
}
|
||
msgsenddata(net_local_addr, sizeof(struct net_ota), 0);
|
||
os_time_dly(50);
|
||
}
|
||
net_local_addr->status = err ? NET_UPDATE_STATUS_ERR : NET_UPDATE_STATUS_OK;//发送结果
|
||
msgsenddata(net_local_addr, sizeof(struct net_ota), 1);
|
||
net_local_addr->status = 0;
|
||
net_local_addr->download_percent = 0;
|
||
}
|
||
os_time_dly(50);
|
||
net_local_addr = NULL;
|
||
if (client_pcb) {
|
||
puts("client_pcb close\n");
|
||
msgclose(client_pcb);
|
||
}
|
||
//清空数据
|
||
struct net_ota *net_ota = (struct net_ota *)(NET_TCP_OTA);
|
||
memset(net_ota, 0, sizeof(struct net_ota));
|
||
#endif
|
||
net_ota_stop = 0;
|
||
ota_loard_size = 0;
|
||
ota_read_size = 0;
|
||
puts("net_ota_fs_stop ok\n");
|
||
return true;
|
||
}
|
||
static const update_op_api_t net_ota_single_back_fs_update_opt = {
|
||
.f_open = net_ota_single_back_fs_open,
|
||
.f_read = net_ota_single_back_fs_read,
|
||
.f_seek = net_ota_single_back_fs_seek,
|
||
.f_stop = net_ota_single_back_fs_stop,
|
||
.notify_update_content_size = net_ota_single_back_fs_need_size,
|
||
};
|
||
|
||
//单备份升级
|
||
static void net_ota_single_back_fs_update_param_private_handle(UPDATA_PARM *p)
|
||
{
|
||
}
|
||
static void net_ota_single_back_fs_update_state_cbk(int type, u32 state, void *priv)
|
||
{
|
||
update_ret_code_t *ret_code = (update_ret_code_t *)priv;
|
||
switch (state) {
|
||
case UPDATE_CH_EXIT:
|
||
if ((0 == ret_code->stu) && (0 == ret_code->err_code)) {
|
||
update_succes_state = UPDATE_SUCCES;
|
||
UPDATA_PARM *update_ram = UPDATA_FLAG_ADDR;
|
||
memset(update_ram, 0, 32);
|
||
UPDATA_PARM *p = UPDATA_FLAG_ADDR + sizeof(UPDATA_PARM);
|
||
if (support_dual_bank_update_en) {
|
||
memset(update_ram, 0, sizeof(UPDATA_PARM));
|
||
update_ram->magic = type;
|
||
update_result_set(UPDATA_SUCC);
|
||
printf(">>>>>>>>>>>>>>>>>>update ok , cpu reset ...\n");
|
||
} else {
|
||
//单备份
|
||
update_mode_api_v2(type, net_ota_single_back_fs_update_param_private_handle, NULL);
|
||
}
|
||
#if HTTP_UPDATE_ENABLE
|
||
wifi_enter_sta_mode("#@!$%^&*()##$$", "#@!$%^&*()##$$");
|
||
os_time_dly(200);
|
||
#else
|
||
void wifi_all_sta_discon(void);
|
||
wifi_all_sta_discon();//断开所有连接STA
|
||
os_time_dly(200);
|
||
#endif
|
||
system_reset();
|
||
} else {
|
||
if (update_succes_state == UPDATE_DOING) {
|
||
update_succes_state = UPDATE_ERROR;
|
||
}
|
||
update_result_set(UPDATA_DEV_ERR);
|
||
printf("\nupdate err !!! \n");
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
#if HTTP_UPDATE_ENABLE
|
||
int net_ota_single_back_update(void);
|
||
int net_ota_single_back_update_state(void)
|
||
{
|
||
static u8 update_retry_cnt = 0;//升级失败尝试次数
|
||
switch (update_succes_state) {
|
||
case UPDATE_ERROR:
|
||
if (++update_retry_cnt < 6) {
|
||
sys_timeout_add(NULL, net_ota_single_back_update, 500);
|
||
} else {
|
||
update_retry_cnt = 0;
|
||
}
|
||
break;
|
||
case UPDATE_SUCCES:
|
||
case UPDATE_STOP:
|
||
update_retry_cnt = 0;
|
||
break;
|
||
default:
|
||
sys_timeout_add(NULL, net_ota_single_back_update_state, 500);
|
||
break;
|
||
}
|
||
return (int)update_succes_state;
|
||
}
|
||
#endif
|
||
|
||
//单备份网络升级例子
|
||
int net_ota_single_back_update(void)
|
||
{
|
||
printf("\n>>>>>>>>>>>>net_ota_single_back_update\n");
|
||
#if HTTP_UPDATE_ENABLE
|
||
if (net_ota_single_back_init()) {//http下先初始化
|
||
return -1;
|
||
}
|
||
sys_timeout_add(NULL, net_ota_single_back_update_state, 500);
|
||
#endif
|
||
update_mode_info_t info = {
|
||
.type = NET_UFW_UPDATA,
|
||
.state_cbk = net_ota_single_back_fs_update_state_cbk,
|
||
.p_op_api = &net_ota_single_back_fs_update_opt,
|
||
.task_en = 1,
|
||
};
|
||
update_succes_state = UPDATE_DOING;
|
||
app_active_update_task_init(&info);
|
||
return 0;
|
||
}
|
||
#endif
|
||
|
||
//===============sta模式下的http单备份升级例子===========================//
|
||
static void net_single_http_update_doing(void)
|
||
{
|
||
#if HTTP_UPDATE_ENABLE
|
||
int state = wifi_get_sta_connect_state();
|
||
switch (state) {
|
||
case WIFI_STA_NETWORK_STACK_DHCP_SUCC:
|
||
net_ota_single_back_update();//获取IP后启动单备份升级流程
|
||
return;
|
||
case WIFI_STA_CONNECT_TIMEOUT_NOT_FOUND_SSID:
|
||
puts("NOT_FOUND_SSID\n");
|
||
break;
|
||
case WIFI_STA_CONNECT_ASSOCIAT_TIMEOUT:
|
||
puts("CONNECT_ASSOCIAT_TIMEOUT\n");
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
sys_timeout_add(NULL, net_single_http_update_doing, 500);//定时500ms检测是否连上网络
|
||
#endif
|
||
}
|
||
//应用层调用函数例子
|
||
void net_single_http_update_test(void)
|
||
{
|
||
#if HTTP_UPDATE_ENABLE
|
||
sys_timeout_add(NULL, net_single_http_update_doing, 500);//定时500ms检测是否连上网络
|
||
#endif
|
||
}
|
||
|
||
|
||
|
||
|