2005 lines
68 KiB
C
2005 lines
68 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_cli_plc_module.h"
|
|
#include "iot_cli_host_upgrade_internal.h"
|
|
#include "iot_version_api.h"
|
|
#include "iot_oem.h"
|
|
#include "iot_cli_plc_tx_rx.h"
|
|
#include "plc_utils.h"
|
|
|
|
iot_plc_upgrade_info_t *upgrade_info = NULL;
|
|
extern iot_plc_host_config_t *host_config;
|
|
extern iot_cli_host_info_t *host_info;
|
|
extern iot_cli_t cli;
|
|
extern uint32_t cli_module_type;
|
|
|
|
#if IOT_CLI_UPGRADE_ENABLE
|
|
/* print block info */
|
|
void cli_upgrade_print_block_info(iot_plc_upgrade_data_dl_t *data)
|
|
{
|
|
if (!data) {
|
|
return;
|
|
}
|
|
|
|
iot_printf("file type:%d, req_block_cnt:%d\n",
|
|
data->file_type, data->block_cnt);
|
|
for (uint16_t i = 0; i < data->block_cnt; i++) {
|
|
iot_printf("plc_upgrade:block_index:%d, block size:%d\n",
|
|
data->block_idx_array[i],
|
|
data->block_size_array[i]);
|
|
}
|
|
}
|
|
|
|
/* calculate total size of data */
|
|
static uint32_t cli_upgrade_data_size(uint16_t block_cnt,
|
|
uint16_t *block_size_array)
|
|
{
|
|
uint32_t size = 0;
|
|
|
|
if (NULL != block_size_array) {
|
|
for (uint32_t i = 0; i < block_cnt; i++) {
|
|
size += block_size_array[i];
|
|
}
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
/* calculate crc per 4 bytes data */
|
|
static uint32_t cli_upgrade_data_crc_calculate(uint8_t *crc_data)
|
|
{
|
|
if (!crc_data) {
|
|
return 0;
|
|
}
|
|
|
|
return *(crc_data)+((uint32_t)*(crc_data + 1) << 8) +
|
|
((uint32_t)*(crc_data + 2) << 16) +
|
|
((uint32_t)*(crc_data + 3) << 24);
|
|
}
|
|
|
|
/* upgrade type check */
|
|
uint8_t cli_upgrade_type_check(iot_plc_upgrade_start_dl_t *data)
|
|
{
|
|
if (!data) {
|
|
return UPGRADE_START_OTHER_ERROR;
|
|
}
|
|
|
|
if ((IOT_PLC_UPGRADE_LOCAL != data->upgrade_type) &&
|
|
(IOT_PLC_UPGRADE_ALL != data->upgrade_type) &&
|
|
(IOT_PLC_UPGRADE_STA_LIST != data->upgrade_type)) {
|
|
return UPGRADE_START_INVALID_TYPE;
|
|
}
|
|
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
if ((IOT_PLC_DEV_ROLE_CCO == host_config->dev_role) &&
|
|
(IOT_PLC_UPGRADE_ALL == data->upgrade_type) &&
|
|
!data->dst_total_num) {
|
|
return UPGRADE_START_INVALID_DATA;
|
|
}
|
|
#endif
|
|
|
|
return UPGRADE_START_OK;
|
|
}
|
|
|
|
/* upgrade data check */
|
|
uint8_t cli_upgrade_data_check(uint16_t block_cnt, uint16_t *block_idx_array,
|
|
uint16_t *block_size_array, uint8_t *data, uint8_t file_type)
|
|
{
|
|
if ((!data) || (!block_idx_array)) {
|
|
return UPGRADE_DATA_INVALID_DATA;
|
|
}
|
|
|
|
/* 0 means stop */
|
|
if (0 == block_cnt) {
|
|
return UPGRADE_DATA_STA_STOP;
|
|
}
|
|
|
|
/* upgrade type check */
|
|
if ((IOT_PLC_UPGRADE_LOCAL == upgrade_info->upgrade_type) ||
|
|
(((IOT_PLC_UPGRADE_ALL == upgrade_info->upgrade_type) ||
|
|
(IOT_PLC_UPGRADE_STA_LIST == upgrade_info->upgrade_type)) &&
|
|
(IOT_PLC_DEV_ROLE_CCO == host_config->dev_role))) {
|
|
uint32_t data_size = cli_upgrade_data_size(block_cnt, block_size_array);
|
|
uint32_t crcCode = iot_getcrc32(data, data_size);
|
|
uint32_t crcCodePLC = cli_upgrade_data_crc_calculate(
|
|
data + data_size);
|
|
if (crcCode != crcCodePLC) {
|
|
/* crc check only for local upgrade */
|
|
/*iot_printf("plc_upgrade:crc check, crcCode:%x, crcCodePLC:%x\n",
|
|
crcCode, crcCodePLC);*/
|
|
return UPGRADE_DATA_CRC_ERROR;
|
|
}
|
|
}
|
|
|
|
/* file type check */
|
|
if ((UPGRADE_DATA_TYPE_FW != file_type) &&
|
|
(UPGRADE_DATA_TYPE_PIB != file_type) &&
|
|
(UPGRADE_DATA_TYPE_CUS != file_type)) {
|
|
iot_printf("plc_upgrade: invalid file type\n");
|
|
return UPGRADE_DATA_INVALID_FILE_TYPE;
|
|
}
|
|
|
|
if ((IOT_PLC_UPGRADE_STARTED == upgrade_info->upgrade_state) ||
|
|
(IOT_PLC_UPGRADE_STARTING == upgrade_info->upgrade_state)) {
|
|
/* block idx check */
|
|
for (uint32_t i = 0; i < block_cnt; i++) {
|
|
if ((upgrade_info->block_idx + i) != block_idx_array[i]) {
|
|
iot_printf("plc_ugrade:expect block_index = 0n%d,"
|
|
"block_index = 0n%d\n",
|
|
upgrade_info->block_idx + i, block_idx_array[i]);
|
|
return UPGRADE_DATA_BLOCK_IDX_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
return UPGRADE_DATA_SUCCESS;
|
|
}
|
|
|
|
/* initialize latest block info */
|
|
void cli_remote_upgrade_initialize_latest_block()
|
|
{
|
|
for (uint8_t idx = 0; idx < IOT_PLC_UPGRADE_LATEST_BLOCK_CNT; idx++)
|
|
{
|
|
upgrade_info->latest_block_info.latest_block_request[idx].block_idx
|
|
= 0;
|
|
upgrade_info->latest_block_info.latest_block_request[idx].file_type
|
|
= UPGRADE_DATA_TYPE_INVALID;
|
|
upgrade_info->latest_block_info.latest_block_request[idx].request_times
|
|
= 0;
|
|
}
|
|
}
|
|
|
|
/* query latest block info */
|
|
static void cli_remote_upgrade_update_latest_block(uint8_t file_type,
|
|
uint16_t block_idx)
|
|
{
|
|
uint16_t request_times = 0xFFFF;
|
|
uint8_t candiate_index = 0;
|
|
for (uint8_t idx = 0; idx < IOT_PLC_UPGRADE_LATEST_BLOCK_CNT; idx++)
|
|
{
|
|
iot_plc_upgrade_block_info_t *block_info =
|
|
&upgrade_info->latest_block_info.latest_block_request[idx];
|
|
if (UPGRADE_DATA_TYPE_INVALID == block_info->file_type) {
|
|
candiate_index = idx;
|
|
break;
|
|
} else {
|
|
if (block_info->request_times < request_times) {
|
|
request_times = block_info->request_times;
|
|
candiate_index = idx;
|
|
}
|
|
}
|
|
}
|
|
|
|
upgrade_info->latest_block_info.
|
|
latest_block_request[candiate_index].file_type = file_type;
|
|
upgrade_info->latest_block_info.
|
|
latest_block_request[candiate_index].block_idx = block_idx;
|
|
}
|
|
|
|
/* find latest block info with file type and block idx */
|
|
static bool_t cli_remote_upgrade_update_find_latest_block(uint8_t file_type,
|
|
uint16_t block_idx)
|
|
{
|
|
for (uint8_t idx = 0; idx < IOT_PLC_UPGRADE_LATEST_BLOCK_CNT; idx++)
|
|
{
|
|
iot_plc_upgrade_block_info_t *block_info =
|
|
&upgrade_info->latest_block_info.latest_block_request[idx];
|
|
if ((block_info->block_idx == block_idx) &&
|
|
(block_info->file_type == file_type)) {
|
|
block_info->request_times++;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* pco strart upgrade */
|
|
void cli_remote_upgrade_pco_start()
|
|
{
|
|
iot_plc_query_neighbor_dev(host_config->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT, 0, 1, IOT_PLC_QUERY_TOPO_START_AS_TEI);
|
|
}
|
|
|
|
/* clean gw upgrade info, in case gw upgrade get error info */
|
|
static void cli_clean_gw_upgrade_info()
|
|
{
|
|
uint32_t part = 0;
|
|
uint32_t other_part = 0;
|
|
|
|
if (iot_upgrade_get_part(&part)) {
|
|
/* cannot upgrade because failed to read partition info */
|
|
iot_printf("failed to get current boot part.\n");
|
|
return;
|
|
}
|
|
other_part = iot_upgrade_get_another_part(part);
|
|
/* clean crc info */
|
|
iot_upgrade_save_fw_crc(other_part, 0);
|
|
}
|
|
|
|
/* crc check callback for flash write operation */
|
|
static void cli_upgrade_file_part_crc_check(uint8_t check_result)
|
|
{
|
|
uint8_t error_code = UPGRADE_DATA_SUCCESS;
|
|
|
|
iot_printf("plc_upgrade: crc_check, role %x state:%x\n",
|
|
host_config->dev_role, upgrade_info->upgrade_state);
|
|
|
|
if ((IOT_PLC_UPGRADE_LOCAL == upgrade_info->upgrade_type) &&
|
|
(COMMUNICATOR_BT == cli.commu.type)) {
|
|
iot_upgrade_commit(upgrade_info->src.id);
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_TRANSFERRED;
|
|
}
|
|
cli_upgrade_reset_timer(0, 0);
|
|
|
|
if (upgrade_info->src.crc_check_buf) {
|
|
iot_pkt_free(upgrade_info->src.crc_check_buf);
|
|
upgrade_info->src.crc_check_buf = NULL;
|
|
}
|
|
|
|
if ((IOT_PLC_UPGRADE_STARTING == upgrade_info->upgrade_state) ||
|
|
(IOT_PLC_UPGRADE_STARTED == upgrade_info->upgrade_state) ||
|
|
(IOT_PLC_UPGRADE_LISTEN == upgrade_info->upgrade_state)) {
|
|
if (check_result) {
|
|
/* set LED to show upgrading state */
|
|
iot_plc_led_request(IOT_PLC_LED_UPGRADE_ON);
|
|
cli_clean_gw_upgrade_info();
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_TRANSFERRED;
|
|
iot_printf("plc_upgrade: crc passed, commit\n");
|
|
iot_upgrade_commit(upgrade_info->src.id);
|
|
if (IOT_PLC_DEV_ROLE_PCO == host_config->dev_role)
|
|
{
|
|
//pco to start 1hop remote upgrade
|
|
iot_printf("plc_upgrade: start sub nodes, role %x\n",
|
|
host_config->dev_role);
|
|
cli_remote_upgrade_pco_start();
|
|
}
|
|
} else {
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_FAILED;
|
|
iot_printf("plc_upgrade: crc failed\n");
|
|
iot_upgrade_cancel_commit(upgrade_info->src.id);
|
|
error_code = UPGRADE_DATA_CRC_ERROR;
|
|
//todo:handle crc error
|
|
}
|
|
|
|
cli_upgrade_sta_send_upgrade_result(IOT_PLC_MSG_TYPE_UNICAST,
|
|
host_config->mac_addr, host_config->cco_mac, error_code);
|
|
}
|
|
}
|
|
|
|
/* sta upgrade info initialize */
|
|
void cli_remote_upgrade_sta_initialize(
|
|
uint8_t upgrade_type, uint16_t block_size, uint16_t remote_block_size,
|
|
uint32_t fw_size, uint32_t pib_size, uint32_t cus_size,
|
|
uint32_t fw_checksum, uint32_t pib_checksum, uint32_t cus_checksum,
|
|
uint16_t time_window, uint16_t remote_block_cnt)
|
|
{
|
|
//stop last timer
|
|
cli_upgrade_reset_timer(0, 0);
|
|
|
|
upgrade_info->upgrade_type = upgrade_type;
|
|
upgrade_info->block_size = block_size;
|
|
upgrade_info->remote_block_size = remote_block_size;
|
|
upgrade_info->block_idx = 0;
|
|
upgrade_info->fw_recv_done = 0;
|
|
upgrade_info->pib_recv_done = 0;
|
|
upgrade_info->cus_recv_done = 0;
|
|
|
|
upgrade_info->fw_size = fw_size;
|
|
if (upgrade_info->fw_size == 0) {
|
|
upgrade_info->fw_recv_done = 1;
|
|
upgrade_info->fw_blocks = 0;
|
|
upgrade_info->fw_checksum = 0;
|
|
} else {
|
|
upgrade_info->fw_blocks = (uint16_t)iot_ceil(upgrade_info->fw_size,
|
|
upgrade_info->block_size);
|
|
upgrade_info->fw_checksum = fw_checksum;
|
|
}
|
|
upgrade_info->pib_size = pib_size;
|
|
if (upgrade_info->pib_size == 0) {
|
|
upgrade_info->pib_recv_done = 1;
|
|
upgrade_info->pib_blocks = 0;
|
|
upgrade_info->pib_checksum = 0;
|
|
} else {
|
|
upgrade_info->pib_blocks = (uint16_t)iot_ceil(upgrade_info->pib_size,
|
|
upgrade_info->block_size);
|
|
upgrade_info->pib_checksum = pib_checksum;
|
|
}
|
|
upgrade_info->cus_size = cus_size;
|
|
if (upgrade_info->cus_size == 0) {
|
|
upgrade_info->cus_recv_done = 1;
|
|
upgrade_info->cus_blocks = 0;
|
|
upgrade_info->cus_checksum = 0;
|
|
} else {
|
|
upgrade_info->cus_blocks = (uint16_t)iot_ceil(upgrade_info->cus_size,
|
|
upgrade_info->block_size);
|
|
upgrade_info->cus_checksum = cus_checksum;
|
|
}
|
|
|
|
iot_printf("fw_size:%d,fw_recv_done:%d,fw_blocks:%d,"
|
|
"fw_checksum %x\n",
|
|
upgrade_info->fw_size, upgrade_info->fw_recv_done,
|
|
upgrade_info->fw_blocks, upgrade_info->fw_checksum);
|
|
iot_printf("pib_size:%d,pib_recv_done:%d,pib_blocks:%d,"
|
|
"pib_checksum %x\n",
|
|
upgrade_info->pib_size, upgrade_info->pib_recv_done,
|
|
upgrade_info->pib_blocks, upgrade_info->pib_checksum);
|
|
iot_printf("cus_size:%d,cus_recv_done:%d,cus_blocks:%d,"
|
|
"cus_checksum %x\n",
|
|
upgrade_info->cus_size, upgrade_info->cus_recv_done,
|
|
upgrade_info->cus_blocks, upgrade_info->cus_checksum);
|
|
|
|
iot_printf("time_window %d, remote_block_cnt %d\n",
|
|
time_window, remote_block_cnt);
|
|
|
|
upgrade_info->time_window = time_window;
|
|
upgrade_info->remote_block_cnt = remote_block_cnt;
|
|
upgrade_info->reported_percentage = 0;
|
|
|
|
if (UPGRADE_DATA_BLOCK_MAX_SIZE < upgrade_info->remote_block_size) {
|
|
upgrade_info->remote_block_size = UPGRADE_DATA_BLOCK_MAX_SIZE;
|
|
}
|
|
|
|
if (IOT_PLC_UPGRADE_LISTEN != upgrade_info->upgrade_state) {
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_INIT;
|
|
//upgrade_info->remote_written_blocks = 0;
|
|
}
|
|
}
|
|
|
|
/* initialize upgrade info */
|
|
void cli_upgrade_info_initialize(iot_plc_upgrade_start_dl_t *data)
|
|
{
|
|
iot_plc_upgrade_cust_start_dl_t cus_info;
|
|
if (!data) {
|
|
return;
|
|
}
|
|
|
|
if (data->cus_upgrade_flag) {
|
|
os_mem_cpy((uint8_t *)&cus_info,
|
|
(data->dst + data->dst_num * IOT_MAC_ADDR_LEN),
|
|
sizeof(iot_plc_upgrade_cust_start_dl_t));
|
|
} else {
|
|
os_mem_set((uint8_t *)&cus_info, 0, sizeof(cus_info));
|
|
}
|
|
|
|
cli_remote_upgrade_sta_initialize(data->upgrade_type,
|
|
data->block_size, data->remote_block_size, data->fw_size,
|
|
data->pib_size, cus_info.cus_size, data->fw_checksum,
|
|
data->pib_checksum, cus_info.cus_checksum, data->time_window,
|
|
data->remote_block_cnt);
|
|
/**
|
|
*for local upgrade, always start from block #0
|
|
*todo: for remote upgrade support resuming from break point
|
|
*/
|
|
upgrade_info->fw_version = data->fw_version;
|
|
upgrade_info->pib_version = data->pib_version;
|
|
upgrade_info->cus_version = cus_info.cus_version;
|
|
upgrade_info->control_upgrade_flag = !!data->control_flag;
|
|
|
|
if (IOT_PLC_DEV_ROLE_CCO != host_config->dev_role) {
|
|
upgrade_info->upgrade_id = data->upgrade_id;
|
|
}
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
else {
|
|
upgrade_info->broadcast_retry_times = data->broadcast_retry_times;
|
|
if (upgrade_info->broadcast_retry_times <
|
|
IOT_PLC_UPGRADE_CCO_BCAST_MIN_RETRY_CNT) {
|
|
upgrade_info->broadcast_retry_times =
|
|
IOT_PLC_UPGRADE_CCO_BCAST_MIN_RETRY_CNT;
|
|
}
|
|
upgrade_info->level_one_pco_count = data->level_one_pco_count;
|
|
cli_remote_upgrade_dest_info_reset();
|
|
|
|
cli_upgrade_add_upgrade_list_dest_info(data->dst, data->dst_num, 1);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* initialize falsh info */
|
|
uint32_t cli_upgrade_flash_info_initialize(uint16_t block_size,
|
|
uint32_t fw_size, uint16_t pib_size, uint16_t cus_size, uint32_t upgrade_id,
|
|
uint32_t fw_checksum, uint32_t pib_checksum, uint32_t cus_checksum,
|
|
uint32_t fw_version)
|
|
{
|
|
upgrade_info->src.block_size = block_size;
|
|
upgrade_info->src.fw_size = fw_size;
|
|
upgrade_info->src.pib_size = pib_size;
|
|
upgrade_info->src.cus_size = cus_size;
|
|
upgrade_info->src.id = upgrade_id;
|
|
upgrade_info->src.fw_crc = fw_checksum;
|
|
upgrade_info->src.pib_crc = pib_checksum;
|
|
upgrade_info->src.cus_crc = cus_checksum;
|
|
upgrade_info->src.fw_version = fw_version;
|
|
if (!upgrade_info->src.crc_check_buf) {
|
|
upgrade_info->src.crc_check_buf = iot_pkt_alloc(
|
|
UPGRADE_DEFAULT_BLOCK_SIZE, IOT_DRIVER_MID);
|
|
}
|
|
upgrade_info->src.crc_check_cb = cli_upgrade_file_part_crc_check;
|
|
upgrade_info->src.read_block_cb = NULL;
|
|
upgrade_info->src.write_block_cb = NULL;
|
|
|
|
return iot_upgrade_start(&upgrade_info->result, &upgrade_info->src);
|
|
}
|
|
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
/* initialize buffer */
|
|
void cli_upgrade_buffer_initialize()
|
|
{
|
|
IOT_ASSERT(upgrade_info->file_data);
|
|
IOT_ASSERT(IOT_CLI_UPGRADE_MAX_FILE_SIZE >= (upgrade_info->fw_size +
|
|
upgrade_info->pib_size + upgrade_info->cus_size));
|
|
upgrade_info->pib_data = upgrade_info->file_data;
|
|
upgrade_info->fw_data =
|
|
upgrade_info->file_data + upgrade_info->pib_size;
|
|
upgrade_info->cus_data =
|
|
upgrade_info->file_data + upgrade_info->pib_size + upgrade_info->fw_size;
|
|
}
|
|
|
|
static uint32_t cli_upgrade_get_cache_data(uint8_t file_type, uint32_t offset,
|
|
uint8_t *buf, uint32_t len)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
|
|
#if IOT_CLI_UPGRADE_CACHE_TYPE
|
|
if (file_type == UPGRADE_DATA_TYPE_PIB) {
|
|
os_mem_cpy(buf, upgrade_info->pib_data + offset, len);
|
|
} else if (file_type == UPGRADE_DATA_TYPE_FW) {
|
|
os_mem_cpy(buf, upgrade_info->fw_data + offset, len);
|
|
} else if (file_type == UPGRADE_DATA_TYPE_CUS) {
|
|
os_mem_cpy(buf, upgrade_info->cus_data + offset, len);
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
#else
|
|
uint32_t data_pos = 0;
|
|
uint8_t read_file_type = UPGRADE_DATA_TYPE_FW;
|
|
|
|
if (file_type == UPGRADE_DATA_TYPE_PIB) {
|
|
data_pos = upgrade_info->pib_start;
|
|
} else if (file_type == UPGRADE_DATA_TYPE_FW) {
|
|
data_pos = upgrade_info->fw_start;
|
|
} else if (file_type == UPGRADE_DATA_TYPE_CUS) {
|
|
read_file_type = UPGRADE_DATA_TYPE_CUS;
|
|
data_pos = upgrade_info->cus_start;
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
ret = cli_upgrade_read_data_from_flash(read_file_type, data_pos + offset,
|
|
buf, (uint16_t)len);
|
|
if (ret != UPGRADE_DATA_SUCCESS) {
|
|
ret = ERR_FAIL;
|
|
}
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
iot_plc_upgrade_dest_desc_t *
|
|
cli_remote_upgrade_find_init_dest_from_idx(uint16_t start_idx)
|
|
{
|
|
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_INIT ==
|
|
upgrade_info->dest_info.upgrading_list[start_idx]->status) {
|
|
dest = upgrade_info->dest_info.upgrading_list[start_idx];
|
|
upgrade_info->dest_info.upgrading_list_idx = start_idx + 1;
|
|
break;
|
|
}
|
|
start_idx++;
|
|
}
|
|
return dest;
|
|
}
|
|
|
|
/* cco add multi node start upgrade command */
|
|
uint32_t cli_remote_upgrade_multi_node_start_notify(uint8_t send_type,
|
|
uint8_t phase_flag)
|
|
{
|
|
iot_plc_upgrade_start_dl_t *start_dl;
|
|
iot_pkt_t *pkt = NULL;
|
|
uint32_t len;
|
|
iot_plc_upgrade_dest_desc_t *dest;
|
|
uint8_t *list_mac;
|
|
uint8_t sta_cnt;
|
|
uint32_t ret = ERR_OK;
|
|
iot_plc_upgrade_cust_start_dl_t *cus_start = NULL;
|
|
|
|
len = IOT_MAC_ADDR_LEN * IOT_PLC_UPGRADE_BROADCAST_STA_MAX_CNT;
|
|
len += sizeof(*start_dl);
|
|
if (upgrade_info->cus_size) {
|
|
len += sizeof(iot_plc_upgrade_cust_start_dl_t);
|
|
}
|
|
pkt = iot_pkt_alloc(len, IOT_CLI_MID);
|
|
if (!pkt) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
list_mac = iot_pkt_data(pkt) + sizeof(*start_dl);
|
|
for (sta_cnt = 0; sta_cnt < IOT_PLC_UPGRADE_BROADCAST_STA_MAX_CNT;
|
|
sta_cnt++) {
|
|
//find next start sta
|
|
dest = cli_remote_upgrade_find_init_dest_from_idx(
|
|
upgrade_info->dest_info.upgrading_list_idx);
|
|
if (!dest) {
|
|
break;
|
|
}
|
|
iot_mac_addr_cpy(list_mac + (sta_cnt * IOT_MAC_ADDR_LEN),
|
|
dest->entry.addr);
|
|
}
|
|
|
|
if (upgrade_info->cus_size) {
|
|
cus_start = (iot_plc_upgrade_cust_start_dl_t *)
|
|
(list_mac + (sta_cnt * IOT_MAC_ADDR_LEN));
|
|
}
|
|
|
|
if (sta_cnt) {
|
|
len = sizeof(*start_dl) + IOT_MAC_ADDR_LEN * sta_cnt;
|
|
if (upgrade_info->cus_size) {
|
|
len += sizeof(iot_plc_upgrade_cust_start_dl_t);
|
|
}
|
|
start_dl = (iot_plc_upgrade_start_dl_t *)iot_pkt_data(pkt);
|
|
start_dl->phase_flag = phase_flag;
|
|
start_dl->upgrade_id = upgrade_info->upgrade_id;
|
|
start_dl->fw_checksum = upgrade_info->fw_checksum;
|
|
start_dl->pib_checksum = upgrade_info->pib_checksum;
|
|
start_dl->block_size = upgrade_info->remote_block_size;
|
|
start_dl->fw_size = upgrade_info->fw_size;
|
|
start_dl->fw_version = upgrade_info->fw_version;
|
|
start_dl->pib_size = (uint16_t)upgrade_info->pib_size;
|
|
start_dl->pib_version = upgrade_info->pib_version;
|
|
start_dl->upgrade_type = upgrade_info->upgrade_type;
|
|
start_dl->remote_block_cnt = upgrade_info->remote_block_cnt;
|
|
start_dl->remote_block_size = upgrade_info->remote_block_size;
|
|
start_dl->time_window = upgrade_info->time_window;
|
|
start_dl->dst_num = sta_cnt;
|
|
start_dl->control_flag = upgrade_info->control_upgrade_flag;
|
|
if (upgrade_info->cus_size) {
|
|
cus_start->cus_size = (uint16_t)upgrade_info->cus_size;
|
|
cus_start->cus_checksum = upgrade_info->cus_checksum;
|
|
cus_start->cus_version = upgrade_info->cus_version;
|
|
start_dl->cus_upgrade_flag = 1;
|
|
} else {
|
|
start_dl->cus_upgrade_flag = 0;
|
|
}
|
|
|
|
iot_cli_module_send_data_with_retry(send_type,
|
|
IOT_PLC_UPGRADE_START_RETRY_TIMES,
|
|
CLI_MODULEID_HOSTINTERFACE,
|
|
CLI_MSGID_REMOTE_UPGRADE_START, NULL, NULL,
|
|
(uint8_t*)start_dl, len);
|
|
}
|
|
if (sta_cnt >= IOT_PLC_UPGRADE_BROADCAST_STA_MAX_CNT) {
|
|
ret = ERR_AGAIN;
|
|
}
|
|
out:
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* cco upgrade timer handler */
|
|
void iot_cli_upgrade_cco_handle_timer_msg()
|
|
{
|
|
uint8_t phase3_node_cnt = 0;
|
|
uint16_t phase3_interval = 0;
|
|
|
|
host_info->link_load = iot_plc_get_link_load();
|
|
switch (upgrade_info->upgrade_state) {
|
|
case IOT_PLC_UPGRADE_INIT:
|
|
{
|
|
break;
|
|
}
|
|
case IOT_PLC_UPGRADE_STARTING:
|
|
{
|
|
/* list node upgrade, continue broadcast start upgrade */
|
|
cli_remote_upgrade_broadcast_start_sta_list(false);
|
|
break;
|
|
}
|
|
case IOT_PLC_UPGRADE_STARTED:
|
|
{
|
|
if (host_info->link_load < IOT_PLC_UPGRADE_LINK_LOAD_LIMIT) {
|
|
if (upgrade_info->bcast_wait_flag == 0) {
|
|
/* continue broadcast upgrade data */
|
|
cli_remote_upgrade_cco_broadcast_data(false);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_UPGRADE_TRANSFERRED:
|
|
{
|
|
upgrade_info->action_times++;
|
|
cli_remote_upgrade_initialize_latest_block();
|
|
if (0 == (upgrade_info->action_times %
|
|
IOT_PLC_UPGRADE_LONG_TIMER_CNT)) {
|
|
if (upgrade_info->request_times) {
|
|
upgrade_info->request_times /= IOT_PLC_UPGRADE_LONG_TIMER_CNT;
|
|
if ((cli_remote_upgrade_calculate_time_window(
|
|
upgrade_info->request_times) *
|
|
IOT_PLC_UPGRADE_TIME_WINDOW_ADJ_VALUE2) <
|
|
upgrade_info->time_window) {
|
|
iot_printf("plc_upgrade: request times %lu,"
|
|
" new time window %lu, old time window %lu\n",
|
|
upgrade_info->request_times,
|
|
cli_remote_upgrade_calculate_time_window(
|
|
upgrade_info->request_times),
|
|
upgrade_info->time_window);
|
|
upgrade_info->time_window =
|
|
(uint16_t)(upgrade_info->time_window *
|
|
IOT_PLC_UPGRADE_TIME_WINDOW_ADJ_VALUE1);
|
|
}
|
|
upgrade_info->request_times = 0;
|
|
}
|
|
|
|
if ((!upgrade_info->recv_req_flag) &&
|
|
((IOT_PLC_UPGRADE_ALL == upgrade_info->upgrade_type) ||
|
|
(IOT_PLC_UPGRADE_STA_LIST == upgrade_info->upgrade_type))) {
|
|
cli_remote_upgrade_start_sub_nodes();
|
|
}
|
|
/* clean recv req flag */
|
|
upgrade_info->recv_req_flag = 0;
|
|
}
|
|
|
|
// check if need to start phase 3
|
|
if ((IOT_PLC_UPGRADE_STA_LIST == upgrade_info->upgrade_type) ||
|
|
(upgrade_info->dest_info.dst_transferred_num >
|
|
(upgrade_info->dest_info.dst_total_num *
|
|
IOT_PLC_UPGRADE_PHASE_THREE_THRESHOLD))) {
|
|
iot_printf("plc_upgrade:upgraded sta num %lu,"
|
|
" total num %lu\n",
|
|
upgrade_info->dest_info.dst_transferred_num,
|
|
upgrade_info->dest_info.dst_total_num);
|
|
// initialize upgrading list for the first time
|
|
if (IOT_PLC_UPGRADE_ALL == upgrade_info->upgrade_type) {
|
|
if (upgrade_info->dst_list_idx == 0) {
|
|
cli_remote_upgrade_initialize_upgrading_list();
|
|
}
|
|
}
|
|
|
|
if (!upgrade_info->calc_time_window_flag) {
|
|
upgrade_info->calc_time_window_flag = 1;
|
|
if (upgrade_info->control_upgrade_flag) {
|
|
phase3_interval =
|
|
cli_remote_upgrade_get_resend_time_window(
|
|
upgrade_info->dest_info.dst_total_num);
|
|
upgrade_info->dest_info.query_node_timeout =
|
|
IOT_PLC_UPGRADE_QUERY_NODE_INFO_TIMEOUT / phase3_interval;
|
|
|
|
cli_upgrade_reset_timer(1, phase3_interval);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (upgrade_info->control_upgrade_flag) {
|
|
phase3_node_cnt = cli_remote_upgrade_resend_phase();
|
|
}
|
|
|
|
// start uncompleted sta
|
|
phase3_node_cnt += cli_remote_upgrade_start_phase_three();
|
|
}
|
|
|
|
if (IOT_PLC_UPGRADE_ALL == upgrade_info->upgrade_type) {
|
|
if ((0 == (upgrade_info->action_times %
|
|
IOT_PLC_UPGRADE_COMPLETE_CHECK_TIMER_CNT))) {
|
|
iot_printf("plc_upgrade:cco complete upgrade %lu\n",
|
|
upgrade_info->sta_upgrade_active);
|
|
if (upgrade_info->sta_upgrade_active) {
|
|
upgrade_info->sta_upgrade_active = 0;
|
|
} else {
|
|
if (upgrade_info->completed_handler) {
|
|
upgrade_info->completed_handler();
|
|
}
|
|
}
|
|
}
|
|
} else if ((!phase3_node_cnt) && upgrade_info->completed_handler) {
|
|
upgrade_info->completed_handler();
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_UPGRADE_STOPED:
|
|
{
|
|
if (upgrade_info->action_times <
|
|
IOT_PLC_UPGRADE_STOP_RETRY_TIMES) {
|
|
uint8_t dest[IOT_MAC_ADDR_LEN] = { 0 };
|
|
iot_plc_upgrade_stop_dl_t stop_dl;
|
|
iot_cli_host_send_data_plc(IOT_PLC_MSG_TYPE_BCAST,
|
|
CLI_MSGID_UPGRADE_STOP, dest,
|
|
(uint8_t*)&stop_dl, sizeof(stop_dl));
|
|
upgrade_info->action_times++;
|
|
} else {
|
|
// cco stop after broadcast stop
|
|
cli_remote_upgrade_coo_stop();
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_INIT;
|
|
upgrade_info->action_times = 0;
|
|
upgrade_info->calc_time_window_flag = 0;
|
|
upgrade_info->node_response_flag = 1;
|
|
upgrade_info->resend_data_state = CLI_QUERY_NODE;
|
|
upgrade_info->query_node_retry_cnt = 0;
|
|
upgrade_info->control_upgrade_flag = 0;
|
|
iot_printf("plc_upgrade:cco stop upgrade\n");
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_UPGRADE_RESET:
|
|
{
|
|
if (upgrade_info->action_times <
|
|
IOT_PLC_UPGRADE_RESET_RETRY_TIMES) {
|
|
uint8_t dest[IOT_MAC_ADDR_LEN] = { 0 };
|
|
iot_plc_upgrade_reset_dl_t reset_dl;
|
|
iot_cli_host_send_data_plc(IOT_PLC_MSG_TYPE_BCAST,
|
|
CLI_MSGID_UPGRADE_RESET, dest,
|
|
(uint8_t*)&reset_dl, sizeof(reset_dl));
|
|
upgrade_info->action_times++;
|
|
} else {
|
|
cli_remote_upgrade_coo_stop();
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_INIT;
|
|
upgrade_info->action_times = 0;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
//IOT_ASSERT(0); // invalid state
|
|
break;
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
/* sta/pco upgrade timer handler */
|
|
void iot_cli_upgrade_sta_handle_timer_msg()
|
|
{
|
|
switch (upgrade_info->upgrade_state) {
|
|
case IOT_PLC_UPGRADE_INIT:
|
|
case IOT_PLC_UPGRADE_LISTEN:
|
|
{
|
|
break;
|
|
}
|
|
case IOT_PLC_UPGRADE_STARTING:
|
|
{
|
|
//sta send data request
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_STARTED;
|
|
cli_remote_upgrade_sta_send_request_data(false);
|
|
cli_upgrade_reset_timer(1, upgrade_info->time_window);
|
|
break;
|
|
}
|
|
case IOT_PLC_UPGRADE_STARTED:
|
|
{
|
|
upgrade_info->last_timer_time = os_boot_time32();
|
|
if (upgrade_info->skip_timer) {
|
|
upgrade_info->skip_timer = false;
|
|
return;
|
|
}
|
|
//sta send data request
|
|
cli_remote_upgrade_sta_send_request_data(false);
|
|
break;
|
|
}
|
|
case IOT_PLC_UPGRADE_TRANSFERRED:
|
|
{
|
|
if ((IOT_PLC_DEV_ROLE_PCO == host_config->dev_role) &&
|
|
((IOT_PLC_UPGRADE_ALL == upgrade_info->upgrade_type) ||
|
|
(IOT_PLC_UPGRADE_STA_LIST == upgrade_info->upgrade_type))) {
|
|
upgrade_info->action_times++;
|
|
cli_remote_upgrade_initialize_latest_block();
|
|
if (0 == (upgrade_info->action_times %
|
|
IOT_PLC_UPGRADE_LONG_TIMER_CNT)) {
|
|
if (upgrade_info->request_times) {
|
|
upgrade_info->request_times /=
|
|
IOT_PLC_UPGRADE_LONG_TIMER_CNT;
|
|
|
|
if ((cli_remote_upgrade_calculate_time_window(
|
|
upgrade_info->request_times) *
|
|
IOT_PLC_UPGRADE_TIME_WINDOW_ADJ_VALUE2) <
|
|
upgrade_info->time_window) {
|
|
iot_printf("plc_upgrade: request times %lu,"
|
|
" new time window %lu, old time window %lu\n",
|
|
upgrade_info->request_times,
|
|
cli_remote_upgrade_calculate_time_window(
|
|
upgrade_info->request_times),
|
|
upgrade_info->time_window);
|
|
upgrade_info->time_window =
|
|
(uint16_t)(upgrade_info->time_window *
|
|
IOT_PLC_UPGRADE_TIME_WINDOW_ADJ_VALUE1);
|
|
}
|
|
upgrade_info->request_times = 0;
|
|
}
|
|
if (!upgrade_info->recv_req_flag) {
|
|
cli_remote_upgrade_start_sub_nodes();
|
|
} else {
|
|
/* clean recv req flag */
|
|
upgrade_info->recv_req_flag = 0;
|
|
}
|
|
}
|
|
} else {
|
|
cli_upgrade_sta_send_upgrade_result(IOT_PLC_MSG_TYPE_UNICAST,
|
|
host_config->mac_addr, host_config->cco_mac,
|
|
UPGRADE_DATA_SUCCESS);
|
|
cli_upgrade_reset_timer(0, 0);
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_UPGRADE_FAILED:
|
|
case IOT_PLC_UPGRADE_START_FAIL:
|
|
{
|
|
cli_upgrade_reset_timer(0, 0);
|
|
break;
|
|
}
|
|
case IOT_PLC_UPGRADE_STOPED:
|
|
case IOT_PLC_UPGRADE_RESET:
|
|
default:
|
|
IOT_ASSERT(0); // invalid state
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endif /* PLC_SUPPORT_CCO_ROLE */
|
|
|
|
/* upgrade timer handler */
|
|
void iot_cli_upgrade_handle_timer_msg()
|
|
{
|
|
switch (host_config->dev_role) {
|
|
case IOT_PLC_DEV_ROLE_CCO:
|
|
{
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
iot_cli_upgrade_cco_handle_timer_msg();
|
|
#endif
|
|
break;
|
|
}
|
|
case IOT_PLC_DEV_ROLE_STA:
|
|
case IOT_PLC_DEV_ROLE_PCO:
|
|
{
|
|
#if !PLC_SUPPORT_CCO_ROLE
|
|
iot_cli_upgrade_sta_handle_timer_msg();
|
|
#endif
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
uint32_t cli_upgrade_write_data_to_flash_cache_init(uint32_t upgrade_id,
|
|
uint32_t fw_size, uint32_t cus_sise, uint32_t block_size)
|
|
{
|
|
iot_upgrade_cancel_commit(0);
|
|
upgrade_info->src.block_size = block_size;
|
|
upgrade_info->src.fw_size = fw_size;
|
|
upgrade_info->src.pib_size = 0;
|
|
upgrade_info->src.cus_size = cus_sise;
|
|
upgrade_info->src.id = upgrade_id;
|
|
upgrade_info->src.fw_crc = 0;
|
|
upgrade_info->src.pib_crc = 0;
|
|
upgrade_info->src.fw_version = 0;
|
|
upgrade_info->src.crc_check_cb = NULL;
|
|
upgrade_info->src.read_block_cb = NULL;
|
|
upgrade_info->src.write_block_cb = NULL;
|
|
|
|
return iot_upgrade_start(&upgrade_info->result, &upgrade_info->src);
|
|
}
|
|
|
|
/* check if block is blank */
|
|
uint8_t cli_upgrade_block_blank_check(
|
|
uint8_t file_type, uint16_t block_index)
|
|
{
|
|
iot_upg_block_info_rst rst;
|
|
iot_upg_block_info_src src;
|
|
rst.blank = false;
|
|
src.id = upgrade_info->src.id;
|
|
src.file_type = file_type;
|
|
src.block_index = block_index;
|
|
|
|
iot_upgrade_query_block_info(&rst, &src);
|
|
|
|
return rst.blank;
|
|
}
|
|
|
|
/* write fw data to flash */
|
|
uint8_t cli_upgrade_write_data_to_flash(uint8_t file_type, uint16_t block_cnt,
|
|
uint16_t *block_idx_array, uint16_t *block_size_array, uint8_t *data)
|
|
{
|
|
iot_trans_cmd_t trans;
|
|
iot_pkt_t *block_data = NULL;
|
|
uint32_t begin_index = 0;
|
|
uint16_t i;
|
|
|
|
for (i = 0; i < block_cnt; i++) {
|
|
if (cli_upgrade_block_blank_check(file_type, block_idx_array[i])) {
|
|
trans.id = upgrade_info->src.id;
|
|
block_data = iot_pkt_alloc(block_size_array[i], IOT_CLI_MID);
|
|
|
|
if (!block_data) {
|
|
return UPGRADE_DATA_CLI_NO_MEM;
|
|
}
|
|
|
|
trans.block_num = block_idx_array[i];
|
|
trans.data = block_data;
|
|
trans.data_type = file_type;
|
|
|
|
os_mem_cpy(iot_pkt_data(block_data), data + begin_index,
|
|
block_size_array[i]);
|
|
iot_pkt_put(block_data, block_size_array[i]);
|
|
iot_upgrade_trans(&trans);
|
|
|
|
//upgrade_info->remote_written_blocks++;
|
|
|
|
#if PLC_SUPPORT_UPGRADE_DEBUG
|
|
iot_printf("write data to flash. %d bytes,"
|
|
"index:%d, blocks:%d\n", trans.block_size,
|
|
block_idx_array[i], upgrade_info->remote_written_blocks);
|
|
#endif
|
|
|
|
}
|
|
begin_index += block_size_array[i];
|
|
}
|
|
|
|
return UPGRADE_DATA_SUCCESS;
|
|
}
|
|
|
|
uint8_t cli_upgrade_read_data_from_flash(uint8_t file_type, uint32_t offset,
|
|
uint8_t *data, uint16_t data_len)
|
|
{
|
|
if ((file_type != UPGRADE_DATA_TYPE_FW) &&
|
|
(file_type != UPGRADE_DATA_TYPE_PIB) &&
|
|
(file_type != UPGRADE_DATA_TYPE_CUS)) {
|
|
return UPGRADE_DATA_INVALID_DATA;
|
|
}
|
|
|
|
iot_pkg_upgrade_read(data, data_len, offset, file_type, 1);
|
|
|
|
return UPGRADE_DATA_SUCCESS;
|
|
}
|
|
|
|
/* check if data receive done */
|
|
bool_t cli_upgrade_check_data_recv_done(uint8_t file_type)
|
|
{
|
|
if (UPGRADE_DATA_TYPE_FW == file_type) {
|
|
if (upgrade_info->block_idx >= upgrade_info->fw_blocks) {
|
|
iot_printf("fw done\n");
|
|
upgrade_info->fw_recv_done = 1;
|
|
upgrade_info->block_idx = 0;
|
|
}
|
|
} else if(UPGRADE_DATA_TYPE_PIB == file_type) {
|
|
if (upgrade_info->block_idx >= upgrade_info->pib_blocks) {
|
|
iot_printf("pib done\n");
|
|
upgrade_info->pib_recv_done = 1;
|
|
upgrade_info->block_idx = 0;
|
|
}
|
|
} else {
|
|
if (upgrade_info->block_idx >= upgrade_info->cus_blocks) {
|
|
iot_printf("cus done\n");
|
|
upgrade_info->cus_recv_done = 1;
|
|
upgrade_info->block_idx = 0;
|
|
}
|
|
}
|
|
|
|
if (upgrade_info->fw_recv_done && upgrade_info->pib_recv_done &&
|
|
upgrade_info->cus_recv_done) {
|
|
// reset these value when recv file done.
|
|
upgrade_info->fw_recv_done = 0;
|
|
upgrade_info->pib_recv_done = 0;
|
|
upgrade_info->cus_recv_done = 0;
|
|
upgrade_info->block_idx = 0;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/* handle upgrade start command from plc manager */
|
|
void cli_upgrade_start(uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
iot_plc_upgrade_start_ul_t ack;
|
|
iot_plc_upgrade_start_dl_t *data;
|
|
data = (iot_plc_upgrade_start_dl_t *)buffer;
|
|
iot_plc_upgrade_cust_start_dl_t cus_info;
|
|
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
os_mem_set(upgrade_info->upgrade_src_mac, 0, IOT_MAC_ADDR_LEN);
|
|
if (src_mac) {
|
|
iot_mac_addr_cpy(upgrade_info->upgrade_src_mac, src_mac);
|
|
}
|
|
#endif
|
|
/* ckb p2p upgrade sta */
|
|
add_addr_to_mapping_table(src_mac);
|
|
iot_printf("plc_upgrade:cco recv upgrade start, role:%d\n",
|
|
host_config->dev_role);
|
|
|
|
if ((!data) || (bufferlen < (sizeof(*data)))) {
|
|
iot_printf("%s param error\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if (data->cus_upgrade_flag) {
|
|
if (bufferlen < (sizeof(*data) + data->dst_num * IOT_MAC_ADDR_LEN +
|
|
sizeof(cus_info))) {
|
|
iot_printf("%s data len error\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
os_mem_cpy((uint8_t *)&cus_info,
|
|
(data->dst + data->dst_num * IOT_MAC_ADDR_LEN),
|
|
sizeof(iot_plc_upgrade_cust_start_dl_t));
|
|
} else {
|
|
if (bufferlen < (sizeof(*data) + data->dst_num * IOT_MAC_ADDR_LEN)) {
|
|
iot_printf("%s data len error\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
os_mem_set((uint8_t *)&cus_info, 0, sizeof(cus_info));
|
|
}
|
|
|
|
if (upgrade_info->upgrade_state != IOT_PLC_UPGRADE_INIT) {
|
|
ack.result = UPGRADE_START_CCO_UPGRADING;
|
|
goto err_exit;
|
|
}
|
|
|
|
ack.result = cli_upgrade_type_check(data);
|
|
if (UPGRADE_START_OK != ack.result) {
|
|
goto err_exit;
|
|
}
|
|
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
/* set plc manager upgrade flag */
|
|
host_config->cli_upgrade_enabled = 1;
|
|
#endif
|
|
|
|
cli_upgrade_info_initialize(data);
|
|
if (IOT_PLC_UPGRADE_LOCAL == upgrade_info->upgrade_type) {
|
|
cli_upgrade_flash_info_initialize(data->block_size, data->fw_size,
|
|
data->pib_size, cus_info.cus_size, data->upgrade_id,
|
|
data->fw_checksum, data->pib_checksum, cus_info.cus_checksum,
|
|
data->fw_version);
|
|
}
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
else {
|
|
if ((upgrade_info->full_bitmap == NULL) &&
|
|
upgrade_info->control_upgrade_flag) {
|
|
upgrade_info->full_bitmap =
|
|
os_mem_malloc(IOT_CLI_MID, IOT_PLC_UPGRADE_STA_BM_SIZE_MAX);
|
|
if (upgrade_info->full_bitmap == NULL) {
|
|
ack.result = UPGRADE_START_OTHER_ERROR;
|
|
goto err_exit;
|
|
}
|
|
}
|
|
upgrade_info->phase_one_broadcast_times =
|
|
data->phase_one_broadcast_times;
|
|
|
|
iot_printf("p1_bcast_times %d\n",
|
|
upgrade_info->phase_one_broadcast_times);
|
|
|
|
#if IOT_CLI_UPGRADE_CACHE_TYPE
|
|
cli_upgrade_buffer_initialize();
|
|
#else
|
|
uint32_t fw_size = 0;
|
|
upgrade_info->pib_start = 0;
|
|
upgrade_info->cus_start = 0;
|
|
upgrade_info->fw_start =
|
|
((data->pib_size + (data->block_size - 1)) / data->block_size) *
|
|
data->block_size;
|
|
if (upgrade_info->fw_size) {
|
|
fw_size = upgrade_info->fw_size + upgrade_info->fw_start;
|
|
} else {
|
|
fw_size = upgrade_info->pib_size;
|
|
}
|
|
if (cli_upgrade_write_data_to_flash_cache_init(data->upgrade_id,
|
|
fw_size, upgrade_info->cus_size, data->block_size) !=
|
|
ERR_OK) {
|
|
ack.result = UPGRADE_START_OTHER_ERROR;
|
|
goto err_exit;
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
ack.result = UPGRADE_START_OK;
|
|
iot_mac_addr_cpy(ack.dst, host_config->mac_addr);
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_STARTING;
|
|
err_exit:
|
|
iot_printf("plc_upgrade:upgrade start, ack.result: %d\n", ack.result);
|
|
iot_cli_send_to_host(CLI_MSGID_UPGRADE_START_ACK, (uint8_t *)&ack,
|
|
sizeof(ack), src_mac);
|
|
}
|
|
|
|
/* handle upgrade data command */
|
|
void cli_upgrade_data(uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
uint16_t index = 0;
|
|
bool_t recv_done = false;
|
|
iot_plc_upgrade_data_ack_ul_t ack;
|
|
iot_plc_upgrade_data_dl_t *data = NULL;
|
|
data = (iot_plc_upgrade_data_dl_t *)buffer;
|
|
|
|
(void)index;
|
|
if ((!data) || (bufferlen < sizeof(*data))) {
|
|
iot_printf("%s param error", __FUNCTION__);
|
|
return;
|
|
}
|
|
/* ckb p2p upgrade sta */
|
|
add_addr_to_mapping_table(src_mac);
|
|
iot_printf("plc_upgrade:recv upgrade data\n");
|
|
cli_upgrade_print_block_info(data);
|
|
|
|
ack.file_type = data->file_type;
|
|
ack.upgrade_id = data->upgrade_id;
|
|
ack.block_idx = data->block_idx_array[0];
|
|
|
|
ack.error_code = cli_upgrade_data_check(data->block_cnt,
|
|
data->block_idx_array, data->block_size_array,
|
|
data->data, data->file_type);
|
|
if (UPGRADE_DATA_SUCCESS != ack.error_code) {
|
|
if (UPGRADE_DATA_BLOCK_IDX_ERROR != ack.error_code) {
|
|
goto err_exit;
|
|
}
|
|
if ((COMMUNICATOR_BT != cli.commu.type) ||
|
|
(IOT_PLC_UPGRADE_LOCAL != upgrade_info->upgrade_type)) {
|
|
ack.block_idx = upgrade_info->block_idx;
|
|
if (upgrade_info->pib_recv_done)
|
|
{
|
|
ack.file_type = UPGRADE_DATA_TYPE_FW;
|
|
} else {
|
|
ack.file_type = UPGRADE_DATA_TYPE_PIB;
|
|
}
|
|
goto err_exit;
|
|
}
|
|
}
|
|
|
|
/* write data to flash directly only if it's local upgrade */
|
|
if (IOT_PLC_UPGRADE_LOCAL == upgrade_info->upgrade_type) {
|
|
if (upgrade_info->upgrade_state == IOT_PLC_UPGRADE_TRANSFERRED) {
|
|
ack.error_code = UPGRADE_DATA_DUPLICATE;
|
|
goto err_exit;
|
|
}
|
|
if (upgrade_info->upgrade_state == IOT_PLC_UPGRADE_INIT) {
|
|
ack.error_code = UPGRADE_DATA_STA_STOP;
|
|
goto err_exit;
|
|
}
|
|
ack.error_code = cli_upgrade_write_data_to_flash(data->file_type,
|
|
data->block_cnt, data->block_idx_array, data->block_size_array,
|
|
data->data);
|
|
if (UPGRADE_DATA_SUCCESS != ack.error_code) {
|
|
goto err_exit;
|
|
}
|
|
}
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
else {
|
|
#if IOT_CLI_UPGRADE_CACHE_TYPE
|
|
cli_upgrade_write_data_to_buffer(data->file_type, data->block_cnt,
|
|
data->block_idx_array, data->block_size_array, data->data);
|
|
#else
|
|
uint8_t file_type = UPGRADE_DATA_TYPE_FW;
|
|
|
|
if (data->file_type == UPGRADE_DATA_TYPE_CUS) {
|
|
file_type = UPGRADE_DATA_TYPE_CUS;
|
|
}
|
|
if (data->file_type == UPGRADE_DATA_TYPE_FW) {
|
|
index = (uint16_t)((upgrade_info->pib_size +
|
|
(upgrade_info->block_size - 1)) / upgrade_info->block_size);
|
|
}
|
|
|
|
for (uint8_t i = 0; i < data->block_cnt; i++) {
|
|
data->block_idx_array[i] += index;
|
|
}
|
|
cli_upgrade_write_data_to_flash(file_type, data->block_cnt,
|
|
data->block_idx_array, data->block_size_array, data->data);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
upgrade_info->block_idx += data->block_cnt;
|
|
|
|
if ((COMMUNICATOR_BT != cli.commu.type) ||
|
|
(IOT_PLC_UPGRADE_LOCAL != upgrade_info->upgrade_type)) {
|
|
recv_done = cli_upgrade_check_data_recv_done(data->file_type);
|
|
}
|
|
if (recv_done) {
|
|
if (IOT_PLC_UPGRADE_LOCAL == upgrade_info->upgrade_type) {
|
|
iot_upgrade_commit(upgrade_info->src.id);
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_TRANSFERRED;
|
|
}
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
else if (IOT_PLC_UPGRADE_STA_LIST == upgrade_info->upgrade_type) {
|
|
upgrade_info->completed_handler = cli_remote_upgrade_complete;
|
|
cli_remote_upgrade_sta_list_start();
|
|
} else if (IOT_PLC_UPGRADE_ALL == upgrade_info->upgrade_type) {
|
|
cli_remote_upgrade_all_sta_start();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
ack.error_code = UPGRADE_DATA_SUCCESS;
|
|
err_exit:
|
|
iot_printf("plc_upgrade:send ack. error_code = %d\n", ack.error_code);
|
|
iot_cli_send_to_host(CLI_MSGID_UPGRADE_DATA_ACK,
|
|
(uint8_t *)&ack, sizeof(ack), src_mac);
|
|
}
|
|
|
|
/* cco/pco send start command to target STA */
|
|
void cli_remote_upgrade_send_start_notify(uint8_t send_type,
|
|
uint8_t *sta_mac, uint8_t *dest_mac, uint8_t phase_flag)
|
|
{
|
|
iot_plc_upgrade_start_dl_t *start_dl;
|
|
iot_pkt_t *pkt;
|
|
uint32_t len;
|
|
iot_plc_upgrade_cust_start_dl_t *cus_start = NULL;
|
|
|
|
if ((!sta_mac) || (!dest_mac)) {
|
|
return;
|
|
}
|
|
len = sizeof(*start_dl) + IOT_MAC_ADDR_LEN;
|
|
if (upgrade_info->cus_size) {
|
|
len += sizeof(iot_plc_upgrade_cust_start_dl_t);
|
|
}
|
|
pkt = iot_pkt_alloc(len, IOT_CLI_MID);
|
|
if (!pkt) {
|
|
return;
|
|
}
|
|
|
|
start_dl = (iot_plc_upgrade_start_dl_t *)iot_pkt_data(pkt);
|
|
if (upgrade_info->cus_size) {
|
|
cus_start = (iot_plc_upgrade_cust_start_dl_t *)
|
|
(start_dl + sizeof(*start_dl) + IOT_MAC_ADDR_LEN);
|
|
}
|
|
start_dl->phase_flag = phase_flag;
|
|
start_dl->upgrade_id = upgrade_info->upgrade_id;
|
|
start_dl->fw_checksum = upgrade_info->fw_checksum;
|
|
start_dl->pib_checksum = upgrade_info->pib_checksum;
|
|
start_dl->block_size = upgrade_info->remote_block_size;
|
|
start_dl->fw_size = upgrade_info->fw_size;
|
|
start_dl->fw_version = upgrade_info->fw_version;
|
|
start_dl->pib_size = (uint16_t)upgrade_info->pib_size;
|
|
start_dl->pib_version = upgrade_info->pib_version;
|
|
start_dl->upgrade_type = upgrade_info->upgrade_type;
|
|
start_dl->remote_block_cnt = upgrade_info->remote_block_cnt;
|
|
start_dl->remote_block_size = upgrade_info->remote_block_size;
|
|
start_dl->time_window = upgrade_info->time_window;
|
|
start_dl->dst_num = 1;
|
|
start_dl->control_flag = upgrade_info->control_upgrade_flag;
|
|
iot_mac_addr_cpy(start_dl->dst, dest_mac);
|
|
if (upgrade_info->cus_size) {
|
|
cus_start->cus_size = (uint16_t)upgrade_info->cus_size;
|
|
cus_start->cus_checksum = upgrade_info->cus_checksum;
|
|
cus_start->cus_version = upgrade_info->cus_version;
|
|
start_dl->cus_upgrade_flag = 1;
|
|
} else {
|
|
start_dl->cus_upgrade_flag = 0;
|
|
}
|
|
|
|
iot_cli_module_send_data_with_retry(send_type,
|
|
IOT_PLC_UPGRADE_START_RETRY_TIMES,
|
|
CLI_MODULEID_HOSTINTERFACE,
|
|
CLI_MSGID_REMOTE_UPGRADE_START, host_config->mac_addr, sta_mac,
|
|
(uint8_t*)start_dl, len);
|
|
iot_pkt_free(pkt);
|
|
}
|
|
|
|
/* start sub nodes to upgrade */
|
|
void cli_remote_upgrade_start_sub_nodes()
|
|
{
|
|
uint8_t dest[IOT_MAC_ADDR_LEN] = { 0xFF };
|
|
iot_printf("plc_upgrade: start sub nodes\n");
|
|
cli_upgrade_print_mac_info(host_config->mac_addr);
|
|
cli_remote_upgrade_send_start_notify(
|
|
IOT_PLC_MSG_TYPE_BCAST_1HOP, dest, dest, UPGRADE_START_UPGRADE_PHASE2);
|
|
}
|
|
|
|
uint32_t cli_upgrade_is_unicast_to_broadcast(
|
|
iot_plc_upgrade_remote_data_dl *data)
|
|
{
|
|
if (iot_mac_addr_cmp(host_config->mac_addr, data->dst) && data->fwd_type) {
|
|
return ERR_OK;
|
|
}
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
/* create date packet for remote upgrade */
|
|
static iot_pkt_t *cli_remote_create_remote_data_packet(uint8_t send_type,
|
|
uint8_t retry_cnt, uint8_t *dst, uint16_t block_size, uint32_t upgrade_id,
|
|
uint8_t control_byte, uint8_t file_type, uint16_t block_idx,
|
|
uint8_t fwd_type)
|
|
{
|
|
iot_pkt_t *data_pkt = NULL;
|
|
uint32_t data_len = block_size + sizeof(iot_plc_upgrade_remote_data_dl);
|
|
|
|
data_pkt = iot_cli_create_pkt_plc(send_type, retry_cnt,
|
|
CLI_MODULEID_HOSTINTERFACE, CLI_MSGID_REMOTE_UPGRADE_DATA, NULL, dst,
|
|
dst, data_len);
|
|
|
|
if (data_pkt) {
|
|
iot_plc_upgrade_remote_data_dl *data = NULL;
|
|
data = (iot_plc_upgrade_remote_data_dl *)
|
|
iot_pkt_block_ptr(data_pkt, IOT_PKT_BLOCK_TAIL);
|
|
|
|
data->fwd_type = fwd_type;
|
|
data->upgrade_id = upgrade_id;
|
|
data->block_cnt = 1;
|
|
data->block_idx_array[0] = block_idx;
|
|
data->block_size_array[0] = block_size;
|
|
data->fw_size = upgrade_info->fw_size;
|
|
data->pib_size = (uint16_t)upgrade_info->pib_size;
|
|
data->cus_size = (uint16_t)upgrade_info->cus_size;
|
|
data->block_size = upgrade_info->remote_block_size;
|
|
data->fw_checksum = upgrade_info->fw_checksum;
|
|
data->pib_checksum = upgrade_info->pib_checksum;
|
|
data->cus_checksum = upgrade_info->cus_checksum;
|
|
data->contol_byte = control_byte;
|
|
data->time_window = upgrade_info->time_window;
|
|
data->remote_block_cnt = upgrade_info->remote_block_cnt;
|
|
data->file_type = file_type;
|
|
iot_mac_addr_cpy(data->dst, dst);
|
|
}
|
|
|
|
return data_pkt;
|
|
}
|
|
|
|
/* send data for remote upgrade */
|
|
void cli_remote_upgrade_send_data(uint8_t send_type, uint8_t retry_cnt,
|
|
uint8_t *dst, uint32_t upgrade_id, uint8_t file_type, uint8_t control_byte,
|
|
uint16_t block_size, uint16_t* block_idx_array, uint16_t block_cnt,
|
|
uint8_t fwd_type, iot_pkt_free_func_t bcast_tx_done_func)
|
|
{
|
|
uint32_t file_size = 0;
|
|
uint32_t blocks = 0;
|
|
|
|
if (block_cnt) {
|
|
if (file_type == UPGRADE_DATA_TYPE_PIB) {
|
|
file_size = upgrade_info->pib_size;
|
|
blocks = upgrade_info->pib_blocks;
|
|
} else if (file_type == UPGRADE_DATA_TYPE_FW) {
|
|
file_size = upgrade_info->fw_size;
|
|
blocks = upgrade_info->fw_blocks;
|
|
} else if (file_type == UPGRADE_DATA_TYPE_CUS) {
|
|
file_size = upgrade_info->cus_size;
|
|
blocks = upgrade_info->cus_blocks;
|
|
}
|
|
|
|
for (int i = 0; i < block_cnt; i++) {
|
|
iot_pkt_t *packet = cli_remote_create_remote_data_packet(
|
|
send_type, retry_cnt, dst, block_size,
|
|
upgrade_id, control_byte, file_type, block_idx_array[i],
|
|
fwd_type);
|
|
if (packet) {
|
|
iot_plc_upgrade_remote_data_dl * data =
|
|
(iot_plc_upgrade_remote_data_dl *)
|
|
iot_pkt_block_ptr(packet, IOT_PKT_BLOCK_TAIL);
|
|
iot_pkt_put(packet, sizeof(*data));
|
|
|
|
if (block_idx_array[i] <= (blocks - 1)) {
|
|
if (block_idx_array[i] == (blocks - 1)) {
|
|
data->block_size_array[0] =
|
|
(uint16_t)(file_size - (blocks - 1) * block_size);
|
|
}
|
|
|
|
if (data->block_size_array[0] > block_size) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
if (IOT_PLC_DEV_ROLE_CCO != host_config->dev_role) {
|
|
(void)bcast_tx_done_func;
|
|
iot_pkg_upgrade_read(
|
|
data->data, data->block_size_array[0],
|
|
block_idx_array[i] * block_size,
|
|
file_type, 1);
|
|
iot_pkt_put(packet, block_size);
|
|
iot_plc_send_msdu(host_config->app_handle, packet);
|
|
}
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
else {
|
|
cli_upgrade_get_cache_data(file_type,
|
|
block_idx_array[i] * block_size, data->data,
|
|
data->block_size_array[0]);
|
|
if (bcast_tx_done_func &&
|
|
(send_type == IOT_PLC_MSG_TYPE_BCAST)) {
|
|
if (iot_pkt_set_free_callback(packet,
|
|
bcast_tx_done_func, NULL) == ERR_OK) {
|
|
upgrade_info->bcast_wait_flag = 1;
|
|
}
|
|
}
|
|
iot_pkt_put(packet, block_size);
|
|
iot_plc_send_msdu(host_config->app_handle, packet);
|
|
}
|
|
#endif
|
|
|
|
cli_remote_upgrade_update_latest_block(
|
|
file_type, block_idx_array[i]);
|
|
|
|
iot_printf("plc_upgrade:cco send remote data file_type %d"
|
|
" block_index %d, block size %d\n",
|
|
file_type, block_idx_array[i], block_size);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* cco handle remote upgrade data request */
|
|
void cli_remote_upgrade_data_request(
|
|
uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
(void)src_mac;
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
iot_plc_upgrade_dest_desc_t * dest = NULL;
|
|
#endif
|
|
iot_plc_upgrade_remote_data_req_ul_t *req;
|
|
uint8_t send_type = IOT_PLC_MSG_TYPE_BCAST_1HOP;
|
|
uint8_t retry_cnt = IOT_PLC_LOCAL_RETRY_CNT;
|
|
uint8_t control_byte = UPGRADE_REMOTE_ALL_PHASE2_DATA;
|
|
req = (iot_plc_upgrade_remote_data_req_ul_t *)buffer;
|
|
|
|
if ((!req) || (bufferlen < sizeof(*req))) {
|
|
iot_printf("%s param error", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
iot_printf("cco recv request,"
|
|
" %02X:%02X:%02X:%02X:%02X:%02X\n", req->dst[0], req->dst[1],
|
|
req->dst[2], req->dst[3], req->dst[4], req->dst[5]);
|
|
|
|
if ((IOT_PLC_DEV_ROLE_CCO != host_config->dev_role) &&
|
|
(IOT_PLC_DEV_ROLE_PCO != host_config->dev_role)) {
|
|
iot_printf("reject request, role %x\n",
|
|
host_config->dev_role);
|
|
return;
|
|
}
|
|
|
|
if ((IOT_PLC_UPGRADE_TRANSFERRED != upgrade_info->upgrade_state) ||
|
|
(IOT_PLC_UPGRADE_LOCAL == upgrade_info->upgrade_type)) {
|
|
//if (IOT_PLC_DEV_ROLE_CCO == host_config->dev_role) {
|
|
// return;
|
|
//} else if ((IOT_PLC_DEV_ROLE_PCO == host_config->dev_role) &&
|
|
// cli_upgrade_block_blank_check(
|
|
// req->file_type, req->block_idx_array[0])) {
|
|
// return;
|
|
//} else {
|
|
// iot_printf("pco not yet upgraded but has this block\n");
|
|
//}
|
|
return;
|
|
}
|
|
|
|
upgrade_info->request_times++;
|
|
upgrade_info->recv_req_flag = 1;
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
if ((IOT_PLC_DEV_ROLE_CCO == host_config->dev_role) &&
|
|
upgrade_info->dest_info.table) {
|
|
cli_upgrade_print_mac_info(req->dst);
|
|
|
|
upgrade_info->sta_upgrade_active = 1;
|
|
|
|
dest = (iot_plc_upgrade_dest_desc_t *)iot_addr_hash_table_find(
|
|
upgrade_info->dest_info.table, req->dst);
|
|
|
|
if (dest && (dest->status != IOT_PLC_UPGRADE_TRANSFERRED)) {
|
|
if (req->progress) {
|
|
dest->percentage = req->progress;
|
|
}
|
|
dest->upgrade_type = CLI_UPGRADE_TYPE_V0;
|
|
dest->error_code = UPGRADE_DATA_STA_IN_PROGRESS;
|
|
|
|
if (dest->percentage > (dest->reported_percentage +
|
|
IOT_PLC_UPGRADE_PROGRESS_REPORT_INTERVAL))
|
|
{
|
|
dest->reported_percentage = dest->percentage;
|
|
cli_remote_upgrade_add_report_status(dest);
|
|
}
|
|
dest->status = IOT_PLC_UPGRADE_STARTED;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (!req->phase3) {
|
|
if (cli_remote_upgrade_update_find_latest_block(
|
|
req->file_type, req->block_idx_array[0])) {
|
|
return;
|
|
}
|
|
if (upgrade_info->last_timer_time) {
|
|
if ((IOT_PLC_DEV_ROLE_CCO != host_config->dev_role) &&
|
|
(os_boot_time32() < (upgrade_info->last_timer_time +
|
|
IOT_PLC_UPGRADE_PCO_REJECT_REQ_TIME))) {
|
|
return;
|
|
}
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
else if ((IOT_PLC_DEV_ROLE_CCO == host_config->dev_role) &&
|
|
(os_boot_time32() < (upgrade_info->last_timer_time +
|
|
IOT_PLC_UPGRADE_CCO_REJECT_REQ_TIME))) {
|
|
return;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
upgrade_info->last_timer_time = os_boot_time32();
|
|
}
|
|
|
|
if (IOT_PLC_DEV_ROLE_CCO != host_config->dev_role) {
|
|
if (req->progress) {
|
|
cli_upgrade_sta_send_progress(req->dst,
|
|
host_config->cco_mac, req->progress);
|
|
}
|
|
}
|
|
|
|
iot_printf("plc_upgrade: cco accept request, "
|
|
"file_type %d, progress %d, block cnt %d, block idx %d\n",
|
|
req->file_type, req->progress, req->req_block_cnt,
|
|
req->block_idx_array[0]);
|
|
|
|
if ((IOT_PLC_DEV_ROLE_CCO == host_config->dev_role) &&
|
|
(req->phase3)) {
|
|
send_type = IOT_PLC_MSG_TYPE_UNICAST;
|
|
retry_cnt = IOT_PLC_UPGRADE_PHASE_THREE_RETRY_TIMES;
|
|
control_byte = UPGRADE_REMOTE_ALL_PHASE3_DATA;
|
|
}
|
|
if (IOT_PLC_UPGRADE_STA_LIST == upgrade_info->upgrade_type) {
|
|
control_byte = UPGRADE_REMOTE_STA_LIST_DATA;
|
|
}
|
|
|
|
cli_remote_upgrade_send_data(send_type, retry_cnt, req->dst,
|
|
upgrade_info->upgrade_id, req->file_type, control_byte,
|
|
upgrade_info->remote_block_size, req->block_idx_array,
|
|
req->req_block_cnt, UPGRADE_DATA_FORWARD_LOCAL_BCAST, NULL);
|
|
}
|
|
|
|
/* timer for one/all sta upgrade */
|
|
static void iot_cli_upgrade_timer(timer_id_t timer_id, void *arg)
|
|
{
|
|
(void)timer_id;
|
|
(void)arg;
|
|
|
|
iot_task_msg_t *msg =
|
|
iot_cli_create_cli_msg(IOT_CLI_UPGRADE_TIMER, NULL);
|
|
if (msg) {
|
|
iot_task_queue_msg(
|
|
cli.cli_task_h, msg, IOT_CLI_QUEUE_TIMER);
|
|
}
|
|
}
|
|
|
|
/* pco/cco calculate time window by sub node cnt */
|
|
uint16_t cli_remote_upgrade_calculate_time_window(uint16_t sub_node_cnt)
|
|
{
|
|
uint16_t time_window = 0;
|
|
|
|
if (sub_node_cnt > 350) {
|
|
time_window = 20000;
|
|
} else if (sub_node_cnt > 30) {
|
|
time_window = 2400 + 50 * sub_node_cnt;
|
|
} else {
|
|
time_window = 800 + 100 * sub_node_cnt;
|
|
}
|
|
|
|
return 2 * time_window;
|
|
}
|
|
|
|
void cli_upgrade_reset_timer(uint8_t start, uint32_t time_window)
|
|
{
|
|
os_stop_timer(upgrade_info->upgrade_timer);
|
|
iot_task_clean_msg(cli.cli_task_h, IOT_CLI_MSG_TYPE, IOT_CLI_UPGRADE_TIMER);
|
|
if (start) {
|
|
os_start_timer(upgrade_info->upgrade_timer, time_window);
|
|
}
|
|
}
|
|
|
|
/* handle stop command */
|
|
void cli_upgrade_stop(uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
(void)src_mac;
|
|
iot_plc_upgrade_stop_dl_t *stop_dl = (iot_plc_upgrade_stop_dl_t *)buffer;
|
|
|
|
if ((!stop_dl) || (bufferlen < sizeof(*stop_dl))) {
|
|
return;
|
|
}
|
|
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
if (!host_config->cli_upgrade_enabled) {
|
|
cli_sg_upgrade_stop();
|
|
cli_upgrade_send_stop_ack(host_config->mac_addr,
|
|
UPGRADE_ACTION_SUCCESS);
|
|
return;
|
|
}
|
|
host_config->cli_upgrade_enabled = 0;
|
|
#endif
|
|
|
|
if (IOT_PLC_UPGRADE_LOCAL == upgrade_info->upgrade_type) {
|
|
cli_upgrade_print_mac_info(host_config->mac_addr);
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_INIT;
|
|
//send stop ack t plc mgr
|
|
cli_upgrade_send_stop_ack(host_config->mac_addr,
|
|
UPGRADE_ACTION_SUCCESS);
|
|
} else if ((IOT_PLC_UPGRADE_ALL == upgrade_info->upgrade_type) ||
|
|
(IOT_PLC_UPGRADE_STA_LIST == upgrade_info->upgrade_type)) {
|
|
if (IOT_PLC_DEV_ROLE_CCO == host_config->dev_role) {
|
|
cli_upgrade_print_mac_info(stop_dl->dst);
|
|
// cco stop
|
|
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);
|
|
cli_upgrade_send_stop_ack(host_config->mac_addr,
|
|
UPGRADE_ACTION_WAIT);
|
|
} else {
|
|
// sta stop requesting data
|
|
if ((IOT_PLC_UPGRADE_STARTED == upgrade_info->upgrade_state) ||
|
|
(IOT_PLC_UPGRADE_STARTING == upgrade_info->upgrade_state) ||
|
|
(IOT_PLC_UPGRADE_LISTEN == upgrade_info->upgrade_state)) {
|
|
cli_remote_upgrade_sta_stop();
|
|
cli_upgrade_send_stop_ack(host_config->mac_addr,
|
|
UPGRADE_ACTION_SUCCESS);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* start remote upgrade phase2 */
|
|
void cli_remote_upgrade_start_phase2(uint16_t sub_node_cnt)
|
|
{
|
|
cli_remote_upgrade_initialize_latest_block();
|
|
upgrade_info->action_times = 0;
|
|
upgrade_info->last_timer_time = 0;
|
|
upgrade_info->request_times = 0;
|
|
upgrade_info->time_window =
|
|
cli_remote_upgrade_calculate_time_window(sub_node_cnt);
|
|
|
|
cli_remote_upgrade_start_sub_nodes();
|
|
|
|
cli_upgrade_reset_timer(1, 2 * IOT_PLC_UPGRADE_DEFAULT_TIMER);
|
|
}
|
|
|
|
/* start remote upgrade phase3 */
|
|
void cli_remote_upgrade_start_phase3()
|
|
{
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_TRANSFERRED;
|
|
|
|
upgrade_info->action_times = 0;
|
|
upgrade_info->last_timer_time = 0;
|
|
upgrade_info->request_times = 0;
|
|
|
|
cli_upgrade_reset_timer(1, IOT_PLC_UPGRADE_DEFAULT_TIMER / 6);
|
|
}
|
|
|
|
/* init the upgrade module of CLI host */
|
|
void iot_cli_upgrade_init()
|
|
{
|
|
void* ptr = os_mem_malloc(IOT_CLI_MID, sizeof(iot_plc_upgrade_info_t));
|
|
upgrade_info = (iot_plc_upgrade_info_t*)ptr;
|
|
if (!upgrade_info){
|
|
IOT_ASSERT(upgrade_info);
|
|
return;
|
|
}
|
|
|
|
upgrade_info->upgrade_timer = os_create_timer(IOT_CLI_MID, 1,
|
|
iot_cli_upgrade_timer, NULL);
|
|
iot_printf("plc_upgrade: timer:%x\n", upgrade_info->upgrade_timer);
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_INIT;
|
|
upgrade_info->upgrade_type = IOT_PLC_UPGRADE_ALL;
|
|
upgrade_info->upgrade_id = 0;
|
|
upgrade_info->time_window = IOT_PLC_UPGRADE_DEFAULT_TIMER;
|
|
upgrade_info->src.crc_check_buf = NULL;
|
|
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
if (MODULE_TYPE_CCO == cli_module_type) {
|
|
iot_printf("plc_upgrade:cco init upgrade info\n");
|
|
upgrade_info->file_size = IOT_CLI_UPGRADE_MAX_FILE_SIZE;
|
|
if (upgrade_info->file_size) {
|
|
upgrade_info->file_data =
|
|
os_mem_malloc(IOT_CLI_MID, upgrade_info->file_size);
|
|
IOT_ASSERT(upgrade_info->file_data);
|
|
}
|
|
upgrade_info->pib_data = NULL;
|
|
upgrade_info->fw_data = NULL;
|
|
upgrade_info->dest_info.entry_ptr = NULL;
|
|
upgrade_info->dest_info.table = NULL;
|
|
upgrade_info->sta_upgrade_active = 0;
|
|
upgrade_info->completed_handler = NULL;
|
|
upgrade_info->sg_upgrade_handler = NULL;
|
|
upgrade_info->calc_time_window_flag = 0;
|
|
upgrade_info->node_response_flag = 1;
|
|
upgrade_info->resend_data_state = CLI_QUERY_NODE;
|
|
upgrade_info->query_node_retry_cnt = 0;
|
|
|
|
cli_remote_upgrade_init_dest_info();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* deinit the upgrade module of CLI host */
|
|
void iot_cli_upgrade_deinit()
|
|
{
|
|
if (upgrade_info) {
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
cli_remote_upgrade_destroy_buffer();
|
|
cli_remote_upgrade_destroy_dest_info();
|
|
#endif
|
|
if (upgrade_info->src.crc_check_buf) {
|
|
iot_pkt_free(upgrade_info->src.crc_check_buf);
|
|
upgrade_info->src.crc_check_buf = NULL;
|
|
}
|
|
|
|
if (upgrade_info->upgrade_timer) {
|
|
os_delete_timer(upgrade_info->upgrade_timer);
|
|
iot_task_clean_msg(cli.cli_task_h, IOT_CLI_MSG_TYPE,
|
|
IOT_CLI_UPGRADE_TIMER);
|
|
upgrade_info->upgrade_timer = 0;
|
|
}
|
|
os_mem_free(upgrade_info);
|
|
upgrade_info = NULL;
|
|
}
|
|
}
|
|
|
|
void cli_remote_upgrade_bcast_tx_done_callback(void *param, uint8_t state)
|
|
{
|
|
(void)param;
|
|
(void)state;
|
|
iot_task_msg_t *msg = iot_cli_create_cli_msg(IOT_CLI_BCAST_TX_DONE, NULL);
|
|
if (msg) {
|
|
iot_task_queue_msg(cli.cli_task_h, msg, IOT_CLI_QUEUE_HOST);
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
}
|
|
#else /* IOT_CLI_UPGRADE_ENABLE */
|
|
|
|
/* handle stop command */
|
|
void cli_upgrade_stop(uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
(void)src_mac;
|
|
iot_plc_upgrade_stop_dl_t *stop_dl = (iot_plc_upgrade_stop_dl_t *)buffer;
|
|
|
|
if ((!stop_dl) || (bufferlen < sizeof(*stop_dl))) {
|
|
return;
|
|
}
|
|
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
if (!host_config->cli_upgrade_enabled) {
|
|
cli_sg_upgrade_stop();
|
|
cli_upgrade_send_stop_ack(host_config->mac_addr,
|
|
UPGRADE_ACTION_SUCCESS);
|
|
return;
|
|
}
|
|
host_config->cli_upgrade_enabled = 0;
|
|
#endif
|
|
}
|
|
|
|
/* init the upgrade module of CLI host */
|
|
void iot_cli_upgrade_init()
|
|
{
|
|
iot_printf("disable cli upgrade\n");
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
void* ptr = os_mem_malloc(IOT_CLI_MID, sizeof(iot_plc_upgrade_info_t));
|
|
upgrade_info = (iot_plc_upgrade_info_t*)ptr;
|
|
if (!upgrade_info){
|
|
IOT_ASSERT(upgrade_info);
|
|
return;
|
|
}
|
|
upgrade_info->file_size = IOT_CLI_UPGRADE_MAX_FILE_SIZE;
|
|
upgrade_info->file_data =
|
|
os_mem_malloc(IOT_CLI_MID, upgrade_info->file_size);
|
|
IOT_ASSERT(upgrade_info->file_data);
|
|
#endif
|
|
}
|
|
|
|
/* deinit the upgrade module of CLI host */
|
|
void iot_cli_upgrade_deinit()
|
|
{
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
if (!upgrade_info) {
|
|
return;
|
|
}
|
|
if (upgrade_info->file_data) {
|
|
os_mem_free(upgrade_info->file_data);
|
|
}
|
|
os_mem_free(upgrade_info);
|
|
upgrade_info = NULL;
|
|
#endif
|
|
}
|
|
|
|
/* start remote upgrade phase2 */
|
|
void cli_remote_upgrade_start_phase2(uint16_t sub_node_cnt)
|
|
{
|
|
(void)sub_node_cnt;
|
|
}
|
|
|
|
void iot_cli_upgrade_handle_timer_msg()
|
|
{
|
|
}
|
|
|
|
#endif /* IOT_CLI_UPGRADE_ENABLE */
|
|
|
|
/* print mac info */
|
|
void cli_upgrade_print_mac_info(uint8_t *mac)
|
|
{
|
|
if (!mac) {
|
|
return;
|
|
}
|
|
|
|
iot_printf("mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
|
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
}
|
|
|
|
/* send stop ack to PLC Manager */
|
|
void cli_upgrade_send_stop_ack(uint8_t * mac, uint16_t error_code)
|
|
{
|
|
iot_plc_upgrade_stop_ul_t stop_ul;
|
|
|
|
if (!mac) {
|
|
return;
|
|
}
|
|
|
|
cli_upgrade_print_mac_info(mac);
|
|
|
|
stop_ul.upgrade_id = upgrade_info->upgrade_id;
|
|
stop_ul.error_code = error_code;
|
|
os_mem_cpy(stop_ul.dst, mac, IOT_MAC_ADDR_LEN);
|
|
|
|
iot_cli_send_to_host(CLI_MSGID_UPGRADE_STOP_ACK,
|
|
(uint8_t*)&stop_ul, sizeof(stop_ul), NULL);
|
|
}
|
|
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
|
|
/* read fw data from buffer */
|
|
uint8_t cli_upgrade_read_data_from_buffer(uint8_t file_type, uint32_t offset,
|
|
uint8_t *data, uint16_t data_len)
|
|
{
|
|
uint8_t *data_part = NULL;
|
|
|
|
if (!data) {
|
|
return UPGRADE_DATA_INVALID_DATA;
|
|
}
|
|
#if IOT_CLI_UPGRADE_ENABLE
|
|
if (file_type == UPGRADE_DATA_TYPE_FW) {
|
|
data_part = upgrade_info->fw_data;
|
|
} else if (file_type == UPGRADE_DATA_TYPE_PIB) {
|
|
data_part = upgrade_info->pib_data;
|
|
} else if (file_type == UPGRADE_DATA_TYPE_CUS) {
|
|
data_part = upgrade_info->cus_data;
|
|
} else if (file_type == UPGRADE_DATA_TYPE_PKG) {
|
|
data_part = upgrade_info->file_data;
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
#else
|
|
if (file_type == UPGRADE_DATA_TYPE_PKG) {
|
|
data_part = upgrade_info->file_data;
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
#endif /* IOT_CLI_UPGRADE_ENABLE */
|
|
os_mem_cpy(data, data_part + offset, data_len);
|
|
|
|
return UPGRADE_DATA_SUCCESS;
|
|
}
|
|
|
|
/* write fw data to buffer */
|
|
uint8_t cli_upgrade_write_data_to_buffer(uint8_t file_type, uint16_t block_cnt,
|
|
uint16_t *block_idx_array, uint16_t *block_size_array, uint8_t *data)
|
|
{
|
|
uint32_t begin_index = 0;
|
|
uint8_t *data_part = NULL;
|
|
|
|
if (!data) {
|
|
return UPGRADE_DATA_INVALID_DATA;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < block_cnt; i++) {
|
|
if (block_size_array[i]) {
|
|
iot_printf("plc_upgrade:cco write %d block %d bytes type %d\n",
|
|
block_idx_array[i], block_size_array[i], file_type);
|
|
#if IOT_CLI_UPGRADE_ENABLE
|
|
if (file_type == UPGRADE_DATA_TYPE_FW) {
|
|
data_part = upgrade_info->fw_data;
|
|
} else if (file_type == UPGRADE_DATA_TYPE_PIB) {
|
|
data_part = upgrade_info->pib_data;
|
|
} else if (file_type == UPGRADE_DATA_TYPE_CUS) {
|
|
data_part = upgrade_info->cus_data;
|
|
} else if (file_type == UPGRADE_DATA_TYPE_PKG) {
|
|
data_part = upgrade_info->file_data;
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
#else
|
|
if (file_type == UPGRADE_DATA_TYPE_PKG) {
|
|
data_part = upgrade_info->file_data;
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
#endif /* IOT_CLI_UPGRADE_ENABLE */
|
|
|
|
iot_printf("cpy dst idx %d, size %d\n",
|
|
block_idx_array[i] * upgrade_info->block_size,
|
|
block_size_array[i]);
|
|
|
|
os_mem_cpy(data_part +
|
|
block_idx_array[i] * upgrade_info->block_size,
|
|
data + begin_index, block_size_array[i]);
|
|
|
|
begin_index += block_size_array[i];
|
|
}
|
|
}
|
|
|
|
return UPGRADE_DATA_SUCCESS;
|
|
}
|
|
#endif /* PLC_SUPPORT_CCO_ROLE */
|
|
|
|
/* send reset ack to PLC Manager */
|
|
void cli_upgrade_send_reset_ack(uint8_t * mac, uint16_t error_code)
|
|
{
|
|
iot_plc_upgrade_reset_ul_t reset_ul;
|
|
|
|
if (!mac) {
|
|
return;
|
|
}
|
|
|
|
cli_upgrade_print_mac_info(mac);
|
|
|
|
reset_ul.upgrade_id = upgrade_info->upgrade_id;
|
|
reset_ul.error_code = error_code;
|
|
os_mem_cpy(reset_ul.dst, mac, IOT_MAC_ADDR_LEN);
|
|
|
|
iot_cli_send_to_host(CLI_MSGID_UPGRADE_RESET_ACK,
|
|
(uint8_t*)&reset_ul, sizeof(reset_ul), NULL);
|
|
}
|
|
|
|
/* handle reset command */
|
|
void cli_upgrade_reset(uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
iot_plc_upgrade_reset_ul_t reset_ul;
|
|
(void)src_mac;
|
|
|
|
iot_plc_upgrade_reset_dl_t *data = NULL;
|
|
data = (iot_plc_upgrade_reset_dl_t *)buffer;
|
|
|
|
if ((!data) || (bufferlen < sizeof(*data))) {
|
|
iot_printf("%s param error", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if (IOT_PLC_DEV_ROLE_CCO != host_config->dev_role) {
|
|
os_mem_cpy(reset_ul.dst, host_config->mac_addr, IOT_MAC_ADDR_LEN);
|
|
iot_cli_host_send_data_plc(IOT_PLC_MSG_TYPE_UNICAST,
|
|
CLI_MSGID_UPGRADE_RESET_ACK, host_config->cco_mac,
|
|
(uint8_t*)&reset_ul, sizeof(reset_ul));
|
|
#if IOT_CLI_UPGRADE_ENABLE
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_INIT;
|
|
#endif
|
|
//reset sta
|
|
iot_upgrade_reset();
|
|
}
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
else {
|
|
//reset one
|
|
if (data->type) {
|
|
if (iot_mac_addr_cmp(data->dst, host_config->mac_addr)) {
|
|
//reset cco
|
|
iot_upgrade_reset();
|
|
} else {
|
|
iot_cli_host_send_data_plc(IOT_PLC_MSG_TYPE_UNICAST,
|
|
CLI_MSGID_UPGRADE_RESET, data->dst, buffer, bufferlen);
|
|
}
|
|
} else {
|
|
#if !IOT_CLI_UPGRADE_ENABLE
|
|
cli_upgrade_send_reset_ack(host_config->mac_addr,
|
|
UPGRADE_ACTION_OTHER_ERROR);
|
|
#else
|
|
cli_upgrade_send_reset_ack(host_config->mac_addr,
|
|
UPGRADE_ACTION_WAIT);
|
|
// cco reset all
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_RESET;
|
|
upgrade_info->action_times = 0;
|
|
if (!os_is_timer_active(upgrade_info->upgrade_timer)) {
|
|
os_start_timer(upgrade_info->upgrade_timer,
|
|
upgrade_info->time_window);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
}
|