static void process_dfu_packet(void * p_event_data, uint16_t event_size) { uint32_t retval; uint32_t index; dfu_update_packet_t * packet; while (false == DATA_QUEUE_EMPTY()) { // Fetch the element to be processed. for (index = 0; index < MAX_BUFFERS ; index++) { packet = &m_data_queue.data_packet[index]; if (INVALID_PACKET != packet->packet_type) { switch (DATA_QUEUE_ELEMENT_GET_PTYPE(index)) { case DATA_PACKET: (void)dfu_data_pkt_handle(packet); break; case START_PACKET: packet->params.start_packet = (dfu_start_packet_t*)packet->params.data_packet.p_data_packet; retval = dfu_start_pkt_handle(packet); APP_ERROR_CHECK(retval); break; case INIT_PACKET: (void)dfu_init_pkt_handle(packet); retval = dfu_init_pkt_complete(); APP_ERROR_CHECK(retval); break; case STOP_DATA_PACKET: (void)dfu_image_validate(); (void)dfu_image_activate(); // Break the loop by returning. return; default: // No implementation needed. break; } // Free the processed element. retval = data_queue_element_free(index); APP_ERROR_CHECK(retval); } } } }
/**@brief Function for processing initialization data written by the peer to the DFU Packet * Characteristic. * * @param[in] p_dfu DFU Service Structure. * @param[in] p_evt Pointer to the event received from the BLE stack. */ static void init_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { uint32_t err_code; uint8_t num_of_padding_bytes = 0; dfu_update_packet_t dfu_pkt; dfu_pkt.packet_type = INIT_PACKET; dfu_pkt.p_data_packet = (uint32_t *) p_evt->evt.ble_dfu_pkt_write.p_data; // The DFU module accepts the dfu_pkt.packet_length to be in 'number of words'. And so if the // received data does not have a size which is a multiple of four, it should be padded with // zeros and the packet_length should be incremented accordingly before calling // dfu_init_pkt_handle. if ((p_evt->evt.ble_dfu_pkt_write.len & (sizeof(uint32_t) - 1)) != 0) { // Find out the number of bytes to be padded. num_of_padding_bytes = sizeof(uint32_t) - (p_evt->evt.ble_dfu_pkt_write.len & (sizeof(uint32_t) - 1)); uint8_t i; for (i = 0; i < num_of_padding_bytes; i++) { dfu_pkt.p_data_packet[p_evt->evt.ble_dfu_pkt_write.len + i] = 0; } } dfu_pkt.packet_length = (p_evt->evt.ble_dfu_pkt_write.len + num_of_padding_bytes) / sizeof(uint32_t); err_code = dfu_init_pkt_handle(&dfu_pkt); // Translate the err_code returned by the above function to DFU Response Value. ble_dfu_resp_val_t resp_val; resp_val = nrf_error_to_dfu_resp_val(err_code, BLE_DFU_INIT_PROCEDURE); err_code = ble_dfu_response_send(p_dfu, BLE_DFU_INIT_PROCEDURE, resp_val); APP_ERROR_CHECK(err_code); }
/**@brief Function for processing start data written by the peer to the DFU Packet * Characteristic. * * @param[in] p_dfu DFU Service Structure. * @param[in] p_evt Pointer to the event received from the S110 SoftDevice. */ static void start_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { uint32_t err_code; dfu_start_packet_t start_packet = {.dfu_update_mode = m_update_mode}; dfu_update_packet_t update_packet = { .packet_type = START_PACKET, .params.start_packet = &start_packet }; uint32_t length = p_evt->evt.ble_dfu_pkt_write.len; // Verify that the data is exactly three * four bytes (three words) long. // Or a single word to support backwards compatibility of application image transfer. if ((length != (3 * sizeof(uint32_t))) && (length != sizeof(uint32_t))) { err_code = ble_dfu_response_send(p_dfu, BLE_DFU_START_PROCEDURE, BLE_DFU_RESP_VAL_NOT_SUPPORTED); APP_ERROR_CHECK(err_code); } else { // Extract the size of from the DFU Packet Characteristic. uint8_t * length_data = p_evt->evt.ble_dfu_pkt_write.p_data; if (length == sizeof(uint32_t)) { // Legacy update. start_packet.sd_image_size = 0; start_packet.bl_image_size = 0; start_packet.app_image_size = uint32_decode(length_data); } else { start_packet.sd_image_size = uint32_decode(length_data); start_packet.bl_image_size = uint32_decode(length_data + 4); start_packet.app_image_size = uint32_decode(length_data + 8); } err_code = dfu_start_pkt_handle(&update_packet); if (err_code != NRF_SUCCESS) { // Translate the err_code returned by the above function to DFU Response Value. ble_dfu_resp_val_t resp_val; resp_val = nrf_err_code_translate(err_code, BLE_DFU_START_PROCEDURE); err_code = ble_dfu_response_send(p_dfu, BLE_DFU_START_PROCEDURE, resp_val); } APP_ERROR_CHECK(err_code); } } /**@brief Function for processing initialization data written by the peer to the DFU Packet * Characteristic. * * @param[in] p_dfu DFU Service Structure. * @param[in] p_evt Pointer to the event received from the S110 SoftDevice. */ static void init_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { uint32_t err_code; dfu_update_packet_t dfu_pkt; uint8_t num_of_padding_bytes = 0; dfu_pkt.packet_type = INIT_PACKET; dfu_pkt.params.data_packet.p_data_packet = (uint32_t *)p_evt->evt.ble_dfu_pkt_write.p_data; // The DFU module accepts the dfu_pkt.packet_length to be in 'number of words'. And so if the // received data does not have a size which is a multiple of four, it should be padded with // zeros and the packet_length should be incremented accordingly before calling // dfu_init_pkt_handle. if ((p_evt->evt.ble_dfu_pkt_write.len & (sizeof(uint32_t) - 1)) != 0) { // Find out the number of bytes to be padded. num_of_padding_bytes = sizeof(uint32_t) - (p_evt->evt.ble_dfu_pkt_write.len & (sizeof(uint32_t) - 1)); uint32_t i; for (i = 0; i < num_of_padding_bytes; i++) { dfu_pkt.params.data_packet.p_data_packet[p_evt->evt.ble_dfu_pkt_write.len + i] = 0; } } dfu_pkt.params.data_packet.packet_length = (p_evt->evt.ble_dfu_pkt_write.len + num_of_padding_bytes) / sizeof(uint32_t); err_code = dfu_init_pkt_handle(&dfu_pkt); // Translate the err_code returned by the above function to DFU Response Value. ble_dfu_resp_val_t resp_val; resp_val = nrf_err_code_translate(err_code, BLE_DFU_INIT_PROCEDURE); err_code = ble_dfu_response_send(p_dfu, BLE_DFU_INIT_PROCEDURE, resp_val); APP_ERROR_CHECK(err_code); }
/**@brief Function for processing ANTFS upload request data event. * * @param[in] p_event The event extracted from the queue to be processed. */ static void antfs_event_upload_request_handle(const antfs_event_return_t * p_event) { uint32_t err_code = RESPONSE_MESSAGE_OK; uint8_t new_request = false; if ((m_antfs_dfu_state == ANTFS_DFU_STATE_FLASH_ERASE) || (m_antfs_dfu_state == ANTFS_DFU_STATE_FLASH_PENDING)) { return; } /*reset*/ m_response_info.file_index.data = p_event->file_index; m_response_info.max_burst_block_size.data = 0; m_response_info.max_file_size = 0; m_response_info.file_size.data = 0; m_response_info.file_crc = 0; // Evaluate File Index first if (m_current_file_index != p_event->file_index ) { m_current_file_index = p_event->file_index; m_current_offset = 0; m_current_crc = 0; } if (p_event->offset == MAX_ULONG) { // This is a request to continue upload. } else if (p_event->offset == 0x00) { new_request = true; } else if(p_event->offset != m_current_offset) { // Something is wrong. UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_INVALID_OPERATION, &m_response_info)); m_antfs_dfu_state = ANTFS_DFU_STATE_STALL; } else { // no implementation. } switch (m_current_file_index) { #if !defined (S210_V3_STACK) case ANTFS_FILE_INDEX_UPDATE_STACK: case ANTFS_FILE_INDEX_UPDATE_BOOTLOADER: case ANTFS_FILE_INDEX_UPDATE_STACK_BOOTLOADER: #endif // S210_V3_STACK case ANTFS_FILE_INDEX_UPDATE_APPLICATION: { // Current valid file size is the last offset written to the file. m_response_info.file_size.data = m_current_offset; // Intentionally report maximum allowed upload file size as max writeable file size + header and crc. // Writeable size check will be performed by dfu_start_pkt_handle() after parsing uploaded header m_response_info.max_file_size = ANTFS_FILE_SIZE_MAX_DFU_IMAGE + OTA_IMAGE_HEADER_SIZE_MAX; // Maximum burst block should be maximum allowable downloadable file size. m_response_info.max_burst_block_size.data = ANTFS_FILE_SIZE_MAX_DFU_IMAGE + OTA_IMAGE_HEADER_SIZE_MAX; // Last valid CRC. m_response_info.file_crc = m_current_crc; // Will only handle upload request while at ANTFS_DFU_STATE_READY if (m_antfs_dfu_state == ANTFS_DFU_STATE_VALIDATED) { if (new_request) { UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_NOT_AVAILABLE, &m_response_info)); } else { UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_OK, &m_response_info)); // To handle resume at end of data. } return; } else if (m_antfs_dfu_state != ANTFS_DFU_STATE_READY) { UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_NOT_AVAILABLE, &m_response_info)); return; } // Check File Size if it can still fit. Uploaded file size may be larger than the total writeable space because it includes header // and CRC that do not get written to flash. Writeable size check will be performed by dfu_start_pk_handle() after // parsing uploaded header if ((p_event->offset + p_event->bytes) > (ANTFS_FILE_SIZE_MAX_DFU_IMAGE + OTA_IMAGE_HEADER_SIZE_MAX + OTA_IMAGE_CRC_SIZE_MAX)) { UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_NOT_ENOUGH_SPACE, &m_response_info)); return; } m_data_buffered = 0; if (new_request) { m_current_offset = 0; m_current_crc = 0; m_pending_offset = 0; antfs_ota_init(); // Only supports offset starting at 0; if (p_event->offset != 0) { UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_FAIL, &m_response_info)); return; } // boot_return_set(PARAM_RETURN_BOOT_STATUS_Entered); // Store file size, m_current_file_size = p_event->bytes; if (m_current_file_index == ANTFS_FILE_INDEX_UPDATE_STACK) { m_update_mode = DFU_UPDATE_SD; } else if (m_current_file_index == ANTFS_FILE_INDEX_UPDATE_BOOTLOADER) { m_update_mode = DFU_UPDATE_BL; } else if (m_current_file_index == ANTFS_FILE_INDEX_UPDATE_APPLICATION) { m_update_mode = DFU_UPDATE_APP; } else if (m_current_file_index == ANTFS_FILE_INDEX_UPDATE_STACK_BOOTLOADER) { m_update_mode = DFU_UPDATE_SD; m_update_mode |= DFU_UPDATE_BL;//lint !e655 suppress Lint Warning 655: Bit-wise operations } m_dfu_pkt.packet_type = INIT_PACKET; if ((*ANT_BOOT_APP_SIZE > DFU_IMAGE_MAX_SIZE_BANKED) || (*ANT_BOOT_APP_SIZE == 0xFFFFFFFF) || (*ANT_BOOT_APP_SIZE == 0x00000000) || (m_update_mode & DFU_UPDATE_SD))/*lint !e655 suppress Lint Warning 655: Bit-wise operations*/ { m_dfu_pkt.params.init_packet.total_image_size = DFU_IMAGE_MAX_SIZE_FULL; } else { m_dfu_pkt.params.init_packet.total_image_size = m_current_file_size; } if (m_upload_swap_space_prepared == true) { // Prepare no flash, except the states m_dfu_pkt.params.init_packet.total_image_size = 0; } err_code = dfu_init_pkt_handle(&m_dfu_pkt); if (err_code) { if (err_code == NRF_ERROR_INVALID_STATE) { UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_INVALID_OPERATION, &m_response_info)); } else { UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_FAIL, &m_response_info)); } return; } m_ota_image_header_parsed = false; m_image_data_complete = false; m_image_data_offset = 0; m_data_buffered = 0; // A flash erase is expected at this time. postpone response if there is. if (flash_busy()) { m_upload_request_in_progress = true; m_antfs_dfu_state = ANTFS_DFU_STATE_FLASH_ERASE; return; } } else { // Check if there are still pending writes scheduled in Flash. if (flash_busy()) { m_upload_request_in_progress = true; m_antfs_dfu_state = ANTFS_DFU_STATE_FLASH_PENDING; return; } } m_antfs_dfu_state = ANTFS_DFU_STATE_READY; UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_OK, &m_response_info)); } break; default: m_antfs_dfu_state = ANTFS_DFU_STATE_READY; UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_NOT_EXIST, &m_response_info)); } }