Files
kunlun/app/grapp/iot_gr_upgrade.c
2024-09-28 14:24:04 +08:00

930 lines
36 KiB
C
Executable File

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
/* os_ship header files */
#include "os_task_api.h"
#include "os_timer_api.h"
#include "os_utils_api.h"
/* iot common header files */
#include "iot_app_api.h"
#include "iot_io_api.h"
#include "iot_task_api.h"
#include "iot_upgrade_api.h"
#include "iot_cli_upgrade_api.h"
#include "iot_grapp.h"
#include "iot_plctxrx.h"
#include "iot_proto_common.h"
#include "iot_gr_upgrade.h"
#if PLC_SUPPORT_CCO_ROLE && IOT_GR_APP_ENABLE && ENABLE_GREE_UPGRADE
extern prototask_contxt_t prototask_contxt;
/** define cco local upgrade info */
gree_cco_upgrade_info_t cco_upgrade_info;
/** define all sta upgrade info */
gree_sta_upgrade_info_t sta_upgrade_info[STA_DEV_MAX];
/* INVALID_MACADDR and MAC_ALL_STA now used by upgrade, modified later */
const uint8_t INVALID_MACADDR[UPGRADE_MAC_BYTE] = {0x00};
const uint8_t MAC_ALL_STA[UPGRADE_MAC_BYTE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static void iot_proto_upgrade_data(uint8_t *data, uint16_t len);
static void iot_proto_upgrade_query_status(uint8_t *data, uint16_t len);
static void iot_proto_upgrade_stop(uint8_t *data, uint16_t len);
static void iot_proto_upgrade_start_node(uint8_t *data, uint16_t len);
static bool_t iot_proto_upgrade_file_check();
static void iot_proto_upgrade_complete_ind();
static void iot_proto_upgrade_data_ack(uint8_t seq, uint16_t index,
uint8_t result);
static void iot_upgrade_id_init(void);
static proto_upgrade_fnhdl_tbl_t proto_upgrade_subfnhdl_tbl[] = {
{ PROTO_UPGRADE_DATA, iot_proto_upgrade_data},
{ PROTO_UPGRADE_QUERY_STATUS, iot_proto_upgrade_query_status},
{ PROTO_UPGRADE_STOP, iot_proto_upgrade_stop},
{ PROTO_UPGRADE_START_NODE, iot_proto_upgrade_start_node},
};
/* send upgrade sta result to mcu */
static void iot_proto_upgrade_completed_handler()
{
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_COMPLETE;
if (IOT_GREE_UPGRADE_LOCAL == cco_upgrade_info.upgrade_type) {
cco_upgrade_info.data_progress = GREE_CCO_UPGRADE_SUCC_PROGRESS;
iot_proto_upgrade_complete_ind();
} else if (cco_upgrade_info.sta_upgrade_prg ==
GREE_CCO_UPGRADE_SUCC_PROGRESS) {
/* remote upgrade successful need check all stations progress */
iot_proto_upgrade_complete_ind();
if (os_is_timer_active(prototask_contxt.upgrade_tmr)) {
os_stop_timer(prototask_contxt.upgrade_tmr);
}
}
}
/* initial the upgrade_id */
static void iot_upgrade_id_init(void)
{
if (cco_upgrade_info.upgrade_id == 0) {
cco_upgrade_info.upgrade_id = os_rand();
}
if (cco_upgrade_info.upgrade_id == 0) {
cco_upgrade_info.upgrade_id++;
}
}
/* send upgrade cmd ack to mcu */
void iot_proto_upgrade_complete_ind(void)
{
gree_frame_fn251_subfn03_t *ind;
iot_pkt_t *frame_pkt = iot_pkt_alloc(
sizeof(gree_frame_fn251_subfn03_t), IOT_GREE_APP_MID);
if (!frame_pkt) {
iot_cus_printf("[glpr][up]:alloc pkt err!\n");
return;
}
ind = (gree_frame_fn251_subfn03_t *)iot_pkt_data(frame_pkt);
IOT_ASSERT(ind);
iot_cus_printf("[glpr][up]:upgrade complete\n");
iot_pkt_put(frame_pkt, sizeof(*ind));
os_mem_set(ind, 0, sizeof(*ind));
ind->seq = prototask_contxt.local_dev.ind_seq++;
EXT_FN_FRM_PREPARE(ind, PROTO_UPGRADE_UL, PROTO_UPGRADE_COMPLETE);
ind->tail.check_sum = ge_frm_checksum_calc((uint8_t *)ind,
sizeof(*ind) - sizeof(ge_frm_tail_t));
iot_proto_send_to_mainboard(frame_pkt);
}
static void iot_proto_upgrade_data_ack(uint8_t seq, uint16_t index,
uint8_t result)
{
gree_frame_fn251_subfn01_t *ack;
iot_pkt_t *ack_pkt = iot_pkt_alloc(
sizeof(gree_frame_fn251_subfn01_t), IOT_GREE_APP_MID);
if (!ack_pkt) {
iot_cus_printf("[glpr][up]:alloc pkt err!\n");
return;
}
ack = (gree_frame_fn251_subfn01_t *)iot_pkt_data(ack_pkt);
IOT_ASSERT(ack);
iot_cus_printf("[glpr][up]:upgrade result: %d\n", result);
iot_pkt_put(ack_pkt, sizeof(*ack));
os_mem_set(ack, 0, sizeof(*ack));
ack->seq = seq;
ack->result = result;
ack->seg_index = index;
EXT_FN_FRM_PREPARE(ack, PROTO_UPGRADE_UL, PROTO_UPGRADE_DATA_ACK);
ack->tail.check_sum = ge_frm_checksum_calc((uint8_t *)ack,
sizeof(*ack) - sizeof(ge_frm_tail_t));
iot_proto_send_to_mainboard(ack_pkt);
}
/* send upgrade event to mcu */
static void iot_proto_upgrade_report_event(uint8_t reason)
{
gree_frame_fn251_subfn02_t *result;
iot_pkt_t *result_pkt = iot_pkt_alloc(sizeof(gree_frame_fn251_subfn02_t),
IOT_GREE_APP_MID);
if (!result_pkt) {
iot_cus_printf("[glpr][up]:alloc pkt err!\n");
return;
}
result = (gree_frame_fn251_subfn02_t *)iot_pkt_data(result_pkt);
IOT_ASSERT(result);
iot_cus_printf("[glpr][up]:upgrade event : %d\n", reason);
iot_pkt_put(result_pkt, sizeof(*result));
os_mem_set(result, 0, sizeof(*result));
result->seq = prototask_contxt.local_dev.ind_seq++;
result->result = (reason != GREE_REPORT_UPGRADE_CRC_OK);
result->reason = reason;
EXT_FN_FRM_PREPARE(result, PROTO_UPGRADE_UL, PROTO_UPGRADE_DATA_RESULT);
result->tail.check_sum = ge_frm_checksum_calc((uint8_t *)result,
sizeof(*result) - sizeof(ge_frm_tail_t));
iot_proto_send_to_mainboard(result_pkt);
}
static void iot_proto_init_upgrade_state(void)
{
proto_dev_list_t *dev_lst = &prototask_contxt.dev_lst;
uint16_t i;
os_mem_set(sta_upgrade_info, 0, sizeof(*sta_upgrade_info)* STA_DEV_MAX);
cco_upgrade_info.sta_upgrade_cnt = 0;
for (i = 0; i < STA_DEV_MAX; i++)
{
if (!os_mem_cmp(dev_lst->dev[i].mac, INVALID_MACADDR,
UPGRADE_MAC_BYTE)) {
/* invalid mac address */
continue;
}
os_mem_cpy(sta_upgrade_info[i].mac, dev_lst->dev[i].mac,
UPGRADE_MAC_BYTE);
sta_upgrade_info[i].status = UPGRADE_STATUS_DATA_RECVING;
cco_upgrade_info.sta_upgrade_cnt++;
}
}
void iot_proto_sync_upgrade_list(void)
{
uint16_t i;
uint8_t *data = NULL;
uint8_t cnt = GE_UPGRADE_REMOTE_ADDR_NUM;
uint8_t start_index = 0;
uint8_t end_flag = 0;
uint16_t pkt_len = IOT_MAC_ADDR_LEN * GE_UPGRADE_REMOTE_ADDR_NUM;
iot_pkt_t *pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
if (pkt == NULL) {
iot_cus_printf("[glpr][up]:alloc pkt err!\n");
return;
}
data = iot_pkt_data(pkt);
os_mem_set(data, 0, pkt_len);
for (i = 0; i < STA_DEV_MAX; i++) {
if (!os_mem_cmp(sta_upgrade_info[i].mac, INVALID_MACADDR,
UPGRADE_MAC_BYTE)) {
end_flag = 1;
cnt = start_index;
} else {
os_mem_cpy(data + start_index * IOT_MAC_ADDR_LEN,
sta_upgrade_info[i].mac, UPGRADE_MAC_BYTE);
start_index++;
}
if (start_index >= GE_UPGRADE_REMOTE_ADDR_NUM || end_flag == 1) {
iot_cli_upgrade_set_renew_nodelist(data, cnt);
start_index = 0;
os_mem_set(data, 0, pkt_len);
}
if (end_flag == 1) {
break;
}
}
iot_pkt_free(pkt);
}
static uint8_t iot_proto_upgrade_type_convert(uint8_t type)
{
uint8_t upgrade_type;
switch (type) {
case IOT_GREE_UPGRADE_LOCAL:
upgrade_type = IOT_PLC_UPGRADE_LOCAL;
break;
case IOT_GREE_UPGRADE_ALL:
upgrade_type = IOT_PLC_UPGRADE_ALL;
break;
case IOT_GREE_UPGRADE_STA_LIST:
case IOT_GREE_UPGRADE_P2P:
upgrade_type = IOT_PLC_UPGRADE_STA_LIST;
break;
default:
upgrade_type = IOT_PLC_UPGRADE_INVALID;
break;
}
return upgrade_type;
}
/* process gree upgrade data */
static void iot_proto_upgrade_data(uint8_t *data, uint16_t len)
{
uint32_t ret = ERR_FAIL;
(void)len;
gree_frame_fn250_subfn01_t *upgrade_data =
(gree_frame_fn250_subfn01_t *)data;
IOT_ASSERT(upgrade_data);
if (prototask_contxt.groupnet_state.state == CCO_STATE_GROUPNETING &&
upgrade_data->upgrade_type != IOT_GREE_UPGRADE_LOCAL) {
/* cco is in networking state, not do remote network upgrade */
iot_cus_printf("[glpr][war]: cco is in networking state,not do remote "
"network upgrade\n");
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_IDLE;
iot_proto_upgrade_data_ack(upgrade_data->seq, upgrade_data->seg_index,
GREE_UPGRADE_CMD_CCO_IS_GROUPNETING);
return;
}
if (cco_upgrade_info.expect_seg_index < upgrade_data->seg_index) {
iot_cus_printf("[glpr][err]: invalid index %d expect %d\n",
upgrade_data->seg_index, cco_upgrade_info.expect_seg_index);
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_IDX_ERR;
iot_proto_upgrade_data_ack(upgrade_data->seq, upgrade_data->seg_index,
GREE_UPGRADE_CMD_DATA_INDEXERROR);
return;
}
iot_cus_printf("[glpr][up]:seg index %d total seg count %d data len %d\n",
upgrade_data->seg_index, upgrade_data->total_seg_cnt,
upgrade_data->data_len);
// prepare for upgrading
if (1 == upgrade_data->seg_index) {
if ((IOT_GREE_UPGRADE_P2P == upgrade_data->upgrade_type) ||
(IOT_GREE_UPGRADE_STA_LIST == upgrade_data->upgrade_type)) {
uint16_t i;
iot_plc_upgrade_dst_list_t list;
list.dst_list_idx = 0;
list.dst_num = cco_upgrade_info.sta_upgrade_cnt;
list.end = 0;
for (i = list.dst_list_idx; i < list.dst_num; i++) {
iot_mac_addr_cpy(&list.dst_list[i * IOT_MAC_ADDR_LEN],
&sta_upgrade_info[i].mac[0]);
iot_cus_printf("upgrade: mac. = %d, %d, %d, %d, %d, %d\n",
list.dst_list[i * IOT_MAC_ADDR_LEN + 0],
list.dst_list[i * IOT_MAC_ADDR_LEN + 1],
list.dst_list[i * IOT_MAC_ADDR_LEN + 2],
list.dst_list[i * IOT_MAC_ADDR_LEN + 3],
list.dst_list[i * IOT_MAC_ADDR_LEN + 4],
list.dst_list[i * IOT_MAC_ADDR_LEN + 5]);
}
iot_cli_upgrade_set_dst_list(&list, 1);
}
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_DATA_RECVING;
if ((IOT_GREE_UPGRADE_LOCAL != upgrade_data->upgrade_type) &&
(IOT_GREE_UPGRADE_ALL != upgrade_data->upgrade_type) &&
(IOT_GREE_UPGRADE_P2P != upgrade_data->upgrade_type)) {
iot_cus_printf("[glpr][err]:upgrade type error\n");
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_TYPE_ERR;
iot_proto_upgrade_data_ack(upgrade_data->seq,
upgrade_data->seg_index, GREE_UPGRADE_CMD_UGTYPE_NONSUPPORT);
return;
}
cco_upgrade_info.expect_seg_index = 1;
cco_upgrade_info.upgrade_type = upgrade_data->upgrade_type;
//first seg of upgrade file
if ((IOT_GREE_UPGRADE_ALL == upgrade_data->upgrade_type) ||
(IOT_GREE_UPGRADE_STA_LIST == upgrade_data->upgrade_type) ||
(IOT_GREE_UPGRADE_P2P == cco_upgrade_info.upgrade_type)) {
iot_cli_upgrade_prepare(iot_proto_upgrade_completed_handler,
IOT_GREE_MAX_STA_FW_SIZE, &cco_upgrade_info.file_data,
upgrade_data->data, upgrade_data->data_len,
iot_proto_upgrade_type_convert(cco_upgrade_info.upgrade_type));
if (IOT_GREE_UPGRADE_ALL == upgrade_data->upgrade_type) {
/* list upgrade have inited upgrade list*/
iot_proto_init_upgrade_state();
}
os_start_timer(prototask_contxt.upgrade_tmr,
PROTO_TMR_UPDATE_UPGRADE_STATE_INTVL);
} else if (IOT_GREE_UPGRADE_LOCAL == cco_upgrade_info.upgrade_type) {
if (cco_upgrade_info.upgrade_type == IOT_PLC_UPGRADE_LOCAL) {
/* start rset */
iot_start_rst_t rst;
iot_upgrade_id_init();
iot_pkg_upgrade_cancel_commit(cco_upgrade_info.upgrade_id, true);
cco_upgrade_info.upgrade_id++;
ret = iot_pkg_upgrade_start(&rst, cco_upgrade_info.upgrade_id,
GREE_UPGRADE_DATA_PACKET_LEN, 0, 0, 0, 0, upgrade_data->data);
if (ret != ERR_OK) {
iot_cus_printf("upgrade: start failed. result = %d\n", ret);
return;
}
}
}
} else if (cco_upgrade_info.upgrade_type != upgrade_data->upgrade_type) {
iot_cus_printf("[glpr][err]:upgrade type invaild\n");
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_TYPE_ERR;
iot_proto_upgrade_data_ack(upgrade_data->seq, upgrade_data->seg_index,
GREE_UPGRADE_CMD_PARAM_INVALID);
return;
}
// ack success to mcu
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_DATA_RECVING;
iot_proto_upgrade_data_ack(upgrade_data->seq, upgrade_data->seg_index,
GREE_UPGRADE_CMD_SUCCESS);
if (IOT_GREE_UPGRADE_LOCAL == cco_upgrade_info.upgrade_type) {
cco_upgrade_info.data_progress =
(uint8_t)(GREE_CCO_UPGRADE_SUCC_PROGRESS *
upgrade_data->seg_index / upgrade_data->total_seg_cnt);
} else {
cco_upgrade_info.data_progress =
(uint8_t)(GREE_CCO_RECV_STA_UPGRADE_DATA_MAX_PROGRESS *
upgrade_data->seg_index / upgrade_data->total_seg_cnt);
}
/* to make sure each seg index only save one time */
if (upgrade_data->seg_index == cco_upgrade_info.expect_seg_index) {
cco_upgrade_info.expect_seg_index++;
if ((cco_upgrade_info.upgrade_type == IOT_PLC_UPGRADE_ALL) ||
(cco_upgrade_info.upgrade_type == IOT_PLC_UPGRADE_STA_LIST) ||
(cco_upgrade_info.upgrade_type == IOT_GREE_UPGRADE_P2P)) {
(void)iot_cli_upgrade_write (cco_upgrade_info.len,
upgrade_data->data, upgrade_data->data_len);
cco_upgrade_info.len += upgrade_data->data_len;
} else if (IOT_GREE_UPGRADE_LOCAL == cco_upgrade_info.upgrade_type) {
iot_trans_cmd_t trans;
iot_pkt_t *trans_pkt = NULL;
trans_pkt = (iot_pkt_t *)iot_pkt_alloc(upgrade_data->data_len,
IOT_GREE_APP_MID);
if (trans_pkt == NULL) {
iot_cus_printf("trans_pkt alloc error");
return;
}
iot_pkt_put(trans_pkt, upgrade_data->data_len);
os_mem_cpy(iot_pkt_data(trans_pkt), upgrade_data->data,
upgrade_data->data_len);
trans.data = trans_pkt;
trans.block_num = upgrade_data->seg_index - 1;
trans.data_type = UPGRADE_DATA_TYPE_PKG;
trans.id = cco_upgrade_info.upgrade_id;
trans.crc_flag = 0;
if (ERR_OK != (ret = iot_pkg_upgrade_trans(&trans))) {
iot_cus_printf("[upd]update data failed. result = %d\n", ret);
return;
}
}
}
// start upgrading
if (upgrade_data->total_seg_cnt == upgrade_data->seg_index) {
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_DATA_RECV_CMP;
cco_upgrade_info.expect_seg_index = 1;
// check crc of upgrade file
if ((cco_upgrade_info.upgrade_type == IOT_GREE_UPGRADE_LOCAL)||
(true == iot_proto_upgrade_file_check())) {
// report that file had received completion
iot_proto_upgrade_report_event(GREE_REPORT_UPGRADE_FILE_COMPLETED);
switch (cco_upgrade_info.upgrade_type) {
case IOT_GREE_UPGRADE_LOCAL:
{
iot_pkg_upgrade_commit(cco_upgrade_info.upgrade_id);
iot_proto_upgrade_completed_handler();
iot_pkg_upgrade_reset();
break;
}
case IOT_GREE_UPGRADE_ALL:
{
iot_proto_upgrade_initialize();
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_DATA_BRST;
cco_upgrade_info.data_progress =
GREE_CCO_RECV_STA_UPGRADE_DATA_MAX_PROGRESS;
iot_cli_upgrade_start(iot_proto_upgrade_type_convert
(cco_upgrade_info.upgrade_type), 0);
break;
}
case IOT_GREE_UPGRADE_P2P:
case IOT_PLC_UPGRADE_STA_LIST:
{
iot_cus_printf("[glpr][up]:list upgrade start\n");
iot_proto_upgrade_initialize();
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_STA_QUERY;
cco_upgrade_info.data_progress =
GREE_CCO_RECV_STA_UPGRADE_DATA_MAX_PROGRESS;
iot_cli_upgrade_start(iot_proto_upgrade_type_convert
(cco_upgrade_info.upgrade_type), 0);
break;
}
default:
break;
}
}
}
}
static void iot_proto_upgrade_resp_status_to_mainboard(
gree_frame_fn251_subfn04_t frame)
{
gree_frame_fn251_subfn04_t *resp_frame;
iot_pkt_t *resp_pkt = iot_pkt_alloc(sizeof(*resp_frame), IOT_GREE_APP_MID);
if (!resp_pkt) {
iot_cus_printf("[glpr][up]:alloc pkt err!\n");
return;
}
resp_frame = (gree_frame_fn251_subfn04_t *)iot_pkt_data(resp_pkt);
IOT_ASSERT(resp_frame);
iot_pkt_put(resp_pkt, sizeof(*resp_frame));
*resp_frame = frame;
EXT_FN_FRM_PREPARE(resp_frame, PROTO_UPGRADE_UL, PROTO_UPGRADE_STATUS_RESP);
resp_frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_frame,
sizeof(*resp_frame) - sizeof(ge_frm_tail_t));
iot_proto_send_to_mainboard(resp_pkt);
}
void iot_proto_update_sta_upgrade_status(void)
{
static uint16_t start_idx = 0;
static GE_UPGRADE_UNITBIT resp_index = 0;
iot_plc_upgrade_dst_status_list status_list;
gree_frame_fn251_subfn04_t resp_frame;
uint16_t all_sta_upgrade_progress = 0;
uint8_t resp_cnt = 0;
uint8_t count = UPGRADE_REMOTE_DST_STATUS_ONCE_MAX_NUM;
GE_UPGRADE_UNITBIT sta_count =
(GE_UPGRADE_UNITBIT)cco_upgrade_info.sta_upgrade_cnt;
GE_UPGRADE_UNITBIT i, j;
os_mem_set(&status_list, 0, sizeof(status_list));
if (start_idx + count > sta_count) {
count = (uint8_t)(sta_count - start_idx);
}
//query state
iot_cli_upgrade_qr_dst_status_list(start_idx, count, &status_list);
iot_cus_printf("[glpr][up] query upgrade status, cnt=%d "
"local status=%d progress=%d resp_flag=%d\n",
status_list.dst_num, cco_upgrade_info.upgrade_status,
cco_upgrade_info.data_progress, prototask_contxt.resp_state_flag);
/* find mac in whitelist first */
for (i = 0; i < sta_count; i++) {
if (!os_mem_cmp(sta_upgrade_info[i].mac, INVALID_MACADDR,
UPGRADE_MAC_BYTE)) {
/* invalid mac address */
continue;
}
if (cco_upgrade_info.upgrade_status == UPGRADE_STATUS_DATA_RECVING ||
cco_upgrade_info.upgrade_status == UPGRADE_STATUS_DATA_RECV_CMP) {
/* cco receive upgrade data */
sta_upgrade_info[i].status = cco_upgrade_info.upgrade_status;
sta_upgrade_info[i].progress = cco_upgrade_info.data_progress;
} else if (cco_upgrade_info.upgrade_status == UPGRADE_STATUS_DATA_BRST) {
/* cco broadcast upgrade data */
sta_upgrade_info[i].status = cco_upgrade_info.upgrade_status;
sta_upgrade_info[i].progress = cco_upgrade_info.data_progress +
status_list.dst_status_list[0].percentage *
GREE_CCO_BROADCAST_UPGRADE_DATA_MAX_PROGRESS /
GREE_CCO_UPGRADE_SUCC_PROGRESS;
iot_cus_printf("[glpr][up]: upgrade progress=%d org=%d\n",
sta_upgrade_info[i].progress,
status_list.dst_status_list[0].percentage);
/* cco broadcast completed*/
if (status_list.dst_status_list[0].percentage ==
GREE_STA_RECV_UPGRADE_DATA_MAX_PROGRESS) {
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_DATA_BRST_CMP;
}
} else if (cco_upgrade_info.upgrade_status == UPGRADE_STATUS_COMPLETE &&
sta_upgrade_info[i].progress == GREE_CCO_UPGRADE_SUCC_PROGRESS) {
/* upgrade completed successful */
sta_upgrade_info[i].status = UPGRADE_STATUS_COMPLETE;
} else {
/* error happened or broadcast data */
if (status_list.dst_num == 0) {
/* have no response from cli */
break;
}
/* to find mac in status_list */
for (j = 0; j < status_list.dst_num; j++) {
if (!os_mem_cmp(sta_upgrade_info[i].mac,
status_list.dst_status_list[j].dst, UPGRADE_MAC_BYTE)) {
/* find and save to local */
if (status_list.dst_status_list[j].error_code ==
UPGRADE_DATA_SUCCESS ||
status_list.dst_status_list[j].error_code ==
UPGRADE_DATA_STA_IN_PROGRESS) {
/* sta have received upgrade data */
sta_upgrade_info[i].status =
UPGRADE_STATUS_DATA_BRST_CMP;
} else {
sta_upgrade_info[i].status = UPGRADE_STATUS_REMOTE_ERR;
}
if (IOT_GREE_UPGRADE_P2P == cco_upgrade_info.upgrade_type) {
sta_upgrade_info[i].progress =
cco_upgrade_info.data_progress +
(status_list.dst_status_list[j].percentage -
GREE_STA_RECV_UPGRADE_DATA_MAX_PROGRESS) *
GREE_CCO_BROADCAST_UPGRADE_DATA_MAX_PROGRESS /
GREE_STA_RECV_UPGRADE_DATA_MAX_PROGRESS;
} else {
sta_upgrade_info[i].progress =
cco_upgrade_info.data_progress +
status_list.dst_status_list[j].percentage *
GREE_CCO_BROADCAST_UPGRADE_DATA_MAX_PROGRESS /
GREE_CCO_UPGRADE_SUCC_PROGRESS;
}
iot_cus_printf("[glpr][up]: find %02x,%02x,%02x,%02x,%02x,"
"%02x error_code=%d progress =%d clc_prg=%d\n",
status_list.dst_status_list[j].dst[0],
status_list.dst_status_list[j].dst[1],
status_list.dst_status_list[j].dst[2],
status_list.dst_status_list[j].dst[3],
status_list.dst_status_list[j].dst[4],
status_list.dst_status_list[j].dst[5],
status_list.dst_status_list[j].error_code,
status_list.dst_status_list[j].percentage,
sta_upgrade_info[i].progress);
if (sta_upgrade_info[i].progress ==
GREE_CCO_UPGRADE_SUCC_PROGRESS) {
sta_upgrade_info[i].status = UPGRADE_STATUS_COMPLETE;
}
break;
}
}
}
all_sta_upgrade_progress += sta_upgrade_info[i].progress;
/* add k for save next sta upgrade info */
}
if (sta_count > 0) {
cco_upgrade_info.sta_upgrade_prg =
(uint8_t)(all_sta_upgrade_progress / sta_count);
}
/* response sta upgrade state */
if (prototask_contxt.resp_state_flag == 1) {
os_mem_set(&resp_frame, 0, sizeof(resp_frame));
resp_cnt = ((sta_count - resp_index) > RESP_UPGRADE_STATE_CNT_MAX) ?
RESP_UPGRADE_STATE_CNT_MAX : (uint8_t)(sta_count - resp_index);
resp_frame.total = sta_count;
resp_frame.seq = prototask_contxt.sm.seq;
for (j = resp_index; j < resp_index + resp_cnt; j++) {
os_mem_cpy(resp_frame.mac, sta_upgrade_info[j].mac,
UPGRADE_MAC_BYTE);
resp_frame.index = j + 1;
resp_frame.status = sta_upgrade_info[j].status;
resp_frame.progress = sta_upgrade_info[j].progress;
iot_proto_upgrade_resp_status_to_mainboard(resp_frame);
}
resp_index += resp_cnt;
if (resp_index >= sta_count) {
/* have response all info to mainboard
* clear flag, and init index
*/
prototask_contxt.resp_state_flag = 0;
resp_index = 0;
}
}
start_idx += count;
if (start_idx >= sta_count) {
start_idx = 0;
}
if (cco_upgrade_info.sta_upgrade_prg != GREE_CCO_UPGRADE_SUCC_PROGRESS ||
prototask_contxt.resp_state_flag) {
os_start_timer(prototask_contxt.upgrade_tmr,
PROTO_TMR_UPDATE_UPGRADE_STATE_INTVL);
}
}
static void iot_proto_upgrade_query_status(uint8_t *data, uint16_t len)
{
gree_frame_fn250_subfn02_t *cmd_frame = (gree_frame_fn250_subfn02_t*)data;
gree_frame_fn251_subfn04_t resp_frame;
GE_UPGRADE_UNITBIT sta_cnt = 0, total_cnt = 0;
GE_UPGRADE_UNITBIT i = 0;
os_mem_set(&resp_frame, 0, sizeof(resp_frame));
if (sizeof(gree_frame_fn250_subfn02_t) != len) {
/* command length check error*/
iot_cus_printf("[glpr][err]:cmd length err\n");
iot_proto_upgrade_resp_status_to_mainboard(resp_frame);
} else if (!os_mem_cmp(cmd_frame->mac, INVALID_MACADDR, UPGRADE_MAC_BYTE)) {
/* mac is invalid */
iot_cus_printf("[glpr][war]:query mac is invalid\n");
resp_frame.seq = cmd_frame->seq;
os_mem_cpy(resp_frame.mac, cmd_frame->mac, UPGRADE_MAC_BYTE);
iot_proto_upgrade_resp_status_to_mainboard(resp_frame);
} else if (IOT_GREE_UPGRADE_LOCAL == cco_upgrade_info.upgrade_type) {
/* cco local upgrade */
resp_frame.total = 1;
resp_frame.index = 1;
resp_frame.seq = cmd_frame->seq;
os_mem_cpy(resp_frame.mac, cmd_frame->mac, UPGRADE_MAC_BYTE);
if (!os_mem_cmp(cmd_frame->mac, MAC_ALL_STA, UPGRADE_MAC_BYTE) ||
!os_mem_cmp(cmd_frame->mac, prototask_contxt.local_dev.mac,
UPGRADE_MAC_BYTE)) {
/* query is valid,response local status and process */
resp_frame.status = cco_upgrade_info.upgrade_status;
resp_frame.progress = cco_upgrade_info.data_progress;
} else {
resp_frame.status = 0;
resp_frame.progress = 0;
}
iot_cus_printf("[glpr][up]: %02x,%02x,%02x,%02x,%02x,%02x,"
"status=%d progress=%d\n",
prototask_contxt.local_dev.mac[0],
prototask_contxt.local_dev.mac[1],
prototask_contxt.local_dev.mac[2],
prototask_contxt.local_dev.mac[3],
prototask_contxt.local_dev.mac[4],
prototask_contxt.local_dev.mac[5],
resp_frame.status, resp_frame.progress);
iot_proto_upgrade_resp_status_to_mainboard(resp_frame);
} else if (IOT_GREE_UPGRADE_ALL == cco_upgrade_info.upgrade_type ||
IOT_GREE_UPGRADE_P2P == cco_upgrade_info.upgrade_type) {
/* remote network upgrade */
total_cnt = (GE_UPGRADE_UNITBIT)cco_upgrade_info.sta_upgrade_cnt;
if (!os_mem_cmp(cmd_frame->mac, MAC_ALL_STA, UPGRADE_MAC_BYTE)) {
/* query all stations upgrade status, set flag for response */
prototask_contxt.resp_state_flag = 1;
if (!os_is_timer_active(prototask_contxt.upgrade_tmr)) {
os_start_timer(prototask_contxt.upgrade_tmr,
PROTO_TMR_UPDATE_UPGRADE_STATE_INTVL);
}
} else {
/* query one stations upgrade status */
resp_frame.seq = cmd_frame->seq;
resp_frame.total = 1;
for (i = 0; i < total_cnt; i++) {
if (!os_mem_cmp(sta_upgrade_info[i].mac, cmd_frame->mac,
UPGRADE_MAC_BYTE)) {
/* find mac in sta_upgrade_info list */
resp_frame.index = ++sta_cnt;
resp_frame.status = sta_upgrade_info[i].status;
resp_frame.progress = sta_upgrade_info[i].progress;
os_mem_cpy(resp_frame.mac, cmd_frame->mac, UPGRADE_MAC_BYTE);
iot_cus_printf("[glpr][up]:find %02x,%02x,%02x,%02x,%02x,"
"%02x status=%d progress=%d\n",
sta_upgrade_info[i].mac[0], sta_upgrade_info[i].mac[1],
sta_upgrade_info[i].mac[2], sta_upgrade_info[i].mac[3],
sta_upgrade_info[i].mac[4], sta_upgrade_info[i].mac[5],
sta_upgrade_info[i].status,
sta_upgrade_info[i].progress);
iot_proto_upgrade_resp_status_to_mainboard(resp_frame);
break;
}
}
}
if (total_cnt == 0 || i >= total_cnt) {
/* not in white list */
resp_frame.index = 1;
resp_frame.status = UPGRADE_STATUS_NO_IN_WHT_ERR;
resp_frame.progress = 0;
os_mem_cpy(resp_frame.mac, cmd_frame->mac, UPGRADE_MAC_BYTE);
iot_cus_printf("[glpr][war]:not in whitelist or whitelist empty\n");
iot_proto_upgrade_resp_status_to_mainboard(resp_frame);
}
} else {
/* IOT_GREE_UPGRADE_INVALID,have not do upgrade */
resp_frame.seq = cmd_frame->seq;
resp_frame.total = 1;
resp_frame.index = 1;
resp_frame.status = UPGRADE_STATUS_IDLE;
resp_frame.progress = 0;
os_mem_cpy(resp_frame.mac, cmd_frame->mac, UPGRADE_MAC_BYTE);
iot_cus_printf("[glpr][war]: not in upgrade status\n");
iot_proto_upgrade_resp_status_to_mainboard(resp_frame);
}
return;
}
static void iot_proto_upgrade_stop(uint8_t *data, uint16_t len)
{
(void)len;
gree_frame_fn250_subfn03_t *stop_frame = (gree_frame_fn250_subfn03_t*)data;
gree_frame_fn251_subfn05_t *ack;
iot_pkt_t *ack_pkt;
prototask_contxt.resp_state_flag = 0;
/* stop update upgrade timer */
if (os_is_timer_active(prototask_contxt.upgrade_tmr)) {
os_stop_timer(prototask_contxt.upgrade_tmr);
}
ack_pkt = iot_pkt_alloc(sizeof(gree_frame_fn251_subfn05_t),
IOT_GREE_APP_MID);
if (!ack_pkt) {
iot_cus_printf("[glpr][up]:alloc pkt err!\n");
return;
}
ack = (gree_frame_fn251_subfn05_t *)iot_pkt_data(ack_pkt);
iot_pkt_put(ack_pkt, sizeof(*ack));
os_mem_set(ack, 0, sizeof(*ack));
ack->seq = stop_frame->seq;
if(IOT_GREE_UPGRADE_LOCAL == cco_upgrade_info.upgrade_type) {
iot_pkg_upgrade_cancel_commit(cco_upgrade_info.upgrade_id, true);
cco_upgrade_info.upgrade_id++;
}
if (sizeof(gree_frame_fn250_subfn03_t) != len) {
iot_cus_printf("[glpr][err]: stop gree upgrade length check error\n");
ack->result = GREE_UPGRADE_CMD_FAILUR;
ack->reason = GREE_UPGRADE_CMD_LENGTH_CHECK_ERR;
} else {
iot_cus_printf("[glpr][up]: stop gree upgrade\n");
iot_proto_upgrade_initialize();
iot_cli_upgrade_stop();
ack->result = GREE_UPGRADE_CMD_SUCCESS;
ack->reason = 0;
}
// report upgrade stop cfm to mcu
EXT_FN_FRM_PREPARE(ack, PROTO_UPGRADE_UL, PROTO_UPGRADE_STOP_ACK);
ack->tail.check_sum = ge_frm_checksum_calc((uint8_t *)ack,
sizeof(*ack) - sizeof(ge_frm_tail_t));
iot_proto_send_to_mainboard(ack_pkt);
}
static void iot_proto_upgrade_start_node(uint8_t *data, uint16_t len)
{
(void)len;
gree_frame_fn250_subfn04_t *start_node_frame =
(gree_frame_fn250_subfn04_t*)data;
gree_frame_fn251_subfn06_t *ack;
iot_pkt_t *ack_pkt;
static uint8_t sync_upgrade_list = 0;
prototask_contxt.resp_state_flag = 0;
if (start_node_frame->total <= 0 || start_node_frame->index <= 0 ||
start_node_frame->total < start_node_frame->index ||
cco_upgrade_info.upgrade_status != UPGRADE_STATUS_IDLE) {
iot_cus_printf("[gepr][up]:cmd err!\n");
return;
} else if (!os_mem_cmp(start_node_frame->mac, INVALID_MACADDR,
UPGRADE_MAC_BYTE)) {
iot_cus_printf("[gepr][up]:invalid mac!\n");
return;
} else {
if (start_node_frame->index == 1) {
sync_upgrade_list = 1;
/* reset upgrade list */
os_mem_set(sta_upgrade_info, 0,
sizeof(*sta_upgrade_info) * STA_DEV_MAX);
cco_upgrade_info.sta_upgrade_cnt = 0;
} else if (sync_upgrade_list == 0) {
iot_cus_printf("[gepr][up]: state err!\n");
return;
}
/* copy mac to upgrade list */
os_mem_cpy(sta_upgrade_info[start_node_frame->index - 1].mac,
start_node_frame->mac, UPGRADE_MAC_BYTE);
sta_upgrade_info[start_node_frame->index - 1].status =
UPGRADE_STATUS_DATA_RECVING;
cco_upgrade_info.sta_upgrade_cnt++;
iot_cus_printf("[gepr][up]: start mac sta_upgrade_cnt = %d\n",
cco_upgrade_info.sta_upgrade_cnt);
/* check end */
if (start_node_frame->total == start_node_frame->index) {
sync_upgrade_list = 0;
/* end and resp ack */
ack_pkt = iot_pkt_alloc(sizeof(gree_frame_fn251_subfn06_t),
IOT_GREE_APP_MID);
if (!ack_pkt) {
iot_cus_printf("[gepr][up]:alloc pkt err!\n");
return;
}
ack = (gree_frame_fn251_subfn06_t *)iot_pkt_data(ack_pkt);
iot_pkt_put(ack_pkt, sizeof(*ack));
os_mem_set(ack, 0, sizeof(*ack));
ack->seq = start_node_frame->seq;
ack->result = GREE_UPGRADE_CMD_SUCCESS;
ack->reason = 0;
/* report upgrade stop cfm to mcu */
EXT_FN_FRM_PREPARE(ack, PROTO_UPGRADE_UL,
PROTO_UPGRADE_START_NODE_ACK);
ack->tail.check_sum = ge_frm_checksum_calc((uint8_t *)ack,
sizeof(*ack) - sizeof(ge_frm_tail_t));
iot_proto_send_to_mainboard(ack_pkt);
}
}
}
/* handle gree upgrade dl fn cmd */
void iot_proto_upgrade_fn_handler(uint8_t *data, uint16_t len)
{
PROTO_UPGRADE_FN_HANDLE cmd_handle_fn = NULL;
ge_extend_fn_hdr_t *frm_hdr = (ge_extend_fn_hdr_t *)data;
uint8_t i;
IOT_ASSERT(frm_hdr);
for (i = 0; i < ARRAY_CNT(proto_upgrade_subfnhdl_tbl); i++) {
if (proto_upgrade_subfnhdl_tbl[i].cmdid == frm_hdr->subfn) {
cmd_handle_fn = proto_upgrade_subfnhdl_tbl[i].cmd_handle_fn;
break;
}
}
if (cmd_handle_fn) {
cmd_handle_fn(data, len);
}
}
void iot_proto_upgrade_initialize()
{
iot_cus_printf("[glpr][up]:gree upgrade initialize\n");
cco_upgrade_info.len = 0;
cco_upgrade_info.expect_seg_index = 1;
cco_upgrade_info.file_data = NULL;
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_IDLE;
cco_upgrade_info.data_progress = 0;
}
bool_t iot_proto_upgrade_file_check()
{
uint32_t file_type = IOT_FILE_TYPE_CCO;
uint8_t reason = GREE_REPORT_UPGRADE_INVALID;
if (!iot_check_file_crc(cco_upgrade_info.file_data, cco_upgrade_info.len)) {
iot_cus_printf("[glpr][err]:upgrade file ack crc error\n");
reason = GREE_REPORT_UPGRADE_CRC_ERROR;
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_CRC_ERR;
goto check_fail;
}
file_type = iot_get_file_type_value(cco_upgrade_info.file_data);
if (IOT_FILE_TYPE_CCO == file_type) {
if (IOT_GREE_UPGRADE_LOCAL != cco_upgrade_info.upgrade_type) {
reason = GREE_REPORT_UPGRADE_UGTYPE_MISMATCH;
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_TYPE_ERR;
goto check_fail;
}
} else if (IOT_FILE_TYPE_STA == file_type) {
if ((IOT_GREE_UPGRADE_ALL != cco_upgrade_info.upgrade_type) &&
(IOT_GREE_UPGRADE_P2P != cco_upgrade_info.upgrade_type)) {
reason = GREE_REPORT_UPGRADE_UGTYPE_MISMATCH;
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_TYPE_ERR;
goto check_fail;
}
} else {
reason = GREE_REPORT_UPGRADE_FILE_INVALID;
cco_upgrade_info.upgrade_status = UPGRADE_STATUS_FILE_ERR;
goto check_fail;
}
return true;
check_fail:
// report error to mcu
iot_proto_upgrade_report_event(reason);
return false;
}
#endif