Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers vfs_manager.c Source File

vfs_manager.c

Go to the documentation of this file.
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 }