// File callback to be used with vfs_add_file to return file contents static uint32_t read_file_fail_txt(uint32_t sector_offset, uint8_t* data, uint32_t num_sectors) { const char* contents = (const char*)error_get_string(fail_reason); uint32_t size = strlen(contents); if (sector_offset != 0) { return 0; } memcpy(data, contents, size); return size; }
// Check if the current transfer is still in progress, done, or if an error has occurred static void transfer_update_state(error_t status) { bool transfer_timeout; bool transfer_started; bool transfer_can_be_finished; bool transfer_must_be_finished; bool out_of_order_sector; error_t local_status = status; util_assert((status != ERROR_SUCCESS_DONE) && (status != ERROR_SUCCESS_DONE_OR_CONTINUE)); if (TRASNFER_FINISHED == file_transfer_state.transfer_state) { util_assert(0); return; } // Update file info status. The end of a file is never known for sure since // what looks like a complete file could be part of a file getting flushed to disk. // The criteria for an successful optional finish is // 1. A file has been detected // 2. The size of the file indicated in the root dir has been transferred // 3. The file size is greater than zero file_transfer_state.file_info_optional_finish = (file_transfer_state.file_to_program != VFS_FILE_INVALID) && (file_transfer_state.size_transferred >= file_transfer_state.file_size) && (file_transfer_state.file_size > 0); transfer_timeout = file_transfer_state.transfer_timeout; transfer_started = (VFS_FILE_INVALID != file_transfer_state.file_to_program) || (STREAM_TYPE_NONE != file_transfer_state.stream); // The transfer can be finished if both file and stream processing // can be considered complete transfer_can_be_finished = file_transfer_state.file_info_optional_finish && file_transfer_state.stream_optional_finish; // The transfer must be fnished if stream processing is for sure complete // and file processing can be considered complete transfer_must_be_finished = file_transfer_state.stream_finished && file_transfer_state.file_info_optional_finish; out_of_order_sector = false; if (file_transfer_state.last_ooo_sector != VFS_INVALID_SECTOR) { util_assert(file_transfer_state.start_sector != VFS_INVALID_SECTOR); uint32_t sector_offset = (file_transfer_state.last_ooo_sector - file_transfer_state.start_sector) * VFS_SECTOR_SIZE; if (sector_offset < file_transfer_state.size_processed) { // The out of order sector was within the range of data already // processed. out_of_order_sector = true; } } // Set the transfer state and set the status if necessary if (local_status != ERROR_SUCCESS) { file_transfer_state.transfer_state = TRASNFER_FINISHED; } else if (transfer_timeout) { if (out_of_order_sector) { local_status = ERROR_OOO_SECTOR; } else if (!transfer_started) { local_status = ERROR_SUCCESS; } else if (transfer_can_be_finished) { local_status = ERROR_SUCCESS; } else { local_status = ERROR_TRANSFER_TIMEOUT; } file_transfer_state.transfer_state = TRASNFER_FINISHED; } else if (transfer_must_be_finished) { file_transfer_state.transfer_state = TRASNFER_FINISHED; } else if (transfer_can_be_finished) { file_transfer_state.transfer_state = TRANSFER_CAN_BE_FINISHED; } else if (transfer_started) { file_transfer_state.transfer_state = TRANSFER_IN_PROGRESS; } if (TRASNFER_FINISHED == file_transfer_state.transfer_state) { vfs_mngr_printf("vfs_manager transfer_update_state(status=%i)\r\n", status); vfs_mngr_printf(" file=%p, start_sect= %i, size=%i\r\n", file_transfer_state.file_to_program, file_transfer_state.start_sector, file_transfer_state.file_size); vfs_mngr_printf(" stream=%i, size_processed=%i, opt_finish=%i, timeout=%i\r\n", file_transfer_state.stream, file_transfer_state.size_processed, file_transfer_state.file_info_optional_finish, transfer_timeout); // Close the file stream if it is open if (file_transfer_state.stream_open) { error_t close_status; close_status = stream_close(); vfs_mngr_printf(" stream closed ret=%i\r\n", close_status); file_transfer_state.stream_open = false; if (ERROR_SUCCESS == local_status) { local_status = close_status; } } // Set the fail reason fail_reason = local_status; vfs_mngr_printf(" Transfer finished, status: %i=%s\r\n", fail_reason, error_get_string(fail_reason)); } // If this state change is not from aborting a transfer // due to a remount then trigger a remount if (!transfer_timeout) { vfs_mngr_fs_remount(); } }