![](/media/cache/group/arrow_temp_636x636.png.50x50_q85.png)
Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.
Upstream: https://github.com/ARMmbed/DAPLink
source/daplink/drag-n-drop/vfs_manager.c@0:01f31e923fe2, 2020-04-07 (annotated)
- Committer:
- Pawel Zarembski
- Date:
- Tue Apr 07 12:55:42 2020 +0200
- Revision:
- 0:01f31e923fe2
hani: DAPLink with reset workaround
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Pawel Zarembski |
0:01f31e923fe2 | 1 | /** |
Pawel Zarembski |
0:01f31e923fe2 | 2 | * @file vfs_manager.c |
Pawel Zarembski |
0:01f31e923fe2 | 3 | * @brief Implementation of vfs_manager.h |
Pawel Zarembski |
0:01f31e923fe2 | 4 | * |
Pawel Zarembski |
0:01f31e923fe2 | 5 | * DAPLink Interface Firmware |
Pawel Zarembski |
0:01f31e923fe2 | 6 | * Copyright (c) 2009-2019, ARM Limited, All Rights Reserved |
Pawel Zarembski |
0:01f31e923fe2 | 7 | * SPDX-License-Identifier: Apache-2.0 |
Pawel Zarembski |
0:01f31e923fe2 | 8 | * |
Pawel Zarembski |
0:01f31e923fe2 | 9 | * Licensed under the Apache License, Version 2.0 (the "License"); you may |
Pawel Zarembski |
0:01f31e923fe2 | 10 | * not use this file except in compliance with the License. |
Pawel Zarembski |
0:01f31e923fe2 | 11 | * You may obtain a copy of the License at |
Pawel Zarembski |
0:01f31e923fe2 | 12 | * |
Pawel Zarembski |
0:01f31e923fe2 | 13 | * http://www.apache.org/licenses/LICENSE-2.0 |
Pawel Zarembski |
0:01f31e923fe2 | 14 | * |
Pawel Zarembski |
0:01f31e923fe2 | 15 | * Unless required by applicable law or agreed to in writing, software |
Pawel Zarembski |
0:01f31e923fe2 | 16 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
Pawel Zarembski |
0:01f31e923fe2 | 17 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
Pawel Zarembski |
0:01f31e923fe2 | 18 | * See the License for the specific language governing permissions and |
Pawel Zarembski |
0:01f31e923fe2 | 19 | * limitations under the License. |
Pawel Zarembski |
0:01f31e923fe2 | 20 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 21 | |
Pawel Zarembski |
0:01f31e923fe2 | 22 | #include <ctype.h> |
Pawel Zarembski |
0:01f31e923fe2 | 23 | |
Pawel Zarembski |
0:01f31e923fe2 | 24 | #include "main.h" |
Pawel Zarembski |
0:01f31e923fe2 | 25 | #include "cmsis_os2.h" |
Pawel Zarembski |
0:01f31e923fe2 | 26 | #include "rl_usb.h" |
Pawel Zarembski |
0:01f31e923fe2 | 27 | #include "virtual_fs.h" |
Pawel Zarembski |
0:01f31e923fe2 | 28 | #include "vfs_manager.h" |
Pawel Zarembski |
0:01f31e923fe2 | 29 | #include "daplink_debug.h" |
Pawel Zarembski |
0:01f31e923fe2 | 30 | #include "info.h" |
Pawel Zarembski |
0:01f31e923fe2 | 31 | #include "settings.h" |
Pawel Zarembski |
0:01f31e923fe2 | 32 | #include "daplink.h" |
Pawel Zarembski |
0:01f31e923fe2 | 33 | #include "util.h" |
Pawel Zarembski |
0:01f31e923fe2 | 34 | #include "version_git.h" |
Pawel Zarembski |
0:01f31e923fe2 | 35 | #include "IO_Config.h" |
Pawel Zarembski |
0:01f31e923fe2 | 36 | #include "file_stream.h" |
Pawel Zarembski |
0:01f31e923fe2 | 37 | #include "error.h" |
Pawel Zarembski |
0:01f31e923fe2 | 38 | |
Pawel Zarembski |
0:01f31e923fe2 | 39 | // Set to 1 to enable debugging |
Pawel Zarembski |
0:01f31e923fe2 | 40 | #define DEBUG_VFS_MANAGER 0 |
Pawel Zarembski |
0:01f31e923fe2 | 41 | |
Pawel Zarembski |
0:01f31e923fe2 | 42 | #if DEBUG_VFS_MANAGER |
Pawel Zarembski |
0:01f31e923fe2 | 43 | #define vfs_mngr_printf debug_msg |
Pawel Zarembski |
0:01f31e923fe2 | 44 | #else |
Pawel Zarembski |
0:01f31e923fe2 | 45 | #define vfs_mngr_printf(...) |
Pawel Zarembski |
0:01f31e923fe2 | 46 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 47 | |
Pawel Zarembski |
0:01f31e923fe2 | 48 | #define INVALID_TIMEOUT_MS 0xFFFFFFFF |
Pawel Zarembski |
0:01f31e923fe2 | 49 | #define MAX_EVENT_TIME_MS 60000 |
Pawel Zarembski |
0:01f31e923fe2 | 50 | |
Pawel Zarembski |
0:01f31e923fe2 | 51 | #define CONNECT_DELAY_MS 0 |
Pawel Zarembski |
0:01f31e923fe2 | 52 | #define RECONNECT_DELAY_MS 2500 // Must be above 1s for windows (more for linux) |
Pawel Zarembski |
0:01f31e923fe2 | 53 | // TRANSFER_IN_PROGRESS |
Pawel Zarembski |
0:01f31e923fe2 | 54 | #define DISCONNECT_DELAY_TRANSFER_TIMEOUT_MS 20000 |
Pawel Zarembski |
0:01f31e923fe2 | 55 | // TRANSFER_CAN_BE_FINISHED |
Pawel Zarembski |
0:01f31e923fe2 | 56 | #define DISCONNECT_DELAY_TRANSFER_IDLE_MS 500 |
Pawel Zarembski |
0:01f31e923fe2 | 57 | // TRANSFER_NOT_STARTED || TRASNFER_FINISHED |
Pawel Zarembski |
0:01f31e923fe2 | 58 | #define DISCONNECT_DELAY_MS 500 |
Pawel Zarembski |
0:01f31e923fe2 | 59 | |
Pawel Zarembski |
0:01f31e923fe2 | 60 | // Make sure none of the delays exceed the max time |
Pawel Zarembski |
0:01f31e923fe2 | 61 | COMPILER_ASSERT(CONNECT_DELAY_MS < MAX_EVENT_TIME_MS); |
Pawel Zarembski |
0:01f31e923fe2 | 62 | COMPILER_ASSERT(RECONNECT_DELAY_MS < MAX_EVENT_TIME_MS); |
Pawel Zarembski |
0:01f31e923fe2 | 63 | COMPILER_ASSERT(DISCONNECT_DELAY_TRANSFER_TIMEOUT_MS < MAX_EVENT_TIME_MS); |
Pawel Zarembski |
0:01f31e923fe2 | 64 | COMPILER_ASSERT(DISCONNECT_DELAY_TRANSFER_IDLE_MS < MAX_EVENT_TIME_MS); |
Pawel Zarembski |
0:01f31e923fe2 | 65 | COMPILER_ASSERT(DISCONNECT_DELAY_MS < MAX_EVENT_TIME_MS); |
Pawel Zarembski |
0:01f31e923fe2 | 66 | |
Pawel Zarembski |
0:01f31e923fe2 | 67 | typedef enum { |
Pawel Zarembski |
0:01f31e923fe2 | 68 | TRANSFER_NOT_STARTED, |
Pawel Zarembski |
0:01f31e923fe2 | 69 | TRANSFER_IN_PROGRESS, |
Pawel Zarembski |
0:01f31e923fe2 | 70 | TRANSFER_CAN_BE_FINISHED, |
Pawel Zarembski |
0:01f31e923fe2 | 71 | TRASNFER_FINISHED, |
Pawel Zarembski |
0:01f31e923fe2 | 72 | } transfer_state_t; |
Pawel Zarembski |
0:01f31e923fe2 | 73 | |
Pawel Zarembski |
0:01f31e923fe2 | 74 | typedef struct { |
Pawel Zarembski |
0:01f31e923fe2 | 75 | vfs_file_t file_to_program; // A pointer to the directory entry of the file being programmed |
Pawel Zarembski |
0:01f31e923fe2 | 76 | vfs_sector_t start_sector; // Start sector of the file being programmed by stream |
Pawel Zarembski |
0:01f31e923fe2 | 77 | vfs_sector_t file_start_sector; // Start sector of the file being programmed by vfs |
Pawel Zarembski |
0:01f31e923fe2 | 78 | vfs_sector_t file_next_sector; // Expected next sector of the file |
Pawel Zarembski |
0:01f31e923fe2 | 79 | vfs_sector_t last_ooo_sector; // Last out of order sector within the file |
Pawel Zarembski |
0:01f31e923fe2 | 80 | uint32_t size_processed; // The number of bytes processed by the stream |
Pawel Zarembski |
0:01f31e923fe2 | 81 | uint32_t file_size; // Size of the file indicated by root dir. Only allowed to increase |
Pawel Zarembski |
0:01f31e923fe2 | 82 | uint32_t size_transferred; // The number of bytes transferred |
Pawel Zarembski |
0:01f31e923fe2 | 83 | transfer_state_t transfer_state;// Transfer state |
Pawel Zarembski |
0:01f31e923fe2 | 84 | bool stream_open; // State of the stream |
Pawel Zarembski |
0:01f31e923fe2 | 85 | bool stream_started; // Stream processing started. This only gets reset remount |
Pawel Zarembski |
0:01f31e923fe2 | 86 | bool stream_finished; // Stream processing is done. This only gets reset remount |
Pawel Zarembski |
0:01f31e923fe2 | 87 | bool stream_optional_finish; // True if the stream processing can be considered done |
Pawel Zarembski |
0:01f31e923fe2 | 88 | bool file_info_optional_finish; // True if the file transfer can be considered done |
Pawel Zarembski |
0:01f31e923fe2 | 89 | bool transfer_timeout; // Set if the transfer was finished because of a timeout. This only gets reset remount |
Pawel Zarembski |
0:01f31e923fe2 | 90 | stream_type_t stream; // Current stream or STREAM_TYPE_NONE is stream is closed. This only gets reset remount |
Pawel Zarembski |
0:01f31e923fe2 | 91 | } file_transfer_state_t; |
Pawel Zarembski |
0:01f31e923fe2 | 92 | |
Pawel Zarembski |
0:01f31e923fe2 | 93 | typedef enum { |
Pawel Zarembski |
0:01f31e923fe2 | 94 | VFS_MNGR_STATE_DISCONNECTED, |
Pawel Zarembski |
0:01f31e923fe2 | 95 | VFS_MNGR_STATE_RECONNECTING, |
Pawel Zarembski |
0:01f31e923fe2 | 96 | VFS_MNGR_STATE_CONNECTED |
Pawel Zarembski |
0:01f31e923fe2 | 97 | } vfs_mngr_state_t; |
Pawel Zarembski |
0:01f31e923fe2 | 98 | |
Pawel Zarembski |
0:01f31e923fe2 | 99 | static const file_transfer_state_t default_transfer_state = { |
Pawel Zarembski |
0:01f31e923fe2 | 100 | VFS_FILE_INVALID, |
Pawel Zarembski |
0:01f31e923fe2 | 101 | VFS_INVALID_SECTOR, |
Pawel Zarembski |
0:01f31e923fe2 | 102 | VFS_INVALID_SECTOR, |
Pawel Zarembski |
0:01f31e923fe2 | 103 | VFS_INVALID_SECTOR, |
Pawel Zarembski |
0:01f31e923fe2 | 104 | VFS_INVALID_SECTOR, |
Pawel Zarembski |
0:01f31e923fe2 | 105 | 0, |
Pawel Zarembski |
0:01f31e923fe2 | 106 | 0, |
Pawel Zarembski |
0:01f31e923fe2 | 107 | 0, |
Pawel Zarembski |
0:01f31e923fe2 | 108 | TRANSFER_NOT_STARTED, |
Pawel Zarembski |
0:01f31e923fe2 | 109 | false, |
Pawel Zarembski |
0:01f31e923fe2 | 110 | false, |
Pawel Zarembski |
0:01f31e923fe2 | 111 | false, |
Pawel Zarembski |
0:01f31e923fe2 | 112 | false, |
Pawel Zarembski |
0:01f31e923fe2 | 113 | false, |
Pawel Zarembski |
0:01f31e923fe2 | 114 | false, |
Pawel Zarembski |
0:01f31e923fe2 | 115 | STREAM_TYPE_NONE, |
Pawel Zarembski |
0:01f31e923fe2 | 116 | }; |
Pawel Zarembski |
0:01f31e923fe2 | 117 | |
Pawel Zarembski |
0:01f31e923fe2 | 118 | //Compile option not to include MSC at all, these will be dummy variables |
Pawel Zarembski |
0:01f31e923fe2 | 119 | #ifndef MSC_ENDPOINT |
Pawel Zarembski |
0:01f31e923fe2 | 120 | BOOL USBD_MSC_MediaReady = __FALSE; |
Pawel Zarembski |
0:01f31e923fe2 | 121 | BOOL USBD_MSC_ReadOnly = __FALSE; |
Pawel Zarembski |
0:01f31e923fe2 | 122 | U32 USBD_MSC_MemorySize; |
Pawel Zarembski |
0:01f31e923fe2 | 123 | U32 USBD_MSC_BlockSize; |
Pawel Zarembski |
0:01f31e923fe2 | 124 | U32 USBD_MSC_BlockGroup; |
Pawel Zarembski |
0:01f31e923fe2 | 125 | U32 USBD_MSC_BlockCount; |
Pawel Zarembski |
0:01f31e923fe2 | 126 | U8 *USBD_MSC_BlockBuf; |
Pawel Zarembski |
0:01f31e923fe2 | 127 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 128 | |
Pawel Zarembski |
0:01f31e923fe2 | 129 | static uint32_t usb_buffer[VFS_SECTOR_SIZE / sizeof(uint32_t)]; |
Pawel Zarembski |
0:01f31e923fe2 | 130 | static error_t fail_reason = ERROR_SUCCESS; |
Pawel Zarembski |
0:01f31e923fe2 | 131 | static file_transfer_state_t file_transfer_state; |
Pawel Zarembski |
0:01f31e923fe2 | 132 | |
Pawel Zarembski |
0:01f31e923fe2 | 133 | // These variables can be access from multiple threads |
Pawel Zarembski |
0:01f31e923fe2 | 134 | // so access to them must be synchronized |
Pawel Zarembski |
0:01f31e923fe2 | 135 | static vfs_mngr_state_t vfs_state; |
Pawel Zarembski |
0:01f31e923fe2 | 136 | static vfs_mngr_state_t vfs_state_next; |
Pawel Zarembski |
0:01f31e923fe2 | 137 | static uint32_t time_usb_idle; |
Pawel Zarembski |
0:01f31e923fe2 | 138 | |
Pawel Zarembski |
0:01f31e923fe2 | 139 | static osMutexId_t sync_mutex; |
Pawel Zarembski |
0:01f31e923fe2 | 140 | static osThreadId_t sync_thread = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 141 | |
Pawel Zarembski |
0:01f31e923fe2 | 142 | // Synchronization functions |
Pawel Zarembski |
0:01f31e923fe2 | 143 | static void sync_init(void); |
Pawel Zarembski |
0:01f31e923fe2 | 144 | static void sync_assert_usb_thread(void); |
Pawel Zarembski |
0:01f31e923fe2 | 145 | static void sync_lock(void); |
Pawel Zarembski |
0:01f31e923fe2 | 146 | static void sync_unlock(void); |
Pawel Zarembski |
0:01f31e923fe2 | 147 | |
Pawel Zarembski |
0:01f31e923fe2 | 148 | static bool changing_state(void); |
Pawel Zarembski |
0:01f31e923fe2 | 149 | static void build_filesystem(void); |
Pawel Zarembski |
0:01f31e923fe2 | 150 | static void file_change_handler(const vfs_filename_t filename, vfs_file_change_t change, vfs_file_t file, vfs_file_t new_file_data); |
Pawel Zarembski |
0:01f31e923fe2 | 151 | static void file_data_handler(uint32_t sector, const uint8_t *buf, uint32_t num_of_sectors); |
Pawel Zarembski |
0:01f31e923fe2 | 152 | static bool ready_for_state_change(void); |
Pawel Zarembski |
0:01f31e923fe2 | 153 | static void abort_remount(void); |
Pawel Zarembski |
0:01f31e923fe2 | 154 | |
Pawel Zarembski |
0:01f31e923fe2 | 155 | static void transfer_update_file_info(vfs_file_t file, uint32_t start_sector, uint32_t size, stream_type_t stream); |
Pawel Zarembski |
0:01f31e923fe2 | 156 | static void transfer_reset_file_info(void); |
Pawel Zarembski |
0:01f31e923fe2 | 157 | static void transfer_stream_open(stream_type_t stream, uint32_t start_sector); |
Pawel Zarembski |
0:01f31e923fe2 | 158 | static void transfer_stream_data(uint32_t sector, const uint8_t *data, uint32_t size); |
Pawel Zarembski |
0:01f31e923fe2 | 159 | static void transfer_update_state(error_t status); |
Pawel Zarembski |
0:01f31e923fe2 | 160 | |
Pawel Zarembski |
0:01f31e923fe2 | 161 | |
Pawel Zarembski |
0:01f31e923fe2 | 162 | void vfs_mngr_fs_enable(bool enable) |
Pawel Zarembski |
0:01f31e923fe2 | 163 | { |
Pawel Zarembski |
0:01f31e923fe2 | 164 | sync_lock(); |
Pawel Zarembski |
0:01f31e923fe2 | 165 | |
Pawel Zarembski |
0:01f31e923fe2 | 166 | if (enable) { |
Pawel Zarembski |
0:01f31e923fe2 | 167 | if (VFS_MNGR_STATE_DISCONNECTED == vfs_state_next) { |
Pawel Zarembski |
0:01f31e923fe2 | 168 | vfs_state_next = VFS_MNGR_STATE_CONNECTED; |
Pawel Zarembski |
0:01f31e923fe2 | 169 | } |
Pawel Zarembski |
0:01f31e923fe2 | 170 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 171 | vfs_state_next = VFS_MNGR_STATE_DISCONNECTED; |
Pawel Zarembski |
0:01f31e923fe2 | 172 | } |
Pawel Zarembski |
0:01f31e923fe2 | 173 | |
Pawel Zarembski |
0:01f31e923fe2 | 174 | sync_unlock(); |
Pawel Zarembski |
0:01f31e923fe2 | 175 | } |
Pawel Zarembski |
0:01f31e923fe2 | 176 | |
Pawel Zarembski |
0:01f31e923fe2 | 177 | void vfs_mngr_fs_remount(void) |
Pawel Zarembski |
0:01f31e923fe2 | 178 | { |
Pawel Zarembski |
0:01f31e923fe2 | 179 | sync_lock(); |
Pawel Zarembski |
0:01f31e923fe2 | 180 | |
Pawel Zarembski |
0:01f31e923fe2 | 181 | // Only start a remount if in the connected state and not in a transition |
Pawel Zarembski |
0:01f31e923fe2 | 182 | if (!changing_state() && (VFS_MNGR_STATE_CONNECTED == vfs_state)) { |
Pawel Zarembski |
0:01f31e923fe2 | 183 | vfs_state_next = VFS_MNGR_STATE_RECONNECTING; |
Pawel Zarembski |
0:01f31e923fe2 | 184 | } |
Pawel Zarembski |
0:01f31e923fe2 | 185 | |
Pawel Zarembski |
0:01f31e923fe2 | 186 | sync_unlock(); |
Pawel Zarembski |
0:01f31e923fe2 | 187 | } |
Pawel Zarembski |
0:01f31e923fe2 | 188 | |
Pawel Zarembski |
0:01f31e923fe2 | 189 | void vfs_mngr_init(bool enable) |
Pawel Zarembski |
0:01f31e923fe2 | 190 | { |
Pawel Zarembski |
0:01f31e923fe2 | 191 | sync_assert_usb_thread(); |
Pawel Zarembski |
0:01f31e923fe2 | 192 | build_filesystem(); |
Pawel Zarembski |
0:01f31e923fe2 | 193 | |
Pawel Zarembski |
0:01f31e923fe2 | 194 | if (enable) { |
Pawel Zarembski |
0:01f31e923fe2 | 195 | vfs_state = VFS_MNGR_STATE_CONNECTED; |
Pawel Zarembski |
0:01f31e923fe2 | 196 | vfs_state_next = VFS_MNGR_STATE_CONNECTED; |
Pawel Zarembski |
0:01f31e923fe2 | 197 | USBD_MSC_MediaReady = 1; |
Pawel Zarembski |
0:01f31e923fe2 | 198 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 199 | vfs_state = VFS_MNGR_STATE_DISCONNECTED; |
Pawel Zarembski |
0:01f31e923fe2 | 200 | vfs_state_next = VFS_MNGR_STATE_DISCONNECTED; |
Pawel Zarembski |
0:01f31e923fe2 | 201 | USBD_MSC_MediaReady = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 202 | } |
Pawel Zarembski |
0:01f31e923fe2 | 203 | } |
Pawel Zarembski |
0:01f31e923fe2 | 204 | |
Pawel Zarembski |
0:01f31e923fe2 | 205 | void vfs_mngr_periodic(uint32_t elapsed_ms) |
Pawel Zarembski |
0:01f31e923fe2 | 206 | { |
Pawel Zarembski |
0:01f31e923fe2 | 207 | bool change_state; |
Pawel Zarembski |
0:01f31e923fe2 | 208 | vfs_mngr_state_t vfs_state_local; |
Pawel Zarembski |
0:01f31e923fe2 | 209 | vfs_mngr_state_t vfs_state_local_prev; |
Pawel Zarembski |
0:01f31e923fe2 | 210 | sync_assert_usb_thread(); |
Pawel Zarembski |
0:01f31e923fe2 | 211 | sync_lock(); |
Pawel Zarembski |
0:01f31e923fe2 | 212 | |
Pawel Zarembski |
0:01f31e923fe2 | 213 | // Return immediately if the desired state has been reached |
Pawel Zarembski |
0:01f31e923fe2 | 214 | if (!changing_state()) { |
Pawel Zarembski |
0:01f31e923fe2 | 215 | sync_unlock(); |
Pawel Zarembski |
0:01f31e923fe2 | 216 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 217 | } |
Pawel Zarembski |
0:01f31e923fe2 | 218 | |
Pawel Zarembski |
0:01f31e923fe2 | 219 | change_state = ready_for_state_change(); |
Pawel Zarembski |
0:01f31e923fe2 | 220 | |
Pawel Zarembski |
0:01f31e923fe2 | 221 | if (time_usb_idle < MAX_EVENT_TIME_MS) { |
Pawel Zarembski |
0:01f31e923fe2 | 222 | time_usb_idle += elapsed_ms; |
Pawel Zarembski |
0:01f31e923fe2 | 223 | } |
Pawel Zarembski |
0:01f31e923fe2 | 224 | |
Pawel Zarembski |
0:01f31e923fe2 | 225 | if (!change_state) { |
Pawel Zarembski |
0:01f31e923fe2 | 226 | sync_unlock(); |
Pawel Zarembski |
0:01f31e923fe2 | 227 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 228 | } |
Pawel Zarembski |
0:01f31e923fe2 | 229 | |
Pawel Zarembski |
0:01f31e923fe2 | 230 | vfs_mngr_printf("vfs_mngr_periodic()\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 231 | vfs_mngr_printf(" time_usb_idle=%i\r\n", time_usb_idle); |
Pawel Zarembski |
0:01f31e923fe2 | 232 | vfs_mngr_printf(" transfer_state=%i\r\n", file_transfer_state.transfer_state); |
Pawel Zarembski |
0:01f31e923fe2 | 233 | // Transistion to new state |
Pawel Zarembski |
0:01f31e923fe2 | 234 | vfs_state_local_prev = vfs_state; |
Pawel Zarembski |
0:01f31e923fe2 | 235 | vfs_state = vfs_state_next; |
Pawel Zarembski |
0:01f31e923fe2 | 236 | |
Pawel Zarembski |
0:01f31e923fe2 | 237 | switch (vfs_state) { |
Pawel Zarembski |
0:01f31e923fe2 | 238 | case VFS_MNGR_STATE_RECONNECTING: |
Pawel Zarembski |
0:01f31e923fe2 | 239 | // Transition back to the connected state |
Pawel Zarembski |
0:01f31e923fe2 | 240 | vfs_state_next = VFS_MNGR_STATE_CONNECTED; |
Pawel Zarembski |
0:01f31e923fe2 | 241 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 242 | |
Pawel Zarembski |
0:01f31e923fe2 | 243 | default: |
Pawel Zarembski |
0:01f31e923fe2 | 244 | // No state change logic required in other states |
Pawel Zarembski |
0:01f31e923fe2 | 245 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 246 | } |
Pawel Zarembski |
0:01f31e923fe2 | 247 | |
Pawel Zarembski |
0:01f31e923fe2 | 248 | vfs_state_local = vfs_state; |
Pawel Zarembski |
0:01f31e923fe2 | 249 | time_usb_idle = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 250 | sync_unlock(); |
Pawel Zarembski |
0:01f31e923fe2 | 251 | // Processing when leaving a state |
Pawel Zarembski |
0:01f31e923fe2 | 252 | vfs_mngr_printf(" state %i->%i\r\n", vfs_state_local_prev, vfs_state_local); |
Pawel Zarembski |
0:01f31e923fe2 | 253 | |
Pawel Zarembski |
0:01f31e923fe2 | 254 | switch (vfs_state_local_prev) { |
Pawel Zarembski |
0:01f31e923fe2 | 255 | case VFS_MNGR_STATE_DISCONNECTED: |
Pawel Zarembski |
0:01f31e923fe2 | 256 | // No action needed |
Pawel Zarembski |
0:01f31e923fe2 | 257 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 258 | |
Pawel Zarembski |
0:01f31e923fe2 | 259 | case VFS_MNGR_STATE_RECONNECTING: |
Pawel Zarembski |
0:01f31e923fe2 | 260 | // No action needed |
Pawel Zarembski |
0:01f31e923fe2 | 261 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 262 | |
Pawel Zarembski |
0:01f31e923fe2 | 263 | case VFS_MNGR_STATE_CONNECTED: |
Pawel Zarembski |
0:01f31e923fe2 | 264 | |
Pawel Zarembski |
0:01f31e923fe2 | 265 | // Close ongoing transfer if there is one |
Pawel Zarembski |
0:01f31e923fe2 | 266 | if (file_transfer_state.transfer_state != TRASNFER_FINISHED) { |
Pawel Zarembski |
0:01f31e923fe2 | 267 | vfs_mngr_printf(" transfer timeout\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 268 | file_transfer_state.transfer_timeout = true; |
Pawel Zarembski |
0:01f31e923fe2 | 269 | transfer_update_state(ERROR_SUCCESS); |
Pawel Zarembski |
0:01f31e923fe2 | 270 | } |
Pawel Zarembski |
0:01f31e923fe2 | 271 | |
Pawel Zarembski |
0:01f31e923fe2 | 272 | util_assert(TRASNFER_FINISHED == file_transfer_state.transfer_state); |
Pawel Zarembski |
0:01f31e923fe2 | 273 | vfs_user_disconnecting(); |
Pawel Zarembski |
0:01f31e923fe2 | 274 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 275 | } |
Pawel Zarembski |
0:01f31e923fe2 | 276 | |
Pawel Zarembski |
0:01f31e923fe2 | 277 | // Processing when entering a state |
Pawel Zarembski |
0:01f31e923fe2 | 278 | switch (vfs_state_local) { |
Pawel Zarembski |
0:01f31e923fe2 | 279 | case VFS_MNGR_STATE_DISCONNECTED: |
Pawel Zarembski |
0:01f31e923fe2 | 280 | USBD_MSC_MediaReady = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 281 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 282 | |
Pawel Zarembski |
0:01f31e923fe2 | 283 | case VFS_MNGR_STATE_RECONNECTING: |
Pawel Zarembski |
0:01f31e923fe2 | 284 | USBD_MSC_MediaReady = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 285 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 286 | |
Pawel Zarembski |
0:01f31e923fe2 | 287 | case VFS_MNGR_STATE_CONNECTED: |
Pawel Zarembski |
0:01f31e923fe2 | 288 | build_filesystem(); |
Pawel Zarembski |
0:01f31e923fe2 | 289 | USBD_MSC_MediaReady = 1; |
Pawel Zarembski |
0:01f31e923fe2 | 290 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 291 | } |
Pawel Zarembski |
0:01f31e923fe2 | 292 | |
Pawel Zarembski |
0:01f31e923fe2 | 293 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 294 | } |
Pawel Zarembski |
0:01f31e923fe2 | 295 | |
Pawel Zarembski |
0:01f31e923fe2 | 296 | error_t vfs_mngr_get_transfer_status() |
Pawel Zarembski |
0:01f31e923fe2 | 297 | { |
Pawel Zarembski |
0:01f31e923fe2 | 298 | sync_assert_usb_thread(); |
Pawel Zarembski |
0:01f31e923fe2 | 299 | return fail_reason; |
Pawel Zarembski |
0:01f31e923fe2 | 300 | } |
Pawel Zarembski |
0:01f31e923fe2 | 301 | |
Pawel Zarembski |
0:01f31e923fe2 | 302 | void usbd_msc_init(void) |
Pawel Zarembski |
0:01f31e923fe2 | 303 | { |
Pawel Zarembski |
0:01f31e923fe2 | 304 | sync_init(); |
Pawel Zarembski |
0:01f31e923fe2 | 305 | build_filesystem(); |
Pawel Zarembski |
0:01f31e923fe2 | 306 | vfs_state = VFS_MNGR_STATE_DISCONNECTED; |
Pawel Zarembski |
0:01f31e923fe2 | 307 | vfs_state_next = VFS_MNGR_STATE_DISCONNECTED; |
Pawel Zarembski |
0:01f31e923fe2 | 308 | time_usb_idle = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 309 | USBD_MSC_MediaReady = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 310 | } |
Pawel Zarembski |
0:01f31e923fe2 | 311 | |
Pawel Zarembski |
0:01f31e923fe2 | 312 | void usbd_msc_read_sect(uint32_t sector, uint8_t *buf, uint32_t num_of_sectors) |
Pawel Zarembski |
0:01f31e923fe2 | 313 | { |
Pawel Zarembski |
0:01f31e923fe2 | 314 | sync_assert_usb_thread(); |
Pawel Zarembski |
0:01f31e923fe2 | 315 | |
Pawel Zarembski |
0:01f31e923fe2 | 316 | // dont proceed if we're not ready |
Pawel Zarembski |
0:01f31e923fe2 | 317 | if (!USBD_MSC_MediaReady) { |
Pawel Zarembski |
0:01f31e923fe2 | 318 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 319 | } |
Pawel Zarembski |
0:01f31e923fe2 | 320 | |
Pawel Zarembski |
0:01f31e923fe2 | 321 | // indicate msc activity |
Pawel Zarembski |
0:01f31e923fe2 | 322 | main_blink_msc_led(MAIN_LED_FLASH); |
Pawel Zarembski |
0:01f31e923fe2 | 323 | vfs_read(sector, buf, num_of_sectors); |
Pawel Zarembski |
0:01f31e923fe2 | 324 | } |
Pawel Zarembski |
0:01f31e923fe2 | 325 | |
Pawel Zarembski |
0:01f31e923fe2 | 326 | void usbd_msc_write_sect(uint32_t sector, uint8_t *buf, uint32_t num_of_sectors) |
Pawel Zarembski |
0:01f31e923fe2 | 327 | { |
Pawel Zarembski |
0:01f31e923fe2 | 328 | sync_assert_usb_thread(); |
Pawel Zarembski |
0:01f31e923fe2 | 329 | |
Pawel Zarembski |
0:01f31e923fe2 | 330 | if (!USBD_MSC_MediaReady) { |
Pawel Zarembski |
0:01f31e923fe2 | 331 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 332 | } |
Pawel Zarembski |
0:01f31e923fe2 | 333 | |
Pawel Zarembski |
0:01f31e923fe2 | 334 | // Restart the disconnect counter on every packet |
Pawel Zarembski |
0:01f31e923fe2 | 335 | // so the device does not detach in the middle of a |
Pawel Zarembski |
0:01f31e923fe2 | 336 | // transfer. |
Pawel Zarembski |
0:01f31e923fe2 | 337 | time_usb_idle = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 338 | |
Pawel Zarembski |
0:01f31e923fe2 | 339 | if (TRASNFER_FINISHED == file_transfer_state.transfer_state) { |
Pawel Zarembski |
0:01f31e923fe2 | 340 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 341 | } |
Pawel Zarembski |
0:01f31e923fe2 | 342 | |
Pawel Zarembski |
0:01f31e923fe2 | 343 | // indicate msc activity |
Pawel Zarembski |
0:01f31e923fe2 | 344 | main_blink_msc_led(MAIN_LED_FLASH); |
Pawel Zarembski |
0:01f31e923fe2 | 345 | vfs_write(sector, buf, num_of_sectors); |
Pawel Zarembski |
0:01f31e923fe2 | 346 | if (TRASNFER_FINISHED == file_transfer_state.transfer_state) { |
Pawel Zarembski |
0:01f31e923fe2 | 347 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 348 | } |
Pawel Zarembski |
0:01f31e923fe2 | 349 | file_data_handler(sector, buf, num_of_sectors); |
Pawel Zarembski |
0:01f31e923fe2 | 350 | } |
Pawel Zarembski |
0:01f31e923fe2 | 351 | |
Pawel Zarembski |
0:01f31e923fe2 | 352 | static void sync_init(void) |
Pawel Zarembski |
0:01f31e923fe2 | 353 | { |
Pawel Zarembski |
0:01f31e923fe2 | 354 | sync_thread = osThreadGetId(); |
Pawel Zarembski |
0:01f31e923fe2 | 355 | sync_mutex = osMutexNew(NULL); |
Pawel Zarembski |
0:01f31e923fe2 | 356 | } |
Pawel Zarembski |
0:01f31e923fe2 | 357 | |
Pawel Zarembski |
0:01f31e923fe2 | 358 | static void sync_assert_usb_thread(void) |
Pawel Zarembski |
0:01f31e923fe2 | 359 | { |
Pawel Zarembski |
0:01f31e923fe2 | 360 | util_assert(osThreadGetId() == sync_thread); |
Pawel Zarembski |
0:01f31e923fe2 | 361 | } |
Pawel Zarembski |
0:01f31e923fe2 | 362 | |
Pawel Zarembski |
0:01f31e923fe2 | 363 | static void sync_lock(void) |
Pawel Zarembski |
0:01f31e923fe2 | 364 | { |
Pawel Zarembski |
0:01f31e923fe2 | 365 | osMutexAcquire(sync_mutex, 0); |
Pawel Zarembski |
0:01f31e923fe2 | 366 | } |
Pawel Zarembski |
0:01f31e923fe2 | 367 | |
Pawel Zarembski |
0:01f31e923fe2 | 368 | static void sync_unlock(void) |
Pawel Zarembski |
0:01f31e923fe2 | 369 | { |
Pawel Zarembski |
0:01f31e923fe2 | 370 | osMutexRelease(sync_mutex); |
Pawel Zarembski |
0:01f31e923fe2 | 371 | } |
Pawel Zarembski |
0:01f31e923fe2 | 372 | |
Pawel Zarembski |
0:01f31e923fe2 | 373 | static bool changing_state() |
Pawel Zarembski |
0:01f31e923fe2 | 374 | { |
Pawel Zarembski |
0:01f31e923fe2 | 375 | return vfs_state != vfs_state_next; |
Pawel Zarembski |
0:01f31e923fe2 | 376 | } |
Pawel Zarembski |
0:01f31e923fe2 | 377 | |
Pawel Zarembski |
0:01f31e923fe2 | 378 | static void build_filesystem() |
Pawel Zarembski |
0:01f31e923fe2 | 379 | { |
Pawel Zarembski |
0:01f31e923fe2 | 380 | // Update anything that could have changed file system state |
Pawel Zarembski |
0:01f31e923fe2 | 381 | file_transfer_state = default_transfer_state; |
Pawel Zarembski |
0:01f31e923fe2 | 382 | vfs_user_build_filesystem(); |
Pawel Zarembski |
0:01f31e923fe2 | 383 | vfs_set_file_change_callback(file_change_handler); |
Pawel Zarembski |
0:01f31e923fe2 | 384 | // Set mass storage parameters |
Pawel Zarembski |
0:01f31e923fe2 | 385 | USBD_MSC_MemorySize = vfs_get_total_size(); |
Pawel Zarembski |
0:01f31e923fe2 | 386 | USBD_MSC_BlockSize = VFS_SECTOR_SIZE; |
Pawel Zarembski |
0:01f31e923fe2 | 387 | USBD_MSC_BlockGroup = 1; |
Pawel Zarembski |
0:01f31e923fe2 | 388 | USBD_MSC_BlockCount = USBD_MSC_MemorySize / USBD_MSC_BlockSize; |
Pawel Zarembski |
0:01f31e923fe2 | 389 | USBD_MSC_BlockBuf = (uint8_t *)usb_buffer; |
Pawel Zarembski |
0:01f31e923fe2 | 390 | } |
Pawel Zarembski |
0:01f31e923fe2 | 391 | |
Pawel Zarembski |
0:01f31e923fe2 | 392 | // Callback to handle changes to the root directory. Should be used with vfs_set_file_change_callback |
Pawel Zarembski |
0:01f31e923fe2 | 393 | static void file_change_handler(const vfs_filename_t filename, vfs_file_change_t change, vfs_file_t file, vfs_file_t new_file_data) |
Pawel Zarembski |
0:01f31e923fe2 | 394 | { |
Pawel Zarembski |
0:01f31e923fe2 | 395 | vfs_mngr_printf("vfs_manager file_change_handler(name=%*s, file=%p, change=%i)\r\n", 11, filename, file, change); |
Pawel Zarembski |
0:01f31e923fe2 | 396 | vfs_user_file_change_handler(filename, change, file, new_file_data); |
Pawel Zarembski |
0:01f31e923fe2 | 397 | if (TRASNFER_FINISHED == file_transfer_state.transfer_state) { |
Pawel Zarembski |
0:01f31e923fe2 | 398 | // If the transfer is finished stop further processing |
Pawel Zarembski |
0:01f31e923fe2 | 399 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 400 | } |
Pawel Zarembski |
0:01f31e923fe2 | 401 | |
Pawel Zarembski |
0:01f31e923fe2 | 402 | if (VFS_FILE_CHANGED == change) { |
Pawel Zarembski |
0:01f31e923fe2 | 403 | if (file == file_transfer_state.file_to_program) { |
Pawel Zarembski |
0:01f31e923fe2 | 404 | stream_type_t stream; |
Pawel Zarembski |
0:01f31e923fe2 | 405 | uint32_t size = vfs_file_get_size(new_file_data); |
Pawel Zarembski |
0:01f31e923fe2 | 406 | vfs_sector_t sector = vfs_file_get_start_sector(new_file_data); |
Pawel Zarembski |
0:01f31e923fe2 | 407 | stream = stream_type_from_name(filename); |
Pawel Zarembski |
0:01f31e923fe2 | 408 | transfer_update_file_info(file, sector, size, stream); |
Pawel Zarembski |
0:01f31e923fe2 | 409 | } |
Pawel Zarembski |
0:01f31e923fe2 | 410 | } |
Pawel Zarembski |
0:01f31e923fe2 | 411 | |
Pawel Zarembski |
0:01f31e923fe2 | 412 | if (VFS_FILE_CREATED == change) { |
Pawel Zarembski |
0:01f31e923fe2 | 413 | stream_type_t stream; |
Pawel Zarembski |
0:01f31e923fe2 | 414 | |
Pawel Zarembski |
0:01f31e923fe2 | 415 | if (STREAM_TYPE_NONE != stream_type_from_name(filename)) { |
Pawel Zarembski |
0:01f31e923fe2 | 416 | // Check for a know file extension to detect the current file being |
Pawel Zarembski |
0:01f31e923fe2 | 417 | // transferred. Ignore hidden files since MAC uses hidden files with |
Pawel Zarembski |
0:01f31e923fe2 | 418 | // the same extension to keep track of transfer info in some cases. |
Pawel Zarembski |
0:01f31e923fe2 | 419 | if (!(VFS_FILE_ATTR_HIDDEN & vfs_file_get_attr(new_file_data))) { |
Pawel Zarembski |
0:01f31e923fe2 | 420 | stream = stream_type_from_name(filename); |
Pawel Zarembski |
0:01f31e923fe2 | 421 | uint32_t size = vfs_file_get_size(new_file_data); |
Pawel Zarembski |
0:01f31e923fe2 | 422 | vfs_sector_t sector = vfs_file_get_start_sector(new_file_data); |
Pawel Zarembski |
0:01f31e923fe2 | 423 | transfer_update_file_info(file, sector, size, stream); |
Pawel Zarembski |
0:01f31e923fe2 | 424 | } |
Pawel Zarembski |
0:01f31e923fe2 | 425 | } |
Pawel Zarembski |
0:01f31e923fe2 | 426 | } |
Pawel Zarembski |
0:01f31e923fe2 | 427 | |
Pawel Zarembski |
0:01f31e923fe2 | 428 | if (VFS_FILE_DELETED == change) { |
Pawel Zarembski |
0:01f31e923fe2 | 429 | if (file == file_transfer_state.file_to_program) { |
Pawel Zarembski |
0:01f31e923fe2 | 430 | // The file that was being transferred has been deleted |
Pawel Zarembski |
0:01f31e923fe2 | 431 | transfer_reset_file_info(); |
Pawel Zarembski |
0:01f31e923fe2 | 432 | } |
Pawel Zarembski |
0:01f31e923fe2 | 433 | } |
Pawel Zarembski |
0:01f31e923fe2 | 434 | } |
Pawel Zarembski |
0:01f31e923fe2 | 435 | |
Pawel Zarembski |
0:01f31e923fe2 | 436 | // Handler for file data arriving over USB. This function is responsible |
Pawel Zarembski |
0:01f31e923fe2 | 437 | // for detecting the start of a BIN/HEX file and performing programming |
Pawel Zarembski |
0:01f31e923fe2 | 438 | static void file_data_handler(uint32_t sector, const uint8_t *buf, uint32_t num_of_sectors) |
Pawel Zarembski |
0:01f31e923fe2 | 439 | { |
Pawel Zarembski |
0:01f31e923fe2 | 440 | stream_type_t stream; |
Pawel Zarembski |
0:01f31e923fe2 | 441 | uint32_t size; |
Pawel Zarembski |
0:01f31e923fe2 | 442 | |
Pawel Zarembski |
0:01f31e923fe2 | 443 | // this is the key for starting a file write - we dont care what file types are sent |
Pawel Zarembski |
0:01f31e923fe2 | 444 | // just look for something unique (NVIC table, hex, srec, etc) until root dir is updated |
Pawel Zarembski |
0:01f31e923fe2 | 445 | if (!file_transfer_state.stream_started) { |
Pawel Zarembski |
0:01f31e923fe2 | 446 | // look for file types we can program |
Pawel Zarembski |
0:01f31e923fe2 | 447 | stream = stream_start_identify((uint8_t *)buf, VFS_SECTOR_SIZE * num_of_sectors); |
Pawel Zarembski |
0:01f31e923fe2 | 448 | |
Pawel Zarembski |
0:01f31e923fe2 | 449 | if (STREAM_TYPE_NONE != stream) { |
Pawel Zarembski |
0:01f31e923fe2 | 450 | transfer_stream_open(stream, sector); |
Pawel Zarembski |
0:01f31e923fe2 | 451 | } |
Pawel Zarembski |
0:01f31e923fe2 | 452 | } |
Pawel Zarembski |
0:01f31e923fe2 | 453 | |
Pawel Zarembski |
0:01f31e923fe2 | 454 | if (file_transfer_state.stream_started) { |
Pawel Zarembski |
0:01f31e923fe2 | 455 | // Ignore sectors coming before this file |
Pawel Zarembski |
0:01f31e923fe2 | 456 | if (sector < file_transfer_state.start_sector) { |
Pawel Zarembski |
0:01f31e923fe2 | 457 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 458 | } |
Pawel Zarembski |
0:01f31e923fe2 | 459 | |
Pawel Zarembski |
0:01f31e923fe2 | 460 | // sectors must be in order |
Pawel Zarembski |
0:01f31e923fe2 | 461 | if (sector != file_transfer_state.file_next_sector) { |
Pawel Zarembski |
0:01f31e923fe2 | 462 | vfs_mngr_printf("vfs_manager file_data_handler sector=%i\r\n", sector); |
Pawel Zarembski |
0:01f31e923fe2 | 463 | |
Pawel Zarembski |
0:01f31e923fe2 | 464 | if (sector < file_transfer_state.file_next_sector) { |
Pawel Zarembski |
0:01f31e923fe2 | 465 | vfs_mngr_printf(" sector out of order! lowest ooo = %i\r\n", |
Pawel Zarembski |
0:01f31e923fe2 | 466 | file_transfer_state.last_ooo_sector); |
Pawel Zarembski |
0:01f31e923fe2 | 467 | |
Pawel Zarembski |
0:01f31e923fe2 | 468 | if (VFS_INVALID_SECTOR == file_transfer_state.last_ooo_sector) { |
Pawel Zarembski |
0:01f31e923fe2 | 469 | file_transfer_state.last_ooo_sector = sector; |
Pawel Zarembski |
0:01f31e923fe2 | 470 | } |
Pawel Zarembski |
0:01f31e923fe2 | 471 | |
Pawel Zarembski |
0:01f31e923fe2 | 472 | file_transfer_state.last_ooo_sector = |
Pawel Zarembski |
0:01f31e923fe2 | 473 | MIN(file_transfer_state.last_ooo_sector, sector); |
Pawel Zarembski |
0:01f31e923fe2 | 474 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 475 | vfs_mngr_printf(" sector not part of file transfer\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 476 | } |
Pawel Zarembski |
0:01f31e923fe2 | 477 | |
Pawel Zarembski |
0:01f31e923fe2 | 478 | vfs_mngr_printf(" discarding data - size transferred=0x%x, data=%x,%x,%x,%x,...\r\n", |
Pawel Zarembski |
0:01f31e923fe2 | 479 | file_transfer_state.size_transferred, buf[0], buf[1], buf[2], buf[3]); |
Pawel Zarembski |
0:01f31e923fe2 | 480 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 481 | } |
Pawel Zarembski |
0:01f31e923fe2 | 482 | |
Pawel Zarembski |
0:01f31e923fe2 | 483 | // This sector could be part of the file so record it |
Pawel Zarembski |
0:01f31e923fe2 | 484 | size = VFS_SECTOR_SIZE * num_of_sectors; |
Pawel Zarembski |
0:01f31e923fe2 | 485 | file_transfer_state.size_transferred += size; |
Pawel Zarembski |
0:01f31e923fe2 | 486 | file_transfer_state.file_next_sector = sector + num_of_sectors; |
Pawel Zarembski |
0:01f31e923fe2 | 487 | |
Pawel Zarembski |
0:01f31e923fe2 | 488 | // If stream processing is done then discard the data |
Pawel Zarembski |
0:01f31e923fe2 | 489 | if (file_transfer_state.stream_finished) { |
Pawel Zarembski |
0:01f31e923fe2 | 490 | vfs_mngr_printf("vfs_manager file_data_handler\r\n sector=%i, size=%i\r\n", sector, size); |
Pawel Zarembski |
0:01f31e923fe2 | 491 | vfs_mngr_printf(" discarding data - size transferred=0x%x, data=%x,%x,%x,%x,...\r\n", |
Pawel Zarembski |
0:01f31e923fe2 | 492 | file_transfer_state.size_transferred, buf[0], buf[1], buf[2], buf[3]); |
Pawel Zarembski |
0:01f31e923fe2 | 493 | transfer_update_state(ERROR_SUCCESS); |
Pawel Zarembski |
0:01f31e923fe2 | 494 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 495 | } |
Pawel Zarembski |
0:01f31e923fe2 | 496 | |
Pawel Zarembski |
0:01f31e923fe2 | 497 | transfer_stream_data(sector, buf, size); |
Pawel Zarembski |
0:01f31e923fe2 | 498 | } |
Pawel Zarembski |
0:01f31e923fe2 | 499 | } |
Pawel Zarembski |
0:01f31e923fe2 | 500 | |
Pawel Zarembski |
0:01f31e923fe2 | 501 | static bool ready_for_state_change(void) |
Pawel Zarembski |
0:01f31e923fe2 | 502 | { |
Pawel Zarembski |
0:01f31e923fe2 | 503 | uint32_t timeout_ms = INVALID_TIMEOUT_MS; |
Pawel Zarembski |
0:01f31e923fe2 | 504 | util_assert(vfs_state != vfs_state_next); |
Pawel Zarembski |
0:01f31e923fe2 | 505 | |
Pawel Zarembski |
0:01f31e923fe2 | 506 | if (VFS_MNGR_STATE_CONNECTED == vfs_state) { |
Pawel Zarembski |
0:01f31e923fe2 | 507 | switch (file_transfer_state.transfer_state) { |
Pawel Zarembski |
0:01f31e923fe2 | 508 | case TRANSFER_NOT_STARTED: |
Pawel Zarembski |
0:01f31e923fe2 | 509 | case TRASNFER_FINISHED: |
Pawel Zarembski |
0:01f31e923fe2 | 510 | timeout_ms = DISCONNECT_DELAY_MS; |
Pawel Zarembski |
0:01f31e923fe2 | 511 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 512 | |
Pawel Zarembski |
0:01f31e923fe2 | 513 | case TRANSFER_IN_PROGRESS: |
Pawel Zarembski |
0:01f31e923fe2 | 514 | timeout_ms = DISCONNECT_DELAY_TRANSFER_TIMEOUT_MS; |
Pawel Zarembski |
0:01f31e923fe2 | 515 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 516 | |
Pawel Zarembski |
0:01f31e923fe2 | 517 | case TRANSFER_CAN_BE_FINISHED: |
Pawel Zarembski |
0:01f31e923fe2 | 518 | timeout_ms = DISCONNECT_DELAY_TRANSFER_IDLE_MS; |
Pawel Zarembski |
0:01f31e923fe2 | 519 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 520 | |
Pawel Zarembski |
0:01f31e923fe2 | 521 | default: |
Pawel Zarembski |
0:01f31e923fe2 | 522 | util_assert(0); |
Pawel Zarembski |
0:01f31e923fe2 | 523 | timeout_ms = DISCONNECT_DELAY_MS; |
Pawel Zarembski |
0:01f31e923fe2 | 524 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 525 | } |
Pawel Zarembski |
0:01f31e923fe2 | 526 | } else if ((VFS_MNGR_STATE_DISCONNECTED == vfs_state) && |
Pawel Zarembski |
0:01f31e923fe2 | 527 | (VFS_MNGR_STATE_CONNECTED == vfs_state_next)) { |
Pawel Zarembski |
0:01f31e923fe2 | 528 | timeout_ms = CONNECT_DELAY_MS; |
Pawel Zarembski |
0:01f31e923fe2 | 529 | } else if ((VFS_MNGR_STATE_RECONNECTING == vfs_state) && |
Pawel Zarembski |
0:01f31e923fe2 | 530 | (VFS_MNGR_STATE_CONNECTED == vfs_state_next)) { |
Pawel Zarembski |
0:01f31e923fe2 | 531 | timeout_ms = RECONNECT_DELAY_MS; |
Pawel Zarembski |
0:01f31e923fe2 | 532 | } else if ((VFS_MNGR_STATE_RECONNECTING == vfs_state) && |
Pawel Zarembski |
0:01f31e923fe2 | 533 | (VFS_MNGR_STATE_DISCONNECTED == vfs_state_next)) { |
Pawel Zarembski |
0:01f31e923fe2 | 534 | timeout_ms = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 535 | } |
Pawel Zarembski |
0:01f31e923fe2 | 536 | |
Pawel Zarembski |
0:01f31e923fe2 | 537 | if (INVALID_TIMEOUT_MS == timeout_ms) { |
Pawel Zarembski |
0:01f31e923fe2 | 538 | util_assert(0); |
Pawel Zarembski |
0:01f31e923fe2 | 539 | timeout_ms = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 540 | } |
Pawel Zarembski |
0:01f31e923fe2 | 541 | |
Pawel Zarembski |
0:01f31e923fe2 | 542 | return time_usb_idle > timeout_ms ? true : false; |
Pawel Zarembski |
0:01f31e923fe2 | 543 | } |
Pawel Zarembski |
0:01f31e923fe2 | 544 | |
Pawel Zarembski |
0:01f31e923fe2 | 545 | // Abort a remount if one is pending |
Pawel Zarembski |
0:01f31e923fe2 | 546 | void abort_remount(void) |
Pawel Zarembski |
0:01f31e923fe2 | 547 | { |
Pawel Zarembski |
0:01f31e923fe2 | 548 | sync_lock(); |
Pawel Zarembski |
0:01f31e923fe2 | 549 | |
Pawel Zarembski |
0:01f31e923fe2 | 550 | // Only abort a remount if in the connected state and reconnecting is the next state |
Pawel Zarembski |
0:01f31e923fe2 | 551 | if ((VFS_MNGR_STATE_RECONNECTING == vfs_state_next) && (VFS_MNGR_STATE_CONNECTED == vfs_state)) { |
Pawel Zarembski |
0:01f31e923fe2 | 552 | vfs_state_next = VFS_MNGR_STATE_CONNECTED; |
Pawel Zarembski |
0:01f31e923fe2 | 553 | } |
Pawel Zarembski |
0:01f31e923fe2 | 554 | |
Pawel Zarembski |
0:01f31e923fe2 | 555 | sync_unlock(); |
Pawel Zarembski |
0:01f31e923fe2 | 556 | } |
Pawel Zarembski |
0:01f31e923fe2 | 557 | |
Pawel Zarembski |
0:01f31e923fe2 | 558 | // Update the tranfer state with file information |
Pawel Zarembski |
0:01f31e923fe2 | 559 | static void transfer_update_file_info(vfs_file_t file, uint32_t start_sector, uint32_t size, stream_type_t stream) |
Pawel Zarembski |
0:01f31e923fe2 | 560 | { |
Pawel Zarembski |
0:01f31e923fe2 | 561 | vfs_mngr_printf("vfs_manager transfer_update_file_info(file=%p, start_sector=%i, size=%i)\r\n", file, start_sector, size); |
Pawel Zarembski |
0:01f31e923fe2 | 562 | |
Pawel Zarembski |
0:01f31e923fe2 | 563 | if (TRASNFER_FINISHED == file_transfer_state.transfer_state) { |
Pawel Zarembski |
0:01f31e923fe2 | 564 | util_assert(0); |
Pawel Zarembski |
0:01f31e923fe2 | 565 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 566 | } |
Pawel Zarembski |
0:01f31e923fe2 | 567 | |
Pawel Zarembski |
0:01f31e923fe2 | 568 | // Initialize the directory entry if it has not been set |
Pawel Zarembski |
0:01f31e923fe2 | 569 | if (VFS_FILE_INVALID == file_transfer_state.file_to_program) { |
Pawel Zarembski |
0:01f31e923fe2 | 570 | file_transfer_state.file_to_program = file; |
Pawel Zarembski |
0:01f31e923fe2 | 571 | |
Pawel Zarembski |
0:01f31e923fe2 | 572 | if (file != VFS_FILE_INVALID) { |
Pawel Zarembski |
0:01f31e923fe2 | 573 | vfs_mngr_printf(" file_to_program=%p\r\n", file); |
Pawel Zarembski |
0:01f31e923fe2 | 574 | } |
Pawel Zarembski |
0:01f31e923fe2 | 575 | } |
Pawel Zarembski |
0:01f31e923fe2 | 576 | |
Pawel Zarembski |
0:01f31e923fe2 | 577 | // Initialize the starting sector if it has not been set |
Pawel Zarembski |
0:01f31e923fe2 | 578 | if (VFS_INVALID_SECTOR == file_transfer_state.file_start_sector) { |
Pawel Zarembski |
0:01f31e923fe2 | 579 | file_transfer_state.file_start_sector = start_sector; |
Pawel Zarembski |
0:01f31e923fe2 | 580 | |
Pawel Zarembski |
0:01f31e923fe2 | 581 | if (start_sector != VFS_INVALID_SECTOR) { |
Pawel Zarembski |
0:01f31e923fe2 | 582 | vfs_mngr_printf(" start_sector=%i\r\n", start_sector); |
Pawel Zarembski |
0:01f31e923fe2 | 583 | } |
Pawel Zarembski |
0:01f31e923fe2 | 584 | } |
Pawel Zarembski |
0:01f31e923fe2 | 585 | |
Pawel Zarembski |
0:01f31e923fe2 | 586 | // Initialize the stream if it has not been set |
Pawel Zarembski |
0:01f31e923fe2 | 587 | if (STREAM_TYPE_NONE == file_transfer_state.stream) { |
Pawel Zarembski |
0:01f31e923fe2 | 588 | file_transfer_state.stream = stream; |
Pawel Zarembski |
0:01f31e923fe2 | 589 | |
Pawel Zarembski |
0:01f31e923fe2 | 590 | if (stream != STREAM_TYPE_NONE) { |
Pawel Zarembski |
0:01f31e923fe2 | 591 | vfs_mngr_printf(" stream=%i\r\n", stream); |
Pawel Zarembski |
0:01f31e923fe2 | 592 | } |
Pawel Zarembski |
0:01f31e923fe2 | 593 | } |
Pawel Zarembski |
0:01f31e923fe2 | 594 | |
Pawel Zarembski |
0:01f31e923fe2 | 595 | // Check - File size must either grow or be smaller than the size already transferred |
Pawel Zarembski |
0:01f31e923fe2 | 596 | if ((size < file_transfer_state.file_size) && (size < file_transfer_state.size_transferred) && (size > 0)) { |
Pawel Zarembski |
0:01f31e923fe2 | 597 | vfs_mngr_printf(" error: file size changed from %i to %i\r\n", file_transfer_state.file_size, size); |
Pawel Zarembski |
0:01f31e923fe2 | 598 | transfer_update_state(ERROR_ERROR_DURING_TRANSFER); |
Pawel Zarembski |
0:01f31e923fe2 | 599 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 600 | } |
Pawel Zarembski |
0:01f31e923fe2 | 601 | |
Pawel Zarembski |
0:01f31e923fe2 | 602 | // Check - Starting sector must be the same - this is optional for file info since it may not be present initially |
Pawel Zarembski |
0:01f31e923fe2 | 603 | if ((VFS_INVALID_SECTOR != start_sector) && (start_sector != file_transfer_state.file_start_sector)) { |
Pawel Zarembski |
0:01f31e923fe2 | 604 | vfs_mngr_printf(" error: starting sector changed from %i to %i\r\n", file_transfer_state.file_start_sector, start_sector); |
Pawel Zarembski |
0:01f31e923fe2 | 605 | transfer_update_state(ERROR_ERROR_DURING_TRANSFER); |
Pawel Zarembski |
0:01f31e923fe2 | 606 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 607 | } |
Pawel Zarembski |
0:01f31e923fe2 | 608 | |
Pawel Zarembski |
0:01f31e923fe2 | 609 | // Check - stream must be the same |
Pawel Zarembski |
0:01f31e923fe2 | 610 | if ((stream != STREAM_TYPE_NONE) && (stream != file_transfer_state.stream)) { |
Pawel Zarembski |
0:01f31e923fe2 | 611 | vfs_mngr_printf(" error: changed types during transfer from %i to %i\r\n", file_transfer_state.stream, stream); |
Pawel Zarembski |
0:01f31e923fe2 | 612 | transfer_update_state(ERROR_ERROR_DURING_TRANSFER); |
Pawel Zarembski |
0:01f31e923fe2 | 613 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 614 | } |
Pawel Zarembski |
0:01f31e923fe2 | 615 | |
Pawel Zarembski |
0:01f31e923fe2 | 616 | // Update values - Size is the only value that can change |
Pawel Zarembski |
0:01f31e923fe2 | 617 | file_transfer_state.file_size = size; |
Pawel Zarembski |
0:01f31e923fe2 | 618 | vfs_mngr_printf(" updated size=%i\r\n", size); |
Pawel Zarembski |
0:01f31e923fe2 | 619 | |
Pawel Zarembski |
0:01f31e923fe2 | 620 | transfer_update_state(ERROR_SUCCESS); |
Pawel Zarembski |
0:01f31e923fe2 | 621 | } |
Pawel Zarembski |
0:01f31e923fe2 | 622 | |
Pawel Zarembski |
0:01f31e923fe2 | 623 | // Reset the transfer information or error if transfer is already in progress |
Pawel Zarembski |
0:01f31e923fe2 | 624 | static void transfer_reset_file_info() |
Pawel Zarembski |
0:01f31e923fe2 | 625 | { |
Pawel Zarembski |
0:01f31e923fe2 | 626 | vfs_mngr_printf("vfs_manager transfer_reset_file_info()\r\n"); |
Pawel Zarembski |
0:01f31e923fe2 | 627 | //check if the data started streaming; size can be updated on matching start sector and stream type |
Pawel Zarembski |
0:01f31e923fe2 | 628 | if(file_transfer_state.stream_started){ |
Pawel Zarembski |
0:01f31e923fe2 | 629 | //file, start sector and size has to be updated |
Pawel Zarembski |
0:01f31e923fe2 | 630 | file_transfer_state.file_to_program = VFS_FILE_INVALID; |
Pawel Zarembski |
0:01f31e923fe2 | 631 | file_transfer_state.file_start_sector = VFS_INVALID_SECTOR; |
Pawel Zarembski |
0:01f31e923fe2 | 632 | file_transfer_state.file_size = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 633 | }else{ |
Pawel Zarembski |
0:01f31e923fe2 | 634 | file_transfer_state = default_transfer_state; |
Pawel Zarembski |
0:01f31e923fe2 | 635 | abort_remount(); |
Pawel Zarembski |
0:01f31e923fe2 | 636 | } |
Pawel Zarembski |
0:01f31e923fe2 | 637 | |
Pawel Zarembski |
0:01f31e923fe2 | 638 | } |
Pawel Zarembski |
0:01f31e923fe2 | 639 | |
Pawel Zarembski |
0:01f31e923fe2 | 640 | // Update the tranfer state with new information |
Pawel Zarembski |
0:01f31e923fe2 | 641 | static void transfer_stream_open(stream_type_t stream, uint32_t start_sector) |
Pawel Zarembski |
0:01f31e923fe2 | 642 | { |
Pawel Zarembski |
0:01f31e923fe2 | 643 | error_t status; |
Pawel Zarembski |
0:01f31e923fe2 | 644 | util_assert(!file_transfer_state.stream_open); |
Pawel Zarembski |
0:01f31e923fe2 | 645 | util_assert(start_sector != VFS_INVALID_SECTOR); |
Pawel Zarembski |
0:01f31e923fe2 | 646 | vfs_mngr_printf("vfs_manager transfer_update_stream_open(stream=%i, start_sector=%i)\r\n", |
Pawel Zarembski |
0:01f31e923fe2 | 647 | stream, start_sector); |
Pawel Zarembski |
0:01f31e923fe2 | 648 | |
Pawel Zarembski |
0:01f31e923fe2 | 649 | // Initialize the starting sector if it has not been set |
Pawel Zarembski |
0:01f31e923fe2 | 650 | if (VFS_INVALID_SECTOR == file_transfer_state.start_sector) { |
Pawel Zarembski |
0:01f31e923fe2 | 651 | file_transfer_state.start_sector = start_sector; |
Pawel Zarembski |
0:01f31e923fe2 | 652 | |
Pawel Zarembski |
0:01f31e923fe2 | 653 | if (start_sector != VFS_INVALID_SECTOR) { |
Pawel Zarembski |
0:01f31e923fe2 | 654 | vfs_mngr_printf(" start_sector=%i\r\n", start_sector); |
Pawel Zarembski |
0:01f31e923fe2 | 655 | } |
Pawel Zarembski |
0:01f31e923fe2 | 656 | } |
Pawel Zarembski |
0:01f31e923fe2 | 657 | |
Pawel Zarembski |
0:01f31e923fe2 | 658 | // Initialize the stream if it has not been set |
Pawel Zarembski |
0:01f31e923fe2 | 659 | if (STREAM_TYPE_NONE == file_transfer_state.stream) { |
Pawel Zarembski |
0:01f31e923fe2 | 660 | file_transfer_state.stream = stream; |
Pawel Zarembski |
0:01f31e923fe2 | 661 | |
Pawel Zarembski |
0:01f31e923fe2 | 662 | if (stream != STREAM_TYPE_NONE) { |
Pawel Zarembski |
0:01f31e923fe2 | 663 | vfs_mngr_printf(" stream=%i\r\n", stream); |
Pawel Zarembski |
0:01f31e923fe2 | 664 | } |
Pawel Zarembski |
0:01f31e923fe2 | 665 | } |
Pawel Zarembski |
0:01f31e923fe2 | 666 | |
Pawel Zarembski |
0:01f31e923fe2 | 667 | // Check - Starting sector must be the same |
Pawel Zarembski |
0:01f31e923fe2 | 668 | if (start_sector != file_transfer_state.start_sector) { |
Pawel Zarembski |
0:01f31e923fe2 | 669 | vfs_mngr_printf(" error: starting sector changed from %i to %i\r\n", file_transfer_state.start_sector, start_sector); |
Pawel Zarembski |
0:01f31e923fe2 | 670 | transfer_update_state(ERROR_ERROR_DURING_TRANSFER); |
Pawel Zarembski |
0:01f31e923fe2 | 671 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 672 | } |
Pawel Zarembski |
0:01f31e923fe2 | 673 | |
Pawel Zarembski |
0:01f31e923fe2 | 674 | // Check - stream must be the same |
Pawel Zarembski |
0:01f31e923fe2 | 675 | if (stream != file_transfer_state.stream) { |
Pawel Zarembski |
0:01f31e923fe2 | 676 | vfs_mngr_printf(" error: changed types during transfer from %i to %i\r\n", file_transfer_state.stream, stream); |
Pawel Zarembski |
0:01f31e923fe2 | 677 | transfer_update_state(ERROR_ERROR_DURING_TRANSFER); |
Pawel Zarembski |
0:01f31e923fe2 | 678 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 679 | } |
Pawel Zarembski |
0:01f31e923fe2 | 680 | |
Pawel Zarembski |
0:01f31e923fe2 | 681 | // Open stream |
Pawel Zarembski |
0:01f31e923fe2 | 682 | status = stream_open(stream); |
Pawel Zarembski |
0:01f31e923fe2 | 683 | vfs_mngr_printf(" stream_open stream=%i ret %i\r\n", stream, status); |
Pawel Zarembski |
0:01f31e923fe2 | 684 | |
Pawel Zarembski |
0:01f31e923fe2 | 685 | if (ERROR_SUCCESS == status) { |
Pawel Zarembski |
0:01f31e923fe2 | 686 | file_transfer_state.file_next_sector = start_sector; |
Pawel Zarembski |
0:01f31e923fe2 | 687 | file_transfer_state.stream_open = true; |
Pawel Zarembski |
0:01f31e923fe2 | 688 | file_transfer_state.stream_started = true; |
Pawel Zarembski |
0:01f31e923fe2 | 689 | } |
Pawel Zarembski |
0:01f31e923fe2 | 690 | |
Pawel Zarembski |
0:01f31e923fe2 | 691 | transfer_update_state(status); |
Pawel Zarembski |
0:01f31e923fe2 | 692 | } |
Pawel Zarembski |
0:01f31e923fe2 | 693 | |
Pawel Zarembski |
0:01f31e923fe2 | 694 | // Update the tranfer state with new information |
Pawel Zarembski |
0:01f31e923fe2 | 695 | static void transfer_stream_data(uint32_t sector, const uint8_t *data, uint32_t size) |
Pawel Zarembski |
0:01f31e923fe2 | 696 | { |
Pawel Zarembski |
0:01f31e923fe2 | 697 | error_t status; |
Pawel Zarembski |
0:01f31e923fe2 | 698 | vfs_mngr_printf("vfs_manager transfer_stream_data(sector=%i, size=%i)\r\n", sector, size); |
Pawel Zarembski |
0:01f31e923fe2 | 699 | vfs_mngr_printf(" size processed=0x%x, data=%x,%x,%x,%x,...\r\n", |
Pawel Zarembski |
0:01f31e923fe2 | 700 | file_transfer_state.size_processed, data[0], data[1], data[2], data[3]); |
Pawel Zarembski |
0:01f31e923fe2 | 701 | |
Pawel Zarembski |
0:01f31e923fe2 | 702 | if (file_transfer_state.stream_finished) { |
Pawel Zarembski |
0:01f31e923fe2 | 703 | util_assert(0); |
Pawel Zarembski |
0:01f31e923fe2 | 704 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 705 | } |
Pawel Zarembski |
0:01f31e923fe2 | 706 | |
Pawel Zarembski |
0:01f31e923fe2 | 707 | util_assert(size % VFS_SECTOR_SIZE == 0); |
Pawel Zarembski |
0:01f31e923fe2 | 708 | util_assert(file_transfer_state.stream_open); |
Pawel Zarembski |
0:01f31e923fe2 | 709 | status = stream_write((uint8_t *)data, size); |
Pawel Zarembski |
0:01f31e923fe2 | 710 | vfs_mngr_printf(" stream_write ret=%i\r\n", status); |
Pawel Zarembski |
0:01f31e923fe2 | 711 | |
Pawel Zarembski |
0:01f31e923fe2 | 712 | if (ERROR_SUCCESS_DONE == status) { |
Pawel Zarembski |
0:01f31e923fe2 | 713 | // Override status so ERROR_SUCCESS_DONE |
Pawel Zarembski |
0:01f31e923fe2 | 714 | // does not get passed into transfer_update_state |
Pawel Zarembski |
0:01f31e923fe2 | 715 | status = stream_close(); |
Pawel Zarembski |
0:01f31e923fe2 | 716 | vfs_mngr_printf(" stream_close ret=%i\r\n", status); |
Pawel Zarembski |
0:01f31e923fe2 | 717 | file_transfer_state.stream_open = false; |
Pawel Zarembski |
0:01f31e923fe2 | 718 | file_transfer_state.stream_finished = true; |
Pawel Zarembski |
0:01f31e923fe2 | 719 | file_transfer_state.stream_optional_finish = true; |
Pawel Zarembski |
0:01f31e923fe2 | 720 | } else if (ERROR_SUCCESS_DONE_OR_CONTINUE == status) { |
Pawel Zarembski |
0:01f31e923fe2 | 721 | status = ERROR_SUCCESS; |
Pawel Zarembski |
0:01f31e923fe2 | 722 | file_transfer_state.stream_optional_finish = true; |
Pawel Zarembski |
0:01f31e923fe2 | 723 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 724 | file_transfer_state.stream_optional_finish = false; |
Pawel Zarembski |
0:01f31e923fe2 | 725 | } |
Pawel Zarembski |
0:01f31e923fe2 | 726 | |
Pawel Zarembski |
0:01f31e923fe2 | 727 | file_transfer_state.size_processed += size; |
Pawel Zarembski |
0:01f31e923fe2 | 728 | transfer_update_state(status); |
Pawel Zarembski |
0:01f31e923fe2 | 729 | } |
Pawel Zarembski |
0:01f31e923fe2 | 730 | |
Pawel Zarembski |
0:01f31e923fe2 | 731 | // Check if the current transfer is still in progress, done, or if an error has occurred |
Pawel Zarembski |
0:01f31e923fe2 | 732 | static void transfer_update_state(error_t status) |
Pawel Zarembski |
0:01f31e923fe2 | 733 | { |
Pawel Zarembski |
0:01f31e923fe2 | 734 | bool transfer_timeout; |
Pawel Zarembski |
0:01f31e923fe2 | 735 | bool transfer_started; |
Pawel Zarembski |
0:01f31e923fe2 | 736 | bool transfer_can_be_finished; |
Pawel Zarembski |
0:01f31e923fe2 | 737 | bool transfer_must_be_finished; |
Pawel Zarembski |
0:01f31e923fe2 | 738 | bool out_of_order_sector; |
Pawel Zarembski |
0:01f31e923fe2 | 739 | error_t local_status = status; |
Pawel Zarembski |
0:01f31e923fe2 | 740 | util_assert((status != ERROR_SUCCESS_DONE) && |
Pawel Zarembski |
0:01f31e923fe2 | 741 | (status != ERROR_SUCCESS_DONE_OR_CONTINUE)); |
Pawel Zarembski |
0:01f31e923fe2 | 742 | |
Pawel Zarembski |
0:01f31e923fe2 | 743 | if (TRASNFER_FINISHED == file_transfer_state.transfer_state) { |
Pawel Zarembski |
0:01f31e923fe2 | 744 | util_assert(0); |
Pawel Zarembski |
0:01f31e923fe2 | 745 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 746 | } |
Pawel Zarembski |
0:01f31e923fe2 | 747 | |
Pawel Zarembski |
0:01f31e923fe2 | 748 | // Update file info status. The end of a file is never known for sure since |
Pawel Zarembski |
0:01f31e923fe2 | 749 | // what looks like a complete file could be part of a file getting flushed to disk. |
Pawel Zarembski |
0:01f31e923fe2 | 750 | // The criteria for an successful optional finish is |
Pawel Zarembski |
0:01f31e923fe2 | 751 | // 1. A file has been detected |
Pawel Zarembski |
0:01f31e923fe2 | 752 | // 2. The size of the file indicated in the root dir has been transferred |
Pawel Zarembski |
0:01f31e923fe2 | 753 | // 3. The file size is greater than zero |
Pawel Zarembski |
0:01f31e923fe2 | 754 | // 4. Matching start sector set by stream and vfs changes |
Pawel Zarembski |
0:01f31e923fe2 | 755 | file_transfer_state.file_info_optional_finish = |
Pawel Zarembski |
0:01f31e923fe2 | 756 | (file_transfer_state.file_to_program != VFS_FILE_INVALID) && |
Pawel Zarembski |
0:01f31e923fe2 | 757 | (file_transfer_state.size_transferred >= file_transfer_state.file_size) && |
Pawel Zarembski |
0:01f31e923fe2 | 758 | (file_transfer_state.file_size > 0) && |
Pawel Zarembski |
0:01f31e923fe2 | 759 | (file_transfer_state.start_sector == file_transfer_state.file_start_sector); |
Pawel Zarembski |
0:01f31e923fe2 | 760 | transfer_timeout = file_transfer_state.transfer_timeout; |
Pawel Zarembski |
0:01f31e923fe2 | 761 | transfer_started = (VFS_FILE_INVALID != file_transfer_state.file_to_program) || |
Pawel Zarembski |
0:01f31e923fe2 | 762 | (STREAM_TYPE_NONE != file_transfer_state.stream); |
Pawel Zarembski |
0:01f31e923fe2 | 763 | // The transfer can be finished if both file and stream processing |
Pawel Zarembski |
0:01f31e923fe2 | 764 | // can be considered complete |
Pawel Zarembski |
0:01f31e923fe2 | 765 | transfer_can_be_finished = file_transfer_state.file_info_optional_finish && |
Pawel Zarembski |
0:01f31e923fe2 | 766 | file_transfer_state.stream_optional_finish; |
Pawel Zarembski |
0:01f31e923fe2 | 767 | // The transfer must be fnished if stream processing is for sure complete |
Pawel Zarembski |
0:01f31e923fe2 | 768 | // and file processing can be considered complete |
Pawel Zarembski |
0:01f31e923fe2 | 769 | transfer_must_be_finished = file_transfer_state.stream_finished && |
Pawel Zarembski |
0:01f31e923fe2 | 770 | file_transfer_state.file_info_optional_finish; |
Pawel Zarembski |
0:01f31e923fe2 | 771 | out_of_order_sector = false; |
Pawel Zarembski |
0:01f31e923fe2 | 772 | |
Pawel Zarembski |
0:01f31e923fe2 | 773 | if (file_transfer_state.last_ooo_sector != VFS_INVALID_SECTOR) { |
Pawel Zarembski |
0:01f31e923fe2 | 774 | util_assert(file_transfer_state.start_sector != VFS_INVALID_SECTOR); |
Pawel Zarembski |
0:01f31e923fe2 | 775 | uint32_t sector_offset = (file_transfer_state.last_ooo_sector - |
Pawel Zarembski |
0:01f31e923fe2 | 776 | file_transfer_state.start_sector) * VFS_SECTOR_SIZE; |
Pawel Zarembski |
0:01f31e923fe2 | 777 | |
Pawel Zarembski |
0:01f31e923fe2 | 778 | if (sector_offset < file_transfer_state.size_processed) { |
Pawel Zarembski |
0:01f31e923fe2 | 779 | // The out of order sector was within the range of data already |
Pawel Zarembski |
0:01f31e923fe2 | 780 | // processed. |
Pawel Zarembski |
0:01f31e923fe2 | 781 | out_of_order_sector = true; |
Pawel Zarembski |
0:01f31e923fe2 | 782 | } |
Pawel Zarembski |
0:01f31e923fe2 | 783 | } |
Pawel Zarembski |
0:01f31e923fe2 | 784 | |
Pawel Zarembski |
0:01f31e923fe2 | 785 | // Set the transfer state and set the status if necessary |
Pawel Zarembski |
0:01f31e923fe2 | 786 | if (local_status != ERROR_SUCCESS) { |
Pawel Zarembski |
0:01f31e923fe2 | 787 | file_transfer_state.transfer_state = TRASNFER_FINISHED; |
Pawel Zarembski |
0:01f31e923fe2 | 788 | } else if (transfer_timeout) { |
Pawel Zarembski |
0:01f31e923fe2 | 789 | if (out_of_order_sector) { |
Pawel Zarembski |
0:01f31e923fe2 | 790 | local_status = ERROR_OOO_SECTOR; |
Pawel Zarembski |
0:01f31e923fe2 | 791 | } else if (!transfer_started) { |
Pawel Zarembski |
0:01f31e923fe2 | 792 | local_status = ERROR_SUCCESS; |
Pawel Zarembski |
0:01f31e923fe2 | 793 | } else if (transfer_can_be_finished) { |
Pawel Zarembski |
0:01f31e923fe2 | 794 | local_status = ERROR_SUCCESS; |
Pawel Zarembski |
0:01f31e923fe2 | 795 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 796 | local_status = ERROR_TRANSFER_TIMEOUT; |
Pawel Zarembski |
0:01f31e923fe2 | 797 | } |
Pawel Zarembski |
0:01f31e923fe2 | 798 | |
Pawel Zarembski |
0:01f31e923fe2 | 799 | file_transfer_state.transfer_state = TRASNFER_FINISHED; |
Pawel Zarembski |
0:01f31e923fe2 | 800 | } else if (transfer_must_be_finished) { |
Pawel Zarembski |
0:01f31e923fe2 | 801 | file_transfer_state.transfer_state = TRASNFER_FINISHED; |
Pawel Zarembski |
0:01f31e923fe2 | 802 | } else if (transfer_can_be_finished) { |
Pawel Zarembski |
0:01f31e923fe2 | 803 | file_transfer_state.transfer_state = TRANSFER_CAN_BE_FINISHED; |
Pawel Zarembski |
0:01f31e923fe2 | 804 | } else if (transfer_started) { |
Pawel Zarembski |
0:01f31e923fe2 | 805 | file_transfer_state.transfer_state = TRANSFER_IN_PROGRESS; |
Pawel Zarembski |
0:01f31e923fe2 | 806 | } |
Pawel Zarembski |
0:01f31e923fe2 | 807 | |
Pawel Zarembski |
0:01f31e923fe2 | 808 | if (TRASNFER_FINISHED == file_transfer_state.transfer_state) { |
Pawel Zarembski |
0:01f31e923fe2 | 809 | vfs_mngr_printf("vfs_manager transfer_update_state(status=%i)\r\n", status); |
Pawel Zarembski |
0:01f31e923fe2 | 810 | vfs_mngr_printf(" file=%p, start_sect= %i %i, size=%i\r\n", |
Pawel Zarembski |
0:01f31e923fe2 | 811 | file_transfer_state.file_to_program, file_transfer_state.start_sector, |
Pawel Zarembski |
0:01f31e923fe2 | 812 | file_transfer_state.file_start_sector, file_transfer_state.file_size); |
Pawel Zarembski |
0:01f31e923fe2 | 813 | vfs_mngr_printf(" stream=%i, size_processed=%i, opt_finish=%i, timeout=%i\r\n", |
Pawel Zarembski |
0:01f31e923fe2 | 814 | file_transfer_state.stream, file_transfer_state.size_processed, |
Pawel Zarembski |
0:01f31e923fe2 | 815 | file_transfer_state.file_info_optional_finish, transfer_timeout); |
Pawel Zarembski |
0:01f31e923fe2 | 816 | |
Pawel Zarembski |
0:01f31e923fe2 | 817 | // Close the file stream if it is open |
Pawel Zarembski |
0:01f31e923fe2 | 818 | if (file_transfer_state.stream_open) { |
Pawel Zarembski |
0:01f31e923fe2 | 819 | error_t close_status; |
Pawel Zarembski |
0:01f31e923fe2 | 820 | close_status = stream_close(); |
Pawel Zarembski |
0:01f31e923fe2 | 821 | vfs_mngr_printf(" stream closed ret=%i\r\n", close_status); |
Pawel Zarembski |
0:01f31e923fe2 | 822 | file_transfer_state.stream_open = false; |
Pawel Zarembski |
0:01f31e923fe2 | 823 | |
Pawel Zarembski |
0:01f31e923fe2 | 824 | if (ERROR_SUCCESS == local_status) { |
Pawel Zarembski |
0:01f31e923fe2 | 825 | local_status = close_status; |
Pawel Zarembski |
0:01f31e923fe2 | 826 | } |
Pawel Zarembski |
0:01f31e923fe2 | 827 | } |
Pawel Zarembski |
0:01f31e923fe2 | 828 | |
Pawel Zarembski |
0:01f31e923fe2 | 829 | // Set the fail reason |
Pawel Zarembski |
0:01f31e923fe2 | 830 | fail_reason = local_status; |
Pawel Zarembski |
0:01f31e923fe2 | 831 | vfs_mngr_printf(" Transfer finished, status: %i=%s\r\n", fail_reason, error_get_string(fail_reason)); |
Pawel Zarembski |
0:01f31e923fe2 | 832 | } |
Pawel Zarembski |
0:01f31e923fe2 | 833 | |
Pawel Zarembski |
0:01f31e923fe2 | 834 | // If this state change is not from aborting a transfer |
Pawel Zarembski |
0:01f31e923fe2 | 835 | // due to a remount then trigger a remount |
Pawel Zarembski |
0:01f31e923fe2 | 836 | if (!transfer_timeout) { |
Pawel Zarembski |
0:01f31e923fe2 | 837 | vfs_mngr_fs_remount(); |
Pawel Zarembski |
0:01f31e923fe2 | 838 | } |
Pawel Zarembski |
0:01f31e923fe2 | 839 | } |