Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
vfs_manager.c
00001 /** 00002 * @file vfs_manager.c 00003 * @brief Implementation of vfs_manager.h 00004 * 00005 * DAPLink Interface Firmware 00006 * Copyright (c) 2009-2019, ARM Limited, All Rights Reserved 00007 * SPDX-License-Identifier: Apache-2.0 00008 * 00009 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00010 * not use this file except in compliance with the License. 00011 * You may obtain a copy of the License at 00012 * 00013 * http://www.apache.org/licenses/LICENSE-2.0 00014 * 00015 * Unless required by applicable law or agreed to in writing, software 00016 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00017 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00018 * See the License for the specific language governing permissions and 00019 * limitations under the License. 00020 */ 00021 00022 #include <ctype.h> 00023 00024 #include "main.h" 00025 #include "cmsis_os2.h" 00026 #include "rl_usb.h" 00027 #include "virtual_fs.h" 00028 #include "vfs_manager.h" 00029 #include "daplink_debug.h" 00030 #include "info.h" 00031 #include "settings.h" 00032 #include "daplink.h" 00033 #include "util.h" 00034 #include "version_git.h" 00035 #include "IO_Config.h" 00036 #include "file_stream.h" 00037 #include "error.h" 00038 00039 // Set to 1 to enable debugging 00040 #define DEBUG_VFS_MANAGER 0 00041 00042 #if DEBUG_VFS_MANAGER 00043 #define vfs_mngr_printf debug_msg 00044 #else 00045 #define vfs_mngr_printf(...) 00046 #endif 00047 00048 #define INVALID_TIMEOUT_MS 0xFFFFFFFF 00049 #define MAX_EVENT_TIME_MS 60000 00050 00051 #define CONNECT_DELAY_MS 0 00052 #define RECONNECT_DELAY_MS 2500 // Must be above 1s for windows (more for linux) 00053 // TRANSFER_IN_PROGRESS 00054 #define DISCONNECT_DELAY_TRANSFER_TIMEOUT_MS 20000 00055 // TRANSFER_CAN_BE_FINISHED 00056 #define DISCONNECT_DELAY_TRANSFER_IDLE_MS 500 00057 // TRANSFER_NOT_STARTED || TRASNFER_FINISHED 00058 #define DISCONNECT_DELAY_MS 500 00059 00060 // Make sure none of the delays exceed the max time 00061 COMPILER_ASSERT(CONNECT_DELAY_MS < MAX_EVENT_TIME_MS); 00062 COMPILER_ASSERT(RECONNECT_DELAY_MS < MAX_EVENT_TIME_MS); 00063 COMPILER_ASSERT(DISCONNECT_DELAY_TRANSFER_TIMEOUT_MS < MAX_EVENT_TIME_MS); 00064 COMPILER_ASSERT(DISCONNECT_DELAY_TRANSFER_IDLE_MS < MAX_EVENT_TIME_MS); 00065 COMPILER_ASSERT(DISCONNECT_DELAY_MS < MAX_EVENT_TIME_MS); 00066 00067 typedef enum { 00068 TRANSFER_NOT_STARTED, 00069 TRANSFER_IN_PROGRESS, 00070 TRANSFER_CAN_BE_FINISHED, 00071 TRASNFER_FINISHED, 00072 } transfer_state_t; 00073 00074 typedef struct { 00075 vfs_file_t file_to_program; // A pointer to the directory entry of the file being programmed 00076 vfs_sector_t start_sector; // Start sector of the file being programmed by stream 00077 vfs_sector_t file_start_sector; // Start sector of the file being programmed by vfs 00078 vfs_sector_t file_next_sector; // Expected next sector of the file 00079 vfs_sector_t last_ooo_sector; // Last out of order sector within the file 00080 uint32_t size_processed; // The number of bytes processed by the stream 00081 uint32_t file_size; // Size of the file indicated by root dir. Only allowed to increase 00082 uint32_t size_transferred; // The number of bytes transferred 00083 transfer_state_t transfer_state;// Transfer state 00084 bool stream_open; // State of the stream 00085 bool stream_started; // Stream processing started. This only gets reset remount 00086 bool stream_finished; // Stream processing is done. This only gets reset remount 00087 bool stream_optional_finish; // True if the stream processing can be considered done 00088 bool file_info_optional_finish; // True if the file transfer can be considered done 00089 bool transfer_timeout; // Set if the transfer was finished because of a timeout. This only gets reset remount 00090 stream_type_t stream; // Current stream or STREAM_TYPE_NONE is stream is closed. This only gets reset remount 00091 } file_transfer_state_t; 00092 00093 typedef enum { 00094 VFS_MNGR_STATE_DISCONNECTED, 00095 VFS_MNGR_STATE_RECONNECTING, 00096 VFS_MNGR_STATE_CONNECTED 00097 } vfs_mngr_state_t; 00098 00099 static const file_transfer_state_t default_transfer_state = { 00100 VFS_FILE_INVALID, 00101 VFS_INVALID_SECTOR, 00102 VFS_INVALID_SECTOR, 00103 VFS_INVALID_SECTOR, 00104 VFS_INVALID_SECTOR, 00105 0, 00106 0, 00107 0, 00108 TRANSFER_NOT_STARTED, 00109 false, 00110 false, 00111 false, 00112 false, 00113 false, 00114 false, 00115 STREAM_TYPE_NONE, 00116 }; 00117 00118 //Compile option not to include MSC at all, these will be dummy variables 00119 #ifndef MSC_ENDPOINT 00120 BOOL USBD_MSC_MediaReady = __FALSE; 00121 BOOL USBD_MSC_ReadOnly = __FALSE; 00122 U32 USBD_MSC_MemorySize; 00123 U32 USBD_MSC_BlockSize; 00124 U32 USBD_MSC_BlockGroup; 00125 U32 USBD_MSC_BlockCount; 00126 U8 *USBD_MSC_BlockBuf; 00127 #endif 00128 00129 static uint32_t usb_buffer[VFS_SECTOR_SIZE / sizeof(uint32_t)]; 00130 static error_t fail_reason = ERROR_SUCCESS; 00131 static file_transfer_state_t file_transfer_state; 00132 00133 // These variables can be access from multiple threads 00134 // so access to them must be synchronized 00135 static vfs_mngr_state_t vfs_state; 00136 static vfs_mngr_state_t vfs_state_next; 00137 static uint32_t time_usb_idle; 00138 00139 static osMutexId_t sync_mutex; 00140 static osThreadId_t sync_thread = 0; 00141 00142 // Synchronization functions 00143 static void sync_init(void); 00144 static void sync_assert_usb_thread(void); 00145 static void sync_lock(void); 00146 static void sync_unlock(void); 00147 00148 static bool changing_state(void); 00149 static void build_filesystem(void); 00150 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); 00151 static void file_data_handler(uint32_t sector, const uint8_t *buf, uint32_t num_of_sectors); 00152 static bool ready_for_state_change(void); 00153 static void abort_remount(void); 00154 00155 static void transfer_update_file_info(vfs_file_t file, uint32_t start_sector, uint32_t size, stream_type_t stream); 00156 static void transfer_reset_file_info(void); 00157 static void transfer_stream_open(stream_type_t stream, uint32_t start_sector); 00158 static void transfer_stream_data(uint32_t sector, const uint8_t *data, uint32_t size); 00159 static void transfer_update_state(error_t status); 00160 00161 00162 void vfs_mngr_fs_enable(bool enable) 00163 { 00164 sync_lock(); 00165 00166 if (enable) { 00167 if (VFS_MNGR_STATE_DISCONNECTED == vfs_state_next) { 00168 vfs_state_next = VFS_MNGR_STATE_CONNECTED; 00169 } 00170 } else { 00171 vfs_state_next = VFS_MNGR_STATE_DISCONNECTED; 00172 } 00173 00174 sync_unlock(); 00175 } 00176 00177 void vfs_mngr_fs_remount(void) 00178 { 00179 sync_lock(); 00180 00181 // Only start a remount if in the connected state and not in a transition 00182 if (!changing_state() && (VFS_MNGR_STATE_CONNECTED == vfs_state)) { 00183 vfs_state_next = VFS_MNGR_STATE_RECONNECTING; 00184 } 00185 00186 sync_unlock(); 00187 } 00188 00189 void vfs_mngr_init(bool enable) 00190 { 00191 sync_assert_usb_thread(); 00192 build_filesystem(); 00193 00194 if (enable) { 00195 vfs_state = VFS_MNGR_STATE_CONNECTED; 00196 vfs_state_next = VFS_MNGR_STATE_CONNECTED; 00197 USBD_MSC_MediaReady = 1; 00198 } else { 00199 vfs_state = VFS_MNGR_STATE_DISCONNECTED; 00200 vfs_state_next = VFS_MNGR_STATE_DISCONNECTED; 00201 USBD_MSC_MediaReady = 0; 00202 } 00203 } 00204 00205 void vfs_mngr_periodic(uint32_t elapsed_ms) 00206 { 00207 bool change_state; 00208 vfs_mngr_state_t vfs_state_local; 00209 vfs_mngr_state_t vfs_state_local_prev; 00210 sync_assert_usb_thread(); 00211 sync_lock(); 00212 00213 // Return immediately if the desired state has been reached 00214 if (!changing_state()) { 00215 sync_unlock(); 00216 return; 00217 } 00218 00219 change_state = ready_for_state_change(); 00220 00221 if (time_usb_idle < MAX_EVENT_TIME_MS) { 00222 time_usb_idle += elapsed_ms; 00223 } 00224 00225 if (!change_state) { 00226 sync_unlock(); 00227 return; 00228 } 00229 00230 vfs_mngr_printf("vfs_mngr_periodic()\r\n"); 00231 vfs_mngr_printf(" time_usb_idle=%i\r\n", time_usb_idle); 00232 vfs_mngr_printf(" transfer_state=%i\r\n", file_transfer_state.transfer_state); 00233 // Transistion to new state 00234 vfs_state_local_prev = vfs_state; 00235 vfs_state = vfs_state_next; 00236 00237 switch (vfs_state) { 00238 case VFS_MNGR_STATE_RECONNECTING: 00239 // Transition back to the connected state 00240 vfs_state_next = VFS_MNGR_STATE_CONNECTED; 00241 break; 00242 00243 default: 00244 // No state change logic required in other states 00245 break; 00246 } 00247 00248 vfs_state_local = vfs_state; 00249 time_usb_idle = 0; 00250 sync_unlock(); 00251 // Processing when leaving a state 00252 vfs_mngr_printf(" state %i->%i\r\n", vfs_state_local_prev, vfs_state_local); 00253 00254 switch (vfs_state_local_prev) { 00255 case VFS_MNGR_STATE_DISCONNECTED: 00256 // No action needed 00257 break; 00258 00259 case VFS_MNGR_STATE_RECONNECTING: 00260 // No action needed 00261 break; 00262 00263 case VFS_MNGR_STATE_CONNECTED: 00264 00265 // Close ongoing transfer if there is one 00266 if (file_transfer_state.transfer_state != TRASNFER_FINISHED) { 00267 vfs_mngr_printf(" transfer timeout\r\n"); 00268 file_transfer_state.transfer_timeout = true; 00269 transfer_update_state(ERROR_SUCCESS); 00270 } 00271 00272 util_assert(TRASNFER_FINISHED == file_transfer_state.transfer_state); 00273 vfs_user_disconnecting(); 00274 break; 00275 } 00276 00277 // Processing when entering a state 00278 switch (vfs_state_local) { 00279 case VFS_MNGR_STATE_DISCONNECTED: 00280 USBD_MSC_MediaReady = 0; 00281 break; 00282 00283 case VFS_MNGR_STATE_RECONNECTING: 00284 USBD_MSC_MediaReady = 0; 00285 break; 00286 00287 case VFS_MNGR_STATE_CONNECTED: 00288 build_filesystem(); 00289 USBD_MSC_MediaReady = 1; 00290 break; 00291 } 00292 00293 return; 00294 } 00295 00296 error_t vfs_mngr_get_transfer_status() 00297 { 00298 sync_assert_usb_thread(); 00299 return fail_reason; 00300 } 00301 00302 void usbd_msc_init(void) 00303 { 00304 sync_init(); 00305 build_filesystem(); 00306 vfs_state = VFS_MNGR_STATE_DISCONNECTED; 00307 vfs_state_next = VFS_MNGR_STATE_DISCONNECTED; 00308 time_usb_idle = 0; 00309 USBD_MSC_MediaReady = 0; 00310 } 00311 00312 void usbd_msc_read_sect(uint32_t sector, uint8_t *buf, uint32_t num_of_sectors) 00313 { 00314 sync_assert_usb_thread(); 00315 00316 // dont proceed if we're not ready 00317 if (!USBD_MSC_MediaReady) { 00318 return; 00319 } 00320 00321 // indicate msc activity 00322 main_blink_msc_led(MAIN_LED_FLASH); 00323 vfs_read(sector, buf, num_of_sectors); 00324 } 00325 00326 void usbd_msc_write_sect(uint32_t sector, uint8_t *buf, uint32_t num_of_sectors) 00327 { 00328 sync_assert_usb_thread(); 00329 00330 if (!USBD_MSC_MediaReady) { 00331 return; 00332 } 00333 00334 // Restart the disconnect counter on every packet 00335 // so the device does not detach in the middle of a 00336 // transfer. 00337 time_usb_idle = 0; 00338 00339 if (TRASNFER_FINISHED == file_transfer_state.transfer_state) { 00340 return; 00341 } 00342 00343 // indicate msc activity 00344 main_blink_msc_led(MAIN_LED_FLASH); 00345 vfs_write(sector, buf, num_of_sectors); 00346 if (TRASNFER_FINISHED == file_transfer_state.transfer_state) { 00347 return; 00348 } 00349 file_data_handler(sector, buf, num_of_sectors); 00350 } 00351 00352 static void sync_init(void) 00353 { 00354 sync_thread = osThreadGetId(); 00355 sync_mutex = osMutexNew(NULL); 00356 } 00357 00358 static void sync_assert_usb_thread(void) 00359 { 00360 util_assert(osThreadGetId() == sync_thread); 00361 } 00362 00363 static void sync_lock(void) 00364 { 00365 osMutexAcquire(sync_mutex, 0); 00366 } 00367 00368 static void sync_unlock(void) 00369 { 00370 osMutexRelease(sync_mutex); 00371 } 00372 00373 static bool changing_state() 00374 { 00375 return vfs_state != vfs_state_next; 00376 } 00377 00378 static void build_filesystem() 00379 { 00380 // Update anything that could have changed file system state 00381 file_transfer_state = default_transfer_state; 00382 vfs_user_build_filesystem(); 00383 vfs_set_file_change_callback(file_change_handler); 00384 // Set mass storage parameters 00385 USBD_MSC_MemorySize = vfs_get_total_size(); 00386 USBD_MSC_BlockSize = VFS_SECTOR_SIZE; 00387 USBD_MSC_BlockGroup = 1; 00388 USBD_MSC_BlockCount = USBD_MSC_MemorySize / USBD_MSC_BlockSize; 00389 USBD_MSC_BlockBuf = (uint8_t *)usb_buffer; 00390 } 00391 00392 // Callback to handle changes to the root directory. Should be used with vfs_set_file_change_callback 00393 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) 00394 { 00395 vfs_mngr_printf("vfs_manager file_change_handler(name=%*s, file=%p, change=%i)\r\n", 11, filename, file, change); 00396 vfs_user_file_change_handler(filename, change, file, new_file_data); 00397 if (TRASNFER_FINISHED == file_transfer_state.transfer_state) { 00398 // If the transfer is finished stop further processing 00399 return; 00400 } 00401 00402 if (VFS_FILE_CHANGED == change) { 00403 if (file == file_transfer_state.file_to_program) { 00404 stream_type_t stream; 00405 uint32_t size = vfs_file_get_size(new_file_data); 00406 vfs_sector_t sector = vfs_file_get_start_sector(new_file_data); 00407 stream = stream_type_from_name(filename); 00408 transfer_update_file_info(file, sector, size, stream); 00409 } 00410 } 00411 00412 if (VFS_FILE_CREATED == change) { 00413 stream_type_t stream; 00414 00415 if (STREAM_TYPE_NONE != stream_type_from_name(filename)) { 00416 // Check for a know file extension to detect the current file being 00417 // transferred. Ignore hidden files since MAC uses hidden files with 00418 // the same extension to keep track of transfer info in some cases. 00419 if (!(VFS_FILE_ATTR_HIDDEN & vfs_file_get_attr(new_file_data))) { 00420 stream = stream_type_from_name(filename); 00421 uint32_t size = vfs_file_get_size(new_file_data); 00422 vfs_sector_t sector = vfs_file_get_start_sector(new_file_data); 00423 transfer_update_file_info(file, sector, size, stream); 00424 } 00425 } 00426 } 00427 00428 if (VFS_FILE_DELETED == change) { 00429 if (file == file_transfer_state.file_to_program) { 00430 // The file that was being transferred has been deleted 00431 transfer_reset_file_info(); 00432 } 00433 } 00434 } 00435 00436 // Handler for file data arriving over USB. This function is responsible 00437 // for detecting the start of a BIN/HEX file and performing programming 00438 static void file_data_handler(uint32_t sector, const uint8_t *buf, uint32_t num_of_sectors) 00439 { 00440 stream_type_t stream; 00441 uint32_t size; 00442 00443 // this is the key for starting a file write - we dont care what file types are sent 00444 // just look for something unique (NVIC table, hex, srec, etc) until root dir is updated 00445 if (!file_transfer_state.stream_started) { 00446 // look for file types we can program 00447 stream = stream_start_identify((uint8_t *)buf, VFS_SECTOR_SIZE * num_of_sectors); 00448 00449 if (STREAM_TYPE_NONE != stream) { 00450 transfer_stream_open(stream, sector); 00451 } 00452 } 00453 00454 if (file_transfer_state.stream_started) { 00455 // Ignore sectors coming before this file 00456 if (sector < file_transfer_state.start_sector) { 00457 return; 00458 } 00459 00460 // sectors must be in order 00461 if (sector != file_transfer_state.file_next_sector) { 00462 vfs_mngr_printf("vfs_manager file_data_handler sector=%i\r\n", sector); 00463 00464 if (sector < file_transfer_state.file_next_sector) { 00465 vfs_mngr_printf(" sector out of order! lowest ooo = %i\r\n", 00466 file_transfer_state.last_ooo_sector); 00467 00468 if (VFS_INVALID_SECTOR == file_transfer_state.last_ooo_sector) { 00469 file_transfer_state.last_ooo_sector = sector; 00470 } 00471 00472 file_transfer_state.last_ooo_sector = 00473 MIN(file_transfer_state.last_ooo_sector, sector); 00474 } else { 00475 vfs_mngr_printf(" sector not part of file transfer\r\n"); 00476 } 00477 00478 vfs_mngr_printf(" discarding data - size transferred=0x%x, data=%x,%x,%x,%x,...\r\n", 00479 file_transfer_state.size_transferred, buf[0], buf[1], buf[2], buf[3]); 00480 return; 00481 } 00482 00483 // This sector could be part of the file so record it 00484 size = VFS_SECTOR_SIZE * num_of_sectors; 00485 file_transfer_state.size_transferred += size; 00486 file_transfer_state.file_next_sector = sector + num_of_sectors; 00487 00488 // If stream processing is done then discard the data 00489 if (file_transfer_state.stream_finished) { 00490 vfs_mngr_printf("vfs_manager file_data_handler\r\n sector=%i, size=%i\r\n", sector, size); 00491 vfs_mngr_printf(" discarding data - size transferred=0x%x, data=%x,%x,%x,%x,...\r\n", 00492 file_transfer_state.size_transferred, buf[0], buf[1], buf[2], buf[3]); 00493 transfer_update_state(ERROR_SUCCESS); 00494 return; 00495 } 00496 00497 transfer_stream_data(sector, buf, size); 00498 } 00499 } 00500 00501 static bool ready_for_state_change(void) 00502 { 00503 uint32_t timeout_ms = INVALID_TIMEOUT_MS; 00504 util_assert(vfs_state != vfs_state_next); 00505 00506 if (VFS_MNGR_STATE_CONNECTED == vfs_state) { 00507 switch (file_transfer_state.transfer_state) { 00508 case TRANSFER_NOT_STARTED: 00509 case TRASNFER_FINISHED: 00510 timeout_ms = DISCONNECT_DELAY_MS; 00511 break; 00512 00513 case TRANSFER_IN_PROGRESS: 00514 timeout_ms = DISCONNECT_DELAY_TRANSFER_TIMEOUT_MS; 00515 break; 00516 00517 case TRANSFER_CAN_BE_FINISHED: 00518 timeout_ms = DISCONNECT_DELAY_TRANSFER_IDLE_MS; 00519 break; 00520 00521 default: 00522 util_assert(0); 00523 timeout_ms = DISCONNECT_DELAY_MS; 00524 break; 00525 } 00526 } else if ((VFS_MNGR_STATE_DISCONNECTED == vfs_state) && 00527 (VFS_MNGR_STATE_CONNECTED == vfs_state_next)) { 00528 timeout_ms = CONNECT_DELAY_MS; 00529 } else if ((VFS_MNGR_STATE_RECONNECTING == vfs_state) && 00530 (VFS_MNGR_STATE_CONNECTED == vfs_state_next)) { 00531 timeout_ms = RECONNECT_DELAY_MS; 00532 } else if ((VFS_MNGR_STATE_RECONNECTING == vfs_state) && 00533 (VFS_MNGR_STATE_DISCONNECTED == vfs_state_next)) { 00534 timeout_ms = 0; 00535 } 00536 00537 if (INVALID_TIMEOUT_MS == timeout_ms) { 00538 util_assert(0); 00539 timeout_ms = 0; 00540 } 00541 00542 return time_usb_idle > timeout_ms ? true : false; 00543 } 00544 00545 // Abort a remount if one is pending 00546 void abort_remount(void) 00547 { 00548 sync_lock(); 00549 00550 // Only abort a remount if in the connected state and reconnecting is the next state 00551 if ((VFS_MNGR_STATE_RECONNECTING == vfs_state_next) && (VFS_MNGR_STATE_CONNECTED == vfs_state)) { 00552 vfs_state_next = VFS_MNGR_STATE_CONNECTED; 00553 } 00554 00555 sync_unlock(); 00556 } 00557 00558 // Update the tranfer state with file information 00559 static void transfer_update_file_info(vfs_file_t file, uint32_t start_sector, uint32_t size, stream_type_t stream) 00560 { 00561 vfs_mngr_printf("vfs_manager transfer_update_file_info(file=%p, start_sector=%i, size=%i)\r\n", file, start_sector, size); 00562 00563 if (TRASNFER_FINISHED == file_transfer_state.transfer_state) { 00564 util_assert(0); 00565 return; 00566 } 00567 00568 // Initialize the directory entry if it has not been set 00569 if (VFS_FILE_INVALID == file_transfer_state.file_to_program) { 00570 file_transfer_state.file_to_program = file; 00571 00572 if (file != VFS_FILE_INVALID) { 00573 vfs_mngr_printf(" file_to_program=%p\r\n", file); 00574 } 00575 } 00576 00577 // Initialize the starting sector if it has not been set 00578 if (VFS_INVALID_SECTOR == file_transfer_state.file_start_sector) { 00579 file_transfer_state.file_start_sector = start_sector; 00580 00581 if (start_sector != VFS_INVALID_SECTOR) { 00582 vfs_mngr_printf(" start_sector=%i\r\n", start_sector); 00583 } 00584 } 00585 00586 // Initialize the stream if it has not been set 00587 if (STREAM_TYPE_NONE == file_transfer_state.stream) { 00588 file_transfer_state.stream = stream; 00589 00590 if (stream != STREAM_TYPE_NONE) { 00591 vfs_mngr_printf(" stream=%i\r\n", stream); 00592 } 00593 } 00594 00595 // Check - File size must either grow or be smaller than the size already transferred 00596 if ((size < file_transfer_state.file_size) && (size < file_transfer_state.size_transferred) && (size > 0)) { 00597 vfs_mngr_printf(" error: file size changed from %i to %i\r\n", file_transfer_state.file_size, size); 00598 transfer_update_state(ERROR_ERROR_DURING_TRANSFER); 00599 return; 00600 } 00601 00602 // Check - Starting sector must be the same - this is optional for file info since it may not be present initially 00603 if ((VFS_INVALID_SECTOR != start_sector) && (start_sector != file_transfer_state.file_start_sector)) { 00604 vfs_mngr_printf(" error: starting sector changed from %i to %i\r\n", file_transfer_state.file_start_sector, start_sector); 00605 transfer_update_state(ERROR_ERROR_DURING_TRANSFER); 00606 return; 00607 } 00608 00609 // Check - stream must be the same 00610 if ((stream != STREAM_TYPE_NONE) && (stream != file_transfer_state.stream)) { 00611 vfs_mngr_printf(" error: changed types during transfer from %i to %i\r\n", file_transfer_state.stream, stream); 00612 transfer_update_state(ERROR_ERROR_DURING_TRANSFER); 00613 return; 00614 } 00615 00616 // Update values - Size is the only value that can change 00617 file_transfer_state.file_size = size; 00618 vfs_mngr_printf(" updated size=%i\r\n", size); 00619 00620 transfer_update_state(ERROR_SUCCESS); 00621 } 00622 00623 // Reset the transfer information or error if transfer is already in progress 00624 static void transfer_reset_file_info() 00625 { 00626 vfs_mngr_printf("vfs_manager transfer_reset_file_info()\r\n"); 00627 //check if the data started streaming; size can be updated on matching start sector and stream type 00628 if(file_transfer_state.stream_started){ 00629 //file, start sector and size has to be updated 00630 file_transfer_state.file_to_program = VFS_FILE_INVALID; 00631 file_transfer_state.file_start_sector = VFS_INVALID_SECTOR; 00632 file_transfer_state.file_size = 0; 00633 }else{ 00634 file_transfer_state = default_transfer_state; 00635 abort_remount(); 00636 } 00637 00638 } 00639 00640 // Update the tranfer state with new information 00641 static void transfer_stream_open(stream_type_t stream, uint32_t start_sector) 00642 { 00643 error_t status; 00644 util_assert(!file_transfer_state.stream_open); 00645 util_assert(start_sector != VFS_INVALID_SECTOR); 00646 vfs_mngr_printf("vfs_manager transfer_update_stream_open(stream=%i, start_sector=%i)\r\n", 00647 stream, start_sector); 00648 00649 // Initialize the starting sector if it has not been set 00650 if (VFS_INVALID_SECTOR == file_transfer_state.start_sector) { 00651 file_transfer_state.start_sector = start_sector; 00652 00653 if (start_sector != VFS_INVALID_SECTOR) { 00654 vfs_mngr_printf(" start_sector=%i\r\n", start_sector); 00655 } 00656 } 00657 00658 // Initialize the stream if it has not been set 00659 if (STREAM_TYPE_NONE == file_transfer_state.stream) { 00660 file_transfer_state.stream = stream; 00661 00662 if (stream != STREAM_TYPE_NONE) { 00663 vfs_mngr_printf(" stream=%i\r\n", stream); 00664 } 00665 } 00666 00667 // Check - Starting sector must be the same 00668 if (start_sector != file_transfer_state.start_sector) { 00669 vfs_mngr_printf(" error: starting sector changed from %i to %i\r\n", file_transfer_state.start_sector, start_sector); 00670 transfer_update_state(ERROR_ERROR_DURING_TRANSFER); 00671 return; 00672 } 00673 00674 // Check - stream must be the same 00675 if (stream != file_transfer_state.stream) { 00676 vfs_mngr_printf(" error: changed types during transfer from %i to %i\r\n", file_transfer_state.stream, stream); 00677 transfer_update_state(ERROR_ERROR_DURING_TRANSFER); 00678 return; 00679 } 00680 00681 // Open stream 00682 status = stream_open(stream); 00683 vfs_mngr_printf(" stream_open stream=%i ret %i\r\n", stream, status); 00684 00685 if (ERROR_SUCCESS == status) { 00686 file_transfer_state.file_next_sector = start_sector; 00687 file_transfer_state.stream_open = true; 00688 file_transfer_state.stream_started = true; 00689 } 00690 00691 transfer_update_state(status); 00692 } 00693 00694 // Update the tranfer state with new information 00695 static void transfer_stream_data(uint32_t sector, const uint8_t *data, uint32_t size) 00696 { 00697 error_t status; 00698 vfs_mngr_printf("vfs_manager transfer_stream_data(sector=%i, size=%i)\r\n", sector, size); 00699 vfs_mngr_printf(" size processed=0x%x, data=%x,%x,%x,%x,...\r\n", 00700 file_transfer_state.size_processed, data[0], data[1], data[2], data[3]); 00701 00702 if (file_transfer_state.stream_finished) { 00703 util_assert(0); 00704 return; 00705 } 00706 00707 util_assert(size % VFS_SECTOR_SIZE == 0); 00708 util_assert(file_transfer_state.stream_open); 00709 status = stream_write((uint8_t *)data, size); 00710 vfs_mngr_printf(" stream_write ret=%i\r\n", status); 00711 00712 if (ERROR_SUCCESS_DONE == status) { 00713 // Override status so ERROR_SUCCESS_DONE 00714 // does not get passed into transfer_update_state 00715 status = stream_close(); 00716 vfs_mngr_printf(" stream_close ret=%i\r\n", status); 00717 file_transfer_state.stream_open = false; 00718 file_transfer_state.stream_finished = true; 00719 file_transfer_state.stream_optional_finish = true; 00720 } else if (ERROR_SUCCESS_DONE_OR_CONTINUE == status) { 00721 status = ERROR_SUCCESS; 00722 file_transfer_state.stream_optional_finish = true; 00723 } else { 00724 file_transfer_state.stream_optional_finish = false; 00725 } 00726 00727 file_transfer_state.size_processed += size; 00728 transfer_update_state(status); 00729 } 00730 00731 // Check if the current transfer is still in progress, done, or if an error has occurred 00732 static void transfer_update_state(error_t status) 00733 { 00734 bool transfer_timeout; 00735 bool transfer_started; 00736 bool transfer_can_be_finished; 00737 bool transfer_must_be_finished; 00738 bool out_of_order_sector; 00739 error_t local_status = status; 00740 util_assert((status != ERROR_SUCCESS_DONE) && 00741 (status != ERROR_SUCCESS_DONE_OR_CONTINUE)); 00742 00743 if (TRASNFER_FINISHED == file_transfer_state.transfer_state) { 00744 util_assert(0); 00745 return; 00746 } 00747 00748 // Update file info status. The end of a file is never known for sure since 00749 // what looks like a complete file could be part of a file getting flushed to disk. 00750 // The criteria for an successful optional finish is 00751 // 1. A file has been detected 00752 // 2. The size of the file indicated in the root dir has been transferred 00753 // 3. The file size is greater than zero 00754 // 4. Matching start sector set by stream and vfs changes 00755 file_transfer_state.file_info_optional_finish = 00756 (file_transfer_state.file_to_program != VFS_FILE_INVALID) && 00757 (file_transfer_state.size_transferred >= file_transfer_state.file_size) && 00758 (file_transfer_state.file_size > 0) && 00759 (file_transfer_state.start_sector == file_transfer_state.file_start_sector); 00760 transfer_timeout = file_transfer_state.transfer_timeout; 00761 transfer_started = (VFS_FILE_INVALID != file_transfer_state.file_to_program) || 00762 (STREAM_TYPE_NONE != file_transfer_state.stream); 00763 // The transfer can be finished if both file and stream processing 00764 // can be considered complete 00765 transfer_can_be_finished = file_transfer_state.file_info_optional_finish && 00766 file_transfer_state.stream_optional_finish; 00767 // The transfer must be fnished if stream processing is for sure complete 00768 // and file processing can be considered complete 00769 transfer_must_be_finished = file_transfer_state.stream_finished && 00770 file_transfer_state.file_info_optional_finish; 00771 out_of_order_sector = false; 00772 00773 if (file_transfer_state.last_ooo_sector != VFS_INVALID_SECTOR) { 00774 util_assert(file_transfer_state.start_sector != VFS_INVALID_SECTOR); 00775 uint32_t sector_offset = (file_transfer_state.last_ooo_sector - 00776 file_transfer_state.start_sector) * VFS_SECTOR_SIZE; 00777 00778 if (sector_offset < file_transfer_state.size_processed) { 00779 // The out of order sector was within the range of data already 00780 // processed. 00781 out_of_order_sector = true; 00782 } 00783 } 00784 00785 // Set the transfer state and set the status if necessary 00786 if (local_status != ERROR_SUCCESS) { 00787 file_transfer_state.transfer_state = TRASNFER_FINISHED; 00788 } else if (transfer_timeout) { 00789 if (out_of_order_sector) { 00790 local_status = ERROR_OOO_SECTOR; 00791 } else if (!transfer_started) { 00792 local_status = ERROR_SUCCESS; 00793 } else if (transfer_can_be_finished) { 00794 local_status = ERROR_SUCCESS; 00795 } else { 00796 local_status = ERROR_TRANSFER_TIMEOUT; 00797 } 00798 00799 file_transfer_state.transfer_state = TRASNFER_FINISHED; 00800 } else if (transfer_must_be_finished) { 00801 file_transfer_state.transfer_state = TRASNFER_FINISHED; 00802 } else if (transfer_can_be_finished) { 00803 file_transfer_state.transfer_state = TRANSFER_CAN_BE_FINISHED; 00804 } else if (transfer_started) { 00805 file_transfer_state.transfer_state = TRANSFER_IN_PROGRESS; 00806 } 00807 00808 if (TRASNFER_FINISHED == file_transfer_state.transfer_state) { 00809 vfs_mngr_printf("vfs_manager transfer_update_state(status=%i)\r\n", status); 00810 vfs_mngr_printf(" file=%p, start_sect= %i %i, size=%i\r\n", 00811 file_transfer_state.file_to_program, file_transfer_state.start_sector, 00812 file_transfer_state.file_start_sector, file_transfer_state.file_size); 00813 vfs_mngr_printf(" stream=%i, size_processed=%i, opt_finish=%i, timeout=%i\r\n", 00814 file_transfer_state.stream, file_transfer_state.size_processed, 00815 file_transfer_state.file_info_optional_finish, transfer_timeout); 00816 00817 // Close the file stream if it is open 00818 if (file_transfer_state.stream_open) { 00819 error_t close_status; 00820 close_status = stream_close(); 00821 vfs_mngr_printf(" stream closed ret=%i\r\n", close_status); 00822 file_transfer_state.stream_open = false; 00823 00824 if (ERROR_SUCCESS == local_status) { 00825 local_status = close_status; 00826 } 00827 } 00828 00829 // Set the fail reason 00830 fail_reason = local_status; 00831 vfs_mngr_printf(" Transfer finished, status: %i=%s\r\n", fail_reason, error_get_string(fail_reason)); 00832 } 00833 00834 // If this state change is not from aborting a transfer 00835 // due to a remount then trigger a remount 00836 if (!transfer_timeout) { 00837 vfs_mngr_fs_remount(); 00838 } 00839 }
Generated on Tue Jul 12 2022 15:37:27 by
