821 lines
28 KiB
C
821 lines
28 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_cli_plc_tx_rx.h"
|
|
|
|
extern iot_plc_upgrade_info_t *upgrade_info;
|
|
extern iot_plc_host_config_t *host_config;
|
|
|
|
#if IOT_CLI_UPGRADE_ENABLE
|
|
|
|
/* sta request data from cco */
|
|
void cli_remote_upgrade_sta_send_request_data(bool_t phase3)
|
|
{
|
|
uint8_t *dst_mac;
|
|
|
|
if ((cli_remote_upgrade_get_next_block(UPGRADE_DATA_TYPE_PIB, 0)) &&
|
|
(upgrade_info->control_upgrade_flag == 0)) {
|
|
uint8_t send_type = IOT_PLC_MSG_TYPE_UNICAST_TO_PCO;
|
|
iot_plc_upgrade_remote_data_req_ul_t req;
|
|
uint16_t written_blocks =
|
|
(uint16_t)iot_upgrade_query_written_block_num();
|
|
req.file_type = upgrade_info->current_file_type;
|
|
|
|
req.progress = (uint8_t)(written_blocks * 100 /
|
|
(upgrade_info->fw_blocks + upgrade_info->pib_blocks));
|
|
if (req.progress > (upgrade_info->reported_percentage +
|
|
IOT_PLC_UPGRADE_PROGRESS_REPORT_INTERVAL)) {
|
|
upgrade_info->reported_percentage = req.progress;
|
|
} else {
|
|
req.progress = 0;
|
|
}
|
|
|
|
req.req_block_cnt = upgrade_info->remote_block_cnt;
|
|
if (UPGRADE_REMOTE_BLOCK_MAX_NUM < req.req_block_cnt) {
|
|
req.req_block_cnt = UPGRADE_REMOTE_BLOCK_MAX_NUM;
|
|
}
|
|
|
|
if ((UPGRADE_DATA_TYPE_FW == req.file_type) &&
|
|
((upgrade_info->block_idx + req.req_block_cnt) >
|
|
upgrade_info->fw_blocks)) {
|
|
req.req_block_cnt =
|
|
upgrade_info->fw_blocks - upgrade_info->block_idx;
|
|
}
|
|
else if ((UPGRADE_DATA_TYPE_PIB == req.file_type) &&
|
|
((upgrade_info->block_idx + req.req_block_cnt) >
|
|
upgrade_info->pib_blocks)) {
|
|
req.req_block_cnt =
|
|
upgrade_info->pib_blocks - upgrade_info->block_idx;
|
|
}
|
|
|
|
for (uint16_t i = 0; i < req.req_block_cnt; i++) {
|
|
req.block_idx_array[i] = upgrade_info->block_idx + i;
|
|
iot_printf("plc_upgrade:sta request, file"
|
|
" type:%d, index:%d, cnt:%d, written blocks:%d\n",
|
|
req.file_type, req.block_idx_array[i], req.req_block_cnt,
|
|
written_blocks);
|
|
}
|
|
|
|
iot_mac_addr_cpy(req.dst, host_config->mac_addr);
|
|
req.upgrade_id = upgrade_info->upgrade_id;
|
|
|
|
req.phase3 = 0;
|
|
if (phase3) {
|
|
req.phase3 = 1;
|
|
send_type = IOT_PLC_MSG_TYPE_UNICAST;
|
|
}
|
|
if (IOT_PLC_UPGRADE_STA_LIST == upgrade_info->upgrade_type) {
|
|
send_type = IOT_PLC_MSG_TYPE_UNICAST;
|
|
}
|
|
if (send_type == IOT_PLC_MSG_TYPE_UNICAST_TO_PCO) {
|
|
dst_mac = (uint8_t *)bcast_mac;
|
|
} else {
|
|
dst_mac = host_config->cco_mac;
|
|
}
|
|
iot_cli_host_send_data_plc(send_type,
|
|
CLI_MSGID_REMOTE_UPGRADE_DATA_REQUEST,
|
|
dst_mac, (uint8_t*)&req, sizeof(req));
|
|
} else {
|
|
//finished wait for crc check
|
|
iot_printf("plc_upgrade:fw file transferred, wait for crc check\n");
|
|
}
|
|
}
|
|
|
|
/* sta complete remote upgrade */
|
|
void cli_remote_upgrade_sta_complete()
|
|
{
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_INIT;
|
|
cli_upgrade_reset_timer(0, 0);
|
|
}
|
|
|
|
/* sta stop remote upgrade */
|
|
void cli_remote_upgrade_sta_stop()
|
|
{
|
|
iot_upgrade_cancel_commit(upgrade_info->src.id);
|
|
cli_remote_upgrade_sta_complete();
|
|
}
|
|
|
|
/* stat send start ack to cco */
|
|
void cli_upgrade_sta_send_start_ack(uint8_t send_type, uint8_t error_code)
|
|
{
|
|
iot_plc_upgrade_start_ul_t ack;
|
|
ack.result = error_code;
|
|
iot_mac_addr_cpy(ack.dst, host_config->mac_addr);
|
|
iot_cli_host_send_data_plc(send_type,
|
|
CLI_MSGID_REMOTE_UPGRADE_START_ACK, host_config->cco_mac,
|
|
(uint8_t *)&ack, sizeof(ack));
|
|
}
|
|
|
|
/* sta send upgrade result to cco */
|
|
void cli_upgrade_sta_send_upgrade_result(uint8_t send_type,
|
|
uint8_t *src_mac, uint8_t *dst_mac, uint8_t error_code)
|
|
{
|
|
iot_plc_upgrade_result_ul_t result;
|
|
result.upgrade_id = upgrade_info->upgrade_id;
|
|
result.upgrade_type = upgrade_info->upgrade_type;
|
|
iot_mac_addr_cpy(result.dst, src_mac);
|
|
result.error_code = error_code;
|
|
|
|
iot_printf("plc_upgrade:report upgrade result to cco"
|
|
"reuslt %d, src mac:\n", result.error_code);
|
|
cli_upgrade_print_mac_info(host_config->mac_addr);
|
|
iot_cli_module_send_data_with_retry(send_type,
|
|
IOT_PLC_UPGRADE_RETRY_COUNT, CLI_MODULEID_HOSTINTERFACE,
|
|
CLI_MSGID_UPGRADE_RESULT, NULL, dst_mac, (uint8_t *)&result,
|
|
sizeof(result));
|
|
}
|
|
|
|
/* sta send progress to cco */
|
|
void cli_upgrade_sta_send_progress(uint8_t *src_mac, uint8_t *dst_mac,
|
|
uint8_t progress_value)
|
|
{
|
|
iot_plc_upgrade_progress_ul_t progress;
|
|
progress.upgrade_id = upgrade_info->upgrade_id;
|
|
progress.upgrade_type = upgrade_info->upgrade_type;
|
|
progress.progress = progress_value;
|
|
iot_mac_addr_cpy(progress.dst, src_mac);
|
|
|
|
iot_cli_host_send_data_plc(IOT_PLC_MSG_TYPE_UNICAST,
|
|
CLI_MSGID_UPGRADE_PROGRESS,
|
|
dst_mac, (uint8_t *)&progress, sizeof(progress));
|
|
}
|
|
|
|
/* sta get net block type & index*/
|
|
bool_t cli_remote_upgrade_get_next_block(uint32_t file_type,
|
|
uint32_t block_index)
|
|
{
|
|
iot_upg_block_info_src src;
|
|
iot_upg_block_info_rst rst;
|
|
src.file_type = file_type;
|
|
src.block_index = block_index;
|
|
|
|
if ((ERR_OK == iot_upgrade_query_next_block(&rst, &src))) {
|
|
upgrade_info->current_file_type =
|
|
(uint8_t)rst.file_type;
|
|
upgrade_info->block_idx =
|
|
(uint16_t)rst.next_blank_block_index;
|
|
iot_printf("plc_upgrade:file_type:%d, block_index:%d\n",
|
|
upgrade_info->current_file_type,
|
|
upgrade_info->block_idx);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
#if !IOT_STA_CONTROL_MODE
|
|
static uint8_t cli_remote_upgrade_requset_phase_three_data()
|
|
{
|
|
if (cli_remote_upgrade_get_next_block(UPGRADE_DATA_TYPE_PIB, 0)) {
|
|
cli_remote_upgrade_sta_send_request_data(true);
|
|
return UPGRADE_START_OK;
|
|
}
|
|
|
|
return UPGRADE_START_END_SINCE_COMPLETED;
|
|
}
|
|
|
|
/* stat request data */
|
|
static uint8_t cli_remote_upgrade_start_requset_data()
|
|
{
|
|
uint32_t period = 0;
|
|
if (cli_remote_upgrade_get_next_block(UPGRADE_DATA_TYPE_PIB, 0)) {
|
|
period = os_rand() % upgrade_info->time_window;
|
|
if (IOT_PLC_DEV_ROLE_PCO == host_config->dev_role) {
|
|
period /= 2;
|
|
}
|
|
cli_upgrade_reset_timer(1, period);
|
|
iot_printf("start upgrade timer, time window %lu ms\n", period);
|
|
return UPGRADE_START_OK;
|
|
}
|
|
|
|
return UPGRADE_START_END_SINCE_COMPLETED;
|
|
}
|
|
|
|
static uint32_t cli_find_node_from_listnode(uint8_t *list_mac, uint8_t list_size,
|
|
uint8_t *src_mac)
|
|
{
|
|
uint8_t i;
|
|
for (i = 0; i < list_size; i++) {
|
|
if (iot_mac_addr_cmp(list_mac + i * IOT_MAC_ADDR_LEN, src_mac)) {
|
|
return ERR_OK;
|
|
}
|
|
}
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
#endif
|
|
|
|
/* sta handle remote upgrade start command from cco */
|
|
void cli_remote_upgrade_start(
|
|
uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
#if IOT_STA_CONTROL_MODE
|
|
(void)buffer;
|
|
(void)bufferlen;
|
|
(void)src_mac;
|
|
iot_printf("plc_upgrade:sta control mode no need to upgrade");
|
|
return;
|
|
#else
|
|
(void)src_mac;
|
|
uint8_t result = UPGRADE_START_OK;
|
|
iot_plc_upgrade_cust_start_dl_t cus_info;
|
|
iot_plc_upgrade_start_dl_t *data =
|
|
(iot_plc_upgrade_start_dl_t *)buffer;
|
|
uint32_t version = iot_version_hex();
|
|
uint8_t iscco = 0;
|
|
uint8_t ret = 0;
|
|
|
|
if ((!data) || (bufferlen < sizeof(*data))) {
|
|
iot_printf("%s param error", __FUNCTION__);
|
|
ret = 1;
|
|
goto out;
|
|
}
|
|
|
|
if (data->cus_upgrade_flag) {
|
|
if (bufferlen < (sizeof(*data) + data->dst_num * IOT_MAC_ADDR_LEN +
|
|
sizeof(cus_info))) {
|
|
iot_printf("%s param dest mac error", __FUNCTION__);
|
|
ret = 2;
|
|
goto out;
|
|
}
|
|
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 param dest mac error", __FUNCTION__);
|
|
ret = 2;
|
|
goto out;
|
|
}
|
|
os_mem_set((uint8_t *)&cus_info, 0, sizeof(cus_info));
|
|
}
|
|
|
|
iot_printf("plc_upgrade:recv remote upgrade start, role:%d, type:%d "
|
|
"state:%d\n", host_config->dev_role, host_config->dev_type,
|
|
upgrade_info->upgrade_state);
|
|
|
|
if (IOT_PLC_DEV_TYPE_METER_CONTROLLER == host_config->dev_type) {
|
|
/* METER_CONTROLLER no do remote upgrade */
|
|
iot_printf("plc_upgrade:controller skip upgrade\n");
|
|
ret = 3;
|
|
goto out;
|
|
}
|
|
|
|
if ((data->control_flag) &&
|
|
(data->phase_flag != UPGRADE_START_UPGRADE_PHASE1)) {
|
|
/* if in control upgrade mode, skip phase2/3 requesting cco data */
|
|
ret = 4;
|
|
iot_printf("plc_upgrade: drop phase2 and phase3 start cmd\n");
|
|
goto out;
|
|
}
|
|
|
|
//version check
|
|
if (version == data->fw_version) {
|
|
if (IOT_PLC_DEV_ROLE_STA == host_config->dev_role) {
|
|
iot_printf("plc_upgrade:version equal\n");
|
|
//upgrade_info->upgrade_state = IOT_PLC_UPGRADE_TRANSFERRED;
|
|
}
|
|
}
|
|
|
|
if (iot_mac_addr_cmp(host_config->cco_mac, src_mac)) {
|
|
iscco = 1;
|
|
}
|
|
|
|
if ((IOT_PLC_UPGRADE_TRANSFERRED == upgrade_info->upgrade_state)) {
|
|
if (!upgrade_info->stop_upgrade_rpt) {
|
|
if (IOT_PLC_DEV_ROLE_STA == host_config->dev_role) {
|
|
if (!os_is_timer_active(upgrade_info->upgrade_timer)) {
|
|
os_start_timer(upgrade_info->upgrade_timer,
|
|
os_rand() % (upgrade_info->time_window *
|
|
IOT_PLC_UPGRADE_LONG_TIMER_CNT));
|
|
}
|
|
} else {
|
|
cli_upgrade_sta_send_upgrade_result(
|
|
IOT_PLC_MSG_TYPE_UNICAST, host_config->mac_addr,
|
|
host_config->cco_mac, UPGRADE_DATA_SUCCESS);
|
|
}
|
|
}
|
|
return;
|
|
} else if ((IOT_PLC_UPGRADE_INIT != upgrade_info->upgrade_state) &&
|
|
(IOT_PLC_UPGRADE_LISTEN != upgrade_info->upgrade_state)) {
|
|
if ((upgrade_info->upgrade_type != data->upgrade_type) ||
|
|
(upgrade_info->upgrade_id != data->upgrade_id)) {
|
|
if (iscco) {
|
|
/* stop before upgrade, ready receive cco new upgrade */
|
|
cli_remote_upgrade_sta_stop();
|
|
} else {
|
|
/* drop invalid start upgrade */
|
|
ret = 5;
|
|
goto out;
|
|
}
|
|
} else if (data->phase_flag == UPGRADE_START_UPGRADE_PHASE1) {
|
|
/* node had init upgrade */
|
|
ret = 6;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
// initialize upgrade info
|
|
if ((IOT_PLC_UPGRADE_INIT == upgrade_info->upgrade_state) ||
|
|
(IOT_PLC_UPGRADE_LISTEN == upgrade_info->upgrade_state)) {
|
|
if (data->upgrade_type == IOT_PLC_UPGRADE_STA_LIST) {
|
|
if (!iscco) {
|
|
// list upgrade, disable pco start upgrade cmd
|
|
ret = 7;
|
|
goto out;
|
|
}
|
|
if (data->phase_flag == UPGRADE_START_UPGRADE_PHASE2) {
|
|
/*
|
|
* drop phase2 start upgrade cmd,
|
|
* because cmd dst param is invalid.
|
|
*/
|
|
ret = 8;
|
|
goto out;
|
|
}
|
|
if (cli_find_node_from_listnode(data->dst, data->dst_num,
|
|
host_config->mac_addr) != ERR_OK) {
|
|
ret = 9;
|
|
goto out;
|
|
}
|
|
}
|
|
result = cli_upgrade_type_check(data);
|
|
if (UPGRADE_START_OK != result) {
|
|
goto rsp;
|
|
}
|
|
cli_upgrade_info_initialize(data);
|
|
if (IOT_PLC_UPGRADE_INIT == upgrade_info->upgrade_state) {
|
|
if (ERR_OK != 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)) {
|
|
result = UPGRADE_START_OTHER_ERROR;
|
|
goto rsp;
|
|
}
|
|
}
|
|
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_STARTING;
|
|
}
|
|
|
|
if (data->phase_flag == UPGRADE_START_UPGRADE_PHASE3) {
|
|
iot_printf("plc_upgrade:start recv phase3 start\n");
|
|
result = cli_remote_upgrade_requset_phase_three_data();
|
|
} else if (data->phase_flag == UPGRADE_START_UPGRADE_PHASE2) {
|
|
if (!os_is_timer_active(upgrade_info->upgrade_timer)) {
|
|
/* node had start request data timer */
|
|
cli_remote_upgrade_start_requset_data();
|
|
}
|
|
ret = 10;
|
|
goto out;
|
|
}
|
|
|
|
rsp:
|
|
if ((data->upgrade_type == IOT_PLC_UPGRADE_STA_LIST) ||
|
|
(UPGRADE_START_OK != result)) {
|
|
cli_upgrade_sta_send_start_ack(IOT_PLC_MSG_TYPE_UNICAST, result);
|
|
}
|
|
out:
|
|
if (ret) {
|
|
iot_printf("%s ret: %d\n", __FUNCTION__, ret);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void cli_set_stop_upgrade_rpt(uint8_t *buffer, uint32_t bufferlen,
|
|
uint8_t *src_mac)
|
|
{
|
|
(void)src_mac;
|
|
|
|
if (!buffer) {
|
|
return;
|
|
}
|
|
|
|
iot_plc_sg_upgrade_stop_rpt_dl_t *data =
|
|
(iot_plc_sg_upgrade_stop_rpt_dl_t *)buffer;
|
|
if (bufferlen >= sizeof(*data)) {
|
|
if (data->flag) {
|
|
upgrade_info->stop_upgrade_rpt = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
iot_pkt_t *cli_rempte_upgrade_get_sta_bitmap(uint16_t start_seq, uint16_t cnt)
|
|
{
|
|
iot_pkt_t *bitmap_pkt = NULL;
|
|
uint8_t *bm;
|
|
uint16_t start_sn;
|
|
uint16_t bm_byte_size;
|
|
uint16_t bm_byte_cnt;
|
|
uint16_t i;
|
|
/* query upgrade bitmap */
|
|
iot_pkg_upg_sts_rst_t rst = {0};
|
|
iot_pkg_upg_sts_src_t src = {0};
|
|
|
|
if (IOT_PLC_UPGRADE_QUERY_BM_ALL == cnt) {
|
|
/* return all blocks */
|
|
cnt = (uint16_t)upgrade_info->pib_blocks + upgrade_info->fw_blocks;
|
|
start_sn = 0;
|
|
bm_byte_cnt = 0;
|
|
} else {
|
|
start_sn = start_seq;
|
|
}
|
|
bm_byte_size = ((cnt + 7) >> 3);
|
|
iot_printf("%s cnt is : %lu\n", __FUNCTION__, bm_byte_size);
|
|
|
|
bitmap_pkt = iot_pkt_alloc(bm_byte_size, IOT_SMART_GRID_MID);
|
|
if (bitmap_pkt == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
bm = iot_pkt_data(bitmap_pkt);
|
|
if (upgrade_info->upgrade_state == IOT_PLC_UPGRADE_INIT ||
|
|
upgrade_info->upgrade_state == IOT_PLC_UPGRADE_TRANSFERRED) {
|
|
/* if sta doesn't start upgrade/upgrad complete, set bm data is zero */
|
|
os_mem_set(bm, 0x00, bm_byte_size);
|
|
iot_pkt_put(bitmap_pkt, bm_byte_size);
|
|
return bitmap_pkt;
|
|
}
|
|
|
|
src.id = upgrade_info->upgrade_id;
|
|
src.block_size = upgrade_info->block_size;
|
|
src.block_index = start_sn;
|
|
src.block_cnt = cnt;
|
|
|
|
if (ERR_OK == iot_pkg_upgrade_query_state(&rst, &src)) {
|
|
bm_byte_cnt = (uint16_t)(rst.block_cnt >> 3);
|
|
if (bm_byte_cnt) {
|
|
os_mem_cpy(bm, rst.bitmap, bm_byte_cnt);
|
|
}
|
|
|
|
iot_pkt_put(bitmap_pkt, bm_byte_size);
|
|
iot_printf("upgrade: bm byte size = %d, start block = %d, len = %d,"
|
|
" cnt = %d.\n", bm_byte_cnt, start_seq, bm_byte_size, cnt);
|
|
for (i = 0; i < bm_byte_size; ++i) {
|
|
if (bm[i] != 0xFF || i + 1 == bm_byte_size) {
|
|
iot_printf("upgrade: bm[%d] = %02X\n", i, bm[i]);
|
|
}
|
|
}
|
|
} else {
|
|
iot_pkt_free(bitmap_pkt);
|
|
bitmap_pkt = NULL;
|
|
}
|
|
|
|
return bitmap_pkt;
|
|
}
|
|
|
|
void cli_remote_upgrade_node_info_query(uint8_t *buffer, uint32_t bufferlen,
|
|
uint8_t *src_mac)
|
|
{
|
|
(void)src_mac;
|
|
uint8_t err_code = 0;
|
|
uint32_t pkt_len = 0;
|
|
iot_pkt_t *bitmap_pkt;
|
|
iot_pkt_t *response_pkt = NULL;
|
|
iot_plc_upgrade_query_sta_info_dl_t *data =
|
|
(iot_plc_upgrade_query_sta_info_dl_t *)buffer;
|
|
iot_plc_upgrade_query_sta_info_ul_t *rsp;
|
|
|
|
if (bufferlen < sizeof(*data)) {
|
|
err_code = 1;
|
|
goto err;
|
|
}
|
|
|
|
bitmap_pkt = cli_rempte_upgrade_get_sta_bitmap(data->start_idx, data->cnt);
|
|
|
|
if ((bitmap_pkt == NULL) &&
|
|
(upgrade_info->upgrade_state != IOT_PLC_UPGRADE_INIT)) {
|
|
return;
|
|
}
|
|
|
|
pkt_len = iot_pkt_data_len(bitmap_pkt) + sizeof(*rsp);
|
|
response_pkt = iot_pkt_alloc(pkt_len, IOT_CLI_MID);
|
|
IOT_ASSERT(response_pkt);
|
|
|
|
rsp = (iot_plc_upgrade_query_sta_info_ul_t *)iot_pkt_data(response_pkt);
|
|
rsp->start_idx = data->start_idx;
|
|
rsp->upgrade_id = upgrade_info->upgrade_id;
|
|
rsp->state = (uint8_t)upgrade_info->upgrade_state;
|
|
iot_mac_addr_cpy(rsp->dst, host_config->mac_addr);
|
|
if (data->cnt == IOT_PLC_UPGRADE_QUERY_BM_ALL) {
|
|
rsp->cnt = upgrade_info->fw_blocks + upgrade_info->pib_blocks;
|
|
} else {
|
|
rsp->cnt = data->cnt;
|
|
}
|
|
if (bitmap_pkt) {
|
|
os_mem_cpy(rsp->bm, iot_pkt_data(bitmap_pkt),
|
|
iot_pkt_data_len(bitmap_pkt));
|
|
}
|
|
|
|
iot_cli_host_send_data_plc(IOT_PLC_MSG_TYPE_UNICAST,
|
|
CLI_MSGID_UPGRADE_NODE_INFO_RESPONSE, host_config->cco_mac,
|
|
iot_pkt_data(response_pkt), pkt_len);
|
|
|
|
err:
|
|
iot_printf("plc_upgrade: %s err code:%d\n", __FUNCTION__, err_code);
|
|
if (response_pkt != NULL) {
|
|
iot_pkt_free(response_pkt);
|
|
}
|
|
}
|
|
|
|
#if !IOT_STA_CONTROL_MODE
|
|
static bool_t cli_remote_upgrade_is_broadcast_start(
|
|
uint8_t contol_byte, uint8_t file_type)
|
|
{
|
|
if ((!contol_byte) && (UPGRADE_DATA_TYPE_PIB == file_type)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static uint8_t cli_remote_data_trans_type_to_plc(uint16_t fwd_type)
|
|
{
|
|
uint8_t plc_fwd_type = IOT_PLC_MSG_TYPE_INVALID;
|
|
|
|
switch (fwd_type) {
|
|
case UPGRADE_DATA_FORWARD_LOCAL_BCAST:
|
|
{
|
|
plc_fwd_type = IOT_PLC_MSG_TYPE_BCAST_1HOP;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return plc_fwd_type;
|
|
}
|
|
#endif
|
|
|
|
/* sta receive remote upgrade data from cco */
|
|
void cli_remote_upgrade_data(
|
|
uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac)
|
|
{
|
|
#if IOT_STA_CONTROL_MODE
|
|
(void)buffer;
|
|
(void)bufferlen;
|
|
(void)src_mac;
|
|
iot_printf("plc_upgrade:control mode skip upgrade");
|
|
return;
|
|
#else
|
|
(void)src_mac;
|
|
iot_plc_upgrade_result_ul_t result;
|
|
iot_plc_upgrade_remote_data_dl *data =
|
|
(iot_plc_upgrade_remote_data_dl *)buffer;
|
|
bool_t isDest = false;
|
|
uint8_t plc_trans_type = IOT_PLC_MSG_TYPE_BCAST_1HOP;
|
|
uint8_t is_unicast_to_broad = 0;
|
|
|
|
if ((!data) || (bufferlen < sizeof(*data))) {
|
|
iot_printf("%s param error", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if (bufferlen < ((data->block_size * data->block_cnt) + sizeof(*data))) {
|
|
iot_printf("%s length error", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if ((UPGRADE_REMOTE_STA_LIST_DATA == data->contol_byte) &&
|
|
(IOT_PLC_UPGRADE_STA_LIST != upgrade_info->upgrade_type)) {
|
|
return;
|
|
}
|
|
|
|
if (IOT_PLC_DEV_TYPE_METER_CONTROLLER == host_config->dev_type) {
|
|
/* METER_CONTROLLER no do remote upgrade */
|
|
iot_printf("plc_upgrade:controller skip upgrade\n");
|
|
return;
|
|
}
|
|
|
|
if (iot_mac_addr_cmp(host_config->mac_addr, data->dst)) {
|
|
isDest = true;
|
|
}
|
|
|
|
iot_printf("plc_upgrade: remote data, state %d,"
|
|
" type %d, idx %d, size %d\n", upgrade_info->upgrade_state,
|
|
data->file_type, data->block_idx_array[0], data->block_size_array[0]);
|
|
|
|
if ((IOT_PLC_UPGRADE_TRANSFERRED == upgrade_info->upgrade_state) ||
|
|
(IOT_PLC_UPGRADE_FAILED == upgrade_info->upgrade_state) ||
|
|
(IOT_PLC_UPGRADE_START_FAIL == upgrade_info->upgrade_state) ||
|
|
(IOT_PLC_UPGRADE_STOPED == upgrade_info->upgrade_state))
|
|
{
|
|
if (cli_remote_upgrade_is_broadcast_start(
|
|
data->contol_byte, data->file_type)) {
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_INIT;
|
|
} else {
|
|
return;
|
|
}
|
|
} else if ((IOT_PLC_UPGRADE_STARTED == upgrade_info->upgrade_state) ||
|
|
(IOT_PLC_UPGRADE_LISTEN == upgrade_info->upgrade_state)) {
|
|
if (cli_remote_upgrade_is_broadcast_start(
|
|
data->contol_byte, data->file_type) &&
|
|
(upgrade_info->upgrade_id != data->upgrade_id)) {
|
|
cli_remote_upgrade_sta_stop();
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_INIT;
|
|
}
|
|
}
|
|
|
|
if (IOT_PLC_UPGRADE_INIT == upgrade_info->upgrade_state) {
|
|
if (ERR_OK != cli_upgrade_flash_info_initialize(data->block_size,
|
|
data->fw_size, data->pib_size, data->cus_size, data->upgrade_id,
|
|
data->fw_checksum, data->pib_checksum, data->cus_checksum,
|
|
upgrade_info->fw_version)) {
|
|
iot_printf("plc_upgrade:cli_upgrade_flash_info_initialize error\n");
|
|
return;
|
|
}
|
|
cli_remote_upgrade_sta_initialize(IOT_PLC_UPGRADE_ALL,
|
|
data->block_size, data->block_size, data->fw_size,
|
|
data->pib_size, data->cus_size, data->fw_checksum, data->pib_checksum,
|
|
data->cus_checksum, data->time_window, data->remote_block_cnt);
|
|
upgrade_info->upgrade_id = data->upgrade_id;
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_LISTEN;
|
|
}
|
|
|
|
result.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 == result.error_code ||
|
|
UPGRADE_DATA_BLOCK_IDX_ERROR == result.error_code) {
|
|
result.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 (ERR_OK == cli_upgrade_is_unicast_to_broadcast(data)) {
|
|
is_unicast_to_broad = 1;
|
|
plc_trans_type =
|
|
cli_remote_data_trans_type_to_plc(data->fwd_type);
|
|
}
|
|
if (is_unicast_to_broad ||
|
|
((UPGRADE_REMOTE_ALL_PHASE2_DATA == data->contol_byte) &&
|
|
(IOT_PLC_DEV_ROLE_PCO == host_config->dev_role)) ||
|
|
(UPGRADE_REMOTE_ALL_PHASE3_DATA == data->contol_byte)) {
|
|
if (UPGRADE_REMOTE_STA_LIST_DATA != data->contol_byte) {
|
|
data->contol_byte = UPGRADE_REMOTE_ALL_PHASE3_DATA_1;
|
|
}
|
|
iot_cli_module_send_data_with_retry(plc_trans_type, 1,
|
|
CLI_MODULEID_HOSTINTERFACE, CLI_MSGID_REMOTE_UPGRADE_DATA,
|
|
src_mac, host_config->mac_addr, buffer, bufferlen);
|
|
if (!is_unicast_to_broad) {
|
|
return;
|
|
}
|
|
} else if (UPGRADE_REMOTE_ALL_PHASE3_DATA_1 == data->contol_byte) {
|
|
return;
|
|
}
|
|
|
|
if ((IOT_PLC_UPGRADE_STARTING == upgrade_info->upgrade_state) ||
|
|
(IOT_PLC_UPGRADE_STARTED == upgrade_info->upgrade_state)) {
|
|
upgrade_info->skip_timer = false;
|
|
if (!isDest) {
|
|
if ((upgrade_info->last_timer_time +
|
|
upgrade_info->time_window) <
|
|
(os_boot_time32() + IOT_PLC_UPGRADE_STA_SKIP_REQ_TIME)) {
|
|
upgrade_info->skip_timer = true;
|
|
}
|
|
}
|
|
|
|
if (UPGRADE_DATA_SUCCESS == result.error_code) {
|
|
bool_t recv_done = false;
|
|
if (ERR_OK == iot_upgrade_is_completed()) {
|
|
recv_done = true;
|
|
}
|
|
if (recv_done) {
|
|
iot_printf("plc_upgrade: recv fw done,"
|
|
"wait for crc check\n");
|
|
} else if (isDest) {
|
|
/* check time_window */
|
|
if (data->time_window && ((upgrade_info->time_window >=
|
|
(IOT_PLC_UPGRADE_TIME_WINDOW_ADJ_VALUE3 *
|
|
data->time_window)) || ((upgrade_info->time_window *
|
|
IOT_PLC_UPGRADE_TIME_WINDOW_ADJ_VALUE3) <=
|
|
data->time_window))) {
|
|
iot_printf("plc_upgrade:time window adjust,"
|
|
" %lu to %lu\n", upgrade_info->time_window,
|
|
data->time_window);
|
|
/* renew time_window */
|
|
upgrade_info->time_window = data->time_window;
|
|
cli_upgrade_reset_timer(1, upgrade_info->time_window);
|
|
} else if (os_is_timer_active(upgrade_info->upgrade_timer)) {
|
|
os_reset_timer(upgrade_info->upgrade_timer);
|
|
}
|
|
}
|
|
} else if (UPGRADE_DATA_STA_STOP == result.error_code) {
|
|
cli_remote_upgrade_sta_stop();
|
|
cli_upgrade_sta_send_upgrade_result(IOT_PLC_MSG_TYPE_UNICAST,
|
|
host_config->mac_addr, host_config->cco_mac, result.error_code);
|
|
}
|
|
} else if (IOT_PLC_UPGRADE_LISTEN == upgrade_info->upgrade_state) {
|
|
if (data->contol_byte) {
|
|
uint8_t start_result = UPGRADE_START_OK;
|
|
iot_printf("plc_upgrade: start since recv data\n");
|
|
cli_remote_upgrade_sta_initialize(IOT_PLC_UPGRADE_ALL,
|
|
data->block_size, data->block_size, data->fw_size,
|
|
data->pib_size, 0, data->fw_checksum, data->pib_checksum, 0,
|
|
data->time_window, data->remote_block_cnt);
|
|
upgrade_info->upgrade_id = data->upgrade_id;
|
|
upgrade_info->upgrade_state = IOT_PLC_UPGRADE_STARTING;
|
|
start_result = cli_remote_upgrade_start_requset_data();
|
|
if (UPGRADE_START_OK != start_result) {
|
|
if ((IOT_PLC_UPGRADE_TRANSFERRED !=
|
|
upgrade_info->upgrade_state) &&
|
|
(IOT_PLC_UPGRADE_FAILED !=
|
|
upgrade_info->upgrade_state)) {
|
|
iot_dbglog_input(IOT_DRIVER_MID, DBGLOG_ERR,
|
|
IOT_DRIVER_UPGRADE_COMMIT_ID, 1, 3);
|
|
}
|
|
cli_upgrade_sta_send_start_ack(
|
|
IOT_PLC_MSG_TYPE_UNICAST, start_result);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* sta state change handler */
|
|
void iot_cli_sta_state_change(uint8_t prev_nw_sn, uint8_t nw_sn)
|
|
{
|
|
iot_printf("plc_upgrade: sta state change\n");
|
|
cli_upgrade_print_mac_info(host_config->mac_addr);
|
|
|
|
if (prev_nw_sn != nw_sn) {
|
|
iot_printf("prev_nw_sn %lu, nw_sn %lu\n",
|
|
prev_nw_sn, nw_sn);
|
|
#if (!IOT_SMART_GRID_ENABLE)
|
|
if (IOT_PLC_UPGRADE_TRANSFERRED == upgrade_info->upgrade_state) {
|
|
iot_printf("plc_upgrade: reset since leave\n");
|
|
iot_upgrade_reset();
|
|
return;
|
|
}
|
|
#endif /* !IOT_SMART_GRID_ENABLE */
|
|
if (IOT_PLC_UPGRADE_INIT != upgrade_info->upgrade_state) {
|
|
cli_remote_upgrade_sta_stop();
|
|
}
|
|
} else if ((IOT_PLC_UPGRADE_TRANSFERRED == upgrade_info->upgrade_state) &&
|
|
(IOT_PLC_DEV_ROLE_PCO == host_config->dev_role)) {
|
|
cli_remote_upgrade_pco_start();
|
|
}
|
|
}
|
|
|
|
/* sta handle leave */
|
|
void iot_cli_sta_leave()
|
|
{
|
|
iot_printf("plc_upgrade: sta leave\n");
|
|
if (host_config->switch_flag) {
|
|
iot_printf("plc_upgrade: switch flag is true, reset since leave\n");
|
|
iot_upgrade_reset();
|
|
return;
|
|
}
|
|
#if (IOT_SMART_GRID_ENABLE)
|
|
if (IOT_PLC_UPGRADE_TRANSFERRED == upgrade_info->upgrade_state) {
|
|
iot_printf("plc_upgrade: reset since leave\n");
|
|
iot_upgrade_reset();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void iot_cli_role_change(uint8_t prev_role, uint8_t cur_role)
|
|
{
|
|
if ((IOT_PLC_DEV_ROLE_STA == prev_role) && (IOT_PLC_DEV_ROLE_PCO == cur_role) &&
|
|
IOT_PLC_UPGRADE_TRANSFERRED == upgrade_info->upgrade_state) {
|
|
iot_printf("plc_upgrade: role change\n");
|
|
cli_remote_upgrade_pco_start();
|
|
}
|
|
}
|
|
|
|
#else /* IOT_CLI_UPGRADE_ENABLE */
|
|
|
|
/* sta state change handler */
|
|
void iot_cli_sta_state_change(uint8_t prev_nw_sn, uint8_t nw_sn)
|
|
{
|
|
(void)prev_nw_sn;
|
|
(void)nw_sn;
|
|
}
|
|
|
|
/* sta handle leave */
|
|
void iot_cli_sta_leave()
|
|
{
|
|
iot_printf("plc_upgrade: sta leave\n");
|
|
if (host_config->switch_flag) {
|
|
iot_printf("plc_upgrade: switch flag is true, reset since leave\n");
|
|
iot_upgrade_reset();
|
|
}
|
|
}
|
|
|
|
void iot_cli_role_change(uint8_t prev_role, uint8_t cur_role)
|
|
{
|
|
(void)prev_role;
|
|
(void)cur_role;
|
|
}
|
|
|
|
#endif /* IOT_CLI_UPGRADE_ENABLE */ |