1958 lines
63 KiB
C
1958 lines
63 KiB
C
/****************************************************************************
|
|
|
|
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.
|
|
|
|
****************************************************************************/
|
|
|
|
#include "iot_oem_api.h"
|
|
#include "iot_img_hdr.h"
|
|
#include "iot_ntoh_api.h"
|
|
#include "iot_system.h"
|
|
|
|
#include "iot_cli_plc_tx_rx.h"
|
|
#include "iot_cli_plc_module.h"
|
|
#include "iot_cli_upgrade_api.h"
|
|
#include "iot_cli_host_upgrade_internal.h"
|
|
#include "iot_cli_upgrade_status_type_def.h"
|
|
#include "iot_cli_sg.h"
|
|
#include "iot_bitmap_api.h"
|
|
#include "plc_utils.h"
|
|
#include "iot_mtd.h"
|
|
|
|
extern iot_plc_upgrade_info_t *upgrade_info;
|
|
extern iot_plc_host_config_t *host_config;
|
|
extern iot_cli_host_info_t *host_info;
|
|
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
|
|
iot_cli_upgrade_app_handler sg_upgrade_handler = NULL;
|
|
|
|
#if IOT_CLI_UPGRADE_ENABLE
|
|
|
|
/* remote upgrade dst list check */
|
|
static uint8_t cli_upgrade_dst_list_check(
|
|
iot_plc_upgrade_dst_list_t *data)
|
|
{
|
|
if (!data) {
|
|
return UPGRADE_DST_LIST_INVALID_DATA;
|
|
}
|
|
|
|
if (upgrade_info->dst_list_idx != data->dst_list_idx) {
|
|
iot_printf("plc_upgrade:recv dst list, expect %d, recv %x",
|
|
upgrade_info->dst_list_idx, data->dst_list_idx);
|
|
return UPGRADE_DST_LIST_IDX_ERROR;
|
|
}
|
|
|
|
return UPGRADE_DST_LIST_SUCCESS;
|
|
}
|
|
|
|
static void cli_upgrade_set_dst_status_ack(
|
|
iot_plc_upgrade_dst_status_query *query)
|
|
{
|
|
if (!query) {
|
|
return;
|
|
}
|
|
query->dst_total_num = upgrade_info->dest_info.dst_total_num;
|
|
query->dst_num = UPGRADE_REMOTE_DST_STATUS_ONCE_MAX_NUM;
|
|
query->upgrade_state = upgrade_info->upgrade_state;
|
|
}
|
|
|
|
/* cco handle destination status query from plc manager */
|
|
static void cli_upgrade_dst_status_query_internal(uint8_t *src_mac)
|
|
{
|
|
iot_plc_upgrade_dst_status_query_ul query_ack;
|
|
|
|
cli_upgrade_set_dst_status_ack(&(query_ack.query));
|
|
|
|
iot_cli_send_to_host(CLI_MSGID_UPGRADE_DST_STATUS_QUERY_ACK,
|
|
(uint8_t *)&query_ack, sizeof(query_ack), src_mac);
|
|
}
|
|
|
|
static void cli_upgrade_set_dst_status_list(uint16_t start_idx,
|
|
uint8_t count, iot_plc_upgrade_dst_status_list *status_list)
|
|
{
|
|
uint16_t end_idx = 0;
|
|
uint16_t total_dst_num;
|
|
iot_plc_upgrade_dest_desc_t **org_dest_desc;
|
|
iot_plc_upgrade_dest_desc_t *dest_desc;
|
|
|
|
if (!status_list) {
|
|
return;
|
|
}
|
|
|
|
if (upgrade_info->upgrade_type == IOT_PLC_UPGRADE_STA_LIST) {
|
|
total_dst_num = upgrade_info->dst_list_idx;
|
|
org_dest_desc = &upgrade_info->dest_info.upgrading_list[0];
|
|
} else {
|
|
total_dst_num = upgrade_info->dest_info.dst_total_num;
|
|
org_dest_desc = upgrade_info->dest_info.entry_ptr;
|
|
}
|
|
|
|
if ((!count) || (start_idx >= total_dst_num)) {
|
|
status_list->dst_num = 0;
|
|
status_list->end = 1;
|
|
return;
|
|
}
|
|
if (count > UPGRADE_REMOTE_DST_STATUS_ONCE_MAX_NUM) {
|
|
count = UPGRADE_REMOTE_DST_STATUS_ONCE_MAX_NUM;
|
|
}
|
|
end_idx = start_idx + count - 1;
|
|
status_list->dst_status_list_idx = start_idx;
|
|
status_list->end = 0;
|
|
if (end_idx > (total_dst_num - 1)) {
|
|
end_idx = total_dst_num - 1;
|
|
status_list->end = 1;
|
|
}
|
|
|
|
if (upgrade_info->dest_info.entry_ptr) {
|
|
status_list->dst_num = (uint8_t)(end_idx - start_idx + 1);
|
|
os_mem_set(status_list->dst_status_list, 0,
|
|
UPGRADE_REMOTE_DST_STATUS_ONCE_MAX_NUM *
|
|
sizeof(iot_plc_upgrade_dst_status_t));
|
|
org_dest_desc += start_idx;
|
|
for (uint8_t i = 0; i < status_list->dst_num; i++, org_dest_desc++) {
|
|
dest_desc = *org_dest_desc;
|
|
if (dest_desc) {
|
|
status_list->dst_status_list[i].status =
|
|
dest_desc->status;
|
|
status_list->dst_status_list[i].percentage =
|
|
dest_desc->percentage;
|
|
status_list->dst_status_list[i].error_code =
|
|
dest_desc->error_code;
|
|
iot_mac_addr_cpy(status_list->dst_status_list[i].dst,
|
|
dest_desc->entry.addr);
|
|
}
|
|
}
|
|
} else {
|
|
status_list->dst_num = 0;
|
|
status_list->end = 1;
|
|
}
|
|
}
|
|
|
|
/* coo handle destination status list query from plc manager*/
|
|
void cli_upgrade_dst_status_list_internal(uint16_t start_index,
|
|
uint8_t dst_num, uint8_t *src_mac)
|
|
{
|
|
iot_plc_upgrade_dst_status_list_ul *list_ul;
|
|
iot_pkt_t *buf_pkt;
|
|
uint16_t rsp_len;
|
|
uint8_t i;
|
|
uint8_t temp_percent;
|
|
|
|
/* allocate buffer for response */
|
|
rsp_len = sizeof(iot_plc_upgrade_dst_status_list_ul);
|
|
buf_pkt = iot_pkt_alloc(rsp_len, IOT_CLI_MID);
|
|
|
|
if (!buf_pkt) {
|
|
iot_printf("%s pkt malloc fail\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
list_ul = (iot_plc_upgrade_dst_status_list_ul*)iot_pkt_data(buf_pkt);
|
|
|
|
cli_upgrade_set_dst_status_list(start_index, dst_num,
|
|
&(list_ul->status_list));
|
|
|
|
if (upgrade_info->upgrade_state == IOT_PLC_UPGRADE_TRANSFERRED) {
|
|
for (i = 0; i < list_ul->status_list.dst_num; i++) {
|
|
temp_percent = list_ul->status_list.dst_status_list->percentage;
|
|
list_ul->status_list.dst_status_list->percentage =
|
|
UPGRADE_BDCT_PROGRESS_IN_BCAST_PHASE +
|
|
(temp_percent * (100 - UPGRADE_BDCT_PROGRESS_IN_BCAST_PHASE));
|
|
}
|
|
}
|
|
iot_pkt_put(buf_pkt, rsp_len);
|
|
|
|
iot_printf("upgrade status rpt sta cnt %d \n",
|
|
list_ul->status_list.dst_num);
|
|
iot_cli_send_to_host(CLI_MSGID_UPGRADE_DST_STATUS_LIST_ACK,
|
|
(uint8_t *)list_ul, rsp_len, src_mac);
|
|
|
|
iot_pkt_free(buf_pkt);
|
|
}
|
|
|
|
/* cco handle destination list from plc manager */
|
|
void cli_upgrade_dst_list(uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
(void)bufferlen;
|
|
(void)src_mac;
|
|
iot_plc_upgrade_dst_list_ul_t ack;
|
|
iot_plc_upgrade_dst_list_dl_t *data;
|
|
iot_plc_upgrade_dst_list_t *info;
|
|
|
|
data = (iot_plc_upgrade_dst_list_dl_t *)buffer;
|
|
info = (iot_plc_upgrade_dst_list_t *)&(data->info);
|
|
ack.dst_list_idx = data->info.dst_list_idx;
|
|
ack.error_code = cli_upgrade_dst_list_check(info);
|
|
if (UPGRADE_DST_LIST_SUCCESS != ack.error_code) {
|
|
goto err_exit;
|
|
}
|
|
|
|
iot_cli_upgrade_set_dst_list(info, 0);
|
|
|
|
ack.error_code = UPGRADE_DST_LIST_SUCCESS;
|
|
err_exit:
|
|
iot_cli_send_to_host(CLI_MSGID_UPGRADE_DST_LIST_ACK, (uint8_t *)&ack,
|
|
sizeof(ack), src_mac);
|
|
}
|
|
|
|
/* cco send upgrade progress to PLC Manager */
|
|
void cli_remote_upgrade_send_upgrade_progress(uint8_t progress_value,
|
|
uint8_t *mac)
|
|
{
|
|
iot_plc_upgrade_progress_ul_t progress;
|
|
|
|
if (!mac) {
|
|
return;
|
|
}
|
|
|
|
#if PLC_SUPPORT_UPGRADE_DEBUG
|
|
iot_printf("plc_upgrade:cco send upgrade progress"
|
|
" to plc manager, sta mac:\n");
|
|
cli_upgrade_print_mac_info(mac);
|
|
#endif
|
|
|
|
progress.progress = progress_value;
|
|
progress.upgrade_id = upgrade_info->upgrade_id;
|
|
progress.upgrade_type = IOT_PLC_UPGRADE_ALL;
|
|
os_mem_cpy(progress.dst, mac, IOT_MAC_ADDR_LEN);
|
|
|
|
iot_cli_send_to_host(CLI_MSGID_UPGRADE_PROGRESS,
|
|
(uint8_t*)&progress, sizeof(progress), upgrade_info->upgrade_src_mac);
|
|
}
|
|
|
|
static uint32_t cli_upgrade_get_dest_index(uint16_t *index)
|
|
{
|
|
uint16_t i = 0;
|
|
|
|
for (i = 0; i < IOT_PLC_UPGRADE_STATUS_ITEM_MAX_CNT; i++) {
|
|
if (!upgrade_info->dest_info.entry_ptr[i]) {
|
|
*index = i;
|
|
return ERR_OK;
|
|
}
|
|
}
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
/* cco add dest info into hash table */
|
|
iot_plc_upgrade_dest_desc_t *cli_upgrade_add_dest_info(uint8_t *mac)
|
|
{
|
|
iot_plc_upgrade_dest_desc_t *dest = NULL;
|
|
uint16_t idx;
|
|
|
|
dest = (iot_plc_upgrade_dest_desc_t *)iot_addr_hash_table_find(
|
|
upgrade_info->dest_info.table, mac);
|
|
|
|
if (dest) {
|
|
return dest;
|
|
}
|
|
|
|
if (!mac || (IOT_PLC_UPGRADE_STATUS_ITEM_MAX_CNT <=
|
|
upgrade_info->dest_info.dst_total_num)) {
|
|
return dest;
|
|
}
|
|
if (ERR_OK != cli_upgrade_get_dest_index(&idx)) {
|
|
return dest;
|
|
}
|
|
dest = (iot_plc_upgrade_dest_desc_t *)iot_addr_hash_table_alloc(
|
|
upgrade_info->dest_info.table);
|
|
if (dest) {
|
|
dest->status = IOT_PLC_UPGRADE_INIT;
|
|
dest->percentage = 0;
|
|
dest->reported_percentage = 0;
|
|
dest->start_retry_times = 0;
|
|
dest->upgrade_type = CLI_UPGRADE_TYPE_UNKNOWN;
|
|
if (IOT_PLC_UPGRADE_INIT != upgrade_info->upgrade_state) {
|
|
dest->error_code = UPGRADE_DATA_STA_IN_PROGRESS;
|
|
} else {
|
|
dest->error_code = 0;
|
|
}
|
|
iot_mac_addr_cpy(dest->entry.addr, mac);
|
|
upgrade_info->dest_info.entry_ptr[idx] = dest;
|
|
iot_addr_hash_table_add(upgrade_info->dest_info.table,
|
|
&dest->entry);
|
|
upgrade_info->dest_info.dst_total_num++;
|
|
} else {
|
|
iot_printf("add dest failed, alloc failed\n");
|
|
}
|
|
|
|
return dest;
|
|
}
|
|
|
|
uint16_t cli_upgrade_add_upgrade_list_dest_info(
|
|
uint8_t *node_mac, uint16_t node_cnt, uint8_t is_renew)
|
|
{
|
|
uint16_t i;
|
|
iot_plc_upgrade_dest_desc_t *desc;
|
|
uint16_t cnt = 0;
|
|
|
|
if (is_renew) {
|
|
for (i = 0; i < IOT_PLC_UPGRADE_PHASE_THREE_MAX_SAT_CNT; i++) {
|
|
upgrade_info->dest_info.upgrading_list[i] = NULL;
|
|
}
|
|
upgrade_info->dst_list_idx = 0;
|
|
}
|
|
for (i = 0; i < node_cnt; i++) {
|
|
desc = cli_upgrade_add_dest_info(node_mac + (i * IOT_MAC_ADDR_LEN));
|
|
if (desc) {
|
|
upgrade_info->dest_info.upgrading_list[upgrade_info->dst_list_idx] =
|
|
desc;
|
|
upgrade_info->dst_list_idx++;
|
|
cnt++;
|
|
}
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
/* cco destroy buffer for remote upgrade */
|
|
void cli_remote_upgrade_destroy_buffer()
|
|
{
|
|
if (upgrade_info->file_data) {
|
|
os_mem_free(upgrade_info->file_data);
|
|
upgrade_info->file_data = NULL;
|
|
upgrade_info->pib_data = NULL;
|
|
upgrade_info->fw_data = NULL;
|
|
upgrade_info->cus_data = NULL;
|
|
}
|
|
}
|
|
|
|
/* cco init dest info */
|
|
void cli_remote_upgrade_init_dest_info()
|
|
{
|
|
if (upgrade_info->dest_info.table) {
|
|
cli_remote_upgrade_destroy_dest_info();
|
|
}
|
|
upgrade_info->dest_info.dst_total_num = 0;
|
|
upgrade_info->dest_info.dst_transferred_num = 0;
|
|
upgrade_info->dest_info.dest_idx = 0;
|
|
upgrade_info->dest_info.upgrading_list_idx = 0;
|
|
upgrade_info->dest_info.query_node_timeout = 0;
|
|
upgrade_info->dest_info.entry_ptr = (iot_plc_upgrade_dest_desc_t **)
|
|
os_mem_malloc(IOT_CLI_MID, IOT_PLC_UPGRADE_STATUS_ITEM_MAX_CNT *
|
|
sizeof(iot_plc_upgrade_dest_desc_t *));
|
|
IOT_ASSERT(upgrade_info->dest_info.entry_ptr);
|
|
upgrade_info->dest_info.table = iot_addr_hash_table_create(
|
|
IOT_CLI_MID, IOT_PLC_UPGRADE_STATUS_ITEM_MAX_CNT,
|
|
sizeof(iot_plc_upgrade_dest_desc_t),
|
|
IOT_PLC_UPGRADE_STATUS_TABLE_SIZE);
|
|
IOT_ASSERT(upgrade_info->dest_info.table);
|
|
}
|
|
|
|
/* reset cli upgrade dest info when begin cli upgrade */
|
|
void cli_remote_upgrade_dest_info_reset()
|
|
{
|
|
uint16_t i;
|
|
iot_plc_upgrade_dest_desc_t *entry_ptr;
|
|
|
|
/* init node upgrade info */
|
|
for (i = 0; i < IOT_PLC_UPGRADE_STATUS_ITEM_MAX_CNT; i++) {
|
|
entry_ptr = upgrade_info->dest_info.entry_ptr[i];
|
|
if (!entry_ptr) {
|
|
continue;
|
|
}
|
|
entry_ptr->status = IOT_PLC_UPGRADE_INIT;
|
|
entry_ptr->error_code = 0;
|
|
entry_ptr->percentage = 0;
|
|
entry_ptr->reported_percentage = 0;
|
|
entry_ptr->start_retry_times = 0;
|
|
entry_ptr->updated = 0;
|
|
entry_ptr->error_code = UPGRADE_DATA_STA_IN_PROGRESS;
|
|
entry_ptr->upgrade_type = CLI_UPGRADE_TYPE_UNKNOWN;
|
|
}
|
|
/* init cli upgrade info */
|
|
upgrade_info->dest_info.dst_transferred_num = 0;
|
|
upgrade_info->dest_info.dest_idx = 0;
|
|
upgrade_info->dest_info.upgrading_list_idx = 0;
|
|
upgrade_info->dest_info.query_node_timeout = 0;
|
|
}
|
|
|
|
/* cco destroy dest info */
|
|
void cli_remote_upgrade_destroy_dest_info()
|
|
{
|
|
for (uint16_t i = 0; i < upgrade_info->dest_info.dst_total_num; i++) {
|
|
if (upgrade_info->dest_info.entry_ptr[i]) {
|
|
iot_addr_hash_table_free(upgrade_info->dest_info.table,
|
|
(iot_addr_hash_entry_t *)
|
|
upgrade_info->dest_info.entry_ptr[i]);
|
|
}
|
|
}
|
|
if (upgrade_info->dest_info.entry_ptr) {
|
|
os_mem_free(upgrade_info->dest_info.entry_ptr);
|
|
upgrade_info->dest_info.entry_ptr = NULL;
|
|
}
|
|
if (upgrade_info->dest_info.table) {
|
|
iot_addr_hash_table_delete(upgrade_info->dest_info.table);
|
|
upgrade_info->dest_info.table = NULL;
|
|
}
|
|
}
|
|
|
|
/* cco send stop report upgrade result command to target pco/sta */
|
|
void cli_remote_upgrade_send_stop_rpt_notify(uint8_t *dest_mac)
|
|
{
|
|
iot_plc_sg_upgrade_stop_rpt_dl_t stop_rpt_dl = { 0 };
|
|
|
|
stop_rpt_dl.flag = 1;
|
|
|
|
iot_printf("%s set sta: %x:%x:%x:%x:%x:%x stop report\n", __FUNCTION__,
|
|
dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3], dest_mac[4],
|
|
dest_mac[5]);
|
|
iot_cli_module_send_data_with_retry(IOT_PLC_MSG_TYPE_UNICAST,
|
|
IOT_PLC_UPGRADE_RETRY_COUNT, CLI_MODULEID_HOSTINTERFACE,
|
|
CLI_MSGID_SET_STOP_UPGRADE_RPT, NULL, dest_mac, (uint8_t *)&stop_rpt_dl,
|
|
sizeof(stop_rpt_dl));
|
|
}
|
|
|
|
/* cco stop remote upgrade */
|
|
void cli_remote_upgrade_coo_stop()
|
|
{
|
|
//stop all logic
|
|
//todo: add stop one sta logic
|
|
upgrade_info->dest_info.dest_idx = upgrade_info->dest_info.dst_total_num;
|
|
cli_upgrade_reset_timer(0, 0);
|
|
if (upgrade_info->full_bitmap) {
|
|
os_mem_free(upgrade_info->full_bitmap);
|
|
upgrade_info->full_bitmap = NULL;
|
|
}
|
|
iot_printf("plc_upgrade:cco stop timer\n");
|
|
}
|
|
|
|
/* query next broadcast block idx */
|
|
static bool_t cli_remote_upgrade_next_block_idx(bool_t first)
|
|
{
|
|
bool_t next = true;
|
|
|
|
if (first) {
|
|
upgrade_info->block_idx = 0;
|
|
if (upgrade_info->pib_size) {
|
|
upgrade_info->current_file_type = UPGRADE_DATA_TYPE_PIB;
|
|
} else if (upgrade_info->fw_size) {
|
|
upgrade_info->current_file_type = UPGRADE_DATA_TYPE_FW;
|
|
} else if (upgrade_info->cus_size) {
|
|
upgrade_info->current_file_type = UPGRADE_DATA_TYPE_CUS;
|
|
} else {
|
|
next = false;
|
|
}
|
|
} else {
|
|
upgrade_info->block_idx++;
|
|
if ((UPGRADE_DATA_TYPE_PIB == upgrade_info->current_file_type) &&
|
|
(upgrade_info->pib_blocks == upgrade_info->block_idx)) {
|
|
upgrade_info->block_idx = 0;
|
|
if (upgrade_info->fw_size) {
|
|
upgrade_info->current_file_type = UPGRADE_DATA_TYPE_FW;
|
|
} else if (upgrade_info->cus_size) {
|
|
upgrade_info->current_file_type = UPGRADE_DATA_TYPE_CUS;
|
|
} else {
|
|
next = false;
|
|
}
|
|
} else if ((UPGRADE_DATA_TYPE_FW == upgrade_info->current_file_type) &&
|
|
(upgrade_info->fw_blocks == upgrade_info->block_idx)) {
|
|
if (upgrade_info->cus_size) {
|
|
upgrade_info->block_idx = 0;
|
|
upgrade_info->current_file_type = UPGRADE_DATA_TYPE_CUS;
|
|
} else {
|
|
next = false;
|
|
}
|
|
} else if ((UPGRADE_DATA_TYPE_CUS == upgrade_info->current_file_type) &&
|
|
(upgrade_info->cus_blocks == upgrade_info->block_idx)) {
|
|
next = false;
|
|
}
|
|
}
|
|
|
|
return next;
|
|
}
|
|
|
|
uint8_t cli_remote_upgrade_calculate_bcast_max_times()
|
|
{
|
|
uint8_t max_times =
|
|
(uint8_t)upgrade_info->phase_one_broadcast_times;
|
|
|
|
if (!max_times) {
|
|
max_times = IOT_PLC_UPGRADE_BCAST_TIMES_LEV1;
|
|
if (upgrade_info->dest_info.dst_total_num >
|
|
IOT_PLC_UPGRADE_BCAST_STA_THRESHOLD2) {
|
|
max_times = IOT_PLC_UPGRADE_BCAST_TIMES_LEV3;
|
|
} else if (upgrade_info->dest_info.dst_total_num >
|
|
IOT_PLC_UPGRADE_BCAST_STA_THRESHOLD) {
|
|
max_times = IOT_PLC_UPGRADE_BCAST_TIMES_LEV2;
|
|
}
|
|
}
|
|
|
|
if (max_times > IOT_PLC_UPGRADE_BCAST_TIMES_LEV4) {
|
|
max_times = IOT_PLC_UPGRADE_BCAST_TIMES_LEV4;
|
|
}
|
|
|
|
iot_printf("calculate bcast max times %d\n", max_times);
|
|
|
|
return max_times;
|
|
}
|
|
|
|
/* cco report broadcast progress to plc mgr */
|
|
static void cli_remote_upgrade_report_broadcast_progress()
|
|
{
|
|
uint8_t dest[IOT_MAC_ADDR_LEN] = { 0 };
|
|
uint16_t blocks = upgrade_info->block_idx + 1;
|
|
uint16_t total_blocks =
|
|
upgrade_info->pib_blocks + upgrade_info->fw_blocks;
|
|
|
|
if (UPGRADE_DATA_TYPE_FW == upgrade_info->current_file_type) {
|
|
blocks += upgrade_info->pib_blocks;
|
|
}
|
|
|
|
if ((blocks % IOT_PLC_UPGRADE_PROGRESS_BLOCKS_INTERVAL) == 0) {
|
|
uint8_t progress = (uint8_t)((blocks + total_blocks *
|
|
upgrade_info->broadcast_times) *
|
|
UPGRADE_BDCT_PROGRESS_IN_BCAST_PHASE / (total_blocks *
|
|
cli_remote_upgrade_calculate_bcast_max_times()));
|
|
|
|
cli_remote_upgrade_send_upgrade_progress(progress, dest);
|
|
}
|
|
}
|
|
|
|
static uint32_t cli_remote_upgrade_calculate_broadcast_time()
|
|
{
|
|
uint32_t base_interval_tm;
|
|
|
|
#if HW_PLATFORM == HW_PLATFORM_SIMU
|
|
base_interval_tm = IOT_PLC_UPGRADE_CCO_BCAST_TIME;
|
|
#else
|
|
if (upgrade_info->dest_info.dst_total_num <=
|
|
IOT_PLC_UPGRADE_CCO_MIN_BCAST_NODE_CNT) {
|
|
base_interval_tm = IOT_PLC_UPGRADE_CCO_MIN_BCAST_TIME;
|
|
} else {
|
|
base_interval_tm = IOT_PLC_UPGRADE_CCO_SHORT_BCAST_TIME;
|
|
}
|
|
#endif
|
|
base_interval_tm = (uint32_t)(base_interval_tm +
|
|
upgrade_info->dest_info.dst_total_num *
|
|
IOT_PLC_UPGRADE_STA_CNT_ADJ_VALUE + IOT_PLC_UPGRADE_PCO_ADJ_TIME *
|
|
upgrade_info->level_one_pco_count);
|
|
return base_interval_tm;
|
|
}
|
|
|
|
void cli_remote_upgrade_bcast_tx_done()
|
|
{
|
|
uint32_t interval = 0;
|
|
if (upgrade_info->bcast_wait_flag) {
|
|
upgrade_info->bcast_wait_flag = 0;
|
|
interval = cli_remote_upgrade_calculate_broadcast_time();
|
|
cli_upgrade_reset_timer(1, interval);
|
|
}
|
|
}
|
|
/* cco send broadcast data */
|
|
void cli_remote_upgrade_cco_broadcast_data(bool_t first)
|
|
{
|
|
uint8_t ctrl_type = UPGRADE_REMOTE_ALL_PHASE1_DATA;
|
|
|
|
if (upgrade_info->upgrade_type == IOT_PLC_UPGRADE_STA_LIST) {
|
|
ctrl_type = UPGRADE_REMOTE_STA_LIST_DATA;
|
|
}
|
|
|
|
if (cli_remote_upgrade_next_block_idx(first)) {
|
|
uint8_t dest[IOT_MAC_ADDR_LEN] = { 0 };
|
|
uint16_t idx[1];
|
|
idx[0] = upgrade_info->block_idx;
|
|
|
|
cli_remote_upgrade_send_data(IOT_PLC_MSG_TYPE_BCAST,
|
|
upgrade_info->broadcast_retry_times, dest,
|
|
upgrade_info->upgrade_id, upgrade_info->current_file_type,
|
|
ctrl_type, upgrade_info->remote_block_size, idx, 1,
|
|
UPGRADE_DATA_FORWARD_INVALID,
|
|
cli_remote_upgrade_bcast_tx_done_callback);
|
|
|
|
if (first) {
|
|
if (!os_is_timer_active(upgrade_info->upgrade_timer)) {
|
|
uint32_t broadcast_interval =
|
|
cli_remote_upgrade_calculate_broadcast_time();
|
|
iot_printf("plc_upgrade: start broadcast data"
|
|
" interval %d, retry times %d\n",
|
|
broadcast_interval, upgrade_info->broadcast_retry_times);
|
|
os_start_timer(upgrade_info->upgrade_timer,
|
|
broadcast_interval);
|
|
}
|
|
} else {
|
|
cli_remote_upgrade_report_broadcast_progress();
|
|
}
|
|
} else {
|
|
upgrade_info->broadcast_times++;
|
|
iot_printf("plc_upgrade:cco bcast time %d phase1\n",
|
|
upgrade_info->broadcast_times);
|
|
if (upgrade_info->broadcast_times <
|
|
cli_remote_upgrade_calculate_bcast_max_times()) {
|
|
cli_remote_upgrade_cco_broadcast_data(true);
|
|
} else {
|
|
cli_upgrade_reset_timer(0, 0);
|
|
iot_printf("plc_upgrade:coo stop broadcast\n");
|
|
|
|
os_delay(5000);
|
|
iot_printf("plc_upgrade:phase 2\n");
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_TRANSFERRED;
|
|
|
|
iot_plc_query_neighbor_dev(host_config->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT, 0, 1,
|
|
IOT_PLC_QUERY_TOPO_START_AS_TEI);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void cli_remote_upgrade_prepare()
|
|
{
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_STARTING;
|
|
upgrade_info->fw_blocks = (uint16_t)iot_ceil(upgrade_info->fw_size,
|
|
upgrade_info->remote_block_size);
|
|
upgrade_info->pib_blocks = (uint16_t)iot_ceil(upgrade_info->pib_size,
|
|
upgrade_info->remote_block_size);
|
|
upgrade_info->cus_blocks = (uint16_t)iot_ceil(upgrade_info->cus_size,
|
|
upgrade_info->remote_block_size);
|
|
|
|
iot_printf("cco prepare for upgrade pib blocks %d fw blocks %d"
|
|
"cus blocks %d\n", upgrade_info->pib_blocks, upgrade_info->fw_blocks,
|
|
upgrade_info->cus_blocks);
|
|
//create new upgrade id
|
|
upgrade_info->upgrade_id++;
|
|
}
|
|
|
|
/* cco send upgrade broadcast start to sta list */
|
|
uint32_t cli_remote_upgrade_broadcast_start_sta_list(bool_t first)
|
|
{
|
|
uint32_t result = ERR_OK;
|
|
|
|
if (first) {
|
|
upgrade_info->dest_info.upgrading_list_idx = 0;
|
|
cli_upgrade_reset_timer(1, upgrade_info->time_window);
|
|
iot_printf("upgrade start time window: %lu\n",
|
|
upgrade_info->time_window);
|
|
}
|
|
result = cli_remote_upgrade_multi_node_start_notify(IOT_PLC_MSG_TYPE_BCAST,
|
|
UPGRADE_START_UPGRADE_PHASE1);
|
|
if ((!first) && result == ERR_OK) {
|
|
upgrade_info->broadcast_times++;
|
|
iot_printf("plc_upgrade:cco bcast start cmd time %d phase1\n",
|
|
upgrade_info->broadcast_times);
|
|
if ((cli_remote_upgrade_find_init_dest_from_idx(0) != NULL) &&
|
|
(upgrade_info->broadcast_times <
|
|
IOT_PLC_UPGRADE_BROADCAST_TIMES_CNT)) {
|
|
cli_remote_upgrade_broadcast_start_sta_list(true);
|
|
} else {
|
|
iot_printf("plc_upgrade:coo stop broadcast start upgrade cmd\n");
|
|
cli_upgrade_reset_timer(0, 0);
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_STARTED;
|
|
/*
|
|
* list node upgrade, begin broadcast upgrade data
|
|
* init broadcast upgrade file count
|
|
*/
|
|
upgrade_info->broadcast_times = 0;
|
|
iot_printf("plc_upgrade:coo begin broadcast upgrade data\n");
|
|
cli_remote_upgrade_cco_broadcast_data(true);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/* cco start sta list to start upgrade */
|
|
void cli_remote_upgrade_sta_list_start()
|
|
{
|
|
cli_remote_upgrade_prepare();
|
|
|
|
cli_remote_upgrade_initialize_latest_block();
|
|
//init broadcast start upgrade count
|
|
upgrade_info->broadcast_times = 0;
|
|
upgrade_info->action_times = 0;
|
|
upgrade_info->last_timer_time = 0;
|
|
upgrade_info->time_window =
|
|
cli_remote_upgrade_calculate_time_window(upgrade_info->dst_list_idx);
|
|
iot_printf("plc_upgrade:coo start upgrade timer for broadcast data, "
|
|
"timewindow: %lu\n",
|
|
upgrade_info->time_window);
|
|
cli_remote_upgrade_broadcast_start_sta_list(true);
|
|
}
|
|
|
|
/* cco start remote upgrade */
|
|
void cli_remote_upgrade_all_sta_start()
|
|
{
|
|
cli_remote_upgrade_prepare();
|
|
|
|
//start broadcast
|
|
upgrade_info->broadcast_times = 0;
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_STARTED;
|
|
cli_remote_upgrade_cco_broadcast_data(true);
|
|
}
|
|
|
|
/* add status to list for report timer */
|
|
void cli_remote_upgrade_add_report_status(
|
|
iot_plc_upgrade_dest_desc_t *status)
|
|
{
|
|
if (status) {
|
|
if ((!status->updated) &&
|
|
(IOT_PLC_UPGRADE_LATEST_STATUS_MAX_CNT >
|
|
upgrade_info->dest_info.dest_idx))
|
|
{
|
|
status->updated = true;
|
|
|
|
iot_printf("add status upgrade, %d, %d ",\
|
|
"mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
|
|
status->percentage, status->error_code,
|
|
status->entry.addr[0], status->entry.addr[1],
|
|
status->entry.addr[2], status->entry.addr[3],
|
|
status->entry.addr[4], status->entry.addr[5]);
|
|
|
|
upgrade_info->dest_info.latest_status_list[
|
|
upgrade_info->dest_info.dest_idx] = status;
|
|
upgrade_info->dest_info.dest_idx++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* coo handle remote upgrade start ack from sta */
|
|
void cli_remote_upgrade_start_ack(
|
|
uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
(void)src_mac;
|
|
iot_plc_upgrade_dest_desc_t * dest = NULL;
|
|
iot_plc_upgrade_start_ul_t *ack;
|
|
ack = (iot_plc_upgrade_start_ul_t*)buffer;
|
|
|
|
if (!ack){
|
|
IOT_ASSERT(ack);
|
|
return;
|
|
}
|
|
IOT_ASSERT(bufferlen >= sizeof(*ack));
|
|
|
|
cli_upgrade_print_mac_info(ack->dst);
|
|
|
|
dest = (iot_plc_upgrade_dest_desc_t *)
|
|
iot_addr_hash_table_find(upgrade_info->dest_info.table, ack->dst);
|
|
if (dest) {
|
|
if (UPGRADE_START_OK == ack->result) {
|
|
dest->status = IOT_PLC_UPGRADE_STARTED;
|
|
} else {
|
|
if ((dest->status != IOT_PLC_UPGRADE_TRANSFERRED) &&
|
|
(dest->status != IOT_PLC_UPGRADE_FAILED) &&
|
|
(dest->status != IOT_PLC_UPGRADE_START_FAIL)) {
|
|
iot_printf("upgrade result, mac: %02X:%02X:%02X:%02X:%02X:%02X,"
|
|
" result %d\n",
|
|
dest->entry.addr[0], dest->entry.addr[1],
|
|
dest->entry.addr[2], dest->entry.addr[3],
|
|
dest->entry.addr[4], dest->entry.addr[5],
|
|
UPGRADE_START_END_SINCE_COMPLETED == ack->result);
|
|
}
|
|
|
|
dest->status = IOT_PLC_UPGRADE_START_FAIL;
|
|
dest->error_code = UPGRADE_DATA_OTHER_ERROR;
|
|
if (UPGRADE_START_END_SINCE_COMPLETED == ack->result) {
|
|
if (dest->status != IOT_PLC_UPGRADE_TRANSFERRED) {
|
|
upgrade_info->dest_info.dst_transferred_num++;
|
|
}
|
|
dest->status = IOT_PLC_UPGRADE_TRANSFERRED;
|
|
dest->error_code = UPGRADE_DATA_SUCCESS;
|
|
}
|
|
|
|
cli_remote_upgrade_add_report_status(dest);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* cco check sta recv done */
|
|
static uint8_t cli_remote_upgrade_check_sta_recv_done(uint8_t *bm, uint16_t cnt)
|
|
{
|
|
uint8_t result = 1;
|
|
uint16_t byte_count = 0;
|
|
uint8_t over_bit = 0;
|
|
|
|
byte_count = (cnt + 7) >> 3;
|
|
over_bit = (uint8_t)((byte_count << 3) - cnt);
|
|
/* last byte redundant bit set 1 */
|
|
bm[byte_count - 1] |= 0xff << (8 - over_bit);
|
|
|
|
if (iot_bitmap_cbz(bm, byte_count) == 0) {
|
|
result = 1;
|
|
} else {
|
|
result = 0;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
/* cco handle sta info ack from sta */
|
|
void cli_remote_upgrade_node_info_rsp(uint8_t *buffer, uint32_t bufferlen,
|
|
uint8_t *src_mac)
|
|
{
|
|
(void)src_mac;
|
|
uint8_t err_code = 0;
|
|
uint16_t sta_written_block = 0;
|
|
uint16_t bm_size = 0;
|
|
iot_plc_upgrade_query_sta_info_ul_t *ack =
|
|
(iot_plc_upgrade_query_sta_info_ul_t *)buffer;
|
|
iot_plc_upgrade_dest_desc_t *dest;
|
|
|
|
if (bufferlen < sizeof(*ack)) {
|
|
err_code = 1;
|
|
goto err;
|
|
}
|
|
|
|
iot_printf("plc_upgrade:response node-%02X:%02X:%02X:%02X:%02X:%02X, "
|
|
"state:%d\n", ack->dst[0], ack->dst[1], ack->dst[2], ack->dst[3],
|
|
ack->dst[4], ack->dst[5], ack->state);
|
|
dest = (iot_plc_upgrade_dest_desc_t *)iot_addr_hash_table_find(
|
|
upgrade_info->dest_info.table, ack->dst);
|
|
if (dest == NULL) {
|
|
err_code = 2;
|
|
goto err;
|
|
}
|
|
|
|
if (iot_mac_addr_cmp(ack->dst, upgrade_info->sta_mac) == 0) {
|
|
if (ack->state == IOT_PLC_UPGRADE_TRANSFERRED) {
|
|
dest->status = IOT_PLC_UPGRADE_TRANSFERRED;
|
|
dest->error_code = UPGRADE_DATA_SUCCESS;
|
|
dest->percentage = 100;
|
|
}
|
|
|
|
err_code = 3;
|
|
goto err;
|
|
}
|
|
|
|
if(upgrade_info->resend_data_state == CLI_SEND_DATA) {
|
|
err_code = 4;
|
|
goto err;
|
|
}
|
|
|
|
upgrade_info->node_response_flag = 1;
|
|
if (ack->state == IOT_PLC_UPGRADE_INIT) {
|
|
/* the current node not started to upgrade, query the next node */
|
|
upgrade_info->resend_data_state = CLI_QUERY_NODE;
|
|
os_mem_set(upgrade_info->sta_mac, 0, IOT_MAC_ADDR_LEN);
|
|
cli_remote_upgrade_send_start_notify(IOT_PLC_MSG_TYPE_UNICAST,
|
|
dest->entry.addr, dest->entry.addr, UPGRADE_START_UPGRADE_PHASE1);
|
|
goto err;
|
|
}
|
|
|
|
bm_size = (ack->cnt + 7) >> 3;
|
|
sta_written_block = (uint16_t)iot_bitmap_cbs(ack->bm, bm_size);
|
|
dest->percentage = (uint8_t)(sta_written_block * 100 /
|
|
(upgrade_info->pib_blocks + upgrade_info->fw_blocks));
|
|
|
|
if (cli_remote_upgrade_check_sta_recv_done(ack->bm, ack->cnt) ||
|
|
ack->state == IOT_PLC_UPGRADE_TRANSFERRED) {
|
|
dest->status = IOT_PLC_UPGRADE_TRANSFERRED;
|
|
dest->error_code = UPGRADE_DATA_SUCCESS;
|
|
dest->percentage = 100;
|
|
upgrade_info->resend_data_state = CLI_QUERY_NODE;
|
|
os_mem_set(upgrade_info->sta_mac, 0, IOT_MAC_ADDR_LEN);
|
|
iot_printf("%02x:%02x:%02x:%02x:%02x:%02x: upgrade complete\n",
|
|
dest->entry.addr[0], dest->entry.addr[1], dest->entry.addr[2],
|
|
dest->entry.addr[3], dest->entry.addr[4], dest->entry.addr[5]);
|
|
} else {
|
|
os_mem_cpy(upgrade_info->full_bitmap, ack->bm, bm_size);
|
|
upgrade_info->resend_data_state = CLI_SEND_DATA;
|
|
dest->upgrade_type = CLI_UPGRADE_TYPE_V1;
|
|
}
|
|
|
|
err:
|
|
iot_printf("plc_upgrade: %s , resend state:%d err:%d \n", __FUNCTION__,
|
|
upgrade_info->resend_data_state, err_code);
|
|
}
|
|
|
|
/* cco send upgrade result to plc manager */
|
|
void cli_remote_upgrade_result(
|
|
uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
(void)src_mac;
|
|
iot_plc_upgrade_dest_desc_t * dest = NULL;
|
|
iot_plc_upgrade_result_ul_t *result;
|
|
result = (iot_plc_upgrade_result_ul_t *)buffer;
|
|
|
|
if ((!result) || (bufferlen < sizeof(*result))) {
|
|
iot_printf("%s param error", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if (!upgrade_info->dest_info.table) {
|
|
return;
|
|
}
|
|
|
|
dest = (iot_plc_upgrade_dest_desc_t *)iot_addr_hash_table_find(
|
|
upgrade_info->dest_info.table, result->dst);
|
|
if (dest) {
|
|
if ((dest->status != IOT_PLC_UPGRADE_TRANSFERRED) &&
|
|
(dest->status != IOT_PLC_UPGRADE_FAILED)) {
|
|
upgrade_info->sta_upgrade_active = 1;
|
|
iot_printf("upgrade result, mac: %02X:%02X:%02X:%02X:%02X:%02X,"
|
|
" result %d\n",
|
|
dest->entry.addr[0], dest->entry.addr[1],
|
|
dest->entry.addr[2], dest->entry.addr[3],
|
|
dest->entry.addr[4], dest->entry.addr[5],
|
|
result->error_code);
|
|
}
|
|
|
|
if (UPGRADE_DATA_SUCCESS == result->error_code) {
|
|
if (dest->status != IOT_PLC_UPGRADE_TRANSFERRED) {
|
|
upgrade_info->dest_info.dst_transferred_num++;
|
|
}
|
|
cli_remote_upgrade_send_stop_rpt_notify(result->dst);
|
|
dest->status = IOT_PLC_UPGRADE_TRANSFERRED;
|
|
dest->error_code = result->error_code;
|
|
if (upgrade_info->control_upgrade_flag) {
|
|
/* the current node upgrade complete, resend next node */
|
|
if (iot_mac_addr_cmp(upgrade_info->sta_mac, result->dst)) {
|
|
os_mem_set(upgrade_info->sta_mac, 0, IOT_METER_ADDR_LEN);
|
|
upgrade_info->node_response_flag = 1;
|
|
upgrade_info->resend_data_state = CLI_QUERY_NODE;
|
|
}
|
|
}
|
|
} else {
|
|
dest->status = IOT_PLC_UPGRADE_FAILED;
|
|
dest->error_code = result->error_code;
|
|
}
|
|
|
|
cli_remote_upgrade_add_report_status(dest);
|
|
}
|
|
}
|
|
|
|
/* cco send upgrade progress to plc manager */
|
|
void cli_remote_upgrade_progress(
|
|
uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
(void)src_mac;
|
|
iot_plc_upgrade_dest_desc_t * dest = NULL;
|
|
iot_plc_upgrade_progress_ul_t *progress;
|
|
progress = (iot_plc_upgrade_progress_ul_t *)buffer;
|
|
|
|
if ((!progress) || (bufferlen < sizeof(*progress))) {
|
|
iot_printf("%s param error", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if (!upgrade_info->dest_info.table) {
|
|
return;
|
|
}
|
|
|
|
upgrade_info->sta_upgrade_active = 1;
|
|
|
|
dest = (iot_plc_upgrade_dest_desc_t *)iot_addr_hash_table_find(
|
|
upgrade_info->dest_info.table, progress->dst);
|
|
if (dest) {
|
|
dest->percentage = progress->progress;
|
|
dest->error_code = UPGRADE_DATA_STA_IN_PROGRESS;
|
|
|
|
cli_remote_upgrade_add_report_status(dest);
|
|
}
|
|
}
|
|
|
|
/* initialize upgrading list */
|
|
void cli_remote_upgrade_initialize_upgrading_list()
|
|
{
|
|
uint16_t index = 0;
|
|
upgrade_info->dest_info.upgrading_list_idx = 0;
|
|
for (uint16_t i = 0; i < upgrade_info->dest_info.dst_total_num; i++) {
|
|
iot_plc_upgrade_dest_desc_t *desc =
|
|
upgrade_info->dest_info.entry_ptr[i];
|
|
// add uncompleted sta into
|
|
if (desc && (IOT_PLC_UPGRADE_TRANSFERRED != desc->status &&
|
|
(index < IOT_PLC_UPGRADE_PHASE_THREE_MAX_SAT_CNT))) {
|
|
upgrade_info->dest_info.upgrading_list[index] = desc;
|
|
index++;
|
|
}
|
|
}
|
|
upgrade_info->dst_list_idx = index;
|
|
iot_printf("plc_upgrade:cco initialize upgrading"
|
|
" list for phase3 %lu\n", index);
|
|
}
|
|
|
|
static uint8_t cli_remote_upgrade_conform_node_mode(
|
|
iot_plc_upgrade_dest_desc_t *dest, uint8_t mode)
|
|
{
|
|
uint8_t result = 0;
|
|
|
|
if (mode == CLI_FIND_START_NODE) {
|
|
if ((dest->upgrade_type == CLI_UPGRADE_TYPE_UNKNOWN) ||
|
|
(dest->upgrade_type == CLI_UPGRADE_TYPE_V0)) {
|
|
result = 1;
|
|
}
|
|
} else {
|
|
if ((dest->upgrade_type == CLI_UPGRADE_TYPE_UNKNOWN) ||
|
|
(dest->upgrade_type == CLI_UPGRADE_TYPE_V1)) {
|
|
result = 1;
|
|
}
|
|
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static iot_plc_upgrade_dest_desc_t *
|
|
cli_remote_upgrade_find_uncompleted_dest_from_idx(uint16_t start_idx,
|
|
uint8_t mode)
|
|
{
|
|
iot_plc_upgrade_dest_desc_t *dest = NULL;
|
|
while ((start_idx < IOT_PLC_UPGRADE_PHASE_THREE_MAX_SAT_CNT) &&
|
|
upgrade_info->dest_info.upgrading_list[start_idx]) {
|
|
if (IOT_PLC_UPGRADE_TRANSFERRED !=
|
|
upgrade_info->dest_info.upgrading_list[start_idx]->status) {
|
|
if (cli_remote_upgrade_conform_node_mode(
|
|
upgrade_info->dest_info.upgrading_list[start_idx], mode)) {
|
|
dest = upgrade_info->dest_info.upgrading_list[start_idx];
|
|
upgrade_info->dest_info.upgrading_list_idx = start_idx + 1;
|
|
break;
|
|
}
|
|
}
|
|
start_idx++;
|
|
}
|
|
return dest;
|
|
}
|
|
|
|
static iot_plc_upgrade_dest_desc_t *cli_remote_upgrade_find_uncompleted_dest(
|
|
uint8_t mode)
|
|
{
|
|
iot_plc_upgrade_dest_desc_t *dest = NULL;
|
|
dest = cli_remote_upgrade_find_uncompleted_dest_from_idx(
|
|
upgrade_info->dest_info.upgrading_list_idx, mode);
|
|
|
|
if (!dest) {
|
|
dest = cli_remote_upgrade_find_uncompleted_dest_from_idx(0, mode);
|
|
}
|
|
|
|
return dest;
|
|
}
|
|
|
|
/* get resend phase time window */
|
|
uint16_t cli_remote_upgrade_get_resend_time_window(uint16_t node_cnt)
|
|
{
|
|
uint16_t result = IOT_PLC_UPGRADE_CCO_SHORT_BCAST_TIME;
|
|
|
|
if (node_cnt > 500) {
|
|
result += ((node_cnt - 200) + (node_cnt - 500) * 2);
|
|
} else if (node_cnt > 300) {
|
|
result += ((node_cnt - 100) + (node_cnt - 300) * 2);
|
|
} else if (node_cnt > 50) {
|
|
result += (node_cnt - 50) * 2;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static uint8_t cli_remote_upgrade_find_resend_dest()
|
|
{
|
|
uint8_t query_cnt = 0;
|
|
iot_plc_upgrade_dest_desc_t *dest = NULL;
|
|
|
|
dest = cli_remote_upgrade_find_uncompleted_dest(CLI_FIND_QUERY_NODE);
|
|
if (dest) {
|
|
iot_mac_addr_cpy(upgrade_info->sta_mac, dest->entry.addr);
|
|
query_cnt++;
|
|
iot_printf("plc_upgrade: find a resend node -"
|
|
"%02X:%02X:%02X:%02X:%02X:%02X\n", dest->entry.addr[0],
|
|
dest->entry.addr[1], dest->entry.addr[2], dest->entry.addr[3],
|
|
dest->entry.addr[4], dest->entry.addr[5]);
|
|
}
|
|
|
|
return query_cnt;
|
|
}
|
|
|
|
static void cli_remote_upgrade_query_node_bitmap(uint16_t start, uint16_t cnt)
|
|
{
|
|
iot_plc_upgrade_query_sta_info_dl_t query_dl = {0};
|
|
|
|
if (iot_mac_addr_valid(upgrade_info->sta_mac) == 0) {
|
|
iot_printf("plc_upgrade: %s dest mac invalid\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
query_dl.upgrade_id = upgrade_info->upgrade_id;
|
|
query_dl.start_idx = start;
|
|
query_dl.cnt = cnt;
|
|
iot_mac_addr_cpy(query_dl.dst, upgrade_info->sta_mac);
|
|
|
|
iot_cli_module_send_data_with_retry(IOT_PLC_MSG_TYPE_UNICAST,
|
|
IOT_PLC_UPGRADE_PHASE_THREE_RETRY_TIMES,
|
|
CLI_MODULEID_HOSTINTERFACE,
|
|
CLI_MSGID_UPGRADE_NODE_INFO_QUERY, host_config->mac_addr,
|
|
upgrade_info->sta_mac, (uint8_t*)&query_dl, sizeof(query_dl));
|
|
iot_printf("plc_upgrade: cco send query node info cmd\n");
|
|
}
|
|
|
|
static uint16_t cli_remote_upgrade_find_miss_block(uint8_t *file_type)
|
|
{
|
|
uint16_t block_index = 0;
|
|
uint16_t bm_size = 0;
|
|
uint16_t fw_blocks = upgrade_info->fw_blocks;
|
|
uint16_t pib_blocks = upgrade_info->pib_blocks;
|
|
|
|
bm_size = (pib_blocks + fw_blocks + 7) >> 3;
|
|
block_index =
|
|
(uint16_t)iot_bitmap_ffz_and_s(upgrade_info->full_bitmap, bm_size);
|
|
|
|
if (block_index > 0) {
|
|
if (block_index <= pib_blocks) {
|
|
*file_type = UPGRADE_DATA_TYPE_PIB;
|
|
block_index -= 1;
|
|
} else if (block_index <= (fw_blocks + pib_blocks)) {
|
|
*file_type = UPGRADE_DATA_TYPE_FW;
|
|
block_index -= pib_blocks + 1;
|
|
}
|
|
} else {
|
|
if (upgrade_info->full_bitmap[0] & 0x01) {
|
|
/* if block index is 0,but bitmap bit0 is 1, return invalid index */
|
|
block_index = IOT_PLC_UPGRADE_INVALID_BLOCK_INDEX;
|
|
}
|
|
}
|
|
|
|
return block_index;
|
|
}
|
|
|
|
static uint8_t cli_remote_upgrade_send_miss_block()
|
|
{
|
|
uint8_t file_type = UPGRADE_DATA_TYPE_PIB;
|
|
uint16_t idx[1];
|
|
uint16_t block_idx;
|
|
uint8_t i = 0;
|
|
|
|
if (iot_mac_addr_valid(upgrade_info->sta_mac) == 0) {
|
|
iot_printf("plc_upgrade: %s dest mac invalid\n", __FUNCTION__);
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0; i < IOT_PLC_UPGRADE_SEND_BLOCK_CNT; ++i) {
|
|
block_idx = cli_remote_upgrade_find_miss_block(&file_type);
|
|
if (block_idx == IOT_PLC_UPGRADE_INVALID_BLOCK_INDEX) {
|
|
return 0;
|
|
}
|
|
|
|
idx[0] = block_idx;
|
|
|
|
cli_remote_upgrade_send_data(IOT_PLC_MSG_TYPE_UNICAST,
|
|
IOT_PLC_UPGRADE_MAX_START_RETRY_TIMES, upgrade_info->sta_mac,
|
|
upgrade_info->upgrade_id, file_type, UPGRADE_REMOTE_STA_LIST_DATA,
|
|
upgrade_info->remote_block_size, idx, 1,
|
|
UPGRADE_DATA_FORWARD_LOCAL_BCAST, NULL);
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
uint8_t cli_remote_upgrade_resend_phase()
|
|
{
|
|
uint8_t node_cnt = 1;
|
|
|
|
if (upgrade_info->node_response_flag) {
|
|
if (upgrade_info->resend_data_state == CLI_QUERY_NODE) {
|
|
if (iot_mac_addr_valid(upgrade_info->sta_mac) == 0) {
|
|
node_cnt = cli_remote_upgrade_find_resend_dest();
|
|
upgrade_info->query_node_retry_cnt = 0;
|
|
}
|
|
cli_remote_upgrade_query_node_bitmap(1, IOT_PLC_UPGRADE_QUERY_BM_ALL);
|
|
upgrade_info->dest_info.query_node_timeout_cnt = 0;
|
|
upgrade_info->node_response_flag = 0;
|
|
upgrade_info->query_node_retry_cnt++;
|
|
os_mem_set(upgrade_info->full_bitmap, 0,
|
|
IOT_PLC_UPGRADE_STA_BM_SIZE_MAX);
|
|
|
|
} else if (upgrade_info->resend_data_state == CLI_SEND_DATA) {
|
|
if (cli_remote_upgrade_send_miss_block() == 0) {
|
|
upgrade_info->resend_data_state = CLI_QUERY_NODE;
|
|
os_mem_set(upgrade_info->full_bitmap, 0,
|
|
IOT_PLC_UPGRADE_STA_BM_SIZE_MAX);
|
|
|
|
if (upgrade_info->query_node_retry_cnt >
|
|
IOT_PLC_UPGRADE_QUERY_RETRY_MAX) {
|
|
os_mem_set(upgrade_info->sta_mac, 0, IOT_MAC_ADDR_LEN);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
upgrade_info->dest_info.query_node_timeout_cnt++;
|
|
if (upgrade_info->dest_info.query_node_timeout_cnt >=
|
|
upgrade_info->dest_info.query_node_timeout) {
|
|
upgrade_info->node_response_flag = 1;
|
|
upgrade_info->resend_data_state = CLI_QUERY_NODE;
|
|
os_mem_set(upgrade_info->sta_mac, 0, IOT_MAC_ADDR_LEN);
|
|
}
|
|
}
|
|
|
|
return node_cnt;
|
|
}
|
|
|
|
void cli_remote_upgrade_complete()
|
|
{
|
|
iot_printf("plc_upgrade: cli remote upgrade complete\n");
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_STOPED;
|
|
}
|
|
|
|
/* start phase three */
|
|
uint8_t cli_remote_upgrade_start_phase_three()
|
|
{
|
|
iot_plc_upgrade_dest_desc_t *dest = NULL;
|
|
iot_plc_upgrade_dest_desc_t *prev = NULL;
|
|
uint8_t phase_three_cnt = IOT_PLC_UPGRADE_PHASE_THREE_START_CNT;
|
|
uint8_t dec_mac[IOT_MAC_ADDR_LEN] = { 0 };
|
|
uint8_t total_send_cnt = 0;
|
|
iot_printf("plc_upgrade: cco start phase3\n");
|
|
for (uint8_t i = 0; i < phase_three_cnt; i++) {
|
|
//find next start sta
|
|
dest = cli_remote_upgrade_find_uncompleted_dest(CLI_FIND_START_NODE);
|
|
|
|
if (!dest) {
|
|
break;
|
|
}
|
|
|
|
if (prev && (prev == dest)) {
|
|
break;
|
|
} else {
|
|
prev = dest;
|
|
}
|
|
if (IOT_PLC_UPGRADE_STA_LIST == upgrade_info->upgrade_type) {
|
|
iot_mac_addr_cpy(dec_mac, dest->entry.addr);
|
|
}
|
|
cli_remote_upgrade_send_start_notify(IOT_PLC_MSG_TYPE_UNICAST,
|
|
dest->entry.addr, dec_mac, UPGRADE_START_UPGRADE_PHASE3);
|
|
total_send_cnt++;
|
|
}
|
|
return total_send_cnt;
|
|
}
|
|
|
|
/* cco receive stop ack from sta */
|
|
void cli_upgrade_stop_ack(
|
|
uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
(void)src_mac;
|
|
iot_plc_upgrade_stop_ul_t *stop_ul;
|
|
stop_ul = (iot_plc_upgrade_stop_ul_t *)buffer;
|
|
|
|
if ((!stop_ul) || (bufferlen < sizeof(*stop_ul))) {
|
|
iot_printf("%s param error", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
cli_upgrade_send_stop_ack(stop_ul->dst, stop_ul->error_code);
|
|
|
|
if (upgrade_info->dest_info.table) {
|
|
iot_plc_upgrade_dest_desc_t * dest = (iot_plc_upgrade_dest_desc_t *)
|
|
iot_addr_hash_table_find(
|
|
upgrade_info->dest_info.table, stop_ul->dst);
|
|
|
|
if (dest) {
|
|
dest->status = IOT_PLC_UPGRADE_STOPED;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* cco receive reset ack from sta */
|
|
void cli_upgrade_reset_ack(
|
|
uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
(void)src_mac;
|
|
iot_plc_upgrade_reset_ul_t *reset_ul;
|
|
reset_ul = (iot_plc_upgrade_reset_ul_t *)buffer;
|
|
|
|
if ((!reset_ul) || (bufferlen < sizeof(*reset_ul))) {
|
|
iot_printf("%s param error", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
cli_upgrade_send_reset_ack(reset_ul->dst, reset_ul->error_code);
|
|
}
|
|
|
|
/* cco handle sta join */
|
|
void iot_cli_cco_handle_sta_join(uint8_t *mac)
|
|
{
|
|
iot_plc_upgrade_dest_desc_t *dest = NULL;
|
|
iot_printf("plc_upgrade: sta join\n");
|
|
cli_upgrade_print_mac_info(mac);
|
|
dest = (iot_plc_upgrade_dest_desc_t *)iot_addr_hash_table_find(
|
|
upgrade_info->dest_info.table, mac);
|
|
if (!dest) {
|
|
cli_upgrade_add_dest_info(mac);
|
|
// add node to phase3
|
|
if (IOT_PLC_UPGRADE_ALL == upgrade_info->upgrade_type) {
|
|
if (upgrade_info->dst_list_idx) {
|
|
cli_upgrade_add_upgrade_list_dest_info(mac, 1, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* cco handle sta leave */
|
|
void iot_cli_cco_handle_sta_leave(iot_plc_sta_info_t *sta)
|
|
{
|
|
iot_plc_upgrade_dest_desc_t *dest = NULL;
|
|
|
|
iot_printf("plc_upgrade: sta leave\n");
|
|
cli_upgrade_print_mac_info(sta->mac_addr);
|
|
|
|
if (!upgrade_info->dest_info.dst_total_num) {
|
|
return;
|
|
}
|
|
|
|
dest = (iot_plc_upgrade_dest_desc_t *)
|
|
iot_addr_hash_table_find(upgrade_info->dest_info.table, sta->mac_addr);
|
|
|
|
if (dest) {
|
|
dest->error_code = UPGRADE_DATA_STA_LEAVE;
|
|
}
|
|
}
|
|
|
|
void iot_cli_upgrade_app_register_handler(iot_cli_upgrade_app_handler handler)
|
|
{
|
|
sg_upgrade_handler = handler;
|
|
}
|
|
|
|
void cli_upgrade_cache_file_init(uint8_t *file_hdr)
|
|
{
|
|
upgrade_info->cus_size = iot_get_file_cus_len(file_hdr);
|
|
upgrade_info->cus_data = NULL;
|
|
|
|
upgrade_info->pib_size = 0;
|
|
upgrade_info->pib_data = NULL;
|
|
|
|
upgrade_info->fw_size = (iot_get_file_len(file_hdr) +
|
|
iot_get_file_header_len(file_hdr)) - upgrade_info->cus_size;
|
|
upgrade_info->fw_data = NULL;
|
|
|
|
cli_upgrade_write_data_to_flash_cache_init(upgrade_info->upgrade_id++,
|
|
upgrade_info->fw_size, upgrade_info->cus_size, upgrade_info->block_size);
|
|
}
|
|
|
|
uint32_t iot_cli_upgrade_prepare(iot_cli_upgrade_completed_handler handler,
|
|
uint32_t file_size, uint8_t **data, uint8_t *file_hdr, uint16_t block_size,
|
|
uint8_t upgrade_type)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
uint32_t file_len = iot_get_file_len(file_hdr);
|
|
|
|
/* if the file header is invalid, the file size is used */
|
|
if (file_len == 0) {
|
|
file_len = file_size;
|
|
} else {
|
|
file_len += iot_get_file_header_len(file_hdr);
|
|
}
|
|
if ((block_size != 100) && (block_size != 200) &&
|
|
(block_size != 300) && (block_size != 400)) {
|
|
iot_printf("%s block size %d is invalid\n", block_size);
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
if (file_size) {
|
|
cli_remote_upgrade_dest_info_reset();
|
|
} else {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
if (handler) {
|
|
upgrade_info->completed_handler = handler;
|
|
}
|
|
|
|
upgrade_info->block_size = block_size;
|
|
#if IOT_CLI_UPGRADE_CACHE_TYPE
|
|
(void)file_hdr;
|
|
(void)upgrade_type;
|
|
if (file_len > IOT_CLI_UPGRADE_MAX_FILE_SIZE) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
#else
|
|
uint8_t part_num;
|
|
uint32_t part_size = 0;
|
|
if (upgrade_type == IOT_PLC_UPGRADE_LOCAL) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
dev_get_upgrade_fw_part_num(&part_num);
|
|
part_size = dev_get_part_size(part_num);
|
|
if (file_len > part_size) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
cli_upgrade_cache_file_init(file_hdr);
|
|
upgrade_info->fw_start = iot_get_file_fw_start(file_hdr);
|
|
upgrade_info->pib_start = iot_get_file_pib_start(file_hdr);
|
|
upgrade_info->cus_start = iot_get_file_cus_start(file_hdr);
|
|
upgrade_info->fw_size = iot_get_file_fw_len(file_hdr);
|
|
upgrade_info->pib_size = iot_get_file_pib_len(file_hdr);
|
|
upgrade_info->cus_size = iot_get_file_cus_len(file_hdr);
|
|
#endif
|
|
*data = upgrade_info->file_data;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
void iot_cli_translate_file()
|
|
{
|
|
upgrade_info->fw_size = iot_get_file_fw_len(upgrade_info->file_data);
|
|
upgrade_info->pib_size = iot_get_file_pib_len(upgrade_info->file_data);
|
|
upgrade_info->cus_size = iot_get_file_cus_len(upgrade_info->file_data);
|
|
|
|
upgrade_info->pib_data = upgrade_info->file_data +
|
|
iot_get_file_pib_start(upgrade_info->file_data);
|
|
upgrade_info->fw_data = upgrade_info->file_data +
|
|
iot_get_file_fw_start(upgrade_info->file_data);
|
|
upgrade_info->cus_data = upgrade_info->file_data +
|
|
iot_get_file_cus_start(upgrade_info->file_data);
|
|
}
|
|
|
|
uint32_t iot_cli_upgrade_calc_file_crc(uint32_t file_size, uint32_t start_pos)
|
|
{
|
|
uint32_t crc_tmp = 0xFFFFFFFF;
|
|
|
|
uint32_t index = 0;
|
|
uint8_t *ptr;
|
|
uint32_t block_size = 2000;
|
|
uint32_t read_size = block_size;
|
|
iot_pkt_t *pkt = iot_pkt_alloc(block_size, IOT_CLI_MID);
|
|
IOT_ASSERT(pkt);
|
|
|
|
ptr = iot_pkt_put(pkt, block_size);
|
|
|
|
while (index < file_size) {
|
|
if ((index + block_size) > file_size) {
|
|
read_size = file_size - index;
|
|
}
|
|
|
|
cli_upgrade_read_data_from_flash(UPGRADE_DATA_TYPE_FW,
|
|
start_pos + index, ptr, (uint16_t)read_size);
|
|
|
|
crc_tmp = iot_getcrc32_update(crc_tmp, ptr, read_size);
|
|
index += block_size;
|
|
}
|
|
|
|
iot_pkt_free(pkt);
|
|
return (crc_tmp ^ 0xFFFFFFFF);
|
|
}
|
|
|
|
uint8_t iot_cli_upgrade_external_start(uint8_t upgrade_type,
|
|
uint8_t control_flag)
|
|
{
|
|
|
|
if (upgrade_info->upgrade_state != IOT_PLC_UPGRADE_INIT) {
|
|
return UPGRADE_START_CCO_UPGRADING;
|
|
}
|
|
if ((IOT_PLC_UPGRADE_ALL != upgrade_type) &&
|
|
(IOT_PLC_UPGRADE_STA_LIST != upgrade_type)) {
|
|
iot_printf("cli upgrade not support upgrade type: %d\n", upgrade_type);
|
|
return UPGRADE_START_INVALID_TYPE;
|
|
}
|
|
iot_printf("cli upgrade start\n");
|
|
|
|
#if IOT_CLI_UPGRADE_CACHE_TYPE
|
|
iot_cli_translate_file();
|
|
|
|
if (upgrade_info->fw_data && upgrade_info->fw_size) {
|
|
upgrade_info->fw_checksum =
|
|
iot_getcrc32(upgrade_info->fw_data, upgrade_info->fw_size);
|
|
}
|
|
|
|
if (upgrade_info->pib_data && upgrade_info->pib_size) {
|
|
upgrade_info->pib_checksum =
|
|
iot_getcrc32(upgrade_info->pib_data, upgrade_info->pib_size);
|
|
}
|
|
|
|
if (upgrade_info->cus_data && upgrade_info->cus_size) {
|
|
upgrade_info->cus_checksum =
|
|
iot_getcrc32(upgrade_info->cus_data, upgrade_info->cus_size);
|
|
}
|
|
#else
|
|
//delay for share task write upgrade file.
|
|
os_delay(100);
|
|
if (upgrade_info->fw_size) {
|
|
upgrade_info->fw_checksum = iot_cli_upgrade_calc_file_crc(
|
|
upgrade_info->fw_size, upgrade_info->fw_start);
|
|
}
|
|
|
|
if (upgrade_info->pib_size) {
|
|
upgrade_info->pib_checksum = iot_cli_upgrade_calc_file_crc(
|
|
upgrade_info->pib_size, upgrade_info->pib_start);
|
|
}
|
|
|
|
if (upgrade_info->cus_size) {
|
|
upgrade_info->cus_checksum = iot_cli_upgrade_calc_file_crc(
|
|
upgrade_info->cus_size, upgrade_info->cus_start);
|
|
}
|
|
#endif
|
|
|
|
cli_remote_upgrade_sta_initialize(upgrade_type,
|
|
UPGRADE_DEFAULT_BLOCK_SIZE, UPGRADE_DEFAULT_BLOCK_SIZE,
|
|
upgrade_info->fw_size, upgrade_info->pib_size, upgrade_info->cus_size,
|
|
upgrade_info->fw_checksum, upgrade_info->pib_checksum,
|
|
upgrade_info->cus_checksum, IOT_PLC_UPGRADE_DEFAULT_TIMER,
|
|
IOT_PLC_UPGRADE_DEFAULT_REMOTE_BLOCK_CNT);
|
|
|
|
upgrade_info->control_upgrade_flag = !!control_flag;
|
|
upgrade_info->level_one_pco_count = IOT_PLC_UPGRADE_PCO_DEFAULT_ADJ_COUNT;
|
|
upgrade_info->broadcast_retry_times =
|
|
IOT_PLC_UPGRADE_CCO_BCAST_MIN_RETRY_CNT;
|
|
//start sg upgrade
|
|
cli_remote_upgrade_prepare();
|
|
if (IOT_PLC_UPGRADE_STA_LIST == upgrade_type) {
|
|
cli_remote_upgrade_sta_list_start();
|
|
} else {
|
|
/* init upgrade list */
|
|
cli_upgrade_add_upgrade_list_dest_info(NULL, 0, 1);
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_STARTED;
|
|
cli_remote_upgrade_cco_broadcast_data(true);
|
|
}
|
|
return UPGRADE_START_OK;
|
|
}
|
|
|
|
/* sg cli upgrade start */
|
|
uint8_t iot_cli_upgrade_start(uint8_t upgrade_type, uint8_t control_flag)
|
|
{
|
|
return iot_cli_upgrade_external_start(upgrade_type, control_flag);
|
|
}
|
|
|
|
/* sg cli upgrade stop */
|
|
void iot_cli_upgrade_stop()
|
|
{
|
|
iot_printf("cli upgrade stop\n");
|
|
upgrade_info->completed_handler = NULL;
|
|
if ((IOT_PLC_UPGRADE_STARTING == upgrade_info->upgrade_state) ||
|
|
(IOT_PLC_UPGRADE_STARTED == upgrade_info->upgrade_state) ||
|
|
(IOT_PLC_UPGRADE_TRANSFERRED == upgrade_info->upgrade_state)) {
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_STOPED;
|
|
upgrade_info->action_times = 0;
|
|
cli_upgrade_reset_timer(1, IOT_PLC_UPGRADE_CCO_MIN_BCAST_TIME);
|
|
}
|
|
}
|
|
|
|
/* write pib or fw data to flash !! */
|
|
void iot_cli_upgrade_write_file_to_flash(uint8_t file_type,
|
|
uint16_t interval)
|
|
{
|
|
uint32_t written_size = 0;
|
|
uint16_t block_index = 0;
|
|
uint32_t src_block_size = upgrade_info->pib_size;
|
|
uint8_t *src_data = upgrade_info->pib_data;
|
|
uint16_t block_size = upgrade_info->block_size;
|
|
|
|
if (UPGRADE_DATA_TYPE_PIB != file_type) {
|
|
src_block_size = upgrade_info->fw_size;
|
|
src_data = upgrade_info->fw_data;
|
|
}
|
|
|
|
while (written_size < src_block_size) {
|
|
if ((written_size + block_size) >
|
|
src_block_size) {
|
|
block_size = (uint16_t)(src_block_size - written_size);
|
|
}
|
|
cli_upgrade_write_data_to_flash(file_type, 1,
|
|
&block_index, &block_size,
|
|
src_data + written_size);
|
|
written_size += block_size;
|
|
block_index++;
|
|
os_delay(interval);
|
|
}
|
|
}
|
|
|
|
/* cco handle destination list from app */
|
|
uint8_t iot_cli_upgrade_set_dst_list(iot_plc_upgrade_dst_list_t *data,
|
|
uint8_t is_renew)
|
|
{
|
|
uint8_t error_code;
|
|
uint16_t tmp_dst_list_idx = upgrade_info->dst_list_idx;
|
|
if (is_renew) {
|
|
upgrade_info->dst_list_idx = 0;
|
|
}
|
|
error_code = cli_upgrade_dst_list_check(data);
|
|
upgrade_info->dst_list_idx = tmp_dst_list_idx;
|
|
if (UPGRADE_DST_LIST_SUCCESS != error_code) {
|
|
goto err_exit;
|
|
}
|
|
cli_upgrade_add_upgrade_list_dest_info(data->dst_list, data->dst_num,
|
|
is_renew);
|
|
upgrade_info->dest_info.upgrading_list_idx = 0;
|
|
|
|
error_code = UPGRADE_DST_LIST_SUCCESS;
|
|
|
|
err_exit:
|
|
return error_code;
|
|
}
|
|
|
|
void iot_cli_upgrade_qr_dst_status_list(uint16_t start_idx,
|
|
uint8_t count, iot_plc_upgrade_dst_status_list *status_list)
|
|
{
|
|
uint8_t progress = 0;
|
|
iot_plc_upgrade_dst_status_list tmp_status_list;
|
|
uint8_t i = 0;
|
|
uint8_t weight_value = UPGRADE_BDCT_PROGRESS_WEIGHT_FOR_LIST;
|
|
|
|
if ((upgrade_info->upgrade_type == IOT_PLC_UPGRADE_ALL) &&
|
|
(upgrade_info->dest_info.dst_total_num >
|
|
UPGRADE_PROGRESS_THRESHOLD_VALUE_STA_CNT)) {
|
|
weight_value = UPGRADE_BDCT_PROGRESS_WEIGHT_FOR_ALL;
|
|
}
|
|
|
|
cli_upgrade_set_dst_status_list(start_idx, count, &tmp_status_list);
|
|
switch (upgrade_info->upgrade_state) {
|
|
case IOT_PLC_UPGRADE_STARTING:
|
|
case IOT_PLC_UPGRADE_STARTED:
|
|
if ((upgrade_info->current_file_type == UPGRADE_DATA_TYPE_PIB) &&
|
|
upgrade_info->pib_blocks) {
|
|
progress = (uint8_t)((weight_value *
|
|
upgrade_info->block_idx) /
|
|
(upgrade_info->pib_blocks + upgrade_info->fw_blocks));
|
|
} else {
|
|
progress = (uint8_t)((weight_value *
|
|
(upgrade_info->block_idx + upgrade_info->pib_blocks)) /
|
|
(upgrade_info->pib_blocks + upgrade_info->fw_blocks));
|
|
}
|
|
|
|
status_list->end = 1;
|
|
if (count > UPGRADE_REMOTE_DST_STATUS_ONCE_MAX_NUM) {
|
|
count = UPGRADE_REMOTE_DST_STATUS_ONCE_MAX_NUM;
|
|
status_list->end = 0;
|
|
}
|
|
status_list->dst_num = tmp_status_list.dst_num;
|
|
status_list->dst_status_list_idx = tmp_status_list.dst_status_list_idx;
|
|
|
|
for (i = 0; i < status_list->dst_num; i++) {
|
|
os_mem_cpy(status_list->dst_status_list[i].dst,
|
|
tmp_status_list.dst_status_list[i].dst, IOT_MAC_ADDR_LEN);
|
|
status_list->dst_status_list[i].error_code =
|
|
UPGRADE_DATA_STA_IN_PROGRESS;
|
|
status_list->dst_status_list[i].percentage = progress;
|
|
}
|
|
break;
|
|
case IOT_PLC_UPGRADE_TRANSFERRED:
|
|
{
|
|
status_list->dst_num = tmp_status_list.dst_num;
|
|
status_list->dst_status_list_idx = tmp_status_list.dst_status_list_idx;
|
|
status_list->end = tmp_status_list.end;
|
|
for (i = 0; i < tmp_status_list.dst_num; i++) {
|
|
os_mem_cpy(status_list->dst_status_list[i].dst,
|
|
tmp_status_list.dst_status_list[i].dst,
|
|
IOT_MAC_ADDR_LEN);
|
|
status_list->dst_status_list[i].error_code =
|
|
tmp_status_list.dst_status_list[i].error_code;
|
|
if ((IOT_PLC_UPGRADE_INIT ==
|
|
tmp_status_list.dst_status_list[i].status) ||
|
|
(IOT_PLC_UPGRADE_STARTED ==
|
|
tmp_status_list.dst_status_list[i].status) ||
|
|
(IOT_PLC_UPGRADE_LISTEN ==
|
|
tmp_status_list.dst_status_list[i].status)) {
|
|
status_list->dst_status_list[i].error_code =
|
|
UPGRADE_DATA_STA_IN_PROGRESS;
|
|
}
|
|
if (UPGRADE_DATA_SUCCESS ==
|
|
status_list->dst_status_list[i].error_code) {
|
|
status_list->dst_status_list[i].percentage = 100;
|
|
} else {
|
|
status_list->dst_status_list[i].percentage =
|
|
(weight_value +
|
|
(tmp_status_list.dst_status_list[i].percentage *
|
|
(100 - weight_value)));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_UPGRADE_STOPED:
|
|
case IOT_PLC_UPGRADE_RESET:
|
|
case IOT_PLC_UPGRADE_INIT:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void iot_cli_upgrade_qr_dst_status(iot_plc_upgrade_dst_status_query *query)
|
|
{
|
|
cli_upgrade_set_dst_status_ack(query);
|
|
}
|
|
|
|
#if (!IOT_SMART_GRID_ENABLE)
|
|
uint16_t iot_cli_upgrade_set_renew_nodelist(uint8_t *dstlist, uint16_t cnt)
|
|
{
|
|
uint16_t tmp_cnt = 0;
|
|
|
|
if (cnt > IOT_PLC_UPGRADE_PHASE_THREE_MAX_SAT_CNT) {
|
|
cnt = IOT_PLC_UPGRADE_PHASE_THREE_MAX_SAT_CNT;
|
|
}
|
|
|
|
tmp_cnt = cli_upgrade_add_upgrade_list_dest_info(dstlist, cnt, 1);
|
|
upgrade_info->dest_info.upgrading_list_idx = 0;
|
|
if (tmp_cnt) {
|
|
cli_remote_upgrade_start_phase3();
|
|
}
|
|
return tmp_cnt;
|
|
}
|
|
|
|
#endif /* end !IOT_SMART_GRID_ENABLE */
|
|
|
|
#else /* IOT_CLI_UPGRADE_ENABLE */
|
|
|
|
/* cco handle sta join */
|
|
void iot_cli_cco_handle_sta_join(uint8_t *mac)
|
|
{
|
|
iot_printf("plc_upgrade: sta join: %02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
}
|
|
|
|
/* cco handle sta leave */
|
|
void iot_cli_cco_handle_sta_leave(iot_plc_sta_info_t *sta)
|
|
{
|
|
iot_printf("plc_upgrade: sta leave: %02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
sta->mac_addr[0], sta->mac_addr[1], sta->mac_addr[2],
|
|
sta->mac_addr[3], sta->mac_addr[4], sta->mac_addr[5]);
|
|
}
|
|
|
|
/* sg cli upgrade stop */
|
|
void iot_cli_upgrade_stop()
|
|
{
|
|
}
|
|
|
|
uint32_t iot_cli_upgrade_prepare(iot_cli_upgrade_completed_handler handler,
|
|
uint32_t file_size, uint8_t **data, uint8_t *file_hdr, uint16_t block_size,
|
|
uint8_t upgrade_type)
|
|
{
|
|
(void)handler;
|
|
uint32_t ret = ERR_OK;
|
|
uint32_t file_len = iot_get_file_len(file_hdr);
|
|
|
|
/* if the file header is invalid, the file size is used */
|
|
if (file_len == 0) {
|
|
file_len = file_size;
|
|
}
|
|
|
|
if ((block_size != 100) && (block_size != 200) &&
|
|
(block_size != 300) && (block_size != 400)) {
|
|
iot_printf("%s block size %d is invalid\n", block_size);
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
upgrade_info->block_size = block_size;
|
|
#if IOT_CLI_UPGRADE_CACHE_TYPE
|
|
(void)file_hdr;
|
|
(void)upgrade_type;
|
|
if (file_len > IOT_CLI_UPGRADE_MAX_FILE_SIZE) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
#else
|
|
uint8_t part_num;
|
|
uint32_t part_size = 0;
|
|
if (upgrade_type == IOT_PLC_UPGRADE_LOCAL) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
dev_get_upgrade_fw_part_num(&part_num);
|
|
part_size = dev_get_part_size(part_num);
|
|
if (file_len > part_size) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
cli_upgrade_cache_file_init(file_hdr);
|
|
#endif
|
|
*data = upgrade_info->file_data;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static void cli_upgrade_dst_status_query_internal(uint8_t *src_mac)
|
|
{
|
|
(void)src_mac;
|
|
}
|
|
|
|
void cli_upgrade_dst_status_list_internal(uint16_t start_index,
|
|
uint8_t dst_num, uint8_t *src_mac)
|
|
{
|
|
(void)start_index;
|
|
(void)dst_num;
|
|
(void)src_mac;
|
|
}
|
|
|
|
/* sg cli upgrade start */
|
|
uint8_t iot_cli_upgrade_start(uint8_t upgrade_type, uint8_t control_flag)
|
|
{
|
|
(void)upgrade_type;
|
|
(void)control_flag;
|
|
return 0;
|
|
}
|
|
|
|
void iot_cli_upgrade_app_register_handler(iot_cli_upgrade_app_handler handler)
|
|
{
|
|
sg_upgrade_handler = handler;
|
|
}
|
|
|
|
void cli_remote_upgrade_bcast_tx_done()
|
|
{
|
|
|
|
}
|
|
|
|
#endif /* IOT_CLI_UPGRADE_ENABLE */
|
|
|
|
void cli_upgrade_dst_status_query(uint8_t *buffer, uint32_t bufferlen,
|
|
uint8_t *src_mac)
|
|
{
|
|
(void)buffer;
|
|
(void)bufferlen;
|
|
|
|
if (host_config->cli_upgrade_enabled) {
|
|
cli_upgrade_dst_status_query_internal(src_mac);
|
|
} else {
|
|
cli_upgrade_dst_status_sg_query(add_addr_to_mapping_table(src_mac));
|
|
}
|
|
}
|
|
|
|
void cli_upgrade_dst_status_list(
|
|
uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
iot_plc_upgrade_dst_status_list_dl *list_dl;
|
|
list_dl = (iot_plc_upgrade_dst_status_list_dl *)buffer;
|
|
|
|
if ((!list_dl) || (bufferlen < sizeof(*list_dl))) {
|
|
iot_printf("%s param error", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if (host_config->cli_upgrade_enabled) {
|
|
cli_upgrade_dst_status_list_internal(list_dl->dst_status_list_idx,
|
|
list_dl->dst_num, src_mac);
|
|
} else {
|
|
cli_upgrade_dst_status_sg_list(list_dl->dst_status_list_idx,
|
|
list_dl->dst_num, add_addr_to_mapping_table(src_mac));
|
|
}
|
|
}
|
|
|
|
/* sg upgrade data ack */
|
|
void cli_sg_upgrade_data_ack(uint8_t result_code, uint16_t seg_index)
|
|
{
|
|
iot_plc_sg_upgrade_data_ack_ul_t ack_ul;
|
|
ack_ul.error_code = result_code;
|
|
ack_ul.seg_index = seg_index;
|
|
|
|
iot_printf("sg upgrade data ack, seg_index %lu result code %lu\n",
|
|
seg_index, result_code);
|
|
|
|
iot_cli_send_to_host(CLI_MSGID_SG_UPGRADE_DATA_ACK,
|
|
(uint8_t*)&ack_ul, sizeof(ack_ul), NULL);
|
|
}
|
|
|
|
/* sg upgrade stop */
|
|
void cli_sg_upgrade_stop()
|
|
{
|
|
iot_printf("cli set sg upgrade stop\n");
|
|
if (sg_upgrade_handler) {
|
|
sg_upgrade_handler(UPGRADE_CLI_UPGRADE_STOP_CMD, NULL, 0);
|
|
}
|
|
}
|
|
|
|
/* sg upgrade data */
|
|
void cli_sg_upgrade_data(
|
|
uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
iot_plc_sg_upgrade_data_dl_t *data =
|
|
(iot_plc_sg_upgrade_data_dl_t *)buffer;
|
|
(void)src_mac;
|
|
uint8_t result_code = UPGRADE_DATA_SUCCESS;
|
|
|
|
BUILD_BUG_ON(sizeof(iot_plc_sg_upgrade_data_dl_t) ==
|
|
sizeof(iot_plc_app_upgrade_data_t));
|
|
|
|
if ((!data) || (bufferlen < sizeof(*data))) {
|
|
iot_printf("%s param error", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if ((data->seg_index == 0) && host_config->cli_upgrade_enabled) {
|
|
host_config->cli_upgrade_enabled = 0;
|
|
}
|
|
|
|
iot_printf("sg upgrade data, seg_index %lu,"
|
|
" total seg cnt %lu, data len %lu\n",
|
|
data->seg_index, data->total_seg_count, data->data_len);
|
|
|
|
if (sg_upgrade_handler) {
|
|
if (ERR_OK != sg_upgrade_handler(UPGRADE_CLI_UPGRADE_DATA, buffer,
|
|
bufferlen)) {
|
|
result_code = UPGRADE_DATA_OTHER_ERROR;
|
|
}
|
|
}
|
|
|
|
if ((data->total_seg_count - 1) == data->seg_index) {
|
|
iot_printf("sg upgrade data recv done\n");
|
|
}
|
|
cli_sg_upgrade_data_ack(result_code, data->seg_index);
|
|
}
|
|
|
|
uint32_t iot_cli_upgrade_read(uint32_t offset, uint8_t *buf,
|
|
uint16_t buf_len)
|
|
{
|
|
uint8_t result = UPGRADE_DATA_SUCCESS;
|
|
|
|
#if IOT_CLI_UPGRADE_CACHE_TYPE
|
|
result = cli_upgrade_read_data_from_buffer(UPGRADE_DATA_TYPE_PKG, offset,
|
|
buf, buf_len);
|
|
#else
|
|
result = cli_upgrade_read_data_from_flash(UPGRADE_DATA_TYPE_FW, offset,
|
|
buf, buf_len);
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
uint32_t iot_cli_upgrade_write(uint32_t offset, uint8_t *buf,
|
|
uint16_t buf_len)
|
|
{
|
|
uint8_t result = UPGRADE_DATA_SUCCESS;
|
|
uint16_t block_idx = (uint16_t)(offset / upgrade_info->block_size);
|
|
|
|
if (offset % upgrade_info->block_size != 0) {
|
|
result = UPGRADE_DATA_INVALID_DATA;
|
|
iot_printf(" %s invalid offset.\n");
|
|
goto out;
|
|
}
|
|
|
|
#if IOT_CLI_UPGRADE_CACHE_TYPE
|
|
result = cli_upgrade_write_data_to_buffer(UPGRADE_DATA_TYPE_PKG, 1,
|
|
&block_idx, &buf_len, buf);
|
|
#else
|
|
result = cli_upgrade_write_data_to_flash(UPGRADE_DATA_TYPE_FW, 1,
|
|
&block_idx, &buf_len, buf);
|
|
#endif
|
|
|
|
out:
|
|
return result;
|
|
}
|
|
|
|
uint32_t iot_cli_upgrade_get_file_limit(uint8_t local_upgrade,
|
|
uint8_t *file_hdr)
|
|
{
|
|
uint32_t size = 0;
|
|
uint8_t part_num;
|
|
|
|
if (local_upgrade) {
|
|
if (file_hdr == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
if (iot_get_file_fw_len(file_hdr)) {
|
|
dev_get_upgrade_fw_part_num(&part_num);
|
|
size += dev_get_part_size(part_num);
|
|
}
|
|
|
|
if (iot_get_file_pib_len(file_hdr)) {
|
|
dev_get_upgrade_pib_part_num(&part_num);
|
|
size += dev_get_part_size(part_num);
|
|
}
|
|
|
|
if (iot_get_file_cus_len(file_hdr)) {
|
|
dev_get_upgrade_cus_part_num(&part_num);
|
|
size += dev_get_part_size(part_num);
|
|
}
|
|
} else {
|
|
if (IOT_CLI_UPGRADE_MAX_FILE_SIZE) {
|
|
size = IOT_CLI_UPGRADE_MAX_FILE_SIZE;
|
|
} else {
|
|
dev_get_upgrade_fw_part_num(&part_num);
|
|
size = dev_get_part_size(part_num);
|
|
}
|
|
}
|
|
return size;
|
|
}
|
|
|
|
#endif /* PLC_SUPPORT_CCO_ROLE */ |