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