Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.

Upstream: https://github.com/ARMmbed/DAPLink

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?

UserRevisionLine numberNew 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 }