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 */ |