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